]>
Commit | Line | Data |
---|---|---|
d4f612b7 JM |
1 | #!/usr/bin/python |
2 | # | |
3 | # Example nfcpy to wpa_supplicant wrapper for WPS NFC operations | |
8140ae96 | 4 | # Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi> |
d4f612b7 JM |
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 | |
e50d01b4 JM |
15 | import nfc.llcp |
16 | import nfc.handover | |
d4f612b7 | 17 | |
8140ae96 JM |
18 | import logging |
19 | logging.basicConfig() | |
20 | ||
d4f612b7 JM |
21 | import wpactrl |
22 | ||
23 | wpas_ctrl = '/var/run/wpa_supplicant' | |
24 | ||
ec4f5a37 | 25 | def wpas_connect(): |
d4f612b7 JM |
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 wpa_supplicant: ", error | |
ec4f5a37 | 32 | return None |
d4f612b7 JM |
33 | |
34 | if len(ifaces) < 1: | |
35 | print "No wpa_supplicant control interface found" | |
ec4f5a37 | 36 | return None |
d4f612b7 JM |
37 | |
38 | for ctrl in ifaces: | |
39 | try: | |
40 | wpas = wpactrl.WPACtrl(ctrl) | |
ec4f5a37 | 41 | return wpas |
d4f612b7 JM |
42 | except wpactrl.error, error: |
43 | print "Error: ", error | |
44 | pass | |
ec4f5a37 JM |
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")) | |
d4f612b7 | 53 | |
dab710c4 | 54 | |
e50d01b4 JM |
55 | def wpas_get_handover_req(): |
56 | wpas = wpas_connect() | |
57 | if (wpas == None): | |
58 | return None | |
59 | return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS").rstrip().decode("hex") | |
60 | ||
61 | ||
62 | def wpas_put_handover_sel(message): | |
63 | wpas = wpas_connect() | |
64 | if (wpas == None): | |
65 | return | |
66 | print wpas.request("NFC_RX_HANDOVER_SEL " + str(message).encode("hex")) | |
67 | ||
68 | ||
69 | def wps_handover_init(peer): | |
70 | print "Trying to initiate WPS handover" | |
71 | ||
72 | data = wpas_get_handover_req() | |
73 | if (data == None): | |
74 | print "Could not get handover request message from wpa_supplicant" | |
75 | return | |
76 | print "Handover request from wpa_supplicant: " + data.encode("hex") | |
77 | message = nfc.ndef.Message(data) | |
78 | print "Parsed handover request: " + message.pretty() | |
79 | ||
80 | nfc.llcp.activate(peer); | |
81 | time.sleep(0.5) | |
82 | ||
83 | client = nfc.handover.HandoverClient() | |
84 | try: | |
85 | print "Trying handover"; | |
86 | client.connect() | |
87 | print "Connected for handover" | |
88 | except nfc.llcp.ConnectRefused: | |
89 | print "Handover connection refused" | |
90 | nfc.llcp.shutdown() | |
91 | client.close() | |
92 | return | |
93 | ||
94 | print "Sending handover request" | |
95 | ||
96 | if not client.send(message): | |
97 | print "Failed to send handover request" | |
98 | ||
99 | print "Receiving handover response" | |
100 | message = client._recv() | |
101 | print "Handover select received" | |
102 | print message.pretty() | |
103 | wpas_put_handover_sel(message) | |
104 | ||
105 | print "Remove peer" | |
106 | nfc.llcp.shutdown() | |
107 | client.close() | |
108 | print "Done with handover" | |
109 | ||
110 | ||
dab710c4 JM |
111 | def wps_tag_read(tag): |
112 | if len(tag.ndef.message): | |
113 | message = nfc.ndef.Message(tag.ndef.message) | |
114 | print "message type " + message.type | |
115 | ||
116 | for record in message: | |
117 | print "record type " + record.type | |
118 | if record.type == "application/vnd.wfa.wsc": | |
119 | print "WPS tag - send to wpa_supplicant" | |
120 | wpas_tag_read(tag.ndef.message) | |
121 | break | |
122 | else: | |
123 | print "Empty tag" | |
124 | ||
125 | print "Remove tag" | |
126 | while tag.is_present: | |
127 | time.sleep(0.1) | |
128 | ||
129 | ||
dc6bda11 JM |
130 | def find_peer(clf): |
131 | while True: | |
132 | if nfc.llcp.connected(): | |
133 | print "LLCP connected" | |
134 | general_bytes = nfc.llcp.startup({}) | |
135 | peer = clf.listen(ord(os.urandom(1)) + 200, general_bytes) | |
136 | if isinstance(peer, nfc.DEP): | |
137 | print "listen -> DEP"; | |
138 | if peer.general_bytes.startswith("Ffm"): | |
139 | print "Found DEP" | |
140 | return peer | |
141 | print "mismatch in general_bytes" | |
142 | print peer.general_bytes | |
143 | ||
144 | peer = clf.poll(general_bytes) | |
145 | if isinstance(peer, nfc.DEP): | |
146 | print "poll -> DEP"; | |
147 | if peer.general_bytes.startswith("Ffm"): | |
148 | print "Found DEP" | |
149 | return peer | |
150 | print "mismatch in general_bytes" | |
151 | print peer.general_bytes | |
152 | ||
153 | if peer: | |
154 | print "Found tag" | |
155 | return peer | |
156 | ||
157 | ||
d4f612b7 JM |
158 | def main(): |
159 | clf = nfc.ContactlessFrontend() | |
160 | ||
161 | try: | |
162 | while True: | |
e50d01b4 | 163 | print "Waiting for a tag or peer to be touched" |
d4f612b7 | 164 | |
dc6bda11 JM |
165 | tag = find_peer(clf) |
166 | if isinstance(tag, nfc.DEP): | |
167 | wps_handover_init(tag) | |
168 | continue | |
169 | ||
170 | if tag.ndef: | |
171 | wps_tag_read(tag) | |
172 | continue | |
173 | ||
174 | print "Not an NDEF tag - remove tag" | |
175 | while tag.is_present: | |
176 | time.sleep(0.1) | |
d4f612b7 JM |
177 | |
178 | except KeyboardInterrupt: | |
179 | raise SystemExit | |
180 | finally: | |
181 | clf.close() | |
182 | ||
183 | raise SystemExit | |
184 | ||
185 | if __name__ == '__main__': | |
186 | main() |