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