#!/bin/bash # Copyright 2012 Álvaro Justen # # 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; version 3 dated June, 2007. # # 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 . SBC=$0 SBC_PATH="$HOME/.sbc" SBC_KEY="$HOME/.ssh/sbc_rsa" SBC_CONTROL_PATH=/tmp/sbc_master_%h_%p_%r AUTH_KEYS="$HOME/.ssh/authorized_keys" SSH_LOCAL_PORT=22 get_username_and_hostname() { args=`getopt :1246AaCfgKkMNnqsTtVvXxYyb:c:D:e:F:I:i:L:l:m:O:o:p:R:S:W:w: "$@"` username="" port=22 last="" for arg in $args; do if [ "$last" = "-l" ]; then username=$arg elif [ "$last" = "-p" ]; then port=$arg fi last=$arg done user_host=$last hostname=${user_host#*@} if [ -z "$username" ]; then username=${user_host%@*} fi echo "$username@$hostname:$port" } if [ -z "$1" ]; then echo "Usage: $0 [--help] [options]" exit 1 fi sbc_command=$1 shift case "$sbc_command" in install) echo 'Deprecated. Please install sbc on the server by hand.' echo 'After installing it on the server, run "sbc setup user@host".' exit 1 ;; configure) # Running on remote - should be run only by sbc itself mkdir -p $HOME/.ssh key=$(cat -) echo "$key" > $SBC_KEY chmod 700 $HOME/.ssh chmod 600 $SBC_KEY ;; setup) # Running on client set -e if [ -z "$1" ]; then echo "Usage: $0 setup [ssh options] " exit 1 fi if [ ! -e "$SBC_KEY" ]; then echo -n "[sbc] Generating SSH RSA key without password ($SBC_KEY)..." ssh-keygen -t rsa -f $SBC_KEY -N '' &> /dev/null chmod 600 $SBC_KEY echo ' [OK]' else echo "[sbc] Using existing key $SBC_KEY" fi # TODO: replace private_key with variable name echo -n "[sbc] Copying private key to remote server..." cat $SBC_KEY | ssh $@ 'sbc configure' echo ' [OK]' echo -n "[sbc] Updating local authorized_keys (if needed)..." if [ ! -e "$HOME/.ssh" ]; then mkdir -p "$HOME/.ssh" chmod 700 "$HOME/.ssh" fi if [ "$(grep -s "$(cat $SBC_KEY.pub)" $AUTH_KEYS | wc -l)" = 0 ]; then cat $SBC_KEY.pub >> $AUTH_KEYS fi echo ' [OK]' echo "[sbc] Done! Try now: sbc ssh $@" set +e ;; ssh) # Running on client to start SSH connection set -e #TODO: warn user if sbc is not installed on server data=$(get_username_and_hostname $@) username=${data%@*} hostname=${data#*@}; hostname=${hostname%:*} port=${data#*:} # GUI applications need local environment env_file=/tmp/sbc-$USER-env-$hostname-$port-$username touch $env_file; chmod 600 $env_file env | sed 's/^/export /; s/=/="/; s/$/"/' >> $env_file SBC_PORT=$(($RANDOM + 1024)) echo -n '[sbc] Creating back-channel and connecting...' ssh -CtR 127.0.0.1:$SBC_PORT:127.0.0.1:$SSH_LOCAL_PORT $@ \ "SBC_USER=$USER SBC_PORT=$SBC_PORT \ SBC_REMOTE_USER=$username SBC_REMOTE_HOST=$hostname \ SBC_REMOTE_PORT=$port sbc shell" set +e ;; shell) # Running on remote host, to open a new SSH shell session #TODO: verify if is already inside a sbc remote session SBC_CMD="ssh -qNf -p $SBC_PORT -o StrictHostKeyChecking=no \ -o ControlMaster=auto -o ControlPath=$SBC_CONTROL_PATH \ -i $SBC_KEY $SBC_USER@localhost" $SBC_CMD SBC_BACKCHANNEL_PID=$(ps -Ao pid,cmd | grep "$(echo $SBC_CMD)" | awk '($2 != "grep") {print $1}') echo ' [OK]' # Open the user's default shell $SHELL echo -n '[sbc] Closing back-channel...' kill -9 $SBC_BACKCHANNEL_PID echo ' [OK]' ;; exec-plugin) # Running on client (called by remote `sbc plugin ...`) plugin=$1 shift # Update environment to the process which called 'sbc ssh' source /tmp/sbc-$USER-env-$SBC_REMOTE_HOST-$SBC_REMOTE_PORT-$SBC_REMOTE_USER if [ ! -x "$SBC_PATH/plugins/$plugin" ]; then echo "ERROR: plugin '$plugin' doesn't exist or isn't executable." exit 1 fi # Run the plugin $SBC_PATH/plugins/$plugin $@ ;; *) # Running on remote (try to run a plugin on local machine) # $sbc_command is the plugin to be executed env_vars="SBC_REMOTE_PWD=$PWD $(env | grep SBC_ | tr '\n' ' ')" ssh -qtp $SBC_PORT -o StrictHostKeyChecking=no \ -i $SBC_KEY -o ControlMaster=auto \ -o ControlPath=$SBC_CONTROL_PATH \ $SBC_USER@localhost \ "/bin/sh -lc \"$env_vars sbc exec-plugin $sbc_command '$@'\"" ;; esac