1 contributor
288 lines | 7.473kb
#!/usr/bin/env bash
set -euo pipefail

real_ssh="/usr/bin/ssh"
ssh_config="$HOME/.ssh/config"
remote_agent="/run/user/0/gnupg/S.gpg-agent.ssh"

# Access model, May 2026
# ----------------------
#
# Cheia fizica este montata pe is-jumper. Wrapper-ul local nu mai face bridge
# de agent in /tmp; in schimb ruleaza clientul SSH activ pe is-jumper:
#
#     local ssh wrapper
#       -> is-jumper (192.168.2.100, acces local cu id_ed25519)
#       -> J1/J2/j1/j2 (autentificare cu agentul fizic de pe is-jumper)
#       -> ssh final-host
#
# Custom jump flags (stripped by wrapper, not passed to real ssh):
#   -J1  use J1 via VPN (default for configured hosts)
#   -J2  use J2 via VPN
#   -j1  use j1 via public DNS (urgente, fara ruta VPN)
#   -j2  use j2 via public DNS (urgente, fara ruta VPN)
#
# Hosturi arbitrare (fara config SSH): wrapper-ul le ruteza prin jump doar daca
# unul dintre flagurile de mai sus este prezent explicit.

target_user=""
target_host=""
target_port=""
target_auth=""
found_target=0
cmd_args=()
ssh_config_args=()
jump_alias="j1"
custom_jump_set=0
host_configured=1
target_is_jump=0
want_subsystem=0
user_option=""
port_option=""

has_explicit_config() {
    local arg

    for arg in "$@"; do
        case "$arg" in
            -F|-F*)
                return 0
                ;;
        esac
    done

    return 1
}

quote_cmd() {
    local out="" q part

    for part in "$@"; do
        printf -v q "%q" "$part"
        out+="$q "
    done

    printf "%s" "$out"
}

resolve_ssh_config() {
    local target=$1
    local line

    target_user=""
    target_host=""
    target_port=""
    target_auth=""

    while IFS= read -r line; do
        case "$line" in
            user\ *)     target_user=${line#user } ;;
            hostname\ *) target_host=${line#hostname } ;;
            port\ *)     target_port=${line#port } ;;
            setenv\ *NG_SSH_AUTH=password-interactive*) target_auth="password_interactive" ;;
        esac
    done < <("$real_ssh" ${ssh_config_args[@]+"${ssh_config_args[@]}"} -G "$target" 2>/dev/null)

    [[ -n "$target_user" && -n "$target_host" && -n "$target_port" ]]
}

run_real_ssh() {
    exec "$real_ssh" ${ssh_config_args[@]+"${ssh_config_args[@]}"} "$@"
}

resolve_target_from_config() {
    local target=$1
    local default_user=${USER:-${LOGNAME:-}}
    local user_override=""

    case "$target" in
        *@*)
            user_override=${target%@*}
            target=${target#*@}
            ;;
    esac

    case "$target" in
        is-jumper|192.168.2.100)
            return 1
            ;;
        J1|J2|j1|j2)
            target_is_jump=1
            ;;
    esac

    resolve_ssh_config "$target" || return 1

    if [[ -n "$user_override" ]]; then
        target_user=$user_override
    fi
    if [[ -n "$user_option" ]]; then
        target_user=$user_option
    fi
    if [[ -n "$port_option" ]]; then
        target_port=$port_option
    fi

    # Unconfigured host (ssh -G returns defaults): bypass unless a custom jump
    # was requested explicitly.
    if [[ "$target_is_jump" -eq 0 && "$target_host" == "$target" && "$target_port" == "22" && "$target_user" == "$default_user" ]]; then
        [[ $custom_jump_set -eq 0 ]] && return 1
        host_configured=0
    fi

    [[ -n "$target_user" && -n "$target_host" && -n "$target_port" ]]
}

resolve_jump() {
    local saved_user saved_host saved_port saved_auth

    saved_user=$target_user
    saved_host=$target_host
    saved_port=$target_port
    saved_auth=$target_auth

    resolve_ssh_config "$jump_alias" || {
        printf "ssh-wrapper: cannot resolve jump alias %s\n" "$jump_alias" >&2
        exit 255
    }

    jump_user=$target_user
    jump_host=$target_host
    jump_port=$target_port

    target_user=$saved_user
    target_host=$saved_host
    target_port=$saved_port
    target_auth=$saved_auth
}

