 89896c0008
			
		
	
	
		89896c0008
		
	
	
	
	
		
			
			This patch is made by using 2to3 command. $ find . -name *.py | xargs 2to3 -f print -w -n Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
		
			
				
	
	
		
			342 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/python
 | |
| #
 | |
| # Example nfcpy to hostapd wrapper for WPS NFC operations
 | |
| # Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
 | |
| #
 | |
| # This software may be distributed under the terms of the BSD license.
 | |
| # See README for more details.
 | |
| 
 | |
| import os
 | |
| import sys
 | |
| import time
 | |
| import argparse
 | |
| 
 | |
| import nfc
 | |
| import nfc.ndef
 | |
| import nfc.llcp
 | |
| import nfc.handover
 | |
| 
 | |
| import logging
 | |
| 
 | |
| import wpaspy
 | |
| 
 | |
| wpas_ctrl = '/var/run/hostapd'
 | |
| continue_loop = True
 | |
| summary_file = None
 | |
| success_file = None
 | |
| 
 | |
| def summary(txt):
 | |
|     print(txt)
 | |
|     if summary_file:
 | |
|         with open(summary_file, 'a') as f:
 | |
|             f.write(txt + "\n")
 | |
| 
 | |
| def success_report(txt):
 | |
|     summary(txt)
 | |
|     if success_file:
 | |
|         with open(success_file, 'a') as f:
 | |
|             f.write(txt + "\n")
 | |
| 
 | |
| def wpas_connect():
 | |
|     ifaces = []
 | |
|     if os.path.isdir(wpas_ctrl):
 | |
|         try:
 | |
|             ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
 | |
|         except OSError as error:
 | |
|             print("Could not find hostapd: ", error)
 | |
|             return None
 | |
| 
 | |
|     if len(ifaces) < 1:
 | |
|         print("No hostapd control interface found")
 | |
|         return None
 | |
| 
 | |
|     for ctrl in ifaces:
 | |
|         try:
 | |
|             wpas = wpaspy.Ctrl(ctrl)
 | |
|             return wpas
 | |
|         except Exception as e:
 | |
|             pass
 | |
|     return None
 | |
| 
 | |
| 
 | |
| def wpas_tag_read(message):
 | |
|     wpas = wpas_connect()
 | |
|     if (wpas == None):
 | |
|         return False
 | |
|     if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")):
 | |
|         return False
 | |
|     return True
 | |
| 
 | |
| 
 | |
| def wpas_get_config_token():
 | |
|     wpas = wpas_connect()
 | |
|     if (wpas == None):
 | |
|         return None
 | |
|     ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF")
 | |
|     if "FAIL" in ret:
 | |
|         return None
 | |
|     return ret.rstrip().decode("hex")
 | |
| 
 | |
| 
 | |
| def wpas_get_password_token():
 | |
|     wpas = wpas_connect()
 | |
|     if (wpas == None):
 | |
|         return None
 | |
|     ret = wpas.request("WPS_NFC_TOKEN NDEF")
 | |
|     if "FAIL" in ret:
 | |
|         return None
 | |
|     return ret.rstrip().decode("hex")
 | |
| 
 | |
| 
 | |
| def wpas_get_handover_sel():
 | |
|     wpas = wpas_connect()
 | |
|     if (wpas == None):
 | |
|         return None
 | |
|     ret = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR")
 | |
|     if "FAIL" in ret:
 | |
|         return None
 | |
|     return ret.rstrip().decode("hex")
 | |
| 
 | |
| 
 | |
| def wpas_report_handover(req, sel):
 | |
|     wpas = wpas_connect()
 | |
|     if (wpas == None):
 | |
|         return None
 | |
|     return wpas.request("NFC_REPORT_HANDOVER RESP WPS " +
 | |
|                         str(req).encode("hex") + " " +
 | |
|                         str(sel).encode("hex"))
 | |
| 
 | |
| 
 | |
| class HandoverServer(nfc.handover.HandoverServer):
 | |
|     def __init__(self, llc):
 | |
|         super(HandoverServer, self).__init__(llc)
 | |
|         self.ho_server_processing = False
 | |
|         self.success = False
 | |
| 
 | |
|     # override to avoid parser error in request/response.pretty() in nfcpy
 | |
|     # due to new WSC handover format
 | |
|     def _process_request(self, request):
 | |
|         summary("received handover request {}".format(request.type))
 | |
