#!/bin/bash #Copyright 2001, William Stearns #Copyleft: # ssh-keyinstall helps an ssh user set up the keys at both ends of an ssh connection. # Copyright (C) 2001 William Stearns # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # # The author can also be reached at: # William Stearns #email: wstearns@pobox.com (preferred) #web: http://www.pobox.com/~wstearns #snail: 544 Winchester Place # Colchester VT, 05446, USA #FIXME Reinstate the following and remove the static require-util and wrap #functions once sam is released. #if [ -f /usr/lib/sam/samlib ]; then # . /usr/lib/sam/samlib #else # echo "/usr/lib/sam/samlib is missing - please get it from" >/dev/stderr # echo "http://www.pobox.com/~wstearns/" >/dev/stderr # echo "Exiting." >/dev/stderr # exit 1 #fi #FIXME Static versions require-util () { while [ -n "$1" ]; do if ! type -path "$1" >/dev/null 2>/dev/null ; then echo Missing utility "$1". Please install it. >/dev/stderr return 1 #False, app is not available. fi shift done return 0 #True, app is there. } #End of require-util if type -path sed >/dev/null 2>/dev/null && type -path wc >/dev/null 2>/dev/null ; then wrap () { if [ -n "$LINELENGTH" ]; then LINELENGTH_INT=$[ $LINELENGTH - `echo -n "$WRAPHEADER" | wc -c` ] else LINELENGTH_INT=$[ 72 - `echo -n "$WRAPHEADER" | wc -c` ] fi if [ $[ $LINELENGTH_INT ] -lt 20 ]; then LINELENGTH_INT=20 fi if [ $# -eq 0 ]; then #Double sed is required as the first sed only thinks there's one ^, even after we've stuck in newlines. sed -e "s/\(.\{1,$LINELENGTH_INT\}\)[[:space:]]\+/\1!!LINEFEED!!/g" -e 's/!!LINEFEED!!/\ /g' | sed -e "s/^/$WRAPHEADER/" else echo $ENH -n "$* " | sed -e "s/\(.\{1,$LINELENGTH_INT\}\)[[:space:]]\+/\1!!LINEFEED!!/g" -e 's/!!LINEFEED!!/\ /g' | sed -e "s/^/$WRAPHEADER/" fi } #End of wrap else #Fall back on alternate form of the function that doesnt need sed or wc. wrap () { if [ $# -eq 0 ]; then while read LINE ; do echo $LINE ; done else echo $ENH $* fi } #End of wrap fi if type -path basename >/dev/null 2>/dev/null ; then SCRIPTNAME=`basename $0` else SCRIPTNAME=$0 fi wrap $SCRIPTNAME, version 0.0.5 wrap ' ' wrap Please report any successes or failures to wstearns@pobox.com . \ Please note the client and server ssh versions, type of key used \ \(rsa=ssh protocol 1 or dsa=ssh protocol 2\), whether you created a \ new key or used an existing key, and whether you forced a particular \ remote command and send that information to William at the above \ address as he is hoping to test every combination. #Client-Server (O=openssh, 1=ssh1/datafellows 1, 2=ssh2/datafellows 2) #1=rsa/2=dsa keys #e=existing key used/n=new key created. c=tested with forced remote command. #Initials show who verified that it works, version reported working. #non-listed combinations are invalid. #WLS=William Stearns #O-O, 1, e WLS, 0.0.1 #O-O, 1, e, c WLS, 0.0.5 #O-O, 2, e WLS, 0.0.1 #O-O, 2, e, c WLS, 0.0.5 #O-O, 1, n #O-O, 1, n, c #O-O, 2, n #O-O, 2, n, c #O-1, 1, e #O-1, 1, e, c #O-1, 1, n #O-1, 1, n, c #O-2, 2, e #O-2, 2, e, c #O-2, 2, n #O-2, 2, n, c #1-O, 1, e #1-O, 1, e, c #1-O, 1, n #1-O, 1, n, c #1-1, 1, e #1-1, 1, e, c #1-1, 1, n #1-1, 1, n, c #2-O, 2, e #2-O, 2, e, c #2-O, 2, n #2-O, 2, n, c #2-2, 2, e #2-2, 2, e, c #2-2, 2, n WLS, 0.0.3...? #2-2, 2, n, c #TODO #askfirst/log to shell script. debug () { if [ "$VERBOSE" = "YES" ]; then wrap $* fi } showhelp () { wrap ' ' >/dev/stderr wrap Usage: >/dev/stderr WRAPHEADER=' ' wrap $SCRIPTNAME -s RemoteServerName [-u UserNameOnTheRemoteServer] [-p RemoteServerPort] [-c RemoteCommand] [-h] >/dev/stderr wrap For example, if I want to ssh to megabox.mydomain.com where I have user account gparker and the server runs on port 2222, I\'d type: >/dev/stderr wrap $SCRIPTNAME -s megabox.mydomain.com -u gparker -p 2222 >/dev/stderr wrap This will set up the necessary keys to connect from this machine to the given ssh server and account. >/dev/stderr wrap The RemoteUserName and port number are optional - if omitted, the value of \$USER and 22/tcp are used, respectively. >/dev/stderr wrap The RemoteCommand option allows you to specify a single command which is the only command that can be run when this key is used to authenticate. For example, if gparker was only allowed to run /usr/sbin/rsync-backup-server: >/dev/stderr wrap $SCRIPTNAME -s megabox.mydomain.com -u gparker -p 2222 -c /usr/sbin/rsync-backup-server >/dev/stderr wrap '-h shows this help.' >/dev/stderr wrap '-v runs verbosely.' >/dev/stderr exit 1 } require-util require-util wrap nc head ssh scp debug showhelp mkdir chmod wc || exit 1 #We do ssh-keygen on a case-by-case basis if needed. if [ $# -eq 0 ]; then showhelp fi unset REMOTECOMMAND REMPORT SERVERNAME REMUSERNAME VERBOSE while [ -n "$1" ]; do case $1 in -c|--remote-command) if [ -n "$2" ]; then REMOTECOMMAND="$2" shift 2 else wrap Remote command option requested, but no remote command specified. Exiting. >/dev/stderr exit 1 fi ;; -p|--remote-port) if [ -n "$2" ]; then REMPORT="$2" shift 2 else wrap Remote port option requested, but no remote port specified. Exiting. >/dev/stderr exit 1 fi ;; -s|--remote-server) if [ -n "$2" ]; then SERVERNAME="$2" shift 2 else wrap Remote server option requested, but no remote server specified. Exiting. >/dev/stderr exit 1 fi ;; -u|--remote-user) if [ -n "$2" ]; then REMUSERNAME="$2" shift 2 else wrap Remote user option requested, but no remote user specified. Exiting. >/dev/stderr exit 1 fi ;; -h|--help) showhelp ;; -v|--verbose) VERBOSE="YES" ;; *) wrap Unrecognized option \"$1\". Exiting. >/dev/stderr exit 1 ;; esac done if [ -z "$REMUSERNAME" ]; then REMUSERNAME=$USER fi if [ -z "$REMPORT" ]; then REMPORT=22 fi CLIENT_SSH1=NO CLIENT_SSH2=NO if type -path ssh1 >/dev/null 2>/dev/null ; then debug ssh1 binary detected, assuming ssh1 client support. CLIENT_SSH1=YES CLIENTTYPE=COMMSSH1 fi if type -path ssh2 >/dev/null 2>/dev/null ; then debug ssh2 binary detected, assuming ssh2 client support. CLIENT_SSH2=YES CLIENTTYPE=COMMSSH2 fi if [ "$CLIENT_SSH1" = "NO" ] && [ "$CLIENT_SSH2" = "NO" ]; then CLIENTSTRING=`ssh -V 2>&1 | sed -e 's/^[^ ]*: //' | head -1` case $CLIENTSTRING in #OpenSSH_2.5.1p2, SSH protocols 1.5/2.0, OpenSSL 0x0090581f -> openssh-2.5.1p2 OpenSSH*) debug OpenSSH client detected, assuming support for protocols 1 and 2. CLIENT_SSH1=YES CLIENT_SSH2=YES CLIENTTYPE=OPENSSH ;; #OK, big risk. I'm going to assume that fsecure ssh1 and ssh.com ssh1 use the same command line syntax. #FIXME # #F-SECURE SSH Version 1.3.6 [i686-unknown-linux], protocol version 1.5. # #Standard version. Does not use RSAREF. # F-SECURE\ SSH\ Version\ 1*) # CLIENT_SSH1=YES # CLIENTTYPE=FSECURESSH1 # ;; #SSH Version 1.2.26 [i686-unknown-linux], protocol version 1.5. #Standard version. Does not use RSAREF. -> commssh 1.2.26 SSH\ Version\ 1*|F-SECURE\ SSH\ Version\ 1*) debug Commercial ssh1 client detected, assuming support for protocol 1 only. CLIENT_SSH1=YES CLIENTTYPE=COMMSSH1 ;; #executable_name: SSH Version 2.0.13 -> commssh 2.0.13 SSH\ Version\ 2*) #FIXME - fsecure ssh2? debug Commercial ssh2 client detected, assuming support for protocol 2 only. CLIENT_SSH2=YES CLIENTTYPE=COMMSSH2 ;; *) wrap Unable to recognize the version string returned from this client: wrap \"$CLIENTSTRING\" wrap Please contact William Stearns \ with this description and the type and version number of the ssh client on this machine. Exiting. exit 1 ;; esac fi SERVERSTRING=`echo 'SSH-2.0' | nc $SERVERNAME $REMPORT 2>/dev/null | head -1` #Using 1.0 or 1.5 in the above probe returns "Protocol mismatch" from ssh2 servers - not useful. #2.0 gives descriptive output from ssh1, openssh, and ssh2. case $SERVERSTRING in '') wrap It does not appear that any ssh server is running on port $REMPORT at $SERVERNAME . Exiting. exit 1 ;; #SSH-1.99-OpenSSH_2.5.1p2 #Openssh SSH-1.99-OpenSSH*) #OpenSSH debug It appears the $SERVERNAME server is an OpenSSH server. Assuming it supports ssh1 and ssh2. SERVER_SSH1=YES SERVER_SSH2=YES #FIXME; Older versions may not... SERVERTYPE=OPENSSH ;; #FIXME If ssh2 is listening on port 22, it may hand off to sshd1. #SSH-1.99-2.0.13 (non-commercial) #ssh.com ssh2 SSH-1.99*) #SSH2 from SSH Comm. Sec. debug It appears the $SERVERNAME server is an SSH2 server from SSH.com. Assuming it supports ssh2 only. SERVER_SSH1=NO #It may be there is a backward compatibility handoff... ? SERVER_SSH2=YES SERVERTYPE=COMMSSH2 ;; #SSH-1.5-1.2.26 #ssh.com ssh1 #SSH-1.5-1.3.6 F-SECURE SSH #Datafellows ssh1 SSH-1.5*) #SSH1 from SSH Comm. Sec. or Datafellows debug It appears the $SERVERNAME server is an SSH1 server from SSH.com or Datafellows. Assuming it supports ssh1 only. SERVER_SSH1=YES SERVER_SSH2=NO SERVERTYPE=COMMSSH1 ;; *) wrap Unable to recognize the version string returned from the server: wrap \"$SERVERSTRING\" wrap Please contact William Stearns \ with this description and the type and version number of the ssh server at $SERVERNAME , port $REMPORT. Exiting. exit 1 ;; esac debug Summary: if [ "$CLIENT_SSH1" = "YES" ]; then debug Client supports SSH protocol 1. else debug Client does NOT support SSH protocol 1. fi if [ "$CLIENT_SSH2" = "YES" ]; then debug Client supports SSH protocol 2. else debug Client does NOT support SSH protocol 2. fi if [ "$SERVER_SSH1" = "YES" ]; then debug Server supports SSH protocol 1. else debug Server does NOT support SSH protocol 1. fi if [ "$SERVER_SSH2" = "YES" ]; then debug Server supports SSH protocol 2. else debug Server does NOT support SSH protocol 2. fi if [ "$CLIENT_SSH2" = "YES" ] && [ "$SERVER_SSH2" = "YES" ]; then debug Both client and server support protocol 2, good, we\'ll use that. #Set up ssh2 keys here. if [ "$CLIENTTYPE" = "COMMSSH1" ] || [ "$SERVERTYPE" = "COMMSSH1" ]; then wrap Ugh. We chose to use protocol 2, but either the client or server turned out to be ssh1 from SSH Communications Security or Datafellows. Please report this to the developer William Stearns \ as a bug. Please note the names and versions of the ssh client and ssh server. Thanks. exit 1 fi mkdir -p ~/.ssh ~/.ssh2 #We may not need both, but feel free to bill me for the lost 4K. chmod 700 ~ ~/.ssh ~/.ssh2 case $CLIENTTYPE in OPENSSH) if [ -f ~/.ssh/id_dsa ] && [ -f ~/.ssh/id_dsa.pub ]; then debug Existing id_dsa and id_dsa.pub files, using those. elif [ ! -f ~/.ssh/id_dsa ] && [ ! -f ~/.ssh/id_dsa.pub ]; then debug No identity file, making one. if [ -n "$REMOTECOMMAND" ]; then wrap You have specified a single allowed remote command. This _may_ be an appropriate situation to use a passphrase-less key, if so press enter twice to assign a blank passphrase. Otherwise please enter a truly hard to guess passphrase. else wrap Please enter a truly hard to guess passphrase. fi if type -path ssh-keygen >/dev/null 2>/dev/null ; then ssh-keygen -b 1024 -d -C "${USER}@$HOSTNAME" -f ~/.ssh/id_dsa else wrap Missing ssh-keygen from this openssh client. Exiting. exit 1 fi else wrap You have ~/.ssh/id_dsa or ~/.ssh/id_dsa.pub, but not both, oops. Please fix. Exiting. exit 1 fi PRIVATEKEY=~/.ssh/id_dsa #Don't quote the tilde's; they need to be expanded by the shell OPENSSHDSAPUBKEY=~/.ssh/id_dsa.pub if [ -f ~/.ssh/id_dsa.commsshformat.pub ]; then SSH2DSAPUBKEY=~/.ssh/id_dsa.commsshformat.pub elif [ ! -f ~/.ssh/id_dsa.commsshformat.pub ] && [ "$SERVERTYPE" = "COMMSSH2" ]; then wrap We do not have a public key in commercial ssh2 format but will need one in a minute. Converting now. This requires you to enter your passphrase as part of the conversion. if type -path ssh-keygen >/dev/null 2>/dev/null ; then ssh-keygen -f ~/.ssh/id_dsa -x >>~/.ssh/id_dsa.commsshformat.pub else wrap Missing ssh-keygen from this openssh client. Exiting. exit 1 fi SSH2DSAPUBKEY=~/.ssh/id_dsa.commsshformat.pub fi ;; #COMMSSH1 was disqualified, above. COMMSSH2) if [ -f ~/.ssh2/id_dsa_1024_a ] && [ -f ~/.ssh2/id_dsa_1024_a.pub ]; then debug Existing id_dsa_1024_a and id_dsa_1024_a.pub files, using those. elif [ ! -f ~/.ssh2/id_dsa_1024_a ] && [ ! -f ~/.ssh2/id_dsa_1024_a.pub ]; then debug No identity file, making one. if [ -n "$REMOTECOMMAND" ]; then wrap You have specified a single allowed remote command. This _may_ be an appropriate situation to use a passphrase-less key, if so press enter twice to assign a blank passphrase. Otherwise please enter a truly hard to guess passphrase. else wrap Please enter a truly hard to guess passphrase. fi if type -path ssh-keygen2 >/dev/null 2>/dev/null ; then ssh-keygen2 -b 1024 -t DSS -c "${USER}@$HOSTNAME" ~/.ssh2/id_dsa_1024_a #"-o" not needed for ssh2, at least elif type -path ssh-keygen >/dev/null 2>/dev/null ; then ssh-keygen -b 1024 -t DSS -c "${USER}@$HOSTNAME" ~/.ssh2/id_dsa_1024_a #"-o" not needed for ssh2, at least else wrap Missing ssh-keygen2/ssh-keygen from this ssh2 client. Exiting. exit 1 fi else wrap You have ~/.ssh2/id_dsa_1024_a or ~/.ssh2/id_dsa_1024_a.pub, but not both, oops. Please fix. Exiting. exit 1 fi PRIVATEKEY=~/.ssh2/id_dsa_1024_a OPENSSHDSAPUBKEY="" SSH2DSAPUBKEY=~/.ssh2/id_dsa_1024_a.pub echo "IdKey id_dsa_1024_a" >>~/.ssh2/identification ;; esac SSH1PUBKEY="" #keys exist chmod 600 $PRIVATEKEY case $SERVERTYPE in OPENSSH) wrap You will be asked to enter your remote password for each of the following commands. If you disagree with a particular command, or simply wish to perform it yourself, enter an incorrect password. set -x ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~ ; mkdir -p ~/.ssh ; chmod 700 ~/.ssh' #FIXME - small race here. ssh ${REMUSERNAME}@${SERVERNAME} 'rm -f ~/.ssh/newpubkey' if [ -n "$REMOTECOMMAND" ]; then ssh ${REMUSERNAME}@${SERVERNAME} "echo -n command=\\\"$REMOTECOMMAND\\\" ' ' >>~/.ssh/authorized_keys2" fi if [ -n "$OPENSSHDSAPUBKEY" ]; then scp -v $OPENSSHDSAPUBKEY ${REMUSERNAME}@${SERVERNAME}:~/.ssh/newpubkey ssh ${REMUSERNAME}@${SERVERNAME} 'cat ~/.ssh/newpubkey >>~/.ssh/authorized_keys2' else scp -v $SSH2DSAPUBKEY ${REMUSERNAME}@${SERVERNAME}:~/.ssh/newpubkey ssh ${REMUSERNAME}@${SERVERNAME} 'ssh-keygen -f ~/.ssh/newpubkey -X >>~/.ssh/authorized_keys2' fi ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 600 ~/.ssh/authorized_keys2' ssh ${REMUSERNAME}@${SERVERNAME} 'rm -f ~/.ssh/newpubkey' set +x ;; COMMSSH2) wrap You will be asked to enter your remote password for each of the following commands. If you disagree with a particular command, or simply wish to perform it yourself, enter an incorrect password. set -x ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~ ; mkdir -p ~/.ssh2 ; chmod 700 ~/.ssh2' #FIXME - small race here. REMKEYNAME=${SSH2DSAPUBKEY##*/} wrap I need to check if the remote key name is already in use. #FIXME - does this run into trouble if $HOME differs between local and remote? while ssh ${REMUSERNAME}@${SERVERNAME} "[ -f ~/.ssh2/${REMKEYNAME} ]" ; do wrap ~/.ssh2/$REMKEYNAME is already in use on $SERVERNAME . Please suggest another filename to use. Enter only the filename. For example, if you know ~/.ssh2/goober.pub is available, enter only \"goober.pub\" read REMKEYNAME done scp -v $SSH2DSAPUBKEY ${REMUSERNAME}@${SERVERNAME}:~/.ssh2/$REMKEYNAME ssh ${REMUSERNAME}@${SERVERNAME} "echo Key $REMKEYNAME >>~/.ssh2/authorization" if [ -n "$REMOTECOMMAND" ]; then ssh ${REMUSERNAME}@${SERVERNAME} "echo Command=\\\"$REMOTECOMMAND\\\">>~/.ssh2/authorization" fi ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 600 ~/.ssh2/authorization' set +x ;; esac if [ "$CLIENTTYPE" = "OPENSSH" ]; then if [ ! -f ~/.ssh/config ]; then touch ~/.ssh/config chmod 600 ~/.ssh/config fi if [ `cat ~/.ssh/config | grep "^Host $SERVERNAME$" | wc -l` -eq 0 ]; then echo "Host $SERVERNAME" >>~/.ssh/config echo " IdentityFile $PRIVATEKEY" >>~/.ssh/config echo " Protocol 2" >>~/.ssh/config echo " User $REMUSERNAME" >>~/.ssh/config fi fi elif [ "$CLIENT_SSH1" = "YES" ] && [ "$SERVER_SSH1" = "YES" ]; then debug Both client and server support protocol 1, good, we\'ll use that. #Set up ssh1 keys here. if [ "$CLIENTTYPE" = "COMMSSH2" ] || [ "$SERVERTYPE" = "COMMSSH2" ]; then wrap Ugh. We chose to use protocol 1, but either the client or server turned out to be ssh2 from SSH Communications Security or Datafellows. Please report this to the developer William Stearns \ as a bug. Please note the names and versions of the ssh client and ssh server. Thanks. exit 1 fi mkdir -p ~/.ssh chmod 700 ~ ~/.ssh if [ -f ~/.ssh/identity ] && [ -f ~/.ssh/identity.pub ]; then debug Existing identity and identity.pub files, using those. PRIVATEKEY=~/.ssh/identity #Don't quote the tilde's; they need to be expanded by the shell SSH1PUBKEY=~/.ssh/identity.pub OPENSSHDSAPUBKEY="" SSH2DSAPUBKEY="" elif [ ! -f ~/.ssh/identity ] && [ ! -f ~/.ssh/identity.pub ]; then debug No identity file, making one. if [ -n "$REMOTECOMMAND" ]; then wrap You have specified a single allowed remote command. This _may_ be an appropriate situation to use a passphrase-less key, if so press enter twice to assign a blank passphrase. Otherwise please enter a truly hard to guess passphrase. else wrap Please enter a truly hard to guess passphrase. fi case $CLIENTTYPE in OPENSSH) if type -path ssh-keygen >/dev/null 2>/dev/null ; then ssh-keygen -b 1024 -t rsa1 -C "${USER}@$HOSTNAME" -f ~/.ssh/identity else wrap Missing ssh-keygen from this openssh client. Exiting. exit 1 fi ;; COMMSSH1) if type -path ssh-keygen1 >/dev/null 2>/dev/null ; then ssh-keygen1 -b 1024 -C "${USER}@$HOSTNAME" -f ~/.ssh/identity elif type -path ssh-keygen >/dev/null 2>/dev/null ; then ssh-keygen -b 1024 -C "${USER}@$HOSTNAME" -f ~/.ssh/identity else wrap Missing ssh-keygen1/ssh-keygen from this ssh1 client. Exiting. exit 1 fi ;; #disqualified above #COMMSSH2) # ssh-keygen2 -b 1024 -t DSS -c "${USER}@$HOSTNAME" -o ~/.ssh/identity # ;; esac PRIVATEKEY=~/.ssh/identity SSH1PUBKEY=~/.ssh/identity.pub OPENSSHDSAPUBKEY="" SSH2DSAPUBKEY="" else wrap You have ~/.ssh/identity or ~/.ssh/identity.pub, but not both, oops. Please fix. Exiting. exit 1 fi #keys exist chmod 600 $PRIVATEKEY wrap You will be asked to enter your remote password for each of the following commands. If you disagree with a particular command, or simply wish to perform it yourself, enter an incorrect password. set -x ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~ ; mkdir -p ~/.ssh ; chmod 700 ~/.ssh' #FIXME - small race here. ssh ${REMUSERNAME}@${SERVERNAME} 'rm -f ~/.ssh/newpubkey' scp -v $SSH1PUBKEY ${REMUSERNAME}@${SERVERNAME}:~/.ssh/newpubkey if [ -n "$REMOTECOMMAND" ]; then ssh ${REMUSERNAME}@${SERVERNAME} "echo -n command=\\\"$REMOTECOMMAND\\\" ' ' >>~/.ssh/authorized_keys" fi ssh ${REMUSERNAME}@${SERVERNAME} 'cat ~/.ssh/newpubkey >>~/.ssh/authorized_keys' ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 600 ~/.ssh/authorized_keys' ssh ${REMUSERNAME}@${SERVERNAME} 'rm -f ~/.ssh/newpubkey' set +x if [ "$CLIENTTYPE" = "OPENSSH" ]; then if [ ! -f ~/.ssh/config ]; then touch ~/.ssh/config chmod 600 ~/.ssh/config fi if [ `cat ~/.ssh/config | grep "^Host $SERVERNAME$" | wc -l` -eq 0 ]; then echo "Host $SERVERNAME" >>~/.ssh/config echo " IdentityFile $PRIVATEKEY" >>~/.ssh/config echo " Protocol 1" >>~/.ssh/config echo " User $REMUSERNAME" >>~/.ssh/config fi fi else wrap Cannot find a protocol they agree on, exiting. exit 1 fi