#!/bin/bash
# Exchance-SSH-Key. This program exchanges the SSH public key between two hosts
# Copyright (C) 2009 Leandro Melo de Sales <leandro@embedded.ufcg.edu.br>
# Copyright (C) 2008 Fabricio Epaminondas <fabricioepa@embedded.ufcg.edu.br>
# Copyright (C) 2008 Hallyson Melo <hallyson.melo@openbossa.org>
#
# 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 2 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, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA

DEBUG=1
SSH_PORT=22

ID_FILE="${HOME}/.ssh/id_rsa.pub"

function ssh-copy-id() {
    if [ "-i" = "$1" ]; then
        shift
        # check if we have 2 parameters left, if so the first is the new ID file
        if [ -n "$2" ]; then
            if expr "$1" : ".*\.pub" > /dev/null ; then
                ID_FILE="$1"
            else
                ID_FILE="$1.pub"
            fi
            shift         # and this should leave $1 as the target name
        fi
    else
        if [ x$SSH_AUTH_SOCK != x ] && ssh-add -L >/dev/null 2>&1; then
            GET_ID="$GET_ID ssh-add -L"
        fi
    fi

    if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ] ; then
        GET_ID="cat ${ID_FILE}"
    fi

    if [ -z "`eval $GET_ID`" ]; then
        echo "$0: ERROR: No identities found" >&2
        return 1
    fi

    if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
        echo "Usage: $0 [-i [identity_file]] [user@]machine" >&2
        return 1
    fi

    { eval "$GET_ID" ; } | ssh -p ${SSH_PORT} ${1%:} "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || return 1

    cat <<EOF
Now try logging into the machine, with "ssh '${1%:}'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

EOF
}

function usage() {
    USAGE="Usage: `basename $0` -l local_address -r remote_address -u remote_user [-p remote_port] [-h] [-q]"
    echo $USAGE >&2
    exit $1
}

function debug() {
    if [ $DEBUG -eq 1 ]; then
        echo $2 $1
    fi
}

function check_execution() {
    if [ $? -ne 0 ]; then
        debug $1
    else
        debug " OK!" ""
    fi
}

if [ $# -eq 0 ]; then
    usage 1
fi

if [ "$1" = "-h" ]; then
    usage 0
fi

while getopts l:r:u:qp: option; do
    case $option in
    l)  LOCAL_ADDR=$OPTARG
        ;;
    r)  REMOTE_ADDR=$OPTARG
        ;;
    u)  TARGET_USER=$OPTARG
        ;;
    q)  DEBUG=0
        ;;
    p)  SSH_PORT=$OPTARG
        ;;
    \?) # getopts issues an error message
        usage 1
        ;;
    *)  usage 0
        ;;
    esac
done

if [ "$TARGET_USER" = "" ]; then
    echo "Couldn't parse Target User."
    usage 1
fi

if [ $DEBUG -eq 0 ]; then
    echo "Working... please wait!"
fi

debug ""
debug "Host Address: ${LOCAL_ADDR}"
debug "Target Address: ${REMOTE_ADDR}"
debug "Target User: ${TARGET_USER}"
debug ""

##Variables
PUB_KEY=~/.ssh/id_rsa.pub

KNOWN_HOSTS=~/.ssh/known_hosts

AUTHORIZED_KEYS=~/.ssh/authorized_keys

REMOTE_HOST=$TARGET_USER@$REMOTE_ADDR

REDIRECT_STD_OUTPUT="/tmp/exchange-ssh-key.log"
REDIRECT_ERR_OUTPUT="/tmp/exchange-ssh-key.log.err"

rm -f $REDIRECT_STD_OUTPUT $REDIRECT_ERR_OUTPUT 2>/dev/null

if [ ${DEBUG} -eq 1 ]; then
    REDIRECT_OUTPUT=""
fi

#Create SOURCE identity if does not exists.
if [ ! -f $PUB_KEY ]; then
   debug "Creating your user local identity..." -n
   ssh-keygen -t rsa -f ~/.ssh/id_rsa -N '' >>$REDIRECT_STD_OUTPUT 2>>$REDIRECT_ERR_OUTPUT
   check_execution "Error executing ssh-keygen to generate user local identity"
fi


#Create known_hosts if does not exists.
if [ ! -f $KNOWN_HOSTS ]; then
  mkdir -p ~/.ssh
  touch $KNOWN_HOSTS
fi

debug "Adding trusted host to 'known hosts'..." -n
ssh-keyscan -t rsa  $REMOTE_ADDR >> $KNOWN_HOSTS 2>>$REDIRECT_ERR_OUTPUT
check_execution "Error executing ssh-keyscan for adding trusted host to the list of 'known hosts'"

debug "Exporting identity to remote host..." -n
ssh-copy-id $REMOTE_HOST >>$REDIRECT_STD_OUTPUT 2>>$REDIRECT_ERR_OUTPUT
check_execution "Error executing ssh-copy-id for exporting local identity to remote host"

debug "Verifying remote user identity and creating it if necessary (this may take a few minutes)..." -n
ssh -p ${SSH_PORT} $REMOTE_HOST "[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ''" >>$REDIRECT_STD_OUTPUT 2>>$REDIRECT_ERR_OUTPUT
debug "OK!"

debug "Authorizing remote host key..." -n
ssh -p ${SSH_PORT} $REMOTE_HOST "cat ~/.ssh/id_rsa.pub"  >>$AUTHORIZED_KEYS 2>>$REDIRECT_ERR_OUTPUT
check_execution "Error executing ssh for adding public key in the remote authorized_key file"
chmod 600 $AUTHORIZED_KEYS

ssh -p ${SSH_PORT} $REMOTE_HOST "ssh -o StrictHostKeyChecking=no $USER@$LOCAL_ADDR echo ''" >>$REDIRECT_STD_OUTPUT 2>>$REDIRECT_ERR_OUTPUT

if [ "x${REDIRECT_STD_OUTPUT}" == "x${REDIRECT_ERR_OUTPUT}" ];
then
    FILES_LOG=${REDIRECT_STD_OUTPUT}
else
    FILES_LOG="${REDIRECT_STD_OUTPUT} and ${REDIRECT_ERR_OUTPUT}"
fi

echo ""
echo "Done. See ${FILES_LOG} for detailed information"
echo "Please, check if everything is correctly by connect to the remote host via SSH."
echo ""
