Compare commits

..

7 Commits

Author SHA1 Message Date
ergosteur
eab8873c14 Refactor GitHub Actions build workflow
Reorganize build steps for .NET project and add cleaning step.
2026-03-16 13:01:47 -04:00
ergosteur
1ead5e6d25 Configure Git line endings and enhance script checks
Added a step to configure Git line endings and improved the shell script to check for file existence before processing.
2026-03-16 12:54:47 -04:00
ergosteur
f1b35deb4e Update GitHub Actions workflow for .NET builds
add both stanadalone and .net builds, versioned filenames
2026-03-16 12:52:11 -04:00
ergosteur
478328896c Update GitHub Actions workflow for build and release
add shell script and batch file to release artifacts
2026-03-16 12:47:44 -04:00
ergosteur
cf7ead5f56 Modify build workflow for tagging and release
Updated workflow to trigger on version tags and added permissions for release creation.
2026-03-16 12:38:53 -04:00
ergosteur
4a7c5330a9 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.
2025-11-19 02:26:37 -05:00
ergosteur
17c6eefddf Add AES-256-CBC cipher option for legacy mode 2025-11-19 02:25:27 -05:00
3 changed files with 369 additions and 16 deletions

View File

@@ -1,35 +1,89 @@
# .github/workflows/build.yml
name: Build Windows Executable
name: Build and Release
on:
push:
branches: [ "main" ] # Runs whenever you push to the main branch
workflow_dispatch: # Allows you to run this workflow manually from the Actions tab
tags:
- 'v*'
workflow_dispatch:
jobs:
build:
runs-on: windows-latest # Use a Windows runner for the build
runs-on: windows-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Configure Git Line Endings
run: git config --global core.autocrlf input
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x # Use a recent .NET version
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build and publish self-contained executable
run: > # This command builds a single .exe with the runtime included
dotnet publish --configuration Release --runtime win-x64
--self-contained true /p:PublishSingleFile=true
/p:IncludeNativeLibrariesForSelfExtract=true
# 1. Build Framework-Dependent FIRST (The tiny one)
- name: Build Framework-Dependent (Requires .NET 8)
run: >
dotnet publish SshHandler/SshHandler.csproj --configuration Release
--self-contained false
/p:PublishSingleFile=true
-o ./publish-dotnet8
- name: Upload artifact
uses: actions/upload-artifact@v4
# 2. Clean to prevent artifact leakage
- name: Clean intermediate files
run: dotnet clean SshHandler/SshHandler.csproj
# 3. Build Standalone SECOND (The heavy one)
- name: Build Standalone (Includes Runtime)
run: >
dotnet publish SshHandler/SshHandler.csproj --configuration Release
--runtime win-x64
--self-contained true
/p:PublishSingleFile=true
/p:IncludeNativeLibrariesForSelfExtract=true
-o ./publish-standalone
- name: Ensure Unix Line Endings for Shell Script
shell: pwsh
run: |
$path = "ssh-handler.sh"
if (Test-Path $path) {
$content = [System.IO.File]::ReadAllText((Get-Item $path).FullName)
$content = $content -replace "`r`n", "`n"
[System.IO.File]::WriteAllText((Get-Item $path).FullName, $content, (New-Object System.Text.UTF8Encoding($false)))
}
- name: Prepare Assets with Versioning
shell: pwsh
run: |
$tag = "${{ github.ref_name }}"
if (-not $tag -or $tag -eq "main") { $tag = "manual" }
# Rename Executables
Move-Item ./publish-standalone/SshHandler.exe "./SshHandler-$tag-Standalone.exe"
Move-Item ./publish-dotnet8/SshHandler.exe "./SshHandler-$tag-dotnet8.exe"
# Rename Scripts
Copy-Item "ssh-handler.sh" "./ssh-handler-$tag.sh"
Copy-Item "openssh_protocol_handler.bat" "./openssh_protocol_handler-$tag.bat"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
name: SshHandler-Windows-Executable # The name of the downloadable file
path: ${{ github.workspace }}/SshHandler/bin/Release/net8.0-windows/win-x64/publish/SshHandler.exe # Adjust the path if your project name is different
files: |
SshHandler-*-Standalone.exe
SshHandler-*-dotnet8.exe
ssh-handler-*.sh
openssh_protocol_handler-*.bat
generate_release_notes: true
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -142,7 +142,7 @@ REM ============================================================================
echo.
SET /P "LEGACY_CHOICE=Enable legacy mode for old devices? (y/N): "
IF /I "!LEGACY_CHOICE!"=="Y" (
SET "LegacyOpts=-o KexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o HostKeyAlgorithms=+ssh-rsa -o MACs=+hmac-sha1,hmac-sha1-96"
SET "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"
echo.
echo [!] Legacy mode enabled. Insecure algorithms will be offered.
)

299
ssh-handler.sh Normal file
View File

@@ -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