Compare commits
2 Commits
88bba53981
...
3a50fc5050
| Author | SHA256 | Date | |
|---|---|---|---|
|
3a50fc5050
|
|||
|
f0bbc6094d
|
@@ -34,9 +34,12 @@ recipe:
|
|||||||
time: 256 # The number of milliseconds to spend with PBKDF passphrase processing.
|
time: 256 # The number of milliseconds to spend with PBKDF passphrase processing.
|
||||||
luks_backup: true # Specify if LUKS Header backups should be created. If so, provide an external backup URL:
|
luks_backup: true # Specify if LUKS Header backups should be created. If so, provide an external backup URL:
|
||||||
# luks_backup_url: "https://cloud.e2ee.li/" or leave empty for local backup.
|
# luks_backup_url: "https://cloud.e2ee.li/" or leave empty for local backup.
|
||||||
# Also provide the cloud access token and access passwords via ./.preseed/password_luks_backup.txt
|
# Also provide the cloud access token and access passwords via
|
||||||
# Yet Nextcloud only is supported.
|
# ./.preseed/password_luks_backup.txt. Yet Nextcloud only is supported.
|
||||||
luks_backup_url: "https://cloud.e2ee.li/"
|
luks_backup_url: "https://cloud.e2ee.li/"
|
||||||
|
luks_backup_pgp: "ciss" # Specify the trigger for use of the LUKS Header backup encryption key.
|
||||||
|
# Allowed values are: 'ciss', and 'physnet'. MUST be provided.
|
||||||
|
# Otherwise, the backup is NOT created.
|
||||||
name: "ciss.2025.gpt.btrfs.ephemeral.non-raid.256GiB.rescue"
|
name: "ciss.2025.gpt.btrfs.ephemeral.non-raid.256GiB.rescue"
|
||||||
nuke: true # Activates Nuke-Mechanism in '/etc/crypttab' keyscript and via dropbear SSH forced command.
|
nuke: true # Activates Nuke-Mechanism in '/etc/crypttab' keyscript and via dropbear SSH forced command.
|
||||||
nuke_rounds: 16384 # SHA512 KDF Rounds for Nuke Passphrase. If omitted, the default value is '8,388,608'.
|
nuke_rounds: 16384 # SHA512 KDF Rounds for Nuke Passphrase. If omitted, the default value is '8,388,608'.
|
||||||
|
|||||||
@@ -863,7 +863,8 @@ user:
|
|||||||
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
|
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
|
||||||
sudo: false # Whether the user can escalate to root using sudo.
|
sudo: false # Whether the user can escalate to root using sudo.
|
||||||
system: true # Whether this is a low-UID system user (e.g., for automation).
|
system: true # Whether this is a low-UID system user (e.g., for automation).
|
||||||
specific: "ciss" # Also used for LUKS Header encryption.
|
specific: "ciss" # Adjust the settings for the user account as required. Allowed values are 'none', 'ciss', and
|
||||||
|
# 'physnet'.
|
||||||
|
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
# Primary administrative user with full sudo access
|
# Primary administrative user with full sudo access
|
||||||
@@ -892,7 +893,8 @@ user:
|
|||||||
system: false # Whether this is a low-UID system user (e.g., for automation).
|
system: false # Whether this is a low-UID system user (e.g., for automation).
|
||||||
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
|
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
|
||||||
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
|
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
|
||||||
specific: "ciss"
|
specific: "ciss" # Adjust the settings for the user account as required. Allowed values are 'none', 'ciss', and
|
||||||
|
# 'physnet'.
|
||||||
|
|
||||||
##############################################################################################################################
|
##############################################################################################################################
|
||||||
# ansible – System user for automation, no interactive shell
|
# ansible – System user for automation, no interactive shell
|
||||||
@@ -921,6 +923,7 @@ user:
|
|||||||
system: true # Whether this is a low-UID system user (e.g., for automation).
|
system: true # Whether this is a low-UID system user (e.g., for automation).
|
||||||
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
|
restricted: false # If true, the user is limited in scope (e.g., no login, no file access, --no-create-home)
|
||||||
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
|
shell: true # MUST be "true" if the shell is not '/usr/sbin/nologin' or '/bin/false'.
|
||||||
specific: "none"
|
specific: "none" # Adjust the settings for the user account as required. Allowed values are 'none', 'ciss', and
|
||||||
|
# 'physnet'.
|
||||||
|
|
||||||
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=yaml
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ guard_sourcing
|
|||||||
# VAR_DROPBEAR
|
# VAR_DROPBEAR
|
||||||
# VAR_GRUB_PASSWORD
|
# VAR_GRUB_PASSWORD
|
||||||
# VAR_LUKS_BACKUP
|
# VAR_LUKS_BACKUP
|
||||||
|
# VAR_LUKS_PGP
|
||||||
# VAR_LUKS_URL
|
# VAR_LUKS_URL
|
||||||
# VAR_NEED_RUN_IN_TARGET
|
# VAR_NEED_RUN_IN_TARGET
|
||||||
# VAR_NUKE
|
# VAR_NUKE
|
||||||
@@ -57,7 +58,7 @@ guard_sourcing
|
|||||||
# None
|
# None
|
||||||
# Returns:
|
# Returns:
|
||||||
# 0: on success
|
# 0: on success
|
||||||
# ERR_NO_VALID_RECIPE
|
# ERR_NO_VALID_RECIPE: on failure
|
||||||
#######################################
|
#######################################
|
||||||
yaml_reader() {
|
yaml_reader() {
|
||||||
### Declare Arrays, HashMaps, and Variables.
|
### Declare Arrays, HashMaps, and Variables.
|
||||||
@@ -67,12 +68,12 @@ yaml_reader() {
|
|||||||
VAR_RECIPE_TABLE="" VAR_NEED_RUN_IN_TARGET="false" VAR_CODENAME="" VAR_DROPBEAR="" VAR_RECOVERY="" \
|
VAR_RECIPE_TABLE="" VAR_NEED_RUN_IN_TARGET="false" VAR_CODENAME="" VAR_DROPBEAR="" VAR_RECOVERY="" \
|
||||||
VAR_GRUB_PASSWORD="false" VAR_SSH_PORT="22" VAR_DEB822="true" VAR_PROVIDER="" VAR_SSH_CA="" VAR_UFW_OUT="deny" \
|
VAR_GRUB_PASSWORD="false" VAR_SSH_PORT="22" VAR_DEB822="true" VAR_PROVIDER="" VAR_SSH_CA="" VAR_UFW_OUT="deny" \
|
||||||
VAR_CHROOT_DEBUG="false" VAR_SEC_FW="selinux" VAR_APT_FULL_UPGRADE="true" VAR_LUKS_BACKUP="false" \
|
VAR_CHROOT_DEBUG="false" VAR_SEC_FW="selinux" VAR_APT_FULL_UPGRADE="true" VAR_LUKS_BACKUP="false" \
|
||||||
VAR_LUKS_URL=""
|
VAR_LUKS_URL="" VAR_LUKS_PGP=""
|
||||||
### Declare and substitute input files.
|
### Declare and substitute input files.
|
||||||
declare -r var_if="${VAR_PRESEED}"
|
declare -r var_if="${VAR_PRESEED}"
|
||||||
declare var_line="" var_middle_part="" var_highest_dev="" var_device="" var_fields="" var_partition="" \
|
declare var_line="" var_middle_part="" var_highest_dev="" var_device="" var_fields="" var_partition="" \
|
||||||
recipe_firmware_var="" recipe_nuke_var="" recipe_nuke_rounds_var="" recipe_table_var="" recipe_recovery_var="" \
|
recipe_firmware_var="" recipe_nuke_var="" recipe_nuke_rounds_var="" recipe_table_var="" recipe_recovery_var="" \
|
||||||
recipe_luks_var="" recipe_luks_url=""
|
recipe_luks_var="" recipe_luks_url="" recipe_luks_pgp=""
|
||||||
|
|
||||||
### Read "${var_if}" line by line.
|
### Read "${var_if}" line by line.
|
||||||
while IFS= read -r var_line; do
|
while IFS= read -r var_line; do
|
||||||
@@ -209,12 +210,17 @@ END { print max }
|
|||||||
VAR_RECIPE_FIRMWARE="${!recipe_firmware_var,,}"
|
VAR_RECIPE_FIRMWARE="${!recipe_firmware_var,,}"
|
||||||
|
|
||||||
### Extract the chosen LUKS Backup strategy.
|
### Extract the chosen LUKS Backup strategy.
|
||||||
recipe_luks_var="recipe_${VAR_RECIPE_STRING}_control_luks_backup"
|
recipe_luks_var="recipe_${VAR_RECIPE_STRING}_control_luks_backup"
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
VAR_LUKS_BACKUP="${!recipe_luks_var,,}"
|
VAR_LUKS_BACKUP="${!recipe_luks_var,,}"
|
||||||
recipe_luks_url="recipe_${VAR_RECIPE_STRING}_control_luks_backup_url"
|
|
||||||
# shellcheck disable=SC2034
|
recipe_luks_pgp="recipe_${VAR_RECIPE_STRING}_control_luks_backup_pgp"
|
||||||
VAR_LUKS_URL="${!recipe_luks_url,,}"
|
# shellcheck disable=SC2034
|
||||||
|
VAR_LUKS_PGP="${!recipe_luks_url,,}"
|
||||||
|
|
||||||
|
recipe_luks_url="recipe_${VAR_RECIPE_STRING}_control_luks_backup_url"
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
VAR_LUKS_URL="${!recipe_luks_url,,}"
|
||||||
|
|
||||||
### Extract the chosen Nuke mechanism.
|
### Extract the chosen Nuke mechanism.
|
||||||
recipe_nuke_var="recipe_${VAR_RECIPE_STRING}_control_nuke"
|
recipe_nuke_var="recipe_${VAR_RECIPE_STRING}_control_nuke"
|
||||||
|
|||||||
@@ -174,20 +174,50 @@ partition_encryption() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
### Opening the encrypted container.
|
||||||
|
if [[ "${var_encryption_path,,}" == "/boot" ]]; then
|
||||||
|
cryptsetup luksOpen "/dev/${var_dev}" \
|
||||||
|
--key-file="${DIR_CNF}/password_luks_boot.txt" \
|
||||||
|
"${var_encryption_label}"
|
||||||
|
else
|
||||||
|
cryptsetup luksOpen "/dev/${var_dev}" \
|
||||||
|
--key-file="${DIR_CNF}/password_luks_common.txt" \
|
||||||
|
"${var_encryption_label}"
|
||||||
|
fi
|
||||||
|
do_log "info" "file_only" "3220() Partition: '/dev/${var_dev}' opened as '/dev/mapper/${var_encryption_label}'."
|
||||||
|
|
||||||
|
### Create luksDump log entry.
|
||||||
|
cryptsetup luksDump "/dev/${var_dev}" >> "${DIR_LOG}/3220_cryptsetup_luksdump_${var_dev}.log"
|
||||||
|
|
||||||
|
### Store UUID of the LUKS container.
|
||||||
|
var_uuid=$(blkid -s UUID -o value "/dev/${var_dev}")
|
||||||
|
|
||||||
|
[[ "${var_encryption_path}" == "/" ]] && declare -grx VAR_CRYPT_ROOT="${var_uuid}"
|
||||||
|
[[ "${var_encryption_path}" == "/boot" ]] && declare -grx VAR_CRYPT_BOOT="${var_uuid}"
|
||||||
|
[[ "${var_encryption_path}" == "/recovery" ]] && declare -grx VAR_CRYPT_RECOVERY="${var_uuid}"
|
||||||
|
|
||||||
|
HMP_PATH_LUKSUUID["${var_encryption_path}"]="${var_uuid}"
|
||||||
|
HMP_PATH_ENCLABEL["${var_encryption_path}"]="${var_encryption_label}"
|
||||||
|
|
||||||
|
do_log "debug" "file_only" "3220() [HMP_PATH_LUKSUUID]: '${var_encryption_path}' -> '${HMP_PATH_LUKSUUID["${var_encryption_path}"]}'"
|
||||||
|
do_log "debug" "file_only" "3220() [HMP_PATH_ENCLABEL]: '${var_encryption_path}' -> '${HMP_PATH_ENCLABEL["${var_encryption_path}"]}'"
|
||||||
|
|
||||||
|
### Backup the LUKS Header.
|
||||||
if [[ "${VAR_LUKS_BACKUP}" == "true" ]]; then
|
if [[ "${VAR_LUKS_BACKUP}" == "true" ]]; then
|
||||||
|
|
||||||
case "${user_root_specific}" in
|
|
||||||
|
|
||||||
ciss) var_pgp_publickey="${VAR_SETUP_PATH}/.pubkey/marc_s_weidner_msw@coresecret.dev_0xE62E84F8_public.asc" ;;
|
|
||||||
physnet) var_pgp_publickey="${VAR_SETUP_PATH}/.pubkey/zimnol_andre_h_git.cs@physnet.eu_0x8A659CC7B4D63AE6_public.asc" ;;
|
|
||||||
*) do_log "error" "file_only" "3220() No valid PGP public key for LUKS Header encryption provided."; return "${ERR_LUKS_HEADER_ENC}" ;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
|
|
||||||
var_luks_backup_file="${DIR_BAK}/luks_header_${var_dev}.bak"
|
var_luks_backup_file="${DIR_BAK}/luks_header_${var_dev}.bak"
|
||||||
var_luks_backup_name="${VAR_FINAL_FQDN}_luks_header_${var_dev}.bak.pgp"
|
var_luks_backup_name="${VAR_FINAL_FQDN}_luks_header_${var_dev}.bak.pgp"
|
||||||
var_luks_backup_pgp="${DIR_BAK}/luks_header_${var_dev}.bak.pgp"
|
var_luks_backup_pgp="${DIR_BAK}/luks_header_${var_dev}.bak.pgp"
|
||||||
|
|
||||||
|
case "${VAR_LUKS_PGP}" in
|
||||||
|
|
||||||
|
ciss) var_pgp_publickey="${VAR_SETUP_PATH}/.pubkey/marc_s_weidner_msw@coresecret.dev_0xE62E84F8_public.asc" ;;
|
||||||
|
physnet) var_pgp_publickey="${VAR_SETUP_PATH}/.pubkey/zimnol_andre_h_git.cs@physnet.eu_0x8A659CC7B4D63AE6_public.asc" ;;
|
||||||
|
none) do_log "error" "file_only" "3220() No PGP public key for LUKS Header encryption provided."; continue ;;
|
||||||
|
*) do_log "fatal" "file_only" "3220() No valid PGP public key for LUKS Header encryption provided."; return "${ERR_LUKS_HEADER_ENC}" ;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
if cryptsetup luksHeaderBackup --header-backup-file="${var_luks_backup_file}" "/dev/${var_dev}"; then
|
if cryptsetup luksHeaderBackup --header-backup-file="${var_luks_backup_file}" "/dev/${var_dev}"; then
|
||||||
|
|
||||||
do_log "info" "file_only" "3220() Partition: '/dev/${var_dev}' LUKS Header saved: '${var_luks_backup_file}'."
|
do_log "info" "file_only" "3220() Partition: '/dev/${var_dev}' LUKS Header saved: '${var_luks_backup_file}'."
|
||||||
@@ -207,11 +237,11 @@ partition_encryption() {
|
|||||||
|
|
||||||
if command -v shred >/dev/null 2>&1; then
|
if command -v shred >/dev/null 2>&1; then
|
||||||
|
|
||||||
shred -u -- "${var_luks_backup_file}" || rm -f -- "${var_luks_backup_file}"
|
shred -vfzu -n 5 "${var_luks_backup_file}" || rm -f "${var_luks_backup_file}"
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
rm -f -- "${var_luks_backup_file}"
|
rm -f "${var_luks_backup_file}"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -245,34 +275,6 @@ partition_encryption() {
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Opening the encrypted container.
|
|
||||||
if [[ "${var_encryption_path,,}" == "/boot" ]]; then
|
|
||||||
cryptsetup luksOpen "/dev/${var_dev}" \
|
|
||||||
--key-file="${DIR_CNF}/password_luks_boot.txt" \
|
|
||||||
"${var_encryption_label}"
|
|
||||||
else
|
|
||||||
cryptsetup luksOpen "/dev/${var_dev}" \
|
|
||||||
--key-file="${DIR_CNF}/password_luks_common.txt" \
|
|
||||||
"${var_encryption_label}"
|
|
||||||
fi
|
|
||||||
do_log "info" "file_only" "3220() Partition: '/dev/${var_dev}' opened as '/dev/mapper/${var_encryption_label}'."
|
|
||||||
|
|
||||||
### Create luksDump log entry.
|
|
||||||
cryptsetup luksDump "/dev/${var_dev}" >> "${DIR_LOG}/3220_cryptsetup_luksdump_${var_dev}.log"
|
|
||||||
|
|
||||||
### Store UUID of the LUKS container.
|
|
||||||
var_uuid=$(blkid -s UUID -o value "/dev/${var_dev}")
|
|
||||||
|
|
||||||
[[ "${var_encryption_path}" == "/" ]] && declare -grx VAR_CRYPT_ROOT="${var_uuid}"
|
|
||||||
[[ "${var_encryption_path}" == "/boot" ]] && declare -grx VAR_CRYPT_BOOT="${var_uuid}"
|
|
||||||
[[ "${var_encryption_path}" == "/recovery" ]] && declare -grx VAR_CRYPT_RECOVERY="${var_uuid}"
|
|
||||||
|
|
||||||
HMP_PATH_LUKSUUID["${var_encryption_path}"]="${var_uuid}"
|
|
||||||
HMP_PATH_ENCLABEL["${var_encryption_path}"]="${var_encryption_label}"
|
|
||||||
|
|
||||||
do_log "debug" "file_only" "3220() [HMP_PATH_LUKSUUID]: '${var_encryption_path}' -> '${HMP_PATH_LUKSUUID["${var_encryption_path}"]}'"
|
|
||||||
do_log "debug" "file_only" "3220() [HMP_PATH_ENCLABEL]: '${var_encryption_path}' -> '${HMP_PATH_ENCLABEL["${var_encryption_path}"]}'"
|
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
[[ -n "${VAR_LUKS_URL}" ]] && unset VAR_TEMP_PLAIN_NC_AUTH
|
[[ -n "${VAR_LUKS_URL}" ]] && unset VAR_TEMP_PLAIN_NC_AUTH
|
||||||
|
|||||||
@@ -82,11 +82,11 @@ hardening_ufw() {
|
|||||||
sed -i "/^# BEGIN custom MLD rules/,/^# END custom MLD rules/d" "${var_rules}"
|
sed -i "/^# BEGIN custom MLD rules/,/^# END custom MLD rules/d" "${var_rules}"
|
||||||
sed -i "/^# BEGIN custom MLD OUTPUT rules/,/^# END custom MLD OUTPUT rules/d" "${var_rules}"
|
sed -i "/^# BEGIN custom MLD OUTPUT rules/,/^# END custom MLD OUTPUT rules/d" "${var_rules}"
|
||||||
|
|
||||||
### Inbound MLD (INPUT chain) – insert before the existing echo-request rule.
|
### Inbound MLD (INPUT chain), insert before the existing echo-request rule.
|
||||||
### Allows MLDv1 (130/131/132) and MLDv2 (143) to link-local multicast (ff02::/16)
|
### Allows MLDv1 (130/131/132) and MLDv2 (143) to link-local multicast (ff02::/16)
|
||||||
sed -i "/-A ufw6-before-input .*--icmpv6-type echo-request -j ACCEPT/i # BEGIN custom MLD rules\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 130 -d ff02::/16 -j ACCEPT\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 131 -d ff02::/16 -j ACCEPT\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 132 -d ff02::/16 -j ACCEPT\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 143 -d ff02::/16 -j ACCEPT\n# END custom MLD rules" "${var_rules}"
|
sed -i "/-A ufw6-before-input .*--icmpv6-type echo-request -j ACCEPT/i # BEGIN custom MLD rules\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 130 -d ff02::/16 -j ACCEPT\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 131 -d ff02::/16 -j ACCEPT\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 132 -d ff02::/16 -j ACCEPT\n-A ufw6-before-input -i ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 143 -d ff02::/16 -j ACCEPT\n# END custom MLD rules" "${var_rules}"
|
||||||
|
|
||||||
### Outbound MLD (OUTPUT chain) – insert before echo-request.
|
### Outbound MLD (OUTPUT chain), insert before echo-request.
|
||||||
### Useful if local daemons join multicast groups, and you want clean logs.
|
### Useful if local daemons join multicast groups, and you want clean logs.
|
||||||
sed -i "/-A ufw6-before-output .*--icmpv6-type echo-request -j ACCEPT/i # BEGIN custom MLD OUTPUT rules\n-A ufw6-before-output -o ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 131 -d ff02::/16 -j ACCEPT\n-A ufw6-before-output -o ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 143 -d ff02::/16 -j ACCEPT\n# END custom MLD OUTPUT rules" "${var_rules}"
|
sed -i "/-A ufw6-before-output .*--icmpv6-type echo-request -j ACCEPT/i # BEGIN custom MLD OUTPUT rules\n-A ufw6-before-output -o ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 131 -d ff02::/16 -j ACCEPT\n-A ufw6-before-output -o ${VAR_FINAL_NIC} -p icmpv6 --icmpv6-type 143 -d ff02::/16 -j ACCEPT\n# END custom MLD OUTPUT rules" "${var_rules}"
|
||||||
|
|
||||||
|
|||||||
@@ -1308,7 +1308,7 @@ session required pam_env.so readenv=1 envfile=/etc/default/locale
|
|||||||
# If user is NOT listed -> succeed and SKIP next two lines (no TOTP prompt).
|
# If user is NOT listed -> succeed and SKIP next two lines (no TOTP prompt).
|
||||||
auth [success=2 default=ignore] pam_listfile.so item=user sense=deny file=/etc/ciss/2fa onerr=ignore
|
auth [success=2 default=ignore] pam_listfile.so item=user sense=deny file=/etc/ciss/2fa onerr=ignore
|
||||||
|
|
||||||
# Listed users: show a clear hint and then require GA. No 'nullok': missing secret → fail.
|
# Listed users: show a clear hint and then require GA. No 'nullok': missing secret -> fail.
|
||||||
auth required pam_echo.so file=/etc/ciss/login_totp.prompt
|
auth required pam_echo.so file=/etc/ciss/login_totp.prompt
|
||||||
auth required pam_google_authenticator.so
|
auth required pam_google_authenticator.so
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user