Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # |
| 3 | # Example nfcpy to wpa_supplicant wrapper for WPS NFC operations |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 4 | # Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi> |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 5 | # |
| 6 | # This software may be distributed under the terms of the BSD license. |
| 7 | # See README for more details. |
| 8 | |
| 9 | import os |
| 10 | import sys |
| 11 | import time |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 12 | import random |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 13 | import threading |
| 14 | import argparse |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 15 | |
| 16 | import nfc |
| 17 | import nfc.ndef |
| 18 | import nfc.llcp |
| 19 | import nfc.handover |
| 20 | |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 21 | import logging |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 22 | |
Dmitry Shmidt | 700a137 | 2013-03-15 14:14:44 -0700 | [diff] [blame] | 23 | import wpaspy |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 24 | |
| 25 | wpas_ctrl = '/var/run/wpa_supplicant' |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 26 | srv = None |
| 27 | continue_loop = True |
| 28 | terminate_now = False |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 29 | summary_file = None |
| 30 | success_file = None |
| 31 | |
| 32 | def summary(txt): |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 33 | print(txt) |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 34 | if summary_file: |
| 35 | with open(summary_file, 'a') as f: |
| 36 | f.write(txt + "\n") |
| 37 | |
| 38 | def success_report(txt): |
| 39 | summary(txt) |
| 40 | if success_file: |
| 41 | with open(success_file, 'a') as f: |
| 42 | f.write(txt + "\n") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 43 | |
| 44 | def wpas_connect(): |
| 45 | ifaces = [] |
| 46 | if os.path.isdir(wpas_ctrl): |
| 47 | try: |
| 48 | ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 49 | except OSError as error: |
| 50 | print("Could not find wpa_supplicant: ", error) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 51 | return None |
| 52 | |
| 53 | if len(ifaces) < 1: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 54 | print("No wpa_supplicant control interface found") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 55 | return None |
| 56 | |
| 57 | for ctrl in ifaces: |
| 58 | try: |
Dmitry Shmidt | 700a137 | 2013-03-15 14:14:44 -0700 | [diff] [blame] | 59 | wpas = wpaspy.Ctrl(ctrl) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 60 | return wpas |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 61 | except Exception as e: |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 62 | pass |
| 63 | return None |
| 64 | |
| 65 | |
| 66 | def wpas_tag_read(message): |
| 67 | wpas = wpas_connect() |
| 68 | if (wpas == None): |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 69 | return False |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 70 | if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")): |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 71 | return False |
| 72 | return True |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 73 | |
Dmitry Shmidt | 1e78e76 | 2013-04-02 11:05:36 -0700 | [diff] [blame] | 74 | def wpas_get_config_token(id=None): |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 75 | wpas = wpas_connect() |
| 76 | if (wpas == None): |
| 77 | return None |
Dmitry Shmidt | 1e78e76 | 2013-04-02 11:05:36 -0700 | [diff] [blame] | 78 | if id: |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 79 | ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF " + id) |
| 80 | else: |
| 81 | ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF") |
| 82 | if "FAIL" in ret: |
| 83 | return None |
| 84 | return ret.rstrip().decode("hex") |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 85 | |
| 86 | |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 87 | def wpas_get_er_config_token(uuid): |
| 88 | wpas = wpas_connect() |
| 89 | if (wpas == None): |
| 90 | return None |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 91 | ret = wpas.request("WPS_ER_NFC_CONFIG_TOKEN NDEF " + uuid) |
| 92 | if "FAIL" in ret: |
| 93 | return None |
| 94 | return ret.rstrip().decode("hex") |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 95 | |
| 96 | |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 97 | def wpas_get_password_token(): |
| 98 | wpas = wpas_connect() |
| 99 | if (wpas == None): |
| 100 | return None |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 101 | ret = wpas.request("WPS_NFC_TOKEN NDEF") |
| 102 | if "FAIL" in ret: |
| 103 | return None |
| 104 | return ret.rstrip().decode("hex") |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 105 | |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 106 | def wpas_get_handover_req(): |
| 107 | wpas = wpas_connect() |
| 108 | if (wpas == None): |
| 109 | return None |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 110 | ret = wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR") |
| 111 | if "FAIL" in ret: |
| 112 | return None |
| 113 | return ret.rstrip().decode("hex") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 114 | |
| 115 | |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 116 | def wpas_get_handover_sel(uuid): |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 117 | wpas = wpas_connect() |
| 118 | if (wpas == None): |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 119 | return None |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 120 | if uuid is None: |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 121 | res = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip() |
| 122 | else: |
| 123 | res = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + uuid).rstrip() |
| 124 | if "FAIL" in res: |
| 125 | return None |
| 126 | return res.decode("hex") |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 127 | |
| 128 | |
| 129 | def wpas_report_handover(req, sel, type): |
| 130 | wpas = wpas_connect() |
| 131 | if (wpas == None): |
| 132 | return None |
| 133 | return wpas.request("NFC_REPORT_HANDOVER " + type + " WPS " + |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 134 | str(req).encode("hex") + " " + |
| 135 | str(sel).encode("hex")) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 136 | |
| 137 | |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 138 | class HandoverServer(nfc.handover.HandoverServer): |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 139 | def __init__(self, llc): |
| 140 | super(HandoverServer, self).__init__(llc) |
| 141 | self.sent_carrier = None |
| 142 | self.ho_server_processing = False |
| 143 | self.success = False |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 144 | |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 145 | # override to avoid parser error in request/response.pretty() in nfcpy |
| 146 | # due to new WSC handover format |
| 147 | def _process_request(self, request): |
| 148 | summary("received handover request {}".format(request.type)) |
| 149 | response = nfc.ndef.Message("\xd1\x02\x01Hs\x12") |
| 150 | if not request.type == 'urn:nfc:wkt:Hr': |
| 151 | summary("not a handover request") |
| 152 | else: |
| 153 | try: |
| 154 | request = nfc.ndef.HandoverRequestMessage(request) |
| 155 | except nfc.ndef.DecodeError as e: |
| 156 | summary("error decoding 'Hr' message: {}".format(e)) |
| 157 | else: |
| 158 | response = self.process_request(request) |
| 159 | summary("send handover response {}".format(response.type)) |
| 160 | return response |
| 161 | |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 162 | def process_request(self, request): |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 163 | self.ho_server_processing = True |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 164 | summary("HandoverServer - request received") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 165 | try: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 166 | print("Parsed handover request: " + request.pretty()) |
| 167 | except Exception as e: |
| 168 | print(e) |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 169 | |
| 170 | sel = nfc.ndef.HandoverSelectMessage(version="1.2") |
| 171 | |
| 172 | for carrier in request.carriers: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 173 | print("Remote carrier type: " + carrier.type) |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 174 | if carrier.type == "application/vnd.wfa.wsc": |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 175 | summary("WPS carrier type match - add WPS carrier record") |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 176 | data = wpas_get_handover_sel(self.uuid) |
| 177 | if data is None: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 178 | summary("Could not get handover select carrier record from wpa_supplicant") |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 179 | continue |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 180 | print("Handover select carrier record from wpa_supplicant:") |
| 181 | print(data.encode("hex")) |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 182 | self.sent_carrier = data |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 183 | if "OK" in wpas_report_handover(carrier.record, self.sent_carrier, "RESP"): |
| 184 | success_report("Handover reported successfully (responder)") |
| 185 | else: |
| 186 | summary("Handover report rejected (responder)") |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 187 | |
| 188 | message = nfc.ndef.Message(data); |
| 189 | sel.add_carrier(message[0], "active", message[1:]) |
| 190 | |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 191 | print("Handover select:") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 192 | try: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 193 | print(sel.pretty()) |
| 194 | except Exception as e: |
| 195 | print(e) |
| 196 | print(str(sel).encode("hex")) |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 197 | |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 198 | summary("Sending handover select") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 199 | self.success = True |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 200 | return sel |
| 201 | |
| 202 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 203 | def wps_handover_init(llc): |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 204 | summary("Trying to initiate WPS handover") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 205 | |
| 206 | data = wpas_get_handover_req() |
| 207 | if (data == None): |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 208 | summary("Could not get handover request carrier record from wpa_supplicant") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 209 | return |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 210 | print("Handover request carrier record from wpa_supplicant: " + data.encode("hex")) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 211 | |
| 212 | message = nfc.ndef.HandoverRequestMessage(version="1.2") |
| 213 | message.nonce = random.randint(0, 0xffff) |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 214 | datamsg = nfc.ndef.Message(data) |
| 215 | message.add_carrier(datamsg[0], "active", datamsg[1:]) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 216 | |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 217 | print("Handover request:") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 218 | try: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 219 | print(message.pretty()) |
| 220 | except Exception as e: |
| 221 | print(e) |
| 222 | print(str(message).encode("hex")) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 223 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 224 | client = nfc.handover.HandoverClient(llc) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 225 | try: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 226 | summary("Trying to initiate NFC connection handover") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 227 | client.connect() |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 228 | summary("Connected for handover") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 229 | except nfc.llcp.ConnectRefused: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 230 | summary("Handover connection refused") |
| 231 | client.close() |
| 232 | return |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 233 | except Exception as e: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 234 | summary("Other exception: " + str(e)) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 235 | client.close() |
| 236 | return |
| 237 | |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 238 | summary("Sending handover request") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 239 | |
| 240 | if not client.send(message): |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 241 | summary("Failed to send handover request") |
| 242 | client.close() |
| 243 | return |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 244 | |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 245 | summary("Receiving handover response") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 246 | message = client._recv() |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 247 | if message is None: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 248 | summary("No response received") |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 249 | client.close() |
| 250 | return |
| 251 | if message.type != "urn:nfc:wkt:Hs": |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 252 | summary("Response was not Hs - received: " + message.type) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 253 | client.close() |
| 254 | return |
| 255 | |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 256 | print("Received message") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 257 | try: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 258 | print(message.pretty()) |
| 259 | except Exception as e: |
| 260 | print(e) |
| 261 | print(str(message).encode("hex")) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 262 | message = nfc.ndef.HandoverSelectMessage(message) |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 263 | summary("Handover select received") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 264 | try: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 265 | print(message.pretty()) |
| 266 | except Exception as e: |
| 267 | print(e) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 268 | |
| 269 | for carrier in message.carriers: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 270 | print("Remote carrier type: " + carrier.type) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 271 | if carrier.type == "application/vnd.wfa.wsc": |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 272 | print("WPS carrier type match - send to wpa_supplicant") |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 273 | if "OK" in wpas_report_handover(data, carrier.record, "INIT"): |
| 274 | success_report("Handover reported successfully (initiator)") |
| 275 | else: |
| 276 | summary("Handover report rejected (initiator)") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 277 | # nfcpy does not support the new format.. |
| 278 | #wifi = nfc.ndef.WifiConfigRecord(carrier.record) |
| 279 | #print wifi.pretty() |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 280 | |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 281 | print("Remove peer") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 282 | client.close() |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 283 | print("Done with handover") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 284 | global only_one |
| 285 | if only_one: |
| 286 | global continue_loop |
| 287 | continue_loop = False |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 288 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 289 | global no_wait |
| 290 | if no_wait: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 291 | print("Trying to exit..") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 292 | global terminate_now |
| 293 | terminate_now = True |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 294 | |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 295 | def wps_tag_read(tag, wait_remove=True): |
| 296 | success = False |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 297 | if len(tag.ndef.message): |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 298 | for record in tag.ndef.message: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 299 | print("record type " + record.type) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 300 | if record.type == "application/vnd.wfa.wsc": |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 301 | summary("WPS tag - send to wpa_supplicant") |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 302 | success = wpas_tag_read(tag.ndef.message) |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 303 | break |
| 304 | else: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 305 | summary("Empty tag") |
| 306 | |
| 307 | if success: |
| 308 | success_report("Tag read succeeded") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 309 | |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 310 | if wait_remove: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 311 | print("Remove tag") |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 312 | while tag.is_present: |
| 313 | time.sleep(0.1) |
| 314 | |
| 315 | return success |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 316 | |
| 317 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 318 | def rdwr_connected_write(tag): |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 319 | summary("Tag found - writing - " + str(tag)) |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 320 | global write_data |
| 321 | tag.ndef.message = str(write_data) |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 322 | success_report("Tag write succeeded") |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 323 | print("Done - remove tag") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 324 | global only_one |
| 325 | if only_one: |
| 326 | global continue_loop |
| 327 | continue_loop = False |
| 328 | global write_wait_remove |
| 329 | while write_wait_remove and tag.is_present: |
| 330 | time.sleep(0.1) |
| 331 | |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 332 | def wps_write_config_tag(clf, id=None, wait_remove=True): |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 333 | print("Write WPS config token") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 334 | global write_data, write_wait_remove |
| 335 | write_wait_remove = wait_remove |
| 336 | write_data = wpas_get_config_token(id) |
| 337 | if write_data == None: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 338 | print("Could not get WPS config token from wpa_supplicant") |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 339 | sys.exit(1) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 340 | return |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 341 | print("Touch an NFC tag") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 342 | clf.connect(rdwr={'on-connect': rdwr_connected_write}) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 343 | |
| 344 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 345 | def wps_write_er_config_tag(clf, uuid, wait_remove=True): |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 346 | print("Write WPS ER config token") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 347 | global write_data, write_wait_remove |
| 348 | write_wait_remove = wait_remove |
| 349 | write_data = wpas_get_er_config_token(uuid) |
| 350 | if write_data == None: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 351 | print("Could not get WPS config token from wpa_supplicant") |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 352 | return |
| 353 | |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 354 | print("Touch an NFC tag") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 355 | clf.connect(rdwr={'on-connect': rdwr_connected_write}) |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 356 | |
| 357 | |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 358 | def wps_write_password_tag(clf, wait_remove=True): |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 359 | print("Write WPS password token") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 360 | global write_data, write_wait_remove |
| 361 | write_wait_remove = wait_remove |
| 362 | write_data = wpas_get_password_token() |
| 363 | if write_data == None: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 364 | print("Could not get WPS password token from wpa_supplicant") |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 365 | return |
| 366 | |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 367 | print("Touch an NFC tag") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 368 | clf.connect(rdwr={'on-connect': rdwr_connected_write}) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 369 | |
| 370 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 371 | def rdwr_connected(tag): |
| 372 | global only_one, no_wait |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 373 | summary("Tag connected: " + str(tag)) |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 374 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 375 | if tag.ndef: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 376 | print("NDEF tag: " + tag.type) |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 377 | try: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 378 | print(tag.ndef.message.pretty()) |
| 379 | except Exception as e: |
| 380 | print(e) |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 381 | success = wps_tag_read(tag, not only_one) |
| 382 | if only_one and success: |
| 383 | global continue_loop |
| 384 | continue_loop = False |
| 385 | else: |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 386 | summary("Not an NDEF tag - remove tag") |
| 387 | return True |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 388 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 389 | return not no_wait |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 390 | |
| 391 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 392 | def llcp_worker(llc): |
| 393 | global arg_uuid |
| 394 | if arg_uuid is None: |
| 395 | wps_handover_init(llc) |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 396 | print("Exiting llcp_worker thread") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 397 | return |
| 398 | |
| 399 | global srv |
| 400 | global wait_connection |
| 401 | while not wait_connection and srv.sent_carrier is None: |
| 402 | if srv.ho_server_processing: |
| 403 | time.sleep(0.025) |
| 404 | |
| 405 | def llcp_startup(clf, llc): |
| 406 | global arg_uuid |
| 407 | if arg_uuid: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 408 | print("Start LLCP server") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 409 | global srv |
| 410 | srv = HandoverServer(llc) |
| 411 | if arg_uuid is "ap": |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 412 | print("Trying to handle WPS handover") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 413 | srv.uuid = None |
| 414 | else: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 415 | print("Trying to handle WPS handover with AP " + arg_uuid) |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 416 | srv.uuid = arg_uuid |
| 417 | return llc |
| 418 | |
| 419 | def llcp_connected(llc): |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 420 | print("P2P LLCP connected") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 421 | global wait_connection |
| 422 | wait_connection = False |
| 423 | global arg_uuid |
| 424 | if arg_uuid: |
| 425 | global srv |
| 426 | srv.start() |
| 427 | else: |
| 428 | threading.Thread(target=llcp_worker, args=(llc,)).start() |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 429 | print("llcp_connected returning") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 430 | return True |
| 431 | |
| 432 | |
| 433 | def terminate_loop(): |
| 434 | global terminate_now |
| 435 | return terminate_now |
| 436 | |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 437 | def main(): |
| 438 | clf = nfc.ContactlessFrontend() |
| 439 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 440 | parser = argparse.ArgumentParser(description='nfcpy to wpa_supplicant integration for WPS NFC operations') |
| 441 | parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO, |
| 442 | action='store_const', dest='loglevel', |
| 443 | help='verbose debug output') |
| 444 | parser.add_argument('-q', const=logging.WARNING, action='store_const', |
| 445 | dest='loglevel', help='be quiet') |
| 446 | parser.add_argument('--only-one', '-1', action='store_true', |
| 447 | help='run only one operation and exit') |
| 448 | parser.add_argument('--no-wait', action='store_true', |
| 449 | help='do not wait for tag to be removed before exiting') |
| 450 | parser.add_argument('--uuid', |
| 451 | help='UUID of an AP (used for WPS ER operations)') |
| 452 | parser.add_argument('--id', |
| 453 | help='network id (used for WPS ER operations)') |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 454 | parser.add_argument('--summary', |
| 455 | help='summary file for writing status updates') |
| 456 | parser.add_argument('--success', |
| 457 | help='success file for writing success update') |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 458 | parser.add_argument('command', choices=['write-config', |
| 459 | 'write-er-config', |
| 460 | 'write-password'], |
| 461 | nargs='?') |
| 462 | args = parser.parse_args() |
| 463 | |
| 464 | global arg_uuid |
| 465 | arg_uuid = args.uuid |
| 466 | |
| 467 | global only_one |
| 468 | only_one = args.only_one |
| 469 | |
| 470 | global no_wait |
| 471 | no_wait = args.no_wait |
| 472 | |
Dmitry Shmidt | 96be622 | 2014-02-13 10:16:51 -0800 | [diff] [blame] | 473 | if args.summary: |
| 474 | global summary_file |
| 475 | summary_file = args.summary |
| 476 | |
| 477 | if args.success: |
| 478 | global success_file |
| 479 | success_file = args.success |
| 480 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 481 | logging.basicConfig(level=args.loglevel) |
| 482 | |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 483 | try: |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 484 | if not clf.open("usb"): |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 485 | print("Could not open connection with an NFC device") |
Dmitry Shmidt | f862328 | 2013-02-20 14:34:59 -0800 | [diff] [blame] | 486 | raise SystemExit |
| 487 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 488 | if args.command == "write-config": |
| 489 | wps_write_config_tag(clf, id=args.id, wait_remove=not args.no_wait) |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 490 | raise SystemExit |
| 491 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 492 | if args.command == "write-er-config": |
| 493 | wps_write_er_config_tag(clf, args.uuid, wait_remove=not args.no_wait) |
Dmitry Shmidt | 1e78e76 | 2013-04-02 11:05:36 -0700 | [diff] [blame] | 494 | raise SystemExit |
| 495 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 496 | if args.command == "write-password": |
| 497 | wps_write_password_tag(clf, wait_remove=not args.no_wait) |
Dmitry Shmidt | 33e38bf | 2013-02-27 12:56:00 -0800 | [diff] [blame] | 498 | raise SystemExit |
| 499 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 500 | global continue_loop |
| 501 | while continue_loop: |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 502 | print("Waiting for a tag or peer to be touched") |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 503 | wait_connection = True |
| 504 | try: |
| 505 | if not clf.connect(rdwr={'on-connect': rdwr_connected}, |
| 506 | llcp={'on-startup': llcp_startup, |
| 507 | 'on-connect': llcp_connected}, |
| 508 | terminate=terminate_loop): |
Dmitry Shmidt | 4b06059 | 2013-04-29 16:42:49 -0700 | [diff] [blame] | 509 | break |
Hai Shalom | 74f70d4 | 2019-02-11 14:42:39 -0800 | [diff] [blame] | 510 | except Exception as e: |
| 511 | print("clf.connect failed") |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 512 | |
Dmitry Shmidt | cf32e60 | 2014-01-28 10:57:39 -0800 | [diff] [blame] | 513 | global srv |
| 514 | if only_one and srv and srv.success: |
| 515 | raise SystemExit |
Dmitry Shmidt | d5e4923 | 2012-12-03 15:08:10 -0800 | [diff] [blame] | 516 | |
| 517 | except KeyboardInterrupt: |
| 518 | raise SystemExit |
| 519 | finally: |
| 520 | clf.close() |
| 521 | |
| 522 | raise SystemExit |
| 523 | |
| 524 | if __name__ == '__main__': |
| 525 | main() |