SSH Authentication on Mac OS X

One of the nicest things about SSH is the ssh-agent which serves up the authentication codes for SSH sessions so that you don't have to keep typing in your password to establish secure connections to all the different machines.

On most Linux distributions, the ssh-agent is invoked at login and all you really need to do is to establish your private keys and then do an ssh-add to load up those keys. On Mac OS X it's a little different and I have to say that I'm a little surprised that there's not a preferences setting that starts this at login. But it's not that hard to do if you get a reasonably nice script written that restarts ssh-agent for you.

Here's what I came up with to restart ssh-agent and update the file that holds the environment variables for subsequent shells:

#!/bin/tcsh
##
# Start SSH Key Agent
##
if (`where ssh-agent` != "") then
	#
	# See if there's already a running copy of ssh-agent
	#
	if (`ps -aux | grep 'ssh-agent' | grep -v grep | wc -l` -eq 1) then
		kill `ps -aux | grep 'ssh-agent' | grep -v grep | awk { print $2 }`
	endif
	#
	# ...and make sure to unset the variable for the PID of the agent
	#
	if ($?SSH_AGENT_PID) then
		unsetenv SSH_AGENT_PID
	endif
	#
	# Now see if we have the socket connection already defined as well
	#
	if ($?SSH_AUTH_SOCK) then
		if (! -S "${SSH_AUTH_SOCK}") then
			unsetenv SSH_AUTH_SOCK
		endif
	endif
	#
	# This is the file location that will hold the environment-setting
	# commands for all subsequent shells based on the results of running
	# ssh-agent for the first time.
	#
	setenv SSH_AGENT_STATE "/tmp/.ssh-agent-state.${user}"
	#
	# If it's still there, it's got old data and needs to be wiped out
	#
	if (-f "${SSH_AGENT_STATE}") then
		rm -f "${SSH_AGENT_STATE}"
	endif
	#
	# If we're all clean, then we need to start up a new instance, and
	# save the environment settings in the proper file for later
	# invocation by other shells.
	#
	if (! $?SSH_AGENT_PID && ! $?SSH_AUTH_SOCK && ! -f "${SSH_AGENT_STATE}") then
		ssh-agent | grep -v '^echo ' >"${SSH_AGENT_STATE}"
		source "${SSH_AGENT_STATE}"
	endif
endif

I call it sshAgent and then in my .login file I have the following lines:

#
# Now get the SSH-Agent up and working on this box so I can get into
# the machines at home where the keys are set up to match.
#
${HOME}/bin/sshAgent
source /tmp/.ssh-agent-state.${user}

Then it's just a matter of generating the keys and getting them to the right hosts for authentication purposes. To generate keys for both SSH v1 and v2 you can simply do this:

ssh-keygen -t rsa1
ssh-keygen -t rsa
ssh-keygen -t dsa

And when each command is executed enter the same pass-phrase so that one pass-phrase activates all key sets. You should have several files in ${HOME}/.ssh and you need to copy most of these to the other hosts you want to make SSH connections to. Specifically, copy:

id_dsa
id_dsa.pub
id_rsa
id_rsa.pub
identity
identity.pub

And make sure to have the non-.pub files read/write only by you, the user.

You're almost done. Now, on these other machines execute the following commands to copy the public keys to the authorized key lists:

cd ${HOME}/.ssh
cp id_dsa.pub authorized_keys2
cat identity.pub id_dsa.pub id_rsa.pub > authorized_keys

Then, on your Mac OS X box, run the sshAgent script and then run ssh-add and enter your pass-phrase - you should see it adding the three keys - DSA, RSA, and RSA1. Now you can simply ssh to the machines that have those copied keys. It's all done.

Excellent!