Securing ssh-agent on Mac OS X 10.5 (Leopard)
In my previous article, I described how
ssh-agent is integrated with Mac OS X 10.5 (Leopard). While it is a huge improvement over previous versions of Mac OS X, SSHKeychain still has a couple of security features that are missing. These are especially nice for laptops when someone can just walk away with your machine, or in an office where you don’t trust everyone.
If you’re not that paranoid, the default Leopard behavior of storing your passphrase in your login keychain is probably fine. However, if you’re like me, we can harden things up a bit, while at the same time keeping security from becoming a burden. Here’s how I got Leopard to work very similarly to SSHKeychain, with some keychain management and small bit of coding.
The first feature I like about SSHKeychain is that it works in such a way that I never have to store my passphrase on disk anywhere, and yet I’m not constantly typing my passphrase all the time. It’s only stored in my head. Yeah, this is me being a little paranoid, but I figure that one good way to ensure the safety of my passphrase is to never store it on disk and never write it down. As long is it’s strong enough, someone won’t be able to crack it. And if it’s not stored on disk, it minimizes the chances that a baddie can get access to it through software bugs. Yes, I know about trojans and root exploits, so maybe I’m not being realistic. But it makes me feel good.
This works because SSHKeychain acts as a proxy to the real
ssh-agent. It only prompts me for my passphrase whenever I first try to run
ssh. But once I enter it, my identity is added to the agent, and I don’t have to enter my passphrase again. Left as-is, this means I type my passphrase at most once per login session.
The second feature I like is the ability to remove identities from the agent on certain system events, like going to sleep or activation of the screen saver. I used the “remove at sleep feature” on my laptop, so that I would be forced to re-type my passphrase after I woke it up. Again, this only happens when/if I actually use SSH. This is really nice on a laptop, because it means if it ever gets stolen, the thief can’t just pop the lid open, examine
~/.ssh/known_hosts and go to town. If you’re in a shared office environment, removing identities on the screen saver activation is also nice (possibly in conjunction with requiring a password to exit the screen saver).
The way to mimic the first feature is use multiple keychains. To set this up, use
ssh to add your passphrase to the keychain. Now open up Keychain Access and create a new keychain. I’ve named it “secure” and I set the password on this keychain to something different than the login keychain. Now, drag the SSH keychain item from the login keychain to the secure keychain.
This works because only the login keychain gets unlocked at login. Other keychains remain locked, until accessed. With my passphrase now in the “secure” keychain, whenever I run any SSH command for the first time, I get this dialog box to unlock the “secure” keychain:
My private key passphrase does end up in the keychain, but if I keep the password to the “secure” keychain in my head only, I’m back where I was with SSHKeychain.
Removing Identities on System Sleep
Forcing a re-type of my passphrase on system sleep takes a little more creativity. First off, you need to change the settings of the “secure” keychain (found under the Edit menu of Keychain Access). From here, you can choose to lock this keychain when sleeping or after a period of inactivity. I only use “Lock when sleeping.”
Just locking the keychain doesn’t remove identities from the agent, though. If there are identities in the agent before going to sleep, they can be used without a passphrase upon wake. Even removing the identities (with
ssh-add -D) at sleep doesn’t get the behavior I want. This will just cause the original “add passhprase to keychain” dialog box to show up (see my previous article). The way to get the behavior I want is to actually stop the agent on sleep. Stopping the agent is a matter of running this command:
% launchctl stop org.openbsd.ssh-agent
Unfortunately, there’s no way to automatically run this command on sleep or when the keychain locks. In order to do this, I decided to write a small application called
ssh_locker that listens for keychain lock notifications, and stops the agent in response. You can find it in my Google code project, if you want to try it out. There’s also a sample
launchd plist file, which you can modify and copy to:
My small app does not handle stopping the agent on screen saver activation. It would be pretty easy to add this, if you wanted. I can potentially see this app getting more sophisticated, with a preference pane UI similar the UI for SSHKeychain to set the options. This is really more work than I care to undertake right now, though, since this 40-line app fits my needs.