wps-ap-nfc.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #!/usr/bin/python
  2. #
  3. # Example nfcpy to hostapd wrapper for WPS NFC operations
  4. # Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
  5. #
  6. # This software may be distributed under the terms of the BSD license.
  7. # See README for more details.
  8. import os
  9. import sys
  10. import time
  11. import nfc
  12. import nfc.ndef
  13. import nfc.llcp
  14. import nfc.handover
  15. import logging
  16. logging.basicConfig()
  17. import wpaspy
  18. wpas_ctrl = '/var/run/hostapd'
  19. continue_loop = True
  20. def wpas_connect():
  21. ifaces = []
  22. if os.path.isdir(wpas_ctrl):
  23. try:
  24. ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
  25. except OSError, error:
  26. print "Could not find hostapd: ", error
  27. return None
  28. if len(ifaces) < 1:
  29. print "No hostapd control interface found"
  30. return None
  31. for ctrl in ifaces:
  32. try:
  33. wpas = wpaspy.Ctrl(ctrl)
  34. return wpas
  35. except Exception, e:
  36. pass
  37. return None
  38. def wpas_tag_read(message):
  39. wpas = wpas_connect()
  40. if (wpas == None):
  41. return
  42. if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")):
  43. return False
  44. return True
  45. def wpas_get_config_token():
  46. wpas = wpas_connect()
  47. if (wpas == None):
  48. return None
  49. return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex")
  50. def wpas_get_password_token():
  51. wpas = wpas_connect()
  52. if (wpas == None):
  53. return None
  54. return wpas.request("WPS_NFC_TOKEN NDEF").rstrip().decode("hex")
  55. def wpas_get_handover_sel():
  56. wpas = wpas_connect()
  57. if (wpas == None):
  58. return None
  59. return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip().decode("hex")
  60. def wpas_report_handover(req, sel):
  61. wpas = wpas_connect()
  62. if (wpas == None):
  63. return None
  64. return wpas.request("NFC_REPORT_HANDOVER RESP WPS " +
  65. str(req).encode("hex") + " " +
  66. str(sel).encode("hex"))
  67. class HandoverServer(nfc.handover.HandoverServer):
  68. def __init__(self, llc):
  69. super(HandoverServer, self).__init__(llc)
  70. self.ho_server_processing = False
  71. self.success = False
  72. def process_request(self, request):
  73. print "HandoverServer - request received"
  74. print "Parsed handover request: " + request.pretty()
  75. sel = nfc.ndef.HandoverSelectMessage(version="1.2")
  76. for carrier in request.carriers:
  77. print "Remote carrier type: " + carrier.type
  78. if carrier.type == "application/vnd.wfa.wsc":
  79. print "WPS carrier type match - add WPS carrier record"
  80. data = wpas_get_handover_sel()
  81. if data is None:
  82. print "Could not get handover select carrier record from hostapd"
  83. continue
  84. print "Handover select carrier record from hostapd:"
  85. print data.encode("hex")
  86. wpas_report_handover(carrier.record, data)
  87. message = nfc.ndef.Message(data);
  88. sel.add_carrier(message[0], "active", message[1:])
  89. print "Handover select:"
  90. print sel.pretty()
  91. print str(sel).encode("hex")
  92. print "Sending handover select"
  93. self.success = True
  94. return sel
  95. def wps_tag_read(tag):
  96. success = False
  97. if len(tag.ndef.message):
  98. for record in tag.ndef.message:
  99. print "record type " + record.type
  100. if record.type == "application/vnd.wfa.wsc":
  101. print "WPS tag - send to hostapd"
  102. success = wpas_tag_read(tag.ndef.message)
  103. break
  104. else:
  105. print "Empty tag"
  106. return success
  107. def rdwr_connected_write(tag):
  108. print "Tag found - writing"
  109. global write_data
  110. tag.ndef.message = str(write_data)
  111. print "Done - remove tag"
  112. global only_one
  113. if only_one:
  114. global continue_loop
  115. continue_loop = False
  116. global write_wait_remove
  117. while write_wait_remove and tag.is_present:
  118. time.sleep(0.1)
  119. def wps_write_config_tag(clf):
  120. print "Write WPS config token"
  121. global write_data, write_wait_remove
  122. write_wait_remove = True
  123. write_data = wpas_get_config_token()
  124. if write_data == None:
  125. print "Could not get WPS config token from hostapd"
  126. return
  127. print "Touch an NFC tag"
  128. clf.connect(rdwr={'on-connect': rdwr_connected_write})
  129. def wps_write_password_tag(clf):
  130. print "Write WPS password token"
  131. global write_data, write_wait_remove
  132. write_wait_remove = True
  133. write_data = wpas_get_password_token()
  134. if write_data == None:
  135. print "Could not get WPS password token from hostapd"
  136. return
  137. print "Touch an NFC tag"
  138. clf.connect(rdwr={'on-connect': rdwr_connected_write})
  139. def rdwr_connected(tag):
  140. global only_one
  141. print "Tag connected: " + str(tag)
  142. if tag.ndef:
  143. print "NDEF tag: " + tag.type
  144. try:
  145. print tag.ndef.message.pretty()
  146. except Exception, e:
  147. print e
  148. success = wps_tag_read(tag)
  149. if only_one and success:
  150. global continue_loop
  151. continue_loop = False
  152. else:
  153. print "Not an NDEF tag - remove tag"
  154. while tag.is_present:
  155. time.sleep(0.1)
  156. return not no_wait
  157. def llcp_startup(clf, llc):
  158. print "Start LLCP server"
  159. global srv
  160. srv = HandoverServer(llc)
  161. return llc
  162. def llcp_connected(llc):
  163. print "P2P LLCP connected"
  164. global wait_connection
  165. wait_connection = False
  166. global srv
  167. srv.start()
  168. return True
  169. def main():
  170. clf = nfc.ContactlessFrontend()
  171. try:
  172. if not clf.open("usb"):
  173. print "Could not open connection with an NFC device"
  174. raise SystemExit
  175. global only_one
  176. only_one = False
  177. if len(sys.argv) > 1 and sys.argv[1] == "write-config":
  178. wps_write_config_tag(clf)
  179. raise SystemExit
  180. if len(sys.argv) > 1 and sys.argv[1] == "write-password":
  181. wps_write_password_tag(clf)
  182. raise SystemExit
  183. global continue_loop
  184. while continue_loop:
  185. print "Waiting for a tag or peer to be touched"
  186. wait_connection = True
  187. try:
  188. if not clf.connect(rdwr={'on-connect': rdwr_connected},
  189. llcp={'on-startup': llcp_startup,
  190. 'on-connect': llcp_connected}):
  191. break
  192. except Exception, e:
  193. print "clf.connect failed"
  194. global srv
  195. if only_one and srv and srv.success:
  196. raise SystemExit
  197. except KeyboardInterrupt:
  198. raise SystemExit
  199. finally:
  200. clf.close()
  201. raise SystemExit
  202. if __name__ == '__main__':
  203. main()