OSDN Git Service

Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78
[android-x86/external-wpa_supplicant_8.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()