From 168e0b367fcefe11904f93056eeea5b1f1eadef2 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 01:44:39 +0100 Subject: [PATCH 01/24] Add ncp app for setting up multi factor authentication for ssh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- .../SECURITY/multi-factor-authentication.sh | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100755 bin/ncp/SECURITY/multi-factor-authentication.sh diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh new file mode 100755 index 000000000..f7046e154 --- /dev/null +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -0,0 +1,215 @@ +#!/usr/bin/env bash + +# Authentication Options: +# ======================= +# * Password +# * Pubkey +# * TOTP + Password +# (* TOTP + Pubkey + Password) not yet supported +# * TOTP + Password / TOTP + Pubkey + +PAMD_PATH="./test/etc/pam.d" +PAMD_BACKUP_PATH="./test/etc/pam.backup" +SSHD_CONFIG_PATH="./test/etc/ssh/sshd_config" + + +# Configure pam.d/sshd config +# ====================== + +patch_pam_ssh_config() { + local cfg + + if [[ "$1" == "--reset" ]]; then + if [[ -f "${PAMD_BACKUP_PATH}/sshd" ]]; then + echo "Restoring original configuration for '${PAMD_PATH}/sshd'..." + mv "${PAMD_BACKUP_PATH}/sshd" "${PAMD_PATH}/sshd" || return 1 + rm "${PAMD_PATH}/sshd-mfa" + return 0 + else + echo "ERROR: Could not restore '${PAMD_PATH}/sshd' from backup '${PAMD_BACKUP_PATH}/sshd' (not found)!" + return 1 + fi + fi + + mkdir -p "$PAMD_BACKUP_PATH" + [[ -f "${PAMD_BACKUP_PATH}/sshd" ]] || { + echo "Backing up '${PAMD_PATH}/sshd'..." + cp "${PAMD_PATH}/sshd" "${PAMD_BACKUP_PATH}/sshd" + } || { + echo "Error creating backup. '${PAMD_PATH}/sshd will remain unchanged!" + return 1 + } + + echo "Writing pam configuration..." + echo "" > "${PAMD_PATH}/sshd-mfa" || return 1 + + if [[ "$ENABLE_TOTP_AND_PASSWORD" == "true" ]]; then + echo "auth required pam_google_authenticator.so nullok" >> "${PAMD_PATH}/sshd-mfa" + fi + echo "@include common-auth" >> "${PAMD_PATH}/sshd-mfa" + + sed -i 's/@include.*common-auth/@include sshd-mfa/g' "${PAMD_PATH}/sshd" || return 1 + + +} + +# Configure sshd_config +# ===================== + +#sshd_authentication_options=("password" "publickey" "publickey,password" "keyboard-interactive" +# "keyboard-interactive,publickey" "keyboard-interactive,publickey keyboard-interactive,password") +patch_sshd_config() { + local cfg + local auth_method="${1?}" + + if [[ "$auth_method" == "--reset" ]] + then + if [[ -f "${SSHD_CONFIG_PATH}.backup" ]] + then + echo "Restoring '${SSHD_CONFIG_PATH}' from '${SSHD_CONFIG_PATH}.backup'..." + mv "${SSHD_CONFIG_PATH}.backup" "${SSHD_CONFIG_PATH}" || return 1 + return 0 + else + echo "ERROR: Could not restore '${SSHD_CONFIG_PATH}' from '${SSHD_CONFIG_PATH}.backup' (not found)!" + return 1 + fi + fi + + # backup sshd_config + mkdir -p /etc/pam.backup + [[ -f "${SSHD_CONFIG_PATH}.backup" ]] || { + echo "Backing up '${SSHD_CONFIG_PATH}'..." + cp "$SSHD_CONFIG_PATH" "${SSHD_CONFIG_PATH}.backup" + } || { + echo "Error creating backup. '${PAMD_PATH}/sshd will remain unchanged!" + return 1 + } + + # get sshd_config without google_authenticator + cfg="$( + grep -v -e "AuthenticationMethods" "${SSHD_CONFIG_PATH}.backup" | + grep -v -e "ChallengeResponseAuthentication" | + grep -v -e "PubkeyAuthentication" | + grep -v -e "PasswordAuthentication" | + grep -v -e "UsePAM" + )" + + echo "Writing sshd configuration..." + echo "$cfg" > "$SSHD_CONFIG_PATH" || return 1 + cat << EOF >> "$SSHD_CONFIG_PATH" + +################################### + +PasswordAuthentication yes +PubkeyAuthentication yes +ChallengeResponseAuthentication yes +UsePAM yes +AuthenticationMethods $auth_method + +EOF + +} + +setup_configuration() { + local auth_method="" + + [[ "$enable_pubkey_only" ]] && auth_method="publickey" + [[ "$enable_password_only" ]] && auth_method="${auth_method} password" + + [[ "$ENABLE_TOTP_AND_PASSWORD" == "yes" ]] && auth_method="keyboard-interactive" + [[ "$ENABLE_PUBLIC_KEY_AND_PASSWORD" == "yes" ]] && auth_method="${auth_method} publickey,password" + + patch_pam_ssh_config || return 2 + patch_sshd_config "$auth_method" || return 1 +} + +restore() { + local ret=0 + patch_pam_ssh_config --reset + ret=$((ret + $?)) + patch_sshd_config --reset + ret=$((ret + $?)) + return $ret +} + +################################################################ + +install() { + apt install libpam-google-authenticator +} + +is_active() { + [[ ! -f "${SSHD_CONFIG_PATH}" ]] \ + || [[ ! -f "${PAMD_PATH}/sshd" ]] \ + || grep -q -e "AuthenticationMethods.*keyboard-interactive" -e "AuthenticationMethods.*publickey" "${SSHD_CONFIG_PATH}" \ + || grep -q -e "sshd-mfa" "${PAMD_PATH}/sshd" +} + +configure() { + + local active enable_totp_and_pw enable_pubkey_and_pw enable_pubkey_only enable_pw_only reset_totp_secret + enable_totp_and_pw="$ENABLE_TOTP_AND_PASSWORD" + enable_pubkey_and_pw="$ENABLE_PUBLIC_KEY_AND_PASSWORD" + enable_pubkey_only="$ENABLE_PUBLIC_KEY_ONLY" + enable_pw_only="$ENABLE_PASSWORD_ONLY" + reset_totp_secret="$RESET_TOTP_SECRET" + active="$ACTIVE" + + trap 'restore' HUP INT QUIT PIPE TERM + + if [[ "$active" == "yes" ]] && [[ "$enable_totp_and_pw" != "yes" ]] \ + && [[ "$enable_pubkey_and_pw" != "yes" ]] && [[ "$enable_pubkey_only" != "yes" ]] + then + [[ $enable_pw_only ]] \ + || echo "WARNING: No authentication method has been enabled. Enabling default authentication (password only)..." + active="no" + fi + + if [[ "$active" != "yes" ]] + then + ret=0 + is_active && { restore || ret=$?; } + systemctl is-enabled ssh -q && systemctl restart ssh + return $ret + else +# ENABLE_TOTP_AND_PASSWORD="" +# ENABLE_PUBLIC_KEY_AND_PASSWORD="" +# ENABLE_PUBLIC_KEY_ONLY="" + + if [[ "$enable_totp_and_pw" == "yes" ]] || [[ "$enable_pubkey_and_pw" ]] + then + if [[ "$ENABLE_PUBLIC_KEY_ONLY" == "yes" ]] + then + echo "At least one multifactor authentication method has been enabled. Therefore, weaker authentication methods will be disabled automatically." + echo "Disabling 'public key only' authentication" + enable_pubkey_only=no + fi + fi + fi + + echo "Setting up configuration files..." + setup_configuration || { + ret=$? + restore + return $ret + } + + echo "Restarting ssh service..." + systemctl is-enabled ssh -q && systemctl restart ssh + + # TODO: Should we rather provider an input field for the SSH user (what happens if it is changed in the ssh config)? + SSH_USER="$(jq '.params[] | select(.id == "USER") | .value' < /etc/ncp-config.d/SSH.cfg)" + + [[ "$reset_totp_secret" == "yes" ]] \ + && [[ -f "~$SSH_USER/.google_authenticator" ]] \ + && su "$SSH_USER" -c "rm '~$SSH_USER/.google_authenticator'" + + if [[ "$enable_totp_and_pw" ]] && [[ ! -f "~$SSH_USER/.google_authenticator" ]] + then + echo "We will now generate TOTP a client secret for your ssh user ('$SSH_USER')." + echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app." + echo "" + su "$SSH_USER" -c "google-authenticator -tdf -w 1 --no-rate-limit" + fi + +} \ No newline at end of file From 6fa0ef45ebfc64e401637772fa34df6e351602a0 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 02:22:53 +0100 Subject: [PATCH 02/24] Properly restore default pam configuration if totp was not enabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix misspelled variable names Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- .../SECURITY/multi-factor-authentication.sh | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index f7046e154..e1612c34a 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -19,7 +19,8 @@ SSHD_CONFIG_PATH="./test/etc/ssh/sshd_config" patch_pam_ssh_config() { local cfg - if [[ "$1" == "--reset" ]]; then + if [[ "$1" == "--reset" ]] + then if [[ -f "${PAMD_BACKUP_PATH}/sshd" ]]; then echo "Restoring original configuration for '${PAMD_PATH}/sshd'..." mv "${PAMD_BACKUP_PATH}/sshd" "${PAMD_PATH}/sshd" || return 1 @@ -41,14 +42,20 @@ patch_pam_ssh_config() { } echo "Writing pam configuration..." + if [[ "$enable_totp_and_pw" != "yes" ]] + then + cp "${PAMD_BACKUP_PATH}/sshd" "${PAMD_PATH}/sshd" || return 1 + [[ -f "${PAMD_PATH}/sshd-mfa" ]] && rm "${PAMD_PATH}/sshd-mfa" + return 0 + fi echo "" > "${PAMD_PATH}/sshd-mfa" || return 1 - if [[ "$ENABLE_TOTP_AND_PASSWORD" == "true" ]]; then + if [[ "$enable_totp_and_pw" == "yes" ]]; then echo "auth required pam_google_authenticator.so nullok" >> "${PAMD_PATH}/sshd-mfa" fi echo "@include common-auth" >> "${PAMD_PATH}/sshd-mfa" - sed -i 's/@include.*common-auth/@include sshd-mfa/g' "${PAMD_PATH}/sshd" || return 1 + sed 's/@include.*common-auth/@include sshd-mfa/g' "${PAMD_BACKUP_PATH}/sshd" > "${PAMD_PATH}/sshd" || return 1 } @@ -114,10 +121,10 @@ setup_configuration() { local auth_method="" [[ "$enable_pubkey_only" ]] && auth_method="publickey" - [[ "$enable_password_only" ]] && auth_method="${auth_method} password" + [[ "$enable_pw_only" ]] && auth_method="${auth_method} password" - [[ "$ENABLE_TOTP_AND_PASSWORD" == "yes" ]] && auth_method="keyboard-interactive" - [[ "$ENABLE_PUBLIC_KEY_AND_PASSWORD" == "yes" ]] && auth_method="${auth_method} publickey,password" + [[ "$enable_totp_and_pw" == "yes" ]] && auth_method="keyboard-interactive" + [[ "$enable_pubkey_and_pw" == "yes" ]] && auth_method="${auth_method} publickey,password" patch_pam_ssh_config || return 2 patch_sshd_config "$auth_method" || return 1 @@ -204,7 +211,7 @@ configure() { && [[ -f "~$SSH_USER/.google_authenticator" ]] \ && su "$SSH_USER" -c "rm '~$SSH_USER/.google_authenticator'" - if [[ "$enable_totp_and_pw" ]] && [[ ! -f "~$SSH_USER/.google_authenticator" ]] + if [[ "$enable_totp_and_pw" == "yes" ]] && [[ ! -f "$(sudo -Hu "$SSH_USER" bash -c 'echo "$HOME"')/.google_authenticator" ]] then echo "We will now generate TOTP a client secret for your ssh user ('$SSH_USER')." echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app." From 71042daa534516aa95d11fcd91e3e8cc394bacaa Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 02:33:22 +0100 Subject: [PATCH 03/24] Add configuration for multi factor authentication app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- .../multi-factor-authentication.cfg | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 etc/ncp-config.d/multi-factor-authentication.cfg diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg new file mode 100644 index 000000000..53da8bf98 --- /dev/null +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -0,0 +1,46 @@ +{ + "id": "MFA", + "name": "Activate multi factory authentication for SSH login", + "title": "Multi-Factor-Authentication", + "description": "Choose among different (single and multi factor) authentication methods for SSH login.", + "info": "The default method (e.g. when this app is disabled) is 'password only'. Please not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods", + "infotitle": "MFA notes", + "params": [ + { + "id": "ACTIVE", + "name": "Active", + "value": "no", + "type": "bool" + }, + { + "id": "ENABLE_PASSWORD_ONLY", + "name": "enable password only authentication", + "value": "yes", + "type": "bool" + }, + { + "id": "ENABLE_PUBLIC_KEY_ONLY", + "name": "enable public key only authentication", + "value": "no", + "type": "bool" + }, + { + "id": "ENABLE_PUBLIC_KEY_AND_PASSWORD", + "name": "enable public key + password authentication (MFA)", + "value": "no", + "type": "bool" + }, + { + "id": "ENABLE_TOTP_AND_PASSWORD", + "name": "enable time-based one time password (TOTP) + password (MFA)", + "value": "no", + "type": "bool" + }, + { + "id": "RESET_TOTP CLIENT SECRET", + "name": "reset the TOTP client secret when applying changes", + "value": "no", + "type": "bool" + } + ] +} \ No newline at end of file From 35d7f049d1ea63aeaa973364593e227ac88ae3d0 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+thecalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 02:41:25 +0100 Subject: [PATCH 04/24] Add cleanup() function to multi-factor-authentication.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index e1612c34a..6ccd86f33 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -141,6 +141,11 @@ restore() { ################################################################ +cleanup() { + restore + [[ -d "${PAMD_BACKUP_PATH}" ]] && rm -r "${PAMD_BACKUP_PATH}" +} + install() { apt install libpam-google-authenticator } From 07a642d7e79f541c94927e06e51c3ee92c37b144 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 02:57:04 +0100 Subject: [PATCH 05/24] multi-factor-authentication: use apt in non-interactive mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 6ccd86f33..bd4a165eb 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -147,7 +147,7 @@ cleanup() { } install() { - apt install libpam-google-authenticator + apt install -y libpam-google-authenticator } is_active() { From 8f2ec463f1e871f67b2cd529c0a0ea510b0122cd Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 03:03:00 +0100 Subject: [PATCH 06/24] multi-factor-authentication: Simplify is-active function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index bd4a165eb..9179e98ad 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -151,9 +151,7 @@ install() { } is_active() { - [[ ! -f "${SSHD_CONFIG_PATH}" ]] \ - || [[ ! -f "${PAMD_PATH}/sshd" ]] \ - || grep -q -e "AuthenticationMethods.*keyboard-interactive" -e "AuthenticationMethods.*publickey" "${SSHD_CONFIG_PATH}" \ + grep -q -e "AuthenticationMethods.*keyboard-interactive" -e "AuthenticationMethods.*publickey" "${SSHD_CONFIG_PATH}" \ || grep -q -e "sshd-mfa" "${PAMD_PATH}/sshd" } From 48622bbc7c9edb6af30dc2d825726ed45b4cff45 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 03:44:47 +0100 Subject: [PATCH 07/24] multi-factor-authentication: Use jq in 'raw' mode (to avoid additional quotes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 2 +- etc/ncp-config.d/multi-factor-authentication.cfg | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 9179e98ad..0b7861257 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -208,7 +208,7 @@ configure() { systemctl is-enabled ssh -q && systemctl restart ssh # TODO: Should we rather provider an input field for the SSH user (what happens if it is changed in the ssh config)? - SSH_USER="$(jq '.params[] | select(.id == "USER") | .value' < /etc/ncp-config.d/SSH.cfg)" + SSH_USER="$(jq -r '.params[] | select(.id == "USER") | .value' < /usr/local/etc/ncp-config.d/SSH.cfg)" [[ "$reset_totp_secret" == "yes" ]] \ && [[ -f "~$SSH_USER/.google_authenticator" ]] \ diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index 53da8bf98..f1f61a8e2 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -1,9 +1,9 @@ { - "id": "MFA", + "id": "multi-factor-authentication", "name": "Activate multi factory authentication for SSH login", "title": "Multi-Factor-Authentication", "description": "Choose among different (single and multi factor) authentication methods for SSH login.", - "info": "The default method (e.g. when this app is disabled) is 'password only'. Please not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods", + "info": "The default method (e.g. when this app is disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods", "infotitle": "MFA notes", "params": [ { @@ -14,31 +14,31 @@ }, { "id": "ENABLE_PASSWORD_ONLY", - "name": "enable password only authentication", + "name": "enable-password-only-authentication", "value": "yes", "type": "bool" }, { "id": "ENABLE_PUBLIC_KEY_ONLY", - "name": "enable public key only authentication", + "name": "enable-public-key-only-authentication", "value": "no", "type": "bool" }, { "id": "ENABLE_PUBLIC_KEY_AND_PASSWORD", - "name": "enable public key + password authentication (MFA)", + "name": "enable-public-key-plus-password-authentication", "value": "no", "type": "bool" }, { "id": "ENABLE_TOTP_AND_PASSWORD", - "name": "enable time-based one time password (TOTP) + password (MFA)", + "name": "enable-time-based-one-time-password-plus-password", "value": "no", "type": "bool" }, { - "id": "RESET_TOTP CLIENT SECRET", - "name": "reset the TOTP client secret when applying changes", + "id": "RESET_TOTP SECRET", + "name": "reset-the-TOTP-client-secret-when-applying-changes", "value": "no", "type": "bool" } From 938499e93dbcd9625e503212b02d911b4aa3d1c2 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 16:36:31 +0100 Subject: [PATCH 08/24] multi-factor-authentication: Implement public key setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- .../SECURITY/multi-factor-authentication.sh | 43 ++++++++++++++----- .../multi-factor-authentication.cfg | 16 ++++--- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 0b7861257..6d4da7743 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -8,9 +8,9 @@ # (* TOTP + Pubkey + Password) not yet supported # * TOTP + Password / TOTP + Pubkey -PAMD_PATH="./test/etc/pam.d" -PAMD_BACKUP_PATH="./test/etc/pam.backup" -SSHD_CONFIG_PATH="./test/etc/ssh/sshd_config" +PAMD_PATH="/etc/pam.d" +PAMD_BACKUP_PATH="/etc/pam.backup" +SSHD_CONFIG_PATH="/etc/ssh/sshd_config" # Configure pam.d/sshd config @@ -130,6 +130,23 @@ setup_configuration() { patch_sshd_config "$auth_method" || return 1 } +setup_totp_secret() { + local ssh_user="${1?}" + local ssh_user_home="${2?}" + + [[ "$reset_totp_secret" == "yes" ]] \ + && [[ -f "$ssh_user_home/.google_authenticator" ]] \ + && su "$ssh_user" -c "rm '${ssh_user_home}/.google_authenticator'" + + if [[ "$enable_totp_and_pw" == "yes" ]] && [[ ! -f "${ssh_user_home}/.google_authenticator" ]] + then + echo "We will now generate TOTP a client secret for your ssh user ('$ssh_user')." + echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app." + echo "" + su "$ssh_user" -c "google-authenticator -tdf -w 1 --no-rate-limit" + fi +} + restore() { local ret=0 patch_pam_ssh_config --reset @@ -209,17 +226,21 @@ configure() { # TODO: Should we rather provider an input field for the SSH user (what happens if it is changed in the ssh config)? SSH_USER="$(jq -r '.params[] | select(.id == "USER") | .value' < /usr/local/etc/ncp-config.d/SSH.cfg)" + SSH_USER_HOME="$(sudo -Hu "$SSH_USER" bash -c 'echo "$HOME"')" - [[ "$reset_totp_secret" == "yes" ]] \ - && [[ -f "~$SSH_USER/.google_authenticator" ]] \ - && su "$SSH_USER" -c "rm '~$SSH_USER/.google_authenticator'" + if [[ -n "$SSH_USER" ]] && id -u "$SSH_USER" > /dev/null + then + echo "Setup incomplete. Please configure SSH via the ncp app and rerun." + return 1 + fi - if [[ "$enable_totp_and_pw" == "yes" ]] && [[ ! -f "$(sudo -Hu "$SSH_USER" bash -c 'echo "$HOME"')/.google_authenticator" ]] + if [[ -n "$SSH_PUBLIC_KEY" ]] then - echo "We will now generate TOTP a client secret for your ssh user ('$SSH_USER')." - echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app." - echo "" - su "$SSH_USER" -c "google-authenticator -tdf -w 1 --no-rate-limit" + echo "Setting up SSH public key..." + echo "$SSH_PUBLIC_KEY" > "${SSH_USER_HOME}/.ssh/authorized_keys" + chown "${SSH_USER}:" "${SSH_USER_HOME}/.ssh/authorized_keys" fi + setup_totp_secret "$SSH_USER" "$SSH_USER_HOME" + } \ No newline at end of file diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index f1f61a8e2..8bc8afc6d 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -14,33 +14,39 @@ }, { "id": "ENABLE_PASSWORD_ONLY", - "name": "enable-password-only-authentication", + "name": "enable-password-only", "value": "yes", "type": "bool" }, { "id": "ENABLE_PUBLIC_KEY_ONLY", - "name": "enable-public-key-only-authentication", + "name": "enable-public-key-only", "value": "no", "type": "bool" }, { "id": "ENABLE_PUBLIC_KEY_AND_PASSWORD", - "name": "enable-public-key-plus-password-authentication", + "name": "enable-public-key-plus-password", "value": "no", "type": "bool" }, { "id": "ENABLE_TOTP_AND_PASSWORD", - "name": "enable-time-based-one-time-password-plus-password", + "name": "enable-TOTP-plus-password", "value": "no", "type": "bool" }, { "id": "RESET_TOTP SECRET", - "name": "reset-the-TOTP-client-secret-when-applying-changes", + "name": "reset-TOTP-secret", "value": "no", "type": "bool" + }, + { + "id": "SSH_PUBLIC_KEY", + "name": "SSH Public Key", + "value": "", + "suggest": "Paste your public key here" } ] } \ No newline at end of file From 386129a60b3ef128d99d5a20e204dbc61d7fd461 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 16:44:29 +0100 Subject: [PATCH 09/24] multi-factor-authentication: Fix improper check whether or not SSH user was retrieved correctly. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 6d4da7743..df4c4f12a 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -228,12 +228,12 @@ configure() { SSH_USER="$(jq -r '.params[] | select(.id == "USER") | .value' < /usr/local/etc/ncp-config.d/SSH.cfg)" SSH_USER_HOME="$(sudo -Hu "$SSH_USER" bash -c 'echo "$HOME"')" - if [[ -n "$SSH_USER" ]] && id -u "$SSH_USER" > /dev/null - then + [[ -n "$SSH_USER" ]] || id -u "$SSH_USER" > /dev/null || { echo "Setup incomplete. Please configure SSH via the ncp app and rerun." return 1 - fi + } + # Setup SSH public key if provided if [[ -n "$SSH_PUBLIC_KEY" ]] then echo "Setting up SSH public key..." @@ -243,4 +243,6 @@ configure() { setup_totp_secret "$SSH_USER" "$SSH_USER_HOME" + echo "Done." + } \ No newline at end of file From 2caaaf6354903fae9c6b33521bb0f496734b79ee Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 14 Dec 2019 17:12:41 +0100 Subject: [PATCH 10/24] Implement escaping of spaces in ncp-app parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 7 ++++--- etc/library.sh | 6 ++++++ etc/ncp-config.d/multi-factor-authentication.cfg | 3 ++- ncp-web/ncp-launcher.php | 2 ++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index df4c4f12a..54e457bf2 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -174,13 +174,14 @@ is_active() { configure() { - local active enable_totp_and_pw enable_pubkey_and_pw enable_pubkey_only enable_pw_only reset_totp_secret + local active enable_totp_and_pw enable_pubkey_and_pw enable_pubkey_only enable_pw_only reset_totp_secret ssh_pubkey enable_totp_and_pw="$ENABLE_TOTP_AND_PASSWORD" enable_pubkey_and_pw="$ENABLE_PUBLIC_KEY_AND_PASSWORD" enable_pubkey_only="$ENABLE_PUBLIC_KEY_ONLY" enable_pw_only="$ENABLE_PASSWORD_ONLY" reset_totp_secret="$RESET_TOTP_SECRET" active="$ACTIVE" + ssh_pubkey="$(unescape "$SSH_PUBLIC_KEY")" trap 'restore' HUP INT QUIT PIPE TERM @@ -234,10 +235,10 @@ configure() { } # Setup SSH public key if provided - if [[ -n "$SSH_PUBLIC_KEY" ]] + if [[ -n "$ssh_pubkey" ]] then echo "Setting up SSH public key..." - echo "$SSH_PUBLIC_KEY" > "${SSH_USER_HOME}/.ssh/authorized_keys" + echo "$ssh_pubkey" > "${SSH_USER_HOME}/.ssh/authorized_keys" chown "${SSH_USER}:" "${SSH_USER_HOME}/.ssh/authorized_keys" fi diff --git a/etc/library.sh b/etc/library.sh index dd9b4b479..d9a174f4a 100644 --- a/etc/library.sh +++ b/etc/library.sh @@ -278,6 +278,12 @@ function check_distro() return 1 } +function unescape() +{ + local str="${1?}" + echo "${str//"%SPACE%"/" "}" +} + function apt_install() { apt-get update diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index 8bc8afc6d..9b51d3509 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -46,7 +46,8 @@ "id": "SSH_PUBLIC_KEY", "name": "SSH Public Key", "value": "", - "suggest": "Paste your public key here" + "suggest": "Paste your public key here", + "allow_unsafe": "true" } ] } \ No newline at end of file diff --git a/ncp-web/ncp-launcher.php b/ncp-web/ncp-launcher.php index a74bb01ac..2e50087ec 100644 --- a/ncp-web/ncp-launcher.php +++ b/ncp-web/ncp-launcher.php @@ -66,6 +66,8 @@ // sanitize $val = trim(escapeshellarg($new_params[$id]),"'"); + if (array_key_exists('allow_unsafe', $cfg['params'][$index]) && $cfg['params'][$index]['allow_unsafe'] == "true") + $val = str_replace(" ", "%SPACE%", $val); preg_match( '/[\'" ]/' , $val , $matches ) and exit( '{ "output": "Invalid parameters" , "token": "' . getCSRFToken() . '" }' ); From f98f21f1c97ecf4669075695fb80f7f83dc0b8fe Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sun, 15 Dec 2019 14:48:31 +0100 Subject: [PATCH 11/24] multi-factor-authentication: Prevent enabling of totp+pw and other password reliant methods (not possible due to limitations of sshd configuration) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- .../SECURITY/multi-factor-authentication.sh | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 54e457bf2..76d58bc45 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -96,8 +96,8 @@ patch_sshd_config() { cfg="$( grep -v -e "AuthenticationMethods" "${SSHD_CONFIG_PATH}.backup" | grep -v -e "ChallengeResponseAuthentication" | - grep -v -e "PubkeyAuthentication" | grep -v -e "PasswordAuthentication" | + grep -v -e "PubkeyAuthentication" | grep -v -e "UsePAM" )" @@ -156,6 +156,21 @@ restore() { return $ret } +check_configuration_is_valid() { + if { [[ "$enable_pubkey_and_pw" == "yes" ]] || [[ "$enable_pubkey_only" == "yes" ]]; } && [[ -z "$SSH_PUBLIC_KEY" ]] + then + echo "ERROR: Public key reliant authentication methods have been enabled, but no publick key has been specified. Aborting..." + return 1 + fi + + if [[ "$enable_totp_and_pw" == "yes" ]] && [[ "$enable_pubkey_and_pw" == "yes" ]] + then + echo "Due to limitations of the sshd configuration, totp+pw and other authentication methods involving a password can't be enabled at the same time." + echo "Aborting..." + return 1 + fi +} + ################################################################ cleanup() { @@ -180,11 +195,29 @@ configure() { enable_pubkey_only="$ENABLE_PUBLIC_KEY_ONLY" enable_pw_only="$ENABLE_PASSWORD_ONLY" reset_totp_secret="$RESET_TOTP_SECRET" - active="$ACTIVE" + active="yes" ssh_pubkey="$(unescape "$SSH_PUBLIC_KEY")" trap 'restore' HUP INT QUIT PIPE TERM + if [[ -f "/usr/local/etc/ncp-config.d/SSH.cfg" ]] + then + # TODO: Should we rather provider an input field for the SSH user (what happens if it is changed in the ssh config)? + SSH_USER="$(jq -r '.params[] | select(.id == "USER") | .value' < /usr/local/etc/ncp-config.d/SSH.cfg)" + SSH_USER_HOME="$(sudo -Hu "$SSH_USER" bash -c 'echo "$HOME"')" + fi + + [[ -n "$SSH_USER" ]] || id -u "$SSH_USER" > /dev/null || { + echo "Setup incomplete. Please configure SSH via the ncp app and rerun." + return 1 + } + + [[ "$enable_totp_and_pw" == "no" ]] && [[ "$enable_pubkey_and_pw" == "no" ]] \ + && [[ "$enable_pubkey_only" == "no" ]] && [[ "$enable_pw_only" == "yes" ]] && { + echo "Default configuration has been detected. Restoring defaults..." + active="no" + } + if [[ "$active" == "yes" ]] && [[ "$enable_totp_and_pw" != "yes" ]] \ && [[ "$enable_pubkey_and_pw" != "yes" ]] && [[ "$enable_pubkey_only" != "yes" ]] then @@ -200,18 +233,20 @@ configure() { systemctl is-enabled ssh -q && systemctl restart ssh return $ret else -# ENABLE_TOTP_AND_PASSWORD="" -# ENABLE_PUBLIC_KEY_AND_PASSWORD="" -# ENABLE_PUBLIC_KEY_ONLY="" - if [[ "$enable_totp_and_pw" == "yes" ]] || [[ "$enable_pubkey_and_pw" ]] + check_configuration_is_valid || return 3 + + if [[ "$enable_totp_and_pw" == "yes" ]] || [[ "$enable_pubkey_and_pw" == "yes" ]] then - if [[ "$ENABLE_PUBLIC_KEY_ONLY" == "yes" ]] - then - echo "At least one multifactor authentication method has been enabled. Therefore, weaker authentication methods will be disabled automatically." + echo "At least one multifactor authentication method has been enabled. Therefore, weaker authentication methods will be disabled automatically." + [[ "$enable_pubkey_only" == "yes" ]] && { echo "Disabling 'public key only' authentication" enable_pubkey_only=no - fi + } + [[ "$enable_pw_only" == "yes" ]] && { + echo "Disabling 'password only' authentication" + enable_pw_only=no + } fi fi @@ -225,15 +260,6 @@ configure() { echo "Restarting ssh service..." systemctl is-enabled ssh -q && systemctl restart ssh - # TODO: Should we rather provider an input field for the SSH user (what happens if it is changed in the ssh config)? - SSH_USER="$(jq -r '.params[] | select(.id == "USER") | .value' < /usr/local/etc/ncp-config.d/SSH.cfg)" - SSH_USER_HOME="$(sudo -Hu "$SSH_USER" bash -c 'echo "$HOME"')" - - [[ -n "$SSH_USER" ]] || id -u "$SSH_USER" > /dev/null || { - echo "Setup incomplete. Please configure SSH via the ncp app and rerun." - return 1 - } - # Setup SSH public key if provided if [[ -n "$ssh_pubkey" ]] then From 97c9df4d6978bf74d6cfb294d64bf16025280baa Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sun, 15 Dec 2019 14:57:27 +0100 Subject: [PATCH 12/24] multi-factor-authentication: Only enable the "UsePAM" setting, if totp is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 76d58bc45..ac34b8cf2 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -24,7 +24,7 @@ patch_pam_ssh_config() { if [[ -f "${PAMD_BACKUP_PATH}/sshd" ]]; then echo "Restoring original configuration for '${PAMD_PATH}/sshd'..." mv "${PAMD_BACKUP_PATH}/sshd" "${PAMD_PATH}/sshd" || return 1 - rm "${PAMD_PATH}/sshd-mfa" + [[ -f "${PAMD_PATH}/sshd-mfa" ]] && rm "${PAMD_PATH}/sshd-mfa" return 0 else echo "ERROR: Could not restore '${PAMD_PATH}/sshd' from backup '${PAMD_BACKUP_PATH}/sshd' (not found)!" @@ -110,7 +110,7 @@ patch_sshd_config() { PasswordAuthentication yes PubkeyAuthentication yes ChallengeResponseAuthentication yes -UsePAM yes +UsePAM $enable_totp_and_pw AuthenticationMethods $auth_method EOF @@ -120,8 +120,8 @@ EOF setup_configuration() { local auth_method="" - [[ "$enable_pubkey_only" ]] && auth_method="publickey" - [[ "$enable_pw_only" ]] && auth_method="${auth_method} password" + [[ "$enable_pubkey_only" == "yes" ]] && auth_method="publickey" + [[ "$enable_pw_only" == "yes" ]] && auth_method="${auth_method} password" [[ "$enable_totp_and_pw" == "yes" ]] && auth_method="keyboard-interactive" [[ "$enable_pubkey_and_pw" == "yes" ]] && auth_method="${auth_method} publickey,password" From ed0d597e8339c3baa7b9c103fd266ad1f92a123f Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sun, 15 Dec 2019 14:58:34 +0100 Subject: [PATCH 13/24] multi-factor-authentication: Remove obsolete "ACTIVE" parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- etc/ncp-config.d/multi-factor-authentication.cfg | 6 ------ 1 file changed, 6 deletions(-) diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index 9b51d3509..2d3026979 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -6,12 +6,6 @@ "info": "The default method (e.g. when this app is disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods", "infotitle": "MFA notes", "params": [ - { - "id": "ACTIVE", - "name": "Active", - "value": "no", - "type": "bool" - }, { "id": "ENABLE_PASSWORD_ONLY", "name": "enable-password-only", From 76465c876b8239add560fe86487f775d85a497d2 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sun, 15 Dec 2019 15:03:00 +0100 Subject: [PATCH 14/24] multi-factor-authentication: Improve description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- etc/ncp-config.d/multi-factor-authentication.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index 2d3026979..17c301637 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -3,7 +3,7 @@ "name": "Activate multi factory authentication for SSH login", "title": "Multi-Factor-Authentication", "description": "Choose among different (single and multi factor) authentication methods for SSH login.", - "info": "The default method (e.g. when this app is disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods", + "info": "The default method (i.e. this app being disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods.\nThe TOTP authentication requires a compatible app to be used, e.g. FreeOTP, Google Authenticator or Authy.\nIf you enable multiple options, they will act as alternatives.", "infotitle": "MFA notes", "params": [ { From a71071de5204f19639b6246fbf5409f6a62bedd1 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sun, 15 Dec 2019 15:06:44 +0100 Subject: [PATCH 15/24] multi-factor-authentication: Remove existing authorized ssh pubkeys if none was given MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index ac34b8cf2..650f2cdc9 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -260,12 +260,16 @@ configure() { echo "Restarting ssh service..." systemctl is-enabled ssh -q && systemctl restart ssh - # Setup SSH public key if provided - if [[ -n "$ssh_pubkey" ]] + # Setup SSH public key + if [[ -n "$SSH_PUBLIC_KEY" ]] then echo "Setting up SSH public key..." echo "$ssh_pubkey" > "${SSH_USER_HOME}/.ssh/authorized_keys" chown "${SSH_USER}:" "${SSH_USER_HOME}/.ssh/authorized_keys" + elif [[ -f "${SSH_USER_HOME}/.ssh/authorized_keys" ]] + then + echo "Removing authorized ssh public key" + rm "${SSH_USER_HOME}/.ssh/authorized_keys" fi setup_totp_secret "$SSH_USER" "$SSH_USER_HOME" From dbea3bcda63b1d97b9416a2aefd98cd44ff5ee18 Mon Sep 17 00:00:00 2001 From: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Date: Sun, 15 Dec 2019 15:43:14 +0100 Subject: [PATCH 16/24] multi-factor-authentication: Ensure we have permissions to delete google authenticator configuration when resetting it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 7 ++++++- etc/ncp-config.d/multi-factor-authentication.cfg | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 650f2cdc9..c15489f91 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -136,7 +136,12 @@ setup_totp_secret() { [[ "$reset_totp_secret" == "yes" ]] \ && [[ -f "$ssh_user_home/.google_authenticator" ]] \ - && su "$ssh_user" -c "rm '${ssh_user_home}/.google_authenticator'" + && { + echo "Deleting google authenticator configuration" + su "$ssh_user" -c "chmod u+w '${ssh_user_home}/.google_authenticator'" + su "$ssh_user" -c "rm '${ssh_user_home}/.google_authenticator'" + } + if [[ "$enable_totp_and_pw" == "yes" ]] && [[ ! -f "${ssh_user_home}/.google_authenticator" ]] then diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index 17c301637..d20d575a2 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -31,7 +31,7 @@ "type": "bool" }, { - "id": "RESET_TOTP SECRET", + "id": "RESET_TOTP_SECRET", "name": "reset-TOTP-secret", "value": "no", "type": "bool" From 9c1b2539f338531e9367e3cebcbb914dc66f3f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= Date: Thu, 19 Dec 2019 16:28:19 +0100 Subject: [PATCH 17/24] Use
 tags and UTF8 mode to show qr code in browser
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com>
---
 bin/ncp/SECURITY/multi-factor-authentication.sh | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh
