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