201 lines
4.9 KiB
Bash
Executable File
201 lines
4.9 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
KEY_DIR="${MAIL_LOGIN_KEY_DIR:-/usr/local/hitme_plugins/mxautologin/secrets}"
|
|
KEY_NAME="${MAIL_LOGIN_KEY_NAME:-mx1_ed25519}"
|
|
KEY_PATH="$KEY_DIR/$KEY_NAME"
|
|
MX_MODE="${MX_LOGIN_MODE:-1}"
|
|
SETTINGS_FILE="${MAIL_LOGIN_SETTINGS_FILE:-/usr/local/directadmin/plugins/mxautologin/plugin-settings.conf}"
|
|
HELPER_COMMAND="${MAIL_LOGIN_HELPER_COMMAND:-/usr/local/hitme_plugins/mail-login-helper/bin/create-login-url}"
|
|
|
|
config_value() {
|
|
key="$1"
|
|
if [ ! -f "$SETTINGS_FILE" ]; then
|
|
return 0
|
|
fi
|
|
awk -F= -v key="$key" '
|
|
$1 == key {
|
|
value = substr($0, index($0, "=") + 1)
|
|
gsub(/^[ \t]+|[ \t]+$/, "", value)
|
|
print value
|
|
exit
|
|
}
|
|
' "$SETTINGS_FILE"
|
|
}
|
|
|
|
derive_servername() {
|
|
if [ -n "${SERVERNAME:-}" ]; then
|
|
printf '%s' "$SERVERNAME"
|
|
return
|
|
fi
|
|
host="$(hostname -f 2>/dev/null || hostname 2>/dev/null || printf 'source')"
|
|
printf '%s' "$host" | awk -F. '{print $1}'
|
|
}
|
|
|
|
clean_label() {
|
|
printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g; s/^-*//; s/-*$//'
|
|
}
|
|
|
|
detect_source_ip() {
|
|
if [ -n "${SOURCE_IP:-}" ]; then
|
|
printf '%s' "$SOURCE_IP"
|
|
return
|
|
fi
|
|
|
|
if command -v ip >/dev/null 2>&1; then
|
|
detected="$(ip route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}')"
|
|
if [ -n "$detected" ]; then
|
|
printf '%s' "$detected"
|
|
return
|
|
fi
|
|
fi
|
|
|
|
if command -v hostname >/dev/null 2>&1; then
|
|
detected="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
|
if [ -n "$detected" ]; then
|
|
printf '%s' "$detected"
|
|
return
|
|
fi
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
pin_mx_host_key() {
|
|
if [ -z "$MX_HOST" ]; then
|
|
HOST_KEY_STATUS="skipped: MAIL_LOGIN_SSH_HOST is not configured"
|
|
return
|
|
fi
|
|
if ! command -v ssh-keyscan >/dev/null 2>&1; then
|
|
HOST_KEY_STATUS="skipped: ssh-keyscan is not available"
|
|
return
|
|
fi
|
|
|
|
known_dir="$(dirname "$KNOWN_HOSTS")"
|
|
mkdir -p "$known_dir"
|
|
chmod 700 "$known_dir"
|
|
touch "$KNOWN_HOSTS"
|
|
chmod 600 "$KNOWN_HOSTS"
|
|
|
|
lookup="$MX_HOST"
|
|
if [ "$MX_PORT" != "22" ]; then
|
|
lookup="[$MX_HOST]:$MX_PORT"
|
|
fi
|
|
if ssh-keygen -F "$lookup" -f "$KNOWN_HOSTS" >/dev/null 2>&1; then
|
|
HOST_KEY_STATUS="already present for $lookup"
|
|
return
|
|
fi
|
|
|
|
tmp="$KNOWN_HOSTS.$$"
|
|
if ssh-keyscan -T "$SCAN_TIMEOUT" -p "$MX_PORT" -t ed25519 "$MX_HOST" > "$tmp" 2>/dev/null && [ -s "$tmp" ]; then
|
|
cat "$tmp" >> "$KNOWN_HOSTS"
|
|
chmod 600 "$KNOWN_HOSTS"
|
|
HOST_KEY_FINGERPRINT="$(ssh-keygen -lf "$tmp" 2>/dev/null | head -n 1 || true)"
|
|
HOST_KEY_STATUS="pinned $lookup"
|
|
rm -f "$tmp"
|
|
return
|
|
fi
|
|
|
|
rm -f "$tmp"
|
|
HOST_KEY_STATUS="failed: cannot fetch ED25519 host key for $MX_HOST:$MX_PORT"
|
|
}
|
|
|
|
SERVER_LABEL="$(clean_label "$(derive_servername)")"
|
|
if [ -z "$SERVER_LABEL" ]; then
|
|
echo "Cannot determine SERVERNAME" >&2
|
|
exit 1
|
|
fi
|
|
|
|
CONFIG_SSH_HOST="$(config_value MAIL_LOGIN_SSH_HOST || true)"
|
|
CONFIG_SSH_PORT="$(config_value MAIL_LOGIN_SSH_PORT || true)"
|
|
CONFIG_KNOWN_HOSTS="$(config_value MAIL_LOGIN_SSH_KNOWN_HOSTS || true)"
|
|
CONFIG_SCAN_TIMEOUT="$(config_value MAIL_LOGIN_CONNECT_TIMEOUT_SECONDS || true)"
|
|
|
|
MX_HOST="${MAIL_LOGIN_SSH_HOST:-$CONFIG_SSH_HOST}"
|
|
MX_PORT="${MAIL_LOGIN_SSH_PORT:-$CONFIG_SSH_PORT}"
|
|
MX_PORT="${MX_PORT:-22}"
|
|
KNOWN_HOSTS="${MAIL_LOGIN_SSH_KNOWN_HOSTS:-$CONFIG_KNOWN_HOSTS}"
|
|
KNOWN_HOSTS="${KNOWN_HOSTS:-$KEY_DIR/known_hosts}"
|
|
SCAN_TIMEOUT="${MAIL_LOGIN_CONNECT_TIMEOUT_SECONDS:-$CONFIG_SCAN_TIMEOUT}"
|
|
SCAN_TIMEOUT="${SCAN_TIMEOUT:-5}"
|
|
|
|
case "$MX_MODE" in
|
|
1|2) ;;
|
|
*)
|
|
echo "MX_LOGIN_MODE must be 1 or 2" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "$MX_PORT" in
|
|
*[!0-9]*|'')
|
|
echo "MAIL_LOGIN_SSH_PORT must be numeric" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "$SCAN_TIMEOUT" in
|
|
*[!0-9]*|'')
|
|
echo "MAIL_LOGIN_CONNECT_TIMEOUT_SECONDS must be numeric" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
SOURCE_IP="$(detect_source_ip || true)"
|
|
case "$SOURCE_IP" in
|
|
*[!A-Za-z0-9:./_-]*|'')
|
|
echo "Cannot determine SOURCE_IP automatically. Set SOURCE_IP explicitly." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
mkdir -p "$KEY_DIR"
|
|
chmod 700 "$KEY_DIR"
|
|
|
|
if [ ! -f "$KEY_PATH" ]; then
|
|
umask 077
|
|
ssh-keygen -q -t ed25519 -a 100 -N "" -f "$KEY_PATH" -C "KLUCZ PLUGINU MX-Autologin DLA SERWERA $SERVER_LABEL"
|
|
fi
|
|
|
|
if [ ! -f "$KEY_PATH.pub" ]; then
|
|
ssh-keygen -y -f "$KEY_PATH" > "$KEY_PATH.pub"
|
|
fi
|
|
|
|
chmod 600 "$KEY_PATH"
|
|
chmod 644 "$KEY_PATH.pub"
|
|
|
|
HOST_KEY_STATUS=""
|
|
HOST_KEY_FINGERPRINT=""
|
|
pin_mx_host_key
|
|
|
|
PUB_KEY="$(cat "$KEY_PATH.pub")"
|
|
BASE_OPTIONS="from=\"$SOURCE_IP\",restrict,no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty"
|
|
|
|
if [ "$MX_MODE" = "2" ]; then
|
|
AUTH_OPTIONS="$BASE_OPTIONS,command=\"$HELPER_COMMAND\""
|
|
else
|
|
AUTH_OPTIONS="$BASE_OPTIONS"
|
|
fi
|
|
|
|
COMMENT="KLUCZ PLUGINU MX-Autologin DLA SERWERA $SERVER_LABEL"
|
|
|
|
cat <<EOF
|
|
Private key:
|
|
$KEY_PATH
|
|
|
|
Public key:
|
|
$KEY_PATH.pub
|
|
|
|
Set this in plugin-settings.conf:
|
|
MAIL_LOGIN_SSH_IDENTITY=$KEY_PATH
|
|
MAIL_LOGIN_SSH_KNOWN_HOSTS=$KNOWN_HOSTS
|
|
|
|
MX known_hosts:
|
|
$KNOWN_HOSTS
|
|
Pinned MX host key: $HOST_KEY_STATUS
|
|
${HOST_KEY_FINGERPRINT}
|
|
|
|
Add this line to /root/.ssh/authorized_keys on mx1:
|
|
$AUTH_OPTIONS $PUB_KEY $COMMENT
|
|
EOF
|