xref: /freebsd-src/contrib/wpa/wpa_supplicant/examples/wps-nfc.py (revision 7648bc9fee8dec6cb3c4941e0165a930fbe8dcb0)
1f05cddf9SRui Paulo#!/usr/bin/python
2f05cddf9SRui Paulo#
3f05cddf9SRui Paulo# Example nfcpy to wpa_supplicant wrapper for WPS NFC operations
45b9c547cSRui Paulo# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
5f05cddf9SRui Paulo#
6f05cddf9SRui Paulo# This software may be distributed under the terms of the BSD license.
7f05cddf9SRui Paulo# See README for more details.
8f05cddf9SRui Paulo
9f05cddf9SRui Pauloimport os
10f05cddf9SRui Pauloimport sys
11f05cddf9SRui Pauloimport time
125b9c547cSRui Pauloimport random
135b9c547cSRui Pauloimport threading
145b9c547cSRui Pauloimport argparse
15f05cddf9SRui Paulo
16f05cddf9SRui Pauloimport nfc
17f05cddf9SRui Pauloimport nfc.ndef
18f05cddf9SRui Pauloimport nfc.llcp
19f05cddf9SRui Pauloimport nfc.handover
20f05cddf9SRui Paulo
215b9c547cSRui Pauloimport logging
225b9c547cSRui Paulo
235b9c547cSRui Pauloimport wpaspy
24f05cddf9SRui Paulo
25f05cddf9SRui Paulowpas_ctrl = '/var/run/wpa_supplicant'
265b9c547cSRui Paulosrv = None
275b9c547cSRui Paulocontinue_loop = True
285b9c547cSRui Pauloterminate_now = False
295b9c547cSRui Paulosummary_file = None
305b9c547cSRui Paulosuccess_file = None
315b9c547cSRui Paulo
325b9c547cSRui Paulodef summary(txt):
33*4bc52338SCy Schubert    print(txt)
345b9c547cSRui Paulo    if summary_file:
355b9c547cSRui Paulo        with open(summary_file, 'a') as f:
365b9c547cSRui Paulo            f.write(txt + "\n")
375b9c547cSRui Paulo
385b9c547cSRui Paulodef success_report(txt):
395b9c547cSRui Paulo    summary(txt)
405b9c547cSRui Paulo    if success_file:
415b9c547cSRui Paulo        with open(success_file, 'a') as f:
425b9c547cSRui Paulo            f.write(txt + "\n")
43f05cddf9SRui Paulo
44f05cddf9SRui Paulodef wpas_connect():
45f05cddf9SRui Paulo    ifaces = []
46f05cddf9SRui Paulo    if os.path.isdir(wpas_ctrl):
47f05cddf9SRui Paulo        try:
48f05cddf9SRui Paulo            ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
49*4bc52338SCy Schubert        except OSError as error:
50*4bc52338SCy Schubert            print("Could not find wpa_supplicant: ", error)
51f05cddf9SRui Paulo            return None
52f05cddf9SRui Paulo
53f05cddf9SRui Paulo    if len(ifaces) < 1:
54*4bc52338SCy Schubert        print("No wpa_supplicant control interface found")
55f05cddf9SRui Paulo        return None
56f05cddf9SRui Paulo
57f05cddf9SRui Paulo    for ctrl in ifaces:
58f05cddf9SRui Paulo        try:
595b9c547cSRui Paulo            wpas = wpaspy.Ctrl(ctrl)
60f05cddf9SRui Paulo            return wpas
61*4bc52338SCy Schubert        except Exception as e:
62f05cddf9SRui Paulo            pass
63f05cddf9SRui Paulo    return None
64f05cddf9SRui Paulo
65f05cddf9SRui Paulo
66f05cddf9SRui Paulodef wpas_tag_read(message):
67f05cddf9SRui Paulo    wpas = wpas_connect()
68f05cddf9SRui Paulo    if (wpas == None):
695b9c547cSRui Paulo        return False
705b9c547cSRui Paulo    if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")):
715b9c547cSRui Paulo        return False
725b9c547cSRui Paulo    return True
73f05cddf9SRui Paulo
745b9c547cSRui Paulodef wpas_get_config_token(id=None):
755b9c547cSRui Paulo    wpas = wpas_connect()
765b9c547cSRui Paulo    if (wpas == None):
775b9c547cSRui Paulo        return None
785b9c547cSRui Paulo    if id:
795b9c547cSRui Paulo        ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id)
805b9c547cSRui Paulo    else:
815b9c547cSRui Paulo        ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF")
825b9c547cSRui Paulo    if "FAIL" in ret:
835b9c547cSRui Paulo        return None
845b9c547cSRui Paulo    return ret.rstrip().decode("hex")
855b9c547cSRui Paulo
865b9c547cSRui Paulo
875b9c547cSRui Paulodef wpas_get_er_config_token(uuid):
885b9c547cSRui Paulo    wpas = wpas_connect()
895b9c547cSRui Paulo    if (wpas == None):
905b9c547cSRui Paulo        return None
915b9c547cSRui Paulo    ret = wpas.request("WPS_ER_NFC_CONFIG_TOKEN NDEF " + uuid)
925b9c547cSRui Paulo    if "FAIL" in ret:
935b9c547cSRui Paulo        return None
945b9c547cSRui Paulo    return ret.rstrip().decode("hex")
955b9c547cSRui Paulo
965b9c547cSRui Paulo
975b9c547cSRui Paulodef wpas_get_password_token():
985b9c547cSRui Paulo    wpas = wpas_connect()
995b9c547cSRui Paulo    if (wpas == None):
1005b9c547cSRui Paulo        return None
1015b9c547cSRui Paulo    ret = wpas.request("WPS_NFC_TOKEN NDEF")
1025b9c547cSRui Paulo    if "FAIL" in ret:
1035b9c547cSRui Paulo        return None
1045b9c547cSRui Paulo    return ret.rstrip().decode("hex")
105f05cddf9SRui Paulo
106f05cddf9SRui Paulodef wpas_get_handover_req():
107f05cddf9SRui Paulo    wpas = wpas_connect()
108f05cddf9SRui Paulo    if (wpas == None):
109f05cddf9SRui Paulo        return None
1105b9c547cSRui Paulo    ret = wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR")
1115b9c547cSRui Paulo    if "FAIL" in ret:
1125b9c547cSRui Paulo        return None
1135b9c547cSRui Paulo    return ret.rstrip().decode("hex")
114f05cddf9SRui Paulo
115f05cddf9SRui Paulo
1165b9c547cSRui Paulodef wpas_get_handover_sel(uuid):
117f05cddf9SRui Paulo    wpas = wpas_connect()
118f05cddf9SRui Paulo    if (wpas == None):
1195b9c547cSRui Paulo        return None
1205b9c547cSRui Paulo    if uuid is None:
1215b9c547cSRui Paulo        res = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
1225b9c547cSRui Paulo    else:
1235b9c547cSRui Paulo	res = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + uuid).rstrip()
1245b9c547cSRui Paulo    if "FAIL" in res:
1255b9c547cSRui Paulo	return None
1265b9c547cSRui Paulo    return res.decode("hex")
127f05cddf9SRui Paulo
128f05cddf9SRui Paulo
1295b9c547cSRui Paulodef wpas_report_handover(req, sel, type):
1305b9c547cSRui Paulo    wpas = wpas_connect()
1315b9c547cSRui Paulo    if (wpas == None):
1325b9c547cSRui Paulo        return None
1335b9c547cSRui Paulo    return wpas.request("NFC_REPORT_HANDOVER " + type + " WPS " +
1345b9c547cSRui Paulo                        str(req).encode("hex") + " " +
1355b9c547cSRui Paulo                        str(sel).encode("hex"))
1365b9c547cSRui Paulo
1375b9c547cSRui Paulo
1385b9c547cSRui Pauloclass HandoverServer(nfc.handover.HandoverServer):
1395b9c547cSRui Paulo    def __init__(self, llc):
1405b9c547cSRui Paulo        super(HandoverServer, self).__init__(llc)
1415b9c547cSRui Paulo        self.sent_carrier = None
1425b9c547cSRui Paulo        self.ho_server_processing = False
1435b9c547cSRui Paulo        self.success = False
1445b9c547cSRui Paulo
1455b9c547cSRui Paulo    # override to avoid parser error in request/response.pretty() in nfcpy
1465b9c547cSRui Paulo    # due to new WSC handover format
1475b9c547cSRui Paulo    def _process_request(self, request):
1485b9c547cSRui Paulo        summary("received handover request {}".format(request.type))
1495b9c547cSRui Paulo        response = nfc.ndef.Message("\xd1\x02\x01Hs\x12")
1505b9c547cSRui Paulo        if not request.type == 'urn:nfc:wkt:Hr':
1515b9c547cSRui Paulo            summary("not a handover request")
1525b9c547cSRui Paulo        else:
1535b9c547cSRui Paulo            try:
1545b9c547cSRui Paulo                request = nfc.ndef.HandoverRequestMessage(request)
1555b9c547cSRui Paulo            except nfc.ndef.DecodeError as e:
1565b9c547cSRui Paulo                summary("error decoding 'Hr' message: {}".format(e))
1575b9c547cSRui Paulo            else:
1585b9c547cSRui Paulo                response = self.process_request(request)
1595b9c547cSRui Paulo        summary("send handover response {}".format(response.type))
1605b9c547cSRui Paulo        return response
1615b9c547cSRui Paulo
1625b9c547cSRui Paulo    def process_request(self, request):
1635b9c547cSRui Paulo        self.ho_server_processing = True
1645b9c547cSRui Paulo        summary("HandoverServer - request received")
1655b9c547cSRui Paulo        try:
166*4bc52338SCy Schubert            print("Parsed handover request: " + request.pretty())
167*4bc52338SCy Schubert        except Exception as e:
168*4bc52338SCy Schubert            print(e)
1695b9c547cSRui Paulo
1705b9c547cSRui Paulo        sel = nfc.ndef.HandoverSelectMessage(version="1.2")
1715b9c547cSRui Paulo
1725b9c547cSRui Paulo        for carrier in request.carriers:
173*4bc52338SCy Schubert            print("Remote carrier type: " + carrier.type)
1745b9c547cSRui Paulo            if carrier.type == "application/vnd.wfa.wsc":
1755b9c547cSRui Paulo                summary("WPS carrier type match - add WPS carrier record")
1765b9c547cSRui Paulo                data = wpas_get_handover_sel(self.uuid)
1775b9c547cSRui Paulo                if data is None:
1785b9c547cSRui Paulo                    summary("Could not get handover select carrier record from wpa_supplicant")
1795b9c547cSRui Paulo                    continue
180*4bc52338SCy Schubert                print("Handover select carrier record from wpa_supplicant:")
181*4bc52338SCy Schubert                print(data.encode("hex"))
1825b9c547cSRui Paulo                self.sent_carrier = data
1835b9c547cSRui Paulo                if "OK" in wpas_report_handover(carrier.record, self.sent_carrier, "RESP"):
1845b9c547cSRui Paulo                    success_report("Handover reported successfully (responder)")
1855b9c547cSRui Paulo                else:
1865b9c547cSRui Paulo                    summary("Handover report rejected (responder)")
1875b9c547cSRui Paulo
1885b9c547cSRui Paulo                message = nfc.ndef.Message(data);
1895b9c547cSRui Paulo                sel.add_carrier(message[0], "active", message[1:])
1905b9c547cSRui Paulo
191*4bc52338SCy Schubert        print("Handover select:")
1925b9c547cSRui Paulo        try:
193*4bc52338SCy Schubert            print(sel.pretty())
194*4bc52338SCy Schubert        except Exception as e:
195*4bc52338SCy Schubert            print(e)
196*4bc52338SCy Schubert        print(str(sel).encode("hex"))
1975b9c547cSRui Paulo
1985b9c547cSRui Paulo        summary("Sending handover select")
1995b9c547cSRui Paulo        self.success = True
2005b9c547cSRui Paulo        return sel
2015b9c547cSRui Paulo
2025b9c547cSRui Paulo
2035b9c547cSRui Paulodef wps_handover_init(llc):
2045b9c547cSRui Paulo    summary("Trying to initiate WPS handover")
205f05cddf9SRui Paulo
206f05cddf9SRui Paulo    data = wpas_get_handover_req()
207f05cddf9SRui Paulo    if (data == None):
2085b9c547cSRui Paulo        summary("Could not get handover request carrier record from wpa_supplicant")
209f05cddf9SRui Paulo        return
210*4bc52338SCy Schubert    print("Handover request carrier record from wpa_supplicant: " + data.encode("hex"))
211f05cddf9SRui Paulo
2125b9c547cSRui Paulo    message = nfc.ndef.HandoverRequestMessage(version="1.2")
2135b9c547cSRui Paulo    message.nonce = random.randint(0, 0xffff)
2145b9c547cSRui Paulo    datamsg = nfc.ndef.Message(data)
2155b9c547cSRui Paulo    message.add_carrier(datamsg[0], "active", datamsg[1:])
216f05cddf9SRui Paulo
217*4bc52338SCy Schubert    print("Handover request:")
218f05cddf9SRui Paulo    try:
219*4bc52338SCy Schubert        print(message.pretty())
220*4bc52338SCy Schubert    except Exception as e:
221*4bc52338SCy Schubert        print(e)
222*4bc52338SCy Schubert    print(str(message).encode("hex"))
2235b9c547cSRui Paulo
2245b9c547cSRui Paulo    client = nfc.handover.HandoverClient(llc)
2255b9c547cSRui Paulo    try:
2265b9c547cSRui Paulo        summary("Trying to initiate NFC connection handover")
227f05cddf9SRui Paulo        client.connect()
2285b9c547cSRui Paulo        summary("Connected for handover")
229f05cddf9SRui Paulo    except nfc.llcp.ConnectRefused:
2305b9c547cSRui Paulo        summary("Handover connection refused")
2315b9c547cSRui Paulo        client.close()
2325b9c547cSRui Paulo        return
233*4bc52338SCy Schubert    except Exception as e:
2345b9c547cSRui Paulo        summary("Other exception: " + str(e))
235f05cddf9SRui Paulo        client.close()
236f05cddf9SRui Paulo        return
237f05cddf9SRui Paulo
2385b9c547cSRui Paulo    summary("Sending handover request")
239f05cddf9SRui Paulo
240f05cddf9SRui Paulo    if not client.send(message):
2415b9c547cSRui Paulo        summary("Failed to send handover request")
2425b9c547cSRui Paulo        client.close()
2435b9c547cSRui Paulo        return
244f05cddf9SRui Paulo
2455b9c547cSRui Paulo    summary("Receiving handover response")
246f05cddf9SRui Paulo    message = client._recv()
2475b9c547cSRui Paulo    if message is None:
2485b9c547cSRui Paulo        summary("No response received")
2495b9c547cSRui Paulo        client.close()
2505b9c547cSRui Paulo        return
2515b9c547cSRui Paulo    if message.type != "urn:nfc:wkt:Hs":
2525b9c547cSRui Paulo        summary("Response was not Hs - received: " + message.type)
2535b9c547cSRui Paulo        client.close()
2545b9c547cSRui Paulo        return
2555b9c547cSRui Paulo
256*4bc52338SCy Schubert    print("Received message")
2575b9c547cSRui Paulo    try:
258*4bc52338SCy Schubert        print(message.pretty())
259*4bc52338SCy Schubert    except Exception as e:
260*4bc52338SCy Schubert        print(e)
261*4bc52338SCy Schubert    print(str(message).encode("hex"))
2625b9c547cSRui Paulo    message = nfc.ndef.HandoverSelectMessage(message)
2635b9c547cSRui Paulo    summary("Handover select received")
2645b9c547cSRui Paulo    try:
265*4bc52338SCy Schubert        print(message.pretty())
266*4bc52338SCy Schubert    except Exception as e:
267*4bc52338SCy Schubert        print(e)
2685b9c547cSRui Paulo
2695b9c547cSRui Paulo    for carrier in message.carriers:
270*4bc52338SCy Schubert        print("Remote carrier type: " + carrier.type)
2715b9c547cSRui Paulo        if carrier.type == "application/vnd.wfa.wsc":
272*4bc52338SCy Schubert            print("WPS carrier type match - send to wpa_supplicant")
2735b9c547cSRui Paulo            if "OK" in wpas_report_handover(data, carrier.record, "INIT"):
2745b9c547cSRui Paulo                success_report("Handover reported successfully (initiator)")
2755b9c547cSRui Paulo            else:
2765b9c547cSRui Paulo                summary("Handover report rejected (initiator)")
2775b9c547cSRui Paulo            # nfcpy does not support the new format..
2785b9c547cSRui Paulo            #wifi = nfc.ndef.WifiConfigRecord(carrier.record)
2795b9c547cSRui Paulo            #print wifi.pretty()
280f05cddf9SRui Paulo
281*4bc52338SCy Schubert    print("Remove peer")
282f05cddf9SRui Paulo    client.close()
283*4bc52338SCy Schubert    print("Done with handover")
2845b9c547cSRui Paulo    global only_one
2855b9c547cSRui Paulo    if only_one:
2865b9c547cSRui Paulo        global continue_loop
2875b9c547cSRui Paulo        continue_loop = False
288f05cddf9SRui Paulo
2895b9c547cSRui Paulo    global no_wait
2905b9c547cSRui Paulo    if no_wait:
291*4bc52338SCy Schubert        print("Trying to exit..")
2925b9c547cSRui Paulo        global terminate_now
2935b9c547cSRui Paulo        terminate_now = True
294f05cddf9SRui Paulo
2955b9c547cSRui Paulodef wps_tag_read(tag, wait_remove=True):
2965b9c547cSRui Paulo    success = False
297f05cddf9SRui Paulo    if len(tag.ndef.message):
2985b9c547cSRui Paulo        for record in tag.ndef.message:
299*4bc52338SCy Schubert            print("record type " + record.type)
300f05cddf9SRui Paulo            if record.type == "application/vnd.wfa.wsc":
3015b9c547cSRui Paulo                summary("WPS tag - send to wpa_supplicant")
3025b9c547cSRui Paulo                success = wpas_tag_read(tag.ndef.message)
303f05cddf9SRui Paulo                break
304f05cddf9SRui Paulo    else:
3055b9c547cSRui Paulo        summary("Empty tag")
306f05cddf9SRui Paulo
3075b9c547cSRui Paulo    if success:
3085b9c547cSRui Paulo        success_report("Tag read succeeded")
3095b9c547cSRui Paulo
3105b9c547cSRui Paulo    if wait_remove:
311*4bc52338SCy Schubert        print("Remove tag")
312f05cddf9SRui Paulo        while tag.is_present:
313f05cddf9SRui Paulo            time.sleep(0.1)
314f05cddf9SRui Paulo
3155b9c547cSRui Paulo    return success
3165b9c547cSRui Paulo
3175b9c547cSRui Paulo
3185b9c547cSRui Paulodef rdwr_connected_write(tag):
3195b9c547cSRui Paulo    summary("Tag found - writing - " + str(tag))
3205b9c547cSRui Paulo    global write_data
3215b9c547cSRui Paulo    tag.ndef.message = str(write_data)
3225b9c547cSRui Paulo    success_report("Tag write succeeded")
323*4bc52338SCy Schubert    print("Done - remove tag")
3245b9c547cSRui Paulo    global only_one
3255b9c547cSRui Paulo    if only_one:
3265b9c547cSRui Paulo        global continue_loop
3275b9c547cSRui Paulo        continue_loop = False
3285b9c547cSRui Paulo    global write_wait_remove
3295b9c547cSRui Paulo    while write_wait_remove and tag.is_present:
3305b9c547cSRui Paulo        time.sleep(0.1)
3315b9c547cSRui Paulo
3325b9c547cSRui Paulodef wps_write_config_tag(clf, id=None, wait_remove=True):
333*4bc52338SCy Schubert    print("Write WPS config token")
3345b9c547cSRui Paulo    global write_data, write_wait_remove
3355b9c547cSRui Paulo    write_wait_remove = wait_remove
3365b9c547cSRui Paulo    write_data = wpas_get_config_token(id)
3375b9c547cSRui Paulo    if write_data == None:
338*4bc52338SCy Schubert        print("Could not get WPS config token from wpa_supplicant")
3395b9c547cSRui Paulo        sys.exit(1)
3405b9c547cSRui Paulo        return
341*4bc52338SCy Schubert    print("Touch an NFC tag")
3425b9c547cSRui Paulo    clf.connect(rdwr={'on-connect': rdwr_connected_write})
3435b9c547cSRui Paulo
3445b9c547cSRui Paulo
3455b9c547cSRui Paulodef wps_write_er_config_tag(clf, uuid, wait_remove=True):
346*4bc52338SCy Schubert    print("Write WPS ER config token")
3475b9c547cSRui Paulo    global write_data, write_wait_remove
3485b9c547cSRui Paulo    write_wait_remove = wait_remove
3495b9c547cSRui Paulo    write_data = wpas_get_er_config_token(uuid)
3505b9c547cSRui Paulo    if write_data == None:
351*4bc52338SCy Schubert        print("Could not get WPS config token from wpa_supplicant")
3525b9c547cSRui Paulo        return
3535b9c547cSRui Paulo
354*4bc52338SCy Schubert    print("Touch an NFC tag")
3555b9c547cSRui Paulo    clf.connect(rdwr={'on-connect': rdwr_connected_write})
3565b9c547cSRui Paulo
3575b9c547cSRui Paulo
3585b9c547cSRui Paulodef wps_write_password_tag(clf, wait_remove=True):
359*4bc52338SCy Schubert    print("Write WPS password token")
3605b9c547cSRui Paulo    global write_data, write_wait_remove
3615b9c547cSRui Paulo    write_wait_remove = wait_remove
3625b9c547cSRui Paulo    write_data = wpas_get_password_token()
3635b9c547cSRui Paulo    if write_data == None:
364*4bc52338SCy Schubert        print("Could not get WPS password token from wpa_supplicant")
3655b9c547cSRui Paulo        return
3665b9c547cSRui Paulo
367*4bc52338SCy Schubert    print("Touch an NFC tag")
3685b9c547cSRui Paulo    clf.connect(rdwr={'on-connect': rdwr_connected_write})
3695b9c547cSRui Paulo
3705b9c547cSRui Paulo
3715b9c547cSRui Paulodef rdwr_connected(tag):
3725b9c547cSRui Paulo    global only_one, no_wait
3735b9c547cSRui Paulo    summary("Tag connected: " + str(tag))
3745b9c547cSRui Paulo
3755b9c547cSRui Paulo    if tag.ndef:
376*4bc52338SCy Schubert        print("NDEF tag: " + tag.type)
3775b9c547cSRui Paulo        try:
378*4bc52338SCy Schubert            print(tag.ndef.message.pretty())
379*4bc52338SCy Schubert        except Exception as e:
380*4bc52338SCy Schubert            print(e)
3815b9c547cSRui Paulo        success = wps_tag_read(tag, not only_one)
3825b9c547cSRui Paulo        if only_one and success:
3835b9c547cSRui Paulo            global continue_loop
3845b9c547cSRui Paulo            continue_loop = False
3855b9c547cSRui Paulo    else:
3865b9c547cSRui Paulo        summary("Not an NDEF tag - remove tag")
3875b9c547cSRui Paulo        return True
3885b9c547cSRui Paulo
3895b9c547cSRui Paulo    return not no_wait
3905b9c547cSRui Paulo
3915b9c547cSRui Paulo
3925b9c547cSRui Paulodef llcp_worker(llc):
3935b9c547cSRui Paulo    global arg_uuid
3945b9c547cSRui Paulo    if arg_uuid is None:
3955b9c547cSRui Paulo        wps_handover_init(llc)
396*4bc52338SCy Schubert        print("Exiting llcp_worker thread")
3975b9c547cSRui Paulo        return
3985b9c547cSRui Paulo
3995b9c547cSRui Paulo    global srv
4005b9c547cSRui Paulo    global wait_connection
4015b9c547cSRui Paulo    while not wait_connection and srv.sent_carrier is None:
4025b9c547cSRui Paulo        if srv.ho_server_processing:
4035b9c547cSRui Paulo            time.sleep(0.025)
4045b9c547cSRui Paulo
4055b9c547cSRui Paulodef llcp_startup(clf, llc):
4065b9c547cSRui Paulo    global arg_uuid
4075b9c547cSRui Paulo    if arg_uuid:
408*4bc52338SCy Schubert        print("Start LLCP server")
4095b9c547cSRui Paulo        global srv
4105b9c547cSRui Paulo        srv = HandoverServer(llc)
4115b9c547cSRui Paulo        if arg_uuid is "ap":
412*4bc52338SCy Schubert            print("Trying to handle WPS handover")
4135b9c547cSRui Paulo            srv.uuid = None
4145b9c547cSRui Paulo        else:
415*4bc52338SCy Schubert            print("Trying to handle WPS handover with AP " + arg_uuid)
4165b9c547cSRui Paulo            srv.uuid = arg_uuid
4175b9c547cSRui Paulo    return llc
4185b9c547cSRui Paulo
4195b9c547cSRui Paulodef llcp_connected(llc):
420*4bc52338SCy Schubert    print("P2P LLCP connected")
4215b9c547cSRui Paulo    global wait_connection
4225b9c547cSRui Paulo    wait_connection = False
4235b9c547cSRui Paulo    global arg_uuid
4245b9c547cSRui Paulo    if arg_uuid:
4255b9c547cSRui Paulo        global srv
4265b9c547cSRui Paulo        srv.start()
4275b9c547cSRui Paulo    else:
4285b9c547cSRui Paulo        threading.Thread(target=llcp_worker, args=(llc,)).start()
429*4bc52338SCy Schubert    print("llcp_connected returning")
4305b9c547cSRui Paulo    return True
4315b9c547cSRui Paulo
4325b9c547cSRui Paulo
4335b9c547cSRui Paulodef terminate_loop():
4345b9c547cSRui Paulo    global terminate_now
4355b9c547cSRui Paulo    return terminate_now
436f05cddf9SRui Paulo
437f05cddf9SRui Paulodef main():
438f05cddf9SRui Paulo    clf = nfc.ContactlessFrontend()
439f05cddf9SRui Paulo
4405b9c547cSRui Paulo    parser = argparse.ArgumentParser(description='nfcpy to wpa_supplicant integration for WPS NFC operations')
4415b9c547cSRui Paulo    parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
4425b9c547cSRui Paulo                        action='store_const', dest='loglevel',
4435b9c547cSRui Paulo                        help='verbose debug output')
4445b9c547cSRui Paulo    parser.add_argument('-q', const=logging.WARNING, action='store_const',
4455b9c547cSRui Paulo                        dest='loglevel', help='be quiet')
4465b9c547cSRui Paulo    parser.add_argument('--only-one', '-1', action='store_true',
4475b9c547cSRui Paulo                        help='run only one operation and exit')
4485b9c547cSRui Paulo    parser.add_argument('--no-wait', action='store_true',
4495b9c547cSRui Paulo                        help='do not wait for tag to be removed before exiting')
4505b9c547cSRui Paulo    parser.add_argument('--uuid',
4515b9c547cSRui Paulo                        help='UUID of an AP (used for WPS ER operations)')
4525b9c547cSRui Paulo    parser.add_argument('--id',
4535b9c547cSRui Paulo                        help='network id (used for WPS ER operations)')
4545b9c547cSRui Paulo    parser.add_argument('--summary',
4555b9c547cSRui Paulo                        help='summary file for writing status updates')
4565b9c547cSRui Paulo    parser.add_argument('--success',
4575b9c547cSRui Paulo                        help='success file for writing success update')
4585b9c547cSRui Paulo    parser.add_argument('command', choices=['write-config',
4595b9c547cSRui Paulo                                            'write-er-config',
4605b9c547cSRui Paulo                                            'write-password'],
4615b9c547cSRui Paulo                        nargs='?')
4625b9c547cSRui Paulo    args = parser.parse_args()
4635b9c547cSRui Paulo
4645b9c547cSRui Paulo    global arg_uuid
4655b9c547cSRui Paulo    arg_uuid = args.uuid
4665b9c547cSRui Paulo
4675b9c547cSRui Paulo    global only_one
4685b9c547cSRui Paulo    only_one = args.only_one
4695b9c547cSRui Paulo
4705b9c547cSRui Paulo    global no_wait
4715b9c547cSRui Paulo    no_wait = args.no_wait
4725b9c547cSRui Paulo
4735b9c547cSRui Paulo    if args.summary:
4745b9c547cSRui Paulo        global summary_file
4755b9c547cSRui Paulo        summary_file = args.summary
4765b9c547cSRui Paulo
4775b9c547cSRui Paulo    if args.success:
4785b9c547cSRui Paulo        global success_file
4795b9c547cSRui Paulo        success_file = args.success
4805b9c547cSRui Paulo
4815b9c547cSRui Paulo    logging.basicConfig(level=args.loglevel)
4825b9c547cSRui Paulo
483f05cddf9SRui Paulo    try:
4845b9c547cSRui Paulo        if not clf.open("usb"):
485*4bc52338SCy Schubert            print("Could not open connection with an NFC device")
4865b9c547cSRui Paulo            raise SystemExit
4875b9c547cSRui Paulo
4885b9c547cSRui Paulo        if args.command == "write-config":
4895b9c547cSRui Paulo            wps_write_config_tag(clf, id=args.id, wait_remove=not args.no_wait)
4905b9c547cSRui Paulo            raise SystemExit
4915b9c547cSRui Paulo
4925b9c547cSRui Paulo        if args.command == "write-er-config":
4935b9c547cSRui Paulo            wps_write_er_config_tag(clf, args.uuid, wait_remove=not args.no_wait)
4945b9c547cSRui Paulo            raise SystemExit
4955b9c547cSRui Paulo
4965b9c547cSRui Paulo        if args.command == "write-password":
4975b9c547cSRui Paulo            wps_write_password_tag(clf, wait_remove=not args.no_wait)
4985b9c547cSRui Paulo            raise SystemExit
4995b9c547cSRui Paulo
5005b9c547cSRui Paulo        global continue_loop
5015b9c547cSRui Paulo        while continue_loop:
502*4bc52338SCy Schubert            print("Waiting for a tag or peer to be touched")
5035b9c547cSRui Paulo            wait_connection = True
5045b9c547cSRui Paulo            try:
5055b9c547cSRui Paulo                if not clf.connect(rdwr={'on-connect': rdwr_connected},
5065b9c547cSRui Paulo                                   llcp={'on-startup': llcp_startup,
5075b9c547cSRui Paulo                                         'on-connect': llcp_connected},
5085b9c547cSRui Paulo                                   terminate=terminate_loop):
509f05cddf9SRui Paulo                    break
510*4bc52338SCy Schubert            except Exception as e:
511*4bc52338SCy Schubert                print("clf.connect failed")
512f05cddf9SRui Paulo
5135b9c547cSRui Paulo            global srv
5145b9c547cSRui Paulo            if only_one and srv and srv.success:
5155b9c547cSRui Paulo                raise SystemExit
516f05cddf9SRui Paulo
517f05cddf9SRui Paulo    except KeyboardInterrupt:
518f05cddf9SRui Paulo        raise SystemExit
519f05cddf9SRui Paulo    finally:
520f05cddf9SRui Paulo        clf.close()
521f05cddf9SRui Paulo
522f05cddf9SRui Paulo    raise SystemExit
523f05cddf9SRui Paulo
524f05cddf9SRui Pauloif __name__ == '__main__':
525f05cddf9SRui Paulo    main()
526