From 6f8fa6e552d82c026d8b7a2630119423de002dd5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 Nov 2013 12:16:38 +0200 Subject: [PATCH] WPS NFC: Update wps-nfc.py and wps-ap-nfc.py to use new nfcpy API This moves many of the peer discovery operations into the core nfcpy. Signed-hostap: Jouni Malinen --- hostapd/wps-ap-nfc.py | 194 ++++++++++----------- wpa_supplicant/examples/wps-nfc.py | 260 +++++++++++++---------------- 2 files changed, 209 insertions(+), 245 deletions(-) diff --git a/hostapd/wps-ap-nfc.py b/hostapd/wps-ap-nfc.py index 61b5519ac..be7338d4d 100755 --- a/hostapd/wps-ap-nfc.py +++ b/hostapd/wps-ap-nfc.py @@ -21,6 +21,7 @@ logging.basicConfig() import wpaspy wpas_ctrl = '/var/run/hostapd' +continue_loop = True def wpas_connect(): ifaces = [] @@ -48,7 +49,9 @@ def wpas_tag_read(message): wpas = wpas_connect() if (wpas == None): return - print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex")) + if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")): + return False + return True def wpas_get_config_token(): @@ -82,8 +85,10 @@ def wpas_report_handover(req, sel): class HandoverServer(nfc.handover.HandoverServer): - def __init__(self): - super(HandoverServer, self).__init__() + def __init__(self, llc): + super(HandoverServer, self).__init__(llc) + self.ho_server_processing = False + self.success = False def process_request(self, request): print "HandoverServer - request received" @@ -95,14 +100,13 @@ class HandoverServer(nfc.handover.HandoverServer): print "Remote carrier type: " + carrier.type if carrier.type == "application/vnd.wfa.wsc": print "WPS carrier type match - add WPS carrier record" - self.received_carrier = carrier.record data = wpas_get_handover_sel() if data is None: print "Could not get handover select carrier record from hostapd" continue print "Handover select carrier record from hostapd:" print data.encode("hex") - self.sent_carrier = data + wpas_report_handover(carrier.record, data) message = nfc.ndef.Message(data); sel.add_carrier(message[0], "active", message[1:]) @@ -112,132 +116,112 @@ class HandoverServer(nfc.handover.HandoverServer): print str(sel).encode("hex") print "Sending handover select" + self.success = True return sel -def wps_handover_resp(peer): - print "Trying to handle WPS handover" - - srv = HandoverServer() - srv.sent_carrier = None - - nfc.llcp.activate(peer); - - try: - print "Trying handover"; - srv.start() - print "Wait for disconnect" - while nfc.llcp.connected(): - time.sleep(0.1) - print "Disconnected after handover" - except nfc.llcp.ConnectRefused: - print "Handover connection refused" - nfc.llcp.shutdown() - return - - if srv.sent_carrier: - wpas_report_handover(srv.received_carrier, srv.sent_carrier) - - print "Remove peer" - nfc.llcp.shutdown() - print "Done with handover" - - def wps_tag_read(tag): + success = False if len(tag.ndef.message): - message = nfc.ndef.Message(tag.ndef.message) - print "message type " + message.type - - for record in message: + for record in tag.ndef.message: print "record type " + record.type if record.type == "application/vnd.wfa.wsc": print "WPS tag - send to hostapd" - wpas_tag_read(tag.ndef.message) + success = wpas_tag_read(tag.ndef.message) break else: print "Empty tag" - print "Remove tag" - while tag.is_present: - time.sleep(0.1) + return success +def rdwr_connected_write(tag): + print "Tag found - writing" + global write_data + tag.ndef.message = str(write_data) + 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): print "Write WPS config token" - data = wpas_get_config_token() - if (data == None): + global write_data, write_wait_remove + write_wait_remove = True + write_data = wpas_get_config_token() + if write_data == None: print "Could not get WPS config token from hostapd" return print "Touch an NFC tag" - while True: - tag = clf.poll() - if tag == None: - time.sleep(0.1) - continue - break - - print "Tag found - writing" - tag.ndef.message = data - print "Done - remove tag" - while tag.is_present: - time.sleep(0.1) + clf.connect(rdwr={'on-connect': rdwr_connected_write}) def wps_write_password_tag(clf): print "Write WPS password token" - data = wpas_get_password_token() - if (data == None): + global write_data, write_wait_remove + write_wait_remove = True + write_data = wpas_get_password_token() + if write_data == None: print "Could not get WPS password token from hostapd" return print "Touch an NFC tag" - while True: - tag = clf.poll() - if tag == None: + clf.connect(rdwr={'on-connect': rdwr_connected_write}) + + +def rdwr_connected(tag): + global only_one + print "Tag connected: " + str(tag) + + if tag.ndef: + print "NDEF tag: " + tag.type + try: + print tag.ndef.message.pretty() + except Exception, e: + print e + success = wps_tag_read(tag) + if only_one and success: + global continue_loop + continue_loop = False + else: + print "Not an NDEF tag - remove tag" + while tag.is_present: time.sleep(0.1) - continue - break - print "Tag found - writing" - tag.ndef.message = data - print "Done - remove tag" - while tag.is_present: - time.sleep(0.1) + return not no_wait -def find_peer(clf): - while True: - if nfc.llcp.connected(): - print "LLCP connected" - general_bytes = nfc.llcp.startup({}) - peer = clf.listen(ord(os.urandom(1)) + 250, general_bytes) - if isinstance(peer, nfc.DEP): - print "listen -> DEP"; - if peer.general_bytes.startswith("Ffm"): - print "Found DEP" - return peer - print "mismatch in general_bytes" - print peer.general_bytes +def llcp_startup(clf, llc): + print "Start LLCP server" + global srv + srv = HandoverServer(llc) + return llc - peer = clf.poll(general_bytes) - if isinstance(peer, nfc.DEP): - print "poll -> DEP"; - if peer.general_bytes.startswith("Ffm"): - print "Found DEP" - return peer - print "mismatch in general_bytes" - print peer.general_bytes - - if peer: - print "Found tag" - return peer +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() try: + if not clf.open("usb"): + print "Could not open connection with an NFC device" + raise SystemExit + + global only_one + only_one = False + if len(sys.argv) > 1 and sys.argv[1] == "write-config": wps_write_config_tag(clf) raise SystemExit @@ -246,21 +230,21 @@ def main(): wps_write_password_tag(clf) raise SystemExit - while True: + 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, e: + print "clf.connect failed" - tag = find_peer(clf) - if isinstance(tag, nfc.DEP): - wps_handover_resp(tag) - continue - - if tag.ndef: - wps_tag_read(tag) - continue - - print "Not an NDEF tag - remove tag" - while tag.is_present: - time.sleep(0.1) + global srv + if only_one and srv and srv.success: + raise SystemExit except KeyboardInterrupt: raise SystemExit diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py index d6dec85c8..3d7e01681 100755 --- a/wpa_supplicant/examples/wps-nfc.py +++ b/wpa_supplicant/examples/wps-nfc.py @@ -11,6 +11,7 @@ import sys import time import random import StringIO +import threading import nfc import nfc.ndef @@ -23,6 +24,8 @@ logging.basicConfig() import wpaspy wpas_ctrl = '/var/run/wpa_supplicant' +srv = None +continue_loop = True def wpas_connect(): ifaces = [] @@ -50,7 +53,7 @@ def wpas_tag_read(message): wpas = wpas_connect() if (wpas == None): return False - if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + message.encode("hex")): + if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")): return False return True @@ -107,10 +110,14 @@ def wpas_report_handover(req, sel, type): class HandoverServer(nfc.handover.HandoverServer): - def __init__(self): - super(HandoverServer, self).__init__() + def __init__(self, llc): + super(HandoverServer, self).__init__(llc) + self.sent_carrier = None + self.ho_server_processing = False + self.success = False def process_request(self, request): + self.ho_server_processing = True print "HandoverServer - request received" print "Parsed handover request: " + request.pretty() @@ -120,7 +127,6 @@ class HandoverServer(nfc.handover.HandoverServer): print "Remote carrier type: " + carrier.type if carrier.type == "application/vnd.wfa.wsc": print "WPS carrier type match - add WPS carrier record" - self.received_carrier = carrier.record data = wpas_get_handover_sel(self.uuid) if data is None: print "Could not get handover select carrier record from wpa_supplicant" @@ -128,6 +134,7 @@ class HandoverServer(nfc.handover.HandoverServer): print "Handover select carrier record from wpa_supplicant:" print data.encode("hex") self.sent_carrier = data + wpas_report_handover(carrier.record, self.sent_carrier, "RESP") message = nfc.ndef.Message(data); sel.add_carrier(message[0], "active", message[1:]) @@ -137,43 +144,11 @@ class HandoverServer(nfc.handover.HandoverServer): print str(sel).encode("hex") print "Sending handover select" + self.success = True return sel -def wps_handover_resp(peer, uuid): - if uuid is None: - print "Trying to handle WPS handover" - else: - print "Trying to handle WPS handover with AP " + uuid - - srv = HandoverServer() - srv.sent_carrier = None - srv.uuid = uuid - - nfc.llcp.activate(peer); - - try: - print "Trying handover"; - srv.start() - print "Wait for disconnect" - while nfc.llcp.connected(): - time.sleep(0.1) - print "Disconnected after handover" - except nfc.llcp.ConnectRefused: - print "Handover connection refused" - nfc.llcp.shutdown() - return - - if srv.sent_carrier: - wpas_report_handover(srv.received_carrier, srv.sent_carrier, "RESP") - - print "Remove peer" - nfc.llcp.shutdown() - print "Done with handover" - time.sleep(1) - - -def wps_handover_init(peer): +def wps_handover_init(llc): print "Trying to initiate WPS handover" data = wpas_get_handover_req() @@ -195,16 +170,13 @@ def wps_handover_init(peer): print "Handover request:" print message.pretty() - nfc.llcp.activate(peer); - - client = nfc.handover.HandoverClient() + client = nfc.handover.HandoverClient(llc) try: print "Trying handover"; client.connect() print "Connected for handover" except nfc.llcp.ConnectRefused: print "Handover connection refused" - nfc.llcp.shutdown() client.close() return @@ -217,12 +189,10 @@ def wps_handover_init(peer): message = client._recv() if message is None: print "No response received" - nfc.llcp.shutdown() client.close() return if message.type != "urn:nfc:wkt:Hs": print "Response was not Hs - received: " + message.type - nfc.llcp.shutdown() client.close() return @@ -241,18 +211,18 @@ def wps_handover_init(peer): print wifi.pretty() print "Remove peer" - nfc.llcp.shutdown() client.close() print "Done with handover" + global only_one + if only_one: + global continue_loop + continue_loop = False def wps_tag_read(tag, wait_remove=True): success = False if len(tag.ndef.message): - message = nfc.ndef.Message(tag.ndef.message) - print "message type " + message.type - - for record in message: + for record in tag.ndef.message: print "record type " + record.type if record.type == "application/vnd.wfa.wsc": print "WPS tag - send to wpa_supplicant" @@ -269,114 +239,137 @@ def wps_tag_read(tag, wait_remove=True): return success +def rdwr_connected_write(tag): + print "Tag found - writing" + global write_data + tag.ndef.message = str(write_data) + 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, id=None, wait_remove=True): print "Write WPS config token" - data = wpas_get_config_token(id) - if (data == None): + global write_data, write_wait_remove + write_wait_remove = wait_remove + write_data = wpas_get_config_token(id) + if write_data == None: print "Could not get WPS config token from wpa_supplicant" sys.exit(1) return - print "Touch an NFC tag" - while True: - tag = clf.poll() - if tag == None: - time.sleep(0.1) - continue - break - - print "Tag found - writing" - tag.ndef.message = data - print "Done - remove tag" - while wait_remove and tag.is_present: - time.sleep(0.1) + clf.connect(rdwr={'on-connect': rdwr_connected_write}) def wps_write_er_config_tag(clf, uuid): print "Write WPS ER config token" - data = wpas_get_er_config_token(uuid) - if (data == None): + global write_data, write_wait_remove + write_wait_remove = True + write_data = wpas_get_er_config_token(uuid) + if write_data == None: print "Could not get WPS config token from wpa_supplicant" return print "Touch an NFC tag" - while True: - tag = clf.poll() - if tag == None: - time.sleep(0.1) - continue - break - - print "Tag found - writing" - tag.ndef.message = data - print "Done - remove tag" - while tag.is_present: - time.sleep(0.1) + clf.connect(rdwr={'on-connect': rdwr_connected_write}) def wps_write_password_tag(clf, wait_remove=True): print "Write WPS password token" - data = wpas_get_password_token() - if (data == None): + global write_data, write_wait_remove + write_wait_remove = wait_remove + write_data = wpas_get_password_token() + if write_data == None: print "Could not get WPS password token from wpa_supplicant" return print "Touch an NFC tag" - while True: - tag = clf.poll() - if tag == None: + clf.connect(rdwr={'on-connect': rdwr_connected_write}) + + +def rdwr_connected(tag): + global only_one + print "Tag connected: " + str(tag) + + if tag.ndef: + print "NDEF tag: " + tag.type + try: + print tag.ndef.message.pretty() + except Exception, e: + print e + success = wps_tag_read(tag, not only_one) + if only_one and success: + global continue_loop + continue_loop = False + else: + print "Not an NDEF tag - remove tag" + while tag.is_present: time.sleep(0.1) - continue - break - - print "Tag found - writing" - tag.ndef.message = data - print "Done - remove tag" - while wait_remove and tag.is_present: - time.sleep(0.1) + return True -def find_peer(clf): - while True: - if nfc.llcp.connected(): - print "LLCP connected" - general_bytes = nfc.llcp.startup({}) - peer = clf.listen(ord(os.urandom(1)) + 250, general_bytes) - if isinstance(peer, nfc.DEP): - print "listen -> DEP"; - if peer.general_bytes.startswith("Ffm"): - print "Found DEP" - return peer - print "mismatch in general_bytes" - print peer.general_bytes +def llcp_worker(llc): + global arg_uuid + if arg_uuid is None: + wps_handover_init(llc) + return - peer = clf.poll(general_bytes) - if isinstance(peer, nfc.DEP): - print "poll -> DEP"; - if peer.general_bytes.startswith("Ffm"): - print "Found DEP" - return peer - print "mismatch in general_bytes" - print peer.general_bytes + global srv + global wait_connection + while not wait_connection and srv.sent_carrier is None: + if srv.ho_server_processing: + time.sleep(0.025) - if peer: - print "Found tag" - return peer +def llcp_startup(clf, llc): + global arg_uuid + if arg_uuid: + print "Start LLCP server" + global srv + srv = HandoverServer(llc) + if arg_uuid is "ap": + print "Trying to handle WPS handover" + srv.uuid = None + else: + print "Trying to handle WPS handover with AP " + arg_uuid + srv.uuid = arg_uuid + return llc + +def llcp_connected(llc): + print "P2P LLCP connected" + global wait_connection + wait_connection = False + global arg_uuid + if arg_uuid: + global srv + srv.start() + else: + threading.Thread(target=llcp_worker, args=(llc,)).start() + return True def main(): clf = nfc.ContactlessFrontend() try: + global arg_uuid arg_uuid = None if len(sys.argv) > 1 and sys.argv[1] != '-1': arg_uuid = sys.argv[1] + global only_one if len(sys.argv) > 1 and sys.argv[1] == '-1': only_one = True else: only_one = False + if not clf.open("usb"): + print "Could not open connection with an NFC device" + raise SystemExit + if len(sys.argv) > 1 and sys.argv[1] == "write-config": wps_write_config_tag(clf) raise SystemExit @@ -401,34 +394,21 @@ def main(): wps_write_password_tag(clf, wait_remove=False) raise SystemExit - while True: + global continue_loop + while continue_loop: print "Waiting for a tag or peer to be touched" - - tag = find_peer(clf) - if isinstance(tag, nfc.DEP): - if arg_uuid is None: - wps_handover_init(tag) - elif arg_uuid is "ap": - wps_handover_resp(tag, None) - else: - wps_handover_resp(tag, arg_uuid) - if only_one: + wait_connection = True + try: + if not clf.connect(rdwr={'on-connect': rdwr_connected}, + llcp={'on-startup': llcp_startup, + 'on-connect': llcp_connected}): break - continue + except Exception, e: + print "clf.connect failed" - if tag.ndef: - success = wps_tag_read(tag, not only_one) - if only_one: - if not success: - sys.exit(1) - break - continue - - print "Not an NDEF tag - remove tag" - if only_one: - sys.exit(1) - while tag.is_present: - time.sleep(0.1) + global srv + if only_one and srv and srv.success: + raise SystemExit except KeyboardInterrupt: raise SystemExit