#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-05-05; WEIDNER, Marc S.; <msw@coresecret.dev>
# 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.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# 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

### NIST recommends at least eight characters but advises longer passphrases (e.g., 12-64) for increased security.
### NIST SP 800-63B, https://pages.nist.gov/800-63-3/sp800-63b.html

set -C -e -u -o pipefail

printf "\e[95m++++ ++++ ++++ ++++ ++++ ++++ ++ 🧪 '%s' starting ... \e[0m\n" "${0}"
# sleep 1

cp -a /etc/security/pwquality.conf /root/.ciss/dlb/backup/pwquality.conf.bak
chmod 0644 /root/.ciss/dlb/backup/pwquality.conf.bak

cat << 'EOF' >| /etc/security/pwquality.conf
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-05-05; WEIDNER, Marc S.; <msw@coresecret.dev>
# 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.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# 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

### Current recommendations for '/etc/security/pwquality.conf' based on common best practices,
### including NIST SP 800-63B, https://pages.nist.gov/800-63-3/sp800-63b.html
### and weighing usability against security.

### Configuration for systemwide password quality limits
### Defaults:

### Number of characters in the new password that must not be present in the
### old password.
difok = 4

### Length over complexity: Studies show that longer passphrases are significantly more
### resistant to brute-force and dictionary attacks. NIST recommends at least eight characters
### but advises longer passphrases (e.g., 12-64) for increased security. Twenty characters strike a
### good balance between security and user convenience.
### Minimum acceptable size for the new password (plus one if
### credits are not disabled, which is the default). (See pam_cracklib manual.)
### Cannot be set to a lower value than 6.
minlen = 40

### dcredit = 0, ucredit = 0, lcredit = 0, ocredit = 0, minclass = 0
### NIST SP 800-63B advises against rigid complexity rules (numbers, symbols, uppercase)
### because they can lead users to adopt predictable patterns (e.g., "Pa$$word!").
### Length and dictionary checks are more effective.

  ### The maximum credit for having digits in the new password. If less than 0
  ### it is the minimum number of digits in the new password.
  dcredit = 0

  ### The maximum credit for having uppercase characters in the new password.
  ### If less than 0, it is the minimum number of uppercase characters in the new
  ### password.
  ucredit = 0

  ### The maximum credit for having lowercase characters in the new password.
  ### If less than 0, it is the minimum number of lowercase characters in the new
  ### password.
  lcredit = 0

  ### The maximum credit for having other characters in the new password.
  ### If less than 0, it is the minimum number of other characters in the new
  ### password.
  ocredit = 0

  ### The minimum number of required classes of characters for the new
  ### password (digits, uppercase, lowercase, others).
  minclass = 0

### The maximum number of allowed consecutive same characters in the new password.
### The check is disabled if the value is 0.
maxrepeat = 3

### The maximum number of allowed consecutive characters of the same class in the
### new password.
### The check is disabled if the value is 0.
maxclassrepeat = 0

### Whether to check for the words from the passwd entry GECOS string of the user.
### The check is enabled if the value is not 0.
### gecoscheck = 0

### Whether to check for the words from the cracklib dictionary.
### The check is enabled if the value is not 0.
dictcheck = 1

### Whether to check if it contains the username in some form.
### The check is enabled if the value is not 0.
usercheck = 1

### Length of substrings from the username to check for in the password
### The check is enabled if the value is greater than 0, and the usercheck is enabled.
usersubstr = 3

### Whether the check is enforced by the PAM module and possibly other
### applications.
### The new password is rejected if it fails the check, and the value is not 0.
enforcing = 1

### Path to the cracklib dictionaries. The default is to use the cracklib default.
dictpath =

# Prompt user at most N times before returning with error. The default is 1.
retry = 3

# Enforces pwquality checks on the root user password.
# Enabled if the option is present.
enforce_for_root

# Skip testing the password quality for users that are not present in the
# /etc/passwd file.
# Enabled if the option is present.
local_users_only

EOF

printf "\e[92m++++ ++++ ++++ ++++ ++++ ++++ ++ ✅ '%s' applied successfully. \e[0m\n" "${0}"
# sleep 1

exit 0
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
