OSDN Git Service

Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78
[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
124     nfc.llcp.activate(peer);
125
126     try:
127         print "Trying handover";
128         srv.start()
129         print "Wait for disconnect"
130         while nfc.llcp.connected():
131             time.sleep(0.1)
132         print "Disconnected after handover"
133     except nfc.llcp.ConnectRefused:
134         print "Handover connection refused"
135         nfc.llcp.shutdown()
136         return
137
138     if srv.sent_carrier:
139         wpas_report_handover(srv.received_carrier, srv.sent_carrier)
140
141     print "Remove peer"
142     nfc.llcp.shutdown()
143     print "Done with handover"
144
145
146 def wps_tag_read(tag):
147     if len(tag.ndef.message):
148         message = nfc.ndef.Message(tag.ndef.message)
149         print "message type " + message.type
150
151         for record in message:
152             print "record type " + record.type
153             if record.type == "application/vnd.wfa.wsc":
154                 print "WPS tag - send to hostapd"
155                 wpas_tag_read(tag.ndef.message)
156                 break
157     else:
158         print "Empty tag"
159
160     print "Remove tag"
161     while tag.is_present:
162         time.sleep(0.1)
163
164
165 def wps_write_config_tag(clf):
166     print "Write WPS config token"
167     data = wpas_get_config_token()
168     if (data == None):
169         print "Could not get WPS config token from hostapd"
170         return
171
172     print "Touch an NFC tag"
173     while True:
174         tag = clf.poll()
175         if tag == None:
176             time.sleep(0.1)
177             continue
178         break
179
180     print "Tag found - writing"
181     tag.ndef.message = data
182     print "Done - remove tag"
183     while tag.is_present:
184         time.sleep(0.1)
185
186
187 def wps_write_password_tag(clf):
188     print "Write WPS password token"
189     data = wpas_get_password_token()
190     if (data == None):
191         print "Could not get WPS password token from hostapd"
192         return
193
194     print "Touch an NFC tag"
195     while True:
196         tag = clf.poll()
197         if tag == None:
198             time.sleep(0.1)
199             continue
200         break
201
202     print "Tag found - writing"
203     tag.ndef.message = data
204     print "Done - remove tag"
205     while tag.is_present:
206         time.sleep(0.1)
207
208
209 def find_peer(clf):
210     while True:
211         if nfc.llcp.connected():
212             print "LLCP connected"
213         general_bytes = nfc.llcp.startup({})
214         peer = clf.listen(ord(os.urandom(1)) + 250, general_bytes)
215         if isinstance(peer, nfc.DEP):
216             print "listen -> DEP";
217             if peer.general_bytes.startswith("Ffm"):
218                 print "Found DEP"
219                 return peer
220             print "mismatch in general_bytes"
221             print peer.general_bytes
222
223         peer = clf.poll(general_bytes)
224         if isinstance(peer, nfc.DEP):
225             print "poll -> DEP";
226             if peer.general_bytes.startswith("Ffm"):
227                 print "Found DEP"
228                 return peer
229             print "mismatch in general_bytes"
230             print peer.general_bytes
231
232         if peer:
233             print "Found tag"
234             return peer
235
236
237 def main():
238     clf = nfc.ContactlessFrontend()
239
240     try:
241         if len(sys.argv) > 1 and sys.argv[1] == "write-config":
242             wps_write_config_tag(clf)
243             raise SystemExit
244
245         if len(sys.argv) > 1 and sys.argv[1] == "write-password":
246             wps_write_password_tag(clf)
247             raise SystemExit
248
249         while True:
250             print "Waiting for a tag or peer to be touched"
251
252             tag = find_peer(clf)
253             if isinstance(tag, nfc.DEP):
254                 wps_handover_resp(tag)
255                 continue
256
257             if tag.ndef:
258                 wps_tag_read(tag)
259                 continue
260
261             print "Not an NDEF tag - remove tag"
262             while tag.is_present:
263                 time.sleep(0.1)
264
265     except KeyboardInterrupt:
266         raise SystemExit
267     finally:
268         clf.close()
269
270     raise SystemExit
271
272 if __name__ == '__main__':
273     main()