OSDN Git Service

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