]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/examples/wps-nfc.py
WPS: Add support for config token generation with wpa_supplicant
[thirdparty/hostap.git] / wpa_supplicant / examples / wps-nfc.py
1 #!/usr/bin/python
2 #
3 # Example nfcpy to wpa_supplicant wrapper for WPS NFC operations
4 # Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
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
12 import random
13 import StringIO
14
15 import nfc
16 import nfc.ndef
17 import nfc.llcp
18 import nfc.handover
19
20 import logging
21 logging.basicConfig()
22
23 import wpactrl
24
25 wpas_ctrl = '/var/run/wpa_supplicant'
26
27 def wpas_connect():
28 ifaces = []
29 if os.path.isdir(wpas_ctrl):
30 try:
31 ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
32 except OSError, error:
33 print "Could not find wpa_supplicant: ", error
34 return None
35
36 if len(ifaces) < 1:
37 print "No wpa_supplicant control interface found"
38 return None
39
40 for ctrl in ifaces:
41 try:
42 wpas = wpactrl.WPACtrl(ctrl)
43 return wpas
44 except wpactrl.error, error:
45 print "Error: ", error
46 pass
47 return None
48
49
50 def wpas_tag_read(message):
51 wpas = wpas_connect()
52 if (wpas == None):
53 return
54 print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex"))
55
56
57 def wpas_get_config_token():
58 wpas = wpas_connect()
59 if (wpas == None):
60 return None
61 return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex")
62
63
64 def wpas_get_password_token():
65 wpas = wpas_connect()
66 if (wpas == None):
67 return None
68 return wpas.request("WPS_NFC_TOKEN NDEF").rstrip().decode("hex")
69
70
71 def wpas_get_handover_req():
72 wpas = wpas_connect()
73 if (wpas == None):
74 return None
75 return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex")
76
77
78 def wpas_report_handover(req, sel):
79 wpas = wpas_connect()
80 if (wpas == None):
81 return None
82 return wpas.request("NFC_REPORT_HANDOVER INIT WPS " +
83 str(req).encode("hex") + " " +
84 str(sel).encode("hex"))
85
86
87 def wps_handover_init(peer):
88 print "Trying to initiate WPS handover"
89
90 data = wpas_get_handover_req()
91 if (data == None):
92 print "Could not get handover request carrier record from wpa_supplicant"
93 return
94 print "Handover request carrier record from wpa_supplicant: " + data.encode("hex")
95 record = nfc.ndef.Record()
96 f = StringIO.StringIO(data)
97 record._read(f)
98 record = nfc.ndef.HandoverCarrierRecord(record)
99 print "Parsed handover request carrier record:"
100 print record.pretty()
101
102 message = nfc.ndef.HandoverRequestMessage(version="1.2")
103 message.nonce = random.randint(0, 0xffff)
104 message.add_carrier(record, "active")
105
106 print "Handover request:"
107 print message.pretty()
108
109 nfc.llcp.activate(peer);
110
111 client = nfc.handover.HandoverClient()
112 try:
113 print "Trying handover";
114 client.connect()
115 print "Connected for handover"
116 except nfc.llcp.ConnectRefused:
117 print "Handover connection refused"
118 nfc.llcp.shutdown()
119 client.close()
120 return
121
122 print "Sending handover request"
123
124 if not client.send(message):
125 print "Failed to send handover request"
126
127 print "Receiving handover response"
128 message = client._recv()
129 if message is None:
130 print "No response received"
131 nfc.llcp.shutdown()
132 client.close()
133 return
134 if message.type != "urn:nfc:wkt:Hs":
135 print "Response was not Hs - received: " + message.type
136 nfc.llcp.shutdown()
137 client.close()
138 return
139
140 print "Received message"
141 print message.pretty()
142 message = nfc.ndef.HandoverSelectMessage(message)
143 print "Handover select received"
144 print message.pretty()
145
146 for carrier in message.carriers:
147 print "Remote carrier type: " + carrier.type
148 if carrier.type == "application/vnd.wfa.wsc":
149 print "WPS carrier type match - send to wpa_supplicant"
150 wpas_report_handover(data, carrier.record)
151 wifi = nfc.ndef.WifiConfigRecord(carrier.record)
152 print wifi.pretty()
153
154 print "Remove peer"
155 nfc.llcp.shutdown()
156 client.close()
157 print "Done with handover"
158
159
160 def wps_tag_read(tag):
161 if len(tag.ndef.message):
162 message = nfc.ndef.Message(tag.ndef.message)
163 print "message type " + message.type
164
165 for record in message:
166 print "record type " + record.type
167 if record.type == "application/vnd.wfa.wsc":
168 print "WPS tag - send to wpa_supplicant"
169 wpas_tag_read(tag.ndef.message)
170 break
171 else:
172 print "Empty tag"
173
174 print "Remove tag"
175 while tag.is_present:
176 time.sleep(0.1)
177
178
179 def wps_write_config_tag(clf):
180 print "Write WPS config token"
181 data = wpas_get_config_token()
182 if (data == None):
183 print "Could not get WPS config token from wpa_supplicant"
184 return
185
186 print "Touch an NFC tag"
187 while True:
188 tag = clf.poll()
189 if tag == None:
190 time.sleep(0.1)
191 continue
192 break
193
194 print "Tag found - writing"
195 tag.ndef.message = data
196 print "Done - remove tag"
197 while tag.is_present:
198 time.sleep(0.1)
199
200
201 def wps_write_password_tag(clf):
202 print "Write WPS password token"
203 data = wpas_get_password_token()
204 if (data == None):
205 print "Could not get WPS password token from wpa_supplicant"
206 return
207
208 print "Touch an NFC tag"
209 while True:
210 tag = clf.poll()
211 if tag == None:
212 time.sleep(0.1)
213 continue
214 break
215
216 print "Tag found - writing"
217 tag.ndef.message = data
218 print "Done - remove tag"
219 while tag.is_present:
220 time.sleep(0.1)
221
222
223 def find_peer(clf):
224 while True:
225 if nfc.llcp.connected():
226 print "LLCP connected"
227 general_bytes = nfc.llcp.startup({})
228 peer = clf.listen(ord(os.urandom(1)) + 250, general_bytes)
229 if isinstance(peer, nfc.DEP):
230 print "listen -> DEP";
231 if peer.general_bytes.startswith("Ffm"):
232 print "Found DEP"
233 return peer
234 print "mismatch in general_bytes"
235 print peer.general_bytes
236
237 peer = clf.poll(general_bytes)
238 if isinstance(peer, nfc.DEP):
239 print "poll -> DEP";
240 if peer.general_bytes.startswith("Ffm"):
241 print "Found DEP"
242 return peer
243 print "mismatch in general_bytes"
244 print peer.general_bytes
245
246 if peer:
247 print "Found tag"
248 return peer
249
250
251 def main():
252 clf = nfc.ContactlessFrontend()
253
254 try:
255 if len(sys.argv) > 1 and sys.argv[1] == "write-config":
256 wps_write_config_tag(clf)
257 raise SystemExit
258
259 if len(sys.argv) > 1 and sys.argv[1] == "write-password":
260 wps_write_password_tag(clf)
261 raise SystemExit
262
263 while True:
264 print "Waiting for a tag or peer to be touched"
265
266 tag = find_peer(clf)
267 if isinstance(tag, nfc.DEP):
268 wps_handover_init(tag)
269 continue
270
271 if tag.ndef:
272 wps_tag_read(tag)
273 continue
274
275 print "Not an NDEF tag - remove tag"
276 while tag.is_present:
277 time.sleep(0.1)
278
279 except KeyboardInterrupt:
280 raise SystemExit
281 finally:
282 clf.close()
283
284 raise SystemExit
285
286 if __name__ == '__main__':
287 main()