WPS: Configure logging to show nfcpy log message
[mech_eap.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_req():
70     wpas = wpas_connect()
71     if (wpas == None):
72         return None
73     return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS").rstrip().decode("hex")
74
75
76 def wpas_put_handover_sel(message):
77     wpas = wpas_connect()
78     if (wpas == None):
79         return
80     print wpas.request("NFC_RX_HANDOVER_SEL " + str(message).encode("hex"))
81
82
83 def wps_handover_init(peer):
84     print "Trying to initiate WPS handover"
85
86     data = wpas_get_handover_req()
87     if (data == None):
88         print "Could not get handover request message from hostapd"
89         return
90     print "Handover request from hostapd: " + data.encode("hex")
91     message = nfc.ndef.Message(data)
92     print "Parsed handover request: " + message.pretty()
93
94     nfc.llcp.activate(peer);
95     time.sleep(0.5)
96
97     client = nfc.handover.HandoverClient()
98     try:
99         print "Trying handover";
100         client.connect()
101         print "Connected for handover"
102     except nfc.llcp.ConnectRefused:
103         print "Handover connection refused"
104         nfc.llcp.shutdown()
105         client.close()
106         return
107
108     print "Sending handover request"
109
110     if not client.send(message):
111         print "Failed to send handover request"
112
113     print "Receiving handover response"
114     message = client._recv()
115     print "Handover select received"
116     print message.pretty()
117     wpas_put_handover_sel(message)
118
119     print "Remove peer"
120     nfc.llcp.shutdown()
121     client.close()
122     print "Done with handover"
123
124
125 def wps_tag_read(tag):
126     if len(tag.ndef.message):
127         message = nfc.ndef.Message(tag.ndef.message)
128         print "message type " + message.type
129
130         for record in message:
131             print "record type " + record.type
132             if record.type == "application/vnd.wfa.wsc":
133                 print "WPS tag - send to hostapd"
134                 wpas_tag_read(tag.ndef.message)
135                 break
136     else:
137         print "Empty tag"
138
139     print "Remove tag"
140     while tag.is_present:
141         time.sleep(0.1)
142
143
144 def wps_write_config_tag(clf):
145     print "Write WPS config token"
146     data = wpas_get_config_token()
147     if (data == None):
148         print "Could not get WPS config token from hostapd"
149         return
150
151     print "Touch an NFC tag"
152     while True:
153         tag = clf.poll()
154         if tag == None:
155             time.sleep(0.1)
156             continue
157         break
158
159     print "Tag found - writing"
160     tag.ndef.message = data
161     print "Done - remove tag"
162     while tag.is_present:
163         time.sleep(0.1)
164
165
166 def wps_write_password_tag(clf):
167     print "Write WPS password token"
168     data = wpas_get_password_token()
169     if (data == None):
170         print "Could not get WPS password 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 main():
189     clf = nfc.ContactlessFrontend()
190
191     try:
192         if len(sys.argv) > 1 and sys.argv[1] == "write-config":
193             wps_write_config_tag(clf)
194             raise SystemExit
195
196         if len(sys.argv) > 1 and sys.argv[1] == "write-password":
197             wps_write_password_tag(clf)
198             raise SystemExit
199
200         while True:
201             print "Waiting for a tag or peer to be touched"
202
203             while True:
204                 general_bytes = nfc.llcp.startup({})
205                 tag = clf.poll(general_bytes)
206                 if tag == None:
207                     continue
208
209                 if isinstance(tag, nfc.DEP):
210                     wps_handover_init(tag)
211                     break
212
213                 if tag.ndef:
214                     wps_tag_read(tag)
215                     break
216
217                 if tag:
218                     print "Not an NDEF tag - remove tag"
219                     while tag.is_present:
220                         time.sleep(0.1)
221                     break
222
223     except KeyboardInterrupt:
224         raise SystemExit
225     finally:
226         clf.close()
227
228     raise SystemExit
229
230 if __name__ == '__main__':
231     main()