|         response = nfc.ndef.Message("\xd1\x02\x01Hs\x12")
 | |
|         if not request.type == 'urn:nfc:wkt:Hr':
 | |
|             summary("not a handover request")
 | |
|         else:
 | |
|             try:
 | |
|                 request = nfc.ndef.HandoverRequestMessage(request)
 | |
|             except nfc.ndef.DecodeError as e:
 | |
|                 summary("error decoding 'Hr' message: {}".format(e))
 | |
|             else:
 | |
|                 response = self.process_request(request)
 | |
|         summary("send handover response {}".format(response.type))
 | |
|         return response
 | |
| 
 | |
|     def process_request(self, request):
 | |
|         summary("HandoverServer - request received")
 | |
|         try:
 | |
|             print("Parsed handover request: " + request.pretty())
 | |
|         except Exception as e:
 | |
|             print(e)
 | |
|         print(str(request).encode("hex"))
 | |
| 
 | |
|         sel = nfc.ndef.HandoverSelectMessage(version="1.2")
 | |
| 
 | |
|         for carrier in request.carriers:
 | |
|             print("Remote carrier type: " + carrier.type)
 | |
|             if carrier.type == "application/vnd.wfa.wsc":
 | |
|                 summary("WPS carrier type match - add WPS carrier record")
 | |
|                 data = wpas_get_handover_sel()
 | |
|                 if data is None:
 | |
|                     summary("Could not get handover select carrier record from hostapd")
 | |
|                     continue
 | |
|                 print("Handover select carrier record from hostapd:")
 | |
|                 print(data.encode("hex"))
 | |
|                 if "OK" in wpas_report_handover(carrier.record, data):
 | |
|                     success_report("Handover reported successfully")
 | |
|                 else:
 | |
|                     summary("Handover report rejected")
 | |
| 
 | |
|                 message = nfc.ndef.Message(data);
 | |
|                 sel.add_carrier(message[0], "active", message[1:])
 | |
| 
 | |
|         print("Handover select:")
 | |
|         try:
 | |
|             print(sel.pretty())
 | |
|         except Exception as e:
 | |
|             print(e)
 | |
|         print(str(sel).encode("hex"))
 | |
| 
 | |
|         summary("Sending handover select")
 | |
|         self.success = True
 | |
|         return sel
 | |
| 
 | |
| 
 | |
| def wps_tag_read(tag):
 | |
|     success = False
 | |
|     if len(tag.ndef.message):
 | |
|         for record in tag.ndef.message:
 | |
|             print("record type " + record.type)
 | |
|             if record.type == "application/vnd.wfa.wsc":
 | |
|                 summary("WPS tag - send to hostapd")
 | |
|                 success = wpas_tag_read(tag.ndef.message)
 | |
|                 break
 | |
|     else:
 | |
|         summary("Empty tag")
 | |
| 
 | |
|     if success:
 | |
|         success_report("Tag read succeeded")
 | |
| 
 | |
|     return success
 | |
| 
 | |
| 
 | |
| def rdwr_connected_write(tag):
 | |
|     summary("Tag found - writing - " + str(tag))
 | |
|     global write_data
 | |
|     tag.ndef.message = str(write_data)
 | |
|     success_report("Tag write succeeded")
 | |
|     print("Done - remove tag")
 | |
|     global only_one
 | |
|     if only_one:
 | |
|         global continue_loop
 | |
|         continue_loop = False
 | |
|     global write_wait_remove
 | |
|     while write_wait_remove and tag.is_present:
 | |
|         time.sleep(0.1)
 | |
| 
 | |
| def wps_write_config_tag(clf, wait_remove=True):
 | |
|     summary("Write WPS config token")
 | |
|     global write_data, write_wait_remove
 | |
|     write_wait_remove = wait_remove
 | |
|     write_data = wpas_get_config_token()
 | |
|     if write_data == None:
 | |
|         summary("Could not get WPS config token from hostapd")
 | |
|         return
 | |
| 
 | |
|     print("Touch an NFC tag")
 | |
|     clf.connect(rdwr={'on-connect': rdwr_connected_write})
 | |
| 
 | |
| 
 | |
| def wps_write_password_tag(clf, wait_remove=True):
 | |
|     summary("Write WPS password token")
 | |
|     global write_data, write_wait_remove
 | |
|     write_wait_remove = wait_remove
 | |
|     write_data = wpas_get_password_token()
 | |
|     if write_data == None:
 | |
