]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_ap_hs20.py
tests: Avoid race conditions in couple of Hotspot 2.0 test cases
[thirdparty/hostap.git] / tests / hwsim / test_ap_hs20.py
1 # Hotspot 2.0 tests
2 # Copyright (c) 2013-2019, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 from remotehost import remote_compatible
8 import base64
9 import binascii
10 import struct
11 import time
12 import logging
13 logger = logging.getLogger()
14 import os
15 import os.path
16 import socket
17 import subprocess
18
19 import hostapd
20 from utils import HwsimSkip, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger
21 import hwsim_utils
22 from tshark import run_tshark
23 from wlantest import Wlantest
24 from wpasupplicant import WpaSupplicant
25 from test_ap_eap import check_eap_capa, check_domain_match_full
26 from test_gas import gas_rx, parse_gas, action_response, anqp_initial_resp, send_gas_resp, ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE
27
28 def hs20_ap_params(ssid="test-hs20"):
29 params = hostapd.wpa2_params(ssid=ssid)
30 params['wpa_key_mgmt'] = "WPA-EAP"
31 params['ieee80211w'] = "1"
32 params['ieee8021x'] = "1"
33 params['auth_server_addr'] = "127.0.0.1"
34 params['auth_server_port'] = "1812"
35 params['auth_server_shared_secret'] = "radius"
36 params['interworking'] = "1"
37 params['access_network_type'] = "14"
38 params['internet'] = "1"
39 params['asra'] = "0"
40 params['esr'] = "0"
41 params['uesa'] = "0"
42 params['venue_group'] = "7"
43 params['venue_type'] = "1"
44 params['venue_name'] = ["eng:Example venue", "fin:Esimerkkipaikka"]
45 params['roaming_consortium'] = ["112233", "1020304050", "010203040506",
46 "fedcba"]
47 params['domain_name'] = "example.com,another.example.com"
48 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]",
49 "0,another.example.com"]
50 params['hs20'] = "1"
51 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000"
52 params['hs20_conn_capab'] = ["1:0:2", "6:22:1", "17:5060:0"]
53 params['hs20_operating_class'] = "5173"
54 params['anqp_3gpp_cell_net'] = "244,91"
55 return params
56
57 def check_auto_select(dev, bssid):
58 dev.scan_for_bss(bssid, freq="2412")
59 dev.request("INTERWORKING_SELECT auto freq=2412")
60 ev = dev.wait_connected(timeout=15)
61 if bssid not in ev:
62 raise Exception("Connected to incorrect network")
63 dev.request("REMOVE_NETWORK all")
64 dev.wait_disconnected()
65 dev.dump_monitor()
66
67 def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
68 dev.dump_monitor()
69 if bssid and freq and not no_match:
70 dev.scan_for_bss(bssid, freq=freq)
71 freq_extra = " freq=" + str(freq) if freq else ""
72 dev.request("INTERWORKING_SELECT" + freq_extra)
73 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
74 timeout=15)
75 if ev is None:
76 raise Exception("Network selection timed out")
77 if no_match:
78 if "INTERWORKING-NO-MATCH" not in ev:
79 raise Exception("Unexpected network match")
80 return
81 if "INTERWORKING-NO-MATCH" in ev:
82 logger.info("Matching network not found - try again")
83 dev.dump_monitor()
84 dev.request("INTERWORKING_SELECT" + freq_extra)
85 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
86 timeout=15)
87 if ev is None:
88 raise Exception("Network selection timed out")
89 if "INTERWORKING-NO-MATCH" in ev:
90 raise Exception("Matching network not found")
91 if bssid and bssid not in ev:
92 raise Exception("Unexpected BSSID in match")
93 if type and "type=" + type not in ev:
94 raise Exception("Network type not recognized correctly")
95
96 def check_sp_type(dev, sp_type):
97 type = dev.get_status_field("sp_type")
98 if type is None:
99 raise Exception("sp_type not available")
100 if type != sp_type:
101 raise Exception("sp_type did not indicate %s network" % sp_type)
102
103 def hlr_auc_gw_available():
104 if not os.path.exists("/tmp/hlr_auc_gw.sock"):
105 raise HwsimSkip("No hlr_auc_gw socket available")
106 if not os.path.exists("../../hostapd/hlr_auc_gw"):
107 raise HwsimSkip("No hlr_auc_gw available")
108
109 def interworking_ext_sim_connect(dev, bssid, method):
110 dev.request("INTERWORKING_CONNECT " + bssid)
111 interworking_ext_sim_auth(dev, method)
112
113 def interworking_ext_sim_auth(dev, method):
114 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
115 if ev is None:
116 raise Exception("Network connected timed out")
117 if "(" + method + ")" not in ev:
118 raise Exception("Unexpected EAP method selection")
119
120 ev = dev.wait_event(["CTRL-REQ-SIM"], timeout=15)
121 if ev is None:
122 raise Exception("Wait for external SIM processing request timed out")
123 p = ev.split(':', 2)
124 if p[1] != "GSM-AUTH":
125 raise Exception("Unexpected CTRL-REQ-SIM type")
126 id = p[0].split('-')[3]
127 rand = p[2].split(' ')[0]
128
129 res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
130 "-m",
131 "auth_serv/hlr_auc_gw.milenage_db",
132 "GSM-AUTH-REQ 232010000000000 " + rand]).decode()
133 if "GSM-AUTH-RESP" not in res:
134 raise Exception("Unexpected hlr_auc_gw response")
135 resp = res.split(' ')[2].rstrip()
136
137 dev.request("CTRL-RSP-SIM-" + id + ":GSM-AUTH:" + resp)
138 dev.wait_connected(timeout=15)
139
140 def interworking_connect(dev, bssid, method):
141 dev.request("INTERWORKING_CONNECT " + bssid)
142 interworking_auth(dev, method)
143
144 def interworking_auth(dev, method):
145 ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
146 if ev is None:
147 raise Exception("Network connected timed out")
148 if "(" + method + ")" not in ev:
149 raise Exception("Unexpected EAP method selection")
150
151 dev.wait_connected(timeout=15)
152
153 def check_probe_resp(wt, bssid_unexpected, bssid_expected):
154 if bssid_unexpected:
155 count = wt.get_bss_counter("probe_response", bssid_unexpected)
156 if count > 0:
157 raise Exception("Unexpected Probe Response frame from AP")
158
159 if bssid_expected:
160 count = wt.get_bss_counter("probe_response", bssid_expected)
161 if count == 0:
162 raise Exception("No Probe Response frame from AP")
163
164 def test_ap_anqp_sharing(dev, apdev):
165 """ANQP sharing within ESS and explicit unshare"""
166 check_eap_capa(dev[0], "MSCHAPV2")
167 dev[0].flush_scan_cache()
168
169 bssid = apdev[0]['bssid']
170 params = hs20_ap_params()
171 params['hessid'] = bssid
172 hostapd.add_ap(apdev[0], params)
173
174 bssid2 = apdev[1]['bssid']
175 params = hs20_ap_params()
176 params['hessid'] = bssid
177 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]"]
178 hostapd.add_ap(apdev[1], params)
179
180 dev[0].hs20_enable()
181 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
182 'password': "secret",
183 'domain': "example.com"})
184 logger.info("Normal network selection with shared ANQP results")
185 dev[0].scan_for_bss(bssid, freq="2412")
186 dev[0].scan_for_bss(bssid2, freq="2412")
187 interworking_select(dev[0], None, "home", freq="2412")
188 dev[0].dump_monitor()
189 state = dev[0].get_status_field('wpa_state')
190 if state != "DISCONNECTED":
191 raise Exception("Unexpected wpa_state after INTERWORKING_SELECT: " + state)
192
193 logger.debug("BSS entries:\n" + dev[0].request("BSS RANGE=ALL"))
194 res1 = dev[0].get_bss(bssid)
195 res2 = dev[0].get_bss(bssid2)
196 if 'anqp_nai_realm' not in res1:
197 raise Exception("anqp_nai_realm not found for AP1")
198 if 'anqp_nai_realm' not in res2:
199 raise Exception("anqp_nai_realm not found for AP2")
200 if res1['anqp_nai_realm'] != res2['anqp_nai_realm']:
201 raise Exception("ANQP results were not shared between BSSes")
202
203 logger.info("Explicit ANQP request to unshare ANQP results")
204 dev[0].request("ANQP_GET " + bssid + " 263")
205 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
206 if ev is None:
207 raise Exception("ANQP operation timed out")
208
209 dev[0].request("ANQP_GET " + bssid2 + " 263")
210 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
211 if ev is None:
212 raise Exception("ANQP operation timed out")
213
214 res1 = dev[0].get_bss(bssid)
215 res2 = dev[0].get_bss(bssid2)
216 if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
217 raise Exception("ANQP results were not unshared")
218
219 def test_ap_anqp_domain_id(dev, apdev):
220 """ANQP Domain ID"""
221 check_eap_capa(dev[0], "MSCHAPV2")
222 dev[0].flush_scan_cache()
223
224 bssid = apdev[0]['bssid']
225 params = hs20_ap_params()
226 params['hessid'] = bssid
227 params['anqp_domain_id'] = '1234'
228 hostapd.add_ap(apdev[0], params)
229
230 bssid2 = apdev[1]['bssid']
231 params = hs20_ap_params()
232 params['hessid'] = bssid
233 params['anqp_domain_id'] = '1234'
234 hostapd.add_ap(apdev[1], params)
235
236 dev[0].hs20_enable()
237 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
238 'password': "secret",
239 'domain': "example.com"})
240 dev[0].scan_for_bss(bssid, freq="2412")
241 dev[0].scan_for_bss(bssid2, freq="2412")
242 interworking_select(dev[0], None, "home", freq="2412")
243
244 def test_ap_anqp_no_sharing_diff_ess(dev, apdev):
245 """ANQP no sharing between ESSs"""
246 check_eap_capa(dev[0], "MSCHAPV2")
247 dev[0].flush_scan_cache()
248
249 bssid = apdev[0]['bssid']
250 params = hs20_ap_params()
251 params['hessid'] = bssid
252 hostapd.add_ap(apdev[0], params)
253
254 bssid2 = apdev[1]['bssid']
255 params = hs20_ap_params(ssid="test-hs20-another")
256 params['hessid'] = bssid
257 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]"]
258 hostapd.add_ap(apdev[1], params)
259
260 dev[0].hs20_enable()
261 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
262 'password': "secret",
263 'domain': "example.com"})
264 logger.info("Normal network selection with shared ANQP results")
265 dev[0].scan_for_bss(bssid, freq="2412")
266 dev[0].scan_for_bss(bssid2, freq="2412")
267 interworking_select(dev[0], None, "home", freq="2412")
268
269 def test_ap_anqp_no_sharing_missing_info(dev, apdev):
270 """ANQP no sharing due to missing information"""
271 check_eap_capa(dev[0], "MSCHAPV2")
272 dev[0].flush_scan_cache()
273
274 bssid = apdev[0]['bssid']
275 params = hs20_ap_params()
276 params['hessid'] = bssid
277 del params['roaming_consortium']
278 del params['domain_name']
279 del params['anqp_3gpp_cell_net']
280 del params['nai_realm']
281 hostapd.add_ap(apdev[0], params)
282
283 bssid2 = apdev[1]['bssid']
284 params = hs20_ap_params()
285 params['hessid'] = bssid
286 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]"]
287 hostapd.add_ap(apdev[1], params)
288
289 dev[0].hs20_enable()
290 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
291 'password': "secret",
292 'domain': "example.com"})
293 logger.info("Normal network selection with shared ANQP results")
294 dev[0].scan_for_bss(bssid, freq="2412")
295 dev[0].scan_for_bss(bssid2, freq="2412")
296 interworking_select(dev[0], None, "home", freq="2412")
297
298 def test_ap_anqp_sharing_oom(dev, apdev):
299 """ANQP sharing within ESS and explicit unshare OOM"""
300 check_eap_capa(dev[0], "MSCHAPV2")
301 dev[0].flush_scan_cache()
302
303 bssid = apdev[0]['bssid']
304 params = hs20_ap_params()
305 params['hessid'] = bssid
306 hostapd.add_ap(apdev[0], params)
307
308 bssid2 = apdev[1]['bssid']
309 params = hs20_ap_params()
310 params['hessid'] = bssid
311 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]"]
312 hostapd.add_ap(apdev[1], params)
313
314 dev[0].hs20_enable()
315 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
316 'password': "secret",
317 'domain': "example.com"})
318 dev[0].scan_for_bss(bssid, freq="2412")
319 dev[0].scan_for_bss(bssid2, freq="2412")
320 interworking_select(dev[0], None, "home", freq="2412")
321 dev[0].dump_monitor()
322
323 with alloc_fail(dev[0], 1, "wpa_bss_anqp_clone"):
324 dev[0].request("ANQP_GET " + bssid + " 263")
325 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
326 if ev is None:
327 raise Exception("ANQP operation timed out")
328
329 def test_ap_nai_home_realm_query(dev, apdev):
330 """NAI Home Realm Query"""
331 check_eap_capa(dev[0], "MSCHAPV2")
332 bssid = apdev[0]['bssid']
333 params = hs20_ap_params()
334 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]",
335 "0,another.example.org"]
336 hostapd.add_ap(apdev[0], params)
337
338 dev[0].scan(freq="2412")
339 dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
340 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
341 if ev is None:
342 raise Exception("ANQP operation timed out")
343 nai1 = dev[0].get_bss(bssid)['anqp_nai_realm']
344 dev[0].dump_monitor()
345
346 dev[0].request("ANQP_GET " + bssid + " 263")
347 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
348 if ev is None:
349 raise Exception("ANQP operation timed out")
350 nai2 = dev[0].get_bss(bssid)['anqp_nai_realm']
351
352 if len(nai1) >= len(nai2):
353 raise Exception("Unexpected NAI Realm list response lengths")
354 if binascii.hexlify(b"example.com").decode() not in nai1:
355 raise Exception("Home realm not reported")
356 if binascii.hexlify(b"example.org").decode() in nai1:
357 raise Exception("Non-home realm reported")
358 if binascii.hexlify(b"example.com").decode() not in nai2:
359 raise Exception("Home realm not reported in wildcard query")
360 if binascii.hexlify(b"example.org").decode() not in nai2:
361 raise Exception("Non-home realm not reported in wildcard query ")
362
363 cmds = ["foo",
364 "00:11:22:33:44:55 123",
365 "00:11:22:33:44:55 qq"]
366 for cmd in cmds:
367 if "FAIL" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + cmd):
368 raise Exception("Invalid HS20_GET_NAI_HOME_REALM_LIST accepted: " + cmd)
369
370 dev[0].dump_monitor()
371 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
372 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
373 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
374 if ev is None:
375 raise Exception("ANQP operation timed out")
376 ev = dev[0].wait_event(["RX-ANQP"], timeout=0.1)
377 if ev is not None:
378 raise Exception("Unexpected ANQP response: " + ev)
379
380 dev[0].dump_monitor()
381 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " 01000b6578616d706c652e636f6d"):
382 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
383 ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
384 if ev is None:
385 raise Exception("No ANQP response")
386 if "NAI Realm list" not in ev:
387 raise Exception("Missing NAI Realm list: " + ev)
388
389 dev[0].add_cred_values({'realm': "example.com", 'username': "test",
390 'password': "secret",
391 'domain': "example.com"})
392 dev[0].dump_monitor()
393 if "OK" not in dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid):
394 raise Exception("HS20_GET_NAI_HOME_REALM_LIST failed")
395 ev = dev[0].wait_event(["RX-ANQP"], timeout=10)
396 if ev is None:
397 raise Exception("No ANQP response")
398 if "NAI Realm list" not in ev:
399 raise Exception("Missing NAI Realm list: " + ev)
400
401 @remote_compatible
402 def test_ap_interworking_scan_filtering(dev, apdev):
403 """Interworking scan filtering with HESSID and access network type"""
404 try:
405 _test_ap_interworking_scan_filtering(dev, apdev)
406 finally:
407 dev[0].request("SET hessid 00:00:00:00:00:00")
408 dev[0].request("SET access_network_type 15")
409
410 def _test_ap_interworking_scan_filtering(dev, apdev):
411 bssid = apdev[0]['bssid']
412 params = hs20_ap_params()
413 ssid = "test-hs20-ap1"
414 params['ssid'] = ssid
415 params['hessid'] = bssid
416 hapd0 = hostapd.add_ap(apdev[0], params)
417
418 bssid2 = apdev[1]['bssid']
419 params = hs20_ap_params()
420 ssid2 = "test-hs20-ap2"
421 params['ssid'] = ssid2
422 params['hessid'] = bssid2
423 params['access_network_type'] = "1"
424 del params['venue_group']
425 del params['venue_type']
426 hostapd.add_ap(apdev[1], params)
427
428 dev[0].hs20_enable()
429
430 Wlantest.setup(hapd0)
431 wt = Wlantest()
432 wt.flush()
433
434 # Make sure wlantest has seen both BSSs to avoid issues in trying to clear
435 # counters for non-existing BSS.
436 dev[0].scan_for_bss(bssid, freq="2412")
437 dev[0].scan_for_bss(bssid2, freq="2412")
438 wt.clear_bss_counters(bssid)
439 wt.clear_bss_counters(bssid2)
440
441 logger.info("Check probe request filtering based on HESSID")
442
443 dev[0].request("SET hessid " + bssid2)
444 dev[0].scan(freq="2412")
445 time.sleep(0.03)
446 check_probe_resp(wt, bssid, bssid2)
447
448 logger.info("Check probe request filtering based on access network type")
449
450 wt.clear_bss_counters(bssid)
451 wt.clear_bss_counters(bssid2)
452 dev[0].request("SET hessid 00:00:00:00:00:00")
453 dev[0].request("SET access_network_type 14")
454 dev[0].scan(freq="2412")
455 time.sleep(0.03)
456 check_probe_resp(wt, bssid2, bssid)
457
458 wt.clear_bss_counters(bssid)
459 wt.clear_bss_counters(bssid2)
460 dev[0].request("SET hessid 00:00:00:00:00:00")
461 dev[0].request("SET access_network_type 1")
462 dev[0].scan(freq="2412")
463 time.sleep(0.03)
464 check_probe_resp(wt, bssid, bssid2)
465
466 logger.info("Check probe request filtering based on HESSID and ANT")
467
468 wt.clear_bss_counters(bssid)
469 wt.clear_bss_counters(bssid2)
470 dev[0].request("SET hessid " + bssid)
471 dev[0].request("SET access_network_type 14")
472 dev[0].scan(freq="2412")
473 time.sleep(0.03)
474 check_probe_resp(wt, bssid2, bssid)
475
476 wt.clear_bss_counters(bssid)
477 wt.clear_bss_counters(bssid2)
478 dev[0].request("SET hessid " + bssid2)
479 dev[0].request("SET access_network_type 14")
480 dev[0].scan(freq="2412")
481 time.sleep(0.03)
482 check_probe_resp(wt, bssid, None)
483 check_probe_resp(wt, bssid2, None)
484
485 wt.clear_bss_counters(bssid)
486 wt.clear_bss_counters(bssid2)
487 dev[0].request("SET hessid " + bssid)
488 dev[0].request("SET access_network_type 1")
489 dev[0].scan(freq="2412")
490 time.sleep(0.03)
491 check_probe_resp(wt, bssid, None)
492 check_probe_resp(wt, bssid2, None)
493
494 def test_ap_hs20_select(dev, apdev):
495 """Hotspot 2.0 network selection"""
496 bssid = apdev[0]['bssid']
497 params = hs20_ap_params()
498 params['hessid'] = bssid
499 hostapd.add_ap(apdev[0], params)
500
501 dev[0].hs20_enable()
502 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
503 'password': "secret",
504 'domain': "example.com"})
505 interworking_select(dev[0], bssid, "home")
506
507 dev[0].remove_cred(id)
508 id = dev[0].add_cred_values({'realm': "example.com", 'username': "test",
509 'password': "secret",
510 'domain': "no.match.example.com"})
511 interworking_select(dev[0], bssid, "roaming", freq="2412")
512
513 dev[0].set_cred_quoted(id, "realm", "no.match.example.com")
514 interworking_select(dev[0], bssid, no_match=True, freq="2412")
515
516 res = dev[0].request("SCAN_RESULTS")
517 if "[HS20]" not in res:
518 raise Exception("HS20 flag missing from scan results: " + res)
519
520 bssid2 = apdev[1]['bssid']
521 params = hs20_ap_params()
522 params['nai_realm'] = ["0,example.org,21"]
523 params['hessid'] = bssid2
524 params['domain_name'] = "example.org"
525 hostapd.add_ap(apdev[1], params)
526 dev[0].remove_cred(id)
527 id = dev[0].add_cred_values({'realm': "example.org", 'username': "test",
528 'password': "secret",
529 'domain': "example.org"})
530 interworking_select(dev[0], bssid2, "home", freq="2412")
531
532 def hs20_simulated_sim(dev, ap, method):
533 bssid = ap['bssid']
534 params = hs20_ap_params()
535 params['hessid'] = bssid
536 params['anqp_3gpp_cell_net'] = "555,444"
537 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
538 hostapd.add_ap(ap, params)
539
540 dev.hs20_enable()
541 dev.add_cred_values({'imsi': "555444-333222111", 'eap': method,
542 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
543 interworking_select(dev, bssid, "home", freq="2412")
544 interworking_connect(dev, bssid, method)
545 check_sp_type(dev, "home")
546
547 def test_ap_hs20_sim(dev, apdev):
548 """Hotspot 2.0 with simulated SIM and EAP-SIM"""
549 hlr_auc_gw_available()
550 hs20_simulated_sim(dev[0], apdev[0], "SIM")
551 dev[0].request("INTERWORKING_SELECT auto freq=2412")
552 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
553 if ev is None:
554 raise Exception("Timeout on already-connected event")
555
556 def test_ap_hs20_sim_invalid(dev, apdev):
557 """Hotspot 2.0 with simulated SIM and EAP-SIM - invalid IMSI"""
558 hlr_auc_gw_available()
559 bssid = apdev[0]['bssid']
560 params = hs20_ap_params()
561 params['hessid'] = bssid
562 params['anqp_3gpp_cell_net'] = "555,444"
563 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
564 hostapd.add_ap(apdev[0], params)
565
566 dev[0].hs20_enable()
567 dev[0].add_cred_values({'imsi': "555444-3332221110", 'eap': "SIM",
568 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
569 # This hits "No valid IMSI available" in build_root_nai()
570 interworking_select(dev[0], bssid, freq="2412")
571
572 def test_ap_hs20_sim_oom(dev, apdev):
573 """Hotspot 2.0 with simulated SIM and EAP-SIM - OOM"""
574 hlr_auc_gw_available()
575 bssid = apdev[0]['bssid']
576 params = hs20_ap_params()
577 params['hessid'] = bssid
578 params['anqp_3gpp_cell_net'] = "555,444"
579 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
580 hostapd.add_ap(apdev[0], params)
581
582 dev[0].hs20_enable()
583 dev[0].add_cred_values({'imsi': "555444-333222111", 'eap': "SIM",
584 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
585 dev[0].scan_for_bss(bssid, freq=2412)
586 interworking_select(dev[0], bssid, freq="2412")
587
588 with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect_3gpp"):
589 dev[0].request("INTERWORKING_CONNECT " + bssid)
590 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
591
592 with alloc_fail(dev[0], 1, "=interworking_connect_3gpp"):
593 dev[0].request("INTERWORKING_CONNECT " + bssid)
594 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
595
596 def test_ap_hs20_aka(dev, apdev):
597 """Hotspot 2.0 with simulated USIM and EAP-AKA"""
598 hlr_auc_gw_available()
599 hs20_simulated_sim(dev[0], apdev[0], "AKA")
600
601 def test_ap_hs20_aka_prime(dev, apdev):
602 """Hotspot 2.0 with simulated USIM and EAP-AKA'"""
603 hlr_auc_gw_available()
604 hs20_simulated_sim(dev[0], apdev[0], "AKA'")
605
606 def test_ap_hs20_ext_sim(dev, apdev):
607 """Hotspot 2.0 with external SIM processing"""
608 hlr_auc_gw_available()
609 bssid = apdev[0]['bssid']
610 params = hs20_ap_params()
611 params['hessid'] = bssid
612 params['anqp_3gpp_cell_net'] = "232,01"
613 params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
614 hostapd.add_ap(apdev[0], params)
615
616 dev[0].hs20_enable()
617 try:
618 dev[0].request("SET external_sim 1")
619 dev[0].add_cred_values({'imsi': "23201-0000000000", 'eap': "SIM"})
620 interworking_select(dev[0], bssid, "home", freq="2412")
621 interworking_ext_sim_connect(dev[0], bssid, "SIM")
622 check_sp_type(dev[0], "home")
623 finally:
624 dev[0].request("SET external_sim 0")
625
626 def test_ap_hs20_ext_sim_roaming(dev, apdev):
627 """Hotspot 2.0 with external SIM processing in roaming network"""
628 hlr_auc_gw_available()
629 bssid = apdev[0]['bssid']
630 params = hs20_ap_params()
631 params['hessid'] = bssid
632 params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
633 params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
634 hostapd.add_ap(apdev[0], params)
635
636 dev[0].hs20_enable()
637 try:
638 dev[0].request("SET external_sim 1")
639 dev[0].add_cred_values({'imsi': "23201-0000000000", 'eap': "SIM"})
640 interworking_select(dev[0], bssid, "roaming", freq="2412")
641 interworking_ext_sim_connect(dev[0], bssid, "SIM")
642 check_sp_type(dev[0], "roaming")
643 finally:
644 dev[0].request("SET external_sim 0")
645
646 def test_ap_hs20_username(dev, apdev):
647 """Hotspot 2.0 connection in username/password credential"""
648 check_eap_capa(dev[0], "MSCHAPV2")
649 bssid = apdev[0]['bssid']
650 params = hs20_ap_params()
651 params['hessid'] = bssid
652 params['disable_dgaf'] = '1'
653 hostapd.add_ap(apdev[0], params)
654
655 dev[0].hs20_enable()
656 id = dev[0].add_cred_values({'realm': "example.com",
657 'username': "hs20-test",
658 'password': "password",
659 'ca_cert': "auth_serv/ca.pem",
660 'domain': "example.com",
661 'update_identifier': "1234"})
662 interworking_select(dev[0], bssid, "home", freq="2412")
663 interworking_connect(dev[0], bssid, "TTLS")
664 check_sp_type(dev[0], "home")
665 status = dev[0].get_status()
666 if status['pairwise_cipher'] != "CCMP":
667 raise Exception("Unexpected pairwise cipher")
668 if status['hs20'] != "3":
669 raise Exception("Unexpected HS 2.0 support indication")
670
671 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
672 identity="hs20-test", password="password",
673 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
674 scan_freq="2412")
675
676 def test_ap_hs20_connect_api(dev, apdev):
677 """Hotspot 2.0 connection with connect API"""
678 check_eap_capa(dev[0], "MSCHAPV2")
679 bssid = apdev[0]['bssid']
680 params = hs20_ap_params()
681 params['hessid'] = bssid
682 params['disable_dgaf'] = '1'
683 hostapd.add_ap(apdev[0], params)
684
685 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
686 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
687 wpas.hs20_enable()
688 wpas.flush_scan_cache()
689 id = wpas.add_cred_values({'realm': "example.com",
690 'username': "hs20-test",
691 'password': "password",
692 'ca_cert': "auth_serv/ca.pem",
693 'domain': "example.com",
694 'update_identifier': "1234"})
695 interworking_select(wpas, bssid, "home", freq="2412")
696 interworking_connect(wpas, bssid, "TTLS")
697 check_sp_type(wpas, "home")
698 status = wpas.get_status()
699 if status['pairwise_cipher'] != "CCMP":
700 raise Exception("Unexpected pairwise cipher")
701 if status['hs20'] != "3":
702 raise Exception("Unexpected HS 2.0 support indication")
703
704 def test_ap_hs20_auto_interworking(dev, apdev):
705 """Hotspot 2.0 connection with auto_interworking=1"""
706 check_eap_capa(dev[0], "MSCHAPV2")
707 bssid = apdev[0]['bssid']
708 params = hs20_ap_params()
709 params['hessid'] = bssid
710 params['disable_dgaf'] = '1'
711 hostapd.add_ap(apdev[0], params)
712
713 dev[0].hs20_enable(auto_interworking=True)
714 id = dev[0].add_cred_values({'realm': "example.com",
715 'username': "hs20-test",
716 'password': "password",
717 'ca_cert': "auth_serv/ca.pem",
718 'domain': "example.com",
719 'update_identifier': "1234"})
720 dev[0].request("REASSOCIATE")
721 dev[0].wait_connected(timeout=15)
722 check_sp_type(dev[0], "home")
723 status = dev[0].get_status()
724 if status['pairwise_cipher'] != "CCMP":
725 raise Exception("Unexpected pairwise cipher")
726 if status['hs20'] != "3":
727 raise Exception("Unexpected HS 2.0 support indication")
728
729 @remote_compatible
730 def test_ap_hs20_auto_interworking_no_match(dev, apdev):
731 """Hotspot 2.0 connection with auto_interworking=1 and no matching network"""
732 hapd = hostapd.add_ap(apdev[0], {"ssid": "mismatch"})
733
734 dev[0].hs20_enable(auto_interworking=True)
735 id = dev[0].connect("mismatch", psk="12345678", scan_freq="2412",
736 only_add_network=True)
737 dev[0].request("ENABLE_NETWORK " + str(id) + " no-connect")
738
739 id = dev[0].add_cred_values({'realm': "example.com",
740 'username': "hs20-test",
741 'password': "password",
742 'ca_cert': "auth_serv/ca.pem",
743 'domain': "example.com",
744 'update_identifier': "1234"})
745 dev[0].request("INTERWORKING_SELECT auto freq=2412")
746 time.sleep(0.1)
747 dev[0].dump_monitor()
748 for i in range(5):
749 logger.info("start ping")
750 if "PONG" not in dev[0].ctrl.request("PING", timeout=2):
751 raise Exception("PING failed")
752 logger.info("ping done")
753 fetch = 0
754 scan = 0
755 for j in range(15):
756 ev = dev[0].wait_event(["ANQP fetch completed",
757 "CTRL-EVENT-SCAN-RESULTS"], timeout=0.05)
758 if ev is None:
759 break
760 if "ANQP fetch completed" in ev:
761 fetch += 1
762 else:
763 scan += 1
764 if fetch > 2 * scan + 3:
765 raise Exception("Too many ANQP fetch iterations")
766 dev[0].dump_monitor()
767 dev[0].request("DISCONNECT")
768
769 @remote_compatible
770 def test_ap_hs20_auto_interworking_no_cred_match(dev, apdev):
771 """Hotspot 2.0 connection with auto_interworking=1 but no cred match"""
772 bssid = apdev[0]['bssid']
773 params = {"ssid": "test"}
774 hostapd.add_ap(apdev[0], params)
775
776 dev[0].hs20_enable(auto_interworking=True)
777 dev[0].add_cred_values({'realm': "example.com",
778 'username': "hs20-test",
779 'password': "password",
780 'ca_cert': "auth_serv/ca.pem",
781 'domain': "example.com"})
782
783 id = dev[0].connect("test", psk="12345678", only_add_network=True)
784 dev[0].request("ENABLE_NETWORK %s" % id)
785 logger.info("Verify that scanning continues when there is partial network block match")
786 for i in range(0, 2):
787 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
788 if ev is None:
789 raise Exception("Scan timed out")
790 logger.info("Scan completed")
791
792 def eap_test(dev, ap, eap_params, method, user, release=0):
793 bssid = ap['bssid']
794 params = hs20_ap_params()
795 params['nai_realm'] = ["0,example.com," + eap_params]
796 if release > 0:
797 params['hs20_release'] = str(release)
798 hapd = hostapd.add_ap(ap, params)
799
800 dev.hs20_enable()
801 dev.add_cred_values({'realm': "example.com",
802 'ca_cert': "auth_serv/ca.pem",
803 'username': user,
804 'password': "password"})
805 interworking_select(dev, bssid, freq="2412")
806 interworking_connect(dev, bssid, method)
807 return hapd
808
809 @remote_compatible
810 def test_ap_hs20_eap_unknown(dev, apdev):
811 """Hotspot 2.0 connection with unknown EAP method"""
812 bssid = apdev[0]['bssid']
813 params = hs20_ap_params()
814 params['nai_realm'] = "0,example.com,99"
815 hostapd.add_ap(apdev[0], params)
816
817 dev[0].hs20_enable()
818 dev[0].add_cred_values(default_cred())
819 interworking_select(dev[0], None, no_match=True, freq="2412")
820
821 def test_ap_hs20_eap_peap_mschapv2(dev, apdev):
822 """Hotspot 2.0 connection with PEAP/MSCHAPV2"""
823 check_eap_capa(dev[0], "MSCHAPV2")
824 eap_test(dev[0], apdev[0], "25[3:26]", "PEAP", "user")
825
826 def test_ap_hs20_eap_peap_default(dev, apdev):
827 """Hotspot 2.0 connection with PEAP/MSCHAPV2 (as default)"""
828 check_eap_capa(dev[0], "MSCHAPV2")
829 eap_test(dev[0], apdev[0], "25", "PEAP", "user")
830
831 def test_ap_hs20_eap_peap_gtc(dev, apdev):
832 """Hotspot 2.0 connection with PEAP/GTC"""
833 eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
834
835 @remote_compatible
836 def test_ap_hs20_eap_peap_unknown(dev, apdev):
837 """Hotspot 2.0 connection with PEAP/unknown"""
838 bssid = apdev[0]['bssid']
839 params = hs20_ap_params()
840 params['nai_realm'] = "0,example.com,25[3:99]"
841 hostapd.add_ap(apdev[0], params)
842
843 dev[0].hs20_enable()
844 dev[0].add_cred_values(default_cred())
845 interworking_select(dev[0], None, no_match=True, freq="2412")
846
847 def test_ap_hs20_eap_ttls_chap(dev, apdev):
848 """Hotspot 2.0 connection with TTLS/CHAP"""
849 skip_with_fips(dev[0])
850 eap_test(dev[0], apdev[0], "21[2:2]", "TTLS", "chap user")
851
852 def test_ap_hs20_eap_ttls_mschap(dev, apdev):
853 """Hotspot 2.0 connection with TTLS/MSCHAP"""
854 skip_with_fips(dev[0])
855 eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
856
857 def test_ap_hs20_eap_ttls_default(dev, apdev):
858 """Hotspot 2.0 connection with TTLS/default"""
859 skip_with_fips(dev[0])
860 eap_test(dev[0], apdev[0], "21", "TTLS", "hs20-test")
861
862 def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
863 """Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
864 check_eap_capa(dev[0], "MSCHAPV2")
865 eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user")
866
867 @remote_compatible
868 def test_ap_hs20_eap_ttls_eap_unknown(dev, apdev):
869 """Hotspot 2.0 connection with TTLS/EAP-unknown"""
870 bssid = apdev[0]['bssid']
871 params = hs20_ap_params()
872 params['nai_realm'] = "0,example.com,21[3:99]"
873 hostapd.add_ap(apdev[0], params)
874
875 dev[0].hs20_enable()
876 dev[0].add_cred_values(default_cred())
877 interworking_select(dev[0], None, no_match=True, freq="2412")
878
879 @remote_compatible
880 def test_ap_hs20_eap_ttls_eap_unsupported(dev, apdev):
881 """Hotspot 2.0 connection with TTLS/EAP-OTP(unsupported)"""
882 bssid = apdev[0]['bssid']
883 params = hs20_ap_params()
884 params['nai_realm'] = "0,example.com,21[3:5]"
885 hostapd.add_ap(apdev[0], params)
886
887 dev[0].hs20_enable()
888 dev[0].add_cred_values(default_cred())
889 interworking_select(dev[0], None, no_match=True, freq="2412")
890
891 @remote_compatible
892 def test_ap_hs20_eap_ttls_unknown(dev, apdev):
893 """Hotspot 2.0 connection with TTLS/unknown"""
894 bssid = apdev[0]['bssid']
895 params = hs20_ap_params()
896 params['nai_realm'] = "0,example.com,21[2:5]"
897 hostapd.add_ap(apdev[0], params)
898
899 dev[0].hs20_enable()
900 dev[0].add_cred_values(default_cred())
901 interworking_select(dev[0], None, no_match=True, freq="2412")
902
903 def test_ap_hs20_eap_fast_mschapv2(dev, apdev):
904 """Hotspot 2.0 connection with FAST/EAP-MSCHAPV2"""
905 check_eap_capa(dev[0], "FAST")
906 eap_test(dev[0], apdev[0], "43[3:26]", "FAST", "user")
907
908 def test_ap_hs20_eap_fast_gtc(dev, apdev):
909 """Hotspot 2.0 connection with FAST/EAP-GTC"""
910 check_eap_capa(dev[0], "FAST")
911 eap_test(dev[0], apdev[0], "43[3:6]", "FAST", "user")
912
913 def test_ap_hs20_eap_tls(dev, apdev):
914 """Hotspot 2.0 connection with EAP-TLS"""
915 bssid = apdev[0]['bssid']
916 params = hs20_ap_params()
917 params['nai_realm'] = ["0,example.com,13[5:6]"]
918 hostapd.add_ap(apdev[0], params)
919
920 dev[0].hs20_enable()
921 dev[0].add_cred_values({'realm': "example.com",
922 'username': "certificate-user",
923 'ca_cert': "auth_serv/ca.pem",
924 'client_cert': "auth_serv/user.pem",
925 'private_key': "auth_serv/user.key"})
926 interworking_select(dev[0], bssid, freq="2412")
927 interworking_connect(dev[0], bssid, "TLS")
928
929 @remote_compatible
930 def test_ap_hs20_eap_cert_unknown(dev, apdev):
931 """Hotspot 2.0 connection with certificate, but unknown EAP method"""
932 bssid = apdev[0]['bssid']
933 params = hs20_ap_params()
934 params['nai_realm'] = ["0,example.com,99[5:6]"]
935 hostapd.add_ap(apdev[0], params)
936
937 dev[0].hs20_enable()
938 dev[0].add_cred_values({'realm': "example.com",
939 'username': "certificate-user",
940 'ca_cert': "auth_serv/ca.pem",
941 'client_cert': "auth_serv/user.pem",
942 'private_key': "auth_serv/user.key"})
943 interworking_select(dev[0], None, no_match=True, freq="2412")
944
945 @remote_compatible
946 def test_ap_hs20_eap_cert_unsupported(dev, apdev):
947 """Hotspot 2.0 connection with certificate, but unsupported TTLS"""
948 bssid = apdev[0]['bssid']
949 params = hs20_ap_params()
950 params['nai_realm'] = ["0,example.com,21[5:6]"]
951 hostapd.add_ap(apdev[0], params)
952
953 dev[0].hs20_enable()
954 dev[0].add_cred_values({'realm': "example.com",
955 'username': "certificate-user",
956 'ca_cert': "auth_serv/ca.pem",
957 'client_cert': "auth_serv/user.pem",
958 'private_key': "auth_serv/user.key"})
959 interworking_select(dev[0], None, no_match=True, freq="2412")
960
961 @remote_compatible
962 def test_ap_hs20_eap_invalid_cred(dev, apdev):
963 """Hotspot 2.0 connection with invalid cred configuration"""
964 bssid = apdev[0]['bssid']
965 params = hs20_ap_params()
966 hostapd.add_ap(apdev[0], params)
967
968 dev[0].hs20_enable()
969 dev[0].add_cred_values({'realm': "example.com",
970 'username': "certificate-user",
971 'client_cert': "auth_serv/user.pem"})
972 interworking_select(dev[0], None, no_match=True, freq="2412")
973
974 def test_ap_hs20_nai_realms(dev, apdev):
975 """Hotspot 2.0 connection and multiple NAI realms and TTLS/PAP"""
976 bssid = apdev[0]['bssid']
977 params = hs20_ap_params()
978 params['hessid'] = bssid
979 params['nai_realm'] = ["0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]"]
980 hostapd.add_ap(apdev[0], params)
981
982 dev[0].hs20_enable()
983 id = dev[0].add_cred_values({'realm': "example.com",
984 'ca_cert': "auth_serv/ca.pem",
985 'username': "pap user",
986 'password': "password",
987 'domain': "example.com"})
988 interworking_select(dev[0], bssid, "home", freq="2412")
989 interworking_connect(dev[0], bssid, "TTLS")
990 check_sp_type(dev[0], "home")
991
992 def test_ap_hs20_roaming_consortium(dev, apdev):
993 """Hotspot 2.0 connection based on roaming consortium match"""
994 bssid = apdev[0]['bssid']
995 params = hs20_ap_params()
996 params['hessid'] = bssid
997 hostapd.add_ap(apdev[0], params)
998
999 dev[0].hs20_enable()
1000 for consortium in ["112233", "1020304050", "010203040506", "fedcba"]:
1001 id = dev[0].add_cred_values({'username': "user",
1002 'password': "password",
1003 'domain': "example.com",
1004 'ca_cert': "auth_serv/ca.pem",
1005 'roaming_consortium': consortium,
1006 'eap': "PEAP"})
1007 interworking_select(dev[0], bssid, "home", freq="2412")
1008 interworking_connect(dev[0], bssid, "PEAP")
1009 check_sp_type(dev[0], "home")
1010 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1011 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
1012 if ev is None:
1013 raise Exception("Timeout on already-connected event")
1014 dev[0].remove_cred(id)
1015
1016 def test_ap_hs20_roaming_consortiums_match(dev, apdev):
1017 """Hotspot 2.0 connection based on roaming_consortiums match"""
1018 bssid = apdev[0]['bssid']
1019 params = hs20_ap_params()
1020 params['hessid'] = bssid
1021 hostapd.add_ap(apdev[0], params)
1022
1023 dev[0].hs20_enable()
1024 tests = [("112233", "112233"),
1025 ("ffffff,1020304050,eeeeee", "1020304050")]
1026 for consortium, selected in tests:
1027 id = dev[0].add_cred_values({'username': "user",
1028 'password': "password",
1029 'domain': "my.home.example.com",
1030 'ca_cert': "auth_serv/ca.pem",
1031 'roaming_consortiums': consortium,
1032 'eap': "PEAP"})
1033 interworking_select(dev[0], bssid, "roaming", freq="2412")
1034 interworking_connect(dev[0], bssid, "PEAP")
1035 check_sp_type(dev[0], "roaming")
1036 network_id = dev[0].get_status_field("id")
1037 sel = dev[0].get_network(network_id, "roaming_consortium_selection")
1038 if sel != selected:
1039 raise Exception("Unexpected roaming_consortium_selection value: " +
1040 sel)
1041 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1042 ev = dev[0].wait_event(["INTERWORKING-ALREADY-CONNECTED"], timeout=15)
1043 if ev is None:
1044 raise Exception("Timeout on already-connected event")
1045 dev[0].remove_cred(id)
1046
1047 def test_ap_hs20_max_roaming_consortiums(dev, apdev):
1048 """Maximum number of cred roaming_consortiums"""
1049 id = dev[0].add_cred()
1050 consortium = (36*",ffffff")[1:]
1051 if "OK" not in dev[0].request('SET_CRED %d roaming_consortiums "%s"' % (id, consortium)):
1052 raise Exception("Maximum number of consortium OIs rejected")
1053 consortium = (37*",ffffff")[1:]
1054 if "FAIL" not in dev[0].request('SET_CRED %d roaming_consortiums "%s"' % (id, consortium)):
1055 raise Exception("Over maximum number of consortium OIs accepted")
1056 dev[0].remove_cred(id)
1057
1058 def test_ap_hs20_roaming_consortium_invalid(dev, apdev):
1059 """Hotspot 2.0 connection and invalid roaming consortium ANQP-element"""
1060 bssid = apdev[0]['bssid']
1061 params = hs20_ap_params()
1062 params['hessid'] = bssid
1063 # Override Roaming Consortium ANQP-element with an incorrectly encoded
1064 # value.
1065 params['anqp_elem'] = "261:04fedcba"
1066 hostapd.add_ap(apdev[0], params)
1067
1068 dev[0].hs20_enable()
1069 id = dev[0].add_cred_values({'username': "user",
1070 'password': "password",
1071 'domain': "example.com",
1072 'ca_cert': "auth_serv/ca.pem",
1073 'roaming_consortium': "fedcba",
1074 'eap': "PEAP"})
1075 interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
1076
1077 def test_ap_hs20_roaming_consortium_element(dev, apdev):
1078 """Hotspot 2.0 connection and invalid roaming consortium element"""
1079 bssid = apdev[0]['bssid']
1080 params = hs20_ap_params()
1081 params['hessid'] = bssid
1082 del params['roaming_consortium']
1083 params['vendor_elements'] = '6f00'
1084 hapd = hostapd.add_ap(apdev[0], params)
1085
1086 dev[0].hs20_enable()
1087 dev[0].scan_for_bss(bssid, freq="2412")
1088 id = dev[0].add_cred_values({'username': "user",
1089 'password': "password",
1090 'domain': "example.com",
1091 'ca_cert': "auth_serv/ca.pem",
1092 'roaming_consortium': "112233",
1093 'eap': "PEAP"})
1094 interworking_select(dev[0], bssid, freq="2412", no_match=True)
1095
1096 hapd.set('vendor_elements', '6f020001')
1097 if "OK" not in hapd.request("UPDATE_BEACON"):
1098 raise Exception("UPDATE_BEACON failed")
1099 dev[0].request("BSS_FLUSH 0")
1100 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
1101 interworking_select(dev[0], bssid, freq="2412", no_match=True)
1102
1103 def test_ap_hs20_roaming_consortium_constraints(dev, apdev):
1104 """Hotspot 2.0 connection and roaming consortium constraints"""
1105 bssid = apdev[0]['bssid']
1106 params = hs20_ap_params()
1107 params['hessid'] = bssid
1108 params['bss_load_test'] = "12:200:20000"
1109 hostapd.add_ap(apdev[0], params)
1110
1111 dev[0].hs20_enable()
1112
1113 vals = {'username': "user",
1114 'password': "password",
1115 'domain': "example.com",
1116 'ca_cert': "auth_serv/ca.pem",
1117 'roaming_consortium': "fedcba",
1118 'eap': "TTLS"}
1119 vals2 = vals.copy()
1120 vals2['required_roaming_consortium'] = "223344"
1121 id = dev[0].add_cred_values(vals2)
1122 interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
1123 dev[0].remove_cred(id)
1124
1125 vals2 = vals.copy()
1126 vals2['min_dl_bandwidth_home'] = "65500"
1127 id = dev[0].add_cred_values(vals2)
1128 dev[0].request("INTERWORKING_SELECT freq=2412")
1129 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1130 if ev is None:
1131 raise Exception("No AP found")
1132 if "below_min_backhaul=1" not in ev:
1133 raise Exception("below_min_backhaul not reported")
1134 dev[0].remove_cred(id)
1135
1136 vals2 = vals.copy()
1137 vals2['max_bss_load'] = "100"
1138 id = dev[0].add_cred_values(vals2)
1139 dev[0].request("INTERWORKING_SELECT freq=2412")
1140 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1141 if ev is None:
1142 raise Exception("No AP found")
1143 if "over_max_bss_load=1" not in ev:
1144 raise Exception("over_max_bss_load not reported")
1145 dev[0].remove_cred(id)
1146
1147 vals2 = vals.copy()
1148 vals2['req_conn_capab'] = "6:1234"
1149 vals2['domain'] = 'example.org'
1150 id = dev[0].add_cred_values(vals2)
1151
1152 dev[0].request("INTERWORKING_SELECT freq=2412")
1153 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1154 if ev is None:
1155 raise Exception("No AP found")
1156 if "conn_capab_missing=1" not in ev:
1157 raise Exception("conn_capab_missing not reported")
1158 dev[0].remove_cred(id)
1159
1160 values = default_cred()
1161 values['roaming_consortium'] = "fedcba"
1162 id3 = dev[0].add_cred_values(values)
1163
1164 vals2 = vals.copy()
1165 vals2['roaming_consortium'] = "fedcba"
1166 vals2['priority'] = "2"
1167 id = dev[0].add_cred_values(vals2)
1168
1169 values = default_cred()
1170 values['roaming_consortium'] = "fedcba"
1171 id2 = dev[0].add_cred_values(values)
1172
1173 dev[0].request("INTERWORKING_SELECT freq=2412")
1174 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1175 if ev is None:
1176 raise Exception("No AP found")
1177 dev[0].remove_cred(id)
1178 dev[0].remove_cred(id2)
1179 dev[0].remove_cred(id3)
1180
1181 def test_ap_hs20_3gpp_constraints(dev, apdev):
1182 """Hotspot 2.0 connection and 3GPP credential constraints"""
1183 bssid = apdev[0]['bssid']
1184 params = hs20_ap_params()
1185 params['hessid'] = bssid
1186 params['anqp_3gpp_cell_net'] = "555,444"
1187 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
1188 params['bss_load_test'] = "12:200:20000"
1189 hapd = hostapd.add_ap(apdev[0], params)
1190
1191 dev[0].hs20_enable()
1192
1193 vals = {'imsi': "555444-333222111",
1194 'eap': "SIM",
1195 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"}
1196 vals2 = vals.copy()
1197 vals2['required_roaming_consortium'] = "223344"
1198 id = dev[0].add_cred_values(vals2)
1199 interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
1200 dev[0].remove_cred(id)
1201
1202 vals2 = vals.copy()
1203 vals2['min_dl_bandwidth_home'] = "65500"
1204 id = dev[0].add_cred_values(vals2)
1205 dev[0].request("INTERWORKING_SELECT freq=2412")
1206 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1207 if ev is None:
1208 raise Exception("No AP found")
1209 if "below_min_backhaul=1" not in ev:
1210 raise Exception("below_min_backhaul not reported")
1211 dev[0].remove_cred(id)
1212
1213 vals2 = vals.copy()
1214 vals2['max_bss_load'] = "100"
1215 id = dev[0].add_cred_values(vals2)
1216 dev[0].request("INTERWORKING_SELECT freq=2412")
1217 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1218 if ev is None:
1219 raise Exception("No AP found")
1220 if "over_max_bss_load=1" not in ev:
1221 raise Exception("over_max_bss_load not reported")
1222 dev[0].remove_cred(id)
1223
1224 values = default_cred()
1225 values['roaming_consortium'] = "fedcba"
1226 id3 = dev[0].add_cred_values(values)
1227
1228 vals2 = vals.copy()
1229 vals2['roaming_consortium'] = "fedcba"
1230 vals2['priority'] = "2"
1231 id = dev[0].add_cred_values(vals2)
1232
1233 values = default_cred()
1234 values['roaming_consortium'] = "fedcba"
1235 id2 = dev[0].add_cred_values(values)
1236
1237 dev[0].request("INTERWORKING_SELECT freq=2412")
1238 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1239 if ev is None:
1240 raise Exception("No AP found")
1241 dev[0].remove_cred(id)
1242 dev[0].remove_cred(id2)
1243 dev[0].remove_cred(id3)
1244
1245 hapd.disable()
1246 params = hs20_ap_params()
1247 params['hessid'] = bssid
1248 params['anqp_3gpp_cell_net'] = "555,444"
1249 params['bss_load_test'] = "12:200:20000"
1250 hapd = hostapd.add_ap(apdev[0], params)
1251 vals2 = vals.copy()
1252 vals2['req_conn_capab'] = "6:1234"
1253 id = dev[0].add_cred_values(vals2)
1254 dev[0].request("INTERWORKING_SELECT freq=2412")
1255 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1256 if ev is None:
1257 raise Exception("No AP found")
1258 if "conn_capab_missing=1" not in ev:
1259 raise Exception("conn_capab_missing not reported")
1260 dev[0].remove_cred(id)
1261
1262 def test_ap_hs20_connect_no_full_match(dev, apdev):
1263 """Hotspot 2.0 connection and no full match"""
1264 bssid = apdev[0]['bssid']
1265 params = hs20_ap_params()
1266 params['hessid'] = bssid
1267 params['anqp_3gpp_cell_net'] = "555,444"
1268 hostapd.add_ap(apdev[0], params)
1269
1270 dev[0].hs20_enable()
1271
1272 vals = {'username': "user",
1273 'password': "password",
1274 'domain': "example.com",
1275 'ca_cert': "auth_serv/ca.pem",
1276 'roaming_consortium': "fedcba",
1277 'eap': "TTLS",
1278 'min_dl_bandwidth_home': "65500"}
1279 id = dev[0].add_cred_values(vals)
1280 dev[0].request("INTERWORKING_SELECT freq=2412")
1281 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1282 if ev is None:
1283 raise Exception("No AP found")
1284 if "below_min_backhaul=1" not in ev:
1285 raise Exception("below_min_backhaul not reported")
1286 interworking_connect(dev[0], bssid, "TTLS")
1287 dev[0].remove_cred(id)
1288 dev[0].wait_disconnected()
1289
1290 vals = {'imsi': "555444-333222111", 'eap': "SIM",
1291 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
1292 'min_dl_bandwidth_roaming': "65500"}
1293 id = dev[0].add_cred_values(vals)
1294 dev[0].request("INTERWORKING_SELECT freq=2412")
1295 ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
1296 if ev is None:
1297 raise Exception("No AP found")
1298 if "below_min_backhaul=1" not in ev:
1299 raise Exception("below_min_backhaul not reported")
1300 interworking_connect(dev[0], bssid, "SIM")
1301 dev[0].remove_cred(id)
1302 dev[0].wait_disconnected()
1303
1304 def test_ap_hs20_username_roaming(dev, apdev):
1305 """Hotspot 2.0 connection in username/password credential (roaming)"""
1306 check_eap_capa(dev[0], "MSCHAPV2")
1307 bssid = apdev[0]['bssid']
1308 params = hs20_ap_params()
1309 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]",
1310 "0,roaming.example.com,21[2:4][5:7]",
1311 "0,another.example.com"]
1312 params['domain_name'] = "another.example.com"
1313 params['hessid'] = bssid
1314 hostapd.add_ap(apdev[0], params)
1315
1316 dev[0].hs20_enable()
1317 id = dev[0].add_cred_values({'realm': "roaming.example.com",
1318 'username': "hs20-test",
1319 'password': "password",
1320 'ca_cert': "auth_serv/ca.pem",
1321 'domain': "example.com"})
1322 interworking_select(dev[0], bssid, "roaming", freq="2412")
1323 interworking_connect(dev[0], bssid, "TTLS")
1324 check_sp_type(dev[0], "roaming")
1325
1326 def test_ap_hs20_username_unknown(dev, apdev):
1327 """Hotspot 2.0 connection in username/password credential (no domain in cred)"""
1328 check_eap_capa(dev[0], "MSCHAPV2")
1329 bssid = apdev[0]['bssid']
1330 params = hs20_ap_params()
1331 params['hessid'] = bssid
1332 hostapd.add_ap(apdev[0], params)
1333
1334 dev[0].hs20_enable()
1335 id = dev[0].add_cred_values({'realm': "example.com",
1336 'ca_cert': "auth_serv/ca.pem",
1337 'username': "hs20-test",
1338 'password': "password"})
1339 interworking_select(dev[0], bssid, "unknown", freq="2412")
1340 interworking_connect(dev[0], bssid, "TTLS")
1341 check_sp_type(dev[0], "unknown")
1342
1343 def test_ap_hs20_username_unknown2(dev, apdev):
1344 """Hotspot 2.0 connection in username/password credential (no domain advertized)"""
1345 check_eap_capa(dev[0], "MSCHAPV2")
1346 bssid = apdev[0]['bssid']
1347 params = hs20_ap_params()
1348 params['hessid'] = bssid
1349 del params['domain_name']
1350 hostapd.add_ap(apdev[0], params)
1351
1352 dev[0].hs20_enable()
1353 id = dev[0].add_cred_values({'realm': "example.com",
1354 'ca_cert': "auth_serv/ca.pem",
1355 'username': "hs20-test",
1356 'password': "password",
1357 'domain': "example.com"})
1358 interworking_select(dev[0], bssid, "unknown", freq="2412")
1359 interworking_connect(dev[0], bssid, "TTLS")
1360 check_sp_type(dev[0], "unknown")
1361
1362 def test_ap_hs20_gas_while_associated(dev, apdev):
1363 """Hotspot 2.0 connection with GAS query while associated"""
1364 check_eap_capa(dev[0], "MSCHAPV2")
1365 bssid = apdev[0]['bssid']
1366 params = hs20_ap_params()
1367 params['hessid'] = bssid
1368 hostapd.add_ap(apdev[0], params)
1369
1370 dev[0].hs20_enable()
1371 id = dev[0].add_cred_values({'realm': "example.com",
1372 'ca_cert': "auth_serv/ca.pem",
1373 'username': "hs20-test",
1374 'password': "password",
1375 'domain': "example.com"})
1376 interworking_select(dev[0], bssid, "home", freq="2412")
1377 interworking_connect(dev[0], bssid, "TTLS")
1378
1379 logger.info("Verifying GAS query while associated")
1380 dev[0].request("FETCH_ANQP")
1381 for i in range(0, 6):
1382 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1383 if ev is None:
1384 raise Exception("Operation timed out")
1385
1386 def test_ap_hs20_gas_with_another_ap_while_associated(dev, apdev):
1387 """GAS query with another AP while associated"""
1388 check_eap_capa(dev[0], "MSCHAPV2")
1389 bssid = apdev[0]['bssid']
1390 params = hs20_ap_params()
1391 params['hessid'] = bssid
1392 hostapd.add_ap(apdev[0], params)
1393
1394 bssid2 = apdev[1]['bssid']
1395 params = hs20_ap_params()
1396 params['hessid'] = bssid2
1397 params['nai_realm'] = ["0,no-match.example.org,13[5:6],21[2:4][5:7]"]
1398 hostapd.add_ap(apdev[1], params)
1399
1400 dev[0].hs20_enable()
1401 id = dev[0].add_cred_values({'realm': "example.com",
1402 'ca_cert': "auth_serv/ca.pem",
1403 'username': "hs20-test",
1404 'password': "password",
1405 'domain': "example.com"})
1406 interworking_select(dev[0], bssid, "home", freq="2412")
1407 interworking_connect(dev[0], bssid, "TTLS")
1408 dev[0].dump_monitor()
1409
1410 logger.info("Verifying GAS query with same AP while associated")
1411 dev[0].request("ANQP_GET " + bssid + " 263")
1412 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1413 if ev is None:
1414 raise Exception("ANQP operation timed out")
1415 dev[0].dump_monitor()
1416
1417 logger.info("Verifying GAS query with another AP while associated")
1418 dev[0].scan_for_bss(bssid2, 2412)
1419 dev[0].request("ANQP_GET " + bssid2 + " 263")
1420 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1421 if ev is None:
1422 raise Exception("ANQP operation timed out")
1423
1424 def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
1425 """Hotspot 2.0 connection with GAS query while associated and using PMF"""
1426 check_eap_capa(dev[0], "MSCHAPV2")
1427 try:
1428 _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev)
1429 finally:
1430 dev[0].request("SET pmf 0")
1431
1432 def _test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
1433 bssid = apdev[0]['bssid']
1434 params = hs20_ap_params()
1435 params['hessid'] = bssid
1436 hostapd.add_ap(apdev[0], params)
1437
1438 bssid2 = apdev[1]['bssid']
1439 params = hs20_ap_params()
1440 params['hessid'] = bssid2
1441 params['nai_realm'] = ["0,no-match.example.org,13[5:6],21[2:4][5:7]"]
1442 hostapd.add_ap(apdev[1], params)
1443
1444 dev[0].hs20_enable()
1445 dev[0].request("SET pmf 2")
1446 id = dev[0].add_cred_values({'realm': "example.com",
1447 'ca_cert': "auth_serv/ca.pem",
1448 'username': "hs20-test",
1449 'password': "password",
1450 'domain': "example.com"})
1451 interworking_select(dev[0], bssid, "home", freq="2412")
1452 interworking_connect(dev[0], bssid, "TTLS")
1453
1454 logger.info("Verifying GAS query while associated")
1455 dev[0].request("FETCH_ANQP")
1456 for i in range(0, 2 * 6):
1457 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1458 if ev is None:
1459 raise Exception("Operation timed out")
1460
1461 def test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev):
1462 """GAS query with another AP while associated and using PMF"""
1463 check_eap_capa(dev[0], "MSCHAPV2")
1464 try:
1465 _test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev)
1466 finally:
1467 dev[0].request("SET pmf 0")
1468
1469 def _test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev):
1470 bssid = apdev[0]['bssid']
1471 params = hs20_ap_params()
1472 params['hessid'] = bssid
1473 hapd = hostapd.add_ap(apdev[0], params)
1474
1475 bssid2 = apdev[1]['bssid']
1476 params = hs20_ap_params()
1477 params['hessid'] = bssid2
1478 params['nai_realm'] = ["0,no-match.example.org,13[5:6],21[2:4][5:7]"]
1479 hostapd.add_ap(apdev[1], params)
1480
1481 dev[0].hs20_enable()
1482 dev[0].request("SET pmf 2")
1483 id = dev[0].add_cred_values({'realm': "example.com",
1484 'ca_cert': "auth_serv/ca.pem",
1485 'username': "hs20-test",
1486 'password': "password",
1487 'domain': "example.com"})
1488 interworking_select(dev[0], bssid, "home", freq="2412")
1489 interworking_connect(dev[0], bssid, "TTLS")
1490 dev[0].dump_monitor()
1491 hapd.wait_sta()
1492
1493 logger.info("Verifying GAS query with same AP while associated")
1494 dev[0].request("ANQP_GET " + bssid + " 263")
1495 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1496 if ev is None:
1497 raise Exception("ANQP operation timed out")
1498 dev[0].dump_monitor()
1499
1500 logger.info("Verifying GAS query with another AP while associated")
1501 dev[0].scan_for_bss(bssid2, 2412)
1502 dev[0].request("ANQP_GET " + bssid2 + " 263")
1503 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1504 if ev is None:
1505 raise Exception("ANQP operation timed out")
1506
1507 def test_ap_hs20_gas_frag_while_associated(dev, apdev):
1508 """Hotspot 2.0 connection with fragmented GAS query while associated"""
1509 check_eap_capa(dev[0], "MSCHAPV2")
1510 bssid = apdev[0]['bssid']
1511 params = hs20_ap_params()
1512 params['hessid'] = bssid
1513 hapd = hostapd.add_ap(apdev[0], params)
1514 hapd.set("gas_frag_limit", "50")
1515
1516 dev[0].hs20_enable()
1517 id = dev[0].add_cred_values({'realm': "example.com",
1518 'ca_cert': "auth_serv/ca.pem",
1519 'username': "hs20-test",
1520 'password': "password",
1521 'domain': "example.com"})
1522 interworking_select(dev[0], bssid, "home", freq="2412")
1523 interworking_connect(dev[0], bssid, "TTLS")
1524 hapd.wait_sta()
1525
1526 logger.info("Verifying GAS query while associated")
1527 dev[0].request("FETCH_ANQP")
1528 for i in range(0, 6):
1529 ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
1530 if ev is None:
1531 raise Exception("Operation timed out")
1532
1533 def test_ap_hs20_multiple_connects(dev, apdev):
1534 """Hotspot 2.0 connection through multiple network selections"""
1535 check_eap_capa(dev[0], "MSCHAPV2")
1536 bssid = apdev[0]['bssid']
1537 params = hs20_ap_params()
1538 params['hessid'] = bssid
1539 hostapd.add_ap(apdev[0], params)
1540
1541 dev[0].hs20_enable()
1542 values = {'realm': "example.com",
1543 'ca_cert': "auth_serv/ca.pem",
1544 'username': "hs20-test",
1545 'password': "password",
1546 'domain': "example.com"}
1547 id = dev[0].add_cred_values(values)
1548
1549 dev[0].scan_for_bss(bssid, freq="2412")
1550
1551 for i in range(0, 3):
1552 logger.info("Starting Interworking network selection")
1553 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1554 while True:
1555 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
1556 "INTERWORKING-ALREADY-CONNECTED",
1557 "CTRL-EVENT-CONNECTED"], timeout=15)
1558 if ev is None:
1559 raise Exception("Connection timed out")
1560 if "INTERWORKING-NO-MATCH" in ev:
1561 raise Exception("Matching AP not found")
1562 if "CTRL-EVENT-CONNECTED" in ev:
1563 break
1564 if i == 2 and "INTERWORKING-ALREADY-CONNECTED" in ev:
1565 break
1566 if i == 0:
1567 dev[0].request("DISCONNECT")
1568 dev[0].dump_monitor()
1569
1570 networks = dev[0].list_networks()
1571 if len(networks) > 1:
1572 raise Exception("Duplicated network block detected")
1573
1574 def test_ap_hs20_disallow_aps(dev, apdev):
1575 """Hotspot 2.0 connection and disallow_aps"""
1576 bssid = apdev[0]['bssid']
1577 params = hs20_ap_params()
1578 params['hessid'] = bssid
1579 hostapd.add_ap(apdev[0], params)
1580
1581 dev[0].hs20_enable()
1582 values = {'realm': "example.com",
1583 'ca_cert': "auth_serv/ca.pem",
1584 'username': "hs20-test",
1585 'password': "password",
1586 'domain': "example.com"}
1587 id = dev[0].add_cred_values(values)
1588
1589 dev[0].scan_for_bss(bssid, freq="2412")
1590
1591 logger.info("Verify disallow_aps bssid")
1592 dev[0].request("SET disallow_aps bssid " + bssid.replace(':', ''))
1593 dev[0].request("INTERWORKING_SELECT auto")
1594 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
1595 if ev is None:
1596 raise Exception("Network selection timed out")
1597 dev[0].dump_monitor()
1598
1599 logger.info("Verify disallow_aps ssid")
1600 dev[0].request("SET disallow_aps ssid 746573742d68733230")
1601 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1602 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=15)
1603 if ev is None:
1604 raise Exception("Network selection timed out")
1605 dev[0].dump_monitor()
1606
1607 logger.info("Verify disallow_aps clear")
1608 dev[0].request("SET disallow_aps ")
1609 interworking_select(dev[0], bssid, "home", freq="2412")
1610
1611 dev[0].request("SET disallow_aps bssid " + bssid.replace(':', ''))
1612 ret = dev[0].request("INTERWORKING_CONNECT " + bssid)
1613 if "FAIL" not in ret:
1614 raise Exception("INTERWORKING_CONNECT to disallowed BSS not rejected")
1615
1616 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT foo"):
1617 raise Exception("Invalid INTERWORKING_CONNECT not rejected")
1618 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT 00:11:22:33:44:55"):
1619 raise Exception("Invalid INTERWORKING_CONNECT not rejected")
1620
1621 def policy_test(dev, ap, values, only_one=True):
1622 dev.dump_monitor()
1623 if ap:
1624 logger.info("Verify network selection to AP " + ap['ifname'])
1625 bssid = ap['bssid']
1626 dev.scan_for_bss(bssid, freq="2412")
1627 else:
1628 logger.info("Verify network selection")
1629 bssid = None
1630 dev.hs20_enable()
1631 id = dev.add_cred_values(values)
1632 dev.request("INTERWORKING_SELECT auto freq=2412")
1633 events = []
1634 while True:
1635 ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH",
1636 "INTERWORKING-BLACKLISTED",
1637 "INTERWORKING-SELECTED"], timeout=15)
1638 if ev is None:
1639 raise Exception("Network selection timed out")
1640 events.append(ev)
1641 if "INTERWORKING-NO-MATCH" in ev:
1642 raise Exception("Matching AP not found")
1643 if bssid and only_one and "INTERWORKING-AP" in ev and bssid not in ev:
1644 raise Exception("Unexpected AP claimed acceptable")
1645 if "INTERWORKING-SELECTED" in ev:
1646 if bssid and bssid not in ev:
1647 raise Exception("Selected incorrect BSS")
1648 break
1649
1650 ev = dev.wait_connected(timeout=15)
1651 if bssid and bssid not in ev:
1652 raise Exception("Connected to incorrect BSS")
1653
1654 conn_bssid = dev.get_status_field("bssid")
1655 if bssid and conn_bssid != bssid:
1656 raise Exception("bssid information points to incorrect BSS")
1657
1658 dev.remove_cred(id)
1659 dev.dump_monitor()
1660 return events
1661
1662 def default_cred(domain=None, user="hs20-test"):
1663 cred = {'realm': "example.com",
1664 'ca_cert': "auth_serv/ca.pem",
1665 'username': user,
1666 'password': "password"}
1667 if domain:
1668 cred['domain'] = domain
1669 return cred
1670
1671 def test_ap_hs20_prefer_home(dev, apdev):
1672 """Hotspot 2.0 required roaming consortium"""
1673 check_eap_capa(dev[0], "MSCHAPV2")
1674 params = hs20_ap_params()
1675 params['domain_name'] = "example.org"
1676 hostapd.add_ap(apdev[0], params)
1677
1678 params = hs20_ap_params()
1679 params['ssid'] = "test-hs20-other"
1680 params['domain_name'] = "example.com"
1681 hostapd.add_ap(apdev[1], params)
1682
1683 values = default_cred()
1684 values['domain'] = "example.com"
1685 policy_test(dev[0], apdev[1], values, only_one=False)
1686 values['domain'] = "example.org"
1687 policy_test(dev[0], apdev[0], values, only_one=False)
1688
1689 def test_ap_hs20_req_roaming_consortium(dev, apdev):
1690 """Hotspot 2.0 required roaming consortium"""
1691 check_eap_capa(dev[0], "MSCHAPV2")
1692 params = hs20_ap_params()
1693 hostapd.add_ap(apdev[0], params)
1694
1695 params = hs20_ap_params()
1696 params['ssid'] = "test-hs20-other"
1697 params['roaming_consortium'] = ["223344"]
1698 hostapd.add_ap(apdev[1], params)
1699
1700 values = default_cred()
1701 values['required_roaming_consortium'] = "223344"
1702 policy_test(dev[0], apdev[1], values)
1703 values['required_roaming_consortium'] = "112233"
1704 policy_test(dev[0], apdev[0], values)
1705
1706 id = dev[0].add_cred()
1707 dev[0].set_cred(id, "required_roaming_consortium", "112233")
1708 dev[0].set_cred(id, "required_roaming_consortium", "112233445566778899aabbccddeeff")
1709
1710 for val in ["", "1", "11", "1122", "1122334",
1711 "112233445566778899aabbccddeeff00"]:
1712 if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
1713 raise Exception("Invalid roaming consortium value accepted: " + val)
1714
1715 def test_ap_hs20_req_roaming_consortium_no_match(dev, apdev):
1716 """Hotspot 2.0 required roaming consortium and no match"""
1717 check_eap_capa(dev[0], "MSCHAPV2")
1718 params = hs20_ap_params()
1719 del params['roaming_consortium']
1720 hostapd.add_ap(apdev[0], params)
1721
1722 params = hs20_ap_params()
1723 params['ssid'] = "test-hs20-other"
1724 params['roaming_consortium'] = ["223345"]
1725 hostapd.add_ap(apdev[1], params)
1726
1727 values = default_cred()
1728 values['required_roaming_consortium'] = "223344"
1729 dev[0].hs20_enable()
1730 id = dev[0].add_cred_values(values)
1731 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1732 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=10)
1733 if ev is None:
1734 raise Exception("INTERWORKING-NO-MATCH not reported")
1735
1736 def test_ap_hs20_excluded_ssid(dev, apdev):
1737 """Hotspot 2.0 exclusion based on SSID"""
1738 check_eap_capa(dev[0], "MSCHAPV2")
1739 params = hs20_ap_params()
1740 params['roaming_consortium'] = ["223344"]
1741 params['anqp_3gpp_cell_net'] = "555,444"
1742 hostapd.add_ap(apdev[0], params)
1743
1744 params = hs20_ap_params()
1745 params['ssid'] = "test-hs20-other"
1746 params['roaming_consortium'] = ["223344"]
1747 params['anqp_3gpp_cell_net'] = "555,444"
1748 hostapd.add_ap(apdev[1], params)
1749
1750 values = default_cred()
1751 values['excluded_ssid'] = "test-hs20"
1752 events = policy_test(dev[0], apdev[1], values)
1753 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1754 if len(ev) != 1:
1755 raise Exception("Excluded network not reported")
1756 values['excluded_ssid'] = "test-hs20-other"
1757 events = policy_test(dev[0], apdev[0], values)
1758 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[1]['bssid'] in e]
1759 if len(ev) != 1:
1760 raise Exception("Excluded network not reported")
1761
1762 values = default_cred()
1763 values['roaming_consortium'] = "223344"
1764 values['eap'] = "TTLS"
1765 values['phase2'] = "auth=MSCHAPV2"
1766 values['excluded_ssid'] = "test-hs20"
1767 events = policy_test(dev[0], apdev[1], values)
1768 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1769 if len(ev) != 1:
1770 raise Exception("Excluded network not reported")
1771
1772 values = {'imsi': "555444-333222111", 'eap': "SIM",
1773 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
1774 'excluded_ssid': "test-hs20"}
1775 events = policy_test(dev[0], apdev[1], values)
1776 ev = [e for e in events if "INTERWORKING-BLACKLISTED " + apdev[0]['bssid'] in e]
1777 if len(ev) != 1:
1778 raise Exception("Excluded network not reported")
1779
1780 def test_ap_hs20_roam_to_higher_prio(dev, apdev):
1781 """Hotspot 2.0 and roaming from current to higher priority network"""
1782 check_eap_capa(dev[0], "MSCHAPV2")
1783 bssid = apdev[0]['bssid']
1784 params = hs20_ap_params(ssid="test-hs20-visited")
1785 params['domain_name'] = "visited.example.org"
1786 hostapd.add_ap(apdev[0], params)
1787
1788 dev[0].hs20_enable()
1789 id = dev[0].add_cred_values({'realm': "example.com",
1790 'ca_cert': "auth_serv/ca.pem",
1791 'username': "hs20-test",
1792 'password': "password",
1793 'domain': "example.com"})
1794 logger.info("Connect to the only network option")
1795 interworking_select(dev[0], bssid, "roaming", freq="2412")
1796 dev[0].dump_monitor()
1797 interworking_connect(dev[0], bssid, "TTLS")
1798
1799 logger.info("Start another AP (home operator) and reconnect")
1800 bssid2 = apdev[1]['bssid']
1801 params = hs20_ap_params(ssid="test-hs20-home")
1802 params['domain_name'] = "example.com"
1803 hostapd.add_ap(apdev[1], params)
1804
1805 dev[0].scan_for_bss(bssid2, freq="2412", force_scan=True)
1806 dev[0].request("INTERWORKING_SELECT auto freq=2412")
1807 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH",
1808 "INTERWORKING-ALREADY-CONNECTED",
1809 "CTRL-EVENT-CONNECTED"], timeout=15)
1810 if ev is None:
1811 raise Exception("Connection timed out")
1812 if "INTERWORKING-NO-MATCH" in ev:
1813 raise Exception("Matching AP not found")
1814 if "INTERWORKING-ALREADY-CONNECTED" in ev:
1815 raise Exception("Unexpected AP selected")
1816 if bssid2 not in ev:
1817 raise Exception("Unexpected BSSID after reconnection")
1818
1819 def test_ap_hs20_domain_suffix_match_full(dev, apdev):
1820 """Hotspot 2.0 and domain_suffix_match"""
1821 check_domain_match_full(dev[0])
1822 check_eap_capa(dev[0], "MSCHAPV2")
1823 bssid = apdev[0]['bssid']
1824 params = hs20_ap_params()
1825 hostapd.add_ap(apdev[0], params)
1826
1827 dev[0].hs20_enable()
1828 id = dev[0].add_cred_values({'realm': "example.com",
1829 'username': "hs20-test",
1830 'password': "password",
1831 'ca_cert': "auth_serv/ca.pem",
1832 'domain': "example.com",
1833 'domain_suffix_match': "server.w1.fi"})
1834 interworking_select(dev[0], bssid, "home", freq="2412")
1835 dev[0].dump_monitor()
1836 interworking_connect(dev[0], bssid, "TTLS")
1837 dev[0].request("REMOVE_NETWORK all")
1838 dev[0].dump_monitor()
1839
1840 dev[0].set_cred_quoted(id, "domain_suffix_match", "no-match.example.com")
1841 interworking_select(dev[0], bssid, "home", freq="2412")
1842 dev[0].dump_monitor()
1843 dev[0].request("INTERWORKING_CONNECT " + bssid)
1844 ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"])
1845 if ev is None:
1846 raise Exception("TLS certificate error not reported")
1847 if "Domain suffix mismatch" not in ev:
1848 raise Exception("Domain suffix mismatch not reported")
1849
1850 def test_ap_hs20_domain_suffix_match(dev, apdev):
1851 """Hotspot 2.0 and domain_suffix_match"""
1852 check_eap_capa(dev[0], "MSCHAPV2")
1853 check_domain_match_full(dev[0])
1854 bssid = apdev[0]['bssid']
1855 params = hs20_ap_params()
1856 hostapd.add_ap(apdev[0], params)
1857
1858 dev[0].hs20_enable()
1859 id = dev[0].add_cred_values({'realm': "example.com",
1860 'username': "hs20-test",
1861 'password': "password",
1862 'ca_cert': "auth_serv/ca.pem",
1863 'domain': "example.com",
1864 'domain_suffix_match': "w1.fi"})
1865 interworking_select(dev[0], bssid, "home", freq="2412")
1866 dev[0].dump_monitor()
1867 interworking_connect(dev[0], bssid, "TTLS")
1868
1869 def test_ap_hs20_roaming_partner_preference(dev, apdev):
1870 """Hotspot 2.0 and roaming partner preference"""
1871 check_eap_capa(dev[0], "MSCHAPV2")
1872 params = hs20_ap_params()
1873 params['domain_name'] = "roaming.example.org"
1874 hostapd.add_ap(apdev[0], params)
1875
1876 params = hs20_ap_params()
1877 params['ssid'] = "test-hs20-other"
1878 params['domain_name'] = "roaming.example.net"
1879 hostapd.add_ap(apdev[1], params)
1880
1881 logger.info("Verify default vs. specified preference")
1882 values = default_cred()
1883 values['roaming_partner'] = "roaming.example.net,1,127,*"
1884 policy_test(dev[0], apdev[1], values, only_one=False)
1885 values['roaming_partner'] = "roaming.example.net,1,129,*"
1886 policy_test(dev[0], apdev[0], values, only_one=False)
1887
1888 logger.info("Verify partial FQDN match")
1889 values['roaming_partner'] = "example.net,0,0,*"
1890 policy_test(dev[0], apdev[1], values, only_one=False)
1891 values['roaming_partner'] = "example.net,0,255,*"
1892 policy_test(dev[0], apdev[0], values, only_one=False)
1893
1894 def test_ap_hs20_max_bss_load(dev, apdev):
1895 """Hotspot 2.0 and maximum BSS load"""
1896 check_eap_capa(dev[0], "MSCHAPV2")
1897 params = hs20_ap_params()
1898 params['bss_load_test'] = "12:200:20000"
1899 hostapd.add_ap(apdev[0], params)
1900
1901 params = hs20_ap_params()
1902 params['ssid'] = "test-hs20-other"
1903 params['bss_load_test'] = "5:20:10000"
1904 hostapd.add_ap(apdev[1], params)
1905
1906 logger.info("Verify maximum BSS load constraint")
1907 values = default_cred()
1908 values['domain'] = "example.com"
1909 values['max_bss_load'] = "100"
1910 events = policy_test(dev[0], apdev[1], values, only_one=False)
1911
1912 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1913 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1914 raise Exception("Maximum BSS Load case not noticed")
1915 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1916 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1917 raise Exception("Maximum BSS Load case reported incorrectly")
1918
1919 logger.info("Verify maximum BSS load does not prevent connection")
1920 values['max_bss_load'] = "1"
1921 events = policy_test(dev[0], None, values)
1922
1923 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1924 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1925 raise Exception("Maximum BSS Load case not noticed")
1926 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1927 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1928 raise Exception("Maximum BSS Load case not noticed")
1929
1930 def test_ap_hs20_max_bss_load2(dev, apdev):
1931 """Hotspot 2.0 and maximum BSS load with one AP not advertising"""
1932 check_eap_capa(dev[0], "MSCHAPV2")
1933 params = hs20_ap_params()
1934 params['bss_load_test'] = "12:200:20000"
1935 hostapd.add_ap(apdev[0], params)
1936
1937 params = hs20_ap_params()
1938 params['ssid'] = "test-hs20-other"
1939 hostapd.add_ap(apdev[1], params)
1940
1941 logger.info("Verify maximum BSS load constraint with AP advertisement")
1942 values = default_cred()
1943 values['domain'] = "example.com"
1944 values['max_bss_load'] = "100"
1945 events = policy_test(dev[0], apdev[1], values, only_one=False)
1946
1947 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1948 if len(ev) != 1 or "over_max_bss_load=1" not in ev[0]:
1949 raise Exception("Maximum BSS Load case not noticed")
1950 ev = [e for e in events if "INTERWORKING-AP " + apdev[1]['bssid'] in e]
1951 if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
1952 raise Exception("Maximum BSS Load case reported incorrectly")
1953
1954 def test_ap_hs20_max_bss_load_roaming(dev, apdev):
1955 """Hotspot 2.0 and maximum BSS load (roaming)"""
1956 check_eap_capa(dev[0], "MSCHAPV2")
1957 params = hs20_ap_params()
1958 params['bss_load_test'] = "12:200:20000"
1959 hostapd.add_ap(apdev[0], params)
1960
1961 values = default_cred()
1962 values['domain'] = "roaming.example.com"
1963 values['max_bss_load'] = "100"
1964 events = policy_test(dev[0], apdev[0], values, only_one=True)
1965 ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
1966 if len(ev) != 1:
1967 raise Exception("No INTERWORKING-AP event")
1968 if "over_max_bss_load=1" in ev[0]:
1969 raise Exception("Maximum BSS Load reported for roaming")
1970
1971 def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1972 """Hotspot 2.0 multi-cred sp_priority"""
1973 check_eap_capa(dev[0], "MSCHAPV2")
1974 try:
1975 _test_ap_hs20_multi_cred_sp_prio(dev, apdev)
1976 finally:
1977 dev[0].request("SET external_sim 0")
1978
1979 def _test_ap_hs20_multi_cred_sp_prio(dev, apdev):
1980 hlr_auc_gw_available()
1981 bssid = apdev[0]['bssid']
1982 params = hs20_ap_params()
1983 params['hessid'] = bssid
1984 del params['domain_name']
1985 params['anqp_3gpp_cell_net'] = "232,01"
1986 hostapd.add_ap(apdev[0], params)
1987
1988 dev[0].hs20_enable()
1989 dev[0].scan_for_bss(bssid, freq="2412")
1990 dev[0].request("SET external_sim 1")
1991 id1 = dev[0].add_cred_values({'imsi': "23201-0000000000", 'eap': "SIM",
1992 'provisioning_sp': "example.com",
1993 'sp_priority' :"1"})
1994 id2 = dev[0].add_cred_values({'realm': "example.com",
1995 'ca_cert': "auth_serv/ca.pem",
1996 'username': "hs20-test",
1997 'password': "password",
1998 'domain': "example.com",
1999 'provisioning_sp': "example.com",
2000 'sp_priority': "2"})
2001 dev[0].dump_monitor()
2002 dev[0].scan_for_bss(bssid, freq="2412")
2003 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2004 interworking_ext_sim_auth(dev[0], "SIM")
2005 check_sp_type(dev[0], "unknown")
2006 dev[0].request("REMOVE_NETWORK all")
2007
2008 dev[0].set_cred(id1, "sp_priority", "2")
2009 dev[0].set_cred(id2, "sp_priority", "1")
2010 dev[0].dump_monitor()
2011 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2012 interworking_auth(dev[0], "TTLS")
2013 check_sp_type(dev[0], "unknown")
2014
2015 def test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
2016 """Hotspot 2.0 multi-cred sp_priority with two BSSes"""
2017 check_eap_capa(dev[0], "MSCHAPV2")
2018 try:
2019 _test_ap_hs20_multi_cred_sp_prio2(dev, apdev)
2020 finally:
2021 dev[0].request("SET external_sim 0")
2022
2023 def _test_ap_hs20_multi_cred_sp_prio2(dev, apdev):
2024 hlr_auc_gw_available()
2025 bssid = apdev[0]['bssid']
2026 params = hs20_ap_params()
2027 params['hessid'] = bssid
2028 del params['nai_realm']
2029 del params['domain_name']
2030 params['anqp_3gpp_cell_net'] = "232,01"
2031 hostapd.add_ap(apdev[0], params)
2032
2033 bssid2 = apdev[1]['bssid']
2034 params = hs20_ap_params()
2035 params['ssid'] = "test-hs20-other"
2036 params['hessid'] = bssid2
2037 del params['domain_name']
2038 del params['anqp_3gpp_cell_net']
2039 hostapd.add_ap(apdev[1], params)
2040
2041 dev[0].hs20_enable()
2042 dev[0].request("SET external_sim 1")
2043 id1 = dev[0].add_cred_values({'imsi': "23201-0000000000", 'eap': "SIM",
2044 'provisioning_sp': "example.com",
2045 'sp_priority': "1"})
2046 id2 = dev[0].add_cred_values({'realm': "example.com",
2047 'ca_cert': "auth_serv/ca.pem",
2048 'username': "hs20-test",
2049 'password': "password",
2050 'domain': "example.com",
2051 'provisioning_sp': "example.com",
2052 'sp_priority': "2"})
2053 dev[0].dump_monitor()
2054 dev[0].scan_for_bss(bssid, freq="2412")
2055 dev[0].scan_for_bss(bssid2, freq="2412")
2056 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2057 interworking_ext_sim_auth(dev[0], "SIM")
2058 check_sp_type(dev[0], "unknown")
2059 conn_bssid = dev[0].get_status_field("bssid")
2060 if conn_bssid != bssid:
2061 raise Exception("Connected to incorrect BSS")
2062 dev[0].request("REMOVE_NETWORK all")
2063
2064 dev[0].set_cred(id1, "sp_priority", "2")
2065 dev[0].set_cred(id2, "sp_priority", "1")
2066 dev[0].dump_monitor()
2067 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2068 interworking_auth(dev[0], "TTLS")
2069 check_sp_type(dev[0], "unknown")
2070 conn_bssid = dev[0].get_status_field("bssid")
2071 if conn_bssid != bssid2:
2072 raise Exception("Connected to incorrect BSS")
2073
2074 def test_ap_hs20_multi_cred_sp_prio_same(dev, apdev):
2075 """Hotspot 2.0 multi-cred and same sp_priority"""
2076 check_eap_capa(dev[0], "MSCHAPV2")
2077 hlr_auc_gw_available()
2078 bssid = apdev[0]['bssid']
2079 params = hs20_ap_params()
2080 params['hessid'] = bssid
2081 del params['domain_name']
2082 params['anqp_3gpp_cell_net'] = "232,01"
2083 hostapd.add_ap(apdev[0], params)
2084
2085 dev[0].hs20_enable()
2086 dev[0].scan_for_bss(bssid, freq="2412")
2087 id1 = dev[0].add_cred_values({'realm': "example.com",
2088 'ca_cert': "auth_serv/ca.pem",
2089 'username': "hs20-test",
2090 'password': "password",
2091 'domain': "domain1.example.com",
2092 'provisioning_sp': "example.com",
2093 'sp_priority': "1"})
2094 id2 = dev[0].add_cred_values({'realm': "example.com",
2095 'ca_cert': "auth_serv/ca.pem",
2096 'username': "hs20-test",
2097 'password': "password",
2098 'domain': "domain2.example.com",
2099 'provisioning_sp': "example.com",
2100 'sp_priority': "1"})
2101 dev[0].dump_monitor()
2102 dev[0].scan_for_bss(bssid, freq="2412")
2103 check_auto_select(dev[0], bssid)
2104
2105 def check_conn_capab_selection(dev, type, missing):
2106 dev.request("INTERWORKING_SELECT freq=2412")
2107 ev = dev.wait_event(["INTERWORKING-AP"])
2108 if ev is None:
2109 raise Exception("Network selection timed out")
2110 if "type=" + type not in ev:
2111 raise Exception("Unexpected network type")
2112 if missing and "conn_capab_missing=1" not in ev:
2113 raise Exception("conn_capab_missing not reported")
2114 if not missing and "conn_capab_missing=1" in ev:
2115 raise Exception("conn_capab_missing reported unexpectedly")
2116
2117 def conn_capab_cred(domain=None, req_conn_capab=None):
2118 cred = default_cred(domain=domain)
2119 if req_conn_capab:
2120 cred['req_conn_capab'] = req_conn_capab
2121 return cred
2122
2123 def test_ap_hs20_req_conn_capab(dev, apdev):
2124 """Hotspot 2.0 network selection with req_conn_capab"""
2125 check_eap_capa(dev[0], "MSCHAPV2")
2126 bssid = apdev[0]['bssid']
2127 params = hs20_ap_params()
2128 hostapd.add_ap(apdev[0], params)
2129
2130 dev[0].hs20_enable()
2131 dev[0].scan_for_bss(bssid, freq="2412")
2132 logger.info("Not used in home network")
2133 values = conn_capab_cred(domain="example.com", req_conn_capab="6:1234")
2134 id = dev[0].add_cred_values(values)
2135 check_conn_capab_selection(dev[0], "home", False)
2136
2137 logger.info("Used in roaming network")
2138 dev[0].remove_cred(id)
2139 values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
2140 id = dev[0].add_cred_values(values)
2141 check_conn_capab_selection(dev[0], "roaming", True)
2142
2143 logger.info("Verify that req_conn_capab does not prevent connection if no other network is available")
2144 check_auto_select(dev[0], bssid)
2145
2146 logger.info("Additional req_conn_capab checks")
2147
2148 dev[0].remove_cred(id)
2149 values = conn_capab_cred(domain="example.org", req_conn_capab="1:0")
2150 id = dev[0].add_cred_values(values)
2151 check_conn_capab_selection(dev[0], "roaming", True)
2152
2153 dev[0].remove_cred(id)
2154 values = conn_capab_cred(domain="example.org", req_conn_capab="17:5060")
2155 id = dev[0].add_cred_values(values)
2156 check_conn_capab_selection(dev[0], "roaming", True)
2157
2158 bssid2 = apdev[1]['bssid']
2159 params = hs20_ap_params(ssid="test-hs20b")
2160 params['hs20_conn_capab'] = ["1:0:2", "6:22:1", "17:5060:0", "50:0:1"]
2161 hostapd.add_ap(apdev[1], params)
2162
2163 dev[0].remove_cred(id)
2164 values = conn_capab_cred(domain="example.org", req_conn_capab="50")
2165 id = dev[0].add_cred_values(values)
2166 dev[0].set_cred(id, "req_conn_capab", "6:22")
2167 dev[0].scan_for_bss(bssid2, freq="2412")
2168 dev[0].request("INTERWORKING_SELECT freq=2412")
2169 for i in range(0, 2):
2170 ev = dev[0].wait_event(["INTERWORKING-AP"])
2171 if ev is None:
2172 raise Exception("Network selection timed out")
2173 if bssid in ev and "conn_capab_missing=1" not in ev:
2174 raise Exception("Missing protocol connection capability not reported")
2175 if bssid2 in ev and "conn_capab_missing=1" in ev:
2176 raise Exception("Protocol connection capability not reported correctly")
2177
2178 def test_ap_hs20_req_conn_capab2(dev, apdev):
2179 """Hotspot 2.0 network selection with req_conn_capab (not present)"""
2180 check_eap_capa(dev[0], "MSCHAPV2")
2181 bssid = apdev[0]['bssid']
2182 params = hs20_ap_params()
2183 del params['hs20_conn_capab']
2184 hostapd.add_ap(apdev[0], params)
2185
2186 dev[0].hs20_enable()
2187 dev[0].scan_for_bss(bssid, freq="2412")
2188 values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
2189 id = dev[0].add_cred_values(values)
2190 check_conn_capab_selection(dev[0], "roaming", False)
2191
2192 def test_ap_hs20_req_conn_capab_and_roaming_partner_preference(dev, apdev):
2193 """Hotspot 2.0 and req_conn_capab with roaming partner preference"""
2194 check_eap_capa(dev[0], "MSCHAPV2")
2195 bssid = apdev[0]['bssid']
2196 params = hs20_ap_params()
2197 params['domain_name'] = "roaming.example.org"
2198 params['hs20_conn_capab'] = ["1:0:2", "6:22:1", "17:5060:0", "50:0:1"]
2199 hostapd.add_ap(apdev[0], params)
2200
2201 bssid2 = apdev[1]['bssid']
2202 params = hs20_ap_params(ssid="test-hs20-b")
2203 params['domain_name'] = "roaming.example.net"
2204 hostapd.add_ap(apdev[1], params)
2205
2206 values = default_cred()
2207 values['roaming_partner'] = "roaming.example.net,1,127,*"
2208 id = dev[0].add_cred_values(values)
2209 check_auto_select(dev[0], bssid2)
2210
2211 dev[0].set_cred(id, "req_conn_capab", "50")
2212 check_auto_select(dev[0], bssid)
2213
2214 dev[0].remove_cred(id)
2215 id = dev[0].add_cred_values(values)
2216 dev[0].set_cred(id, "req_conn_capab", "51")
2217 check_auto_select(dev[0], bssid2)
2218
2219 def check_bandwidth_selection(dev, type, below):
2220 dev.request("INTERWORKING_SELECT freq=2412")
2221 ev = dev.wait_event(["INTERWORKING-AP"])
2222 if ev is None:
2223 raise Exception("Network selection timed out")
2224 logger.debug("BSS entries:\n" + dev.request("BSS RANGE=ALL"))
2225 if "type=" + type not in ev:
2226 raise Exception("Unexpected network type")
2227 if below and "below_min_backhaul=1" not in ev:
2228 raise Exception("below_min_backhaul not reported")
2229 if not below and "below_min_backhaul=1" in ev:
2230 raise Exception("below_min_backhaul reported unexpectedly")
2231
2232 def bw_cred(domain=None, dl_home=None, ul_home=None, dl_roaming=None, ul_roaming=None):
2233 cred = default_cred(domain=domain)
2234 if dl_home:
2235 cred['min_dl_bandwidth_home'] = str(dl_home)
2236 if ul_home:
2237 cred['min_ul_bandwidth_home'] = str(ul_home)
2238 if dl_roaming:
2239 cred['min_dl_bandwidth_roaming'] = str(dl_roaming)
2240 if ul_roaming:
2241 cred['min_ul_bandwidth_roaming'] = str(ul_roaming)
2242 return cred
2243
2244 def test_ap_hs20_min_bandwidth_home(dev, apdev):
2245 """Hotspot 2.0 network selection with min bandwidth (home)"""
2246 check_eap_capa(dev[0], "MSCHAPV2")
2247 bssid = apdev[0]['bssid']
2248 params = hs20_ap_params()
2249 hostapd.add_ap(apdev[0], params)
2250
2251 dev[0].hs20_enable()
2252 dev[0].scan_for_bss(bssid, freq="2412")
2253 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
2254 id = dev[0].add_cred_values(values)
2255 check_bandwidth_selection(dev[0], "home", False)
2256 dev[0].remove_cred(id)
2257
2258 values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
2259 id = dev[0].add_cred_values(values)
2260 check_bandwidth_selection(dev[0], "home", True)
2261 dev[0].remove_cred(id)
2262
2263 values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
2264 id = dev[0].add_cred_values(values)
2265 check_bandwidth_selection(dev[0], "home", True)
2266 dev[0].remove_cred(id)
2267
2268 values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
2269 id = dev[0].add_cred_values(values)
2270 check_bandwidth_selection(dev[0], "home", True)
2271 check_auto_select(dev[0], bssid)
2272
2273 bssid2 = apdev[1]['bssid']
2274 params = hs20_ap_params(ssid="test-hs20-b")
2275 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2276 hostapd.add_ap(apdev[1], params)
2277
2278 check_auto_select(dev[0], bssid2)
2279
2280 def test_ap_hs20_min_bandwidth_home2(dev, apdev):
2281 """Hotspot 2.0 network selection with min bandwidth - special cases"""
2282 check_eap_capa(dev[0], "MSCHAPV2")
2283 bssid = apdev[0]['bssid']
2284 params = hs20_ap_params()
2285 hapd = hostapd.add_ap(apdev[0], params)
2286
2287 dev[0].hs20_enable()
2288 dev[0].scan_for_bss(bssid, freq="2412")
2289 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
2290 id = dev[0].add_cred_values(values)
2291 check_bandwidth_selection(dev[0], "home", False)
2292
2293 logger.info("WAN link at capacity")
2294 hapd.set('hs20_wan_metrics', "09:8000:1000:80:240:3000")
2295 check_bandwidth_selection(dev[0], "home", True)
2296
2297 logger.info("Downlink/Uplink Load was not measured")
2298 hapd.set('hs20_wan_metrics', "01:8000:1000:80:240:0")
2299 check_bandwidth_selection(dev[0], "home", False)
2300
2301 logger.info("Uplink and Downlink max values")
2302 hapd.set('hs20_wan_metrics', "01:4294967295:4294967295:80:240:3000")
2303 check_bandwidth_selection(dev[0], "home", False)
2304
2305 dev[0].remove_cred(id)
2306
2307 def test_ap_hs20_min_bandwidth_home_hidden_ssid_in_scan_res(dev, apdev):
2308 """Hotspot 2.0 network selection with min bandwidth (home) while hidden SSID is included in scan results"""
2309 check_eap_capa(dev[0], "MSCHAPV2")
2310 bssid = apdev[0]['bssid']
2311
2312 hapd = hostapd.add_ap(apdev[0], {"ssid": 'secret',
2313 "ignore_broadcast_ssid": "1"})
2314 dev[0].scan_for_bss(bssid, freq=2412)
2315 hapd.disable()
2316 hapd_global = hostapd.HostapdGlobal(apdev[0])
2317 hapd_global.flush()
2318 hapd_global.remove(apdev[0]['ifname'])
2319
2320 params = hs20_ap_params()
2321 hostapd.add_ap(apdev[0], params)
2322
2323 dev[0].hs20_enable()
2324 dev[0].scan_for_bss(bssid, freq="2412")
2325 values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
2326 id = dev[0].add_cred_values(values)
2327 check_bandwidth_selection(dev[0], "home", False)
2328 dev[0].remove_cred(id)
2329
2330 values = bw_cred(domain="example.com", dl_home=5491, ul_home=58)
2331 id = dev[0].add_cred_values(values)
2332 check_bandwidth_selection(dev[0], "home", True)
2333 dev[0].remove_cred(id)
2334
2335 values = bw_cred(domain="example.com", dl_home=5490, ul_home=59)
2336 id = dev[0].add_cred_values(values)
2337 check_bandwidth_selection(dev[0], "home", True)
2338 dev[0].remove_cred(id)
2339
2340 values = bw_cred(domain="example.com", dl_home=5491, ul_home=59)
2341 id = dev[0].add_cred_values(values)
2342 check_bandwidth_selection(dev[0], "home", True)
2343 check_auto_select(dev[0], bssid)
2344
2345 bssid2 = apdev[1]['bssid']
2346 params = hs20_ap_params(ssid="test-hs20-b")
2347 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2348 hostapd.add_ap(apdev[1], params)
2349
2350 check_auto_select(dev[0], bssid2)
2351
2352 dev[0].flush_scan_cache()
2353
2354 def test_ap_hs20_min_bandwidth_roaming(dev, apdev):
2355 """Hotspot 2.0 network selection with min bandwidth (roaming)"""
2356 check_eap_capa(dev[0], "MSCHAPV2")
2357 bssid = apdev[0]['bssid']
2358 params = hs20_ap_params()
2359 hostapd.add_ap(apdev[0], params)
2360
2361 dev[0].hs20_enable()
2362 dev[0].scan_for_bss(bssid, freq="2412")
2363 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=58)
2364 id = dev[0].add_cred_values(values)
2365 check_bandwidth_selection(dev[0], "roaming", False)
2366 dev[0].remove_cred(id)
2367
2368 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=58)
2369 id = dev[0].add_cred_values(values)
2370 check_bandwidth_selection(dev[0], "roaming", True)
2371 dev[0].remove_cred(id)
2372
2373 values = bw_cred(domain="example.org", dl_roaming=5490, ul_roaming=59)
2374 id = dev[0].add_cred_values(values)
2375 check_bandwidth_selection(dev[0], "roaming", True)
2376 dev[0].remove_cred(id)
2377
2378 values = bw_cred(domain="example.org", dl_roaming=5491, ul_roaming=59)
2379 id = dev[0].add_cred_values(values)
2380 check_bandwidth_selection(dev[0], "roaming", True)
2381 check_auto_select(dev[0], bssid)
2382
2383 bssid2 = apdev[1]['bssid']
2384 params = hs20_ap_params(ssid="test-hs20-b")
2385 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2386 hostapd.add_ap(apdev[1], params)
2387
2388 check_auto_select(dev[0], bssid2)
2389
2390 def test_ap_hs20_min_bandwidth_and_roaming_partner_preference(dev, apdev):
2391 """Hotspot 2.0 and minimum bandwidth with roaming partner preference"""
2392 check_eap_capa(dev[0], "MSCHAPV2")
2393 bssid = apdev[0]['bssid']
2394 params = hs20_ap_params()
2395 params['domain_name'] = "roaming.example.org"
2396 params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
2397 hostapd.add_ap(apdev[0], params)
2398
2399 bssid2 = apdev[1]['bssid']
2400 params = hs20_ap_params(ssid="test-hs20-b")
2401 params['domain_name'] = "roaming.example.net"
2402 hostapd.add_ap(apdev[1], params)
2403
2404 values = default_cred()
2405 values['roaming_partner'] = "roaming.example.net,1,127,*"
2406 id = dev[0].add_cred_values(values)
2407 check_auto_select(dev[0], bssid2)
2408
2409 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "6000")
2410 check_auto_select(dev[0], bssid)
2411
2412 dev[0].set_cred(id, "min_dl_bandwidth_roaming", "10000")
2413 check_auto_select(dev[0], bssid2)
2414
2415 def test_ap_hs20_min_bandwidth_no_wan_metrics(dev, apdev):
2416 """Hotspot 2.0 network selection with min bandwidth but no WAN Metrics"""
2417 bssid = apdev[0]['bssid']
2418 params = hs20_ap_params()
2419 del params['hs20_wan_metrics']
2420 hostapd.add_ap(apdev[0], params)
2421
2422 dev[0].hs20_enable()
2423 dev[0].scan_for_bss(bssid, freq="2412")
2424 values = bw_cred(domain="example.com", dl_home=10000, ul_home=10000,
2425 dl_roaming=10000, ul_roaming=10000)
2426 dev[0].add_cred_values(values)
2427 check_bandwidth_selection(dev[0], "home", False)
2428
2429 def test_ap_hs20_deauth_req_ess(dev, apdev):
2430 """Hotspot 2.0 connection and deauthentication request for ESS"""
2431 check_eap_capa(dev[0], "MSCHAPV2")
2432 try:
2433 _test_ap_hs20_deauth_req_ess(dev, apdev)
2434 finally:
2435 dev[0].request("SET pmf 0")
2436
2437 def _test_ap_hs20_deauth_req_ess(dev, apdev):
2438 dev[0].request("SET pmf 2")
2439 hapd = eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
2440 dev[0].dump_monitor()
2441 addr = dev[0].p2p_interface_addr()
2442 hapd.wait_sta()
2443 hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
2444 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
2445 if ev is None:
2446 raise Exception("Timeout on deauth imminent notice")
2447 if "1 120 http://example.com/" not in ev:
2448 raise Exception("Unexpected deauth imminent notice: " + ev)
2449 hapd.request("DEAUTHENTICATE " + addr)
2450 dev[0].wait_disconnected(timeout=10)
2451 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
2452 raise Exception("Network not marked temporarily disabled")
2453 ev = dev[0].wait_event(["SME: Trying to authenticate",
2454 "Trying to associate",
2455 "CTRL-EVENT-CONNECTED"], timeout=5)
2456 if ev is not None:
2457 raise Exception("Unexpected connection attempt")
2458
2459 def test_ap_hs20_deauth_req_bss(dev, apdev):
2460 """Hotspot 2.0 connection and deauthentication request for BSS"""
2461 check_eap_capa(dev[0], "MSCHAPV2")
2462 try:
2463 _test_ap_hs20_deauth_req_bss(dev, apdev)
2464 finally:
2465 dev[0].request("SET pmf 0")
2466
2467 def _test_ap_hs20_deauth_req_bss(dev, apdev):
2468 dev[0].request("SET pmf 2")
2469 hapd = eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
2470 dev[0].dump_monitor()
2471 addr = dev[0].p2p_interface_addr()
2472 hapd.wait_sta()
2473 hapd.request("HS20_DEAUTH_REQ " + addr + " 0 120 http://example.com/")
2474 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"])
2475 if ev is None:
2476 raise Exception("Timeout on deauth imminent notice")
2477 if "0 120 http://example.com/" not in ev:
2478 raise Exception("Unexpected deauth imminent notice: " + ev)
2479 hapd.request("DEAUTHENTICATE " + addr + " reason=4")
2480 ev = dev[0].wait_disconnected(timeout=10)
2481 if "reason=4" not in ev:
2482 raise Exception("Unexpected disconnection reason")
2483 if "[TEMP-DISABLED]" not in dev[0].list_networks()[0]['flags']:
2484 raise Exception("Network not marked temporarily disabled")
2485 ev = dev[0].wait_event(["SME: Trying to authenticate",
2486 "Trying to associate",
2487 "CTRL-EVENT-CONNECTED"], timeout=5)
2488 if ev is not None:
2489 raise Exception("Unexpected connection attempt")
2490
2491 def test_ap_hs20_deauth_req_from_radius(dev, apdev):
2492 """Hotspot 2.0 connection and deauthentication request from RADIUS"""
2493 check_eap_capa(dev[0], "MSCHAPV2")
2494 try:
2495 _test_ap_hs20_deauth_req_from_radius(dev, apdev)
2496 finally:
2497 dev[0].request("SET pmf 0")
2498
2499 def _test_ap_hs20_deauth_req_from_radius(dev, apdev):
2500 bssid = apdev[0]['bssid']
2501 params = hs20_ap_params()
2502 params['nai_realm'] = ["0,example.com,21[2:4]"]
2503 params['hs20_deauth_req_timeout'] = "2"
2504 hostapd.add_ap(apdev[0], params)
2505
2506 dev[0].request("SET pmf 2")
2507 dev[0].hs20_enable()
2508 dev[0].add_cred_values({'realm': "example.com",
2509 'username': "hs20-deauth-test",
2510 'password': "password"})
2511 interworking_select(dev[0], bssid, freq="2412")
2512 interworking_connect(dev[0], bssid, "TTLS")
2513 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=5)
2514 if ev is None:
2515 raise Exception("Timeout on deauth imminent notice")
2516 if " 1 100" not in ev:
2517 raise Exception("Unexpected deauth imminent contents")
2518 dev[0].wait_disconnected(timeout=3)
2519
2520 def test_ap_hs20_deauth_req_without_pmf(dev, apdev):
2521 """Hotspot 2.0 connection and deauthentication request without PMF"""
2522 check_eap_capa(dev[0], "MSCHAPV2")
2523 dev[0].request("SET pmf 0")
2524 hapd = eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user", release=1)
2525 dev[0].dump_monitor()
2526 id = int(dev[0].get_status_field("id"))
2527 dev[0].set_network(id, "ieee80211w", "0")
2528 dev[0].request("DISCONNECT")
2529 dev[0].wait_disconnected()
2530 dev[0].select_network(id, freq=2412)
2531 dev[0].wait_connected()
2532 addr = dev[0].own_addr()
2533 hapd.wait_sta()
2534 hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
2535 ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=0.2)
2536 if ev is not None:
2537 raise Exception("Deauth imminent notice without PMF accepted")
2538 with alloc_fail(hapd, 1, "wpabuf_alloc;hostapd_ctrl_iface_hs20_deauth_req"):
2539 if "FAIL" not in hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/"):
2540 raise Exception("HS20_DEAUTH_REQ accepted during OOM")
2541
2542 def test_ap_hs20_remediation_required(dev, apdev):
2543 """Hotspot 2.0 connection and remediation required from RADIUS"""
2544 check_eap_capa(dev[0], "MSCHAPV2")
2545 try:
2546 _test_ap_hs20_remediation_required(dev, apdev)
2547 finally:
2548 dev[0].request("SET pmf 0")
2549
2550 def _test_ap_hs20_remediation_required(dev, apdev):
2551 bssid = apdev[0]['bssid']
2552 params = hs20_ap_params()
2553 params['nai_realm'] = ["0,example.com,21[2:4]"]
2554 hostapd.add_ap(apdev[0], params)
2555
2556 dev[0].request("SET pmf 1")
2557 dev[0].hs20_enable()
2558 dev[0].add_cred_values({'realm': "example.com",
2559 'username': "hs20-subrem-test",
2560 'password': "password"})
2561 interworking_select(dev[0], bssid, freq="2412")
2562 interworking_connect(dev[0], bssid, "TTLS")
2563 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2564 if ev is None:
2565 raise Exception("Timeout on subscription remediation notice")
2566 if " 1 https://example.com/" not in ev:
2567 raise Exception("Unexpected subscription remediation event contents")
2568
2569 def test_ap_hs20_remediation_required_ctrl(dev, apdev):
2570 """Hotspot 2.0 connection and subrem from ctrl_iface"""
2571 check_eap_capa(dev[0], "MSCHAPV2")
2572 try:
2573 _test_ap_hs20_remediation_required_ctrl(dev, apdev)
2574 finally:
2575 dev[0].request("SET pmf 0")
2576
2577 def _test_ap_hs20_remediation_required_ctrl(dev, apdev):
2578 bssid = apdev[0]['bssid']
2579 addr = dev[0].own_addr()
2580 params = hs20_ap_params()
2581 params['nai_realm'] = ["0,example.com,21[2:4]"]
2582 hapd = hostapd.add_ap(apdev[0], params)
2583
2584 dev[0].request("SET pmf 1")
2585 dev[0].hs20_enable()
2586 dev[0].add_cred_values(default_cred())
2587 interworking_select(dev[0], bssid, freq="2412")
2588 interworking_connect(dev[0], bssid, "TTLS")
2589
2590 hapd.request("HS20_WNM_NOTIF " + addr + " https://example.com/")
2591 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2592 if ev is None:
2593 raise Exception("Timeout on subscription remediation notice")
2594 if " 1 https://example.com/" not in ev:
2595 raise Exception("Unexpected subscription remediation event contents")
2596
2597 hapd.request("HS20_WNM_NOTIF " + addr)
2598 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
2599 if ev is None:
2600 raise Exception("Timeout on subscription remediation notice")
2601 if not ev.endswith("HS20-SUBSCRIPTION-REMEDIATION "):
2602 raise Exception("Unexpected subscription remediation event contents: " + ev)
2603
2604 if "FAIL" not in hapd.request("HS20_WNM_NOTIF "):
2605 raise Exception("Unexpected HS20_WNM_NOTIF success")
2606 if "FAIL" not in hapd.request("HS20_WNM_NOTIF foo"):
2607 raise Exception("Unexpected HS20_WNM_NOTIF success")
2608 if "FAIL" not in hapd.request("HS20_WNM_NOTIF " + addr + " https://12345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678923456789842345678456783456712345678927.very.long.example.com/"):
2609 raise Exception("Unexpected HS20_WNM_NOTIF success")
2610 if "OK" not in hapd.request("HS20_WNM_NOTIF " + addr + " "):
2611 raise Exception("HS20_WNM_NOTIF failed with empty URL")
2612
2613 def test_ap_hs20_session_info(dev, apdev):
2614 """Hotspot 2.0 connection and session information from RADIUS"""
2615 check_eap_capa(dev[0], "MSCHAPV2")
2616 try:
2617 _test_ap_hs20_session_info(dev, apdev)
2618 finally:
2619 dev[0].request("SET pmf 0")
2620
2621 def _test_ap_hs20_session_info(dev, apdev):
2622 bssid = apdev[0]['bssid']
2623 params = hs20_ap_params()
2624 params['nai_realm'] = ["0,example.com,21[2:4]"]
2625 hostapd.add_ap(apdev[0], params)
2626
2627 dev[0].request("SET pmf 1")
2628 dev[0].hs20_enable()
2629 dev[0].add_cred_values({'realm': "example.com",
2630 'username': "hs20-session-info-test",
2631 'password': "password"})
2632 interworking_select(dev[0], bssid, freq="2412")
2633 interworking_connect(dev[0], bssid, "TTLS")
2634 ev = dev[0].wait_event(["ESS-DISASSOC-IMMINENT"], timeout=10)
2635 if ev is None:
2636 raise Exception("Timeout on ESS disassociation imminent notice")
2637 if " 1 59904 https://example.com/" not in ev:
2638 raise Exception("Unexpected ESS disassociation imminent event contents")
2639 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
2640 if ev is None:
2641 raise Exception("Scan not started")
2642 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=30)
2643 if ev is None:
2644 raise Exception("Scan not completed")
2645
2646 def test_ap_hs20_osen(dev, apdev):
2647 """Hotspot 2.0 OSEN connection"""
2648 params = {'ssid': "osen",
2649 'osen': "1",
2650 'auth_server_addr': "127.0.0.1",
2651 'auth_server_port': "1812",
2652 'auth_server_shared_secret': "radius"}
2653 hostapd.add_ap(apdev[0], params)
2654
2655 dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412",
2656 wait_connect=False)
2657 dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"',
2658 scan_freq="2412", wait_connect=False)
2659 dev[0].flush_scan_cache()
2660 dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
2661 group="GTK_NOT_USED CCMP",
2662 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
2663 ca_cert="auth_serv/ca.pem",
2664 scan_freq="2412")
2665 res = dev[0].get_bss(apdev[0]['bssid'])['flags']
2666 if "[OSEN-OSEN-CCMP]" not in res:
2667 raise Exception("OSEN not reported in BSS")
2668 if "[WEP]" in res:
2669 raise Exception("WEP reported in BSS")
2670 res = dev[0].request("SCAN_RESULTS")
2671 if "[OSEN-OSEN-CCMP]" not in res:
2672 raise Exception("OSEN not reported in SCAN_RESULTS")
2673
2674 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2675 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
2676 wpas.connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
2677 group="GTK_NOT_USED CCMP",
2678 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
2679 ca_cert="auth_serv/ca.pem",
2680 scan_freq="2412")
2681 wpas.request("DISCONNECT")
2682
2683 def test_ap_hs20_osen_single_ssid(dev, apdev):
2684 """Hotspot 2.0 OSEN-single-SSID connection"""
2685 bssid = apdev[0]['bssid']
2686 params = hs20_ap_params()
2687 params['wpa_key_mgmt'] = "WPA-EAP OSEN"
2688 params['hessid'] = bssid
2689 hapd = hostapd.add_ap(apdev[0], params)
2690
2691 # RSN-OSEN (for OSU)
2692 dev[0].connect("test-hs20", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP",
2693 group="CCMP GTK_NOT_USED",
2694 eap="WFA-UNAUTH-TLS", identity="osen@example.com",
2695 ca_cert="auth_serv/ca.pem", ieee80211w='2',
2696 scan_freq="2412")
2697 # RSN-EAP (for data connection)
2698 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
2699 identity="hs20-test", password="password",
2700 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
2701 pairwise="CCMP", group="CCMP",
2702 ieee80211w='2', scan_freq="2412")
2703
2704 res = dev[0].get_bss(apdev[0]['bssid'])['flags']
2705 if "[WPA2-EAP+OSEN-CCMP]" not in res:
2706 raise Exception("OSEN not reported in BSS")
2707 if "[WEP]" in res:
2708 raise Exception("WEP reported in BSS")
2709 res = dev[0].request("SCAN_RESULTS")
2710 if "[WPA2-EAP+OSEN-CCMP]" not in res:
2711 raise Exception("OSEN not reported in SCAN_RESULTS")
2712
2713 hwsim_utils.test_connectivity(dev[1], hapd)
2714 hwsim_utils.test_connectivity(dev[0], hapd, broadcast=False)
2715 hwsim_utils.test_connectivity(dev[0], hapd, timeout=1,
2716 success_expected=False)
2717
2718 def test_ap_hs20_network_preference(dev, apdev):
2719 """Hotspot 2.0 network selection with preferred home network"""
2720 check_eap_capa(dev[0], "MSCHAPV2")
2721 bssid = apdev[0]['bssid']
2722 params = hs20_ap_params()
2723 hostapd.add_ap(apdev[0], params)
2724
2725 dev[0].hs20_enable()
2726 values = {'realm': "example.com",
2727 'username': "hs20-test",
2728 'password': "password",
2729 'domain': "example.com"}
2730 dev[0].add_cred_values(values)
2731
2732 id = dev[0].add_network()
2733 dev[0].set_network_quoted(id, "ssid", "home")
2734 dev[0].set_network_quoted(id, "psk", "12345678")
2735 dev[0].set_network(id, "priority", "1")
2736 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
2737
2738 dev[0].scan_for_bss(bssid, freq="2412")
2739 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2740 ev = dev[0].wait_connected(timeout=15)
2741 if bssid not in ev:
2742 raise Exception("Unexpected network selected")
2743
2744 bssid2 = apdev[1]['bssid']
2745 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
2746 hostapd.add_ap(apdev[1], params)
2747
2748 dev[0].scan_for_bss(bssid2, freq="2412")
2749 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2750 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2751 "INTERWORKING-ALREADY-CONNECTED"], timeout=15)
2752 if ev is None:
2753 raise Exception("Connection timed out")
2754 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2755 raise Exception("No roam to higher priority network")
2756 if bssid2 not in ev:
2757 raise Exception("Unexpected network selected")
2758
2759 def test_ap_hs20_network_preference2(dev, apdev):
2760 """Hotspot 2.0 network selection with preferred credential"""
2761 check_eap_capa(dev[0], "MSCHAPV2")
2762 bssid2 = apdev[1]['bssid']
2763 params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
2764 hostapd.add_ap(apdev[1], params)
2765
2766 dev[0].hs20_enable()
2767 values = {'realm': "example.com",
2768 'username': "hs20-test",
2769 'password': "password",
2770 'domain': "example.com",
2771 'priority': "1"}
2772 dev[0].add_cred_values(values)
2773
2774 id = dev[0].add_network()
2775 dev[0].set_network_quoted(id, "ssid", "home")
2776 dev[0].set_network_quoted(id, "psk", "12345678")
2777 dev[0].request("ENABLE_NETWORK %s no-connect" % id)
2778
2779 dev[0].scan_for_bss(bssid2, freq="2412")
2780 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2781 ev = dev[0].wait_connected(timeout=15)
2782 if bssid2 not in ev:
2783 raise Exception("Unexpected network selected")
2784
2785 bssid = apdev[0]['bssid']
2786 params = hs20_ap_params()
2787 hostapd.add_ap(apdev[0], params)
2788
2789 dev[0].scan_for_bss(bssid, freq="2412")
2790 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2791 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2792 "INTERWORKING-ALREADY-CONNECTED"], timeout=15)
2793 if ev is None:
2794 raise Exception("Connection timed out")
2795 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2796 raise Exception("No roam to higher priority network")
2797 if bssid not in ev:
2798 raise Exception("Unexpected network selected")
2799
2800 def test_ap_hs20_network_preference3(dev, apdev):
2801 """Hotspot 2.0 network selection with two credential (one preferred)"""
2802 check_eap_capa(dev[0], "MSCHAPV2")
2803 bssid = apdev[0]['bssid']
2804 params = hs20_ap_params()
2805 hostapd.add_ap(apdev[0], params)
2806
2807 bssid2 = apdev[1]['bssid']
2808 params = hs20_ap_params(ssid="test-hs20b")
2809 params['nai_realm'] = "0,example.org,13[5:6],21[2:4][5:7]"
2810 hostapd.add_ap(apdev[1], params)
2811
2812 dev[0].hs20_enable()
2813 values = {'realm': "example.com",
2814 'username': "hs20-test",
2815 'password': "password",
2816 'priority': "1"}
2817 dev[0].add_cred_values(values)
2818 values = {'realm': "example.org",
2819 'username': "hs20-test",
2820 'password': "password"}
2821 id = dev[0].add_cred_values(values)
2822
2823 dev[0].scan_for_bss(bssid, freq="2412")
2824 dev[0].scan_for_bss(bssid2, freq="2412")
2825 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2826 ev = dev[0].wait_connected(timeout=15)
2827 if bssid not in ev:
2828 raise Exception("Unexpected network selected")
2829
2830 dev[0].set_cred(id, "priority", "2")
2831 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2832 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2833 "INTERWORKING-ALREADY-CONNECTED"], timeout=15)
2834 if ev is None:
2835 raise Exception("Connection timed out")
2836 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2837 raise Exception("No roam to higher priority network")
2838 if bssid2 not in ev:
2839 raise Exception("Unexpected network selected")
2840
2841 def test_ap_hs20_network_preference4(dev, apdev):
2842 """Hotspot 2.0 network selection with username vs. SIM credential"""
2843 check_eap_capa(dev[0], "MSCHAPV2")
2844 bssid = apdev[0]['bssid']
2845 params = hs20_ap_params()
2846 hostapd.add_ap(apdev[0], params)
2847
2848 bssid2 = apdev[1]['bssid']
2849 params = hs20_ap_params(ssid="test-hs20b")
2850 params['hessid'] = bssid2
2851 params['anqp_3gpp_cell_net'] = "555,444"
2852 params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
2853 hostapd.add_ap(apdev[1], params)
2854
2855 dev[0].hs20_enable()
2856 values = {'realm': "example.com",
2857 'username': "hs20-test",
2858 'password': "password",
2859 'priority': "1"}
2860 dev[0].add_cred_values(values)
2861 values = {'imsi': "555444-333222111",
2862 'eap': "SIM",
2863 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"}
2864 id = dev[0].add_cred_values(values)
2865
2866 dev[0].scan_for_bss(bssid, freq="2412")
2867 dev[0].scan_for_bss(bssid2, freq="2412")
2868 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2869 ev = dev[0].wait_connected(timeout=15)
2870 if bssid not in ev:
2871 raise Exception("Unexpected network selected")
2872
2873 dev[0].set_cred(id, "priority", "2")
2874 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2875 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
2876 "INTERWORKING-ALREADY-CONNECTED"], timeout=15)
2877 if ev is None:
2878 raise Exception("Connection timed out")
2879 if "INTERWORKING-ALREADY-CONNECTED" in ev:
2880 raise Exception("No roam to higher priority network")
2881 if bssid2 not in ev:
2882 raise Exception("Unexpected network selected")
2883
2884 def test_ap_hs20_interworking_select_blocking_scan(dev, apdev):
2885 """Ongoing INTERWORKING_SELECT blocking SCAN"""
2886 check_eap_capa(dev[0], "MSCHAPV2")
2887 bssid = apdev[0]['bssid']
2888 params = hs20_ap_params()
2889 hostapd.add_ap(apdev[0], params)
2890
2891 dev[0].hs20_enable()
2892 values = {'realm': "example.com",
2893 'username': "hs20-test",
2894 'password': "password",
2895 'domain': "example.com"}
2896 dev[0].add_cred_values(values)
2897
2898 dev[0].scan_for_bss(bssid, freq="2412")
2899 dev[0].request("INTERWORKING_SELECT auto freq=2412")
2900 if "FAIL-BUSY" not in dev[0].request("SCAN"):
2901 raise Exception("Unexpected SCAN command result")
2902 dev[0].wait_connected(timeout=15)
2903
2904 def test_ap_hs20_fetch_osu(dev, apdev):
2905 """Hotspot 2.0 OSU provider and icon fetch"""
2906 bssid = apdev[0]['bssid']
2907 params = hs20_ap_params()
2908 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2909 params['osu_ssid'] = '"HS 2.0 OSU open"'
2910 params['osu_method_list'] = "1"
2911 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
2912 params['osu_icon'] = "w1fi_logo"
2913 params['osu_service_desc'] = ["eng:Example services", "fin:Esimerkkipalveluja"]
2914 params['osu_server_uri'] = "https://example.com/osu/"
2915 hostapd.add_ap(apdev[0], params)
2916
2917 bssid2 = apdev[1]['bssid']
2918 params = hs20_ap_params(ssid="test-hs20b")
2919 params['hessid'] = bssid2
2920 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
2921 params['osu_ssid'] = '"HS 2.0 OSU OSEN"'
2922 params['osu_method_list'] = "0"
2923 params['osu_nai'] = "osen@example.com"
2924 params['osu_friendly_name'] = ["eng:Test2 OSU", "fin:Testi2-OSU"]
2925 params['osu_icon'] = "w1fi_logo"
2926 params['osu_service_desc'] = ["eng:Example services2", "fin:Esimerkkipalveluja2"]
2927 params['osu_server_uri'] = "https://example.org/osu/"
2928 hostapd.add_ap(apdev[1], params)
2929
2930 with open("w1fi_logo.png", "rb") as f:
2931 orig_logo = f.read()
2932 dev[0].hs20_enable()
2933 dir = "/tmp/osu-fetch"
2934 if os.path.isdir(dir):
2935 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
2936 for f in files:
2937 os.remove(dir + "/" + f)
2938 else:
2939 try:
2940 os.makedirs(dir)
2941 except:
2942 pass
2943 try:
2944 dev[1].scan_for_bss(bssid, freq="2412")
2945 dev[2].scan_for_bss(bssid, freq="2412")
2946 dev[0].request("SET osu_dir " + dir)
2947 dev[0].request("FETCH_OSU")
2948 if "FAIL" not in dev[1].request("HS20_ICON_REQUEST foo w1fi_logo"):
2949 raise Exception("Invalid HS20_ICON_REQUEST accepted")
2950 if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
2951 raise Exception("HS20_ICON_REQUEST failed")
2952 if "OK" not in dev[2].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
2953 raise Exception("REQ_HS20_ICON failed")
2954 icons = 0
2955 while True:
2956 ev = dev[0].wait_event(["OSU provider fetch completed",
2957 "RX-HS20-ANQP-ICON"], timeout=15)
2958 if ev is None:
2959 raise Exception("Timeout on OSU fetch")
2960 if "OSU provider fetch completed" in ev:
2961 break
2962 if "RX-HS20-ANQP-ICON" in ev:
2963 with open(ev.split(' ')[1], "rb") as f:
2964 logo = f.read()
2965 if logo == orig_logo:
2966 icons += 1
2967
2968 with open(dir + "/osu-providers.txt", "r") as f:
2969 prov = f.read()
2970 logger.debug("osu-providers.txt: " + prov)
2971 if "OSU-PROVIDER " + bssid not in prov:
2972 raise Exception("Missing OSU_PROVIDER(1)")
2973 if "OSU-PROVIDER " + bssid2 not in prov:
2974 raise Exception("Missing OSU_PROVIDER(2)")
2975 finally:
2976 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
2977 for f in files:
2978 os.remove(dir + "/" + f)
2979 os.rmdir(dir)
2980
2981 if icons != 2:
2982 raise Exception("Unexpected number of icons fetched")
2983
2984 ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=5)
2985 if ev is None:
2986 raise Exception("Timeout on GAS-QUERY-DONE")
2987 ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=5)
2988 if ev is None:
2989 raise Exception("Timeout on GAS-QUERY-DONE")
2990 if "freq=2412 status_code=0 result=SUCCESS" not in ev:
2991 raise Exception("Unexpected GAS-QUERY-DONE: " + ev)
2992 ev = dev[1].wait_event(["RX-HS20-ANQP"], timeout=15)
2993 if ev is None:
2994 raise Exception("Timeout on icon fetch")
2995 if "Icon Binary File" not in ev:
2996 raise Exception("Unexpected ANQP element")
2997
2998 ev = dev[2].wait_event(["RX-HS20-ICON"], timeout=5)
2999 if ev is None:
3000 raise Exception("Timeout on RX-HS20-ICON")
3001 event_icon_len = ev.split(' ')[3]
3002 if " w1fi_logo " not in ev:
3003 raise Exception("RX-HS20-ICON did not have the expected file name")
3004 if bssid not in ev:
3005 raise Exception("RX-HS20-ICON did not have the expected BSSID")
3006 if "FAIL" in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 10"):
3007 raise Exception("GET_HS20_ICON 0..10 failed")
3008 if "FAIL" in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 5 10"):
3009 raise Exception("GET_HS20_ICON 5..15 failed")
3010 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 100000 10"):
3011 raise Exception("Unexpected success of GET_HS20_ICON with too large offset")
3012 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " no_such_logo 0 10"):
3013 raise Exception("GET_HS20_ICON for not existing icon succeeded")
3014 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 3070"):
3015 raise Exception("GET_HS20_ICON with too many output bytes to fit the buffer succeeded")
3016 if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 0"):
3017 raise Exception("GET_HS20_ICON 0..0 succeeded")
3018 icon = b''
3019 pos = 0
3020 while True:
3021 if pos > 100000:
3022 raise Exception("Unexpectedly long icon")
3023 res = dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo %d 1000" % pos)
3024 if res.startswith("FAIL"):
3025 break
3026 icon += base64.b64decode(res)
3027 pos += 1000
3028 hex = binascii.hexlify(icon).decode()
3029 if not hex.startswith("0009696d6167652f706e677d1d"):
3030 raise Exception("Unexpected beacon binary header: " + hex)
3031 with open('w1fi_logo.png', 'rb') as f:
3032 data = f.read()
3033 if icon[13:] != data:
3034 raise Exception("Unexpected icon data")
3035 if len(icon) != int(event_icon_len):
3036 raise Exception("Unexpected RX-HS20-ICON event length: " + event_icon_len)
3037
3038 for i in range(3):
3039 if "OK" not in dev[i].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3040 raise Exception("REQ_HS20_ICON failed [2]")
3041 for i in range(3):
3042 ev = dev[i].wait_event(["RX-HS20-ICON"], timeout=5)
3043 if ev is None:
3044 raise Exception("Timeout on RX-HS20-ICON [2]")
3045
3046 if "FAIL" not in dev[2].request("DEL_HS20_ICON foo w1fi_logo"):
3047 raise Exception("Invalid DEL_HS20_ICON accepted")
3048 if "OK" not in dev[2].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3049 raise Exception("DEL_HS20_ICON failed")
3050 if "OK" not in dev[1].request("DEL_HS20_ICON " + bssid):
3051 raise Exception("DEL_HS20_ICON failed")
3052 if "OK" not in dev[0].request("DEL_HS20_ICON "):
3053 raise Exception("DEL_HS20_ICON failed")
3054 for i in range(3):
3055 if "FAIL" not in dev[i].request("DEL_HS20_ICON "):
3056 raise Exception("DEL_HS20_ICON accepted when no icons left")
3057
3058 def test_ap_hs20_fetch_osu_no_info(dev, apdev):
3059 """Hotspot 2.0 OSU provider and no AP with info"""
3060 bssid = apdev[0]['bssid']
3061 params = hs20_ap_params()
3062 hostapd.add_ap(apdev[0], params)
3063
3064 dev[0].hs20_enable()
3065 dir = "/tmp/osu-fetch"
3066 if os.path.isdir(dir):
3067 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3068 for f in files:
3069 os.remove(dir + "/" + f)
3070 else:
3071 try:
3072 os.makedirs(dir)
3073 except:
3074 pass
3075 dev[0].scan_for_bss(bssid, freq="2412")
3076 try:
3077 dev[0].request("SET osu_dir " + dir)
3078 dev[0].request("FETCH_OSU")
3079 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3080 if ev is None:
3081 raise Exception("Timeout on OSU fetch")
3082 finally:
3083 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3084 for f in files:
3085 os.remove(dir + "/" + f)
3086 os.rmdir(dir)
3087
3088 def test_ap_hs20_fetch_osu_no_icon(dev, apdev):
3089 """Hotspot 2.0 OSU provider and no icon found"""
3090 bssid = apdev[0]['bssid']
3091 params = hs20_ap_params()
3092 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
3093 params['osu_ssid'] = '"HS 2.0 OSU open"'
3094 params['osu_method_list'] = "1"
3095 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3096 params['osu_icon'] = "w1fi_logo"
3097 params['osu_service_desc'] = ["eng:Example services",
3098 "fin:Esimerkkipalveluja"]
3099 params['osu_server_uri'] = "https://example.com/osu/"
3100 hostapd.add_ap(apdev[0], params)
3101
3102 dev[0].hs20_enable()
3103 dir = "/tmp/osu-fetch"
3104 if os.path.isdir(dir):
3105 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3106 for f in files:
3107 os.remove(dir + "/" + f)
3108 else:
3109 try:
3110 os.makedirs(dir)
3111 except:
3112 pass
3113 dev[0].scan_for_bss(bssid, freq="2412")
3114 try:
3115 dev[0].request("SET osu_dir " + dir)
3116 dev[0].request("FETCH_OSU")
3117 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3118 if ev is None:
3119 raise Exception("Timeout on OSU fetch")
3120 finally:
3121 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3122 for f in files:
3123 os.remove(dir + "/" + f)
3124 os.rmdir(dir)
3125
3126 def test_ap_hs20_fetch_osu_single_ssid(dev, apdev):
3127 """Hotspot 2.0 OSU provider and single SSID"""
3128 bssid = apdev[0]['bssid']
3129 params = hs20_ap_params()
3130 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
3131 params['osu_ssid'] = '"HS 2.0 OSU open"'
3132 params['osu_method_list'] = "1"
3133 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3134 params['osu_nai2'] = "osen@example.com"
3135 params['osu_icon'] = "w1fi_logo"
3136 params['osu_service_desc'] = ["eng:Example services",
3137 "fin:Esimerkkipalveluja"]
3138 params['osu_server_uri'] = "https://example.com/osu/"
3139 params['wpa_key_mgmt'] = "WPA-EAP OSEN"
3140 hostapd.add_ap(apdev[0], params)
3141
3142 dev[0].hs20_enable()
3143 dir = "/tmp/osu-fetch"
3144 if os.path.isdir(dir):
3145 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3146 for f in files:
3147 os.remove(dir + "/" + f)
3148 else:
3149 try:
3150 os.makedirs(dir)
3151 except:
3152 pass
3153 dev[0].scan_for_bss(bssid, freq="2412")
3154 try:
3155 dev[0].request("SET osu_dir " + dir)
3156 dev[0].request("FETCH_OSU")
3157 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3158 if ev is None:
3159 raise Exception("Timeout on OSU fetch")
3160 osu_ssid = False
3161 osu_ssid2 = False
3162 osu_nai = False
3163 osu_nai2 = False
3164 with open(os.path.join(dir, "osu-providers.txt"), "r") as f:
3165 for l in f.readlines():
3166 logger.info(l.strip())
3167 if l.strip() == "osu_ssid=HS 2.0 OSU open":
3168 osu_ssid = True
3169 if l.strip() == "osu_ssid2=test-hs20":
3170 osu_ssid2 = True
3171 if l.strip().startswith("osu_nai="):
3172 osu_nai = True
3173 if l.strip() == "osu_nai2=osen@example.com":
3174 osu_nai2 = True
3175 if not osu_ssid:
3176 raise Exception("osu_ssid not reported")
3177 if not osu_ssid2:
3178 raise Exception("osu_ssid2 not reported")
3179 if osu_nai:
3180 raise Exception("osu_nai reported unexpectedly")
3181 if not osu_nai2:
3182 raise Exception("osu_nai2 not reported")
3183 finally:
3184 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3185 for f in files:
3186 os.remove(dir + "/" + f)
3187 os.rmdir(dir)
3188
3189 def test_ap_hs20_fetch_osu_single_ssid2(dev, apdev):
3190 """Hotspot 2.0 OSU provider and single SSID (two OSU providers)"""
3191 bssid = apdev[0]['bssid']
3192 params = hs20_ap_params()
3193 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
3194 params['osu_ssid'] = '"HS 2.0 OSU open"'
3195 params['osu_method_list'] = "1"
3196 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3197 params['osu_nai2'] = "osen@example.com"
3198 params['osu_icon'] = "w1fi_logo"
3199 params['osu_service_desc'] = ["eng:Example services",
3200 "fin:Esimerkkipalveluja"]
3201 params['osu_server_uri'] = "https://example.com/osu/"
3202 params['wpa_key_mgmt'] = "WPA-EAP OSEN"
3203 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
3204
3205 hapd.set('osu_server_uri', 'https://another.example.com/osu/')
3206 hapd.set('osu_method_list', "1")
3207 hapd.set('osu_nai2', "osen@another.example.com")
3208 hapd.enable()
3209
3210 dev[0].hs20_enable()
3211 dir = "/tmp/osu-fetch"
3212 if os.path.isdir(dir):
3213 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3214 for f in files:
3215 os.remove(dir + "/" + f)
3216 else:
3217 try:
3218 os.makedirs(dir)
3219 except:
3220 pass
3221 dev[0].scan_for_bss(bssid, freq="2412")
3222 try:
3223 dev[0].request("SET osu_dir " + dir)
3224 dev[0].request("FETCH_OSU")
3225 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3226 if ev is None:
3227 raise Exception("Timeout on OSU fetch")
3228 osu_ssid = False
3229 osu_ssid2 = False
3230 osu_nai = False
3231 osu_nai2 = False
3232 osu_nai2b = False
3233 with open(os.path.join(dir, "osu-providers.txt"), "r") as f:
3234 for l in f.readlines():
3235 logger.info(l.strip())
3236 if l.strip() == "osu_ssid=HS 2.0 OSU open":
3237 osu_ssid = True
3238 if l.strip() == "osu_ssid2=test-hs20":
3239 osu_ssid2 = True
3240 if l.strip().startswith("osu_nai="):
3241 osu_nai = True
3242 if l.strip() == "osu_nai2=osen@example.com":
3243 osu_nai2 = True
3244 if l.strip() == "osu_nai2=osen@another.example.com":
3245 osu_nai2b = True
3246 if not osu_ssid:
3247 raise Exception("osu_ssid not reported")
3248 if not osu_ssid2:
3249 raise Exception("osu_ssid2 not reported")
3250 if osu_nai:
3251 raise Exception("osu_nai reported unexpectedly")
3252 if not osu_nai2:
3253 raise Exception("osu_nai2 not reported")
3254 if not osu_nai2b:
3255 raise Exception("osu_nai2b not reported")
3256 finally:
3257 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3258 for f in files:
3259 os.remove(dir + "/" + f)
3260 os.rmdir(dir)
3261
3262 def get_icon(dev, bssid, iconname):
3263 icon = b''
3264 pos = 0
3265 while True:
3266 if pos > 100000:
3267 raise Exception("Unexpectedly long icon")
3268 res = dev.request("GET_HS20_ICON " + bssid + " " + iconname + " %d 3000" % pos)
3269 if res.startswith("FAIL"):
3270 break
3271 icon += base64.b64decode(res)
3272 pos += 3000
3273 if len(icon) < 13:
3274 raise Exception("Too short GET_HS20_ICON response")
3275 return icon[0:13], icon[13:]
3276
3277 def test_ap_hs20_req_hs20_icon(dev, apdev):
3278 """Hotspot 2.0 OSU provider and multi-icon fetch with REQ_HS20_ICON"""
3279 bssid = apdev[0]['bssid']
3280 params = hs20_ap_params()
3281 params['hs20_icon'] = ["128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3282 "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem"]
3283 params['osu_ssid'] = '"HS 2.0 OSU open"'
3284 params['osu_method_list'] = "1"
3285 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3286 params['osu_icon'] = ["w1fi_logo", "w1fi_logo2"]
3287 params['osu_service_desc'] = ["eng:Example services",
3288 "fin:Esimerkkipalveluja"]
3289 params['osu_server_uri'] = "https://example.com/osu/"
3290 hostapd.add_ap(apdev[0], params)
3291
3292 dev[0].scan_for_bss(bssid, freq="2412")
3293 run_req_hs20_icon(dev, bssid)
3294
3295 def run_req_hs20_icon(dev, bssid):
3296 # First, fetch two icons from the AP to wpa_supplicant
3297
3298 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3299 raise Exception("REQ_HS20_ICON failed")
3300 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3301 if ev is None:
3302 raise Exception("Timeout on RX-HS20-ICON (1)")
3303
3304 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " test_logo"):
3305 raise Exception("REQ_HS20_ICON failed")
3306 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3307 if ev is None:
3308 raise Exception("Timeout on RX-HS20-ICON (2)")
3309
3310 # Then, fetch the icons from wpa_supplicant for validation
3311
3312 hdr, data1 = get_icon(dev[0], bssid, "w1fi_logo")
3313 hdr, data2 = get_icon(dev[0], bssid, "test_logo")
3314
3315 with open('w1fi_logo.png', 'rb') as f:
3316 data = f.read()
3317 if data1 != data:
3318 raise Exception("Unexpected icon data (1)")
3319
3320 with open('auth_serv/sha512-server.pem', 'rb') as f:
3321 data = f.read()
3322 if data2 != data:
3323 raise Exception("Unexpected icon data (2)")
3324
3325 # Finally, delete the icons from wpa_supplicant
3326
3327 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3328 raise Exception("DEL_HS20_ICON failed")
3329 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " test_logo"):
3330 raise Exception("DEL_HS20_ICON failed")
3331
3332 def test_ap_hs20_req_operator_icon(dev, apdev):
3333 """Hotspot 2.0 operator icons"""
3334 bssid = apdev[0]['bssid']
3335 params = hs20_ap_params()
3336 params['hs20_icon'] = ["128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3337 "500:300:fi:image/png:test_logo:auth_serv/sha512-server.pem"]
3338 params['operator_icon'] = ["w1fi_logo", "unknown_logo", "test_logo"]
3339 hostapd.add_ap(apdev[0], params)
3340
3341 value = struct.pack('<HH', 128, 80) + b"zxx"
3342 value += struct.pack('B', 9) + b"image/png"
3343 value += struct.pack('B', 9) + b"w1fi_logo"
3344
3345 value += struct.pack('<HH', 500, 300) + b"fi\0"
3346 value += struct.pack('B', 9) + b"image/png"
3347 value += struct.pack('B', 9) + b"test_logo"
3348
3349 dev[0].scan_for_bss(bssid, freq="2412")
3350
3351 if "OK" not in dev[0].request("ANQP_GET " + bssid + " hs20:12"):
3352 raise Exception("ANQP_GET command failed")
3353
3354 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
3355 if ev is None:
3356 raise Exception("GAS query start timed out")
3357
3358 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
3359 if ev is None:
3360 raise Exception("GAS query timed out")
3361
3362 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1)
3363 if ev is None or "Operator Icon Metadata" not in ev:
3364 raise Exception("Did not receive Operator Icon Metadata")
3365
3366 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
3367 if ev is None:
3368 raise Exception("ANQP-QUERY-DONE event not seen")
3369 if "result=SUCCESS" not in ev:
3370 raise Exception("Unexpected result: " + ev)
3371
3372 bss = dev[0].get_bss(bssid)
3373 if "hs20_operator_icon_metadata" not in bss:
3374 raise Exception("hs20_operator_icon_metadata missing from BSS entry")
3375 if bss["hs20_operator_icon_metadata"] != binascii.hexlify(value).decode():
3376 raise Exception("Unexpected hs20_operator_icon_metadata value: " +
3377 bss["hs20_operator_icon_metadata"])
3378
3379 run_req_hs20_icon(dev, bssid)
3380
3381 def test_ap_hs20_req_hs20_icon_oom(dev, apdev):
3382 """Hotspot 2.0 icon fetch OOM with REQ_HS20_ICON"""
3383 bssid = apdev[0]['bssid']
3384 params = hs20_ap_params()
3385 params['hs20_icon'] = ["128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3386 "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem"]
3387 params['osu_ssid'] = '"HS 2.0 OSU open"'
3388 params['osu_method_list'] = "1"
3389 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3390 params['osu_icon'] = ["w1fi_logo", "w1fi_logo2"]
3391 params['osu_service_desc'] = ["eng:Example services",
3392 "fin:Esimerkkipalveluja"]
3393 params['osu_server_uri'] = "https://example.com/osu/"
3394 hostapd.add_ap(apdev[0], params)
3395
3396 dev[0].scan_for_bss(bssid, freq="2412")
3397
3398 if "FAIL" not in dev[0].request("REQ_HS20_ICON 11:22:33:44:55:66 w1fi_logo"):
3399 raise Exception("REQ_HS20_ICON succeeded with unknown BSSID")
3400
3401 with alloc_fail(dev[0], 1, "hs20_build_anqp_req;hs20_anqp_send_req"):
3402 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3403 raise Exception("REQ_HS20_ICON succeeded during OOM")
3404
3405 with alloc_fail(dev[0], 1, "gas_query_req;hs20_anqp_send_req"):
3406 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3407 raise Exception("REQ_HS20_ICON succeeded during OOM")
3408
3409 with alloc_fail(dev[0], 1, "=hs20_anqp_send_req"):
3410 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3411 raise Exception("REQ_HS20_ICON succeeded during OOM")
3412 with alloc_fail(dev[0], 2, "=hs20_anqp_send_req"):
3413 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3414 raise Exception("REQ_HS20_ICON succeeded during OOM")
3415
3416 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3417 raise Exception("REQ_HS20_ICON failed")
3418 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3419 if ev is None:
3420 raise Exception("Timeout on RX-HS20-ICON (1)")
3421
3422 with alloc_fail(dev[0], 1, "hs20_get_icon"):
3423 if "FAIL" not in dev[0].request("GET_HS20_ICON " + bssid + "w1fi_logo 0 100"):
3424 raise Exception("GET_HS20_ICON succeeded during OOM")
3425
3426 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3427 raise Exception("DEL_HS20_ICON failed")
3428
3429 with alloc_fail(dev[0], 1, "=hs20_process_icon_binary_file"):
3430 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3431 raise Exception("REQ_HS20_ICON failed")
3432 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
3433
3434 def test_ap_hs20_req_hs20_icon_parallel(dev, apdev):
3435 """Hotspot 2.0 OSU provider and multi-icon parallel fetch with REQ_HS20_ICON"""
3436 bssid = apdev[0]['bssid']
3437 params = hs20_ap_params()
3438 params['hs20_icon'] = ["128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
3439 "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem"]
3440 params['osu_ssid'] = '"HS 2.0 OSU open"'
3441 params['osu_method_list'] = "1"
3442 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3443 params['osu_icon'] = ["w1fi_logo", "w1fi_logo2"]
3444 params['osu_service_desc'] = ["eng:Example services",
3445 "fin:Esimerkkipalveluja"]
3446 params['osu_server_uri'] = "https://example.com/osu/"
3447 hostapd.add_ap(apdev[0], params)
3448
3449 dev[0].scan_for_bss(bssid, freq="2412")
3450
3451 # First, fetch two icons from the AP to wpa_supplicant
3452
3453 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
3454 raise Exception("REQ_HS20_ICON failed")
3455
3456 if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " test_logo"):
3457 raise Exception("REQ_HS20_ICON failed")
3458 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3459 if ev is None:
3460 raise Exception("Timeout on RX-HS20-ICON (1)")
3461 ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
3462 if ev is None:
3463 raise Exception("Timeout on RX-HS20-ICON (2)")
3464
3465 # Then, fetch the icons from wpa_supplicant for validation
3466
3467 hdr, data1 = get_icon(dev[0], bssid, "w1fi_logo")
3468 hdr, data2 = get_icon(dev[0], bssid, "test_logo")
3469
3470 with open('w1fi_logo.png', 'rb') as f:
3471 data = f.read()
3472 if data1 != data:
3473 raise Exception("Unexpected icon data (1)")
3474
3475 with open('auth_serv/sha512-server.pem', 'rb') as f:
3476 data = f.read()
3477 if data2 != data:
3478 raise Exception("Unexpected icon data (2)")
3479
3480 # Finally, delete the icons from wpa_supplicant
3481
3482 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
3483 raise Exception("DEL_HS20_ICON failed")
3484 if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " test_logo"):
3485 raise Exception("DEL_HS20_ICON failed")
3486
3487 def test_ap_hs20_fetch_osu_stop(dev, apdev):
3488 """Hotspot 2.0 OSU provider fetch stopped"""
3489 bssid = apdev[0]['bssid']
3490 params = hs20_ap_params()
3491 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
3492 params['osu_ssid'] = '"HS 2.0 OSU open"'
3493 params['osu_method_list'] = "1"
3494 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3495 params['osu_icon'] = "w1fi_logo"
3496 params['osu_service_desc'] = ["eng:Example services",
3497 "fin:Esimerkkipalveluja"]
3498 params['osu_server_uri'] = "https://example.com/osu/"
3499 hapd = hostapd.add_ap(apdev[0], params)
3500
3501 dev[0].hs20_enable()
3502 dir = "/tmp/osu-fetch"
3503 if os.path.isdir(dir):
3504 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3505 for f in files:
3506 os.remove(dir + "/" + f)
3507 else:
3508 try:
3509 os.makedirs(dir)
3510 except:
3511 pass
3512 try:
3513 dev[0].request("SET osu_dir " + dir)
3514 dev[0].request("SCAN freq=2412-2462")
3515 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=10)
3516 if ev is None:
3517 raise Exception("Scan did not start")
3518 if "FAIL" not in dev[0].request("FETCH_OSU"):
3519 raise Exception("FETCH_OSU accepted while scanning")
3520 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 10)
3521 if ev is None:
3522 raise Exception("Scan timed out")
3523 hapd.set("ext_mgmt_frame_handling", "1")
3524 dev[0].request("FETCH_ANQP")
3525 if "FAIL" not in dev[0].request("FETCH_OSU"):
3526 raise Exception("FETCH_OSU accepted while in FETCH_ANQP")
3527 dev[0].request("STOP_FETCH_ANQP")
3528 dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
3529 dev[0].dump_monitor()
3530 hapd.dump_monitor()
3531 dev[0].request("INTERWORKING_SELECT freq=2412")
3532 for i in range(5):
3533 msg = hapd.mgmt_rx()
3534 if msg['subtype'] == 13:
3535 break
3536 if "FAIL" not in dev[0].request("FETCH_OSU"):
3537 raise Exception("FETCH_OSU accepted while in INTERWORKING_SELECT")
3538 ev = dev[0].wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
3539 timeout=15)
3540 if ev is None:
3541 raise Exception("Network selection timed out")
3542
3543 dev[0].dump_monitor()
3544 if "OK" not in dev[0].request("FETCH_OSU"):
3545 raise Exception("FETCH_OSU failed")
3546 dev[0].request("CANCEL_FETCH_OSU")
3547
3548 for i in range(15):
3549 time.sleep(0.5)
3550 if dev[0].get_driver_status_field("scan_state") == "SCAN_COMPLETED":
3551 break
3552
3553 dev[0].dump_monitor()
3554 if "OK" not in dev[0].request("FETCH_OSU"):
3555 raise Exception("FETCH_OSU failed")
3556 if "FAIL" not in dev[0].request("FETCH_OSU"):
3557 raise Exception("FETCH_OSU accepted while in FETCH_OSU")
3558 ev = dev[0].wait_event(["GAS-QUERY-START"], 10)
3559 if ev is None:
3560 raise Exception("GAS timed out")
3561 if "FAIL" not in dev[0].request("FETCH_OSU"):
3562 raise Exception("FETCH_OSU accepted while in FETCH_OSU")
3563 dev[0].request("CANCEL_FETCH_OSU")
3564 ev = dev[0].wait_event(["GAS-QUERY-DONE"], 10)
3565 if ev is None:
3566 raise Exception("GAS event timed out after CANCEL_FETCH_OSU")
3567 finally:
3568 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3569 for f in files:
3570 os.remove(dir + "/" + f)
3571 os.rmdir(dir)
3572
3573 def test_ap_hs20_fetch_osu_proto(dev, apdev):
3574 """Hotspot 2.0 OSU provider and protocol testing"""
3575 bssid = apdev[0]['bssid']
3576 params = hs20_ap_params()
3577 hapd = hostapd.add_ap(apdev[0], params)
3578
3579 dev[0].hs20_enable()
3580 dir = "/tmp/osu-fetch"
3581 if os.path.isdir(dir):
3582 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3583 for f in files:
3584 os.remove(dir + "/" + f)
3585 else:
3586 try:
3587 os.makedirs(dir)
3588 except:
3589 pass
3590
3591 tests = [("Empty provider list (no OSU SSID field)", b''),
3592 ("HS 2.0: Not enough room for OSU SSID",
3593 binascii.unhexlify('01')),
3594 ("HS 2.0: Invalid OSU SSID Length 33",
3595 binascii.unhexlify('21') + 33*b'A'),
3596 ("HS 2.0: Not enough room for Number of OSU Providers",
3597 binascii.unhexlify('0130')),
3598 ("Truncated OSU Provider",
3599 binascii.unhexlify('013001020000')),
3600 ("HS 2.0: Ignored 5 bytes of extra data after OSU Providers",
3601 binascii.unhexlify('0130001122334455')),
3602 ("HS 2.0: Not enough room for OSU Friendly Name Length",
3603 binascii.unhexlify('013001000000')),
3604 ("HS 2.0: Not enough room for OSU Friendly Name Duples",
3605 build_prov('0100')),
3606 ("Invalid OSU Friendly Name", build_prov('040000000000')),
3607 ("Invalid OSU Friendly Name(2)", build_prov('040004000000')),
3608 ("HS 2.0: Not enough room for OSU Server URI length",
3609 build_prov('0000')),
3610 ("HS 2.0: Not enough room for OSU Server URI",
3611 build_prov('000001')),
3612 ("HS 2.0: Not enough room for OSU Method list length",
3613 build_prov('000000')),
3614 ("HS 2.0: Not enough room for OSU Method list",
3615 build_prov('00000001')),
3616 ("HS 2.0: Not enough room for Icons Available Length",
3617 build_prov('00000000')),
3618 ("HS 2.0: Not enough room for Icons Available Length(2)",
3619 build_prov('00000001ff00')),
3620 ("HS 2.0: Not enough room for Icons Available",
3621 build_prov('000000000100')),
3622 ("HS 2.0: Invalid Icon Metadata",
3623 build_prov('00000000010000')),
3624 ("HS 2.0: Not room for Icon Type",
3625 build_prov('000000000900111122223333330200')),
3626 ("HS 2.0: Not room for Icon Filename length",
3627 build_prov('000000000900111122223333330100')),
3628 ("HS 2.0: Not room for Icon Filename",
3629 build_prov('000000000900111122223333330001')),
3630 ("HS 2.0: Not enough room for OSU_NAI",
3631 build_prov('000000000000')),
3632 ("HS 2.0: Not enough room for OSU_NAI(2)",
3633 build_prov('00000000000001')),
3634 ("HS 2.0: Not enough room for OSU Service Description Length",
3635 build_prov('00000000000000')),
3636 ("HS 2.0: Not enough room for OSU Service Description Length(2)",
3637 build_prov('0000000000000000')),
3638 ("HS 2.0: Not enough room for OSU Service Description Duples",
3639 build_prov('000000000000000100')),
3640 ("Invalid OSU Service Description",
3641 build_prov('00000000000000040000000000')),
3642 ("Invalid OSU Service Description(2)",
3643 build_prov('00000000000000040004000000'))]
3644
3645 try:
3646 dev[0].request("SET osu_dir " + dir)
3647 run_fetch_osu_icon_failure(hapd, dev, bssid)
3648 for note, prov in tests:
3649 run_fetch_osu(hapd, dev, bssid, note, prov)
3650 finally:
3651 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3652 for f in files:
3653 os.remove(dir + "/" + f)
3654 os.rmdir(dir)
3655
3656 def test_ap_hs20_fetch_osu_invalid_dir(dev, apdev):
3657 """Hotspot 2.0 OSU provider and invalid directory"""
3658 bssid = apdev[0]['bssid']
3659 params = hs20_ap_params()
3660 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
3661 params['osu_ssid'] = '"HS 2.0 OSU open"'
3662 params['osu_method_list'] = "1"
3663 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3664 params['osu_icon'] = "w1fi_logo"
3665 params['osu_service_desc'] = ["eng:Example services",
3666 "fin:Esimerkkipalveluja"]
3667 params['osu_server_uri'] = "https://example.com/osu/"
3668 hostapd.add_ap(apdev[0], params)
3669
3670 dev[0].hs20_enable()
3671 dir = "/tmp/osu-fetch-no-such-dir"
3672 dev[0].scan_for_bss(bssid, freq="2412")
3673 dev[0].request("SET osu_dir " + dir)
3674 dev[0].request("FETCH_OSU no-scan")
3675 ev = dev[0].wait_event(["Could not write OSU provider information"],
3676 timeout=15)
3677 if ev is None:
3678 raise Exception("Timeout on OSU fetch")
3679
3680 def test_ap_hs20_fetch_osu_oom(dev, apdev):
3681 """Hotspot 2.0 OSU provider and OOM"""
3682 bssid = apdev[0]['bssid']
3683 params = hs20_ap_params()
3684 params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
3685 params['osu_ssid'] = '"HS 2.0 OSU open"'
3686 params['osu_method_list'] = "1"
3687 params['osu_friendly_name'] = ["eng:Test OSU", "fin:Testi-OSU"]
3688 params['osu_icon'] = "w1fi_logo"
3689 params['osu_service_desc'] = ["eng:Example services",
3690 "fin:Esimerkkipalveluja"]
3691 params['osu_server_uri'] = "https://example.com/osu/"
3692 hostapd.add_ap(apdev[0], params)
3693
3694 dev[0].hs20_enable()
3695 dir = "/tmp/osu-fetch"
3696 if os.path.isdir(dir):
3697 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3698 for f in files:
3699 os.remove(dir + "/" + f)
3700 else:
3701 try:
3702 os.makedirs(dir)
3703 except:
3704 pass
3705 dev[0].scan_for_bss(bssid, freq="2412")
3706 try:
3707 dev[0].request("SET osu_dir " + dir)
3708 with alloc_fail(dev[0], 1, "=hs20_osu_add_prov"):
3709 dev[0].request("FETCH_OSU no-scan")
3710 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3711 if ev is None:
3712 raise Exception("Timeout on OSU fetch")
3713 with alloc_fail(dev[0], 1, "hs20_anqp_send_req;hs20_next_osu_icon"):
3714 dev[0].request("FETCH_OSU no-scan")
3715 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
3716 if ev is None:
3717 raise Exception("Timeout on OSU fetch")
3718 finally:
3719 files = [f for f in os.listdir(dir) if f.startswith("osu-")]
3720 for f in files:
3721 os.remove(dir + "/" + f)
3722 os.rmdir(dir)
3723
3724 def build_prov(prov):
3725 data = binascii.unhexlify(prov)
3726 return binascii.unhexlify('013001') + struct.pack('<H', len(data)) + data
3727
3728 def handle_osu_prov_fetch(hapd, dev, prov):
3729 # GAS/ANQP query for OSU Providers List
3730 query = gas_rx(hapd)
3731 gas = parse_gas(query['payload'])
3732 dialog_token = gas['dialog_token']
3733
3734 resp = action_response(query)
3735 osu_prov = struct.pack('<HH', 0xdddd, len(prov) + 6) + binascii.unhexlify('506f9a110800') + prov
3736 data = struct.pack('<H', len(osu_prov)) + osu_prov
3737 resp['payload'] = anqp_initial_resp(dialog_token, 0) + data
3738 send_gas_resp(hapd, resp)
3739
3740 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=5)
3741 if ev is None:
3742 raise Exception("ANQP query response for OSU Providers not received")
3743 if "OSU Providers list" not in ev:
3744 raise Exception("ANQP query response for OSU Providers not received(2)")
3745 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
3746 if ev is None:
3747 raise Exception("ANQP query for OSU Providers list not completed")
3748
3749 def start_osu_fetch(hapd, dev, bssid, note):
3750 hapd.set("ext_mgmt_frame_handling", "0")
3751 dev[0].request("BSS_FLUSH 0")
3752 dev[0].scan_for_bss(bssid, freq="2412")
3753 hapd.set("ext_mgmt_frame_handling", "1")
3754 dev[0].dump_monitor()
3755 dev[0].request("NOTE " + note)
3756 dev[0].request("FETCH_OSU no-scan")
3757
3758 def wait_osu_fetch_completed(dev):
3759 ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=5)
3760 if ev is None:
3761 raise Exception("Timeout on OSU fetch")
3762
3763 def run_fetch_osu_icon_failure(hapd, dev, bssid):
3764 start_osu_fetch(hapd, dev, bssid, "Icon fetch failure")
3765
3766 prov = binascii.unhexlify('01ff' + '01' + '800019000b656e6754657374204f53550c66696e54657374692d4f53551868747470733a2f2f6578616d706c652e636f6d2f6f73752f01011b00800050007a787809696d6167652f706e6709773166695f6c6f676f002a0013656e674578616d706c652073657276696365731566696e4573696d65726b6b6970616c76656c756a61')
3767 handle_osu_prov_fetch(hapd, dev, prov)
3768
3769 # GAS/ANQP query for icon
3770 query = gas_rx(hapd)
3771 gas = parse_gas(query['payload'])
3772 dialog_token = gas['dialog_token']
3773
3774 resp = action_response(query)
3775 # Unexpected Advertisement Protocol in response
3776 adv_proto = struct.pack('8B', 108, 6, 127, 0xdd, 0x00, 0x11, 0x22, 0x33)
3777 data = struct.pack('<H', 0)
3778 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
3779 GAS_INITIAL_RESPONSE,
3780 gas['dialog_token'], 0, 0) + adv_proto + data
3781 send_gas_resp(hapd, resp)
3782
3783 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
3784 if ev is None:
3785 raise Exception("ANQP query for icon not completed")
3786
3787 wait_osu_fetch_completed(dev)
3788
3789 def run_fetch_osu(hapd, dev, bssid, note, prov):
3790 start_osu_fetch(hapd, dev, bssid, note)
3791 handle_osu_prov_fetch(hapd, dev, prov)
3792 wait_osu_fetch_completed(dev)
3793
3794 def test_ap_hs20_ft(dev, apdev):
3795 """Hotspot 2.0 connection with FT"""
3796 check_eap_capa(dev[0], "MSCHAPV2")
3797 bssid = apdev[0]['bssid']
3798 params = hs20_ap_params()
3799 params['wpa_key_mgmt'] = "FT-EAP"
3800 params['nas_identifier'] = "nas1.w1.fi"
3801 params['r1_key_holder'] = "000102030405"
3802 params["mobility_domain"] = "a1b2"
3803 params["reassociation_deadline"] = "1000"
3804 hapd = hostapd.add_ap(apdev[0], params)
3805
3806 dev[0].hs20_enable()
3807 id = dev[0].add_cred_values({'realm': "example.com",
3808 'username': "hs20-test",
3809 'password': "password",
3810 'ca_cert': "auth_serv/ca.pem",
3811 'domain': "example.com",
3812 'update_identifier': "1234"})
3813 interworking_select(dev[0], bssid, "home", freq="2412")
3814 interworking_connect(dev[0], bssid, "TTLS")
3815 dev[0].dump_monitor()
3816 key_mgmt = dev[0].get_status_field("key_mgmt")
3817 if key_mgmt != "FT-EAP":
3818 raise Exception("Unexpected key_mgmt: " + key_mgmt)
3819 # speed up testing by avoiding unnecessary scanning of other channels
3820 nid = dev[0].get_status_field("id")
3821 dev[0].set_network(nid, "scan_freq", "2412")
3822
3823 params = hs20_ap_params()
3824 hapd2 = hostapd.add_ap(apdev[1], params)
3825
3826 hapd.disable()
3827 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=10)
3828 if ev is None:
3829 raise Exception("Disconnection not reported")
3830 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
3831 if ev is None:
3832 raise Exception("Connection to AP2 not reported")
3833 key_mgmt = dev[0].get_status_field("key_mgmt")
3834 if key_mgmt != "WPA2/IEEE 802.1X/EAP":
3835 raise Exception("Unexpected key_mgmt: " + key_mgmt)
3836
3837 def test_ap_hs20_remediation_sql(dev, apdev, params):
3838 """Hotspot 2.0 connection and remediation required using SQLite for user DB"""
3839 check_eap_capa(dev[0], "MSCHAPV2")
3840 try:
3841 import sqlite3
3842 except ImportError:
3843 raise HwsimSkip("No sqlite3 module available")
3844 dbfile = os.path.join(params['logdir'], "eap-user.db")
3845 try:
3846 os.remove(dbfile)
3847 except:
3848 pass
3849 con = sqlite3.connect(dbfile)
3850 with con:
3851 cur = con.cursor()
3852 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER)")
3853 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
3854 cur.execute("INSERT INTO users(identity,methods,password,phase2,remediation) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1,'user')")
3855 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
3856 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
3857
3858 try:
3859 params = {"ssid": "as", "beacon_int": "2000",
3860 "radius_server_clients": "auth_serv/radius_clients.conf",
3861 "radius_server_auth_port": '18128',
3862 "eap_server": "1",
3863 "eap_user_file": "sqlite:" + dbfile,
3864 "ca_cert": "auth_serv/ca.pem",
3865 "server_cert": "auth_serv/server.pem",
3866 "private_key": "auth_serv/server.key",
3867 "subscr_remediation_url": "https://example.org/",
3868 "subscr_remediation_method": "1"}
3869 hostapd.add_ap(apdev[1], params)
3870
3871 bssid = apdev[0]['bssid']
3872 params = hs20_ap_params()
3873 params['auth_server_port'] = "18128"
3874 hostapd.add_ap(apdev[0], params)
3875
3876 dev[0].request("SET pmf 1")
3877 dev[0].hs20_enable()
3878 id = dev[0].add_cred_values({'realm': "example.com",
3879 'username': "user-mschapv2",
3880 'password': "password",
3881 'ca_cert': "auth_serv/ca.pem"})
3882 interworking_select(dev[0], bssid, freq="2412")
3883 interworking_connect(dev[0], bssid, "TTLS")
3884 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
3885 if ev is None:
3886 raise Exception("Timeout on subscription remediation notice")
3887 if " 1 https://example.org/" not in ev:
3888 raise Exception("Unexpected subscription remediation event contents")
3889
3890 with con:
3891 cur = con.cursor()
3892 cur.execute("SELECT * from authlog")
3893 rows = cur.fetchall()
3894 if len(rows) < 1:
3895 raise Exception("No authlog entries")
3896
3897 finally:
3898 os.remove(dbfile)
3899 dev[0].request("SET pmf 0")
3900
3901 def test_ap_hs20_sim_provisioning(dev, apdev, params):
3902 """Hotspot 2.0 AAA server behavior for SIM provisioning"""
3903 check_eap_capa(dev[0], "SIM")
3904 try:
3905 import sqlite3
3906 except ImportError:
3907 raise HwsimSkip("No sqlite3 module available")
3908 dbfile = os.path.join(params['logdir'], "ap_hs20_sim_provisioning-eap-user.db")
3909 try:
3910 os.remove(dbfile)
3911 except:
3912 pass
3913 con = sqlite3.connect(dbfile)
3914 with con:
3915 cur = con.cursor()
3916 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER, last_msk TEXT)")
3917 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
3918 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('1','SIM')")
3919 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
3920 cur.execute("CREATE TABLE current_sessions(mac_addr TEXT PRIMARY KEY, identity TEXT, start_time TEXT, nas TEXT, hs20_t_c_filtering BOOLEAN, waiting_coa_ack BOOLEAN, coa_ack_received BOOLEAN)")
3921
3922 try:
3923 params = {"ssid": "as", "beacon_int": "2000",
3924 "radius_server_clients": "auth_serv/radius_clients.conf",
3925 "radius_server_auth_port": '18128',
3926 "eap_server": "1",
3927 "eap_user_file": "sqlite:" + dbfile,
3928 "eap_sim_db": "unix:/tmp/hlr_auc_gw.sock",
3929 "ca_cert": "auth_serv/ca.pem",
3930 "server_cert": "auth_serv/server.pem",
3931 "private_key": "auth_serv/server.key",
3932 "hs20_sim_provisioning_url":
3933 "https://example.org/?hotspot2dot0-mobile-identifier-hash=",
3934 "subscr_remediation_method": "1"}
3935 hostapd.add_ap(apdev[1], params)
3936
3937 bssid = apdev[0]['bssid']
3938 params = hs20_ap_params()
3939 params['auth_server_port'] = "18128"
3940 hostapd.add_ap(apdev[0], params)
3941
3942 dev[0].request("SET pmf 1")
3943 dev[0].hs20_enable()
3944 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="SIM",
3945 ieee80211w="1",
3946 identity="1232010000000000",
3947 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
3948 scan_freq="2412", update_identifier="54321")
3949 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=0.5)
3950 if ev is not None:
3951 raise Exception("Unexpected subscription remediation notice")
3952 dev[0].request("REMOVE_NETWORK all")
3953 dev[0].wait_disconnected()
3954 dev[0].dump_monitor()
3955
3956 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="SIM",
3957 ieee80211w="1",
3958 identity="1232010000000000",
3959 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
3960 scan_freq="2412", update_identifier="0")
3961 ev = dev[0].wait_event(["HS20-SUBSCRIPTION-REMEDIATION"], timeout=5)
3962 if ev is None:
3963 raise Exception("Timeout on subscription remediation notice")
3964 if " 1 https://example.org/?hotspot2dot0-mobile-identifier-hash=" not in ev:
3965 raise Exception("Unexpected subscription remediation event contents: " + ev)
3966 id_hash = ev.split(' ')[2].split('=')[1]
3967
3968 with con:
3969 cur = con.cursor()
3970 cur.execute("SELECT * from authlog")
3971 rows = cur.fetchall()
3972 if len(rows) < 1:
3973 raise Exception("No authlog entries")
3974
3975 with con:
3976 cur = con.cursor()
3977 cur.execute("SELECT * from sim_provisioning")
3978 rows = cur.fetchall()
3979 if len(rows) != 1:
3980 raise Exeception("Unexpected number of rows in sim_provisioning (%d; expected %d)" % (len(rows), 1))
3981 logger.info("sim_provisioning: " + str(rows))
3982 if len(rows[0][0]) != 32:
3983 raise Exception("Unexpected mobile_identifier_hash length in DB")
3984 if rows[0][1] != "232010000000000":
3985 raise Exception("Unexpected IMSI in DB")
3986 if rows[0][2] != dev[0].own_addr():
3987 raise Exception("Unexpected MAC address in DB")
3988 if rows[0][0] != id_hash:
3989 raise Exception("hotspot2dot0-mobile-identifier-hash mismatch")
3990 finally:
3991 dev[0].request("SET pmf 0")
3992
3993 def test_ap_hs20_external_selection(dev, apdev):
3994 """Hotspot 2.0 connection using external network selection and creation"""
3995 check_eap_capa(dev[0], "MSCHAPV2")
3996 bssid = apdev[0]['bssid']
3997 params = hs20_ap_params()
3998 params['hessid'] = bssid
3999 params['disable_dgaf'] = '1'
4000 hostapd.add_ap(apdev[0], params)
4001
4002 dev[0].hs20_enable()
4003 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
4004 ieee80211w="1",
4005 identity="hs20-test", password="password",
4006 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
4007 scan_freq="2412", update_identifier="54321",
4008 roaming_consortium_selection="1020304050")
4009 if dev[0].get_status_field("hs20") != "3":
4010 raise Exception("Unexpected hs20 indication")
4011 network_id = dev[0].get_status_field("id")
4012 sel = dev[0].get_network(network_id, "roaming_consortium_selection")
4013 if sel != "1020304050":
4014 raise Exception("Unexpected roaming_consortium_selection value: " + sel)
4015
4016 def test_ap_hs20_random_mac_addr(dev, apdev):
4017 """Hotspot 2.0 connection with random MAC address"""
4018 check_eap_capa(dev[0], "MSCHAPV2")
4019 bssid = apdev[0]['bssid']
4020 params = hs20_ap_params()
4021 params['hessid'] = bssid
4022 params['disable_dgaf'] = '1'
4023 hapd = hostapd.add_ap(apdev[0], params)
4024
4025 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
4026 wpas.interface_add("wlan5")
4027 addr = wpas.p2p_interface_addr()
4028 wpas.request("SET mac_addr 1")
4029 wpas.request("SET preassoc_mac_addr 1")
4030 wpas.request("SET rand_addr_lifetime 60")
4031 wpas.hs20_enable()
4032 wpas.flush_scan_cache()
4033 id = wpas.add_cred_values({'realm': "example.com",
4034 'username': "hs20-test",
4035 'password': "password",
4036 'ca_cert': "auth_serv/ca.pem",
4037 'domain': "example.com",
4038 'update_identifier': "1234"})
4039 interworking_select(wpas, bssid, "home", freq="2412")
4040 interworking_connect(wpas, bssid, "TTLS")
4041 addr1 = wpas.get_driver_status_field("addr")
4042 if addr == addr1:
4043 raise Exception("Did not use random MAC address")
4044
4045 sta = hapd.get_sta(addr)
4046 if sta['addr'] != "FAIL":
4047 raise Exception("Unexpected STA association with permanent address")
4048 sta = hapd.get_sta(addr1)
4049 if sta['addr'] != addr1:
4050 raise Exception("STA association with random address not found")
4051
4052 def test_ap_hs20_multi_network_and_cred_removal(dev, apdev):
4053 """Multiple networks and cred removal"""
4054 check_eap_capa(dev[0], "MSCHAPV2")
4055 bssid = apdev[0]['bssid']
4056 params = hs20_ap_params()
4057 params['nai_realm'] = ["0,example.com,25[3:26]"]
4058 hapd = hostapd.add_ap(apdev[0], params)
4059
4060 dev[0].add_network()
4061 dev[0].hs20_enable()
4062 id = dev[0].add_cred_values({'realm': "example.com",
4063 'username': "user",
4064 'password': "password"})
4065 interworking_select(dev[0], bssid, freq="2412")
4066 interworking_connect(dev[0], bssid, "PEAP")
4067 dev[0].add_network()
4068
4069 dev[0].request("DISCONNECT")
4070 dev[0].wait_disconnected(timeout=10)
4071
4072 hapd.disable()
4073 hapd.set("ssid", "another ssid")
4074 hapd.enable()
4075
4076 interworking_select(dev[0], bssid, freq="2412")
4077 interworking_connect(dev[0], bssid, "PEAP")
4078 dev[0].add_network()
4079 if len(dev[0].list_networks()) != 5:
4080 raise Exception("Unexpected number of networks prior to remove_crec")
4081
4082 dev[0].dump_monitor()
4083 dev[0].remove_cred(id)
4084 if len(dev[0].list_networks()) != 3:
4085 raise Exception("Unexpected number of networks after to remove_crec")
4086 dev[0].wait_disconnected(timeout=10)
4087
4088 def test_ap_hs20_interworking_add_network(dev, apdev):
4089 """Hotspot 2.0 connection using INTERWORKING_ADD_NETWORK"""
4090 check_eap_capa(dev[0], "MSCHAPV2")
4091 bssid = apdev[0]['bssid']
4092 params = hs20_ap_params()
4093 params['nai_realm'] = ["0,example.com,21[3:26][6:7][99:99]"]
4094 hostapd.add_ap(apdev[0], params)
4095
4096 dev[0].hs20_enable()
4097 dev[0].add_cred_values(default_cred(user="user"))
4098 interworking_select(dev[0], bssid, freq=2412)
4099 id = dev[0].interworking_add_network(bssid)
4100 dev[0].select_network(id, freq=2412)
4101 dev[0].wait_connected()
4102
4103 def _test_ap_hs20_proxyarp(dev, apdev):
4104 bssid = apdev[0]['bssid']
4105 params = hs20_ap_params()
4106 params['hessid'] = bssid
4107 params['disable_dgaf'] = '0'
4108 params['proxy_arp'] = '1'
4109 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4110 if "OK" in hapd.request("ENABLE"):
4111 raise Exception("Incomplete hostapd configuration was accepted")
4112 hapd.set("ap_isolate", "1")
4113 if "OK" in hapd.request("ENABLE"):
4114 raise Exception("Incomplete hostapd configuration was accepted")
4115 hapd.set('bridge', 'ap-br0')
4116 hapd.dump_monitor()
4117 try:
4118 hapd.enable()
4119 except:
4120 # For now, do not report failures due to missing kernel support
4121 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4122 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
4123 if ev is None:
4124 raise Exception("AP startup timed out")
4125 if "AP-ENABLED" not in ev:
4126 raise Exception("AP startup failed")
4127
4128 dev[0].hs20_enable()
4129 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4130 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4131
4132 id = dev[0].add_cred_values({'realm': "example.com",
4133 'username': "hs20-test",
4134 'password': "password",
4135 'ca_cert': "auth_serv/ca.pem",
4136 'domain': "example.com",
4137 'update_identifier': "1234"})
4138 interworking_select(dev[0], bssid, "home", freq="2412")
4139 interworking_connect(dev[0], bssid, "TTLS")
4140
4141 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
4142 identity="hs20-test", password="password",
4143 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
4144 scan_freq="2412")
4145 time.sleep(0.1)
4146
4147 addr0 = dev[0].p2p_interface_addr()
4148 addr1 = dev[1].p2p_interface_addr()
4149
4150 src_ll_opt0 = b"\x01\x01" + binascii.unhexlify(addr0.replace(':', ''))
4151 src_ll_opt1 = b"\x01\x01" + binascii.unhexlify(addr1.replace(':', ''))
4152
4153 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
4154 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
4155 opt=src_ll_opt0)
4156 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
4157 raise Exception("DATA_TEST_FRAME failed")
4158
4159 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:dddd::2",
4160 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:dddd::2",
4161 opt=src_ll_opt1)
4162 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
4163 raise Exception("DATA_TEST_FRAME failed")
4164
4165 pkt = build_ns(src_ll=addr1, ip_src="aaaa:bbbb:eeee::2",
4166 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:eeee::2",
4167 opt=src_ll_opt1)
4168 if "OK" not in dev[1].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
4169 raise Exception("DATA_TEST_FRAME failed")
4170
4171 matches = get_permanent_neighbors("ap-br0")
4172 logger.info("After connect: " + str(matches))
4173 if len(matches) != 3:
4174 raise Exception("Unexpected number of neighbor entries after connect")
4175 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4176 raise Exception("dev0 addr missing")
4177 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
4178 raise Exception("dev1 addr(1) missing")
4179 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
4180 raise Exception("dev1 addr(2) missing")
4181 dev[0].request("DISCONNECT")
4182 dev[1].request("DISCONNECT")
4183 time.sleep(0.5)
4184 matches = get_permanent_neighbors("ap-br0")
4185 logger.info("After disconnect: " + str(matches))
4186 if len(matches) > 0:
4187 raise Exception("Unexpected neighbor entries after disconnect")
4188
4189 def test_ap_hs20_hidden_ssid_in_scan_res(dev, apdev):
4190 """Hotspot 2.0 connection with hidden SSId in scan results"""
4191 check_eap_capa(dev[0], "MSCHAPV2")
4192 bssid = apdev[0]['bssid']
4193
4194 hapd = hostapd.add_ap(apdev[0], {"ssid": 'secret',
4195 "ignore_broadcast_ssid": "1"})
4196 dev[0].scan_for_bss(bssid, freq=2412)
4197 hapd.disable()
4198 hapd_global = hostapd.HostapdGlobal(apdev[0])
4199 hapd_global.flush()
4200 hapd_global.remove(apdev[0]['ifname'])
4201
4202 params = hs20_ap_params()
4203 params['hessid'] = bssid
4204 hapd = hostapd.add_ap(apdev[0], params)
4205
4206 dev[0].hs20_enable()
4207 id = dev[0].add_cred_values({'realm': "example.com",
4208 'username': "hs20-test",
4209 'password': "password",
4210 'ca_cert': "auth_serv/ca.pem",
4211 'domain': "example.com"})
4212 interworking_select(dev[0], bssid, "home", freq="2412")
4213 interworking_connect(dev[0], bssid, "TTLS")
4214
4215 # clear BSS table to avoid issues in following test cases
4216 dev[0].request("DISCONNECT")
4217 dev[0].wait_disconnected()
4218 hapd.disable()
4219 dev[0].flush_scan_cache()
4220 dev[0].flush_scan_cache()
4221
4222 def test_ap_hs20_proxyarp(dev, apdev):
4223 """Hotspot 2.0 and ProxyARP"""
4224 check_eap_capa(dev[0], "MSCHAPV2")
4225 try:
4226 _test_ap_hs20_proxyarp(dev, apdev)
4227 finally:
4228 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
4229 stderr=open('/dev/null', 'w'))
4230 subprocess.call(['brctl', 'delbr', 'ap-br0'],
4231 stderr=open('/dev/null', 'w'))
4232
4233 def _test_ap_hs20_proxyarp_dgaf(dev, apdev, disabled):
4234 bssid = apdev[0]['bssid']
4235 params = hs20_ap_params()
4236 params['hessid'] = bssid
4237 params['disable_dgaf'] = '1' if disabled else '0'
4238 params['proxy_arp'] = '1'
4239 params['na_mcast_to_ucast'] = '1'
4240 params['ap_isolate'] = '1'
4241 params['bridge'] = 'ap-br0'
4242 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4243 try:
4244 hapd.enable()
4245 except:
4246 # For now, do not report failures due to missing kernel support
4247 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4248 ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
4249 if ev is None:
4250 raise Exception("AP startup timed out")
4251
4252 dev[0].hs20_enable()
4253 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4254 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4255
4256 id = dev[0].add_cred_values({'realm': "example.com",
4257 'username': "hs20-test",
4258 'password': "password",
4259 'ca_cert': "auth_serv/ca.pem",
4260 'domain': "example.com",
4261 'update_identifier': "1234"})
4262 interworking_select(dev[0], bssid, "home", freq="2412")
4263 interworking_connect(dev[0], bssid, "TTLS")
4264
4265 dev[1].connect("test-hs20", key_mgmt="WPA-EAP", eap="TTLS",
4266 identity="hs20-test", password="password",
4267 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
4268 scan_freq="2412")
4269 time.sleep(0.1)
4270
4271 addr0 = dev[0].p2p_interface_addr()
4272
4273 src_ll_opt0 = b"\x01\x01" + binascii.unhexlify(addr0.replace(':', ''))
4274
4275 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
4276 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
4277 opt=src_ll_opt0)
4278 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
4279 raise Exception("DATA_TEST_FRAME failed")
4280
4281 pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
4282 ip_dst="ff01::1")
4283 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4284 raise Exception("DATA_TEST_FRAME failed")
4285
4286 pkt = build_na(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::44",
4287 ip_dst="ff01::1", target="aaaa:bbbb:cccc::55")
4288 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4289 raise Exception("DATA_TEST_FRAME failed")
4290
4291 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
4292 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4293 yiaddr="192.168.1.123", chaddr=addr0)
4294 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4295 raise Exception("DATA_TEST_FRAME failed")
4296 # another copy for additional code coverage
4297 pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
4298 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4299 yiaddr="192.168.1.123", chaddr=addr0)
4300 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4301 raise Exception("DATA_TEST_FRAME failed")
4302
4303 matches = get_permanent_neighbors("ap-br0")
4304 logger.info("After connect: " + str(matches))
4305 if len(matches) != 2:
4306 raise Exception("Unexpected number of neighbor entries after connect")
4307 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4308 raise Exception("dev0 addr missing")
4309 if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4310 raise Exception("dev0 IPv4 addr missing")
4311 dev[0].request("DISCONNECT")
4312 dev[1].request("DISCONNECT")
4313 time.sleep(0.5)
4314 matches = get_permanent_neighbors("ap-br0")
4315 logger.info("After disconnect: " + str(matches))
4316 if len(matches) > 0:
4317 raise Exception("Unexpected neighbor entries after disconnect")
4318
4319 def test_ap_hs20_proxyarp_disable_dgaf(dev, apdev):
4320 """Hotspot 2.0 and ProxyARP with DGAF disabled"""
4321 check_eap_capa(dev[0], "MSCHAPV2")
4322 try:
4323 _test_ap_hs20_proxyarp_dgaf(dev, apdev, True)
4324 finally:
4325 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
4326 stderr=open('/dev/null', 'w'))
4327 subprocess.call(['brctl', 'delbr', 'ap-br0'],
4328 stderr=open('/dev/null', 'w'))
4329
4330 def test_ap_hs20_proxyarp_enable_dgaf(dev, apdev):
4331 """Hotspot 2.0 and ProxyARP with DGAF enabled"""
4332 check_eap_capa(dev[0], "MSCHAPV2")
4333 try:
4334 _test_ap_hs20_proxyarp_dgaf(dev, apdev, False)
4335 finally:
4336 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
4337 stderr=open('/dev/null', 'w'))
4338 subprocess.call(['brctl', 'delbr', 'ap-br0'],
4339 stderr=open('/dev/null', 'w'))
4340
4341 def ip_checksum(buf):
4342 sum = 0
4343 if len(buf) & 0x01:
4344 buf += b'\x00'
4345 for i in range(0, len(buf), 2):
4346 val, = struct.unpack('H', buf[i:i+2])
4347 sum += val
4348 while (sum >> 16):
4349 sum = (sum & 0xffff) + (sum >> 16)
4350 return struct.pack('H', ~sum & 0xffff)
4351
4352 def ipv6_solicited_node_mcaddr(target):
4353 prefix = socket.inet_pton(socket.AF_INET6, "ff02::1:ff00:0")
4354 mask = socket.inet_pton(socket.AF_INET6, "::ff:ffff")
4355 _target = socket.inet_pton(socket.AF_INET6, target)
4356 p = struct.unpack('4I', prefix)
4357 m = struct.unpack('4I', mask)
4358 t = struct.unpack('4I', _target)
4359 res = (p[0] | (t[0] & m[0]),
4360 p[1] | (t[1] & m[1]),
4361 p[2] | (t[2] & m[2]),
4362 p[3] | (t[3] & m[3]))
4363 return socket.inet_ntop(socket.AF_INET6, struct.pack('4I', *res))
4364
4365 def build_icmpv6(ipv6_addrs, type, code, payload):
4366 start = struct.pack("BB", type, code)
4367 end = payload
4368 icmp = start + b'\x00\x00' + end
4369 pseudo = ipv6_addrs + struct.pack(">LBBBB", len(icmp), 0, 0, 0, 58)
4370 csum = ip_checksum(pseudo + icmp)
4371 return start + csum + end
4372
4373 def build_ra(src_ll, ip_src, ip_dst, cur_hop_limit=0, router_lifetime=0,
4374 reachable_time=0, retrans_timer=0, opt=None):
4375 link_mc = binascii.unhexlify("3333ff000002")
4376 _src_ll = binascii.unhexlify(src_ll.replace(':', ''))
4377 proto = b'\x86\xdd'
4378 ehdr = link_mc + _src_ll + proto
4379 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
4380 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
4381
4382 adv = struct.pack('>BBHLL', cur_hop_limit, 0, router_lifetime,
4383 reachable_time, retrans_timer)
4384 if opt:
4385 payload = adv + opt
4386 else:
4387 payload = adv
4388 icmp = build_icmpv6(_ip_src + _ip_dst, 134, 0, payload)
4389
4390 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
4391 ipv6 += _ip_src + _ip_dst
4392
4393 return ehdr + ipv6 + icmp
4394
4395 def build_ns(src_ll, ip_src, ip_dst, target, opt=None):
4396 link_mc = binascii.unhexlify("3333ff000002")
4397 _src_ll = binascii.unhexlify(src_ll.replace(':', ''))
4398 proto = b'\x86\xdd'
4399 ehdr = link_mc + _src_ll + proto
4400 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
4401 if ip_dst is None:
4402 ip_dst = ipv6_solicited_node_mcaddr(target)
4403 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
4404
4405 reserved = b'\x00\x00\x00\x00'
4406 _target = socket.inet_pton(socket.AF_INET6, target)
4407 if opt:
4408 payload = reserved + _target + opt
4409 else:
4410 payload = reserved + _target
4411 icmp = build_icmpv6(_ip_src + _ip_dst, 135, 0, payload)
4412
4413 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
4414 ipv6 += _ip_src + _ip_dst
4415
4416 return ehdr + ipv6 + icmp
4417
4418 def send_ns(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
4419 hapd_bssid=None):
4420 if hapd_bssid:
4421 if src_ll is None:
4422 src_ll = hapd_bssid
4423 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
4424 else:
4425 if src_ll is None:
4426 src_ll = dev.p2p_interface_addr()
4427 cmd = "DATA_TEST_FRAME "
4428
4429 if opt is None:
4430 opt = b"\x01\x01" + binascii.unhexlify(src_ll.replace(':', ''))
4431
4432 pkt = build_ns(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
4433 opt=opt)
4434 if "OK" not in dev.request(cmd + binascii.hexlify(pkt).decode()):
4435 raise Exception("DATA_TEST_FRAME failed")
4436
4437 def build_na(src_ll, ip_src, ip_dst, target, opt=None, flags=0):
4438 link_mc = binascii.unhexlify("3333ff000002")
4439 _src_ll = binascii.unhexlify(src_ll.replace(':', ''))
4440 proto = b'\x86\xdd'
4441 ehdr = link_mc + _src_ll + proto
4442 _ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
4443 _ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
4444
4445 _target = socket.inet_pton(socket.AF_INET6, target)
4446 if opt:
4447 payload = struct.pack('>Bxxx', flags) + _target + opt
4448 else:
4449 payload = struct.pack('>Bxxx', flags) + _target
4450 icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
4451
4452 ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
4453 ipv6 += _ip_src + _ip_dst
4454
4455 return ehdr + ipv6 + icmp
4456
4457 def send_na(dev, src_ll=None, target=None, ip_src=None, ip_dst=None, opt=None,
4458 hapd_bssid=None):
4459 if hapd_bssid:
4460 if src_ll is None:
4461 src_ll = hapd_bssid
4462 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
4463 else:
4464 if src_ll is None:
4465 src_ll = dev.p2p_interface_addr()
4466 cmd = "DATA_TEST_FRAME "
4467
4468 pkt = build_na(src_ll=src_ll, ip_src=ip_src, ip_dst=ip_dst, target=target,
4469 opt=opt)
4470 if "OK" not in dev.request(cmd + binascii.hexlify(pkt).decode()):
4471 raise Exception("DATA_TEST_FRAME failed")
4472
4473 def build_dhcp_ack(dst_ll, src_ll, ip_src, ip_dst, yiaddr, chaddr,
4474 subnet_mask="255.255.255.0", truncated_opt=False,
4475 wrong_magic=False, force_tot_len=None, no_dhcp=False,
4476 udp_checksum=True):
4477 _dst_ll = binascii.unhexlify(dst_ll.replace(':', ''))
4478 _src_ll = binascii.unhexlify(src_ll.replace(':', ''))
4479 proto = b'\x08\x00'
4480 ehdr = _dst_ll + _src_ll + proto
4481 _ip_src = socket.inet_pton(socket.AF_INET, ip_src)
4482 _ip_dst = socket.inet_pton(socket.AF_INET, ip_dst)
4483 _subnet_mask = socket.inet_pton(socket.AF_INET, subnet_mask)
4484
4485 _ciaddr = b'\x00\x00\x00\x00'
4486 _yiaddr = socket.inet_pton(socket.AF_INET, yiaddr)
4487 _siaddr = b'\x00\x00\x00\x00'
4488 _giaddr = b'\x00\x00\x00\x00'
4489 _chaddr = binascii.unhexlify(chaddr.replace(':', '') + "00000000000000000000")
4490 payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
4491 payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*b'\x00'
4492 # magic
4493 if wrong_magic:
4494 payload += b'\x63\x82\x53\x00'
4495 else:
4496 payload += b'\x63\x82\x53\x63'
4497 if truncated_opt:
4498 payload += b'\x22\xff\x00'
4499 # Option: DHCP Message Type = ACK
4500 payload += b'\x35\x01\x05'
4501 # Pad Option
4502 payload += b'\x00'
4503 # Option: Subnet Mask
4504 payload += b'\x01\x04' + _subnet_mask
4505 # Option: Time Offset
4506 payload += struct.pack('>BBL', 2, 4, 0)
4507 # End Option
4508 payload += b'\xff'
4509 # Pad Option
4510 payload += b'\x00\x00\x00\x00'
4511
4512 if no_dhcp:
4513 payload = struct.pack('>BBBBL3BB', 2, 1, 6, 0, 12345, 0, 0, 0, 0)
4514 payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + 192*b'\x00'
4515
4516 if udp_checksum:
4517 pseudohdr = _ip_src + _ip_dst + struct.pack('>BBH', 0, 17,
4518 8 + len(payload))
4519 udphdr = struct.pack('>HHHH', 67, 68, 8 + len(payload), 0)
4520 checksum, = struct.unpack('>H', ip_checksum(pseudohdr + udphdr + payload))
4521 else:
4522 checksum = 0
4523 udp = struct.pack('>HHHH', 67, 68, 8 + len(payload), checksum) + payload
4524
4525 if force_tot_len:
4526 tot_len = force_tot_len
4527 else:
4528 tot_len = 20 + len(udp)
4529 start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
4530 ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
4531 csum = ip_checksum(ipv4)
4532 ipv4 = start + csum + _ip_src + _ip_dst
4533
4534 return ehdr + ipv4 + udp
4535
4536 def build_arp(dst_ll, src_ll, opcode, sender_mac, sender_ip,
4537 target_mac, target_ip):
4538 _dst_ll = binascii.unhexlify(dst_ll.replace(':', ''))
4539 _src_ll = binascii.unhexlify(src_ll.replace(':', ''))
4540 proto = b'\x08\x06'
4541 ehdr = _dst_ll + _src_ll + proto
4542
4543 _sender_mac = binascii.unhexlify(sender_mac.replace(':', ''))
4544 _sender_ip = socket.inet_pton(socket.AF_INET, sender_ip)
4545 _target_mac = binascii.unhexlify(target_mac.replace(':', ''))
4546 _target_ip = socket.inet_pton(socket.AF_INET, target_ip)
4547
4548 arp = struct.pack('>HHBBH', 1, 0x0800, 6, 4, opcode)
4549 arp += _sender_mac + _sender_ip
4550 arp += _target_mac + _target_ip
4551
4552 return ehdr + arp
4553
4554 def send_arp(dev, dst_ll="ff:ff:ff:ff:ff:ff", src_ll=None, opcode=1,
4555 sender_mac=None, sender_ip="0.0.0.0",
4556 target_mac="00:00:00:00:00:00", target_ip="0.0.0.0",
4557 hapd_bssid=None):
4558 if hapd_bssid:
4559 if src_ll is None:
4560 src_ll = hapd_bssid
4561 if sender_mac is None:
4562 sender_mac = hapd_bssid
4563 cmd = "DATA_TEST_FRAME ifname=ap-br0 "
4564 else:
4565 if src_ll is None:
4566 src_ll = dev.p2p_interface_addr()
4567 if sender_mac is None:
4568 sender_mac = dev.p2p_interface_addr()
4569 cmd = "DATA_TEST_FRAME "
4570
4571 pkt = build_arp(dst_ll=dst_ll, src_ll=src_ll, opcode=opcode,
4572 sender_mac=sender_mac, sender_ip=sender_ip,
4573 target_mac=target_mac, target_ip=target_ip)
4574 if "OK" not in dev.request(cmd + binascii.hexlify(pkt).decode()):
4575 raise Exception("DATA_TEST_FRAME failed")
4576
4577 def get_permanent_neighbors(ifname):
4578 cmd = subprocess.Popen(['ip', 'nei'], stdout=subprocess.PIPE)
4579 res = cmd.stdout.read().decode()
4580 cmd.stdout.close()
4581 return [line for line in res.splitlines() if "PERMANENT" in line and ifname in line]
4582
4583 def get_bridge_macs(ifname):
4584 cmd = subprocess.Popen(['brctl', 'showmacs', ifname],
4585 stdout=subprocess.PIPE)
4586 res = cmd.stdout.read()
4587 cmd.stdout.close()
4588 return res.decode()
4589
4590 def tshark_get_arp(cap, filter):
4591 res = run_tshark(cap, filter,
4592 ["eth.dst", "eth.src",
4593 "arp.src.hw_mac", "arp.src.proto_ipv4",
4594 "arp.dst.hw_mac", "arp.dst.proto_ipv4"],
4595 wait=False)
4596 frames = []
4597 for l in res.splitlines():
4598 frames.append(l.split('\t'))
4599 return frames
4600
4601 def tshark_get_ns(cap):
4602 res = run_tshark(cap, "icmpv6.type == 135",
4603 ["eth.dst", "eth.src",
4604 "ipv6.src", "ipv6.dst",
4605 "icmpv6.nd.ns.target_address",
4606 "icmpv6.opt.linkaddr"],
4607 wait=False)
4608 frames = []
4609 for l in res.splitlines():
4610 frames.append(l.split('\t'))
4611 return frames
4612
4613 def tshark_get_na(cap):
4614 res = run_tshark(cap, "icmpv6.type == 136",
4615 ["eth.dst", "eth.src",
4616 "ipv6.src", "ipv6.dst",
4617 "icmpv6.nd.na.target_address",
4618 "icmpv6.opt.linkaddr"],
4619 wait=False)
4620 frames = []
4621 for l in res.splitlines():
4622 frames.append(l.split('\t'))
4623 return frames
4624
4625 def _test_proxyarp_open(dev, apdev, params, ebtables=False):
4626 prefix = "proxyarp_open"
4627 if ebtables:
4628 prefix += "_ebtables"
4629 cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap")
4630 cap_dev0 = os.path.join(params['logdir'],
4631 prefix + ".%s.pcap" % dev[0].ifname)
4632 cap_dev1 = os.path.join(params['logdir'],
4633 prefix + ".%s.pcap" % dev[1].ifname)
4634 cap_dev2 = os.path.join(params['logdir'],
4635 prefix + ".%s.pcap" % dev[2].ifname)
4636
4637 bssid = apdev[0]['bssid']
4638 params = {'ssid': 'open'}
4639 params['proxy_arp'] = '1'
4640 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4641 hapd.set("ap_isolate", "1")
4642 hapd.set('bridge', 'ap-br0')
4643 hapd.dump_monitor()
4644 try:
4645 hapd.enable()
4646 except:
4647 # For now, do not report failures due to missing kernel support
4648 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4649 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
4650 if ev is None:
4651 raise Exception("AP startup timed out")
4652 if "AP-ENABLED" not in ev:
4653 raise Exception("AP startup failed")
4654
4655 params2 = {'ssid': 'another'}
4656 hapd2 = hostapd.add_ap(apdev[1], params2, no_enable=True)
4657 hapd2.set('bridge', 'ap-br0')
4658 hapd2.enable()
4659
4660 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4661 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4662
4663 if ebtables:
4664 for chain in ['FORWARD', 'OUTPUT']:
4665 try:
4666 subprocess.call(['ebtables', '-A', chain, '-p', 'ARP',
4667 '-d', 'Broadcast', '-o', apdev[0]['ifname'],
4668 '-j', 'DROP'])
4669 except:
4670 raise HwsimSkip("No ebtables available")
4671
4672 time.sleep(0.5)
4673 cmd = {}
4674 cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
4675 '-w', cap_br, '-s', '2000'],
4676 stderr=open('/dev/null', 'w'))
4677 cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
4678 '-w', cap_dev0, '-s', '2000'],
4679 stderr=open('/dev/null', 'w'))
4680 cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
4681 '-w', cap_dev1, '-s', '2000'],
4682 stderr=open('/dev/null', 'w'))
4683 cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[2].ifname,
4684 '-w', cap_dev2, '-s', '2000'],
4685 stderr=open('/dev/null', 'w'))
4686
4687 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
4688 dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
4689 dev[2].connect("another", key_mgmt="NONE", scan_freq="2412")
4690 time.sleep(1.1)
4691
4692 brcmd = subprocess.Popen(['brctl', 'show'], stdout=subprocess.PIPE)
4693 res = brcmd.stdout.read().decode()
4694 brcmd.stdout.close()
4695 logger.info("Bridge setup: " + res)
4696
4697 brcmd = subprocess.Popen(['brctl', 'showstp', 'ap-br0'],
4698 stdout=subprocess.PIPE)
4699 res = brcmd.stdout.read().decode()
4700 brcmd.stdout.close()
4701 logger.info("Bridge showstp: " + res)
4702
4703 addr0 = dev[0].p2p_interface_addr()
4704 addr1 = dev[1].p2p_interface_addr()
4705 addr2 = dev[2].p2p_interface_addr()
4706
4707 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
4708 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4709 yiaddr="192.168.1.124", chaddr=addr0)
4710 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4711 raise Exception("DATA_TEST_FRAME failed")
4712 # Change address and verify unicast
4713 pkt = build_dhcp_ack(dst_ll=addr0, src_ll=bssid,
4714 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4715 yiaddr="192.168.1.123", chaddr=addr0,
4716 udp_checksum=False)
4717 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4718 raise Exception("DATA_TEST_FRAME failed")
4719
4720 # Not-associated client MAC address
4721 pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
4722 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4723 yiaddr="192.168.1.125", chaddr="22:33:44:55:66:77")
4724 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4725 raise Exception("DATA_TEST_FRAME failed")
4726
4727 # No IP address
4728 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4729 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4730 yiaddr="0.0.0.0", chaddr=addr1)
4731 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4732 raise Exception("DATA_TEST_FRAME failed")
4733
4734 # Zero subnet mask
4735 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4736 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4737 yiaddr="192.168.1.126", chaddr=addr1,
4738 subnet_mask="0.0.0.0")
4739 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4740 raise Exception("DATA_TEST_FRAME failed")
4741
4742 # Truncated option
4743 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4744 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4745 yiaddr="192.168.1.127", chaddr=addr1,
4746 truncated_opt=True)
4747 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4748 raise Exception("DATA_TEST_FRAME failed")
4749
4750 # Wrong magic
4751 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4752 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4753 yiaddr="192.168.1.128", chaddr=addr1,
4754 wrong_magic=True)
4755 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4756 raise Exception("DATA_TEST_FRAME failed")
4757
4758 # Wrong IPv4 total length
4759 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4760 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4761 yiaddr="192.168.1.129", chaddr=addr1,
4762 force_tot_len=1000)
4763 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4764 raise Exception("DATA_TEST_FRAME failed")
4765
4766 # BOOTP
4767 pkt = build_dhcp_ack(dst_ll=addr1, src_ll=bssid,
4768 ip_src="192.168.1.1", ip_dst="255.255.255.255",
4769 yiaddr="192.168.1.129", chaddr=addr1,
4770 no_dhcp=True)
4771 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
4772 raise Exception("DATA_TEST_FRAME failed")
4773
4774 macs = get_bridge_macs("ap-br0")
4775 logger.info("After connect (showmacs): " + str(macs))
4776
4777 matches = get_permanent_neighbors("ap-br0")
4778 logger.info("After connect: " + str(matches))
4779 if len(matches) != 1:
4780 raise Exception("Unexpected number of neighbor entries after connect")
4781 if '192.168.1.123 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
4782 raise Exception("dev0 IPv4 addr missing")
4783
4784 targets = ["192.168.1.123", "192.168.1.124", "192.168.1.125",
4785 "192.168.1.126"]
4786 for target in targets:
4787 send_arp(dev[1], sender_ip="192.168.1.100", target_ip=target)
4788
4789 for target in targets:
4790 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.101",
4791 target_ip=target)
4792
4793 for target in targets:
4794 send_arp(dev[2], sender_ip="192.168.1.103", target_ip=target)
4795
4796 # ARP Probe from wireless STA
4797 send_arp(dev[1], target_ip="192.168.1.127")
4798 # ARP Announcement from wireless STA
4799 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127")
4800 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.127",
4801 opcode=2)
4802
4803 macs = get_bridge_macs("ap-br0")
4804 logger.info("After ARP Probe + Announcement (showmacs): " + str(macs))
4805
4806 matches = get_permanent_neighbors("ap-br0")
4807 logger.info("After ARP Probe + Announcement: " + str(matches))
4808
4809 # ARP Request for the newly introduced IP address from wireless STA
4810 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
4811
4812 # ARP Request for the newly introduced IP address from bridge
4813 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
4814 target_ip="192.168.1.127")
4815 send_arp(dev[2], sender_ip="192.168.1.103", target_ip="192.168.1.127")
4816
4817 # ARP Probe from bridge
4818 send_arp(hapd, hapd_bssid=bssid, target_ip="192.168.1.130")
4819 send_arp(dev[2], target_ip="192.168.1.131")
4820 # ARP Announcement from bridge (not to be learned by AP for proxyarp)
4821 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
4822 target_ip="192.168.1.130")
4823 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.130",
4824 target_ip="192.168.1.130", opcode=2)
4825 send_arp(dev[2], sender_ip="192.168.1.131", target_ip="192.168.1.131")
4826 send_arp(dev[2], sender_ip="192.168.1.131", target_ip="192.168.1.131",
4827 opcode=2)
4828
4829 macs = get_bridge_macs("ap-br0")
4830 logger.info("After ARP Probe + Announcement (showmacs): " + str(macs))
4831
4832 matches = get_permanent_neighbors("ap-br0")
4833 logger.info("After ARP Probe + Announcement: " + str(matches))
4834
4835 # ARP Request for the newly introduced IP address from wireless STA
4836 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.130")
4837 # ARP Response from bridge (AP does not proxy for non-wireless devices)
4838 send_arp(hapd, hapd_bssid=bssid, dst_ll=addr0, sender_ip="192.168.1.130",
4839 target_ip="192.168.1.123", opcode=2)
4840
4841 # ARP Request for the newly introduced IP address from wireless STA
4842 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.131")
4843 # ARP Response from bridge (AP does not proxy for non-wireless devices)
4844 send_arp(dev[2], dst_ll=addr0, sender_ip="192.168.1.131",
4845 target_ip="192.168.1.123", opcode=2)
4846
4847 # ARP Request for the newly introduced IP address from bridge
4848 send_arp(hapd, hapd_bssid=bssid, sender_ip="192.168.1.102",
4849 target_ip="192.168.1.130")
4850 send_arp(dev[2], sender_ip="192.168.1.104", target_ip="192.168.1.131")
4851
4852 # ARP Probe from wireless STA (duplicate address; learned through DHCP)
4853 send_arp(dev[1], target_ip="192.168.1.123")
4854 # ARP Probe from wireless STA (duplicate address; learned through ARP)
4855 send_arp(dev[0], target_ip="192.168.1.127")
4856
4857 # Gratuitous ARP Reply for another STA's IP address
4858 send_arp(dev[0], opcode=2, sender_mac=addr0, sender_ip="192.168.1.127",
4859 target_mac=addr1, target_ip="192.168.1.127")
4860 send_arp(dev[1], opcode=2, sender_mac=addr1, sender_ip="192.168.1.123",
4861 target_mac=addr0, target_ip="192.168.1.123")
4862 # ARP Request to verify previous mapping
4863 send_arp(dev[1], sender_ip="192.168.1.127", target_ip="192.168.1.123")
4864 send_arp(dev[0], sender_ip="192.168.1.123", target_ip="192.168.1.127")
4865
4866 try:
4867 hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
4868 except Exception as e:
4869 logger.info("test_connectibity_iface failed: " + str(e))
4870 raise HwsimSkip("Assume kernel did not have the required patches for proxyarp")
4871 hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
4872 hwsim_utils.test_connectivity(dev[0], dev[1])
4873
4874 dev[0].request("DISCONNECT")
4875 dev[1].request("DISCONNECT")
4876 time.sleep(1.5)
4877 for i in range(len(cmd)):
4878 cmd[i].terminate()
4879 time.sleep(0.1)
4880 macs = get_bridge_macs("ap-br0")
4881 logger.info("After disconnect (showmacs): " + str(macs))
4882 matches = get_permanent_neighbors("ap-br0")
4883 logger.info("After disconnect: " + str(matches))
4884 if len(matches) > 0:
4885 raise Exception("Unexpected neighbor entries after disconnect")
4886 if ebtables:
4887 cmd = subprocess.Popen(['ebtables', '-L', '--Lc'],
4888 stdout=subprocess.PIPE)
4889 res = cmd.stdout.read().decode()
4890 cmd.stdout.close()
4891 logger.info("ebtables results:\n" + res)
4892
4893 # Verify that expected ARP messages were seen and no unexpected
4894 # ARP messages were seen.
4895
4896 arp_req = tshark_get_arp(cap_dev0, "arp.opcode == 1")
4897 arp_reply = tshark_get_arp(cap_dev0, "arp.opcode == 2")
4898 logger.info("dev0 seen ARP requests:\n" + str(arp_req))
4899 logger.info("dev0 seen ARP replies:\n" + str(arp_reply))
4900
4901 if ['ff:ff:ff:ff:ff:ff', addr1,
4902 addr1, '192.168.1.100',
4903 '00:00:00:00:00:00', '192.168.1.123'] in arp_req:
4904 raise Exception("dev0 saw ARP request from dev1")
4905 if ['ff:ff:ff:ff:ff:ff', addr2,
4906 addr2, '192.168.1.103',
4907 '00:00:00:00:00:00', '192.168.1.123'] in arp_req:
4908 raise Exception("dev0 saw ARP request from dev2")
4909 # TODO: Uncomment once fixed in kernel
4910 #if ['ff:ff:ff:ff:ff:ff', bssid,
4911 # bssid, '192.168.1.101',
4912 # '00:00:00:00:00:00', '192.168.1.123'] in arp_req:
4913 # raise Exception("dev0 saw ARP request from br")
4914
4915 if ebtables:
4916 for req in arp_req:
4917 if req[1] != addr0:
4918 raise Exception("Unexpected foreign ARP request on dev0")
4919
4920 arp_req = tshark_get_arp(cap_dev1, "arp.opcode == 1")
4921 arp_reply = tshark_get_arp(cap_dev1, "arp.opcode == 2")
4922 logger.info("dev1 seen ARP requests:\n" + str(arp_req))
4923 logger.info("dev1 seen ARP replies:\n" + str(arp_reply))
4924
4925 if ['ff:ff:ff:ff:ff:ff', addr2,
4926 addr2, '192.168.1.103',
4927 '00:00:00:00:00:00', '192.168.1.123'] in arp_req:
4928 raise Exception("dev1 saw ARP request from dev2")
4929 if [addr1, addr0, addr0, '192.168.1.123', addr1, '192.168.1.100'] not in arp_reply:
4930 raise Exception("dev1 did not get ARP response for 192.168.1.123")
4931
4932 if ebtables:
4933 for req in arp_req:
4934 if req[1] != addr1:
4935 raise Exception("Unexpected foreign ARP request on dev1")
4936
4937 arp_req = tshark_get_arp(cap_dev2, "arp.opcode == 1")
4938 arp_reply = tshark_get_arp(cap_dev2, "arp.opcode == 2")
4939 logger.info("dev2 seen ARP requests:\n" + str(arp_req))
4940 logger.info("dev2 seen ARP replies:\n" + str(arp_reply))
4941
4942 if [addr2, addr0,
4943 addr0, '192.168.1.123',
4944 addr2, '192.168.1.103'] not in arp_reply:
4945 raise Exception("dev2 did not get ARP response for 192.168.1.123")
4946
4947 arp_req = tshark_get_arp(cap_br, "arp.opcode == 1")
4948 arp_reply = tshark_get_arp(cap_br, "arp.opcode == 2")
4949 logger.info("br seen ARP requests:\n" + str(arp_req))
4950 logger.info("br seen ARP replies:\n" + str(arp_reply))
4951
4952 # TODO: Uncomment once fixed in kernel
4953 #if [bssid, addr0,
4954 # addr0, '192.168.1.123',
4955 # bssid, '192.168.1.101'] not in arp_reply:
4956 # raise Exception("br did not get ARP response for 192.168.1.123")
4957
4958 def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False):
4959 prefix = "proxyarp_open"
4960 if ebtables:
4961 prefix += "_ebtables"
4962 prefix += "_ipv6"
4963 cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap")
4964 cap_dev0 = os.path.join(params['logdir'],
4965 prefix + ".%s.pcap" % dev[0].ifname)
4966 cap_dev1 = os.path.join(params['logdir'],
4967 prefix + ".%s.pcap" % dev[1].ifname)
4968 cap_dev2 = os.path.join(params['logdir'],
4969 prefix + ".%s.pcap" % dev[2].ifname)
4970
4971 bssid = apdev[0]['bssid']
4972 params = {'ssid': 'open'}
4973 params['proxy_arp'] = '1'
4974 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
4975 hapd.set("ap_isolate", "1")
4976 hapd.set('bridge', 'ap-br0')
4977 hapd.dump_monitor()
4978 try:
4979 hapd.enable()
4980 except:
4981 # For now, do not report failures due to missing kernel support
4982 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
4983 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
4984 if ev is None:
4985 raise Exception("AP startup timed out")
4986 if "AP-ENABLED" not in ev:
4987 raise Exception("AP startup failed")
4988
4989 params2 = {'ssid': 'another'}
4990 hapd2 = hostapd.add_ap(apdev[1], params2, no_enable=True)
4991 hapd2.set('bridge', 'ap-br0')
4992 hapd2.enable()
4993
4994 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
4995 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
4996
4997 if ebtables:
4998 for chain in ['FORWARD', 'OUTPUT']:
4999 try:
5000 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
5001 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
5002 '--ip6-icmp-type', 'neighbor-solicitation',
5003 '-o', apdev[0]['ifname'], '-j', 'DROP'])
5004 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
5005 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
5006 '--ip6-icmp-type', 'neighbor-advertisement',
5007 '-o', apdev[0]['ifname'], '-j', 'DROP'])
5008 subprocess.call(['ebtables', '-A', chain,
5009 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
5010 '--ip6-icmp-type', 'router-solicitation',
5011 '-o', apdev[0]['ifname'], '-j', 'DROP'])
5012 # Multicast Listener Report Message
5013 subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast',
5014 '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp',
5015 '--ip6-icmp-type', '143',
5016 '-o', apdev[0]['ifname'], '-j', 'DROP'])
5017 except:
5018 raise HwsimSkip("No ebtables available")
5019
5020 time.sleep(0.5)
5021 cmd = {}
5022 cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'ap-br0',
5023 '-w', cap_br, '-s', '2000'],
5024 stderr=open('/dev/null', 'w'))
5025 cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[0].ifname,
5026 '-w', cap_dev0, '-s', '2000'],
5027 stderr=open('/dev/null', 'w'))
5028 cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[1].ifname,
5029 '-w', cap_dev1, '-s', '2000'],
5030 stderr=open('/dev/null', 'w'))
5031 cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', dev[2].ifname,
5032 '-w', cap_dev2, '-s', '2000'],
5033 stderr=open('/dev/null', 'w'))
5034
5035 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
5036 dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
5037 dev[2].connect("another", key_mgmt="NONE", scan_freq="2412")
5038 time.sleep(0.1)
5039
5040 brcmd = subprocess.Popen(['brctl', 'show'], stdout=subprocess.PIPE)
5041 res = brcmd.stdout.read().decode()
5042 brcmd.stdout.close()
5043 logger.info("Bridge setup: " + res)
5044
5045 brcmd = subprocess.Popen(['brctl', 'showstp', 'ap-br0'],
5046 stdout=subprocess.PIPE)
5047 res = brcmd.stdout.read().decode()
5048 brcmd.stdout.close()
5049 logger.info("Bridge showstp: " + res)
5050
5051 addr0 = dev[0].p2p_interface_addr()
5052 addr1 = dev[1].p2p_interface_addr()
5053 addr2 = dev[2].p2p_interface_addr()
5054
5055 src_ll_opt0 = b"\x01\x01" + binascii.unhexlify(addr0.replace(':', ''))
5056 src_ll_opt1 = b"\x01\x01" + binascii.unhexlify(addr1.replace(':', ''))
5057
5058 # DAD NS
5059 send_ns(dev[0], ip_src="::", target="aaaa:bbbb:cccc::2")
5060
5061 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2")
5062 # test frame without source link-layer address option
5063 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5064 opt='')
5065 # test frame with bogus option
5066 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5067 opt=b"\x70\x01\x01\x02\x03\x04\x05\x05")
5068 # test frame with truncated source link-layer address option
5069 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5070 opt=b"\x01\x01\x01\x02\x03\x04")
5071 # test frame with foreign source link-layer address option
5072 send_ns(dev[0], ip_src="aaaa:bbbb:cccc::2", target="aaaa:bbbb:cccc::2",
5073 opt=b"\x01\x01\x01\x02\x03\x04\x05\x06")
5074
5075 send_ns(dev[1], ip_src="aaaa:bbbb:dddd::2", target="aaaa:bbbb:dddd::2")
5076
5077 send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
5078 # another copy for additional code coverage
5079 send_ns(dev[1], ip_src="aaaa:bbbb:eeee::2", target="aaaa:bbbb:eeee::2")
5080
5081 macs = get_bridge_macs("ap-br0")
5082 logger.info("After connect (showmacs): " + str(macs))
5083
5084 matches = get_permanent_neighbors("ap-br0")
5085 logger.info("After connect: " + str(matches))
5086 if len(matches) != 3:
5087 raise Exception("Unexpected number of neighbor entries after connect")
5088 if 'aaaa:bbbb:cccc::2 dev ap-br0 lladdr 02:00:00:00:00:00 PERMANENT' not in matches:
5089 raise Exception("dev0 addr missing")
5090 if 'aaaa:bbbb:dddd::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
5091 raise Exception("dev1 addr(1) missing")
5092 if 'aaaa:bbbb:eeee::2 dev ap-br0 lladdr 02:00:00:00:01:00 PERMANENT' not in matches:
5093 raise Exception("dev1 addr(2) missing")
5094
5095 send_ns(dev[0], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:cccc::2")
5096 time.sleep(0.1)
5097 send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:dddd::2")
5098 time.sleep(0.1)
5099 send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:dddd::2",
5100 ip_src="aaaa:bbbb:ffff::2")
5101 time.sleep(0.1)
5102 send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="aaaa:bbbb:ff00::2")
5103 time.sleep(0.1)
5104 send_ns(dev[2], target="aaaa:bbbb:dddd::2", ip_src="aaaa:bbbb:ff00::2")
5105 time.sleep(0.1)
5106 send_ns(dev[2], target="aaaa:bbbb:eeee::2", ip_src="aaaa:bbbb:ff00::2")
5107 time.sleep(0.1)
5108
5109 # Try to probe for an already assigned address
5110 send_ns(dev[1], target="aaaa:bbbb:cccc::2", ip_src="::")
5111 time.sleep(0.1)
5112 send_ns(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc::2", ip_src="::")
5113 time.sleep(0.1)
5114 send_ns(dev[2], target="aaaa:bbbb:cccc::2", ip_src="::")
5115 time.sleep(0.1)
5116
5117 # Unsolicited NA
5118 send_na(dev[1], target="aaaa:bbbb:cccc:aeae::3",
5119 ip_src="aaaa:bbbb:cccc:aeae::3", ip_dst="ff02::1")
5120 send_na(hapd, hapd_bssid=bssid, target="aaaa:bbbb:cccc:aeae::4",
5121 ip_src="aaaa:bbbb:cccc:aeae::4", ip_dst="ff02::1")
5122 send_na(dev[2], target="aaaa:bbbb:cccc:aeae::5",
5123 ip_src="aaaa:bbbb:cccc:aeae::5", ip_dst="ff02::1")
5124
5125 try:
5126 hwsim_utils.test_connectivity_iface(dev[0], hapd, "ap-br0")
5127 except Exception as e:
5128 logger.info("test_connectibity_iface failed: " + str(e))
5129 raise HwsimSkip("Assume kernel did not have the required patches for proxyarp")
5130 hwsim_utils.test_connectivity_iface(dev[1], hapd, "ap-br0")
5131 hwsim_utils.test_connectivity(dev[0], dev[1])
5132
5133 dev[0].request("DISCONNECT")
5134 dev[1].request("DISCONNECT")
5135 time.sleep(0.5)
5136 for i in range(len(cmd)):
5137 cmd[i].terminate()
5138 macs = get_bridge_macs("ap-br0")
5139 logger.info("After disconnect (showmacs): " + str(macs))
5140 matches = get_permanent_neighbors("ap-br0")
5141 logger.info("After disconnect: " + str(matches))
5142 if len(matches) > 0:
5143 raise Exception("Unexpected neighbor entries after disconnect")
5144 if ebtables:
5145 cmd = subprocess.Popen(['ebtables', '-L', '--Lc'],
5146 stdout=subprocess.PIPE)
5147 res = cmd.stdout.read().decode()
5148 cmd.stdout.close()
5149 logger.info("ebtables results:\n" + res)
5150
5151 ns = tshark_get_ns(cap_dev0)
5152 logger.info("dev0 seen NS: " + str(ns))
5153 na = tshark_get_na(cap_dev0)
5154 logger.info("dev0 seen NA: " + str(na))
5155
5156 if [addr0, addr1, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:cccc::2',
5157 'aaaa:bbbb:dddd::2', addr1] not in na:
5158 # For now, skip the test instead of reporting the error since the IPv6
5159 # proxyarp support is not yet in the upstream kernel tree.
5160 #raise Exception("dev0 did not get NA for aaaa:bbbb:dddd::2")
5161 raise HwsimSkip("Assume kernel did not have the required patches for proxyarp (IPv6)")
5162
5163 if ebtables:
5164 for req in ns:
5165 if req[1] != addr0:
5166 raise Exception("Unexpected foreign NS on dev0: " + str(req))
5167
5168 ns = tshark_get_ns(cap_dev1)
5169 logger.info("dev1 seen NS: " + str(ns))
5170 na = tshark_get_na(cap_dev1)
5171 logger.info("dev1 seen NA: " + str(na))
5172
5173 if [addr1, addr0, 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:dddd::2',
5174 'aaaa:bbbb:cccc::2', addr0] not in na:
5175 raise Exception("dev1 did not get NA for aaaa:bbbb:cccc::2")
5176
5177 if ebtables:
5178 for req in ns:
5179 if req[1] != addr1:
5180 raise Exception("Unexpected foreign NS on dev1: " + str(req))
5181
5182 ns = tshark_get_ns(cap_dev2)
5183 logger.info("dev2 seen NS: " + str(ns))
5184 na = tshark_get_na(cap_dev2)
5185 logger.info("dev2 seen NA: " + str(na))
5186
5187 # FIX: enable once kernel implementation for proxyarp IPv6 is fixed
5188 #if [addr2, addr0, 'aaaa:bbbb:cccc::2', 'aaaa:bbbb:ff00::2',
5189 # 'aaaa:bbbb:cccc::2', addr0] not in na:
5190 # raise Exception("dev2 did not get NA for aaaa:bbbb:cccc::2")
5191 #if [addr2, addr1, 'aaaa:bbbb:dddd::2', 'aaaa:bbbb:ff00::2',
5192 # 'aaaa:bbbb:dddd::2', addr1] not in na:
5193 # raise Exception("dev2 did not get NA for aaaa:bbbb:dddd::2")
5194 #if [addr2, addr1, 'aaaa:bbbb:eeee::2', 'aaaa:bbbb:ff00::2',
5195 # 'aaaa:bbbb:eeee::2', addr1] not in na:
5196 # raise Exception("dev2 did not get NA for aaaa:bbbb:eeee::2")
5197
5198 def test_proxyarp_open(dev, apdev, params):
5199 """ProxyARP with open network"""
5200 try:
5201 _test_proxyarp_open(dev, apdev, params)
5202 finally:
5203 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5204 stderr=open('/dev/null', 'w'))
5205 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5206 stderr=open('/dev/null', 'w'))
5207
5208 def test_proxyarp_open_ipv6(dev, apdev, params):
5209 """ProxyARP with open network (IPv6)"""
5210 try:
5211 _test_proxyarp_open_ipv6(dev, apdev, params)
5212 finally:
5213 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5214 stderr=open('/dev/null', 'w'))
5215 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5216 stderr=open('/dev/null', 'w'))
5217
5218 def test_proxyarp_open_ebtables(dev, apdev, params):
5219 """ProxyARP with open network"""
5220 try:
5221 _test_proxyarp_open(dev, apdev, params, ebtables=True)
5222 finally:
5223 try:
5224 subprocess.call(['ebtables', '-F', 'FORWARD'])
5225 subprocess.call(['ebtables', '-F', 'OUTPUT'])
5226 except:
5227 pass
5228 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5229 stderr=open('/dev/null', 'w'))
5230 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5231 stderr=open('/dev/null', 'w'))
5232
5233 def test_proxyarp_open_ebtables_ipv6(dev, apdev, params):
5234 """ProxyARP with open network (IPv6)"""
5235 try:
5236 _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=True)
5237 finally:
5238 try:
5239 subprocess.call(['ebtables', '-F', 'FORWARD'])
5240 subprocess.call(['ebtables', '-F', 'OUTPUT'])
5241 except:
5242 pass
5243 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5244 stderr=open('/dev/null', 'w'))
5245 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5246 stderr=open('/dev/null', 'w'))
5247
5248 def test_proxyarp_errors(dev, apdev, params):
5249 """ProxyARP error cases"""
5250 try:
5251 run_proxyarp_errors(dev, apdev, params)
5252 finally:
5253 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
5254 stderr=open('/dev/null', 'w'))
5255 subprocess.call(['brctl', 'delbr', 'ap-br0'],
5256 stderr=open('/dev/null', 'w'))
5257
5258 def run_proxyarp_errors(dev, apdev, params):
5259 params = {'ssid': 'open',
5260 'proxy_arp': '1',
5261 'ap_isolate': '1',
5262 'bridge': 'ap-br0',
5263 'disable_dgaf': '1'}
5264 hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
5265 try:
5266 hapd.enable()
5267 except:
5268 # For now, do not report failures due to missing kernel support
5269 raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
5270 ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=10)
5271 if ev is None:
5272 raise Exception("AP startup timed out")
5273 if "AP-ENABLED" not in ev:
5274 raise Exception("AP startup failed")
5275
5276 hapd.disable()
5277 with alloc_fail(hapd, 1, "l2_packet_init;x_snoop_get_l2_packet;dhcp_snoop_init"):
5278 if "FAIL" not in hapd.request("ENABLE"):
5279 raise Exception("ENABLE accepted unexpectedly")
5280 with alloc_fail(hapd, 1, "l2_packet_init;x_snoop_get_l2_packet;ndisc_snoop_init"):
5281 if "FAIL" not in hapd.request("ENABLE"):
5282 raise Exception("ENABLE accepted unexpectedly")
5283 with fail_test(hapd, 1, "l2_packet_set_packet_filter;x_snoop_get_l2_packet;ndisc_snoop_init"):
5284 if "FAIL" not in hapd.request("ENABLE"):
5285 raise Exception("ENABLE accepted unexpectedly")
5286 with fail_test(hapd, 1, "l2_packet_set_packet_filter;x_snoop_get_l2_packet;dhcp_snoop_init"):
5287 if "FAIL" not in hapd.request("ENABLE"):
5288 raise Exception("ENABLE accepted unexpectedly")
5289 hapd.enable()
5290
5291 subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
5292 subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
5293
5294 dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
5295 addr0 = dev[0].own_addr()
5296
5297 pkt = build_ra(src_ll=apdev[0]['bssid'], ip_src="aaaa:bbbb:cccc::33",
5298 ip_dst="ff01::1")
5299 with fail_test(hapd, 1, "x_snoop_mcast_to_ucast_convert_send"):
5300 if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt).decode()):
5301 raise Exception("DATA_TEST_FRAME failed")
5302 wait_fail_trigger(dev[0], "GET_FAIL")
5303
5304 with alloc_fail(hapd, 1, "sta_ip6addr_add"):
5305 src_ll_opt0 = b"\x01\x01" + binascii.unhexlify(addr0.replace(':', ''))
5306 pkt = build_ns(src_ll=addr0, ip_src="aaaa:bbbb:cccc::2",
5307 ip_dst="ff02::1:ff00:2", target="aaaa:bbbb:cccc::2",
5308 opt=src_ll_opt0)
5309 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
5310 raise Exception("DATA_TEST_FRAME failed")
5311 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5312
5313 def test_ap_hs20_connect_deinit(dev, apdev):
5314 """Hotspot 2.0 connection interrupted with deinit"""
5315 check_eap_capa(dev[0], "MSCHAPV2")
5316 bssid = apdev[0]['bssid']
5317 params = hs20_ap_params()
5318 params['hessid'] = bssid
5319 hapd = hostapd.add_ap(apdev[0], params)
5320
5321 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
5322 wpas.interface_add("wlan5", drv_params="")
5323 wpas.hs20_enable()
5324 wpas.flush_scan_cache()
5325 wpas.add_cred_values({'realm': "example.com",
5326 'username': "hs20-test",
5327 'password': "password",
5328 'ca_cert': "auth_serv/ca.pem",
5329 'domain': "example.com"})
5330
5331 wpas.scan_for_bss(bssid, freq=2412)
5332 hapd.disable()
5333
5334 wpas.request("INTERWORKING_SELECT freq=2412")
5335
5336 id = wpas.request("RADIO_WORK add block-work")
5337 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5)
5338 if ev is None:
5339 raise Exception("Timeout while waiting radio work to start")
5340 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5)
5341 if ev is None:
5342 raise Exception("Timeout while waiting radio work to start (2)")
5343
5344 # Remove the interface while the gas-query radio work is still pending and
5345 # GAS query has not yet been started.
5346 wpas.interface_remove("wlan5")
5347
5348 def test_ap_hs20_anqp_format_errors(dev, apdev):
5349 """Interworking network selection and ANQP format errors"""
5350 bssid = apdev[0]['bssid']
5351 params = hs20_ap_params()
5352 params['hessid'] = bssid
5353 hapd = hostapd.add_ap(apdev[0], params)
5354
5355 dev[0].hs20_enable()
5356 values = {'realm': "example.com",
5357 'ca_cert': "auth_serv/ca.pem",
5358 'username': "hs20-test",
5359 'password': "password",
5360 'domain': "example.com"}
5361 id = dev[0].add_cred_values(values)
5362
5363 dev[0].scan_for_bss(bssid, freq="2412")
5364
5365 tests = ["00", "ffff", "010011223344", "020008000005112233445500",
5366 "01000400000000", "01000000000000",
5367 "01000300000200", "0100040000ff0000", "01000300000100",
5368 "01000300000001",
5369 "01000600000056112233",
5370 "01000900000002050001000111",
5371 "01000600000001000000", "01000600000001ff0000",
5372 "01000600000001020001",
5373 "010008000000010400010001", "0100080000000104000100ff",
5374 "010011000000010d00050200020100030005000600",
5375 "0000"]
5376 for t in tests:
5377 hapd.set("anqp_elem", "263:" + t)
5378 dev[0].request("INTERWORKING_SELECT freq=2412")
5379 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=5)
5380 if ev is None:
5381 raise Exception("Network selection timed out")
5382 dev[0].dump_monitor()
5383
5384 dev[0].remove_cred(id)
5385 id = dev[0].add_cred_values({'imsi': "555444-333222111", 'eap': "AKA",
5386 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
5387
5388 tests = ["00", "0100", "0001", "00ff", "000200ff", "0003000101",
5389 "00020100"]
5390 for t in tests:
5391 hapd.set("anqp_elem", "264:" + t)
5392 dev[0].request("INTERWORKING_SELECT freq=2412")
5393 ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=5)
5394 if ev is None:
5395 raise Exception("Network selection timed out")
5396 dev[0].dump_monitor()
5397
5398 def test_ap_hs20_cred_with_nai_realm(dev, apdev):
5399 """Hotspot 2.0 network selection and cred_with_nai_realm cred->realm"""
5400 bssid = apdev[0]['bssid']
5401 params = hs20_ap_params()
5402 params['hessid'] = bssid
5403 hostapd.add_ap(apdev[0], params)
5404
5405 dev[0].hs20_enable()
5406
5407 id = dev[0].add_cred_values({'realm': "example.com",
5408 'username': "test",
5409 'password': "secret",
5410 'domain': "example.com",
5411 'eap': 'TTLS'})
5412 interworking_select(dev[0], bssid, "home", freq=2412)
5413 dev[0].remove_cred(id)
5414
5415 id = dev[0].add_cred_values({'realm': "foo.com",
5416 'username': "test",
5417 'password': "secret",
5418 'domain': "example.com",
5419 'roaming_consortium': "112234",
5420 'eap': 'TTLS'})
5421 interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
5422 dev[0].remove_cred(id)
5423
5424 def test_ap_hs20_cred_and_no_roaming_consortium(dev, apdev):
5425 """Hotspot 2.0 network selection and no roaming consortium"""
5426 bssid = apdev[0]['bssid']
5427 params = hs20_ap_params()
5428 params['hessid'] = bssid
5429 del params['roaming_consortium']
5430 hostapd.add_ap(apdev[0], params)
5431
5432 dev[0].hs20_enable()
5433
5434 id = dev[0].add_cred_values({'realm': "example.com",
5435 'username': "test",
5436 'password': "secret",
5437 'domain': "example.com",
5438 'roaming_consortium': "112234",
5439 'eap': 'TTLS'})
5440 interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
5441
5442 def test_ap_hs20_interworking_oom(dev, apdev):
5443 """Hotspot 2.0 network selection and OOM"""
5444 bssid = apdev[0]['bssid']
5445 params = hs20_ap_params()
5446 params['hessid'] = bssid
5447 params['nai_realm'] = ["0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]",
5448 "0,example.com,13[5:6],21[2:4][5:7]",
5449 "0,another.example.com"]
5450 hostapd.add_ap(apdev[0], params)
5451
5452 dev[0].hs20_enable()
5453
5454 id = dev[0].add_cred_values({'realm': "example.com",
5455 'username': "test",
5456 'password': "secret",
5457 'domain': "example.com",
5458 'eap': 'TTLS'})
5459
5460 dev[0].scan_for_bss(bssid, freq="2412")
5461
5462 funcs = ["wpabuf_alloc;interworking_anqp_send_req",
5463 "anqp_build_req;interworking_anqp_send_req",
5464 "gas_query_req;interworking_anqp_send_req",
5465 "dup_binstr;nai_realm_parse_realm",
5466 "=nai_realm_parse_realm",
5467 "=nai_realm_parse",
5468 "=nai_realm_match"]
5469 for func in funcs:
5470 with alloc_fail(dev[0], 1, func):
5471 dev[0].request("INTERWORKING_SELECT auto freq=2412")
5472 ev = dev[0].wait_event(["Starting ANQP"], timeout=5)
5473 if ev is None:
5474 raise Exception("ANQP did not start")
5475 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5476 dev[0].dump_monitor()
5477
5478 def test_ap_hs20_no_cred_connect(dev, apdev):
5479 """Hotspot 2.0 and connect attempt without credential"""
5480 bssid = apdev[0]['bssid']
5481 params = hs20_ap_params()
5482 params['hessid'] = bssid
5483 hapd = hostapd.add_ap(apdev[0], params)
5484
5485 dev[0].hs20_enable()
5486 dev[0].scan_for_bss(bssid, freq="2412")
5487 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
5488 raise Exception("Unexpected INTERWORKING_CONNECT success")
5489
5490 def test_ap_hs20_no_rsn_connect(dev, apdev):
5491 """Hotspot 2.0 and connect attempt without RSN"""
5492 bssid = apdev[0]['bssid']
5493 params = hostapd.wpa_params(ssid="test-hs20")
5494 params['wpa_key_mgmt'] = "WPA-EAP"
5495 params['ieee80211w'] = "1"
5496 params['ieee8021x'] = "1"
5497 params['auth_server_addr'] = "127.0.0.1"
5498 params['auth_server_port'] = "1812"
5499 params['auth_server_shared_secret'] = "radius"
5500 params['interworking'] = "1"
5501 params['roaming_consortium'] = ["112233", "1020304050", "010203040506",
5502 "fedcba"]
5503 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]",
5504 "0,another.example.com"]
5505 hapd = hostapd.add_ap(apdev[0], params)
5506
5507 dev[0].hs20_enable()
5508 dev[0].scan_for_bss(bssid, freq="2412")
5509
5510 id = dev[0].add_cred_values({'realm': "example.com",
5511 'username': "test",
5512 'password': "secret",
5513 'domain': "example.com",
5514 'roaming_consortium': "112233",
5515 'eap': 'TTLS'})
5516
5517 interworking_select(dev[0], bssid, freq=2412, no_match=True)
5518 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
5519 raise Exception("Unexpected INTERWORKING_CONNECT success")
5520
5521 def test_ap_hs20_no_match_connect(dev, apdev):
5522 """Hotspot 2.0 and connect attempt without matching cred"""
5523 bssid = apdev[0]['bssid']
5524 params = hs20_ap_params()
5525 hapd = hostapd.add_ap(apdev[0], params)
5526
5527 dev[0].hs20_enable()
5528 dev[0].scan_for_bss(bssid, freq="2412")
5529
5530 id = dev[0].add_cred_values({'realm': "example.org",
5531 'username': "test",
5532 'password': "secret",
5533 'domain': "example.org",
5534 'roaming_consortium': "112234",
5535 'eap': 'TTLS'})
5536
5537 interworking_select(dev[0], bssid, freq=2412, no_match=True)
5538 if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
5539 raise Exception("Unexpected INTERWORKING_CONNECT success")
5540
5541 def test_ap_hs20_multiple_home_cred(dev, apdev):
5542 """Hotspot 2.0 and select with multiple matching home credentials"""
5543 bssid = apdev[0]['bssid']
5544 params = hs20_ap_params()
5545 params['hessid'] = bssid
5546 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]"]
5547 params['domain_name'] = "example.com"
5548 hapd = hostapd.add_ap(apdev[0], params)
5549
5550 bssid2 = apdev[1]['bssid']
5551 params = hs20_ap_params(ssid="test-hs20-other")
5552 params['hessid'] = bssid2
5553 params['nai_realm'] = ["0,example.org,13[5:6],21[2:4][5:7]"]
5554 params['domain_name'] = "example.org"
5555 hapd2 = hostapd.add_ap(apdev[1], params)
5556
5557 dev[0].hs20_enable()
5558 dev[0].scan_for_bss(bssid2, freq="2412")
5559 dev[0].scan_for_bss(bssid, freq="2412")
5560 id = dev[0].add_cred_values({'realm': "example.com",
5561 'priority': '2',
5562 'username': "hs20-test",
5563 'password': "password",
5564 'domain': "example.com"})
5565 id2 = dev[0].add_cred_values({'realm': "example.org",
5566 'priority': '3',
5567 'username': "hs20-test",
5568 'password': "password",
5569 'domain': "example.org"})
5570 dev[0].request("INTERWORKING_SELECT auto freq=2412")
5571 ev = dev[0].wait_connected(timeout=15)
5572 if bssid2 not in ev:
5573 raise Exception("Connected to incorrect network")
5574
5575 def test_ap_hs20_anqp_invalid_gas_response(dev, apdev):
5576 """Hotspot 2.0 network selection and invalid GAS response"""
5577 bssid = apdev[0]['bssid']
5578 params = hs20_ap_params()
5579 params['hessid'] = bssid
5580 hapd = hostapd.add_ap(apdev[0], params)
5581
5582 dev[0].scan_for_bss(bssid, freq="2412")
5583 hapd.set("ext_mgmt_frame_handling", "1")
5584
5585 dev[0].hs20_enable()
5586
5587 id = dev[0].add_cred_values({'realm': "example.com",
5588 'username': "test",
5589 'password': "secret",
5590 'domain': "example.com",
5591 'roaming_consortium': "112234",
5592 'eap': 'TTLS'})
5593 dev[0].request("INTERWORKING_SELECT freq=2412")
5594
5595 query = gas_rx(hapd)
5596 gas = parse_gas(query['payload'])
5597
5598 logger.info("ANQP: Unexpected Advertisement Protocol in response")
5599 resp = action_response(query)
5600 adv_proto = struct.pack('8B', 108, 6, 127, 0xdd, 0x00, 0x11, 0x22, 0x33)
5601 data = struct.pack('<H', 0)
5602 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5603 GAS_INITIAL_RESPONSE,
5604 gas['dialog_token'], 0, 0) + adv_proto + data
5605 send_gas_resp(hapd, resp)
5606
5607 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5608 if ev is None:
5609 raise Exception("No ANQP-QUERY-DONE seen")
5610 if "result=INVALID_FRAME" not in ev:
5611 raise Exception("Unexpected result: " + ev)
5612
5613 dev[0].request("INTERWORKING_SELECT freq=2412")
5614
5615 query = gas_rx(hapd)
5616 gas = parse_gas(query['payload'])
5617
5618 logger.info("ANQP: Invalid element length for Info ID 1234")
5619 resp = action_response(query)
5620 adv_proto = struct.pack('BBBB', 108, 2, 127, 0)
5621 elements = struct.pack('<HH', 1234, 1)
5622 data = struct.pack('<H', len(elements)) + elements
5623 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5624 GAS_INITIAL_RESPONSE,
5625 gas['dialog_token'], 0, 0) + adv_proto + data
5626 send_gas_resp(hapd, resp)
5627
5628 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5629 if ev is None:
5630 raise Exception("No ANQP-QUERY-DONE seen")
5631 if "result=INVALID_FRAME" not in ev:
5632 raise Exception("Unexpected result: " + ev)
5633
5634 with alloc_fail(dev[0], 1, "=anqp_add_extra"):
5635 dev[0].request("INTERWORKING_SELECT freq=2412")
5636
5637 query = gas_rx(hapd)
5638 gas = parse_gas(query['payload'])
5639
5640 resp = action_response(query)
5641 elements = struct.pack('<HHHH', 1, 0, 1, 0)
5642 data = struct.pack('<H', len(elements)) + elements
5643 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5644 GAS_INITIAL_RESPONSE,
5645 gas['dialog_token'], 0, 0) + adv_proto + data
5646 send_gas_resp(hapd, resp)
5647
5648 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5649 if ev is None:
5650 raise Exception("No ANQP-QUERY-DONE seen")
5651 if "result=SUCCESS" not in ev:
5652 raise Exception("Unexpected result: " + ev)
5653
5654 with alloc_fail(dev[0], 1, "wpabuf_alloc_copy;anqp_add_extra"):
5655 dev[0].request("INTERWORKING_SELECT freq=2412")
5656
5657 query = gas_rx(hapd)
5658 gas = parse_gas(query['payload'])
5659
5660 resp = action_response(query)
5661 elements = struct.pack('<HHHH', 1, 0, 1, 0)
5662 data = struct.pack('<H', len(elements)) + elements
5663 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5664 GAS_INITIAL_RESPONSE,
5665 gas['dialog_token'], 0, 0) + adv_proto + data
5666 send_gas_resp(hapd, resp)
5667
5668 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5669 if ev is None:
5670 raise Exception("No ANQP-QUERY-DONE seen")
5671 if "result=SUCCESS" not in ev:
5672 raise Exception("Unexpected result: " + ev)
5673
5674 tests = [struct.pack('<HH', 0xdddd, 0),
5675 struct.pack('<HH3B', 0xdddd, 3, 0x50, 0x6f, 0x9a),
5676 struct.pack('<HH4B', 0xdddd, 4, 0x50, 0x6f, 0x9a, 0),
5677 struct.pack('<HH4B', 0xdddd, 4, 0x11, 0x22, 0x33, 0),
5678 struct.pack('<HHHH', 1, 0, 1, 0)]
5679 for elements in tests:
5680 dev[0].request("INTERWORKING_SELECT freq=2412")
5681
5682 query = gas_rx(hapd)
5683 gas = parse_gas(query['payload'])
5684
5685 resp = action_response(query)
5686 data = struct.pack('<H', len(elements)) + elements
5687 resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
5688 GAS_INITIAL_RESPONSE,
5689 gas['dialog_token'], 0, 0) + adv_proto + data
5690 send_gas_resp(hapd, resp)
5691
5692 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
5693 if ev is None:
5694 raise Exception("No ANQP-QUERY-DONE seen")
5695 if "result=SUCCESS" not in ev:
5696 raise Exception("Unexpected result: " + ev)
5697
5698 def test_ap_hs20_set_profile_failures(dev, apdev):
5699 """Hotspot 2.0 and failures during profile configuration"""
5700 bssid = apdev[0]['bssid']
5701 params = hs20_ap_params()
5702 params['hessid'] = bssid
5703 params['anqp_3gpp_cell_net'] = "555,444"
5704 hapd = hostapd.add_ap(apdev[0], params)
5705
5706 dev[0].hs20_enable()
5707 dev[0].scan_for_bss(bssid, freq="2412")
5708
5709 id = dev[0].add_cred_values({'realm': "example.com",
5710 'domain': "example.com",
5711 'username': "test",
5712 'password': "secret",
5713 'eap': 'TTLS'})
5714 interworking_select(dev[0], bssid, "home", freq=2412)
5715 dev[0].dump_monitor()
5716 dev[0].request("NOTE ssid->eap.eap_methods = os_malloc()")
5717 with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
5718 dev[0].request("INTERWORKING_CONNECT " + bssid)
5719 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5720 dev[0].remove_cred(id)
5721
5722 id = dev[0].add_cred_values({'realm': "example.com",
5723 'domain': "example.com",
5724 'username': "hs20-test-with-domain@example.com",
5725 'password': "password"})
5726 interworking_select(dev[0], bssid, "home", freq=2412)
5727 dev[0].dump_monitor()
5728 dev[0].request("NOTE anon = os_malloc()")
5729 with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
5730 dev[0].request("INTERWORKING_CONNECT " + bssid)
5731 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5732 dev[0].request("NOTE Successful connection with cred->username including realm")
5733 dev[0].request("INTERWORKING_CONNECT " + bssid)
5734 dev[0].wait_connected()
5735 dev[0].remove_cred(id)
5736 dev[0].wait_disconnected()
5737
5738 id = dev[0].add_cred_values({'realm': "example.com",
5739 'domain': "example.com",
5740 'username': "hs20-test",
5741 'password': "password"})
5742 interworking_select(dev[0], bssid, "home", freq=2412)
5743 dev[0].dump_monitor()
5744 dev[0].request("NOTE anon = os_malloc() (second)")
5745 with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
5746 dev[0].request("INTERWORKING_CONNECT " + bssid)
5747 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5748 with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect"):
5749 dev[0].request("INTERWORKING_CONNECT " + bssid)
5750 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5751 with alloc_fail(dev[0], 1, "=interworking_connect"):
5752 dev[0].request("INTERWORKING_CONNECT " + bssid)
5753 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5754 dev[0].request("NOTE wpa_config_set(eap)")
5755 with alloc_fail(dev[0], 1, "wpa_config_parse_eap;wpa_config_set;interworking_connect"):
5756 dev[0].request("INTERWORKING_CONNECT " + bssid)
5757 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5758 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_MSCHAPV2-phase2)")
5759 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5760 dev[0].request("INTERWORKING_CONNECT " + bssid)
5761 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5762 dev[0].remove_cred(id)
5763
5764 id = dev[0].add_cred_values({'roaming_consortium': "112233",
5765 'domain': "example.com",
5766 'username': "hs20-test",
5767 'password': "password",
5768 'eap': 'TTLS',
5769 'phase2': "auth=MSCHAPV2"})
5770 interworking_select(dev[0], bssid, "home", freq=2412)
5771 dev[0].dump_monitor()
5772 dev[0].request("NOTE anon = os_strdup()")
5773 with alloc_fail(dev[0], 2, "interworking_set_eap_params"):
5774 dev[0].request("INTERWORKING_CONNECT " + bssid)
5775 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5776 dev[0].request("NOTE wpa_config_set_quoted(anonymous_identity)")
5777 with alloc_fail(dev[0], 1, "=wpa_config_set_quoted;interworking_set_eap_params"):
5778 dev[0].request("INTERWORKING_CONNECT " + bssid)
5779 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5780 dev[0].request("NOTE Successful connection with cred->realm not included")
5781 dev[0].request("INTERWORKING_CONNECT " + bssid)
5782 dev[0].wait_connected()
5783 dev[0].remove_cred(id)
5784 dev[0].wait_disconnected()
5785
5786 id = dev[0].add_cred_values({'roaming_consortium': "112233",
5787 'domain': "example.com",
5788 'realm': "example.com",
5789 'username': "user",
5790 'password': "password",
5791 'eap': 'PEAP'})
5792 interworking_select(dev[0], bssid, "home", freq=2412)
5793 dev[0].dump_monitor()
5794 dev[0].request("NOTE id = os_strdup()")
5795 with alloc_fail(dev[0], 2, "interworking_set_eap_params"):
5796 dev[0].request("INTERWORKING_CONNECT " + bssid)
5797 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5798 dev[0].request("NOTE wpa_config_set_quoted(identity)")
5799 with alloc_fail(dev[0], 1, "=wpa_config_set_quoted;interworking_set_eap_params"):
5800 dev[0].request("INTERWORKING_CONNECT " + bssid)
5801 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5802 dev[0].remove_cred(id)
5803
5804 id = dev[0].add_cred_values({'roaming_consortium': "112233",
5805 'domain': "example.com",
5806 'realm': "example.com",
5807 'username': "user",
5808 'password': "password",
5809 'eap': "TTLS"})
5810 interworking_select(dev[0], bssid, "home", freq=2412)
5811 dev[0].dump_monitor()
5812 dev[0].request("NOTE wpa_config_set_quoted(identity) (second)")
5813 with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_set_eap_params"):
5814 dev[0].request("INTERWORKING_CONNECT " + bssid)
5815 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5816 dev[0].request("NOTE wpa_config_set_quoted(password)")
5817 with alloc_fail(dev[0], 3, "=wpa_config_set_quoted;interworking_set_eap_params"):
5818 dev[0].request("INTERWORKING_CONNECT " + bssid)
5819 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5820 with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect_roaming_consortium"):
5821 dev[0].request("INTERWORKING_CONNECT " + bssid)
5822 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5823 with alloc_fail(dev[0], 1, "=interworking_connect_roaming_consortium"):
5824 dev[0].request("INTERWORKING_CONNECT " + bssid)
5825 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5826 dev[0].remove_cred(id)
5827
5828 id = dev[0].add_cred_values({'roaming_consortium': "112233",
5829 'domain': "example.com",
5830 'realm': "example.com",
5831 'username': "user",
5832 'eap': "PEAP"})
5833 dev[0].set_cred(id, "password", "ext:password")
5834 interworking_select(dev[0], bssid, "home", freq=2412)
5835 dev[0].dump_monitor()
5836 dev[0].request("NOTE wpa_config_set(password)")
5837 with alloc_fail(dev[0], 3, "wpa_config_set;interworking_set_eap_params"):
5838 dev[0].request("INTERWORKING_CONNECT " + bssid)
5839 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5840 with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
5841 dev[0].request("INTERWORKING_CONNECT " + bssid)
5842 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5843 dev[0].remove_cred(id)
5844
5845 id = dev[0].add_cred_values({'realm': "example.com",
5846 'domain': "example.com",
5847 'username': "certificate-user",
5848 'phase1': "include_tls_length=0",
5849 'domain_suffix_match': "example.com",
5850 'ca_cert': "auth_serv/ca.pem",
5851 'client_cert': "auth_serv/user.pem",
5852 'private_key': "auth_serv/user.key",
5853 'private_key_passwd': "secret"})
5854 interworking_select(dev[0], bssid, "home", freq=2412)
5855 dev[0].dump_monitor()
5856 dev[0].request("NOTE wpa_config_set_quoted(client_cert)")
5857 with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_set_eap_params"):
5858 dev[0].request("INTERWORKING_CONNECT " + bssid)
5859 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5860 dev[0].request("NOTE wpa_config_set_quoted(private_key)")
5861 with alloc_fail(dev[0], 3, "=wpa_config_set_quoted;interworking_set_eap_params"):
5862 dev[0].request("INTERWORKING_CONNECT " + bssid)
5863 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5864 dev[0].request("NOTE wpa_config_set_quoted(private_key_passwd)")
5865 with alloc_fail(dev[0], 4, "=wpa_config_set_quoted;interworking_set_eap_params"):
5866 dev[0].request("INTERWORKING_CONNECT " + bssid)
5867 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5868 dev[0].request("NOTE wpa_config_set_quoted(ca_cert)")
5869 with alloc_fail(dev[0], 5, "=wpa_config_set_quoted;interworking_set_eap_params"):
5870 dev[0].request("INTERWORKING_CONNECT " + bssid)
5871 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5872 dev[0].request("NOTE wpa_config_set_quoted(domain_suffix_match)")
5873 with alloc_fail(dev[0], 6, "=wpa_config_set_quoted;interworking_set_eap_params"):
5874 dev[0].request("INTERWORKING_CONNECT " + bssid)
5875 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5876 with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
5877 dev[0].request("INTERWORKING_CONNECT " + bssid)
5878 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5879 dev[0].remove_cred(id)
5880
5881 id = dev[0].add_cred_values({'imsi': "555444-333222111", 'eap': "SIM",
5882 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
5883 interworking_select(dev[0], bssid, freq=2412)
5884 dev[0].dump_monitor()
5885 with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
5886 dev[0].request("INTERWORKING_CONNECT " + bssid)
5887 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5888 dev[0].request("NOTE wpa_config_set_quoted(password;milenage)")
5889 with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_connect_3gpp"):
5890 dev[0].request("INTERWORKING_CONNECT " + bssid)
5891 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5892 dev[0].request("NOTE wpa_config_set(eap)")
5893 with alloc_fail(dev[0], 1, "wpa_config_parse_eap;wpa_config_set;interworking_connect_3gpp"):
5894 dev[0].request("INTERWORKING_CONNECT " + bssid)
5895 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5896 dev[0].request("NOTE set_root_nai:wpa_config_set(identity)")
5897 with alloc_fail(dev[0], 1, "wpa_config_parse_str;interworking_connect_3gpp"):
5898 dev[0].request("INTERWORKING_CONNECT " + bssid)
5899 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5900 dev[0].remove_cred(id)
5901
5902 id = dev[0].add_cred_values({'roaming_consortium': "112233",
5903 'eap': 'TTLS',
5904 'username': "user@example.com",
5905 'password': "password"})
5906 interworking_select(dev[0], bssid, freq=2412)
5907 dev[0].dump_monitor()
5908 dev[0].request("NOTE Interworking: No EAP method set for credential using roaming consortium")
5909 dev[0].request("INTERWORKING_CONNECT " + bssid)
5910 dev[0].remove_cred(id)
5911
5912 hapd.disable()
5913 params = hs20_ap_params()
5914 params['nai_realm'] = "0,example.com,25[3:26]"
5915 hapd = hostapd.add_ap(apdev[0], params)
5916 id = dev[0].add_cred_values({'realm': "example.com",
5917 'domain': "example.com",
5918 'username': "hs20-test",
5919 'password': "password"})
5920 interworking_select(dev[0], bssid, freq=2412)
5921 dev[0].dump_monitor()
5922 dev[0].request("NOTE wpa_config_set(PEAP/FAST-phase1)")
5923 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5924 dev[0].request("INTERWORKING_CONNECT " + bssid)
5925 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5926 dev[0].request("NOTE wpa_config_set(PEAP/FAST-pac_interworking)")
5927 with alloc_fail(dev[0], 2, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5928 dev[0].request("INTERWORKING_CONNECT " + bssid)
5929 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5930 dev[0].request("NOTE wpa_config_set(PEAP/FAST-phase2)")
5931 with alloc_fail(dev[0], 3, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5932 dev[0].request("INTERWORKING_CONNECT " + bssid)
5933 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5934
5935 hapd.disable()
5936 params = hs20_ap_params()
5937 params['nai_realm'] = "0,example.com,21"
5938 hapd = hostapd.add_ap(apdev[0], params)
5939 interworking_select(dev[0], bssid, freq=2412)
5940 dev[0].request("NOTE wpa_config_set(TTLS-defaults-phase2)")
5941 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5942 dev[0].request("INTERWORKING_CONNECT " + bssid)
5943 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5944
5945 hapd.disable()
5946 params = hs20_ap_params()
5947 params['nai_realm'] = "0,example.com,21[2:3]"
5948 hapd = hostapd.add_ap(apdev[0], params)
5949 interworking_select(dev[0], bssid, freq=2412)
5950 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_MSCHAP-phase2)")
5951 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5952 dev[0].request("INTERWORKING_CONNECT " + bssid)
5953 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5954
5955 hapd.disable()
5956 params = hs20_ap_params()
5957 params['nai_realm'] = "0,example.com,21[2:2]"
5958 hapd = hostapd.add_ap(apdev[0], params)
5959 interworking_select(dev[0], bssid, freq=2412)
5960 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_CHAP-phase2)")
5961 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5962 dev[0].request("INTERWORKING_CONNECT " + bssid)
5963 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5964
5965 hapd.disable()
5966 params = hs20_ap_params()
5967 params['nai_realm'] = "0,example.com,21[2:1]"
5968 hapd = hostapd.add_ap(apdev[0], params)
5969 interworking_select(dev[0], bssid, freq=2412)
5970 dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_PAP-phase2)")
5971 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5972 dev[0].request("INTERWORKING_CONNECT " + bssid)
5973 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5974
5975 hapd.disable()
5976 params = hs20_ap_params()
5977 params['nai_realm'] = "0,example.com,21[3:26]"
5978 hapd = hostapd.add_ap(apdev[0], params)
5979 interworking_select(dev[0], bssid, freq=2412)
5980 dev[0].request("NOTE wpa_config_set(TTLS-EAP-MSCHAPV2-phase2)")
5981 with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
5982 dev[0].request("INTERWORKING_CONNECT " + bssid)
5983 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5984
5985 dev[0].remove_cred(id)
5986
5987 def test_ap_hs20_unexpected(dev, apdev):
5988 """Unexpected Hotspot 2.0 AP configuration"""
5989 check_eap_capa(dev[0], "MSCHAPV2")
5990 bssid = apdev[0]['bssid']
5991 params = hostapd.wpa_eap_params(ssid="test-hs20-fake")
5992 params['wpa'] = "3"
5993 params['wpa_pairwise'] = "TKIP CCMP"
5994 params['rsn_pairwise'] = "CCMP"
5995 params['ieee80211w'] = "1"
5996 #params['vendor_elements'] = 'dd07506f9a10140000'
5997 params['vendor_elements'] = 'dd04506f9a10'
5998 hostapd.add_ap(apdev[0], params)
5999
6000 dev[0].hs20_enable()
6001 dev[0].scan_for_bss(bssid, freq="2412")
6002 dev[0].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
6003 pairwise="TKIP",
6004 identity="hs20-test", password="password",
6005 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6006 scan_freq="2412")
6007
6008 dev[1].hs20_enable()
6009 dev[1].scan_for_bss(bssid, freq="2412")
6010 dev[1].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
6011 proto="WPA",
6012 identity="hs20-test", password="password",
6013 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6014 scan_freq="2412")
6015
6016 dev[2].hs20_enable()
6017 dev[2].scan_for_bss(bssid, freq="2412")
6018 dev[2].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
6019 ieee80211w="1",
6020 proto="RSN", pairwise="CCMP",
6021 identity="hs20-test", password="password",
6022 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6023 scan_freq="2412")
6024
6025 def test_ap_interworking_element_update(dev, apdev):
6026 """Dynamic Interworking element update"""
6027 bssid = apdev[0]['bssid']
6028 params = hs20_ap_params()
6029 params['hessid'] = bssid
6030 hapd = hostapd.add_ap(apdev[0], params)
6031
6032 dev[0].hs20_enable()
6033 dev[0].scan_for_bss(bssid, freq="2412")
6034 bss = dev[0].get_bss(bssid)
6035 logger.info("Before update: " + str(bss))
6036 if '6b091e0701020000000300' not in bss['ie']:
6037 raise Exception("Expected Interworking element not seen before update")
6038
6039 # Update configuration parameters related to Interworking element
6040 hapd.set('access_network_type', '2')
6041 hapd.set('asra', '1')
6042 hapd.set('esr', '1')
6043 hapd.set('uesa', '1')
6044 hapd.set('venue_group', '2')
6045 hapd.set('venue_type', '8')
6046 if "OK" not in hapd.request("UPDATE_BEACON"):
6047 raise Exception("UPDATE_BEACON failed")
6048 dev[0].request("BSS_FLUSH 0")
6049 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
6050 bss = dev[0].get_bss(bssid)
6051 logger.info("After update: " + str(bss))
6052 if '6b09f20208020000000300' not in bss['ie']:
6053 raise Exception("Expected Interworking element not seen after update")
6054
6055 def test_ap_hs20_terms_and_conditions(dev, apdev):
6056 """Hotspot 2.0 Terms and Conditions signaling"""
6057 check_eap_capa(dev[0], "MSCHAPV2")
6058 bssid = apdev[0]['bssid']
6059 params = hs20_ap_params()
6060 params['hessid'] = bssid
6061 params['hs20_t_c_filename'] = 'terms-and-conditions'
6062 params['hs20_t_c_timestamp'] = '123456789'
6063
6064 hostapd.add_ap(apdev[0], params)
6065
6066 dev[0].hs20_enable()
6067 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
6068 identity="hs20-t-c-test", password="password",
6069 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6070 ieee80211w='2', scan_freq="2412")
6071 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6072 if ev is None:
6073 raise Exception("Terms and Conditions Acceptance notification not received")
6074 url = "https://example.com/t_and_c?addr=%s&ap=123" % dev[0].own_addr()
6075 if url not in ev:
6076 raise Exception("Unexpected URL: " + ev)
6077
6078 def test_ap_hs20_terms_and_conditions_coa(dev, apdev):
6079 """Hotspot 2.0 Terms and Conditions signaling - CoA"""
6080 try:
6081 import pyrad.client
6082 import pyrad.packet
6083 import pyrad.dictionary
6084 import radius_das
6085 except ImportError:
6086 raise HwsimSkip("No pyrad modules available")
6087
6088 check_eap_capa(dev[0], "MSCHAPV2")
6089 bssid = apdev[0]['bssid']
6090 params = hs20_ap_params()
6091 params['hessid'] = bssid
6092 params['hs20_t_c_filename'] = 'terms-and-conditions'
6093 params['hs20_t_c_timestamp'] = '123456789'
6094 params['own_ip_addr'] = "127.0.0.1"
6095 params['radius_das_port'] = "3799"
6096 params['radius_das_client'] = "127.0.0.1 secret"
6097 params['radius_das_require_event_timestamp'] = "1"
6098 hapd = hostapd.add_ap(apdev[0], params)
6099
6100 dev[0].hs20_enable()
6101 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
6102 identity="hs20-t-c-test", password="password",
6103 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6104 ieee80211w='2', scan_freq="2412")
6105
6106 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=5)
6107 if ev is None:
6108 raise Exception("Terms and Conditions filtering not enabled")
6109 if ev.split(' ')[1] != dev[0].own_addr():
6110 raise Exception("Unexpected STA address for filtering: " + ev)
6111
6112 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6113 if ev is None:
6114 raise Exception("Terms and Conditions Acceptance notification not received")
6115 url = "https://example.com/t_and_c?addr=%s&ap=123" % dev[0].own_addr()
6116 if url not in ev:
6117 raise Exception("Unexpected URL: " + ev)
6118
6119 dict = pyrad.dictionary.Dictionary("dictionary.radius")
6120
6121 srv = pyrad.client.Client(server="127.0.0.1", acctport=3799,
6122 secret=b"secret", dict=dict)
6123 srv.retries = 1
6124 srv.timeout = 1
6125
6126 sta = hapd.get_sta(dev[0].own_addr())
6127 multi_sess_id = sta['authMultiSessionId']
6128
6129 logger.info("CoA-Request with matching Acct-Session-Id")
6130 vsa = binascii.unhexlify('00009f68090600000000')
6131 req = radius_das.CoAPacket(dict=dict, secret=b"secret",
6132 NAS_IP_Address="127.0.0.1",
6133 Acct_Multi_Session_Id=multi_sess_id,
6134 Chargeable_User_Identity="hs20-cui",
6135 Event_Timestamp=int(time.time()),
6136 Vendor_Specific=vsa)
6137 reply = srv.SendPacket(req)
6138 logger.debug("RADIUS response from hostapd")
6139 for i in list(reply.keys()):
6140 logger.debug("%s: %s" % (i, reply[i]))
6141 if reply.code != pyrad.packet.CoAACK:
6142 raise Exception("CoA-Request failed")
6143
6144 ev = hapd.wait_event(["HS20-T-C-FILTERING-REMOVE"], timeout=5)
6145 if ev is None:
6146 raise Exception("Terms and Conditions filtering not disabled")
6147 if ev.split(' ')[1] != dev[0].own_addr():
6148 raise Exception("Unexpected STA address for filtering: " + ev)
6149
6150 def test_ap_hs20_terms_and_conditions_sql(dev, apdev, params):
6151 """Hotspot 2.0 Terms and Conditions using SQLite for user DB"""
6152 addr = dev[0].own_addr()
6153 run_ap_hs20_terms_and_conditions_sql(dev, apdev, params,
6154 "https://example.com/t_and_c?addr=@1@&ap=123",
6155 "https://example.com/t_and_c?addr=" + addr + "&ap=123")
6156
6157 def test_ap_hs20_terms_and_conditions_sql2(dev, apdev, params):
6158 """Hotspot 2.0 Terms and Conditions using SQLite for user DB"""
6159 addr = dev[0].own_addr()
6160 run_ap_hs20_terms_and_conditions_sql(dev, apdev, params,
6161 "https://example.com/t_and_c?addr=@1@",
6162 "https://example.com/t_and_c?addr=" + addr)
6163
6164 def run_ap_hs20_terms_and_conditions_sql(dev, apdev, params, url_template,
6165 url_expected):
6166 check_eap_capa(dev[0], "MSCHAPV2")
6167 try:
6168 import sqlite3
6169 except ImportError:
6170 raise HwsimSkip("No sqlite3 module available")
6171 dbfile = os.path.join(params['logdir'], "eap-user.db")
6172 try:
6173 os.remove(dbfile)
6174 except:
6175 pass
6176 con = sqlite3.connect(dbfile)
6177 with con:
6178 cur = con.cursor()
6179 cur.execute("CREATE TABLE users(identity TEXT PRIMARY KEY, methods TEXT, password TEXT, remediation TEXT, phase2 INTEGER, t_c_timestamp INTEGER)")
6180 cur.execute("CREATE TABLE wildcards(identity TEXT PRIMARY KEY, methods TEXT)")
6181 cur.execute("INSERT INTO users(identity,methods,password,phase2) VALUES ('user-mschapv2','TTLS-MSCHAPV2','password',1)")
6182 cur.execute("INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS')")
6183 cur.execute("CREATE TABLE authlog(timestamp TEXT, session TEXT, nas_ip TEXT, username TEXT, note TEXT)")
6184 cur.execute("CREATE TABLE pending_tc(mac_addr TEXT PRIMARY KEY, identity TEXT)")
6185 cur.execute("CREATE TABLE current_sessions(mac_addr TEXT PRIMARY KEY, identity TEXT, start_time TEXT, nas TEXT, hs20_t_c_filtering BOOLEAN, waiting_coa_ack BOOLEAN, coa_ack_received BOOLEAN)")
6186
6187
6188 try:
6189 params = {"ssid": "as", "beacon_int": "2000",
6190 "radius_server_clients": "auth_serv/radius_clients.conf",
6191 "radius_server_auth_port": '18128',
6192 "eap_server": "1",
6193 "eap_user_file": "sqlite:" + dbfile,
6194 "ca_cert": "auth_serv/ca.pem",
6195 "server_cert": "auth_serv/server.pem",
6196 "private_key": "auth_serv/server.key"}
6197 params['hs20_t_c_server_url'] = url_template
6198 authsrv = hostapd.add_ap(apdev[1], params)
6199
6200 bssid = apdev[0]['bssid']
6201 params = hs20_ap_params()
6202 params['auth_server_port'] = "18128"
6203 params['hs20_t_c_filename'] = 'terms-and-conditions'
6204 params['hs20_t_c_timestamp'] = '123456789'
6205 params['own_ip_addr'] = "127.0.0.1"
6206 params['radius_das_port'] = "3799"
6207 params['radius_das_client'] = "127.0.0.1 radius"
6208 params['radius_das_require_event_timestamp'] = "1"
6209 params['disable_pmksa_caching'] = '1'
6210 hapd = hostapd.add_ap(apdev[0], params)
6211
6212 dev[0].request("SET pmf 1")
6213 dev[0].hs20_enable()
6214 id = dev[0].add_cred_values({'realm': "example.com",
6215 'username': "user-mschapv2",
6216 'password': "password",
6217 'ca_cert': "auth_serv/ca.pem"})
6218 interworking_select(dev[0], bssid, freq="2412")
6219 interworking_connect(dev[0], bssid, "TTLS")
6220
6221 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=5)
6222 if ev is None:
6223 raise Exception("Terms and Conditions filtering not enabled")
6224 hapd.dump_monitor()
6225
6226 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6227 if ev is None:
6228 raise Exception("Terms and Conditions Acceptance notification not received")
6229 url = ev.split(' ')[1]
6230 if url != url_expected:
6231 raise Exception("Unexpected URL delivered to the client: %s (expected %s)" % (url, url_expected))
6232 dev[0].dump_monitor()
6233
6234 with con:
6235 cur = con.cursor()
6236 cur.execute("SELECT * from current_sessions")
6237 rows = cur.fetchall()
6238 if len(rows) != 1:
6239 raise Exeception("Unexpected number of rows in current_sessions (%d; expected %d)" % (len(rows), 1))
6240 logger.info("current_sessions: " + str(rows))
6241
6242 if "OK" not in authsrv.request("DAC_REQUEST coa %s t_c_clear" % dev[0].own_addr()):
6243 raise Exception("DAC_REQUEST failed")
6244
6245 ev = hapd.wait_event(["HS20-T-C-FILTERING-REMOVE"], timeout=5)
6246 if ev is None:
6247 raise Exception("Terms and Conditions filtering not disabled")
6248 if ev.split(' ')[1] != dev[0].own_addr():
6249 raise Exception("Unexpected STA address for filtering: " + ev)
6250
6251 time.sleep(0.2)
6252 with con:
6253 cur = con.cursor()
6254 cur.execute("SELECT * from current_sessions")
6255 rows = cur.fetchall()
6256 if len(rows) != 1:
6257 raise Exeception("Unexpected number of rows in current_sessions (%d; expected %d)" % (len(rows), 1))
6258 logger.info("current_sessions: " + str(rows))
6259 if rows[0][4] != 0 or rows[0][5] != 0 or rows[0][6] != 1:
6260 raise Exception("Unexpected current_sessions information after CoA-ACK")
6261
6262 dev[0].request("DISCONNECT")
6263 dev[0].wait_disconnected()
6264 dev[0].dump_monitor()
6265
6266 # Simulate T&C server operation on user reading the updated version
6267 with con:
6268 cur = con.cursor()
6269 cur.execute("SELECT identity FROM pending_tc WHERE mac_addr='" +
6270 dev[0].own_addr() + "'")
6271 rows = cur.fetchall()
6272 if len(rows) != 1:
6273 raise Exception("No pending_tc entry found")
6274 if rows[0][0] != 'user-mschapv2':
6275 raise Exception("Unexpected pending_tc identity value")
6276
6277 cur.execute("UPDATE users SET t_c_timestamp=123456789 WHERE identity='user-mschapv2'")
6278
6279 dev[0].request("RECONNECT")
6280 dev[0].wait_connected()
6281
6282 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=0.1)
6283 if ev is not None:
6284 raise Exception("Terms and Conditions filtering enabled unexpectedly")
6285 hapd.dump_monitor()
6286
6287 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=0.1)
6288 if ev is not None:
6289 raise Exception("Unexpected Terms and Conditions Acceptance notification")
6290 dev[0].dump_monitor()
6291
6292 dev[0].request("DISCONNECT")
6293 dev[0].wait_disconnected()
6294 dev[0].dump_monitor()
6295
6296 # New T&C available
6297 hapd.set('hs20_t_c_timestamp', '123456790')
6298
6299 dev[0].request("RECONNECT")
6300 dev[0].wait_connected()
6301
6302 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=5)
6303 if ev is None:
6304 raise Exception("Terms and Conditions filtering not enabled")
6305 hapd.dump_monitor()
6306
6307 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=5)
6308 if ev is None:
6309 raise Exception("Terms and Conditions Acceptance notification not received (2)")
6310 dev[0].dump_monitor()
6311
6312 dev[0].request("DISCONNECT")
6313 dev[0].wait_disconnected()
6314 dev[0].dump_monitor()
6315
6316 # Simulate T&C server operation on user reading the updated version
6317 with con:
6318 cur = con.cursor()
6319 cur.execute("UPDATE users SET t_c_timestamp=123456790 WHERE identity='user-mschapv2'")
6320
6321 dev[0].request("RECONNECT")
6322 dev[0].wait_connected()
6323
6324 ev = hapd.wait_event(["HS20-T-C-FILTERING-ADD"], timeout=0.1)
6325 if ev is not None:
6326 raise Exception("Terms and Conditions filtering enabled unexpectedly")
6327 hapd.dump_monitor()
6328
6329 ev = dev[0].wait_event(["HS20-T-C-ACCEPTANCE"], timeout=0.1)
6330 if ev is not None:
6331 raise Exception("Unexpected Terms and Conditions Acceptance notification (2)")
6332 dev[0].dump_monitor()
6333 finally:
6334 os.remove(dbfile)
6335 dev[0].request("SET pmf 0")
6336
6337 def test_ap_hs20_release_number_1(dev, apdev):
6338 """Hotspot 2.0 with AP claiming support for Release 1"""
6339 run_ap_hs20_release_number(dev, apdev, 1)
6340
6341 def test_ap_hs20_release_number_2(dev, apdev):
6342 """Hotspot 2.0 with AP claiming support for Release 2"""
6343 run_ap_hs20_release_number(dev, apdev, 2)
6344
6345 def test_ap_hs20_release_number_3(dev, apdev):
6346 """Hotspot 2.0 with AP claiming support for Release 3"""
6347 run_ap_hs20_release_number(dev, apdev, 3)
6348
6349 def run_ap_hs20_release_number(dev, apdev, release):
6350 check_eap_capa(dev[0], "MSCHAPV2")
6351 eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user",
6352 release=release)
6353 rel = dev[0].get_status_field('hs20')
6354 if rel != str(release):
6355 raise Exception("Unexpected release number indicated: " + rel)
6356
6357 def test_ap_hs20_missing_pmf(dev, apdev):
6358 """Hotspot 2.0 connection attempt without PMF"""
6359 check_eap_capa(dev[0], "MSCHAPV2")
6360 bssid = apdev[0]['bssid']
6361 params = hs20_ap_params()
6362 params['hessid'] = bssid
6363 params['disable_dgaf'] = '1'
6364 hostapd.add_ap(apdev[0], params)
6365
6366 dev[0].hs20_enable()
6367 dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
6368 ieee80211w="0",
6369 identity="hs20-test", password="password",
6370 ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6371 scan_freq="2412", update_identifier="54321",
6372 roaming_consortium_selection="1020304050",
6373 wait_connect=False)
6374 ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
6375 dev[0].request("DISCONNECT")
6376 if ev is None:
6377 raise Exception("Association rejection not reported")
6378 if "status_code=31" not in ev:
6379 raise Exception("Unexpected rejection reason: " + ev)
6380
6381 def test_ap_hs20_open_osu_association(dev, apdev):
6382 """Hotspot 2.0 open OSU association"""
6383 try:
6384 run_ap_hs20_open_osu_association(dev, apdev)
6385 finally:
6386 dev[0].request("VENDOR_ELEM_REMOVE 13 *")
6387
6388 def run_ap_hs20_open_osu_association(dev, apdev):
6389 params = {"ssid": "HS 2.0 OSU open"}
6390 hostapd.add_ap(apdev[0], params)
6391 dev[0].connect("HS 2.0 OSU open", key_mgmt="NONE", scan_freq="2412")
6392 dev[0].request("REMOVE_NETWORK all")
6393 dev[0].wait_disconnected()
6394 dev[0].dump_monitor()
6395 # Test with unexpected Hotspot 2.0 Indication element in Assoc Req
6396 dev[0].request("VENDOR_ELEM_ADD 13 dd07506f9a10220000")
6397 dev[0].connect("HS 2.0 OSU open", key_mgmt="NONE", scan_freq="2412")