#!/usr/bin/env bash
# security/ssh -- harden sshd, with a tested config and a backup
#
# Changing the SSH port without opening it in the firewall is the classic way to
# lock yourself out, so the port change is refused unless the port is allowed.
set -o pipefail
SELF=$(readlink -f "${BASH_SOURCE[0]}")
NV_BASE=$(cd "$(dirname "$SELF")/../../.." && pwd)
export NV_BASE
# shellcheck source=/dev/null
. "$NV_BASE/lib/core/bootstrap.sh"

nv_require_root || exit 1
ui_header "$(t sec_m_ssh)"

cfg=/etc/ssh/sshd_config
val() { sed -n "s/^[[:space:]]*$1[[:space:]]\+//p" "$cfg" 2>/dev/null | tail -n 1; }

cur_root=$(val PermitRootLogin);  cur_root=${cur_root:-prohibit-password}
cur_pass=$(val PasswordAuthentication); cur_pass=${cur_pass:-yes}
cur_port=$(val Port); cur_port=${cur_port:-22}

ui_kv "PermitRootLogin" "$cur_root"
ui_kv "PasswordAuthentication" "$cur_pass"
ui_kv "Port" "$cur_port"
ui_blank
ui_info "1) $(t ssh_no_password)"
ui_info "2) $(t ssh_no_root)"
ui_info "3) $(t ssh_change_port)"
ui_info "0) $(t menu_back)"
ui_blank
printf '  %s: ' "$(t menu_prompt_short)"
read -r pick || exit 130

set_kv() {  # set_kv KEY VALUE
    local k=$1 v=$2
    if grep -qE "^[[:space:]]*${k}[[:space:]]" "$cfg"; then
        sed -i -E "s|^[[:space:]]*${k}[[:space:]]+.*|$k $v|" "$cfg"
    else
        printf '\n%s %s\n' "$k" "$v" >>"$cfg"
    fi
}

case $pick in
    0) exit 0 ;;
    1)
        ui_warn "$(t ssh_password_warn)"
        ui_confirm "$(t ssh_password_q)" n || exit 0
        nv_backup_path "$cfg" ssh >/dev/null 2>&1 || true
        set_kv PasswordAuthentication no
        msg="$(t ssh_password_done)"
        ;;
    2)
        ui_confirm "$(t ssh_root_q)" n || exit 0
        nv_backup_path "$cfg" ssh >/dev/null 2>&1 || true
        set_kv PermitRootLogin prohibit-password
        msg="$(t ssh_root_done)"
        ;;
    3)
        printf '  %s [%s]: ' "$(t ssh_port_prompt)" "$cur_port"
        read -r port || exit 130
        port=$(nv_trim "$port"); [ -z "$port" ] && exit 0
        nv_valid_port "$port" || { ui_err "$(t fw_bad_port)"; exit 2; }
        ui_warn "$(t ssh_port_warn "$port")"
        ui_confirm "$(t ssh_port_q "$port")" n || exit 0
        fw_allow "$port" tcp
        nv_backup_path "$cfg" ssh >/dev/null 2>&1 || true
        set_kv Port "$port"
        msg="$(t ssh_port_done "$port")"
        ;;
    *) ui_err "$(t menu_invalid)"; exit 2 ;;
esac

if sshd -t 2>/dev/null; then
    svc_reload ssh 2>/dev/null || svc_restart ssh 2>/dev/null || true
    nv_trace ssh "option=$pick"
    ui_ok "$msg"
    ui_info "$(t ssh_test_note)"
else
    ui_err "$(t ssh_bad_config)"
    nv_backup_restore "$cfg" >/dev/null 2>&1 || true
    ui_warn "$(t phpini_restored)"
    exit 1
fi
exit 0