|         summary("Could not get WPS password token from hostapd")
 | |
|         return
 | |
| 
 | |
|     print("Touch an NFC tag")
 | |
|     clf.connect(rdwr={'on-connect': rdwr_connected_write})
 | |
| 
 | |
| 
 | |
| def rdwr_connected(tag):
 | |
|     global only_one, no_wait
 | |
|     summary("Tag connected: " + str(tag))
 | |
| 
 | |
|     if tag.ndef:
 | |
|         print("NDEF tag: " + tag.type)
 | |
|         try:
 | |
|             print(tag.ndef.message.pretty())
 | |
|         except Exception as e:
 | |
|             print(e)
 | |
|         success = wps_tag_read(tag)
 | |
|         if only_one and success:
 | |
|             global continue_loop
 | |
|             continue_loop = False
 | |
|     else:
 | |
|         summary("Not an NDEF tag - remove tag")
 | |
|         return True
 | |
| 
 | |
|     return not no_wait
 | |
| 
 | |
| 
 | |
| def llcp_startup(clf, llc):
 | |
|     print("Start LLCP server")
 | |
|     global srv
 | |
|     srv = HandoverServer(llc)
 | |
|     return llc
 | |
| 
 | |
| def llcp_connected(llc):
 | |
|     print("P2P LLCP connected")
 | |
|     global wait_connection
 | |
|     wait_connection = False
 | |
|     global srv
 | |
|     srv.start()
 | |
|     return True
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     clf = nfc.ContactlessFrontend()
 | |
| 
 | |
|     parser = argparse.ArgumentParser(description='nfcpy to hostapd integration for WPS NFC operations')
 | |
|     parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
 | |
|                         action='store_const', dest='loglevel',
 | |
|                         help='verbose debug output')
 | |
|     parser.add_argument('-q', const=logging.WARNING, action='store_const',
 | |
|                         dest='loglevel', help='be quiet')
 | |
|     parser.add_argument('--only-one', '-1', action='store_true',
 | |
|                         help='run only one operation and exit')
 | |
|     parser.add_argument('--no-wait', action='store_true',
 | |
|                         help='do not wait for tag to be removed before exiting')
 | |
|     parser.add_argument('--summary',
 | |
|                         help='summary file for writing status updates')
 | |
|     parser.add_argument('--success',
 | |
|                         help='success file for writing success update')
 | |
|     parser.add_argument('command', choices=['write-config',
 | |
|                                             'write-password'],
 | |
|                         nargs='?')
 | |
|     args = parser.parse_args()
 | |
| 
 | |
|     global only_one
 | |
|     only_one = args.only_one
 | |
| 
 | |
|     global no_wait
 | |
|     no_wait = args.no_wait
 | |
| 
 | |
|     if args.summary:
 | |
|         global summary_file
 | |
|         summary_file = args.summary
 | |
| 
 | |
|     if args.success:
 | |
|         global success_file
 | |
|         success_file = args.success
 | |
| 
 | |
|     logging.basicConfig(level=args.loglevel)
 | |
| 
 | |
|     try:
 | |
|         if not clf.open("usb"):
 | |
|             print("Could not open connection with an NFC device")
 | |
|             raise SystemExit
 | |
| 
 | |
|         if args.command == "write-config":
 | |
|             wps_write_config_tag(clf, wait_remove=not args.no_wait)
 | |
|             raise SystemExit
 | |
| 
 | |
|         if args.command == "write-password":
 | |
|             wps_write_password_tag(clf, wait_remove=not args.no_wait)
 | |
|             raise SystemExit
 | |
| 
 | |
|         global continue_loop
 | |
|         while continue_loop:
 | |
|             print("Waiting for a tag or peer to be touched")
 | |
|             wait_connection = True
 | |
|             try:
 | |
|                 if not clf.connect(rdwr={'on-connect': rdwr_connected},
 | |
|                                    llcp={'on-startup': llcp_startup,
 | |
|                                          'on-connect': llcp_connected}):
 | |
|                     break
 | |
|             except Exception as e:
 | |
|                 print("clf.connect failed")
 | |
| 
 | |
|             global srv
 | |
|             if only_one and srv and srv.success:
 | |
|                 raise SystemExit
 | |
| 
 | |
|     except KeyboardInterrupt:
 | |
|         raise SystemExit
 | |
|     finally:
 | |
|         clf.close()
 | |
| 
 | |
|     raise SystemExit
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |