#!/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