]>
Commit | Line | Data |
---|---|---|
93a06242 JM |
1 | #!/usr/bin/python |
2 | # | |
3 | # Hotspot 2.0 tests | |
2f37a66d | 4 | # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi> |
93a06242 JM |
5 | # |
6 | # This software may be distributed under the terms of the BSD license. | |
7 | # See README for more details. | |
8 | ||
9 | import time | |
10 | import subprocess | |
11 | import logging | |
c9aa4308 | 12 | logger = logging.getLogger() |
efd43d85 JM |
13 | import os.path |
14 | import subprocess | |
93a06242 JM |
15 | |
16 | import hostapd | |
715bf904 | 17 | from wlantest import Wlantest |
93a06242 JM |
18 | |
19 | def hs20_ap_params(): | |
20 | params = hostapd.wpa2_params(ssid="test-hs20") | |
21 | params['wpa_key_mgmt'] = "WPA-EAP" | |
22 | params['ieee80211w'] = "1" | |
23 | params['ieee8021x'] = "1" | |
24 | params['auth_server_addr'] = "127.0.0.1" | |
25 | params['auth_server_port'] = "1812" | |
26 | params['auth_server_shared_secret'] = "radius" | |
27 | params['interworking'] = "1" | |
28 | params['access_network_type'] = "14" | |
29 | params['internet'] = "1" | |
30 | params['asra'] = "0" | |
31 | params['esr'] = "0" | |
32 | params['uesa'] = "0" | |
33 | params['venue_group'] = "7" | |
34 | params['venue_type'] = "1" | |
35 | params['venue_name'] = [ "eng:Example venue", "fin:Esimerkkipaikka" ] | |
36 | params['roaming_consortium'] = [ "112233", "1020304050", "010203040506", | |
37 | "fedcba" ] | |
38 | params['domain_name'] = "example.com,another.example.com" | |
39 | params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]", | |
40 | "0,another.example.com" ] | |
41 | params['hs20'] = "1" | |
42 | params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000" | |
43 | params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0" ] | |
44 | params['hs20_operating_class'] = "5173" | |
45 | params['anqp_3gpp_cell_net'] = "244,91" | |
46 | return params | |
47 | ||
2f37a66d | 48 | def interworking_select(dev, bssid, type=None, no_match=False, freq=None): |
bbe86767 | 49 | dev.dump_monitor() |
2f37a66d JM |
50 | freq_extra = " freq=" + freq if freq else "" |
51 | dev.request("INTERWORKING_SELECT" + freq_extra) | |
bbe86767 JM |
52 | ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"], |
53 | timeout=15) | |
93a06242 JM |
54 | if ev is None: |
55 | raise Exception("Network selection timed out"); | |
bbe86767 JM |
56 | if no_match: |
57 | if "INTERWORKING-NO-MATCH" not in ev: | |
58 | raise Exception("Unexpected network match") | |
59 | return | |
93a06242 JM |
60 | if "INTERWORKING-NO-MATCH" in ev: |
61 | raise Exception("Matching network not found") | |
2cdd91d8 | 62 | if bssid and bssid not in ev: |
93a06242 | 63 | raise Exception("Unexpected BSSID in match") |
bbe86767 JM |
64 | if type and "type=" + type not in ev: |
65 | raise Exception("Network type not recognized correctly") | |
93a06242 | 66 | |
bbe86767 JM |
67 | def check_sp_type(dev, sp_type): |
68 | type = dev.get_status_field("sp_type") | |
69 | if type is None: | |
70 | raise Exception("sp_type not available") | |
71 | if type != sp_type: | |
72 | raise Exception("sp_type did not indicate home network") | |
efd43d85 | 73 | |
bbe86767 | 74 | def hlr_auc_gw_available(): |
efd43d85 JM |
75 | if not os.path.exists("/tmp/hlr_auc_gw.sock"): |
76 | logger.info("No hlr_auc_gw available"); | |
bbe86767 | 77 | return False |
efd43d85 JM |
78 | if not os.path.exists("../../hostapd/hlr_auc_gw"): |
79 | logger.info("No hlr_auc_gw available"); | |
bbe86767 JM |
80 | return False |
81 | return True | |
efd43d85 | 82 | |
bbe86767 JM |
83 | def interworking_ext_sim_connect(dev, bssid, method): |
84 | dev.request("INTERWORKING_CONNECT " + bssid) | |
efd43d85 | 85 | |
bbe86767 | 86 | ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15) |
efd43d85 JM |
87 | if ev is None: |
88 | raise Exception("Network connected timed out") | |
bbe86767 | 89 | if "(" + method + ")" not in ev: |
efd43d85 JM |
90 | raise Exception("Unexpected EAP method selection") |
91 | ||
bbe86767 | 92 | ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15) |
efd43d85 JM |
93 | if ev is None: |
94 | raise Exception("Wait for external SIM processing request timed out") | |
95 | p = ev.split(':', 2) | |
96 | if p[1] != "GSM-AUTH": | |
97 | raise Exception("Unexpected CTRL-REQ-SIM type") | |
98 | id = p[0].split('-')[3] | |
99 | rand = p[2].split(' ')[0] | |
100 | ||
101 | res = subprocess.check_output(["../../hostapd/hlr_auc_gw", | |
102 | "-m", | |
103 | "auth_serv/hlr_auc_gw.milenage_db", | |
104 | "GSM-AUTH-REQ 232010000000000 " + rand]) | |
105 | if "GSM-AUTH-RESP" not in res: | |
106 | raise Exception("Unexpected hlr_auc_gw response") | |
107 | resp = res.split(' ')[2].rstrip() | |
108 | ||
bbe86767 JM |
109 | dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp) |
110 | ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15) | |
efd43d85 JM |
111 | if ev is None: |
112 | raise Exception("Connection timed out") | |
f4defd91 | 113 | |
8fba2e5d JM |
114 | def interworking_connect(dev, bssid, method): |
115 | dev.request("INTERWORKING_CONNECT " + bssid) | |
116 | ||
117 | ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15) | |
118 | if ev is None: | |
119 | raise Exception("Network connected timed out") | |
120 | if "(" + method + ")" not in ev: | |
121 | raise Exception("Unexpected EAP method selection") | |
122 | ||
123 | ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=15) | |
124 | if ev is None: | |
125 | raise Exception("Connection timed out") | |
126 | ||
715bf904 JM |
127 | def check_probe_resp(wt, bssid_unexpected, bssid_expected): |
128 | if bssid_unexpected: | |
129 | count = wt.get_bss_counter("probe_response", bssid_unexpected) | |
130 | if count > 0: | |
131 | raise Exception("Unexpected Probe Response frame from AP") | |
132 | ||
133 | if bssid_expected: | |
134 | count = wt.get_bss_counter("probe_response", bssid_expected) | |
135 | if count == 0: | |
136 | raise Exception("No Probe Response frame from AP") | |
137 | ||
2cdd91d8 JM |
138 | def test_ap_anqp_sharing(dev, apdev): |
139 | """ANQP sharing within ESS and explicit unshare""" | |
140 | bssid = apdev[0]['bssid'] | |
141 | params = hs20_ap_params() | |
142 | params['hessid'] = bssid | |
143 | hostapd.add_ap(apdev[0]['ifname'], params) | |
144 | ||
145 | bssid2 = apdev[1]['bssid'] | |
146 | params = hs20_ap_params() | |
147 | params['hessid'] = bssid | |
148 | params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ] | |
149 | hostapd.add_ap(apdev[1]['ifname'], params) | |
150 | ||
2cdd91d8 JM |
151 | dev[0].hs20_enable() |
152 | id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test", | |
153 | 'password': "secret", | |
154 | 'domain': "example.com" }) | |
155 | logger.info("Normal network selection with shared ANQP results") | |
2f37a66d | 156 | interworking_select(dev[0], None, "home", freq="2412") |
2cdd91d8 JM |
157 | dev[0].dump_monitor() |
158 | ||
159 | res1 = dev[0].get_bss(bssid) | |
160 | res2 = dev[0].get_bss(bssid2) | |
161 | if res1['anqp_nai_realm'] != res2['anqp_nai_realm']: | |
162 | raise Exception("ANQP results were not shared between BSSes") | |
163 | ||
164 | logger.info("Explicit ANQP request to unshare ANQP results") | |
165 | dev[0].request("ANQP_GET " + bssid + " 263") | |
166 | ev = dev[0].wait_event(["RX-ANQP"], timeout=5) | |
167 | if ev is None: | |
168 | raise Exception("ANQP operation timed out") | |
169 | ||
170 | dev[0].request("ANQP_GET " + bssid2 + " 263") | |
171 | ev = dev[0].wait_event(["RX-ANQP"], timeout=5) | |
172 | if ev is None: | |
173 | raise Exception("ANQP operation timed out") | |
174 | ||
175 | res1 = dev[0].get_bss(bssid) | |
176 | res2 = dev[0].get_bss(bssid2) | |
177 | if res1['anqp_nai_realm'] == res2['anqp_nai_realm']: | |
178 | raise Exception("ANQP results were not unshared") | |
179 | ||
715bf904 JM |
180 | def test_ap_interworking_scan_filtering(dev, apdev): |
181 | """Interworking scan filtering with HESSID and access network type""" | |
182 | bssid = apdev[0]['bssid'] | |
183 | params = hs20_ap_params() | |
184 | ssid = "test-hs20-ap1" | |
185 | params['ssid'] = ssid | |
186 | params['hessid'] = bssid | |
187 | hostapd.add_ap(apdev[0]['ifname'], params) | |
188 | ||
189 | bssid2 = apdev[1]['bssid'] | |
190 | params = hs20_ap_params() | |
191 | ssid2 = "test-hs20-ap2" | |
192 | params['ssid'] = ssid2 | |
193 | params['hessid'] = bssid2 | |
194 | params['access_network_type'] = "1" | |
8175854e JM |
195 | del params['venue_group'] |
196 | del params['venue_type'] | |
715bf904 JM |
197 | hostapd.add_ap(apdev[1]['ifname'], params) |
198 | ||
715bf904 JM |
199 | dev[0].hs20_enable() |
200 | ||
201 | wt = Wlantest() | |
202 | wt.flush() | |
203 | ||
204 | logger.info("Check probe request filtering based on HESSID") | |
205 | ||
206 | dev[0].request("SET hessid " + bssid2) | |
0589f401 | 207 | dev[0].scan(freq="2412") |
94a2dd0b | 208 | time.sleep(0.03) |
715bf904 JM |
209 | check_probe_resp(wt, bssid, bssid2) |
210 | ||
211 | logger.info("Check probe request filtering based on access network type") | |
212 | ||
213 | wt.clear_bss_counters(bssid) | |
214 | wt.clear_bss_counters(bssid2) | |
215 | dev[0].request("SET hessid 00:00:00:00:00:00") | |
216 | dev[0].request("SET access_network_type 14") | |
0589f401 | 217 | dev[0].scan(freq="2412") |
94a2dd0b | 218 | time.sleep(0.03) |
715bf904 JM |
219 | check_probe_resp(wt, bssid2, bssid) |
220 | ||
221 | wt.clear_bss_counters(bssid) | |
222 | wt.clear_bss_counters(bssid2) | |
223 | dev[0].request("SET hessid 00:00:00:00:00:00") | |
224 | dev[0].request("SET access_network_type 1") | |
0589f401 | 225 | dev[0].scan(freq="2412") |
94a2dd0b | 226 | time.sleep(0.03) |
715bf904 JM |
227 | check_probe_resp(wt, bssid, bssid2) |
228 | ||
229 | logger.info("Check probe request filtering based on HESSID and ANT") | |
230 | ||
231 | wt.clear_bss_counters(bssid) | |
232 | wt.clear_bss_counters(bssid2) | |
233 | dev[0].request("SET hessid " + bssid) | |
234 | dev[0].request("SET access_network_type 14") | |
0589f401 | 235 | dev[0].scan(freq="2412") |
94a2dd0b | 236 | time.sleep(0.03) |
715bf904 JM |
237 | check_probe_resp(wt, bssid2, bssid) |
238 | ||
239 | wt.clear_bss_counters(bssid) | |
240 | wt.clear_bss_counters(bssid2) | |
241 | dev[0].request("SET hessid " + bssid2) | |
242 | dev[0].request("SET access_network_type 14") | |
0589f401 | 243 | dev[0].scan(freq="2412") |
94a2dd0b | 244 | time.sleep(0.03) |
715bf904 JM |
245 | check_probe_resp(wt, bssid, None) |
246 | check_probe_resp(wt, bssid2, None) | |
247 | ||
248 | wt.clear_bss_counters(bssid) | |
249 | wt.clear_bss_counters(bssid2) | |
250 | dev[0].request("SET hessid " + bssid) | |
251 | dev[0].request("SET access_network_type 1") | |
0589f401 | 252 | dev[0].scan(freq="2412") |
94a2dd0b | 253 | time.sleep(0.03) |
715bf904 JM |
254 | check_probe_resp(wt, bssid, None) |
255 | check_probe_resp(wt, bssid2, None) | |
256 | ||
bbe86767 JM |
257 | def test_ap_hs20_select(dev, apdev): |
258 | """Hotspot 2.0 network selection""" | |
259 | bssid = apdev[0]['bssid'] | |
260 | params = hs20_ap_params() | |
261 | params['hessid'] = bssid | |
262 | hostapd.add_ap(apdev[0]['ifname'], params) | |
263 | ||
264 | dev[0].hs20_enable() | |
2232edf8 JM |
265 | id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test", |
266 | 'password': "secret", | |
267 | 'domain': "example.com" }) | |
bbe86767 JM |
268 | interworking_select(dev[0], bssid, "home") |
269 | ||
270 | dev[0].remove_cred(id) | |
2232edf8 JM |
271 | id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test", |
272 | 'password': "secret", | |
273 | 'domain': "no.match.example.com" }) | |
2f37a66d | 274 | interworking_select(dev[0], bssid, "roaming", freq="2412") |
bbe86767 JM |
275 | |
276 | dev[0].set_cred_quoted(id, "realm", "no.match.example.com"); | |
2f37a66d | 277 | interworking_select(dev[0], bssid, no_match=True, freq="2412") |
bbe86767 | 278 | |
459e96cd JM |
279 | def hs20_simulated_sim(dev, ap, method): |
280 | bssid = ap['bssid'] | |
281 | params = hs20_ap_params() | |
282 | params['hessid'] = bssid | |
283 | params['anqp_3gpp_cell_net'] = "555,444" | |
284 | params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org" | |
285 | hostapd.add_ap(ap['ifname'], params) | |
286 | ||
459e96cd JM |
287 | dev.hs20_enable() |
288 | dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method, | |
289 | 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"}) | |
2f37a66d | 290 | interworking_select(dev, "home", freq="2412") |
459e96cd JM |
291 | interworking_connect(dev, bssid, method) |
292 | check_sp_type(dev, "home") | |
293 | ||
294 | def test_ap_hs20_sim(dev, apdev): | |
295 | """Hotspot 2.0 with simulated SIM and EAP-SIM""" | |
296 | if not hlr_auc_gw_available(): | |
297 | return "skip" | |
298 | hs20_simulated_sim(dev[0], apdev[0], "SIM") | |
299 | ||
300 | def test_ap_hs20_aka(dev, apdev): | |
301 | """Hotspot 2.0 with simulated USIM and EAP-AKA""" | |
302 | if not hlr_auc_gw_available(): | |
303 | return "skip" | |
304 | hs20_simulated_sim(dev[0], apdev[0], "AKA") | |
305 | ||
306 | def test_ap_hs20_aka_prime(dev, apdev): | |
307 | """Hotspot 2.0 with simulated USIM and EAP-AKA'""" | |
308 | if not hlr_auc_gw_available(): | |
309 | return "skip" | |
310 | hs20_simulated_sim(dev[0], apdev[0], "AKA'") | |
311 | ||
bbe86767 JM |
312 | def test_ap_hs20_ext_sim(dev, apdev): |
313 | """Hotspot 2.0 with external SIM processing""" | |
314 | if not hlr_auc_gw_available(): | |
315 | return "skip" | |
316 | bssid = apdev[0]['bssid'] | |
317 | params = hs20_ap_params() | |
318 | params['hessid'] = bssid | |
319 | params['anqp_3gpp_cell_net'] = "232,01" | |
320 | params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org" | |
321 | hostapd.add_ap(apdev[0]['ifname'], params) | |
322 | ||
323 | dev[0].hs20_enable() | |
324 | dev[0].request("SET external_sim 1") | |
2232edf8 | 325 | dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" }) |
2f37a66d | 326 | interworking_select(dev[0], "home", freq="2412") |
bbe86767 JM |
327 | interworking_ext_sim_connect(dev[0], bssid, "SIM") |
328 | check_sp_type(dev[0], "home") | |
59f8a3c6 JM |
329 | |
330 | def test_ap_hs20_ext_sim_roaming(dev, apdev): | |
331 | """Hotspot 2.0 with external SIM processing in roaming network""" | |
332 | if not hlr_auc_gw_available(): | |
333 | return "skip" | |
334 | bssid = apdev[0]['bssid'] | |
335 | params = hs20_ap_params() | |
336 | params['hessid'] = bssid | |
337 | params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56" | |
338 | params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org" | |
339 | hostapd.add_ap(apdev[0]['ifname'], params) | |
340 | ||
341 | dev[0].hs20_enable() | |
342 | dev[0].request("SET external_sim 1") | |
2232edf8 | 343 | dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" }) |
2f37a66d | 344 | interworking_select(dev[0], "roaming", freq="2412") |
59f8a3c6 JM |
345 | interworking_ext_sim_connect(dev[0], bssid, "SIM") |
346 | check_sp_type(dev[0], "roaming") | |
8fba2e5d JM |
347 | |
348 | def test_ap_hs20_username(dev, apdev): | |
349 | """Hotspot 2.0 connection in username/password credential""" | |
8fba2e5d JM |
350 | bssid = apdev[0]['bssid'] |
351 | params = hs20_ap_params() | |
352 | params['hessid'] = bssid | |
353 | hostapd.add_ap(apdev[0]['ifname'], params) | |
354 | ||
355 | dev[0].hs20_enable() | |
2232edf8 JM |
356 | id = dev[0].add_cred_values({ 'realm': "example.com", |
357 | 'username': "hs20-test", | |
358 | 'password': "password", | |
359 | 'domain': "example.com" }) | |
2f37a66d | 360 | interworking_select(dev[0], bssid, "home", freq="2412") |
8fba2e5d JM |
361 | interworking_connect(dev[0], bssid, "TTLS") |
362 | check_sp_type(dev[0], "home") | |
363 | ||
dcd68168 JM |
364 | def eap_test(dev, ap, eap_params, method, user): |
365 | bssid = ap['bssid'] | |
366 | params = hs20_ap_params() | |
367 | params['nai_realm'] = [ "0,example.com," + eap_params ] | |
368 | hostapd.add_ap(ap['ifname'], params) | |
369 | ||
dcd68168 JM |
370 | dev.hs20_enable() |
371 | dev.add_cred_values({ 'realm': "example.com", | |
372 | 'username': user, | |
373 | 'password': "password" }) | |
2f37a66d | 374 | interworking_select(dev, bssid, freq="2412") |
dcd68168 JM |
375 | interworking_connect(dev, bssid, method) |
376 | ||
377 | def test_ap_hs20_eap_peap_mschapv2(dev, apdev): | |
378 | """Hotspot 2.0 connection with PEAP/MSCHAPV2""" | |
379 | eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user") | |
380 | ||
381 | def test_ap_hs20_eap_peap_gtc(dev, apdev): | |
382 | """Hotspot 2.0 connection with PEAP/GTC""" | |
383 | eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user") | |
384 | ||
385 | def test_ap_hs20_eap_ttls_chap(dev, apdev): | |
386 | """Hotspot 2.0 connection with TTLS/CHAP""" | |
387 | eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user") | |
388 | ||
389 | def test_ap_hs20_eap_ttls_mschap(dev, apdev): | |
390 | """Hotspot 2.0 connection with TTLS/MSCHAP""" | |
391 | eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user") | |
392 | ||
393 | def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev): | |
394 | """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2""" | |
395 | eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user") | |
396 | ||
397 | def test_ap_hs20_eap_fast_mschapv2(dev, apdev): | |
398 | """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2""" | |
399 | eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user") | |
400 | ||
401 | def test_ap_hs20_eap_fast_gtc(dev, apdev): | |
402 | """Hotspot 2.0 connection with FAST/EAP-GTC""" | |
403 | eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user") | |
404 | ||
405 | def test_ap_hs20_eap_tls(dev, apdev): | |
406 | """Hotspot 2.0 connection with EAP-TLS""" | |
407 | bssid = apdev[0]['bssid'] | |
408 | params = hs20_ap_params() | |
409 | params['nai_realm'] = [ "0,example.com,13[5:6]" ] | |
410 | hostapd.add_ap(apdev[0]['ifname'], params) | |
411 | ||
dcd68168 JM |
412 | dev[0].hs20_enable() |
413 | dev[0].add_cred_values({ 'realm': "example.com", | |
414 | 'username': "certificate-user", | |
415 | 'ca_cert': "auth_serv/ca.pem", | |
416 | 'client_cert': "auth_serv/user.pem", | |
417 | 'private_key': "auth_serv/user.key"}) | |
2f37a66d | 418 | interworking_select(dev[0], bssid, freq="2412") |
dcd68168 JM |
419 | interworking_connect(dev[0], bssid, "TLS") |
420 | ||
0aca5d13 JM |
421 | def test_ap_hs20_nai_realms(dev, apdev): |
422 | """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP""" | |
423 | bssid = apdev[0]['bssid'] | |
424 | params = hs20_ap_params() | |
425 | params['hessid'] = bssid | |
426 | params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ] | |
427 | hostapd.add_ap(apdev[0]['ifname'], params) | |
428 | ||
0aca5d13 JM |
429 | dev[0].hs20_enable() |
430 | id = dev[0].add_cred_values({ 'realm': "example.com", | |
431 | 'username': "pap user", | |
432 | 'password': "password", | |
433 | 'domain': "example.com" }) | |
2f37a66d | 434 | interworking_select(dev[0], bssid, "home", freq="2412") |
0aca5d13 JM |
435 | interworking_connect(dev[0], bssid, "TTLS") |
436 | check_sp_type(dev[0], "home") | |
437 | ||
e209eb98 JM |
438 | def test_ap_hs20_roaming_consortium(dev, apdev): |
439 | """Hotspot 2.0 connection based on roaming consortium match""" | |
440 | bssid = apdev[0]['bssid'] | |
441 | params = hs20_ap_params() | |
442 | params['hessid'] = bssid | |
443 | hostapd.add_ap(apdev[0]['ifname'], params) | |
444 | ||
e209eb98 JM |
445 | dev[0].hs20_enable() |
446 | id = dev[0].add_cred_values({ 'realm': "example.com", | |
447 | 'username': "user", | |
448 | 'password': "password", | |
449 | 'domain': "example.com", | |
450 | 'roaming_consortium': "fedcba", | |
451 | 'eap': "PEAP" }) | |
2f37a66d | 452 | interworking_select(dev[0], bssid, "home", freq="2412") |
e209eb98 JM |
453 | interworking_connect(dev[0], bssid, "PEAP") |
454 | check_sp_type(dev[0], "home") | |
455 | ||
8fba2e5d JM |
456 | def test_ap_hs20_username_roaming(dev, apdev): |
457 | """Hotspot 2.0 connection in username/password credential (roaming)""" | |
8fba2e5d JM |
458 | bssid = apdev[0]['bssid'] |
459 | params = hs20_ap_params() | |
460 | params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]", | |
461 | "0,roaming.example.com,21[2:4][5:7]", | |
462 | "0,another.example.com" ] | |
463 | params['domain_name'] = "another.example.com" | |
464 | params['hessid'] = bssid | |
465 | hostapd.add_ap(apdev[0]['ifname'], params) | |
466 | ||
467 | dev[0].hs20_enable() | |
2232edf8 JM |
468 | id = dev[0].add_cred_values({ 'realm': "roaming.example.com", |
469 | 'username': "hs20-test", | |
470 | 'password': "password", | |
471 | 'domain': "example.com" }) | |
2f37a66d | 472 | interworking_select(dev[0], bssid, "roaming", freq="2412") |
8fba2e5d JM |
473 | interworking_connect(dev[0], bssid, "TTLS") |
474 | check_sp_type(dev[0], "roaming") | |
475 | ||
476 | def test_ap_hs20_username_unknown(dev, apdev): | |
477 | """Hotspot 2.0 connection in username/password credential (no domain in cred)""" | |
8fba2e5d JM |
478 | bssid = apdev[0]['bssid'] |
479 | params = hs20_ap_params() | |
480 | params['hessid'] = bssid | |
481 | hostapd.add_ap(apdev[0]['ifname'], params) | |
482 | ||
483 | dev[0].hs20_enable() | |
2232edf8 JM |
484 | id = dev[0].add_cred_values({ 'realm': "example.com", |
485 | 'username': "hs20-test", | |
486 | 'password': "password" }) | |
2f37a66d | 487 | interworking_select(dev[0], bssid, "unknown", freq="2412") |
8fba2e5d JM |
488 | interworking_connect(dev[0], bssid, "TTLS") |
489 | check_sp_type(dev[0], "unknown") | |
490 | ||
491 | def test_ap_hs20_username_unknown2(dev, apdev): | |
492 | """Hotspot 2.0 connection in username/password credential (no domain advertized)""" | |
8fba2e5d JM |
493 | bssid = apdev[0]['bssid'] |
494 | params = hs20_ap_params() | |
495 | params['hessid'] = bssid | |
496 | del params['domain_name'] | |
497 | hostapd.add_ap(apdev[0]['ifname'], params) | |
498 | ||
499 | dev[0].hs20_enable() | |
2232edf8 JM |
500 | id = dev[0].add_cred_values({ 'realm': "example.com", |
501 | 'username': "hs20-test", | |
502 | 'password': "password", | |
503 | 'domain': "example.com" }) | |
2f37a66d | 504 | interworking_select(dev[0], bssid, "unknown", freq="2412") |
8fba2e5d JM |
505 | interworking_connect(dev[0], bssid, "TTLS") |
506 | check_sp_type(dev[0], "unknown") | |
d1ba402f | 507 | |
483691bd JM |
508 | def test_ap_hs20_gas_while_associated(dev, apdev): |
509 | """Hotspot 2.0 connection with GAS query while associated""" | |
510 | bssid = apdev[0]['bssid'] | |
511 | params = hs20_ap_params() | |
512 | params['hessid'] = bssid | |
513 | hostapd.add_ap(apdev[0]['ifname'], params) | |
514 | ||
483691bd JM |
515 | dev[0].hs20_enable() |
516 | id = dev[0].add_cred_values({ 'realm': "example.com", | |
517 | 'username': "hs20-test", | |
518 | 'password': "password", | |
519 | 'domain': "example.com" }) | |
2f37a66d | 520 | interworking_select(dev[0], bssid, "home", freq="2412") |
483691bd JM |
521 | interworking_connect(dev[0], bssid, "TTLS") |
522 | ||
523 | logger.info("Verifying GAS query while associated") | |
524 | dev[0].request("FETCH_ANQP") | |
525 | for i in range(0, 6): | |
526 | ev = dev[0].wait_event(["RX-ANQP"], timeout=5) | |
527 | if ev is None: | |
528 | raise Exception("Operation timed out") | |
529 | ||
530 | def test_ap_hs20_gas_frag_while_associated(dev, apdev): | |
531 | """Hotspot 2.0 connection with fragmented GAS query while associated""" | |
532 | bssid = apdev[0]['bssid'] | |
533 | params = hs20_ap_params() | |
534 | params['hessid'] = bssid | |
535 | hostapd.add_ap(apdev[0]['ifname'], params) | |
536 | hapd = hostapd.Hostapd(apdev[0]['ifname']) | |
537 | hapd.set("gas_frag_limit", "50") | |
538 | ||
483691bd JM |
539 | dev[0].hs20_enable() |
540 | id = dev[0].add_cred_values({ 'realm': "example.com", | |
541 | 'username': "hs20-test", | |
542 | 'password': "password", | |
543 | 'domain': "example.com" }) | |
2f37a66d | 544 | interworking_select(dev[0], bssid, "home", freq="2412") |
483691bd JM |
545 | interworking_connect(dev[0], bssid, "TTLS") |
546 | ||
547 | logger.info("Verifying GAS query while associated") | |
548 | dev[0].request("FETCH_ANQP") | |
549 | for i in range(0, 6): | |
550 | ev = dev[0].wait_event(["RX-ANQP"], timeout=5) | |
551 | if ev is None: | |
552 | raise Exception("Operation timed out") | |
553 | ||
6a0b4002 JM |
554 | def test_ap_hs20_multiple_connects(dev, apdev): |
555 | """Hotspot 2.0 connection through multiple network selections""" | |
556 | bssid = apdev[0]['bssid'] | |
557 | params = hs20_ap_params() | |
558 | params['hessid'] = bssid | |
559 | hostapd.add_ap(apdev[0]['ifname'], params) | |
560 | ||
561 | dev[0].hs20_enable() | |
562 | values = { 'realm': "example.com", | |
563 | 'username': "hs20-test", | |
564 | 'password': "password", | |
565 | 'domain': "example.com" } | |
566 | id = dev[0].add_cred_values(values) | |
567 | ||
568 | for i in range(0, 3): | |
569 | logger.info("Starting Interworking network selection") | |
2f37a66d | 570 | dev[0].request("INTERWORKING_SELECT auto freq=2412") |
6a0b4002 JM |
571 | while True: |
572 | ev = dev[0].wait_event(["INTERWORKING-NO-MATCH", | |
573 | "INTERWORKING-ALREADY-CONNECTED", | |
574 | "CTRL-EVENT-CONNECTED"], timeout=15) | |
575 | if ev is None: | |
576 | raise Exception("Connection timed out") | |
577 | if "INTERWORKING-NO-MATCH" in ev: | |
578 | raise Exception("Matching AP not found") | |
579 | if "CTRL-EVENT-CONNECTED" in ev: | |
580 | break | |
581 | if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev: | |
582 | break | |
583 | if i == 0: | |
584 | dev[0].request("DISCONNECT") | |
585 | dev[0].dump_monitor() | |
586 | ||
587 | networks = dev[0].list_networks() | |
588 | if len(networks) > 1: | |
589 | raise Exception("Duplicated network block detected") | |
590 | ||
b4264f8f JM |
591 | def test_ap_hs20_disallow_aps(dev, apdev): |
592 | """Hotspot 2.0 connection and disallow_aps""" | |
593 | bssid = apdev[0]['bssid'] | |
594 | params = hs20_ap_params() | |
595 | params['hessid'] = bssid | |
596 | hostapd.add_ap(apdev[0]['ifname'], params) | |
597 | ||
598 | dev[0].hs20_enable() | |
599 | values = { 'realm': "example.com", | |
600 | 'username': "hs20-test", | |
601 | 'password': "password", | |
602 | 'domain': "example.com" } | |
603 | id = dev[0].add_cred_values(values) | |
604 | ||
605 | logger.info("Verify disallow_aps bssid") | |
606 | dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':')) | |
607 | dev[0].request("INTERWORKING_SELECT auto") | |
608 | ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15) | |
609 | if ev is None: | |
610 | raise Exception("Network selection timed out") | |
611 | dev[0].dump_monitor() | |
612 | ||
613 | logger.info("Verify disallow_aps ssid") | |
614 | dev[0].request("SET disallow_aps ssid 746573742d68733230") | |
2f37a66d | 615 | dev[0].request("INTERWORKING_SELECT auto freq=2412") |
b4264f8f JM |
616 | ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15) |
617 | if ev is None: | |
618 | raise Exception("Network selection timed out") | |
619 | dev[0].dump_monitor() | |
620 | ||
621 | logger.info("Verify disallow_aps clear") | |
622 | dev[0].request("SET disallow_aps ") | |
2f37a66d | 623 | interworking_select(dev[0], bssid, "home", freq="2412") |
b4264f8f JM |
624 | |
625 | dev[0].request("SET disallow_aps bssid " + bssid.translate(None, ':')) | |
626 | ret = dev[0].request("INTERWORKING_CONNECT " + bssid) | |
627 | if "FAIL" not in ret: | |
628 | raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected") | |
629 | ||
d1ba402f JM |
630 | def policy_test(dev, ap, values, only_one=True): |
631 | dev.dump_monitor() | |
632 | logger.info("Verify network selection to AP " + ap['ifname']) | |
633 | bssid = ap['bssid'] | |
634 | dev.hs20_enable() | |
635 | id = dev.add_cred_values(values) | |
2f37a66d | 636 | dev.request("INTERWORKING_SELECT auto freq=2412") |
d1ba402f JM |
637 | while True: |
638 | ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH", | |
639 | "CTRL-EVENT-CONNECTED"], timeout=15) | |
640 | if ev is None: | |
641 | raise Exception("Connection timed out") | |
642 | if "INTERWORKING-NO-MATCH" in ev: | |
643 | raise Exception("Matching AP not found") | |
644 | if only_one and "INTERWORKING-AP" in ev and bssid not in ev: | |
645 | raise Exception("Unexpected AP claimed acceptable") | |
646 | if "CTRL-EVENT-CONNECTED" in ev: | |
647 | if bssid not in ev: | |
648 | raise Exception("Connected to incorrect BSS") | |
649 | break | |
650 | ||
651 | conn_bssid = dev.get_status_field("bssid") | |
652 | if conn_bssid != bssid: | |
653 | raise Exception("bssid information points to incorrect BSS") | |
654 | ||
655 | dev.remove_cred(id) | |
656 | dev.dump_monitor() | |
657 | ||
d355372c JM |
658 | def default_cred(): |
659 | return { 'realm': "example.com", | |
660 | 'username': "hs20-test", | |
661 | 'password': "password" } | |
662 | ||
d1ba402f JM |
663 | def test_ap_hs20_req_roaming_consortium(dev, apdev): |
664 | """Hotspot 2.0 required roaming consortium""" | |
665 | params = hs20_ap_params() | |
666 | hostapd.add_ap(apdev[0]['ifname'], params) | |
667 | ||
668 | params = hs20_ap_params() | |
669 | params['ssid'] = "test-hs20-other" | |
670 | params['roaming_consortium'] = [ "223344" ] | |
671 | hostapd.add_ap(apdev[1]['ifname'], params) | |
672 | ||
d355372c JM |
673 | values = default_cred() |
674 | values['required_roaming_consortium'] = "223344" | |
d1ba402f JM |
675 | policy_test(dev[0], apdev[1], values) |
676 | values['required_roaming_consortium'] = "112233" | |
677 | policy_test(dev[0], apdev[0], values) | |
d355372c JM |
678 | |
679 | def test_ap_hs20_excluded_ssid(dev, apdev): | |
680 | """Hotspot 2.0 exclusion based on SSID""" | |
681 | params = hs20_ap_params() | |
682 | hostapd.add_ap(apdev[0]['ifname'], params) | |
683 | ||
684 | params = hs20_ap_params() | |
685 | params['ssid'] = "test-hs20-other" | |
686 | params['roaming_consortium'] = [ "223344" ] | |
687 | hostapd.add_ap(apdev[1]['ifname'], params) | |
688 | ||
689 | values = default_cred() | |
690 | values['excluded_ssid'] = "test-hs20" | |
691 | policy_test(dev[0], apdev[1], values) | |
692 | values['excluded_ssid'] = "test-hs20-other" | |
693 | policy_test(dev[0], apdev[0], values) |