Using DBUS to take action on a USB storage device

I keep my password-encrypted SSH and PGP keys on a small USB key.  I do this to keep these sensitive files separate from my laptop, in case I were to lose it.  I figure it’s easier to keep a USB key on me whenever I’m at work or traveling.  I don’t want to have to keep my USB key inserted all the time to encrypt files and emails or SSH to remote hosts.  Even though that would probably be more secure, I think I’d wear out the flash memory and would probably get annoyed before that even happened.  So, I want to cache the sensitive data in memory, so that it’s lost on powerdown, but available to me while working normally.

Luckily, ssh-agent provides this sort of functionality already, but GPG does not (that I know of).  What I want is some way for me to just insert my key and have the PGP files copied to a volatile location and the SSH keys inserted into the agent automatically (prompting for a password first, of course).  I could do this with an autorun file on the key itself, but then inserting it into random machines might copy my sensitive files, which would be really bad.  Since DBUS seems to be pretty nifty, I figured I should see about writing a little app to respond to the DBUS mount event to run a script for me.  I don’t know much about DBUS, so it seemed like a good exercise.

At first, I saw a Linux Journal article about doing this with udev rules, but that isn’t as nice because you don’t have DISPLAY set, and it doesn’t run as your own user.  Still workable, but less nice.  So, I googled for examples of using DBUS from Python and came up with the following dispatch app:

#!/usr/bin/python

DEVICE_TAG=”dansmith”
WORK_SCRIPT=”/home/dan/bin/sshkey.sh”

import dbus
import gobject
import dbus.mainloop.glib
import os

def handler(*args, **kwargs):
if not kwargs[“member”] == “VolumeMountedSignal”:
return

uri = args[0][4].replace(“file://”, “”Smilie: ;)
tag = args[0][6]

if tag == DEVICE_TAG:
os.system(“%s %s” % (WORK_SCRIPT, uri))

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
bus.add_signal_receiver(handler,
interface_keyword=”dbus_interface”,
member_keyword=”member”Smilie: ;)

loop = gobject.MainLoop()
loop.run()

I can then exec this as part of my gnome session startup.  The app listens for the “VolumeMountedSignal” and checks the volume label against what I know my USB key has.  If it matches, it runs my little helper script.  The script mounts a tmpfs in a subdirectory of $HOME, copies the PGP files into place, and then runs ssh-add on all of the SSH keys.  Since DISPLAY is set, I get the GUI ssh-askpass box to unlock each key.

It would be interesting to extend this little dispatch app to have a GUI interface to let you add device labels and associated actions.  It might be handy to have a couple things like “exec script foo”, “copy contents to /path/bar”, “freshen a tarball backup”, etc.

Category(s): Codemonkeying, Linux
Tags: ,

Comments are closed.