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 <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-11-29 12:16:38 +02:00 committed by Jouni Malinen
parent c8373f1015
commit 6f8fa6e552
2 changed files with 209 additions and 245 deletions

View file

@ -21,6 +21,7 @@ logging.basicConfig()
import wpaspy import wpaspy
wpas_ctrl = '/var/run/hostapd' wpas_ctrl = '/var/run/hostapd'
continue_loop = True
def wpas_connect(): def wpas_connect():
ifaces = [] ifaces = []
@ -48,7 +49,9 @@ def wpas_tag_read(message):
wpas = wpas_connect() wpas = wpas_connect()
if (wpas == None): if (wpas == None):
return 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(): def wpas_get_config_token():
@ -82,8 +85,10 @@ def wpas_report_handover(req, sel):
class HandoverServer(nfc.handover.HandoverServer): class HandoverServer(nfc.handover.HandoverServer):
def __init__(self): def __init__(self, llc):
super(HandoverServer, self).__init__() super(HandoverServer, self).__init__(llc)
self.ho_server_processing = False
self.success = False
def process_request(self, request): def process_request(self, request):
print "HandoverServer - request received" print "HandoverServer - request received"
@ -95,14 +100,13 @@ class HandoverServer(nfc.handover.HandoverServer):
print "Remote carrier type: " + carrier.type print "Remote carrier type: " + carrier.type
if carrier.type == "application/vnd.wfa.wsc": if carrier.type == "application/vnd.wfa.wsc":
print "WPS carrier type match - add WPS carrier record" print "WPS carrier type match - add WPS carrier record"
self.received_carrier = carrier.record
data = wpas_get_handover_sel() data = wpas_get_handover_sel()
if data is None: if data is None:
print "Could not get handover select carrier record from hostapd" print "Could not get handover select carrier record from hostapd"
continue continue
print "Handover select carrier record from hostapd:" print "Handover select carrier record from hostapd:"
print data.encode("hex") print data.encode("hex")
self.sent_carrier = data wpas_report_handover(carrier.record, data)
message = nfc.ndef.Message(data); message = nfc.ndef.Message(data);
sel.add_carrier(message[0], "active", message[1:]) sel.add_carrier(message[0], "active", message[1:])
@ -112,132 +116,112 @@ class HandoverServer(nfc.handover.HandoverServer):
print str(sel).encode("hex") print str(sel).encode("hex")
print "Sending handover select" print "Sending handover select"
self.success = True
return sel 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): def wps_tag_read(tag):
success = False
if len(tag.ndef.message): if len(tag.ndef.message):
message = nfc.ndef.Message(tag.ndef.message) for record in tag.ndef.message:
print "message type " + message.type
for record in message:
print "record type " + record.type print "record type " + record.type
if record.type == "application/vnd.wfa.wsc": if record.type == "application/vnd.wfa.wsc":
print "WPS tag - send to hostapd" print "WPS tag - send to hostapd"
wpas_tag_read(tag.ndef.message) success = wpas_tag_read(tag.ndef.message)
break break
else: else:
print "Empty tag" print "Empty tag"
print "Remove tag" return success
while tag.is_present:
time.sleep(0.1)
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): def wps_write_config_tag(clf):
print "Write WPS config token" print "Write WPS config token"
data = wpas_get_config_token() global write_data, write_wait_remove
if (data == None): write_wait_remove = True
write_data = wpas_get_config_token()
if write_data == None:
print "Could not get WPS config token from hostapd" print "Could not get WPS config token from hostapd"
return return
print "Touch an NFC tag" print "Touch an NFC tag"
while True: clf.connect(rdwr={'on-connect': rdwr_connected_write})
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)
def wps_write_password_tag(clf): def wps_write_password_tag(clf):
print "Write WPS password token" print "Write WPS password token"
data = wpas_get_password_token() global write_data, write_wait_remove
if (data == None): write_wait_remove = True
write_data = wpas_get_password_token()
if write_data == None:
print "Could not get WPS password token from hostapd" print "Could not get WPS password token from hostapd"
return return
print "Touch an NFC tag" print "Touch an NFC tag"
while True: clf.connect(rdwr={'on-connect': rdwr_connected_write})
tag = clf.poll()
if tag == None:
time.sleep(0.1)
continue
break
print "Tag found - writing"
tag.ndef.message = data def rdwr_connected(tag):
print "Done - remove 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: while tag.is_present:
time.sleep(0.1) 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
peer = clf.poll(general_bytes) def llcp_startup(clf, llc):
if isinstance(peer, nfc.DEP): print "Start LLCP server"
print "poll -> DEP"; global srv
if peer.general_bytes.startswith("Ffm"): srv = HandoverServer(llc)
print "Found DEP" return llc
return peer
print "mismatch in general_bytes"
print peer.general_bytes
if peer: def llcp_connected(llc):
print "Found tag" print "P2P LLCP connected"
return peer global wait_connection
wait_connection = False
global srv
srv.start()
return True
def main(): def main():
clf = nfc.ContactlessFrontend() clf = nfc.ContactlessFrontend()
try: 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": if len(sys.argv) > 1 and sys.argv[1] == "write-config":
wps_write_config_tag(clf) wps_write_config_tag(clf)
raise SystemExit raise SystemExit
@ -246,21 +230,21 @@ def main():
wps_write_password_tag(clf) wps_write_password_tag(clf)
raise SystemExit raise SystemExit
while True: global continue_loop
while continue_loop:
print "Waiting for a tag or peer to be touched" 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) global srv
if isinstance(tag, nfc.DEP): if only_one and srv and srv.success:
wps_handover_resp(tag) raise SystemExit
continue
if tag.ndef:
wps_tag_read(tag)
continue
print "Not an NDEF tag - remove tag"
while tag.is_present:
time.sleep(0.1)
except KeyboardInterrupt: except KeyboardInterrupt:
raise SystemExit raise SystemExit

