1# GAS tests 2# Copyright (c) 2013, Qualcomm Atheros, Inc. 3# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi> 4# 5# This software may be distributed under the terms of the BSD license. 6# See README for more details. 7 8from remotehost import remote_compatible 9import time 10import binascii 11import logging 12logger = logging.getLogger() 13import os 14import re 15import struct 16 17import hostapd 18from wpasupplicant import WpaSupplicant 19from tshark import run_tshark 20from utils import * 21from hwsim import HWSimRadio 22 23def hs20_ap_params(): 24 params = hostapd.wpa2_params(ssid="test-gas") 25 params['wpa_key_mgmt'] = "WPA-EAP" 26 params['ieee80211w'] = "1" 27 params['ieee8021x'] = "1" 28 params['auth_server_addr'] = "127.0.0.1" 29 params['auth_server_port'] = "1812" 30 params['auth_server_shared_secret'] = "radius" 31 params['interworking'] = "1" 32 params['access_network_type'] = "14" 33 params['internet'] = "1" 34 params['asra'] = "0" 35 params['esr'] = "0" 36 params['uesa'] = "0" 37 params['venue_group'] = "7" 38 params['venue_type'] = "1" 39 params['venue_name'] = ["eng:Example venue", "fin:Esimerkkipaikka"] 40 params['roaming_consortium'] = ["112233", "1020304050", "010203040506", 41 "fedcba"] 42 params['domain_name'] = "example.com,another.example.com" 43 params['nai_realm'] = ["0,example.com,13[5:6],21[2:4][5:7]", 44 "0,another.example.com"] 45 params['anqp_3gpp_cell_net'] = "244,91" 46 params['network_auth_type'] = "02http://www.example.com/redirect/me/here/" 47 params['ipaddr_type_availability'] = "14" 48 params['hs20'] = "1" 49 params['hs20_oper_friendly_name'] = ["eng:Example operator", "fin:Esimerkkioperaattori"] 50 params['hs20_wan_metrics'] = "01:8000:1000:80:240:3000" 51 params['hs20_conn_capab'] = ["1:0:2", "6:22:1", "17:5060:0"] 52 params['hs20_operating_class'] = "5173" 53 return params 54 55def start_ap(ap): 56 params = hs20_ap_params() 57 params['hessid'] = ap['bssid'] 58 return hostapd.add_ap(ap, params) 59 60def get_gas_response(dev, bssid, info, allow_fetch_failure=False, 61 extra_test=False): 62 exp = r'<.>(GAS-RESPONSE-INFO) addr=([0-9a-f:]*) dialog_token=([0-9]*) status_code=([0-9]*) resp_len=([\-0-9]*)' 63 res = re.split(exp, info) 64 if len(res) < 6: 65 raise Exception("Could not parse GAS-RESPONSE-INFO") 66 if res[2] != bssid: 67 raise Exception("Unexpected BSSID in response") 68 token = res[3] 69 status = res[4] 70 if status != "0": 71 raise Exception("GAS query failed") 72 resp_len = res[5] 73 if resp_len == "-1": 74 raise Exception("GAS query reported invalid response length") 75 if int(resp_len) > 2000: 76 raise Exception("Unexpected long GAS response") 77 78 if extra_test: 79 if "FAIL" not in dev.request("GAS_RESPONSE_GET " + bssid + " 123456"): 80 raise Exception("Invalid dialog token accepted") 81 if "FAIL-Invalid range" not in dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 10000,10001"): 82 raise Exception("Invalid range accepted") 83 if "FAIL-Invalid range" not in dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 0,10000"): 84 raise Exception("Invalid range accepted") 85 if "FAIL" not in dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 0"): 86 raise Exception("Invalid GAS_RESPONSE_GET accepted") 87 88 res1_2 = dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 1,2") 89 res5_3 = dev.request("GAS_RESPONSE_GET " + bssid + " " + token + " 5,3") 90 91 resp = dev.request("GAS_RESPONSE_GET " + bssid + " " + token) 92 if "FAIL" in resp: 93 if allow_fetch_failure: 94 logger.debug("GAS response was not available anymore") 95 return 96 raise Exception("Could not fetch GAS response") 97 if len(resp) != int(resp_len) * 2: 98 raise Exception("Unexpected GAS response length") 99 logger.debug("GAS response: " + resp) 100 if extra_test: 101 if resp[2:6] != res1_2: 102 raise Exception("Unexpected response substring res1_2: " + res1_2) 103 if resp[10:16] != res5_3: 104 raise Exception("Unexpected response substring res5_3: " + res5_3) 105 106def test_gas_generic(dev, apdev): 107 """Generic GAS query""" 108 bssid = apdev[0]['bssid'] 109 params = hs20_ap_params() 110 params['hessid'] = bssid 111 hostapd.add_ap(apdev[0], params) 112 113 cmds = ["foo", 114 "00:11:22:33:44:55", 115 "00:11:22:33:44:55 ", 116 "00:11:22:33:44:55 ", 117 "00:11:22:33:44:55 1", 118 "00:11:22:33:44:55 1 1234", 119 "00:11:22:33:44:55 qq", 120 "00:11:22:33:44:55 qq 1234", 121 "00:11:22:33:44:55 00 1", 122 "00:11:22:33:44:55 00 123", 123 "00:11:22:33:44:55 00 ", 124 "00:11:22:33:44:55 00 qq"] 125 for cmd in cmds: 126 if "FAIL" not in dev[0].request("GAS_REQUEST " + cmd): 127 raise Exception("Invalid GAS_REQUEST accepted: " + cmd) 128 129 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 130 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101") 131 if "FAIL" in req: 132 raise Exception("GAS query request rejected") 133 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 134 if ev is None: 135 raise Exception("GAS query timed out") 136 get_gas_response(dev[0], bssid, ev, extra_test=True) 137 138 if "FAIL" not in dev[0].request("GAS_RESPONSE_GET ff"): 139 raise Exception("Invalid GAS_RESPONSE_GET accepted") 140 141def test_gas_rand_ta(dev, apdev, params): 142 """Generic GAS query with random TA""" 143 flags = int(dev[0].get_driver_status_field('capa.flags'), 16) 144 if flags & 0x0000400000000000 == 0: 145 raise HwsimSkip("Driver does not support random GAS TA") 146 147 try: 148 _test_gas_rand_ta(dev, apdev, params['logdir']) 149 finally: 150 dev[0].request("SET gas_rand_mac_addr 0") 151 152def _test_gas_rand_ta(dev, apdev, logdir): 153 bssid = apdev[0]['bssid'] 154 params = hs20_ap_params() 155 params['hessid'] = bssid 156 hostapd.add_ap(apdev[0], params) 157 158 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 159 req = dev[0].request("SET gas_rand_mac_addr 1") 160 if "FAIL" in req: 161 raise Exception("Failed to set gas_rand_mac_addr") 162 163 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 164 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101") 165 if "FAIL" in req: 166 raise Exception("GAS query request rejected") 167 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 168 if ev is None: 169 raise Exception("GAS query timed out") 170 get_gas_response(dev[0], bssid, ev, extra_test=True) 171 172 time.sleep(1) 173 out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"), 174 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 175 display=["wlan.ta", "wlan.ra"]) 176 logger.info("tshark output:\n" + out) 177 res = out.splitlines() 178 if len(res) != 2: 179 logger.info("res: " + str(res)) 180 raise Exception("Unexpected number of GAS frames") 181 req_ta = res[0].split('\t')[0] 182 resp_ra = res[1].split('\t')[1] 183 logger.info("Request TA: %s, Response RA: %s" % (req_ta, resp_ra)) 184 if req_ta != resp_ra: 185 raise Exception("Request TA does not match response RA") 186 if req_ta == dev[0].own_addr(): 187 raise Exception("Request TA was own permanent MAC address, not random") 188 189def test_gas_concurrent_scan(dev, apdev): 190 """Generic GAS queries with concurrent scan operation""" 191 bssid = apdev[0]['bssid'] 192 params = hs20_ap_params() 193 params['hessid'] = bssid 194 hapd = hostapd.add_ap(apdev[0], params) 195 196 # get BSS entry available to allow GAS query 197 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 198 199 logger.info("Request concurrent operations") 200 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101") 201 if "FAIL" in req: 202 raise Exception("GAS query request rejected") 203 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000801") 204 if "FAIL" in req: 205 raise Exception("GAS query request rejected") 206 dev[0].scan(no_wait=True) 207 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000201") 208 if "FAIL" in req: 209 raise Exception("GAS query request rejected") 210 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000501") 211 if "FAIL" in req: 212 raise Exception("GAS query request rejected") 213 214 responses = 0 215 for i in range(0, 5): 216 ev = dev[0].wait_event(["GAS-RESPONSE-INFO", "CTRL-EVENT-SCAN-RESULTS"], 217 timeout=10) 218 if ev is None: 219 raise Exception("Operation timed out") 220 if "GAS-RESPONSE-INFO" in ev: 221 responses = responses + 1 222 get_gas_response(dev[0], bssid, ev, allow_fetch_failure=True) 223 224 if responses != 4: 225 raise Exception("Unexpected number of GAS responses") 226 227 # Try to get all GAS frames into the sniffer capture of this test case. 228 hapd.disable() 229 time.sleep(0.1) 230 231def test_gas_concurrent_connect(dev, apdev): 232 """Generic GAS queries with concurrent connection operation""" 233 skip_with_fips(dev[0]) 234 bssid = apdev[0]['bssid'] 235 params = hs20_ap_params() 236 params['hessid'] = bssid 237 hapd = hostapd.add_ap(apdev[0], params) 238 239 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 240 241 logger.debug("Start concurrent connect and GAS request") 242 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 243 identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls", 244 password="password", phase2="auth=MSCHAPV2", 245 ca_cert="auth_serv/ca.pem", wait_connect=False, 246 scan_freq="2412") 247 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101") 248 if "FAIL" in req: 249 raise Exception("GAS query request rejected") 250 251 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "GAS-RESPONSE-INFO"], 252 timeout=20) 253 if ev is None: 254 raise Exception("Operation timed out") 255 if "CTRL-EVENT-CONNECTED" not in ev: 256 raise Exception("Unexpected operation order") 257 258 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "GAS-RESPONSE-INFO"], 259 timeout=20) 260 if ev is None: 261 raise Exception("Operation timed out") 262 if "GAS-RESPONSE-INFO" not in ev: 263 raise Exception("Unexpected operation order") 264 get_gas_response(dev[0], bssid, ev) 265 266 hapd.wait_sta() 267 dev[0].request("DISCONNECT") 268 dev[0].wait_disconnected(timeout=5) 269 hapd.wait_sta_disconnect() 270 271 logger.debug("Wait six seconds for expiration of connect-without-scan") 272 time.sleep(6) 273 dev[0].dump_monitor() 274 275 logger.debug("Start concurrent GAS request and connect") 276 req = dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101") 277 if "FAIL" in req: 278 raise Exception("GAS query request rejected") 279 dev[0].request("RECONNECT") 280 281 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 282 if ev is None: 283 raise Exception("Operation timed out") 284 get_gas_response(dev[0], bssid, ev) 285 286 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=20) 287 if ev is None: 288 raise Exception("No new scan results reported") 289 290 ev = dev[0].wait_connected(timeout=20, error="Operation timed out") 291 if "CTRL-EVENT-CONNECTED" not in ev: 292 raise Exception("Unexpected operation order") 293 294def gas_fragment_and_comeback(dev, apdev, frag_limit=0, comeback_delay=0): 295 hapd = start_ap(apdev) 296 if frag_limit: 297 hapd.set("gas_frag_limit", str(frag_limit)) 298 if comeback_delay: 299 hapd.set("gas_comeback_delay", str(comeback_delay)) 300 301 dev.scan_for_bss(apdev['bssid'], freq="2412", force_scan=True) 302 dev.request("FETCH_ANQP") 303 ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=5) 304 if ev is None: 305 raise Exception("No GAS-QUERY-DONE event") 306 if "result=SUCCESS" not in ev: 307 raise Exception("Unexpected GAS result: " + ev) 308 for i in range(0, 13): 309 ev = dev.wait_event(["RX-ANQP", "RX-HS20-ANQP"], timeout=5) 310 if ev is None: 311 raise Exception("Operation timed out") 312 ev = dev.wait_event(["ANQP-QUERY-DONE"], timeout=1) 313 if ev is None: 314 raise Exception("No ANQP-QUERY-DONE event") 315 if "result=SUCCESS" not in ev: 316 raise Exception("Unexpected ANQP result: " + ev) 317 318def test_gas_fragment(dev, apdev): 319 """GAS fragmentation""" 320 gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50) 321 322def test_gas_fragment_mcc(dev, apdev): 323 """GAS fragmentation with mac80211_hwsim MCC enabled""" 324 with HWSimRadio(n_channels=2) as (radio, iface): 325 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 326 wpas.interface_add(iface) 327 gas_fragment_and_comeback(wpas, apdev[0], frag_limit=50) 328 329def test_gas_fragment_with_comeback_delay(dev, apdev): 330 """GAS fragmentation and comeback delay""" 331 gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50, 332 comeback_delay=500) 333 334def test_gas_fragment_with_comeback_delay_mcc(dev, apdev): 335 """GAS fragmentation and comeback delay with mac80211_hwsim MCC enabled""" 336 with HWSimRadio(n_channels=2) as (radio, iface): 337 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 338 wpas.interface_add(iface) 339 gas_fragment_and_comeback(wpas, apdev[0], frag_limit=50, 340 comeback_delay=500) 341 342def test_gas_comeback_delay(dev, apdev): 343 """GAS comeback delay""" 344 run_gas_comeback_delay(dev, apdev, 500) 345 346def test_gas_comeback_delay_long(dev, apdev): 347 """GAS long comeback delay""" 348 run_gas_comeback_delay(dev, apdev, 2500) 349 350def test_gas_comeback_delay_long2(dev, apdev): 351 """GAS long comeback delay over default STA timeout""" 352 run_gas_comeback_delay(dev, apdev, 6000) 353 354def run_gas_comeback_delay(dev, apdev, delay): 355 hapd = start_ap(apdev[0]) 356 hapd.set("gas_comeback_delay", str(delay)) 357 358 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) 359 dev[0].request("FETCH_ANQP") 360 if "FAIL-BUSY" not in dev[0].request("SCAN"): 361 raise Exception("SCAN accepted during FETCH_ANQP") 362 for i in range(0, 6): 363 ev = dev[0].wait_event(["RX-ANQP"], timeout=10) 364 if ev is None: 365 raise Exception("Operation timed out") 366 367@remote_compatible 368def test_gas_stop_fetch_anqp(dev, apdev): 369 """Stop FETCH_ANQP operation""" 370 hapd = start_ap(apdev[0]) 371 372 dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) 373 hapd.set("ext_mgmt_frame_handling", "1") 374 dev[0].request("FETCH_ANQP") 375 dev[0].request("STOP_FETCH_ANQP") 376 hapd.set("ext_mgmt_frame_handling", "0") 377 ev = dev[0].wait_event(["RX-ANQP", "GAS-QUERY-DONE"], timeout=10) 378 if ev is None: 379 raise Exception("GAS-QUERY-DONE timed out") 380 if "RX-ANQP" in ev: 381 raise Exception("Unexpected ANQP response received") 382 383def test_gas_anqp_get(dev, apdev): 384 """GAS/ANQP query for both IEEE 802.11 and Hotspot 2.0 elements""" 385 hapd = start_ap(apdev[0]) 386 bssid = apdev[0]['bssid'] 387 388 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 389 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258,268,hs20:3,hs20:4"): 390 raise Exception("ANQP_GET command failed") 391 392 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 393 if ev is None: 394 raise Exception("GAS query start timed out") 395 396 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 397 if ev is None: 398 raise Exception("GAS query timed out") 399 400 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 401 if ev is None or "Venue Name" not in ev: 402 raise Exception("Did not receive Venue Name") 403 404 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 405 if ev is None or "Domain Name list" not in ev: 406 raise Exception("Did not receive Domain Name list") 407 408 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1) 409 if ev is None or "Operator Friendly Name" not in ev: 410 raise Exception("Did not receive Operator Friendly Name") 411 412 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1) 413 if ev is None or "WAN Metrics" not in ev: 414 raise Exception("Did not receive WAN Metrics") 415 416 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 417 if ev is None: 418 raise Exception("ANQP-QUERY-DONE event not seen") 419 if "result=SUCCESS" not in ev: 420 raise Exception("Unexpected result: " + ev) 421 422 if "OK" not in dev[0].request("ANQP_GET " + bssid + " hs20:3"): 423 raise Exception("ANQP_GET command failed") 424 425 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 426 if ev is None: 427 raise Exception("GAS query start timed out") 428 429 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 430 if ev is None: 431 raise Exception("GAS query timed out") 432 433 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1) 434 if ev is None or "Operator Friendly Name" not in ev: 435 raise Exception("Did not receive Operator Friendly Name") 436 437 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 438 if ev is None: 439 raise Exception("ANQP-QUERY-DONE event not seen") 440 if "result=SUCCESS" not in ev: 441 raise Exception("Unexpected result: " + ev) 442 443 if "OK" not in dev[0].request("HS20_ANQP_GET " + bssid + " 3,4"): 444 raise Exception("ANQP_GET command failed") 445 446 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1) 447 if ev is None or "Operator Friendly Name" not in ev: 448 raise Exception("Did not receive Operator Friendly Name") 449 450 ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=1) 451 if ev is None or "WAN Metrics" not in ev: 452 raise Exception("Did not receive WAN Metrics") 453 454 logger.info("Attempt an MBO request with an AP that does not support MBO") 455 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 272,mbo:2"): 456 raise Exception("ANQP_GET command failed (2)") 457 458 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 459 if ev is None: 460 raise Exception("GAS query start timed out (2)") 461 462 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 463 if ev is None: 464 raise Exception("GAS query timed out (2)") 465 466 cmds = ["", 467 "foo", 468 "00:11:22:33:44:55 258,hs20:-1", 469 "00:11:22:33:44:55 258,hs20:0", 470 "00:11:22:33:44:55 258,hs20:32", 471 "00:11:22:33:44:55 hs20:-1", 472 "00:11:22:33:44:55 hs20:0", 473 "00:11:22:33:44:55 hs20:32", 474 "00:11:22:33:44:55 mbo:-1", 475 "00:11:22:33:44:55 mbo:0", 476 "00:11:22:33:44:55 mbo:999", 477 "00:11:22:33:44:55 mbo:1,258,mbo:2,mbo:3,259", 478 "00:11:22:33:44:55", 479 "00:11:22:33:44:55 ", 480 "00:11:22:33:44:55 0", 481 "00:11:22:33:44:55 1"] 482 for cmd in cmds: 483 if "FAIL" not in dev[0].request("ANQP_GET " + cmd): 484 raise Exception("Invalid ANQP_GET accepted") 485 486 cmds = ["", 487 "foo", 488 "00:11:22:33:44:55 -1", 489 "00:11:22:33:44:55 0", 490 "00:11:22:33:44:55 32", 491 "00:11:22:33:44:55", 492 "00:11:22:33:44:55 ", 493 "00:11:22:33:44:55 0", 494 "00:11:22:33:44:55 1"] 495 for cmd in cmds: 496 if "FAIL" not in dev[0].request("HS20_ANQP_GET " + cmd): 497 raise Exception("Invalid HS20_ANQP_GET accepted") 498 499def test_gas_anqp_get_no_scan(dev, apdev): 500 """GAS/ANQP query without scan""" 501 hapd = start_ap(apdev[0]) 502 bssid = apdev[0]['bssid'] 503 if "OK" not in dev[0].request("ANQP_GET " + bssid + " freq=2412 258"): 504 raise Exception("ANQP_GET command failed") 505 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 506 if ev is None: 507 raise Exception("ANQP query timed out") 508 dev[0].dump_monitor() 509 510 if "OK" not in dev[0].request("ANQP_GET 02:11:22:33:44:55 freq=2417 258"): 511 raise Exception("ANQP_GET command failed") 512 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 513 if ev is None: 514 raise Exception("ANQP query timed out [2]") 515 if "result=FAILURE" not in ev: 516 raise Exception("Unexpected result: " + ev) 517 518def test_gas_anqp_get_oom(dev, apdev): 519 """GAS/ANQP query OOM""" 520 hapd = start_ap(apdev[0]) 521 bssid = apdev[0]['bssid'] 522 523 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 524 with alloc_fail(dev[0], 1, "wpabuf_alloc;anqp_send_req"): 525 if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258,268,hs20:3,hs20:4"): 526 raise Exception("ANQP_GET command accepted during OOM") 527 with alloc_fail(dev[0], 1, "hs20_build_anqp_req;hs20_anqp_send_req"): 528 if "FAIL" not in dev[0].request("HS20_ANQP_GET " + bssid + " 1"): 529 raise Exception("HS20_ANQP_GET command accepted during OOM") 530 with alloc_fail(dev[0], 1, "gas_query_req;hs20_anqp_send_req"): 531 if "FAIL" not in dev[0].request("HS20_ANQP_GET " + bssid + " 1"): 532 raise Exception("HS20_ANQP_GET command accepted during OOM") 533 534def test_gas_anqp_hs20_proto(dev, apdev): 535 """GAS/ANQP and Hotspot 2.0 element protocol testing""" 536 hapd = start_ap(apdev[0]) 537 bssid = apdev[0]['bssid'] 538 539 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 540 hapd.set("ext_mgmt_frame_handling", "1") 541 542 tests = ['00', '0100', '0201', '0300', '0400', '0500', '0600', '0700', 543 '0800', '0900', '0a00', '0b0000000000'] 544 for test in tests: 545 dev[0].request("HS20_ANQP_GET " + bssid + " 3,4") 546 query = gas_rx(hapd) 547 gas = parse_gas(query['payload']) 548 resp = action_response(query) 549 data = binascii.unhexlify(test) 550 data = binascii.unhexlify('506f9a11') + data 551 data = struct.pack('<HHH', len(data) + 4, 0xdddd, len(data)) + data 552 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + data 553 send_gas_resp(hapd, resp) 554 expect_gas_result(dev[0], "SUCCESS") 555 556def expect_gas_result(dev, result, status=None): 557 ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=10) 558 if ev is None: 559 raise Exception("GAS query timed out") 560 if "result=" + result not in ev: 561 raise Exception("Unexpected GAS query result") 562 if status and "status_code=" + str(status) + ' ' not in ev: 563 raise Exception("Unexpected GAS status code") 564 565def anqp_get(dev, bssid, id): 566 if "OK" not in dev.request("ANQP_GET " + bssid + " " + str(id)): 567 raise Exception("ANQP_GET command failed") 568 ev = dev.wait_event(["GAS-QUERY-START"], timeout=5) 569 if ev is None: 570 raise Exception("GAS query start timed out") 571 572def test_gas_timeout(dev, apdev): 573 """GAS timeout""" 574 hapd = start_ap(apdev[0]) 575 bssid = apdev[0]['bssid'] 576 577 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 578 hapd.set("ext_mgmt_frame_handling", "1") 579 580 anqp_get(dev[0], bssid, 263) 581 582 ev = hapd.wait_event(["MGMT-RX"], timeout=5) 583 if ev is None: 584 raise Exception("MGMT RX wait timed out") 585 586 expect_gas_result(dev[0], "TIMEOUT") 587 588MGMT_SUBTYPE_ACTION = 13 589ACTION_CATEG_PUBLIC = 4 590 591GAS_INITIAL_REQUEST = 10 592GAS_INITIAL_RESPONSE = 11 593GAS_COMEBACK_REQUEST = 12 594GAS_COMEBACK_RESPONSE = 13 595GAS_ACTIONS = [GAS_INITIAL_REQUEST, GAS_INITIAL_RESPONSE, 596 GAS_COMEBACK_REQUEST, GAS_COMEBACK_RESPONSE] 597 598def anqp_adv_proto(): 599 return struct.pack('BBBB', 108, 2, 127, 0) 600 601def anqp_initial_resp(dialog_token, status_code, comeback_delay=0): 602 return struct.pack('<BBBHH', ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE, 603 dialog_token, status_code, comeback_delay) + anqp_adv_proto() 604 605def anqp_comeback_resp(dialog_token, status_code=0, id=0, more=False, comeback_delay=0, bogus_adv_proto=False): 606 if more: 607 id |= 0x80 608 if bogus_adv_proto: 609 adv = struct.pack('BBBB', 108, 2, 127, 1) 610 else: 611 adv = anqp_adv_proto() 612 return struct.pack('<BBBHBH', ACTION_CATEG_PUBLIC, GAS_COMEBACK_RESPONSE, 613 dialog_token, status_code, id, comeback_delay) + adv 614 615def gas_rx(hapd): 616 count = 0 617 while count < 30: 618 count = count + 1 619 query = hapd.mgmt_rx() 620 if query is None: 621 raise Exception("Action frame not received") 622 if query['subtype'] != MGMT_SUBTYPE_ACTION: 623 continue 624 payload = query['payload'] 625 if len(payload) < 2: 626 continue 627 (category, action) = struct.unpack('BB', payload[0:2]) 628 if category != ACTION_CATEG_PUBLIC or action not in GAS_ACTIONS: 629 continue 630 return query 631 raise Exception("No Action frame received") 632 633def parse_gas(payload): 634 pos = payload 635 (category, action, dialog_token) = struct.unpack('BBB', pos[0:3]) 636 if category != ACTION_CATEG_PUBLIC: 637 return None 638 if action not in GAS_ACTIONS: 639 return None 640 gas = {} 641 gas['action'] = action 642 pos = pos[3:] 643 644 if len(pos) < 1 and action != GAS_COMEBACK_REQUEST: 645 return None 646 647 gas['dialog_token'] = dialog_token 648 649 if action == GAS_INITIAL_RESPONSE: 650 if len(pos) < 4: 651 return None 652 (status_code, comeback_delay) = struct.unpack('<HH', pos[0:4]) 653 gas['status_code'] = status_code 654 gas['comeback_delay'] = comeback_delay 655 656 if action == GAS_COMEBACK_RESPONSE: 657 if len(pos) < 5: 658 return None 659 (status_code, frag, comeback_delay) = struct.unpack('<HBH', pos[0:5]) 660 gas['status_code'] = status_code 661 gas['frag'] = frag 662 gas['comeback_delay'] = comeback_delay 663 664 return gas 665 666def action_response(req): 667 resp = {} 668 resp['fc'] = req['fc'] 669 resp['da'] = req['sa'] 670 resp['sa'] = req['da'] 671 resp['bssid'] = req['bssid'] 672 return resp 673 674def send_gas_resp(hapd, resp): 675 hapd.mgmt_tx(resp) 676 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 677 if ev is None: 678 raise Exception("Missing TX status for GAS response") 679 if "ok=1" not in ev: 680 raise Exception("GAS response not acknowledged") 681 682def test_gas_invalid_response_type(dev, apdev): 683 """GAS invalid response type""" 684 hapd = start_ap(apdev[0]) 685 bssid = apdev[0]['bssid'] 686 687 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 688 hapd.set("ext_mgmt_frame_handling", "1") 689 690 anqp_get(dev[0], bssid, 263) 691 692 query = gas_rx(hapd) 693 gas = parse_gas(query['payload']) 694 695 resp = action_response(query) 696 # GAS Comeback Response instead of GAS Initial Response 697 resp['payload'] = anqp_comeback_resp(gas['dialog_token']) + struct.pack('<H', 0) 698 send_gas_resp(hapd, resp) 699 700 # station drops the invalid frame, so this needs to result in GAS timeout 701 expect_gas_result(dev[0], "TIMEOUT") 702 703def test_gas_failure_status_code(dev, apdev): 704 """GAS failure status code""" 705 hapd = start_ap(apdev[0]) 706 bssid = apdev[0]['bssid'] 707 708 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 709 hapd.set("ext_mgmt_frame_handling", "1") 710 711 anqp_get(dev[0], bssid, 263) 712 713 query = gas_rx(hapd) 714 gas = parse_gas(query['payload']) 715 716 resp = action_response(query) 717 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 61) + struct.pack('<H', 0) 718 send_gas_resp(hapd, resp) 719 720 expect_gas_result(dev[0], "FAILURE") 721 722def test_gas_malformed(dev, apdev): 723 """GAS malformed response frames""" 724 hapd = start_ap(apdev[0]) 725 bssid = apdev[0]['bssid'] 726 727 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 728 hapd.set("ext_mgmt_frame_handling", "1") 729 730 anqp_get(dev[0], bssid, 263) 731 732 query = gas_rx(hapd) 733 gas = parse_gas(query['payload']) 734 735 resp = action_response(query) 736 737 resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC, 738 GAS_COMEBACK_RESPONSE, 739 gas['dialog_token'], 0) 740 hapd.mgmt_tx(resp) 741 742 resp['payload'] = struct.pack('<BBBHB', ACTION_CATEG_PUBLIC, 743 GAS_COMEBACK_RESPONSE, 744 gas['dialog_token'], 0, 0) 745 hapd.mgmt_tx(resp) 746 747 hdr = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE, 748 gas['dialog_token'], 0, 0) 749 resp['payload'] = hdr + struct.pack('B', 108) 750 hapd.mgmt_tx(resp) 751 resp['payload'] = hdr + struct.pack('BB', 108, 0) 752 hapd.mgmt_tx(resp) 753 resp['payload'] = hdr + struct.pack('BB', 108, 1) 754 hapd.mgmt_tx(resp) 755 resp['payload'] = hdr + struct.pack('BB', 108, 255) 756 hapd.mgmt_tx(resp) 757 resp['payload'] = hdr + struct.pack('BBB', 108, 1, 127) 758 hapd.mgmt_tx(resp) 759 resp['payload'] = hdr + struct.pack('BBB', 108, 2, 127) 760 hapd.mgmt_tx(resp) 761 resp['payload'] = hdr + struct.pack('BBBB', 0, 2, 127, 0) 762 hapd.mgmt_tx(resp) 763 764 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<H', 1) 765 hapd.mgmt_tx(resp) 766 767 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<HB', 2, 0) 768 hapd.mgmt_tx(resp) 769 770 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<H', 65535) 771 hapd.mgmt_tx(resp) 772 773 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<HBB', 1, 0, 0) 774 hapd.mgmt_tx(resp) 775 776 # Station drops invalid frames, but the last of the responses is valid from 777 # GAS view point even though it has an extra octet in the end and the ANQP 778 # part of the response is not valid. This is reported as successfully 779 # completed GAS exchange. 780 expect_gas_result(dev[0], "SUCCESS") 781 782 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5) 783 if ev is None: 784 raise Exception("ANQP-QUERY-DONE not reported") 785 if "result=INVALID_FRAME" not in ev: 786 raise Exception("Unexpected result: " + ev) 787 788def init_gas(hapd, bssid, dev): 789 anqp_get(dev, bssid, 263) 790 query = gas_rx(hapd) 791 gas = parse_gas(query['payload']) 792 dialog_token = gas['dialog_token'] 793 794 resp = action_response(query) 795 resp['payload'] = anqp_initial_resp(dialog_token, 0, comeback_delay=1) + struct.pack('<H', 0) 796 send_gas_resp(hapd, resp) 797 798 query = gas_rx(hapd) 799 gas = parse_gas(query['payload']) 800 if gas['action'] != GAS_COMEBACK_REQUEST: 801 raise Exception("Unexpected request action") 802 if gas['dialog_token'] != dialog_token: 803 raise Exception("Unexpected dialog token change") 804 return query, dialog_token 805 806def allow_gas_initial_req(hapd, dialog_token): 807 msg = hapd.mgmt_rx(timeout=1) 808 if msg is not None: 809 gas = parse_gas(msg['payload']) 810 if gas['action'] != GAS_INITIAL_REQUEST or dialog_token == gas['dialog_token']: 811 raise Exception("Unexpected management frame") 812 813def test_gas_malformed_comeback_resp(dev, apdev): 814 """GAS malformed comeback response frames""" 815 hapd = start_ap(apdev[0]) 816 bssid = apdev[0]['bssid'] 817 818 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 819 hapd.set("ext_mgmt_frame_handling", "1") 820 821 logger.debug("Non-zero status code in comeback response") 822 query, dialog_token = init_gas(hapd, bssid, dev[0]) 823 resp = action_response(query) 824 resp['payload'] = anqp_comeback_resp(dialog_token, status_code=2) + struct.pack('<H', 0) 825 send_gas_resp(hapd, resp) 826 expect_gas_result(dev[0], "FAILURE", status=2) 827 828 logger.debug("Different advertisement protocol in comeback response") 829 query, dialog_token = init_gas(hapd, bssid, dev[0]) 830 resp = action_response(query) 831 resp['payload'] = anqp_comeback_resp(dialog_token, bogus_adv_proto=True) + struct.pack('<H', 0) 832 send_gas_resp(hapd, resp) 833 expect_gas_result(dev[0], "PEER_ERROR") 834 835 logger.debug("Non-zero frag id and comeback delay in comeback response") 836 query, dialog_token = init_gas(hapd, bssid, dev[0]) 837 resp = action_response(query) 838 resp['payload'] = anqp_comeback_resp(dialog_token, id=1, comeback_delay=1) + struct.pack('<H', 0) 839 send_gas_resp(hapd, resp) 840 expect_gas_result(dev[0], "PEER_ERROR") 841 842 logger.debug("Unexpected frag id in comeback response") 843 query, dialog_token = init_gas(hapd, bssid, dev[0]) 844 resp = action_response(query) 845 resp['payload'] = anqp_comeback_resp(dialog_token, id=1) + struct.pack('<H', 0) 846 send_gas_resp(hapd, resp) 847 expect_gas_result(dev[0], "PEER_ERROR") 848 849 logger.debug("Empty fragment and replay in comeback response") 850 query, dialog_token = init_gas(hapd, bssid, dev[0]) 851 resp = action_response(query) 852 resp['payload'] = anqp_comeback_resp(dialog_token, more=True) + struct.pack('<H', 0) 853 send_gas_resp(hapd, resp) 854 query = gas_rx(hapd) 855 gas = parse_gas(query['payload']) 856 if gas['action'] != GAS_COMEBACK_REQUEST: 857 raise Exception("Unexpected request action") 858 if gas['dialog_token'] != dialog_token: 859 raise Exception("Unexpected dialog token change") 860 resp = action_response(query) 861 resp['payload'] = anqp_comeback_resp(dialog_token) + struct.pack('<H', 0) 862 send_gas_resp(hapd, resp) 863 resp['payload'] = anqp_comeback_resp(dialog_token, id=1) + struct.pack('<H', 0) 864 send_gas_resp(hapd, resp) 865 expect_gas_result(dev[0], "SUCCESS") 866 867 logger.debug("Unexpected initial response when waiting for comeback response") 868 query, dialog_token = init_gas(hapd, bssid, dev[0]) 869 resp = action_response(query) 870 resp['payload'] = anqp_initial_resp(dialog_token, 0) + struct.pack('<H', 0) 871 send_gas_resp(hapd, resp) 872 allow_gas_initial_req(hapd, dialog_token) 873 expect_gas_result(dev[0], "TIMEOUT") 874 875 logger.debug("Too short comeback response") 876 query, dialog_token = init_gas(hapd, bssid, dev[0]) 877 resp = action_response(query) 878 resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC, 879 GAS_COMEBACK_RESPONSE, dialog_token, 0) 880 send_gas_resp(hapd, resp) 881 allow_gas_initial_req(hapd, dialog_token) 882 expect_gas_result(dev[0], "TIMEOUT") 883 884 logger.debug("Too short comeback response(2)") 885 query, dialog_token = init_gas(hapd, bssid, dev[0]) 886 resp = action_response(query) 887 resp['payload'] = struct.pack('<BBBHBB', ACTION_CATEG_PUBLIC, 888 GAS_COMEBACK_RESPONSE, dialog_token, 0, 0x80, 889 0) 890 send_gas_resp(hapd, resp) 891 allow_gas_initial_req(hapd, dialog_token) 892 expect_gas_result(dev[0], "TIMEOUT") 893 894 logger.debug("Maximum comeback response fragment claiming more fragments") 895 query, dialog_token = init_gas(hapd, bssid, dev[0]) 896 resp = action_response(query) 897 resp['payload'] = anqp_comeback_resp(dialog_token, more=True) + struct.pack('<H', 0) 898 send_gas_resp(hapd, resp) 899 for i in range(1, 129): 900 query = gas_rx(hapd) 901 gas = parse_gas(query['payload']) 902 if gas['action'] != GAS_COMEBACK_REQUEST: 903 raise Exception("Unexpected request action") 904 if gas['dialog_token'] != dialog_token: 905 raise Exception("Unexpected dialog token change") 906 resp = action_response(query) 907 resp['payload'] = anqp_comeback_resp(dialog_token, id=i, more=True) + struct.pack('<H', 0) 908 send_gas_resp(hapd, resp) 909 expect_gas_result(dev[0], "PEER_ERROR") 910 911def test_gas_comeback_resp_additional_delay(dev, apdev): 912 """GAS comeback response requesting additional delay""" 913 hapd = start_ap(apdev[0]) 914 bssid = apdev[0]['bssid'] 915 916 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 917 hapd.set("ext_mgmt_frame_handling", "1") 918 919 query, dialog_token = init_gas(hapd, bssid, dev[0]) 920 for i in range(0, 2): 921 resp = action_response(query) 922 resp['payload'] = anqp_comeback_resp(dialog_token, status_code=95, comeback_delay=50) + struct.pack('<H', 0) 923 send_gas_resp(hapd, resp) 924 query = gas_rx(hapd) 925 gas = parse_gas(query['payload']) 926 if gas['action'] != GAS_COMEBACK_REQUEST: 927 raise Exception("Unexpected request action") 928 if gas['dialog_token'] != dialog_token: 929 raise Exception("Unexpected dialog token change") 930 resp = action_response(query) 931 resp['payload'] = anqp_comeback_resp(dialog_token, status_code=0) + struct.pack('<H', 0) 932 send_gas_resp(hapd, resp) 933 expect_gas_result(dev[0], "SUCCESS") 934 935def test_gas_unknown_adv_proto(dev, apdev): 936 """Unknown advertisement protocol id""" 937 bssid = apdev[0]['bssid'] 938 params = hs20_ap_params() 939 params['hessid'] = bssid 940 hostapd.add_ap(apdev[0], params) 941 942 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 943 req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101") 944 if "FAIL" in req: 945 raise Exception("GAS query request rejected") 946 expect_gas_result(dev[0], "FAILURE", "59") 947 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 948 if ev is None: 949 raise Exception("GAS query timed out") 950 exp = r'<.>(GAS-RESPONSE-INFO) addr=([0-9a-f:]*) dialog_token=([0-9]*) status_code=([0-9]*) resp_len=([\-0-9]*)' 951 res = re.split(exp, ev) 952 if len(res) < 6: 953 raise Exception("Could not parse GAS-RESPONSE-INFO") 954 if res[2] != bssid: 955 raise Exception("Unexpected BSSID in response") 956 status = res[4] 957 if status != "59": 958 raise Exception("Unexpected GAS-RESPONSE-INFO status") 959 960def test_gas_request_oom(dev, apdev): 961 """GAS_REQUEST OOM""" 962 bssid = apdev[0]['bssid'] 963 params = hs20_ap_params() 964 params['hessid'] = bssid 965 hostapd.add_ap(apdev[0], params) 966 967 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 968 969 with alloc_fail(dev[0], 1, "gas_build_req;gas_send_request"): 970 if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"): 971 raise Exception("GAS query request rejected") 972 973 with alloc_fail(dev[0], 1, "gas_query_req;gas_send_request"): 974 if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"): 975 raise Exception("GAS query request rejected") 976 977 with alloc_fail(dev[0], 1, "wpabuf_dup;gas_resp_cb"): 978 if "OK" not in dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101"): 979 raise Exception("GAS query request rejected") 980 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 981 if ev is None: 982 raise Exception("No GAS response") 983 if "status_code=0" not in ev: 984 raise Exception("GAS response indicated a failure") 985 986def test_gas_max_pending(dev, apdev): 987 """GAS and maximum pending query limit""" 988 hapd = start_ap(apdev[0]) 989 hapd.set("gas_frag_limit", "50") 990 bssid = apdev[0]['bssid'] 991 992 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 993 wpas.interface_add("wlan5") 994 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 995 raise Exception("Failed to set listen channel") 996 if "OK" not in wpas.p2p_listen(): 997 raise Exception("Failed to start listen state") 998 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 999 raise Exception("Failed to enable external management frame handling") 1000 1001 anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268) 1002 gas = struct.pack('<H', len(anqp_query)) + anqp_query 1003 1004 for dialog_token in range(1, 10): 1005 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 1006 dialog_token) + anqp_adv_proto() + gas 1007 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1008 if "OK" not in wpas.request(req): 1009 raise Exception("Could not send management frame") 1010 resp = wpas.mgmt_rx() 1011 if resp is None: 1012 raise Exception("MGMT-RX timeout") 1013 if 'payload' not in resp: 1014 raise Exception("Missing payload") 1015 gresp = parse_gas(resp['payload']) 1016 if gresp['dialog_token'] != dialog_token: 1017 raise Exception("Dialog token mismatch") 1018 status_code = gresp['status_code'] 1019 if dialog_token < 9 and status_code != 0: 1020 raise Exception("Unexpected failure status code {} for dialog token {}".format(status_code, dialog_token)) 1021 if dialog_token > 8 and status_code == 0: 1022 raise Exception("Unexpected success status code {} for dialog token {}".format(status_code, dialog_token)) 1023 1024def test_gas_no_pending(dev, apdev): 1025 """GAS and no pending query for comeback request""" 1026 hapd = start_ap(apdev[0]) 1027 bssid = apdev[0]['bssid'] 1028 1029 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1030 wpas.interface_add("wlan5") 1031 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1032 raise Exception("Failed to set listen channel") 1033 if "OK" not in wpas.p2p_listen(): 1034 raise Exception("Failed to start listen state") 1035 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1036 raise Exception("Failed to enable external management frame handling") 1037 1038 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1) 1039 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1040 if "OK" not in wpas.request(req): 1041 raise Exception("Could not send management frame") 1042 resp = wpas.mgmt_rx() 1043 if resp is None: 1044 raise Exception("MGMT-RX timeout") 1045 if 'payload' not in resp: 1046 raise Exception("Missing payload") 1047 gresp = parse_gas(resp['payload']) 1048 status_code = gresp['status_code'] 1049 if status_code != 60: 1050 raise Exception("Unexpected status code {} (expected 60)".format(status_code)) 1051 1052def test_gas_delete_at_deinit(dev, apdev): 1053 """GAS query deleted at deinit""" 1054 hapd = start_ap(apdev[0]) 1055 hapd.set("gas_comeback_delay", "1000") 1056 bssid = apdev[0]['bssid'] 1057 1058 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1059 wpas.interface_add("wlan5") 1060 wpas.scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) 1061 wpas.request("ANQP_GET " + bssid + " 258") 1062 1063 wpas.global_request("INTERFACE_REMOVE " + wpas.ifname) 1064 ev = wpas.wait_event(["GAS-QUERY-DONE"], timeout=2) 1065 del wpas 1066 if ev is None: 1067 raise Exception("GAS-QUERY-DONE not seen") 1068 if "result=DELETED_AT_DEINIT" not in ev: 1069 raise Exception("Unexpected result code: " + ev) 1070 1071def test_gas_missing_payload(dev, apdev): 1072 """No action code in the query frame""" 1073 bssid = apdev[0]['bssid'] 1074 params = hs20_ap_params() 1075 params['hessid'] = bssid 1076 hostapd.add_ap(apdev[0], params) 1077 1078 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1079 1080 cmd = "MGMT_TX {} {} freq=2412 action=040A".format(bssid, bssid) 1081 if "FAIL" in dev[0].request(cmd): 1082 raise Exception("Could not send test Action frame") 1083 ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10) 1084 if ev is None: 1085 raise Exception("Timeout on MGMT-TX-STATUS") 1086 if "result=SUCCESS" not in ev: 1087 raise Exception("AP did not ack Action frame") 1088 1089 cmd = "MGMT_TX {} {} freq=2412 action=04".format(bssid, bssid) 1090 if "FAIL" in dev[0].request(cmd): 1091 raise Exception("Could not send test Action frame") 1092 ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10) 1093 if ev is None: 1094 raise Exception("Timeout on MGMT-TX-STATUS") 1095 if "result=SUCCESS" not in ev: 1096 raise Exception("AP did not ack Action frame") 1097 1098def test_gas_query_deinit(dev, apdev): 1099 """Pending GAS/ANQP query during deinit""" 1100 hapd = start_ap(apdev[0]) 1101 bssid = apdev[0]['bssid'] 1102 1103 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1104 wpas.interface_add("wlan5") 1105 1106 wpas.scan_for_bss(bssid, freq="2412", force_scan=True) 1107 id = wpas.request("RADIO_WORK add block-work") 1108 if "OK" not in wpas.request("ANQP_GET " + bssid + " 258"): 1109 raise Exception("ANQP_GET command failed") 1110 1111 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5) 1112 if ev is None: 1113 raise Exception("Timeout while waiting radio work to start") 1114 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5) 1115 if ev is None: 1116 raise Exception("Timeout while waiting radio work to start (2)") 1117 1118 # Remove the interface while the gas-query radio work is still pending and 1119 # GAS query has not yet been started. 1120 wpas.interface_remove("wlan5") 1121 1122@remote_compatible 1123def test_gas_anqp_oom_wpas(dev, apdev): 1124 """GAS/ANQP query and OOM in wpa_supplicant""" 1125 hapd = start_ap(apdev[0]) 1126 bssid = apdev[0]['bssid'] 1127 1128 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1129 1130 with alloc_fail(dev[0], 1, "wpa_bss_anqp_alloc"): 1131 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1132 raise Exception("ANQP_GET command failed") 1133 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5) 1134 if ev is None: 1135 raise Exception("ANQP query did not complete") 1136 1137 with alloc_fail(dev[0], 1, "gas_build_req"): 1138 if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1139 raise Exception("Unexpected ANQP_GET command success (OOM)") 1140 1141def test_gas_anqp_oom_hapd(dev, apdev): 1142 """GAS/ANQP query and OOM in hostapd""" 1143 hapd = start_ap(apdev[0]) 1144 bssid = apdev[0]['bssid'] 1145 1146 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1147 1148 with alloc_fail(hapd, 1, "gas_build_resp"): 1149 # This query will time out due to the AP not sending a response (OOM). 1150 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1151 raise Exception("ANQP_GET command failed") 1152 1153 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1154 if ev is None: 1155 raise Exception("GAS query start timed out") 1156 1157 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1158 if ev is None: 1159 raise Exception("GAS query timed out") 1160 if "result=TIMEOUT" not in ev: 1161 raise Exception("Unexpected result: " + ev) 1162 1163 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1164 if ev is None: 1165 raise Exception("ANQP-QUERY-DONE event not seen") 1166 if "result=FAILURE" not in ev: 1167 raise Exception("Unexpected result: " + ev) 1168 1169 with alloc_fail(hapd, 1, "gas_anqp_build_comeback_resp"): 1170 hapd.set("gas_frag_limit", "50") 1171 1172 # The first attempt of this query will time out due to the AP not 1173 # sending a response (OOM), but the retry succeeds. 1174 dev[0].request("FETCH_ANQP") 1175 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1176 if ev is None: 1177 raise Exception("GAS query start timed out") 1178 1179 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1180 if ev is None: 1181 raise Exception("GAS query timed out") 1182 if "result=SUCCESS" not in ev: 1183 raise Exception("Unexpected result: " + ev) 1184 1185 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1186 if ev is None: 1187 raise Exception("ANQP-QUERY-DONE event not seen") 1188 if "result=SUCCESS" not in ev: 1189 raise Exception("Unexpected result: " + ev) 1190 1191def test_gas_anqp_extra_elements(dev, apdev): 1192 """GAS/ANQP and extra ANQP elements""" 1193 geo_loc = "001052834d12efd2b08b9b4bf1cc2c00004104050000000000060100" 1194 civic_loc = "0000f9555302f50102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5" 1195 held_uri = "https://held.example.com/location" 1196 held = struct.pack('BBB', 0, 1 + len(held_uri), 1) + held_uri.encode() 1197 supl_fqdn = "supl.example.com" 1198 supl = struct.pack('BBB', 0, 1 + len(supl_fqdn), 1) + supl_fqdn.encode() 1199 public_id = binascii.hexlify(held + supl).decode() 1200 params = {"ssid": "gas/anqp", 1201 "interworking": "1", 1202 "anqp_elem": ["265:" + geo_loc, 1203 "266:" + civic_loc, 1204 "262:1122334455", 1205 "267:" + public_id, 1206 "279:01020304", 1207 "60000:01", 1208 "299:0102"]} 1209 hapd = hostapd.add_ap(apdev[0], params) 1210 bssid = apdev[0]['bssid'] 1211 1212 dev[0].flush_scan_cache() 1213 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1214 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 265,266"): 1215 raise Exception("ANQP_GET command failed") 1216 1217 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1218 if ev is None: 1219 raise Exception("GAS query timed out") 1220 1221 bss = dev[0].get_bss(bssid) 1222 1223 if 'anqp[265]' not in bss: 1224 raise Exception("AP Geospatial Location ANQP-element not seen") 1225 if bss['anqp[265]'] != geo_loc: 1226 raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]']) 1227 1228 if 'anqp[266]' not in bss: 1229 raise Exception("AP Civic Location ANQP-element not seen") 1230 if bss['anqp[266]'] != civic_loc: 1231 raise Exception("Unexpected AP Civic Location ANQP-element value: " + bss['anqp[266]']) 1232 1233 dev[1].scan_for_bss(bssid, freq="2412", force_scan=True) 1234 if "OK" not in dev[1].request("ANQP_GET " + bssid + " 257,258,259,260,261,262,263,264,265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299"): 1235 raise Exception("ANQP_GET command failed") 1236 1237 ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=10) 1238 if ev is None: 1239 raise Exception("GAS query timed out") 1240 1241 bss = dev[1].get_bss(bssid) 1242 1243 if 'anqp[265]' not in bss: 1244 raise Exception("AP Geospatial Location ANQP-element not seen") 1245 if bss['anqp[265]'] != geo_loc: 1246 raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]']) 1247 1248 if 'anqp[266]' in bss: 1249 raise Exception("AP Civic Location ANQP-element unexpectedly seen") 1250 1251 if 'anqp[267]' not in bss: 1252 raise Exception("AP Location Public Identifier ANQP-element not seen") 1253 if bss['anqp[267]'] != public_id: 1254 raise Exception("Unexpected AP Location Public Identifier ANQP-element value: " + bss['anqp[267]']) 1255 1256 if 'anqp[279]' not in bss: 1257 raise Exception("ANQP-element Info ID 279 not seen") 1258 if bss['anqp[279]'] != "01020304": 1259 raise Exception("Unexpected AP ANQP-element Info ID 279 value: " + bss['anqp[279]']) 1260 1261 if 'anqp[299]' not in bss: 1262 raise Exception("ANQP-element Info ID 299 not seen") 1263 if bss['anqp[299]'] != "0102": 1264 raise Exception("Unexpected AP ANQP-element Info ID 299 value: " + bss['anqp[299]']) 1265 1266 if 'anqp_ip_addr_type_availability' not in bss: 1267 raise Exception("ANQP-element Info ID 292 not seen") 1268 if bss['anqp_ip_addr_type_availability'] != "1122334455": 1269 raise Exception("Unexpected AP ANQP-element Info ID 262 value: " + bss['anqp_ip_addr_type_availability']) 1270 1271def test_gas_anqp_address3_not_assoc(dev, apdev, params): 1272 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when not associated""" 1273 try: 1274 _test_gas_anqp_address3_not_assoc(dev, apdev, params) 1275 finally: 1276 dev[0].request("SET gas_address3 0") 1277 1278def _test_gas_anqp_address3_not_assoc(dev, apdev, params): 1279 hapd = start_ap(apdev[0]) 1280 bssid = apdev[0]['bssid'] 1281 1282 if "OK" not in dev[0].request("SET gas_address3 1"): 1283 raise Exception("Failed to set gas_address3") 1284 1285 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1286 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1287 raise Exception("ANQP_GET command failed") 1288 1289 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1290 if ev is None: 1291 raise Exception("GAS query start timed out") 1292 1293 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1294 if ev is None: 1295 raise Exception("GAS query timed out") 1296 1297 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1298 if ev is None or "Venue Name" not in ev: 1299 raise Exception("Did not receive Venue Name") 1300 1301 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1302 if ev is None: 1303 raise Exception("ANQP-QUERY-DONE event not seen") 1304 if "result=SUCCESS" not in ev: 1305 raise Exception("Unexpected result: " + ev) 1306 1307 time.sleep(1) 1308 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1309 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1310 display=["wlan.bssid"]) 1311 logger.info("tshark output:\n" + out) 1312 res = out.splitlines() 1313 if len(res) != 2: 1314 logger.info("res: " + str(res)) 1315 raise Exception("Unexpected number of GAS frames") 1316 if res[0] != 'ff:ff:ff:ff:ff:ff': 1317 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1318 if res[1] != 'ff:ff:ff:ff:ff:ff': 1319 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1320 1321def test_gas_anqp_address3_assoc(dev, apdev, params): 1322 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when associated""" 1323 try: 1324 _test_gas_anqp_address3_assoc(dev, apdev, params) 1325 finally: 1326 dev[0].request("SET gas_address3 0") 1327 1328def _test_gas_anqp_address3_assoc(dev, apdev, params): 1329 hapd = start_ap(apdev[0]) 1330 bssid = apdev[0]['bssid'] 1331 1332 if "OK" not in dev[0].request("SET gas_address3 1"): 1333 raise Exception("Failed to set gas_address3") 1334 1335 dev[0].scan_for_bss(bssid, freq="2412") 1336 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 1337 identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls", 1338 password="password", phase2="auth=MSCHAPV2", 1339 ca_cert="auth_serv/ca.pem", scan_freq="2412") 1340 hapd.wait_sta() 1341 1342 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1343 raise Exception("ANQP_GET command failed") 1344 1345 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1346 if ev is None: 1347 raise Exception("GAS query start timed out") 1348 1349 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1350 if ev is None: 1351 raise Exception("GAS query timed out") 1352 1353 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1354 if ev is None or "Venue Name" not in ev: 1355 raise Exception("Did not receive Venue Name") 1356 1357 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1358 if ev is None: 1359 raise Exception("ANQP-QUERY-DONE event not seen") 1360 if "result=SUCCESS" not in ev: 1361 raise Exception("Unexpected result: " + ev) 1362 1363 time.sleep(1) 1364 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1365 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1366 display=["wlan.bssid"]) 1367 logger.info("tshark output:\n" + out) 1368 res = out.splitlines() 1369 if len(res) != 2: 1370 logger.info("res: " + str(res)) 1371 raise Exception("Unexpected number of GAS frames") 1372 if res[0] != bssid: 1373 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1374 if res[1] != bssid: 1375 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1376 1377def test_gas_anqp_address3_ap_forced(dev, apdev, params): 1378 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value on AP""" 1379 hapd = start_ap(apdev[0]) 1380 bssid = apdev[0]['bssid'] 1381 hapd.set("gas_address3", "1") 1382 1383 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1384 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1385 raise Exception("ANQP_GET command failed") 1386 1387 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1388 if ev is None: 1389 raise Exception("GAS query start timed out") 1390 1391 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1392 if ev is None: 1393 raise Exception("GAS query timed out") 1394 1395 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1396 if ev is None or "Venue Name" not in ev: 1397 raise Exception("Did not receive Venue Name") 1398 1399 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1400 if ev is None: 1401 raise Exception("ANQP-QUERY-DONE event not seen") 1402 if "result=SUCCESS" not in ev: 1403 raise Exception("Unexpected result: " + ev) 1404 1405 time.sleep(1) 1406 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1407 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1408 display=["wlan.bssid"]) 1409 logger.info("tshark output:\n" + out) 1410 res = out.splitlines() 1411 if len(res) != 2: 1412 logger.info("res: " + str(res)) 1413 raise Exception("Unexpected number of GAS frames") 1414 if res[0] != bssid: 1415 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1416 if res[1] != 'ff:ff:ff:ff:ff:ff': 1417 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1418 1419def test_gas_anqp_address3_ap_non_compliant(dev, apdev, params): 1420 """GAS/ANQP query using IEEE 802.11 non-compliant Address 3 (AP)""" 1421 try: 1422 _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params) 1423 finally: 1424 dev[0].request("SET gas_address3 0") 1425 1426def _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params): 1427 hapd = start_ap(apdev[0]) 1428 bssid = apdev[0]['bssid'] 1429 hapd.set("gas_address3", "2") 1430 1431 if "OK" not in dev[0].request("SET gas_address3 1"): 1432 raise Exception("Failed to set gas_address3") 1433 1434 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1435 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1436 raise Exception("ANQP_GET command failed") 1437 1438 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1439 if ev is None: 1440 raise Exception("GAS query start timed out") 1441 1442 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1443 if ev is None: 1444 raise Exception("GAS query timed out") 1445 1446 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1447 if ev is None or "Venue Name" not in ev: 1448 raise Exception("Did not receive Venue Name") 1449 1450 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1451 if ev is None: 1452 raise Exception("ANQP-QUERY-DONE event not seen") 1453 if "result=SUCCESS" not in ev: 1454 raise Exception("Unexpected result: " + ev) 1455 1456 time.sleep(1) 1457 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1458 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1459 display=["wlan.bssid"]) 1460 logger.info("tshark output:\n" + out) 1461 res = out.splitlines() 1462 if len(res) != 2: 1463 logger.info("res: " + str(res)) 1464 raise Exception("Unexpected number of GAS frames") 1465 if res[0] != 'ff:ff:ff:ff:ff:ff': 1466 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1467 if res[1] != bssid: 1468 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1469 1470def test_gas_anqp_address3_pmf(dev, apdev): 1471 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value with PMF""" 1472 try: 1473 _test_gas_anqp_address3_pmf(dev, apdev) 1474 finally: 1475 dev[0].request("SET gas_address3 0") 1476 1477def _test_gas_anqp_address3_pmf(dev, apdev): 1478 hapd = start_ap(apdev[0]) 1479 bssid = apdev[0]['bssid'] 1480 hapd.set("gas_comeback_delay", "2") 1481 hapd.set("gas_address3", "1") 1482 1483 if "OK" not in dev[0].request("SET gas_address3 1"): 1484 raise Exception("Failed to set gas_address3") 1485 1486 dev[0].scan_for_bss(bssid, freq="2412") 1487 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 1488 identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls", 1489 password="password", phase2="auth=MSCHAPV2", 1490 ca_cert="auth_serv/ca.pem", scan_freq="2412", 1491 ieee80211w="2") 1492 hapd.wait_sta() 1493 1494 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1495 raise Exception("ANQP_GET command failed") 1496 1497 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1498 if ev is None: 1499 raise Exception("GAS query start timed out") 1500 1501 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1502 if ev is None: 1503 raise Exception("GAS query timed out") 1504 1505 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1506 if ev is None or "Venue Name" not in ev: 1507 raise Exception("Did not receive Venue Name") 1508 1509 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1510 if ev is None: 1511 raise Exception("ANQP-QUERY-DONE event not seen") 1512 if "result=SUCCESS" not in ev: 1513 raise Exception("Unexpected result: " + ev) 1514 1515 req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101") 1516 if "FAIL" in req: 1517 raise Exception("GAS query request rejected") 1518 expect_gas_result(dev[0], "FAILURE", "59") 1519 1520def test_gas_prot_vs_not_prot(dev, apdev, params): 1521 """GAS/ANQP query protected vs. not protected""" 1522 hapd = start_ap(apdev[0]) 1523 bssid = apdev[0]['bssid'] 1524 1525 dev[0].scan_for_bss(bssid, freq="2412") 1526 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 1527 identity="DOMAIN\\mschapv2 user", anonymous_identity="ttls", 1528 password="password", phase2="auth=MSCHAPV2", 1529 ca_cert="auth_serv/ca.pem", scan_freq="2412", 1530 ieee80211w="2") 1531 hapd.wait_sta() 1532 1533 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1534 raise Exception("ANQP_GET command failed") 1535 1536 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1537 if ev is None: 1538 raise Exception("No GAS-QUERY-DONE event") 1539 if "result=SUCCESS" not in ev: 1540 raise Exception("Unexpected GAS result: " + ev) 1541 1542 # GAS: Drop unexpected unprotected GAS frame when PMF is enabled 1543 dev[0].request("SET ext_mgmt_frame_handling 1") 1544 res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000") 1545 dev[0].request("SET ext_mgmt_frame_handling 0") 1546 if "OK" not in res: 1547 raise Exception("MGMT_RX_PROCESS failed") 1548 1549 dev[0].request("DISCONNECT") 1550 dev[0].wait_disconnected() 1551 1552 # GAS: No pending query found for 02:00:00:00:03:00 dialog token 0 1553 dev[0].request("SET ext_mgmt_frame_handling 1") 1554 res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000") 1555 dev[0].request("SET ext_mgmt_frame_handling 0") 1556 if "OK" not in res: 1557 raise Exception("MGMT_RX_PROCESS failed") 1558 1559 # GAS: Drop unexpected protected GAS frame when PMF is disabled 1560 dev[0].request("SET ext_mgmt_frame_handling 1") 1561 res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000090b00000005006c027f000000") 1562 dev[0].request("SET ext_mgmt_frame_handling 0") 1563 if "OK" not in res: 1564 raise Exception("MGMT_RX_PROCESS failed") 1565 1566def test_gas_failures(dev, apdev): 1567 """GAS failure cases""" 1568 hapd = start_ap(apdev[0]) 1569 hapd.set("gas_comeback_delay", "5") 1570 bssid = apdev[0]['bssid'] 1571 1572 hapd2 = start_ap(apdev[1]) 1573 bssid2 = apdev[1]['bssid'] 1574 1575 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1576 dev[0].scan_for_bss(bssid2, freq="2412") 1577 1578 tests = [(bssid, "gas_build_req;gas_query_tx_comeback_req"), 1579 (bssid, "gas_query_tx;gas_query_tx_comeback_req"), 1580 (bssid, "gas_query_append;gas_query_rx_comeback"), 1581 (bssid2, "gas_query_append;gas_query_rx_initial"), 1582 (bssid2, "wpabuf_alloc_copy;gas_query_rx_initial"), 1583 (bssid, "gas_query_tx;gas_query_tx_initial_req")] 1584 for addr, func in tests: 1585 with alloc_fail(dev[0], 1, func): 1586 dev[0].request("ANQP_GET " + addr + " 258") 1587 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1588 if ev is None: 1589 raise Exception("No GAS-QUERY-DONE seen") 1590 if "result=INTERNAL_ERROR" not in ev: 1591 raise Exception("Unexpected result code: " + ev) 1592 dev[0].dump_monitor() 1593 1594 tests = ["=gas_query_req", "radio_add_work;gas_query_req"] 1595 for func in tests: 1596 with alloc_fail(dev[0], 1, func): 1597 if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1598 raise Exception("ANQP_GET succeeded unexpectedly during OOM") 1599 dev[0].dump_monitor() 1600 1601 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1602 wpas.interface_add("wlan5") 1603 wpas.scan_for_bss(bssid2, freq="2412") 1604 wpas.request("SET preassoc_mac_addr 1") 1605 with fail_test(wpas, 1, "random_mac_addr"): 1606 wpas.request("ANQP_GET " + bssid2 + " 258") 1607 ev = wpas.wait_event(["Failed to assign random MAC address for GAS"], 1608 timeout=5) 1609 wpas.request("SET preassoc_mac_addr 0") 1610 if ev is None: 1611 raise Exception("No random MAC address error seen") 1612 1613def test_gas_anqp_venue_url(dev, apdev): 1614 """GAS/ANQP and Venue URL""" 1615 venue_group = 1 1616 venue_type = 13 1617 venue_info = struct.pack('BB', venue_group, venue_type) 1618 lang1 = "eng" 1619 name1 = "Example venue" 1620 lang2 = "fin" 1621 name2 = "Esimerkkipaikka" 1622 venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode() 1623 venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode() 1624 venue_name = binascii.hexlify(venue_info + venue1 + venue2).decode() 1625 1626 url1 = b"http://example.com/venue" 1627 url2 = b"https://example.org/venue-info/" 1628 duple1 = struct.pack('BB', 1 + len(url1), 1) + url1 1629 duple2 = struct.pack('BB', 1 + len(url2), 2) + url2 1630 venue_url = binascii.hexlify(duple1 + duple2).decode() 1631 1632 params = {"ssid": "gas/anqp", 1633 "interworking": "1", 1634 "venue_group": str(venue_group), 1635 "venue_type": str(venue_type), 1636 "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2], 1637 "anqp_elem": ["277:" + venue_url]} 1638 hapd = hostapd.add_ap(apdev[0], params) 1639 bssid = apdev[0]['bssid'] 1640 1641 dev[0].flush_scan_cache() 1642 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1643 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,277"): 1644 raise Exception("ANQP_GET command failed") 1645 1646 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1647 if ev is None: 1648 raise Exception("GAS query timed out") 1649 1650 ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=0.1) 1651 if ev is not None: 1652 raise Exception("Unexpected Venue URL indication without PMF") 1653 1654 bss = dev[0].get_bss(bssid) 1655 1656 if 'anqp_venue_name' not in bss: 1657 raise Exception("Venue Name ANQP-element not seen") 1658 if bss['anqp_venue_name'] != venue_name: 1659 raise Exception("Unexpected Venue Name ANQP-element value: " + bss['anqp_venue_name']) 1660 if 'anqp[277]' not in bss: 1661 raise Exception("Venue URL ANQP-element not seen") 1662 if bss['anqp[277]'] != venue_url: 1663 raise Exception("Unexpected Venue URL ANQP-element value: " + bss['anqp[277]']) 1664 1665 if 'anqp_capability_list' not in bss: 1666 raise Exception("Capability List ANQP-element not seen") 1667 ids = struct.pack('<HHH', 257, 258, 277) 1668 if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()): 1669 raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list']) 1670 1671 if "anqp[277]" not in bss: 1672 raise Exception("Venue-URL ANQP info not available") 1673 if "protected-anqp-info[277]" in bss: 1674 raise Exception("Unexpected Venue-URL protection info") 1675 1676def test_gas_anqp_venue_url2(dev, apdev): 1677 """GAS/ANQP and Venue URL (hostapd venue_url)""" 1678 venue_group = 1 1679 venue_type = 13 1680 venue_info = struct.pack('BB', venue_group, venue_type) 1681 lang1 = "eng" 1682 name1 = "Example venue" 1683 lang2 = "fin" 1684 name2 = "Esimerkkipaikka" 1685 venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode() 1686 venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode() 1687 venue_name = binascii.hexlify(venue_info + venue1 + venue2).decode() 1688 1689 url1 = "http://example.com/venue" 1690 url2 = "https://example.org/venue-info/" 1691 duple1 = struct.pack('BB', 1 + len(url1.encode()), 1) + url1.encode() 1692 duple2 = struct.pack('BB', 1 + len(url2.encode()), 2) + url2.encode() 1693 venue_url = binascii.hexlify(duple1 + duple2).decode() 1694 1695 params = {"ssid": "gas/anqp", 1696 "interworking": "1", 1697 "venue_group": str(venue_group), 1698 "venue_type": str(venue_type), 1699 "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2], 1700 "venue_url": ["1:" + url1, "2:" + url2]} 1701 hapd = hostapd.add_ap(apdev[0], params) 1702 bssid = apdev[0]['bssid'] 1703 1704 dev[0].flush_scan_cache() 1705 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1706 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,277"): 1707 raise Exception("ANQP_GET command failed") 1708 1709 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1710 if ev is None: 1711 raise Exception("GAS query timed out") 1712 1713 bss = dev[0].get_bss(bssid) 1714 1715 if 'anqp_venue_name' not in bss: 1716 raise Exception("Venue Name ANQP-element not seen") 1717 if bss['anqp_venue_name'] != venue_name: 1718 raise Exception("Unexpected Venue Name ANQP-element value: " + bss['anqp_venue_name']) 1719 if 'anqp[277]' not in bss: 1720 raise Exception("Venue URL ANQP-element not seen") 1721 if bss['anqp[277]'] != venue_url: 1722 print(venue_url) 1723 raise Exception("Unexpected Venue URL ANQP-element value: " + bss['anqp[277]']) 1724 1725 if 'anqp_capability_list' not in bss: 1726 raise Exception("Capability List ANQP-element not seen") 1727 ids = struct.pack('<HHH', 257, 258, 277) 1728 if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()): 1729 raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list']) 1730 1731def test_gas_anqp_venue_url_pmf(dev, apdev): 1732 """GAS/ANQP and Venue URL with PMF""" 1733 venue_group = 1 1734 venue_type = 13 1735 venue_info = struct.pack('BB', venue_group, venue_type) 1736 lang1 = "eng" 1737 name1 = "Example venue" 1738 lang2 = "fin" 1739 name2 = "Esimerkkipaikka" 1740 venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode() 1741 venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode() 1742 venue_name = binascii.hexlify(venue_info + venue1 + venue2) 1743 1744 url1 = "http://example.com/venue" 1745 url2 = "https://example.org/venue-info/" 1746 1747 params = {"ssid": "gas/anqp/pmf", 1748 "wpa": "2", 1749 "wpa_key_mgmt": "WPA-PSK", 1750 "rsn_pairwise": "CCMP", 1751 "wpa_passphrase": "12345678", 1752 "ieee80211w": "2", 1753 "interworking": "1", 1754 "venue_group": str(venue_group), 1755 "venue_type": str(venue_type), 1756 "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2], 1757 "venue_url": ["1:" + url1, "2:" + url2]} 1758 hapd = hostapd.add_ap(apdev[0], params) 1759 bssid = apdev[0]['bssid'] 1760 1761 dev[0].flush_scan_cache() 1762 dev[0].connect("gas/anqp/pmf", psk="12345678", ieee80211w="2", 1763 scan_freq="2412") 1764 hapd.wait_sta() 1765 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 277"): 1766 raise Exception("ANQP_GET command failed") 1767 1768 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1769 if ev is None: 1770 raise Exception("GAS query timed out") 1771 1772 ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=5) 1773 if ev is None: 1774 raise Exception("No Venue URL indication seen") 1775 if "1 " + url1 not in ev: 1776 raise Exception("Unexpected Venue URL information: " + ev) 1777 1778 ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=5) 1779 if ev is None: 1780 raise Exception("No Venue URL indication seen (2)") 1781 if "2 " + url2 not in ev: 1782 raise Exception("Unexpected Venue URL information (2): " + ev) 1783 1784 bss = dev[0].get_bss(bssid) 1785 if "anqp[277]" not in bss: 1786 raise Exception("Venue-URL ANQP info not available") 1787 if "protected-anqp-info[277]" not in bss: 1788 raise Exception("Venue-URL protection info not available") 1789 if bss["protected-anqp-info[277]"] != "1": 1790 raise Exception("Venue-URL was not indicated to be protected") 1791 1792def test_gas_anqp_capab_list(dev, apdev): 1793 """GAS/ANQP and Capability List ANQP-element""" 1794 params = {"ssid": "gas/anqp", 1795 "interworking": "1"} 1796 params["anqp_elem"] = [] 1797 for i in range(0, 400): 1798 if i not in [257]: 1799 params["anqp_elem"] += ["%d:010203" % i] 1800 hapd = hostapd.add_ap(apdev[0], params) 1801 bssid = apdev[0]['bssid'] 1802 1803 dev[0].flush_scan_cache() 1804 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1805 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257"): 1806 raise Exception("ANQP_GET command failed") 1807 1808 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1809 if ev is None: 1810 raise Exception("GAS query timed out") 1811 1812 bss = dev[0].get_bss(bssid) 1813 1814 if 'anqp_capability_list' not in bss: 1815 raise Exception("Capability List ANQP-element not seen") 1816 val = bss['anqp_capability_list'] 1817 logger.info("anqp_capability_list: " + val) 1818 ids = [] 1819 while len(val) >= 4: 1820 id_bin = binascii.unhexlify(val[0:4]) 1821 id = struct.unpack('<H', id_bin)[0] 1822 if id == 0xdddd: 1823 break 1824 ids.append(id) 1825 val = val[4:] 1826 logger.info("InfoIDs: " + str(ids)) 1827 for i in range(257, 300): 1828 if i in [273, 274]: 1829 continue 1830 if i not in ids: 1831 raise Exception("Unexpected Capability List ANQP-element value (missing %d): %s" % (i, bss['anqp_capability_list'])) 1832 1833def test_gas_server_oom(dev, apdev): 1834 """GAS server OOM""" 1835 bssid = apdev[0]['bssid'] 1836 params = hs20_ap_params() 1837 params['hessid'] = bssid 1838 params['gas_comeback_delay'] = "5" 1839 hapd = hostapd.add_ap(apdev[0], params) 1840 1841 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1842 1843 tests = ["ap_sta_add;gas_dialog_create", 1844 "=gas_dialog_create", 1845 "wpabuf_alloc_copy;gas_serv_rx_gas_comeback_req"] 1846 for t in tests: 1847 with alloc_fail(hapd, 1, t): 1848 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1849 raise Exception("ANQP_GET command failed") 1850 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1851 if ev is None: 1852 raise Exception("No GAS-QUERY-DONE seen") 1853 dev[0].dump_monitor() 1854 1855 hapd.set("gas_comeback_delay", "0") 1856 1857 tests = ["gas_serv_build_gas_resp_payload"] 1858 for t in tests: 1859 with alloc_fail(hapd, 1, t): 1860 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1861 raise Exception("ANQP_GET command failed") 1862 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1863 if ev is None: 1864 raise Exception("No GAS-QUERY-DONE seen") 1865 dev[0].dump_monitor() 1866 1867 with alloc_fail(hapd, 1, 1868 "gas_build_initial_resp;gas_serv_rx_gas_initial_req"): 1869 req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101") 1870 if "FAIL" in req: 1871 raise Exception("GAS query request rejected") 1872 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1873 if ev is None: 1874 raise Exception("No GAS-QUERY-DONE seen") 1875 dev[0].dump_monitor() 1876 1877 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1878 wpas.interface_add("wlan5") 1879 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1880 raise Exception("Failed to set listen channel") 1881 if "OK" not in wpas.p2p_listen(): 1882 raise Exception("Failed to start listen state") 1883 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1884 raise Exception("Failed to enable external management frame handling") 1885 1886 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1) 1887 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1888 with alloc_fail(hapd, 1, 1889 "gas_anqp_build_comeback_resp_buf;gas_serv_rx_gas_comeback_req"): 1890 if "OK" not in wpas.request(req): 1891 raise Exception("Could not send management frame") 1892 wait_fail_trigger(hapd, "GET_ALLOC_FAIL") 1893 1894def test_gas_anqp_overrides(dev, apdev): 1895 """GAS and ANQP overrides""" 1896 params = {"ssid": "gas/anqp", 1897 "interworking": "1", 1898 "anqp_elem": ["257:111111", 1899 "258:222222", 1900 "260:333333", 1901 "261:444444", 1902 "262:555555", 1903 "263:666666", 1904 "264:777777", 1905 "268:888888", 1906 "275:999999"]} 1907 hapd = hostapd.add_ap(apdev[0], params) 1908 bssid = apdev[0]['bssid'] 1909 1910 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1911 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,260,261,262,263,264,268,275"): 1912 raise Exception("ANQP_GET command failed") 1913 1914 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1915 if ev is None: 1916 raise Exception("GAS query timed out") 1917 elems = 9 1918 capa = dev[0].get_capability("fils") 1919 if capa is None or "FILS" not in capa: 1920 # FILS Realm Info not supported in the build 1921 elems -= 1 1922 for i in range(elems): 1923 ev = dev[0].wait_event(["RX-ANQP"], timeout=5) 1924 if ev is None: 1925 raise Exception("ANQP response not seen") 1926 1927def test_gas_no_dialog_token_match(dev, apdev): 1928 """GAS and no dialog token match for comeback request""" 1929 hapd = start_ap(apdev[0]) 1930 hapd.set("gas_frag_limit", "50") 1931 bssid = apdev[0]['bssid'] 1932 1933 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1934 wpas.interface_add("wlan5") 1935 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1936 raise Exception("Failed to set listen channel") 1937 if "OK" not in wpas.p2p_listen(): 1938 raise Exception("Failed to start listen state") 1939 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1940 raise Exception("Failed to enable external management frame handling") 1941 1942 anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268) 1943 gas = struct.pack('<H', len(anqp_query)) + anqp_query 1944 1945 dialog_token = 100 1946 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 1947 dialog_token) + anqp_adv_proto() + gas 1948 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1949 if "OK" not in wpas.request(req): 1950 raise Exception("Could not send management frame") 1951 resp = wpas.mgmt_rx() 1952 if resp is None: 1953 raise Exception("MGMT-RX timeout") 1954 if 'payload' not in resp: 1955 raise Exception("Missing payload") 1956 gresp = parse_gas(resp['payload']) 1957 if gresp['dialog_token'] != dialog_token: 1958 raise Exception("Dialog token mismatch") 1959 status_code = gresp['status_code'] 1960 if status_code != 0: 1961 raise Exception("Unexpected status code {}".format(status_code)) 1962 1963 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1964 dialog_token + 1) 1965 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1966 if "OK" not in wpas.request(req): 1967 raise Exception("Could not send management frame") 1968 resp = wpas.mgmt_rx() 1969 if resp is None: 1970 raise Exception("MGMT-RX timeout") 1971 if 'payload' not in resp: 1972 raise Exception("Missing payload") 1973 gresp = parse_gas(resp['payload']) 1974 status_code = gresp['status_code'] 1975 if status_code != 60: 1976 raise Exception("Unexpected failure status code {}".format(status_code)) 1977 1978def test_gas_vendor_spec_errors(dev, apdev): 1979 """GAS and vendor specific request error cases""" 1980 bssid = apdev[0]['bssid'] 1981 params = hs20_ap_params() 1982 params['hessid'] = bssid 1983 del params['nai_realm'] 1984 hapd = hostapd.add_ap(apdev[0], params) 1985 1986 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1987 tests = ["00 12340000", 1988 "00 dddd0300506fff", 1989 "00 dddd0400506fffff", 1990 "00 dddd0400506f9aff", 1991 "00 dddd0400506f9a11", 1992 "00 dddd0600506f9a11ff00", 1993 "00 dddd0600506f9a110600", 1994 "00 dddd0600506f9a110600", 1995 "00 dddd0700506f9a11060000", 1996 "00 dddd0700506f9a110600ff", 1997 "00 dddd0800506f9a110600ff00", 1998 "00 dddd0900506f9a110600ff0000", 1999 "00 dddd0900506f9a110600ff0001", 2000 "00 dddd0900506f9a110600ffff00", 2001 "00 dddd0a00506f9a110600ff00013b", 2002 "00 dddd0700506f9a110100ff", 2003 "00 dddd0700506f9a11010008", 2004 "00 dddd14", 2005 "00 dddd1400506f9a11"] 2006 for t in tests: 2007 req = dev[0].request("GAS_REQUEST " + bssid + " " + t) 2008 if "FAIL" in req: 2009 raise Exception("GAS query request rejected") 2010 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 2011 if ev is None: 2012 raise Exception("GAS query did not start") 2013 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 2014 if ev is None: 2015 raise Exception("GAS query did not complete") 2016 if t == "00 dddd0600506f9a110600": 2017 hapd.set("nai_realm", "0,another.example.com") 2018 2019 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 2020 wpas.interface_add("wlan5") 2021 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 2022 raise Exception("Failed to set listen channel") 2023 if "OK" not in wpas.p2p_listen(): 2024 raise Exception("Failed to start listen state") 2025 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 2026 raise Exception("Failed to enable external management frame handling") 2027 2028 anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268) 2029 gas = struct.pack('<H', len(anqp_query)) + anqp_query 2030 2031 dialog_token = 100 2032 adv = struct.pack('BBBB', 109, 2, 0, 0) 2033 adv2 = struct.pack('BBB', 108, 1, 0) 2034 adv3 = struct.pack('BBBB', 108, 3, 0, 0) 2035 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2036 dialog_token) + adv + gas 2037 msg2 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2038 dialog_token) + adv2 + gas 2039 msg3 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2040 dialog_token) + adv3 2041 msg4 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2042 dialog_token) + anqp_adv_proto() 2043 msg5 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2044 dialog_token) + anqp_adv_proto() + struct.pack('<H', 1) 2045 msg6 = struct.pack('<BB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST) 2046 tests = [msg, msg2, msg3, msg4, msg5, msg6] 2047 for t in tests: 2048 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(t).decode()) 2049 if "OK" not in wpas.request(req): 2050 raise Exception("Could not send management frame") 2051 ev = wpas.wait_event(["MGMT-TX-STATUS"], timeout=5) 2052 if ev is None: 2053 raise Exception("No ACK frame seen") 2054