From: Matthias Kruk Date: Tue, 20 Jul 2021 01:04:02 +0000 (+0900) Subject: include/ssh: Import ssh module from toolbox X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=5abbb6c48d1291a9e65309b7f86bab9543b4cdd7;p=toolbox-goodies include/ssh: Import ssh module from toolbox This commit imports the ssh module that has previously been removed from the toolbox core package. --- 5abbb6c48d1291a9e65309b7f86bab9543b4cdd7 diff --git a/include/ssh.sh b/include/ssh.sh new file mode 100755 index 0000000..39e5ba2 --- /dev/null +++ b/include/ssh.sh @@ -0,0 +1,204 @@ +#!/bin/bash + +# ssh.sh - Toolbox module for SSH tunnels and dynamic proxies +# Copyright (C) 2021 Matthias Kruk +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +__init() { + if ! include "log"; then + return 1 + fi + + declare -xgr __ssh_socket_dir="$TOOLBOX_HOME/ssh" + + return 0 +} + +_ssh_get_socket_dir() { + if ! mkdir -p "$__ssh_socket_dir" &> /dev/null; then + error "Could not create $__ssh_socket_dir" + return 1 + fi + + echo "$__ssh_socket_dir" + return 0 +} + +_ssh_tunnel_ctrl_socket_name() { + local host + local port + local lport + + local sockdir + + host="$1" + port="$2" + lport="$3" + + if ! sockdir=$(_ssh_get_socket_dir); then + return 1 + fi + + echo "$sockdir/tunnel-$lport-$host-$port.sock" + return 0 +} + +_ssh_proxy_ctrl_socket_name() { + local host + local port + + local sockdir + + host="$1" + port="$2" + + if ! sockdir=$(_ssh_get_socket_dir); then + return 1 + fi + + echo "$sockdir/proxy-$host-$port.sock" + return 0 +} + +_ssh_make_handle() { + local ctrlsock="$1" + local hostspec="$2" + + local handle + + if ! handle=$(base64 <<< "$ctrlsock" 2>/dev/null); then + return 1 + fi + + handle+=":" + + if ! handle+=$(base64 <<< "$hostspec" 2>/dev/null); then + return 1 + fi + + echo "$handle" + return 0 +} + +_ssh_handle_get_ctrlsock() { + local handle="$1" + + local ctrlsock + + if ! ctrlsock=$(base64 -d <<< "${handle%%:*}" 2>/dev/null); then + return 1 + fi + + echo "$ctrlsock" + return 0 +} + +_ssh_handle_get_hostspec() { + local handle="$1" + + local hostspec + + if ! hostspec=$(base64 -d <<< "${handle##*:}" 2>/dev/null); then + return 1 + fi + + echo "$hostspec" + return 0 +} + +ssh_tunnel_open() { + local tunnel_host="$1" + local tunnel_user="$2" + local remote_addr="$3" + local remote_port="$4" + local local_addr="$5" + local local_port="$6" + + local ctrl_sock + local addrspec + local sshtarget + local handle + + addrspec="$local_addr:$local_port:$remote_addr:$remote_port" + sshtarget="$tunnel_user@$tunnel_host" + + if ! ctrl_sock=$(_ssh_tunnel_ctrl_socket_name "$remote_addr" \ + "$remote_port" \ + "$local_port"); then + return 1 + fi + + if ! handle=$(_ssh_make_handle "$ctrl_sock" "$sshtarget"); then + return 1 + fi + + if ! ssh -M -S "$ctrl_sock" -fnNT -o "ExitOnForwardFailure=yes" \ + -L "$addrspec" "$sshtarget" > /dev/null; then + return 1 + fi + + echo "$handle" + return 0 +} + +ssh_proxy_open() { + local proxy_host="$1" + local proxy_user="$2" + local local_addr="$3" + local local_port="$4" + + local ctrl_sock + local addrspec + local sshtarget + local handle + + addrspec="$local_addr:$local_port" + sshtarget="$proxy_user@$proxy_host" + + if ! ctrl_sock=$(_ssh_proxy_ctrl_socket_name "$local_addr" "$local_port"); then + return 1 + fi + + if ! handle=$(_ssh_make_handle "$ctrl_sock" "$sshtarget"); then + return 1 + fi + + if ! ssh -M -S "$ctrl_sock" -fnNT -o "ExitOnForwardFailure=yes" \ + -D "$addrspec" "$sshtarget" > /dev/null; then + return 1 + fi + + echo "$handle" + return 0 +} + +ssh_close() { + local handle="$1" + + local ctrlsock + local hostspec + + if ! ctrlsock=$(_ssh_handle_get_ctrlsock "$handle") || + ! hostspec=$(_ssh_handle_get_hostspec "$handle"); then + log_error "Invalid handle" + return 1 + fi + + if ! ssh -S "$ctrlsock" -O exit "$hostspec" &> /dev/null; then + return 1 + fi + + return 0 +}