Tuesday, 1 April 2008

Getting SSHKeychain to work on Leopard (OS X 10.5)

For several years I've used the excellent utility SSHkeychain to manage my interactions with external servers. I spend a lot of time running multiple shells and moving files from one system to another and the efficiency that a good key agent brings is something that I've come to rely on.

However, recently I switched to a new machine which came with 10.5 installed and I discovered that Apple have elected to build their own ssh-agent interface into the system.

But it's rubbish.

It doesn't remember the keys other than by adding them to the keychain (which I refuse to do) and it can't be configured to drop them on system events like the screen saver kicking in. And if I install SSHKeychain then the system just ignores it. Damn, that's annoying.

So I googled about a bit and found a couple of posts that talked about the issue, one of which said that SSHKeychain was dead and another that came up with a partial solution that involved extra keychains and an application hack to remove keys from the agent when certain things happen. But no-where - not even on the SSHKeychain site - did I find a recipe to restore SSHKeychain functionality properly.

So, knowing a bit about UNIX, the way that Apple has implemented its on-demand services daemon and the way that ssh-agents work in general, I've come up with a simple way to get back the control over how my system operates.

It turns out to be remarkably simple.

SSH agents work by setting themselves up and listening on a local socket. They advertise this fact by setting an environment variable called SSH_AUTH_SOCK. Programs that need access to the agent look for this environment variable and, if it is set, make a call to it in order to get the necessary authentication.

SSHKeychain does just this, setting up a socket for each machine user named according to the user's unique (by machine) user id number.

Unfortunately, Apple uses the same thing to intercept agent requests and overrides the SSHKeychain setting, pointing the SSH_AUTH_SOCK at its own local socket. Requests to the Apple-supplied socket launch the OS built-in agent instead.

However, there is a way that we can get control of the SSH_AUTH_SOCK variable. We can put an entry in our .profile script (or the [t]csh equivalent .cshrc) to look for the SSHKeychain socket and point at it if it exists.

So, if you love SSHKeychain as much as I do then run, don't walk, to your favourite text editor and edit (or create) a file called .profile in your login directory to contain the following code:


if [ -e "/tmp/${UID}/SSHKeychain.socket" ];
then
export SSH_AUTH_SOCK="/tmp/${UID}/SSHKeychain.socket"
fi


Now, whenever you fire up a terminal, if you have SSHKeychain running then it will be invoked to handle your key requests. The half-a**ed Apple attempt at a key agent GUI will only be used if you've forgotten to run SSHKeychain.

I hope that helps folks, and I look forward to any comments and/or improvements.

7 comments:

Unknown said...

I've had the same annoyance... I found your post when trying to troubleshoot because SSHKeychain suddenly stopped working at all for me for the last few days. Mine didn't have any problems working on Leopard by itself though, I had the "Manage and modify global environment variables" thing set in the preferences for it, and that successfully got it in line in front of Apple's ssh agent until a couple days ago. I'm still not sure what's wrong; typing "env" from the shell does show the SSH_AUTH_SOCK set to SSHKeychain's socket.

Unknown said...

And just in case anyone else finds your blog while looking for solutions to the problem I'm having, I found a solution at http://www.simplicidade.org/notes/archives/2007/12/sshkeychain_bug.html that solved mine. Turns out SSHKeychain had somehow gotten something into the Apple keychain (which I don't recall telling it to do) and that was tripping it up. The error message it was putting into /var/log/system.log every time the Apple ssh-agent prompt came up gave it away.

Anonymous said...

SSHKeychain has an "Environment" preference tab where you can enter such global variables. Isn't that supposed to take care of this?

Andy Law said...

> SSHKeychain has an "Environment"
> preference tab where you can enter
> such global variables. Isn't that
> supposed to take care of this?

Yeah - and it did in 10.4. Unfortunately 10.5 seems to squirt a launchd 'listener' into the environment *after* SSHKeychain has done its work. In fact, I read a post recently that suggested that the way that SSHKeychain does the environment modification is deprecated.

I have since discovered that although my manual method works for terminal shells, it is ignored for processes launched from the Dock. So, for example, TextWrangler gets the Apple-supplied agent when it tries to make SSH/SCP connections rather than the SSHKeychain one. This is annoying.

Unknown said...

> Yeah - and it did in 10.4.
> Unfortunately 10.5 seems to squirt
> a launchd 'listener' into the
> environment *after* SSHKeychain
> has done its work.

... which you can disable by running

launchctl unload -w /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist

On Leopard this will disable it for all users, on Snow Leopard it will only disable it for the user who ran launchctl. You can then use the SSHKeychain environment tab to add the environment variables and all your ssh connections (terminal and GUI) will then use SSHKeychain.

Unknown said...

P.S. on Leopard that launchctl command may need to be run with sudo, I haven't tried it myself (I only needed the fix on SL).

Unknown said...

Thank you!