#!/bin/bash #Copyright 2001, William Stearns #Released under the GPL. echo $0, Version 0.0.1 echo The \"just-barely-code-complete\" release. echo Please report any sucesses or failures to wstearns@pobox.com echo Please note the client and server ssh versions and send them to echo William at the above address. #Tested and working (Client -> Server) #Openssh -> Openssh with rsa/ssh1 keys #Openssh -> Openssh with dsa/ssh2 keys #TODO #- add ~/.ssh/config:hostname:protocol 1/2 lines for openssh client? #askfirst/log to shell script. require-util () { #Assures the utility is / utilities are in the path _and_ executable. while [ -n "$1" ]; do if ! type -path "$1" >/dev/null 2>/dev/null ; then echo Missing utility "$1", exiting. exit 1 fi shift done } showhelp () { echo Usage: >/dev/stderr echo $0 RemoteServerName [UserNameOnTheRemoteServer] [RemoteServerPort] >/dev/stderr echo for example, if I want to ssh to megabox.mydomain.com where I have >/dev/stderr echo user account gparker and the server runs on port 2222, I\'d type: >/dev/stderr echo $0 megabox.mydomain.com gparker 2222 >/dev/stderr echo This will set up the necessary keys to connect from this machine to >/dev/stderr echo the given ssh server and account. >/dev/stderr echo The RemoteUserName is also optional - if omitted, the value of \$USER is used. >/dev/stderr echo The port number is optional - if omitted, port 22/tcp is assumed. >/dev/stderr exit 1 } if [ $# -eq 0 ]; then showhelp fi require-util nc head SERVERNAME=$1 if [ -n "$2" ]; then REMUSERNAME=$2 else REMUSERNAME=$USER fi if [ -n "$3" ]; then REMPORT=$3 else REMPORT=22 fi CLIENT_SSH1=NO CLIENT_SSH2=NO if type -path ssh1 >/dev/null 2>/dev/null ; then echo ssh1 binary detected, assuming ssh1 client support. CLIENT_SSH1=YES fi if type -path ssh2 >/dev/null 2>/dev/null ; then echo ssh2 binary detected, assuming ssh1 client support. CLIENT_SSH2=YES 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*) echo 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. -> realssh 1.2.26 SSH\ Version\ 1*|F-SECURE\ SSH\ Version\ 1*) echo ssh.com ssh1 client detected, assuming support for protocol 1 only. CLIENT_SSH1=YES CLIENTTYPE=REALSSH1 ;; #executable_name: SSH Version 2.0.13 -> realssh 2.0.13 SSH\ Version\ 2*) #FIXME - fsecure ssh2? echo ssh.com ssh2 client detected, assuming support for protocol 2 only. CLIENT_SSH2=YES CLIENTTYPE=REALSSH2 ;; *) echo Unable to recognize the version string returned from this client: echo \"$CLIENTSTRING\" echo 'Please contact William Stearns with this' echo description and the type and version number of the ssh client echo 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 '') echo It does not appear that any ssh server is running on port $REMPORT echo at $SERVERNAME . Exiting. exit 1 ;; #SSH-1.99-OpenSSH_2.5.1p2 #Openssh SSH-1.99-OpenSSH*) #OpenSSH echo It appears the $SERVERNAME server is an OpenSSH server. echo Assuming it supports ssh1 and ssh2. SERVER_SSH1=YES SERVER_SSH2=YES #FIXME; Older versions may not... SERVERTYPE=OPENSSH ;; #SSH-1.99-2.0.13 (non-commercial) #ssh.com ssh2 SSH-1.99*) #SSH2 from SSH Comm. Sec. echo It appears the $SERVERNAME server is an SSH2 server from SSH.com. echo Assuming it supports ssh2 only. SERVER_SSH1=NO #It may be there in a backward compatibility handoff... ? SERVER_SSH2=YES SERVERTYPE=REALSSH2 ;; #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 echo It appears the $SERVERNAME server is an SSH1 server from SSH.com or Datafellows. echo Assuming it supports ssh1 only. SERVER_SSH1=YES SERVER_SSH2=NO SERVERTYPE=REALSSH1 ;; *) echo Unable to recognize the version string returned from the server: echo \"$SERVERSTRING\" echo 'Please contact William Stearns with this' echo description and the type and version number of the ssh server at echo $SERVERNAME , port $REMPORT. Exiting. exit 1 ;; esac echo Summary: if [ "$CLIENT_SSH1" = "YES" ]; then echo Client supports SSH protocol 1 else echo Client does NOT support SSH protocol 1 fi if [ "$CLIENT_SSH2" = "YES" ]; then echo Client supports SSH protocol 2 else echo Client does NOT support SSH protocol 2 fi if [ "$SERVER_SSH1" = "YES" ]; then echo Server supports SSH protocol 1 else echo Server does NOT support SSH protocol 1 fi if [ "$SERVER_SSH2" = "YES" ]; then echo Server supports SSH protocol 2 else echo Server does NOT support SSH protocol 2 fi if [ "$CLIENT_SSH2" = "YES" ] && [ "$SERVER_SSH2" = "YES" ]; then echo Both client and server support protocol 2, good, we\'ll use that. #Set up ssh2 keys here. if [ "$CLIENTTYPE" = "REALSSH1" ] || [ "$SERVERTYPE" = "REALSSH1" ]; then echo Ugh. We chose to use protocol 2, but either the client or server echo turned out to be ssh1 from SSH Communications Security or Datafellows. echo Please report this to the developer echo 'William Stearns ' as a bug. Please note the echo 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 echo Existing id_dsa and id_dsa.pub files, using those. elif [ ! -f ~/.ssh/id_dsa ] && [ ! -f ~/.ssh/id_dsa.pub ]; then echo No identity file, making one. ssh-keygen -b 1024 -d -C "${USER}-backup@$HOSTNAME" -f ~/.ssh/id_dsa else echo You have ~/.ssh/id_dsa or ~/.ssh/id_dsa.pub, but not both, oops. echo 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.realsshformat.pub ]; then SSH2DSAPUBKEY=~/.ssh/id_dsa.realsshformat.pub elif [ ! -f ~/.ssh/id_dsa.realsshformat.pub ] && [ "$SERVERTYPE" = "REALSSH2" ]; then echo We do not have a public key in real ssh2 format but will echo need one in a minute. Converting now. echo This requires you to enter your passphrase as part of the conversion. ssh-keygen -f ~/.ssh/id_dsa -x >>~/.ssh/id_dsa.realsshformat.pub SSH2DSAPUBKEY=~/.ssh/id_dsa.realsshformat.pub fi ;; #disqualified, above. # REALSSH1) # ssh-keygen1 -b 1024 -C "${USER}-backup@$HOSTNAME" -f ~/.ssh/identity # PRIVATEKEY=~/.ssh/identity # OPENSSHDSAPUBKEY=~/.ssh/identity.pub # SSH2DSAPUBKEY="" # ;; REALSSH2) if [ -f ~/.ssh2/id_dsa_1024_a ] && [ -f ~/.ssh2/id_dsa_1024_a.pub ]; then echo 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 echo No identity file, making one. ssh-keygen2 -b 1024 -t DSS -c "${USER}-backup@$HOSTNAME" -o ~/.ssh2/id_dsa_1024_a else echo You have ~/.ssh2/id_dsa_1024_a or ~/.ssh2/id_dsa_1024_a.pub, but not both, oops. echo 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) echo You will be asked to enter your remote password for each of the echo following commands. If you disagree with a particular command, echo or simply wish to perform it yourself, enter an incorrect password. set -x ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~' ssh ${REMUSERNAME}@${SERVERNAME} 'mkdir -p ~/.ssh' ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~/.ssh' #FIXME - small race here. ssh ${REMUSERNAME}@${SERVERNAME} 'rm -f ~/.ssh/newpubkey' 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 ;; REALSSH2) echo You will be asked to enter your remote password for each of the echo following commands. If you disagree with a particular command, echo or simply wish to perform it yourself, enter an incorrect password. set -x ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~' ssh ${REMUSERNAME}@${SERVERNAME} 'mkdir -p ~/.ssh2' ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~/.ssh2' #FIXME - small race here. REMKEYNAME=$SSH2DSAPUBKEY echo 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 echo ~/.ssh2/$REMKEYNAME is already in use on $SERVERNAME . Please suggest echo another filename to use. Enter only the filename. For example, if you echo 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" ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 600 ~/.ssh2/authorization' set +x ;; esac elif [ "$CLIENT_SSH1" = "YES" ] && [ "$SERVER_SSH1" = "YES" ]; then echo Both client and server support protocol 1, good, we\'ll use that. #Set up ssh1 keys here. if [ "$CLIENTTYPE" = "REALSSH2" ] || [ "$SERVERTYPE" = "REALSSH2" ]; then echo Ugh. We chose to use protocol 1, but either the client or server echo turned out to be ssh2 from SSH Communications Security or Datafellows. echo Please report this to the developer echo 'William Stearns ' as a bug. Please note the echo 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 echo 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 echo No identity file, making one. case $CLIENTTYPE in OPENSSH) ssh-keygen -b 1024 -t rsa1 -C "${USER}-backup@$HOSTNAME" -f ~/.ssh/identity ;; REALSSH1) ssh-keygen1 -b 1024 -C "${USER}-backup@$HOSTNAME" -f ~/.ssh/identity ;; #disqualified above #REALSSH2) ssh-keygen2 -b 1024 -t DSS -c "${USER}-backup@$HOSTNAME" -o ~/.ssh/identity ;; esac PRIVATEKEY=~/.ssh/identity SSH1PUBKEY=~/.ssh/identity.pub OPENSSHDSAPUBKEY="" SSH2DSAPUBKEY="" else echo You have ~/.ssh/identity or ~/.ssh/identity.pub, but not both, oops. echo Please fix. Exiting. exit 1 fi #keys exist chmod 600 $PRIVATEKEY echo You will be asked to enter your remote password for each of the echo following commands. If you disagree with a particular command, echo or simply wish to perform it yourself, enter an incorrect password. set -x ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~' ssh ${REMUSERNAME}@${SERVERNAME} 'mkdir -p ~/.ssh' ssh ${REMUSERNAME}@${SERVERNAME} 'chmod 700 ~/.ssh' #FIXME - small race here. ssh ${REMUSERNAME}@${SERVERNAME} 'rm -f ~/.ssh/newpubkey' scp -v $SSH1PUBKEY ${REMUSERNAME}@${SERVERNAME}:~/.ssh/newpubkey 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 else echo Cannot find a protocol they agree on, exiting. exit 1 fi