#!/usr/bin/env python2.4 # # Copyright (c) 2003-2006 Andrea Luzzardi # # This file is part of the pam_usb project. pam_usb is free software; # you can redistribute it and/or modify it under the terms of the GNU General # Public License version 2, as published by the Free Software Foundation. # # pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place, Suite 330, Boston, MA 02111-1307 USA import os import sys import pwd import getopt import gobject import dbus if getattr(dbus, 'version', (0,0,0)) >= (0,41,0): import dbus.glib try: import cElementTree as et except ImportError: import elementtree.ElementTree as et class HotPlugDevice: def __init__(self, serial): self.__udi = None self.__serial = serial self.__callbacks = [] self.__bus = dbus.SystemBus() self.__running = False def run(self): self.__scanDevices() self.__registerSignals() self.__running = True gobject.MainLoop().run() print 'signals registered' def addCallback(self, callback): self.__callbacks.append(callback) def __scanDevices(self): halService = self.__bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') halManager = dbus.Interface(halService, 'org.freedesktop.Hal.Manager') for udi in halManager.FindDeviceStringMatch('info.bus', 'usb_device'): self.__deviceAdded(udi) def __registerSignals(self): for signal, callback in (('DeviceAdded', self.__deviceAdded), ('DeviceRemoved', self.__deviceRemoved)): self.__bus.add_signal_receiver(callback, signal, 'org.freedesktop.Hal.Manager', 'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') def __deviceAdded(self, udi): if self.__udi is not None: return deviceObj = self.__bus.get_object('org.freedesktop.Hal', udi) deviceProperties = deviceObj.GetAllProperties( dbus_interface = 'org.freedesktop.Hal.Device') if not deviceProperties.has_key('usb_device.serial'): return if deviceProperties['usb_device.serial'] != self.__serial: return self.__udi = udi print 'Device %s added' % udi if self.__running: [ cb('added') for cb in self.__callbacks ] def __deviceRemoved(self, udi): if self.__udi is None: return if self.__udi != udi: return self.__udi = None print 'Device %s removed' % udi if self.__running: [ cb('removed') for cb in self.__callbacks ] def usage(): print 'Usage: %s [--config file] [--daemon] [--path pusb_check_path]' \ % sys.argv[0] sys.exit(1) import getopt try: opts, args = getopt.getopt(sys.argv[1:], "hc:dp:", ["help", "config=", "daemon", "path="]) except getopt.GetoptError: usage() options = {'configFile' : '/etc/pam_usb/pusb.conf', 'daemon' : False, 'path' : '/usr/bin/pusb_check'} if len(args) != 0: usage() for o, a in opts: if o in ('-h', '--help'): usage() if o in ('-c', '--config'): options['configFile'] = a if o in ('-d', '--daemon'): options['daemon'] = True if o in ('-p', '--path'): options['path'] = a if not os.path.exists(options['path']): print '%s not found.' % options['path'] print "You might specify manually pusb_check's location using --path." usage() username = pwd.getpwuid(os.getuid())[0] print 'Running pusb_hotplug for user %s' % username doc = et.parse(options['configFile']) users = doc.findall('users/user') for user in users: if user.get('id') == username: break else: print 'User %s not found' % username events = { 'lock' : [], 'unlock' : [] } for hotplug in user.findall('hotplug'): events[hotplug.get('event')].append(hotplug.text) deviceName = user.find('device').text devices = doc.findall("devices/device") for device in devices: if device.get('id') == deviceName: break else: print 'Device %s not found' % deviceName serial = device.find('serial').text def authChangeCallback(event): print 'User %s is now %s' % (username, event) cmdLine = "%s -q -c %s -u %s -s pusb_hotplug -a" % (options['path'], options['configFile'], username) print 'Executing %s' % cmdLine if not os.system(cmdLine): run = events['unlock'] else: run = events['lock'] [os.system(e) for e in run] hpDev = HotPlugDevice(serial) hpDev.addCallback(authChangeCallback) if options['daemon'] and os.fork(): sys.exit(0) try: hpDev.run() except KeyboardInterrupt: print 'Exiting...'