Hardware authentication for Linux using ordinary USB Flash Drives.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
6.7 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (c) 2003-2007 Andrea Luzzardi <scox@sig11.org>
  4. #
  5. # This file is part of the pam_usb project. pam_usb is free software;
  6. # you can redistribute it and/or modify it under the terms of the GNU General
  7. # Public License version 2, as published by the Free Software Foundation.
  8. #
  9. # pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
  10. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  12. # details.
  13. #
  14. # You should have received a copy of the GNU General Public License along with
  15. # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  16. # Place, Suite 330, Boston, MA 02111-1307 USA
  17. import dbus
  18. import sys
  19. import os
  20. from xml.dom import minidom
  21. class Device:
  22. def __init__(self, udi):
  23. self.__udi = udi
  24. self.__findStorageDevice()
  25. deviceObj = bus.get_object('org.freedesktop.Hal',
  26. udi)
  27. deviceProperties = deviceObj.GetAllProperties(
  28. dbus_interface = 'org.freedesktop.Hal.Device')
  29. self.vendor = deviceProperties['usb_device.vendor']
  30. self.product = deviceProperties['info.product']
  31. self.serialNumber = deviceProperties['usb_device.serial']
  32. def __findStorageDevice(self):
  33. for child in halManager.FindDeviceByCapability('storage'):
  34. obj = bus.get_object('org.freedesktop.Hal',
  35. child)
  36. properties = obj.GetAllProperties(
  37. dbus_interface = 'org.freedesktop.Hal.Device')
  38. if properties['storage.physical_device'] == self.__udi + '_if0':
  39. self.__storageUdi = child
  40. return
  41. raise Exception, '%s is not a storage device.' % self.__udi
  42. def __repr__(self):
  43. return "%s %s (%s)" % (self.vendor, self.product, self.serialNumber)
  44. def volumes(self):
  45. vols = []
  46. for volume in halManager.FindDeviceByCapability('volume'):
  47. deviceObj = bus.get_object('org.freedesktop.Hal',
  48. volume)
  49. deviceProperties = deviceObj.GetAllProperties(
  50. dbus_interface = 'org.freedesktop.Hal.Device')
  51. if deviceProperties['block.storage_device'] != self.__storageUdi:
  52. continue
  53. vols.append({'uuid' : deviceProperties['volume.uuid'],
  54. 'device' : deviceProperties['block.device']})
  55. return vols
  56. def listOptions(question, options, force = False):
  57. if force == False and len(options) == 1:
  58. return 0
  59. while True:
  60. try:
  61. print question
  62. for i in range(len(options)):
  63. print "%d) %s" % (i, options[i])
  64. print
  65. sys.stdout.write('[%s-%s]: ' % (0, len(options) - 1))
  66. optionId = int(sys.stdin.readline())
  67. print
  68. if optionId not in range(len(options)):
  69. raise Exception
  70. return optionId
  71. except KeyboardInterrupt: sys.exit()
  72. except Exception: pass
  73. else: break
  74. def addDevice(options):
  75. devices = []
  76. for udi in halManager.FindDeviceStringMatch('info.bus', 'usb_device'):
  77. try:
  78. devices.append(Device(udi))
  79. except Exception, ex:
  80. pass
  81. if len(devices) == 0:
  82. print 'No devices detected.'
  83. sys.exit()
  84. device = devices[listOptions("Please select the device you wish to add.",
  85. devices, force = options['force'])]
  86. volumes = device.volumes()
  87. volume = volumes[listOptions("Which volume would you like to use for " \
  88. "storing data ?",
  89. ["%s (UUID: %s)" % (volume['device'],
  90. volume['uuid'])
  91. for volume in volumes],
  92. force = options['force'])]
  93. print 'Name\t\t: %s' % options['deviceName']
  94. print 'Vendor\t\t: %s' % device.vendor
  95. print 'Model\t\t: %s' % device.product
  96. print 'Serial\t\t: %s' % device.serialNumber
  97. if volume['uuid'] != '':
  98. print 'Volume UUID\t: %s (%s)' % (volume['uuid'], volume['device'])
  99. else:
  100. print
  101. print 'WARNING: No UUID detected for device %s. One time pads will be disabled.' % volume['device']
  102. print
  103. print 'Save device to %s ?' % options['configFile']
  104. sys.stdout.write('[y/n] ')
  105. if sys.stdin.readline().strip() != 'y':
  106. sys.exit(1)
  107. try:
  108. doc = minidom.parse(options['configFile'])
  109. except Exception, err:
  110. print 'Unable to read %s: %s' % (options['configFile'], err)
  111. sys.exit(1)
  112. devs = doc.getElementsByTagName('devices')
  113. dev = doc.createElement('device')
  114. dev.attributes['id'] = options['deviceName']
  115. devs[0].appendChild(dev)
  116. for name, value in (('vendor', device.vendor),
  117. ('model', device.product),
  118. ('serial', device.serialNumber),
  119. ('volume_uuid', volume['uuid'])):
  120. e = doc.createElement(name)
  121. t = doc.createTextNode(value)
  122. e.appendChild(t)
  123. dev.appendChild(e)
  124. # Disable one time pads if there's no device UUID
  125. if volume['uuid'] == '':
  126. e = doc.createElement('option')
  127. e.setAttribute('name', 'one_time_pad')
  128. e.appendChild(doc.createTextNode('false'))
  129. dev.appendChild(e)
  130. try:
  131. f = open(options['configFile'], 'w')
  132. f.write(doc.toxml())
  133. f.close()
  134. except Exception, err:
  135. print 'Unable to save %s: %s' % (options['configFile'], err)
  136. sys.exit(1)
  137. else:
  138. print 'Done.'
  139. def usage():
  140. print 'Usage: %s [--config file] --add-device <name> [--no-autodetect]' % os.path.basename(__file__)
  141. sys.exit(1)
  142. import getopt
  143. try:
  144. opts, args = getopt.getopt(sys.argv[1:], "ha:nc:",
  145. ["help", "add-device=", "no-autodetect",
  146. "config="])
  147. except getopt.GetoptError:
  148. usage()
  149. if len(args) != 0:
  150. usage()
  151. options = { 'force' : False, 'deviceName' : None,
  152. 'configFile' : '/etc/pusb/pusb.conf' }
  153. for o, a in opts:
  154. if o in ("-h", "--help"):
  155. usage()
  156. if o in ("-a", "--add-device"):
  157. options['deviceName'] = a
  158. if o in ("-n", "--no-autodetect"):
  159. options['force'] = True
  160. if o in ("-c", "--config"):
  161. options['configFile'] = a
  162. if options['deviceName'] is None:
  163. usage()
  164. bus = dbus.SystemBus()
  165. halService = bus.get_object('org.freedesktop.Hal',
  166. '/org/freedesktop/Hal/Manager')
  167. halManager = dbus.Interface(halService, 'org.freedesktop.Hal.Manager')
  168. try:
  169. addDevice(options)
  170. except KeyboardInterrupt:
  171. sys.exit(1)