#!/bin/bash # SPDX-Version: 3.0 # SPDX-CreationInfo: 2025-10-11; WEIDNER, Marc S.; # SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.live.builder.git # SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency # SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; # SPDX-FileType: SOURCE # SPDX-License-Identifier: LicenseRef-CNCL-1.1 OR LicenseRef-CCLA-1.1 # SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework. # SPDX-PackageName: CISS.debian.live.builder # SPDX-Security-Contact: security@coresecret.eu set -Ceuo pipefail ####################################### # Iterates all '/etc/shadow' entries and sets: # 4=min age=0, 5=max age=16384, 6=warn=128, 7=inactive=42, 8=expire=17.09.2102 # Safe: creates a timestamped backup and (if available) locks '/etc/.pwd.lock'. # Globals: # RECOVERY # TARGET # VAR_RUN_RECOVERY # Arguments: # None # Returns: # 0: on success ####################################### update_shadow() { ### Declare Arrays, HashMaps, and Variables. declare -r var_shadow="/etc/shadow" declare -r var_backup="/root/.ciss/cdlb/backup/etc/shadow.$(date +%s).bak" declare -r var_temp="${var_shadow}.new.$$" declare -r var_exp_dt="17.09.2102" declare var_exp_ds="" mkdir -p "/root/.ciss/cdlb/backup/etc" var_exp_ds="$( awk -v d="${var_exp_dt}" 'BEGIN{ # Force UTC to avoid DST/timezone off-by-one errors ENVIRON["TZ"]="UTC"; if (match(d, /^([0-9]{2})\.([0-9]{2})\.([0-9]{4})$/, a)) { dd=a[1]+0; mm=a[2]+0; yyyy=a[3]+0; sec = mktime(sprintf("%04d %02d %02d 00 00 00 0", yyyy, mm, dd)); if (sec < 0) { print "ERR"; exit 1 } print int(sec/86400); exit 0 } else { print "ERR"; exit 1 } }' )" || return 42 # shellcheck disable=SC2249 case "${var_exp_ds}" in ''|*ERR*) return 127 ;; esac umask 0077 cp --preserve=mode,ownership "${var_shadow}" "${var_backup}" ### Rewrite fields 4..8 for every line ### Preserve fields 1..3 and 9, keep password hashes untouched. ### Pad to 9 fields if shorter; keep empty lines intact (rare but safe). awk -v FS=":" -v OFS=":" -v v_exp="${var_exp_ds}" ' NF==0 { print; next } # preserve blank lines verbatim { # pad missing trailing fields to 9 for (i=NF+1; i<=9; i++) $i=""; $4=0; $5=16384; $6=128; $7=42; $8=v_exp; # set required fields print } ' "${var_backup}" >| "${var_temp}" ### Defensive: ensure non-empty output. if [[ ! -s "${var_temp}" ]]; then rm -f "${var_temp}" return 42 fi ### Preserve owner/mode (fallback to 0640 root:shadow if reference fails). chown --reference="${var_shadow}" "${var_temp}" 2>/dev/null || chown root:shadow "${var_temp}" 2>/dev/null || true chmod --reference="${var_shadow}" "${var_temp}" 2>/dev/null || chmod 0640 "${var_temp}" 2>/dev/null || true ### Atomic replace. mv -f "${var_temp}" "${var_shadow}" return 0 } ### Prevents accidental 'unset -f'. # shellcheck disable=SC2034 readonly -f update_shadow printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ ๐Ÿงช '%s' starting ... \e[0m\n" "${0}" if ! command -v chage &>/dev/null; then printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Info: 'chage' NOT found. Exiting hook ... \e[0m\n" printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… '%s' applied successfully. \e[0m\n" "${0}" exit 0 fi declare -i max_days=16384 # shellcheck disable=SC2312 mapfile -t users_to_update < <( awk -F: '$2 !~ /^[!*]/ { print $1 }' /etc/shadow ) if [[ ${#users_to_update[@]} -eq 0 ]]; then printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… No enabled-login accounts found in /etc/shadow. Exiting hook ... \e[0m\n" printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… '%s' applied successfully. \e[0m\n" "${0}" exit 0 fi declare user for user in "${users_to_update[@]}"; do printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… Setting max password age for user '%s' to '%s' days. \e[0m\n" "${user}" "${max_days}" chage --maxdays "${max_days}" "${user}" done unset max_days user users_to_update awk -F: '$2 !~ /^\$[0-9]/ && length($2)==13 { print $1,$2 }' /etc/shadow printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… All applicable accounts have been updated. \e[0m\n" update_shadow printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ โœ… '%s' applied successfully. \e[0m\n" "${0}" exit 0 # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh