|
#!/usr/bin/env python2.4
|
|
#
|
|
# Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
|
|
#
|
|
# 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...'
|