# Pre-process: extract custom jump flags and strip them from args.
filtered_args=()
for arg in "$@"; do
    case "$arg" in
        -J1) jump_alias="j1"; custom_jump_set=1 ;;
        -J2) jump_alias="j2"; custom_jump_set=1 ;;
        -j1) jump_alias="j1"; custom_jump_set=1 ;;
        -j2) jump_alias="j2"; custom_jump_set=1 ;;
        *) filtered_args+=("$arg") ;;
    esac
done
set -- "${filtered_args[@]+"${filtered_args[@]}"}"

if [[ -f "$ssh_config" ]] && ! has_explicit_config "$@"; then
    ssh_config_args=(-F "$ssh_config")
fi

skip_next=0
capture_user=0
capture_port=0
after_double_dash=0

for arg in "$@"; do
    if [[ $found_target -eq 1 ]]; then
        cmd_args+=("$arg")
        continue
    fi

    if [[ $capture_user -eq 1 ]]; then
        user_option=$arg
        capture_user=0
        continue
    fi

    if [[ $capture_port -eq 1 ]]; then
        port_option=$arg
        capture_port=0
        continue
    fi

    if [[ $skip_next -eq 1 ]]; then
        skip_next=0
        continue
    fi

    case "$arg" in
        -G|-Q|-V|-h|--help)
            run_real_ssh "$@"
            ;;
        --)
            after_double_dash=1
            continue
            ;;
    esac

    if [[ $after_double_dash -eq 0 ]]; then
        case "$arg" in
            -s)
                want_subsystem=1
                continue
                ;;
            -l)
                capture_user=1
                continue
                ;;
            -l*)
                user_option=${arg#-l}
                continue
                ;;
            -p)
                capture_port=1
                continue
                ;;
            -p*)
                port_option=${arg#-p}
                continue
                ;;
            -b|-c|-D|-E|-e|-F|-I|-i|-J|-L|-m|-O|-o|-Q|-R|-S|-W|-w)
                skip_next=1
                continue
                ;;
            -b*|-c*|-D*|-E*|-e*|-F*|-I*|-i*|-J*|-L*|-m*|-O*|-o*|-Q*|-R*|-S*|-W*|-w*)
                continue
                ;;
            -*)
                continue
                ;;
        esac
    fi

    if ! resolve_target_from_config "$arg"; then
        run_real_ssh "$@"
    fi

    found_target=1
done

if [[ $found_target -eq 0 ]]; then
    run_real_ssh "$@"
fi

tty_flag="-tt"
if [[ ${#cmd_args[@]} -gt 0 || $want_subsystem -eq 1 ]]; then
    tty_flag="-T"
fi

if [[ $target_is_jump -eq 1 ]]; then
    jump_cmd=(ssh "$tty_flag" -A -o BatchMode=yes -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -p "$target_port" "$target_user@$target_host")
    jump_cmd+=(${cmd_args[@]+"${cmd_args[@]}"})
else
    resolve_jump

    final_cmd=(ssh "$tty_flag" -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -o ProxyJump=none -o ProxyCommand=none)
    if [[ "$target_auth" == "password_interactive" ]]; then
        final_cmd+=( -o BatchMode=no -o PreferredAuthentications=keyboard-interactive,password -o PubkeyAuthentication=no )
    elif [[ $host_configured -eq 1 ]]; then
        final_cmd+=( -o BatchMode=yes )
    fi
    if [[ $want_subsystem -eq 1 ]]; then
        final_cmd+=( -s )
    fi
    final_cmd+=( -p "$target_port" "$target_user@$target_host" )
    final_cmd+=(${cmd_args[@]+"${cmd_args[@]}"})

    jump_cmd=(ssh "$tty_flag" -A -o BatchMode=yes -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -p "$jump_port" "$jump_user@$jump_host" "$(quote_cmd "${final_cmd[@]}")")
fi

is_jumper_cmd="SSH_AUTH_SOCK=$remote_agent exec $(quote_cmd "${jump_cmd[@]}")"

exec "$real_ssh" ${ssh_config_args[@]+"${ssh_config_args[@]}"} "$tty_flag" -o BatchMode=yes -o ConnectTimeout=10 is-jumper "$is_jumper_cmd"