From 4a7c5330a93d91bd28cd94286ee4d150b026ad55 Mon Sep 17 00:00:00 2001 From: ergosteur <1992147+ergosteur@users.noreply.github.com> Date: Wed, 19 Nov 2025 02:26:37 -0500 Subject: [PATCH] Add Linux version of SSH link protocol handler script This script handles SSH links, allowing installation, uninstallation, and debugging of the SSH protocol handler on Linux systems. It includes user notifications and checks for proper configuration. --- ssh-handler.sh | 299 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 ssh-handler.sh diff --git a/ssh-handler.sh b/ssh-handler.sh new file mode 100644 index 0000000..9e79964 --- /dev/null +++ b/ssh-handler.sh @@ -0,0 +1,299 @@ +#!/bin/bash +# ============================================================================ +# == Simple SSH Link Protocol Handler for Linux == +# == Uses XDG standards and works with most desktop environments. == +# == == +# == To install, run this script with sudo: == +# == chmod +x ./ssh-handler.sh == +# == sudo ./ssh-handler.sh --install == +# == == +# == To uninstall: == +# == sudo ./ssh-handler.sh --uninstall == +# == == +# == To debug configuration: == +# == ./ssh-handler.sh --debug == +# == == +# == Public Domain. https://tcpip.wtf == +# ============================================================================ + +# --- SCRIPT MODE DETECTION --- +if [ "$1" == "--install" ]; then + MODE="SETUP" +elif [ "$1" == "--uninstall" ]; then + MODE="UNINSTALL" +elif [ "$1" == "--debug" ]; then + MODE="DEBUG" +elif [[ "$1" == ssh://* ]]; then + MODE="HANDLER" +else + echo "Usage:" + echo " To install: $0 --install" + echo " To uninstall: $0 --uninstall" + echo " To debug: $0 --debug" + echo " (This script is usually called by your desktop environment to handle a URL.)" + exit 1 +fi + +# A function to display errors both on stderr and via desktop notifications. +show_error() { + local message="$1" + # Print to standard error + echo "ERROR: $message" >&2 + # Send a desktop notification if possible + if command -v notify-send &> /dev/null; then + notify-send --icon=dialog-error "SSH Handler Error" "$message" + fi +} + +# A function to display informational messages both on stdout and via notifications. +show_info() { + local message="$1" + # Print to standard output + echo "$message" + # Send a desktop notification if possible + if command -v notify-send &> /dev/null; then + notify-send --icon=info "SSH Handler" "$message" + fi +} + +# ============================================================================ +# == DEBUG MODE == +# ============================================================================ +if [ "$MODE" == "DEBUG" ]; then + echo + echo "[ DEBUG MODE ]" + echo "Checking system configuration for ssh:// URL handling..." + echo "--------------------------------------------------------" + + # 1. Check what the system thinks is the default handler + echo "[1] Querying XDG for the default ssh:// handler..." + DEFAULT_HANDLER=$(xdg-mime query default x-scheme-handler/ssh) + if [ -n "$DEFAULT_HANDLER" ]; then + echo " -> Default handler is: $DEFAULT_HANDLER" + if [ "$DEFAULT_HANDLER" != "ssh-handler.desktop" ]; then + echo " [!] WARNING: The default handler is not our script. Another application has taken precedence." + echo " You may need to set the default handler manually in your desktop environment's settings," + echo " or re-run 'sudo ./ssh-handler.sh --install' to try and set it again." + else + echo " [+] CORRECT: The default handler is correctly set to our script." + fi + else + echo " [!] ERROR: No default handler is configured for ssh:// links on your system." + echo " Please run 'sudo ./ssh-handler.sh --install'." + fi + + # 2. Check if the desktop file exists and is correct + echo + echo "[2] Checking the .desktop file..." + DESKTOP_FILE_PATH="/usr/share/applications/ssh-handler.desktop" + if [ -f "$DESKTOP_FILE_PATH" ]; then + echo " [+] FOUND: $DESKTOP_FILE_PATH" + EXEC_LINE=$(grep "^Exec=" "$DESKTOP_FILE_PATH") + echo " -> Exec line is: $EXEC_LINE" + if [[ "$EXEC_LINE" != "Exec=/usr/local/bin/ssh-handler %u" ]]; then + echo " [!] WARNING: The Exec line seems incorrect. It should be 'Exec=/usr/local/bin/ssh-handler %u'." + fi + else + echo " [!] ERROR: The desktop file does not exist. The script is not installed correctly." + fi + + # 3. Check if the script itself is installed + echo + echo "[3] Checking if the handler script is installed..." + INSTALL_PATH="/usr/local/bin/ssh-handler" + if [ -x "$INSTALL_PATH" ]; then + echo " [+] FOUND and executable: $INSTALL_PATH" + else + echo " [!] ERROR: The script is not found or is not executable at $INSTALL_PATH." + fi + echo "--------------------------------------------------------" + echo "Debug finished." + echo + exit 0 +fi + +# ============================================================================ +# == SETUP / UNINSTALL MODE == +# ============================================================================ +if [ "$MODE" == "SETUP" ] || [ "$MODE" == "UNINSTALL" ]; then + + # --- 1. SCRIPT AND DESKTOP FILE CONFIGURATION --- + INSTALL_PATH="/usr/local/bin/ssh-handler" + DESKTOP_FILE_NAME="ssh-handler.desktop" + DESKTOP_FILE_PATH="/usr/share/applications/$DESKTOP_FILE_NAME" + + # --- 2. CHECK FOR ROOT PRIVILEGES --- + if [ "$(id -u)" -ne 0 ]; then + show_error "This operation requires root privileges. Please run with 'sudo'." + exit 1 + fi + echo "[+] Root privileges confirmed." + + + # --- 3. UNINSTALL LOGIC --- + if [ "$MODE" == "UNINSTALL" ]; then + echo + show_info "Uninstalling SSH protocol handler..." + + if [ -f "$INSTALL_PATH" ]; then + echo "[-] Removing script: $INSTALL_PATH" + rm -f "$INSTALL_PATH" + else + echo "[!] Script not found at $INSTALL_PATH (already removed?)." + fi + + if [ -f "$DESKTOP_FILE_PATH" ]; then + echo "[-] Removing .desktop file: $DESKTOP_FILE_PATH" + rm -f "$DESKTOP_FILE_PATH" + update-desktop-database /usr/share/applications + else + echo "[!] Desktop file not found at $DESKTOP_FILE_PATH (already removed?)." + fi + + show_info "Uninstallation complete." + exit 0 + fi + + # --- 4. SETUP LOGIC --- + echo + show_info "Installing SSH protocol handler..." + + echo "[+] Installing script to $INSTALL_PATH..." + cp "$0" "$INSTALL_PATH" + chmod +x "$INSTALL_PATH" + + echo "[+] Creating .desktop file at $DESKTOP_FILE_PATH..." + cat > "$DESKTOP_FILE_PATH" << EOF +[Desktop Entry] +Name=SSH Protocol Handler +Comment=Handles ssh:// links via the system's default terminal +Exec=$INSTALL_PATH %u +Icon=utilities-terminal +Terminal=false +Type=Application +MimeType=x-scheme-handler/ssh; +Categories=Network; +EOF + + echo "[+] Registering the new handler with the system..." + xdg-mime default "$DESKTOP_FILE_NAME" x-scheme-handler/ssh + update-desktop-database /usr/share/applications + + echo + show_info "SUCCESS: Your system is now configured to open ssh:// links." + echo + exit 0 +fi + +# ============================================================================ +# == HANDLER MODE == +# ============================================================================ +if [ "$MODE" == "HANDLER" ]; then + # --- 1. PARSE THE URL --- + FULL_URL="$1" + TARGET="${FULL_URL#ssh://}" + if [ "${TARGET: -1}" == "/" ]; then + TARGET="${TARGET::-1}" + fi + + if [[ "$TARGET" =~ "@" ]]; then + SshUser="${TARGET%@*}" + SshHost="${TARGET#*@}" + else + SshUser="$USER" + SshHost="$TARGET" + fi + + # Show initial notification that the link was received + show_info "Received SSH link for ${SshUser}@${SshHost}..." + + # --- 2. DETERMINE DIALOG TOOL --- + DIALOG_TOOL="read" + if command -v zenity &> /dev/null; then + DIALOG_TOOL="zenity" + fi + + # --- 3. INTERACTIVE PROMPTS --- + LegacyOpts="" + USER_CANCELLED=false + + if [ "$DIALOG_TOOL" == "zenity" ]; then + NewUser=$(zenity --entry --title="SSH Connection" --text="Connecting to Host: $SshHost\nEnter username:" --entry-text="$SshUser" --ok-label="Next") + if [ $? -ne 0 ]; then + USER_CANCELLED=true + else + if [ -n "$NewUser" ]; then SshUser="$NewUser"; fi + zenity --question --title="Legacy Mode" --text="Enable legacy mode for old devices?\n(This uses insecure algorithms)" --ok-label="Yes, Enable" --cancel-label="No" + if [ $? -eq 0 ]; then + LegacyOpts="-o KexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o HostKeyAlgorithms=+ssh-rsa -o MACs=+hmac-sha1,hmac-sha1-96 -o ciphers=+aes256-cbc" + fi + fi + else + TUI_SCRIPT=$(printf 'SshUser="%s"; SshHost="%s"; clear; echo; echo " Host: $SshHost"; echo " User: $SshUser"; echo; read -p "Change username? (y/N): " choice; choice=${choice,,}; if [[ "$choice" == "y" || "$choice" == "yes" ]]; then read -p "Enter new username: " NewUser; if [ -n "$NewUser" ]; then SshUser="$NewUser"; fi; fi; echo; read -p "Enable legacy mode? (y/N): " legacy_choice; legacy_choice=${legacy_choice,,}; if [[ "$legacy_choice" == "y" || "$legacy_choice" == "yes" ]]; then LegacyOpts="-o KexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o HostKeyAlgorithms=+ssh-rsa -o MACs=+hmac-sha1,hmac-sha1-96"; fi; FINAL_TARGET="$SshUser@$SshHost"; echo; echo "Connecting to: $FINAL_TARGET"; echo "-------------------------------------------"; SSH_ARGS_TUI=(-A -C); if [ -n "$LegacyOpts" ]; then read -ra LEGACY_ARRAY_TUI <<< "$LegacyOpts"; SSH_ARGS_TUI+=("${LEGACY_ARRAY_TUI[@]}"); fi; SSH_ARGS_TUI+=("$FINAL_TARGET"); exec ssh "${SSH_ARGS_TUI[@]}"' "$SshUser" "$SshHost") + + # Find and use a terminal emulator + TERMINAL_CMD=() + TERMINAL_NAME="" + if command -v x-terminal-emulator &> /dev/null && [ -x "$(realpath /usr/bin/x-terminal-emulator 2>/dev/null)" ]; then + TERMINAL_NAME="x-terminal-emulator" + TERMINAL_CMD=(x-terminal-emulator -T "SSH to $SshHost" -e "bash -c '$TUI_SCRIPT'") + elif command -v gnome-terminal &> /dev/null; then + TERMINAL_NAME="gnome-terminal" + TERMINAL_CMD=(gnome-terminal --title "SSH to $SshHost" -- bash -c "$TUI_SCRIPT") + elif command -v xfce4-terminal &> /dev/null; then + TERMINAL_NAME="xfce4-terminal" + TERMINAL_CMD=(xfce4-terminal -T "SSH to $SshHost" -e "bash -c '$TUI_SCRIPT'") + fi + + if [ -n "$TERMINAL_NAME" ]; then + show_info "Launching terminal ($TERMINAL_NAME) for interactive prompt..." + "${TERMINAL_CMD[@]}" & + else + show_error "Could not find a known terminal emulator to run interactive prompts." + exit 1 + fi + exit 0 + fi + + if $USER_CANCELLED; then + show_info "SSH connection cancelled by user." + exit 0 + fi + + # --- 4. BUILD AND LAUNCH --- + FINAL_TARGET="$SshUser@$SshHost" + SSH_ARGS=(-A -C) + if [ -n "$LegacyOpts" ]; then + read -ra LEGACY_ARRAY <<< "$LegacyOpts" + SSH_ARGS+=("${LEGACY_ARRAY[@]}") + fi + SSH_ARGS+=("$FINAL_TARGET") + + # Find and use a terminal emulator to launch the final ssh command + LAUNCH_CMD=() + TERMINAL_NAME="" + if command -v x-terminal-emulator &> /dev/null && [ -x "$(realpath /usr/bin/x-terminal-emulator 2>/dev/null)" ]; then + TERMINAL_NAME="x-terminal-emulator" + LAUNCH_CMD=(x-terminal-emulator -T "SSH to $FINAL_TARGET" -e "ssh ${SSH_ARGS[*]}") + elif command -v gnome-terminal &> /dev/null; then + TERMINAL_NAME="gnome-terminal" + LAUNCH_CMD=(gnome-terminal --title "SSH to $FINAL_TARGET" -- ssh "${SSH_ARGS[@]}") + elif command -v xfce4-terminal &> /dev/null; then + TERMINAL_NAME="xfce4-terminal" + LAUNCH_CMD=(xfce4-terminal --title "SSH to $FINAL_TARGET" -x ssh "${SSH_ARGS[@]}") + elif command -v xterm &> /dev/null; then + TERMINAL_NAME="xterm" + LAUNCH_CMD=(xterm -T "SSH to $FINAL_TARGET" -e "ssh ${SSH_ARGS[*]}") + fi + + if [ -n "$TERMINAL_NAME" ]; then + show_info "Connecting to $SshHost via $TERMINAL_NAME..." + "${LAUNCH_CMD[@]}" & + else + show_error "Could not find a known terminal emulator to launch the SSH session." + exit 1 + fi + + exit 0 +fi +