index c15489f91..2eace43b0 100755
--- a/bin/ncp/SECURITY/multi-factor-authentication.sh
+++ b/bin/ncp/SECURITY/multi-factor-authentication.sh
@@ -148,7 +148,9 @@ setup_totp_secret() {
     echo "We will now generate TOTP a client secret for your ssh user ('$ssh_user')."
     echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app."
     echo ""
-    su "$ssh_user" -c "google-authenticator -tdf -w 1 --no-rate-limit"
+    echo "
"
+    su "$ssh_user" -c "google-authenticator -tdf -Q UTF8 -w 1 --no-rate-limit"
+    echo "
" fi } @@ -281,4 +283,4 @@ configure() { echo "Done." -} \ No newline at end of file +} From 58a6c1fba40fa11bc15dca2fd23bb611fad6c4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= Date: Thu, 26 Dec 2019 01:46:21 +0100 Subject: [PATCH 18/24] Revert "Use
 tags and UTF8 mode to show qr code in
 browser"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This reverts commit cfe094c0

Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com>
---
 bin/ncp/SECURITY/multi-factor-authentication.sh | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh
index 2eace43b0..c15489f91 100755
--- a/bin/ncp/SECURITY/multi-factor-authentication.sh
+++ b/bin/ncp/SECURITY/multi-factor-authentication.sh
@@ -148,9 +148,7 @@ setup_totp_secret() {
     echo "We will now generate TOTP a client secret for your ssh user ('$ssh_user')."
     echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app."
     echo ""
-    echo "
"
-    su "$ssh_user" -c "google-authenticator -tdf -Q UTF8 -w 1 --no-rate-limit"
-    echo "
" + su "$ssh_user" -c "google-authenticator -tdf -w 1 --no-rate-limit" fi } @@ -283,4 +281,4 @@ configure() { echo "Done." -} +} \ No newline at end of file From e487dcdfe408f80ece2327196c405f9bbf61bb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= Date: Thu, 26 Dec 2019 01:51:35 +0100 Subject: [PATCH 19/24] multi-factor-authentication.sh: Remove mention of qr code since it is not working multi-factor-authentication.cfg: Add Keepass2Android as compatible OTP app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 4 ++-- etc/ncp-config.d/multi-factor-authentication.cfg | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index c15489f91..fbc21a0c3 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -146,7 +146,7 @@ setup_totp_secret() { if [[ "$enable_totp_and_pw" == "yes" ]] && [[ ! -f "${ssh_user_home}/.google_authenticator" ]] then echo "We will now generate TOTP a client secret for your ssh user ('$ssh_user')." - echo "Please store the following information in a safe place. Use your secret key or scan the QR code (terminal only) to setup your authenticator app." + echo "Please store the following information in a safe place. Use your secret key to setup your authenticator app." echo "" su "$ssh_user" -c "google-authenticator -tdf -w 1 --no-rate-limit" fi @@ -281,4 +281,4 @@ configure() { echo "Done." -} \ No newline at end of file +} diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index d20d575a2..c14d13437 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -3,7 +3,7 @@ "name": "Activate multi factory authentication for SSH login", "title": "Multi-Factor-Authentication", "description": "Choose among different (single and multi factor) authentication methods for SSH login.", - "info": "The default method (i.e. this app being disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods.\nThe TOTP authentication requires a compatible app to be used, e.g. FreeOTP, Google Authenticator or Authy.\nIf you enable multiple options, they will act as alternatives.", + "info": "The default method (i.e. this app being disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods.\nThe TOTP authentication requires a compatible app to be used, e.g. FreeOTP, Keepass2Android, Google Authenticator or Authy.\nIf you enable multiple options, they will act as alternatives.", "infotitle": "MFA notes", "params": [ { @@ -44,4 +44,4 @@ "allow_unsafe": "true" } ] -} \ No newline at end of file +} From 500e9dc00a03c9281eace31fd449cb96762e8318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= Date: Fri, 27 Dec 2019 14:40:34 +0100 Subject: [PATCH 20/24] multi-factor-authentication.cfg: Fix typos and improve concision. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- etc/ncp-config.d/multi-factor-authentication.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index c14d13437..9b42b92a0 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -2,8 +2,8 @@ "id": "multi-factor-authentication", "name": "Activate multi factory authentication for SSH login", "title": "Multi-Factor-Authentication", - "description": "Choose among different (single and multi factor) authentication methods for SSH login.", - "info": "The default method (i.e. this app being disabled) is 'password only'.\nPlease not that single factor authentication methods can not be enabled at the same time as multi factor authentication methods.\nThe TOTP authentication requires a compatible app to be used, e.g. FreeOTP, Keepass2Android, Google Authenticator or Authy.\nIf you enable multiple options, they will act as alternatives.", + "description": "Choose the authentication method for SSH login.", + "info": "The default method is 'password only'.\nPlease note that single factor authentication methods can not be enabled at the same time as multi factor authentication methods.\nThe TOTP authentication requires a compatible app to be used, e.g. FreeOTP, Keepass2Android, Google Authenticator or Authy.\nIf you enable multiple options, they will act as alternatives.", "infotitle": "MFA notes", "params": [ { From 4fc85ceed308e0ce9e159e8ed57e2273a76288fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 11 Jan 2020 00:04:03 +0100 Subject: [PATCH 21/24] multi-factor-authentication.*: Provide 5 fields for SSH pub keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- .../SECURITY/multi-factor-authentication.sh | 15 +++++++-- .../multi-factor-authentication.cfg | 32 +++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index fbc21a0c3..783dceda6 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -201,7 +201,13 @@ configure() { enable_pw_only="$ENABLE_PASSWORD_ONLY" reset_totp_secret="$RESET_TOTP_SECRET" active="yes" - ssh_pubkey="$(unescape "$SSH_PUBLIC_KEY")" + ssh_pubkeys=("$(unescape "$SSH_PUBLIC_KEY_1")" \ + "$(unescape "$SSH_PUBLIC_KEY_2")" \ + "$(unescape "$SSH_PUBLIC_KEY_3")" \ + "$(unescape "$SSH_PUBLIC_KEY_4")" \ + "$(unescape "$SSH_PUBLIC_KEY_5")") + echo "SSH PUBKEYS:" + echo "${ssh_pubkeys[*]}" trap 'restore' HUP INT QUIT PIPE TERM @@ -266,10 +272,13 @@ configure() { systemctl is-enabled ssh -q && systemctl restart ssh # Setup SSH public key - if [[ -n "$SSH_PUBLIC_KEY" ]] + if [[ -n "${ssh_pubkeys[*]}" ]] then echo "Setting up SSH public key..." - echo "$ssh_pubkey" > "${SSH_USER_HOME}/.ssh/authorized_keys" + local IFS_BK="$IFS" + IFS=$'\n' + echo "${ssh_pubkeys[*]}" > "${SSH_USER_HOME}/.ssh/authorized_keys" + IFS="$IFS_BK" chown "${SSH_USER}:" "${SSH_USER_HOME}/.ssh/authorized_keys" elif [[ -f "${SSH_USER_HOME}/.ssh/authorized_keys" ]] then diff --git a/etc/ncp-config.d/multi-factor-authentication.cfg b/etc/ncp-config.d/multi-factor-authentication.cfg index 9b42b92a0..d8a87784c 100644 --- a/etc/ncp-config.d/multi-factor-authentication.cfg +++ b/etc/ncp-config.d/multi-factor-authentication.cfg @@ -37,11 +37,39 @@ "type": "bool" }, { - "id": "SSH_PUBLIC_KEY", - "name": "SSH Public Key", + "id": "SSH_PUBLIC_KEY_1", + "name": "SSH Public Key 1", "value": "", "suggest": "Paste your public key here", "allow_unsafe": "true" + }, + { + "id": "SSH_PUBLIC_KEY_2", + "name": "SSH Public Key 2", + "value": "", + "suggest": "Paste your public key here", + "allow_unsafe": "true" + }, + { + "id": "SSH_PUBLIC_KEY_3", + "name": "SSH Public Key 3", + "value": "", + "suggest": "Paste your public key here", + "allow_unsafe": "true" + }, + { + "id": "SSH_PUBLIC_KEY_4", + "name": "SSH Public Key 4", + "value": "", + "suggest": "Paste your public key here", + "allow_unsafe": "true" + }, + { + "id": "SSH_PUBLIC_KEY_5", + "name": "SSH Public Key 5", + "value": "", + "suggest": "Paste your public key here", + "allow_unsafe": "true" } ] } From cbbf624ee4b1bdf7c2e5735011aeb8826b936e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 11 Jan 2020 00:47:01 +0100 Subject: [PATCH 22/24] library.sh: Support parameters with 'allow_unsafe' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit elements.php: Replace '%SPACE%' with ' ' for parameters with 'allow_unsafe' Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- etc/library.sh | 5 +++++ ncp-web/elements.php | 2 ++ 2 files changed, 7 insertions(+) diff --git a/etc/library.sh b/etc/library.sh index d9a174f4a..fbe8afb2c 100644 --- a/etc/library.sh +++ b/etc/library.sh @@ -73,8 +73,13 @@ function configure_app() $DIALOG_OK) while read val; do local ret_vals+=("$val"); done <<<"$value" + local allow_unsafe + for (( i = 0 ; i < len ; i++ )); do # check for invalid characters + # check if unsafe characters (spaces) are allowed (will return 'null' if key not found) + allow_unsafe="$(jq -r .params[$i].allow_unsafe <<<"$cfg")" + [[ "${allow_unsafe}" == 'true' ]] && ret_vals[$i]="${ret_vals[$i]// /%SPACE%}" grep -q '[\\&#;'"'"'`|*?~<>^"()[{}$&[:space:]]' <<< "${ret_vals[$i]}" && { echo "Invalid characters in field ${vars[$i]}"; return 1; } cfg="$(jq ".params[$i].value = \"${ret_vals[$i]}\"" <<<"$cfg")" diff --git a/ncp-web/elements.php b/ncp-web/elements.php index 8d67fc17e..67633d11c 100644 --- a/ncp-web/elements.php +++ b/ncp-web/elements.php @@ -24,6 +24,8 @@ function print_config_form( $ncp_app, $cfg, $l ) $ret .= ""; $value = $param['value']; + if (array_key_exists('allow_unsafe', $param) && $param['allow_unsafe'] == "true") + $value = str_replace("%SPACE%", " ", $value); if ( $value == '_') $value = ''; From 508397830283bb57fc830c61287dc652cca365fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 11 Jan 2020 01:00:05 +0100 Subject: [PATCH 23/24] multi-factor-authentication.sh: Remove debug output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 783dceda6..49be6fa11 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -206,8 +206,6 @@ configure() { "$(unescape "$SSH_PUBLIC_KEY_3")" \ "$(unescape "$SSH_PUBLIC_KEY_4")" \ "$(unescape "$SSH_PUBLIC_KEY_5")") - echo "SSH PUBKEYS:" - echo "${ssh_pubkeys[*]}" trap 'restore' HUP INT QUIT PIPE TERM From c482983a8511e9742c74ca2dfbf6c617c558abcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kn=C3=B6ppler?= <6317548+theCalcaholic@users.noreply.github.com> Date: Sat, 11 Jan 2020 01:00:47 +0100 Subject: [PATCH 24/24] multi-factor-authentication.sh: Fix typo in variable name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com> --- bin/ncp/SECURITY/multi-factor-authentication.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ncp/SECURITY/multi-factor-authentication.sh b/bin/ncp/SECURITY/multi-factor-authentication.sh index 49be6fa11..2c8c754f2 100755 --- a/bin/ncp/SECURITY/multi-factor-authentication.sh +++ b/bin/ncp/SECURITY/multi-factor-authentication.sh @@ -194,7 +194,7 @@ is_active() { configure() { - local active enable_totp_and_pw enable_pubkey_and_pw enable_pubkey_only enable_pw_only reset_totp_secret ssh_pubkey + local active enable_totp_and_pw enable_pubkey_and_pw enable_pubkey_only enable_pw_only reset_totp_secret ssh_pubkeys enable_totp_and_pw="$ENABLE_TOTP_AND_PASSWORD" enable_pubkey_and_pw="$ENABLE_PUBLIC_KEY_AND_PASSWORD" enable_pubkey_only="$ENABLE_PUBLIC_KEY_ONLY"