View file

@ -11,6 +11,7 @@ import sys
import time import time
import random import random
import StringIO import StringIO
import threading
import nfc import nfc
import nfc.ndef import nfc.ndef
@ -23,6 +24,8 @@ logging.basicConfig()
import wpaspy import wpaspy
wpas_ctrl = '/var/run/wpa_supplicant' wpas_ctrl = '/var/run/wpa_supplicant'
srv = None
continue_loop = True
def wpas_connect(): def wpas_connect():
ifaces = [] ifaces = []
@ -50,7 +53,7 @@ def wpas_tag_read(message):
wpas = wpas_connect() wpas = wpas_connect()
if (wpas == None): if (wpas == None):
return False 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 False
return True return True
@ -107,10 +110,14 @@ def wpas_report_handover(req, sel, type):
class HandoverServer(nfc.handover.HandoverServer): class HandoverServer(nfc.handover.HandoverServer):
def __init__(self): def __init__(self, llc):
super(HandoverServer, self).__init__() super(HandoverServer, self).__init__(llc)
self.sent_carrier = None
self.ho_server_processing = False
self.success = False
def process_request(self, request): def process_request(self, request):
self.ho_server_processing = True
print "HandoverServer - request received" print "HandoverServer - request received"
print "Parsed handover request: " + request.pretty() print "Parsed handover request: " + request.pretty()
@ -120,7 +127,6 @@ class HandoverServer(nfc.handover.HandoverServer):
print "Remote carrier type: " + carrier.type print "Remote carrier type: " + carrier.type
if carrier.type == "application/vnd.wfa.wsc": if carrier.type == "application/vnd.wfa.wsc":
print "WPS carrier type match - add WPS carrier record" print "WPS carrier type match - add WPS carrier record"
self.received_carrier = carrier.record
data = wpas_get_handover_sel(self.uuid) data = wpas_get_handover_sel(self.uuid)
if data is None: if data is None:
print "Could not get handover select carrier record from wpa_supplicant" 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 "Handover select carrier record from wpa_supplicant:"
print data.encode("hex") print data.encode("hex")
self.sent_carrier = data self.sent_carrier = data
wpas_report_handover(carrier.record, self.sent_carrier, "RESP")
message = nfc.ndef.Message(data); message = nfc.ndef.Message(data);
sel.add_carrier(message[0], "active", message[1:]) sel.add_carrier(message[0], "active", message[1:])
@ -137,43 +144,11 @@ class HandoverServer(nfc.handover.HandoverServer):
print str(sel).encode("hex") print str(sel).encode("hex")
print "Sending handover select" print "Sending handover select"
self.success = True
return sel return sel
def wps_handover_resp(peer, uuid): def wps_handover_init(llc):
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):
print "Trying to initiate WPS handover" print "Trying to initiate WPS handover"
data = wpas_get_handover_req() data = wpas_get_handover_req()
@ -195,16 +170,13 @@ def wps_handover_init(peer):
print "Handover request:" print "Handover request:"
print message.pretty() print message.pretty()
nfc.llcp.activate(peer); client = nfc.handover.HandoverClient(llc)
client = nfc.handover.HandoverClient()
try: try:
print "Trying handover"; print "Trying handover";
client.connect() client.connect()
print "Connected for handover" print "Connected for handover"
except nfc.llcp.ConnectRefused: except nfc.llcp.ConnectRefused:
print "Handover connection refused" print "Handover connection refused"
nfc.llcp.shutdown()
client.close() client.close()
return return
@ -217,12 +189,10 @@ def wps_handover_init(peer):
message = client._recv() message = client._recv()
if message is None: if message is None:
print "No response received" print "No response received"
nfc.llcp.shutdown()
client.close() client.close()
return return
if message.type != "urn:nfc:wkt:Hs": if message.type != "urn:nfc:wkt:Hs":
print "Response was not Hs - received: " + message.type print "Response was not Hs - received: " + message.type
nfc.llcp.shutdown()
client.close() client.close()
return return
@ -241,18 +211,18 @@ def wps_handover_init(peer):
print wifi.pretty() print wifi.pretty()
print "Remove peer" print "Remove peer"
nfc.llcp.shutdown()
client.close() client.close()
print "Done with handover" print "Done with handover"
global only_one
if only_one:
global continue_loop
continue_loop = False
def wps_tag_read(tag, wait_remove=True): def wps_tag_read(tag, wait_remove=True):
success = False success = False
if len(tag.ndef.message): if len(tag.ndef.message):
message = nfc.ndef.Message(tag.ndef.message) for record in tag.ndef.message:
print "message type " + message.type
for record in message:
print "record type " + record.type print "record type " + record.type
if record.type == "application/vnd.wfa.wsc": if record.type == "application/vnd.wfa.wsc":
print "WPS tag - send to wpa_supplicant" print "WPS tag - send to wpa_supplicant"
@ -269,114 +239,137 @@ def wps_tag_read(tag, wait_remove=True):
return success 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): def wps_write_config_tag(clf, id=None, wait_remove=True):
print "Write WPS config token" print "Write WPS config token"
data = wpas_get_config_token(id) global write_data, write_wait_remove
if (data == None): 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" print "Could not get WPS config token from wpa_supplicant"
sys.exit(1) sys.exit(1)
return return
print "Touch an NFC tag" print "Touch an NFC tag"
while True: clf.connect(rdwr={'on-connect': rdwr_connected_write})
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)
def wps_write_er_config_tag(clf, uuid): def wps_write_er_config_tag(clf, uuid):
print "Write WPS ER config token" print "Write WPS ER config token"
data = wpas_get_er_config_token(uuid) global write_data, write_wait_remove
if (data == None): 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" print "Could not get WPS config token from wpa_supplicant"
return return
print "Touch an NFC tag" print "Touch an NFC tag"
while True: clf.connect(rdwr={'on-connect': rdwr_connected_write})
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)
def wps_write_password_tag(clf, wait_remove=True): def wps_write_password_tag(clf, wait_remove=True):
print "Write WPS password token" print "Write WPS password token"
data = wpas_get_password_token() global write_data, write_wait_remove
if (data == None): 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" print "Could not get WPS password token from wpa_supplicant"
return return
print "Touch an NFC tag" print "Touch an NFC tag"
while True: clf.connect(rdwr={'on-connect': rdwr_connected_write})
tag = clf.poll()
if tag == None:
time.sleep(0.1) def rdwr_connected(tag):
continue global only_one
break print "Tag connected: " + str(tag)
print "Tag found - writing" if tag.ndef:
tag.ndef.message = data print "NDEF tag: " + tag.type
print "Done - remove tag" try:
while wait_remove and tag.is_present: 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) time.sleep(0.1)
return True
def find_peer(clf): def llcp_worker(llc):
while True: global arg_uuid
if nfc.llcp.connected(): if arg_uuid is None:
print "LLCP connected" wps_handover_init(llc)
general_bytes = nfc.llcp.startup({}) return
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
peer = clf.poll(general_bytes) global srv
if isinstance(peer, nfc.DEP): global wait_connection
print "poll -> DEP"; while not wait_connection and srv.sent_carrier is None:
if peer.general_bytes.startswith("Ffm"): if srv.ho_server_processing:
print "Found DEP" time.sleep(0.025)
return peer
print "mismatch in general_bytes"
print peer.general_bytes
if peer: def llcp_startup(clf, llc):
print "Found tag" global arg_uuid
return peer 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(): def main():
clf = nfc.ContactlessFrontend() clf = nfc.ContactlessFrontend()
try: try:
global arg_uuid
arg_uuid = None arg_uuid = None
if len(sys.argv) > 1 and sys.argv[1] != '-1': if len(sys.argv) > 1 and sys.argv[1] != '-1':
arg_uuid = sys.argv[1] arg_uuid = sys.argv[1]
global only_one
if len(sys.argv) > 1 and sys.argv[1] == '-1': if len(sys.argv) > 1 and sys.argv[1] == '-1':
only_one = True only_one = True
else: else:
only_one = False 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": if len(sys.argv) > 1 and sys.argv[1] == "write-config":
wps_write_config_tag(clf) wps_write_config_tag(clf)
raise SystemExit raise SystemExit
@ -401,34 +394,21 @@ def main():
wps_write_password_tag(clf, wait_remove=False) wps_write_password_tag(clf, wait_remove=False)
raise SystemExit raise SystemExit
while True: global continue_loop
while continue_loop:
print "Waiting for a tag or peer to be touched" print "Waiting for a tag or peer to be touched"
wait_connection = True
tag = find_peer(clf) try:
if isinstance(tag, nfc.DEP): if not clf.connect(rdwr={'on-connect': rdwr_connected},
if arg_uuid is None: llcp={'on-startup': llcp_startup,
wps_handover_init(tag) 'on-connect': llcp_connected}):
elif arg_uuid is "ap":
wps_handover_resp(tag, None)
else:
wps_handover_resp(tag, arg_uuid)
if only_one:
break break
continue except Exception, e:
print "clf.connect failed"
if tag.ndef: global srv
success = wps_tag_read(tag, not only_one) if only_one and srv and srv.success:
if only_one: raise SystemExit
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)
except KeyboardInterrupt: except KeyboardInterrupt:
raise SystemExit raise SystemExit