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 with alloc_fail(dev[0], 1, "=hs20_anqp_send_req"): 534 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"): 535 raise Exception("REQ_HS20_ICON command accepted during OOM") 536 with alloc_fail(dev[0], 2, "=hs20_anqp_send_req"): 537 if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"): 538 raise Exception("REQ_HS20_ICON command accepted during OOM") 539 540def test_gas_anqp_icon_binary_proto(dev, apdev): 541 """GAS/ANQP and icon binary protocol testing""" 542 hapd = start_ap(apdev[0]) 543 bssid = apdev[0]['bssid'] 544 545 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 546 hapd.set("ext_mgmt_frame_handling", "1") 547 548 tests = ['010000', '01000000', '00000000', '00030000', '00020000', 549 '00000100', '0001ff0100ee', '0001ff0200ee'] 550 for test in tests: 551 dev[0].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo") 552 query = gas_rx(hapd) 553 gas = parse_gas(query['payload']) 554 resp = action_response(query) 555 data = binascii.unhexlify(test) 556 data = binascii.unhexlify('506f9a110b00') + data 557 data = struct.pack('<HHH', len(data) + 4, 0xdddd, len(data)) + data 558 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + data 559 send_gas_resp(hapd, resp) 560 expect_gas_result(dev[0], "SUCCESS") 561 562def test_gas_anqp_hs20_proto(dev, apdev): 563 """GAS/ANQP and Hotspot 2.0 element protocol testing""" 564 hapd = start_ap(apdev[0]) 565 bssid = apdev[0]['bssid'] 566 567 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 568 hapd.set("ext_mgmt_frame_handling", "1") 569 570 tests = ['00', '0100', '0201', '0300', '0400', '0500', '0600', '0700', 571 '0800', '0900', '0a00', '0b0000000000'] 572 for test in tests: 573 dev[0].request("HS20_ANQP_GET " + bssid + " 3,4") 574 query = gas_rx(hapd) 575 gas = parse_gas(query['payload']) 576 resp = action_response(query) 577 data = binascii.unhexlify(test) 578 data = binascii.unhexlify('506f9a11') + data 579 data = struct.pack('<HHH', len(data) + 4, 0xdddd, len(data)) + data 580 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + data 581 send_gas_resp(hapd, resp) 582 expect_gas_result(dev[0], "SUCCESS") 583 584def expect_gas_result(dev, result, status=None): 585 ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=10) 586 if ev is None: 587 raise Exception("GAS query timed out") 588 if "result=" + result not in ev: 589 raise Exception("Unexpected GAS query result") 590 if status and "status_code=" + str(status) + ' ' not in ev: 591 raise Exception("Unexpected GAS status code") 592 593def anqp_get(dev, bssid, id): 594 if "OK" not in dev.request("ANQP_GET " + bssid + " " + str(id)): 595 raise Exception("ANQP_GET command failed") 596 ev = dev.wait_event(["GAS-QUERY-START"], timeout=5) 597 if ev is None: 598 raise Exception("GAS query start timed out") 599 600def test_gas_timeout(dev, apdev): 601 """GAS timeout""" 602 hapd = start_ap(apdev[0]) 603 bssid = apdev[0]['bssid'] 604 605 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 606 hapd.set("ext_mgmt_frame_handling", "1") 607 608 anqp_get(dev[0], bssid, 263) 609 610 ev = hapd.wait_event(["MGMT-RX"], timeout=5) 611 if ev is None: 612 raise Exception("MGMT RX wait timed out") 613 614 expect_gas_result(dev[0], "TIMEOUT") 615 616MGMT_SUBTYPE_ACTION = 13 617ACTION_CATEG_PUBLIC = 4 618 619GAS_INITIAL_REQUEST = 10 620GAS_INITIAL_RESPONSE = 11 621GAS_COMEBACK_REQUEST = 12 622GAS_COMEBACK_RESPONSE = 13 623GAS_ACTIONS = [GAS_INITIAL_REQUEST, GAS_INITIAL_RESPONSE, 624 GAS_COMEBACK_REQUEST, GAS_COMEBACK_RESPONSE] 625 626def anqp_adv_proto(): 627 return struct.pack('BBBB', 108, 2, 127, 0) 628 629def anqp_initial_resp(dialog_token, status_code, comeback_delay=0): 630 return struct.pack('<BBBHH', ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE, 631 dialog_token, status_code, comeback_delay) + anqp_adv_proto() 632 633def anqp_comeback_resp(dialog_token, status_code=0, id=0, more=False, comeback_delay=0, bogus_adv_proto=False): 634 if more: 635 id |= 0x80 636 if bogus_adv_proto: 637 adv = struct.pack('BBBB', 108, 2, 127, 1) 638 else: 639 adv = anqp_adv_proto() 640 return struct.pack('<BBBHBH', ACTION_CATEG_PUBLIC, GAS_COMEBACK_RESPONSE, 641 dialog_token, status_code, id, comeback_delay) + adv 642 643def gas_rx(hapd): 644 count = 0 645 while count < 30: 646 count = count + 1 647 query = hapd.mgmt_rx() 648 if query is None: 649 raise Exception("Action frame not received") 650 if query['subtype'] != MGMT_SUBTYPE_ACTION: 651 continue 652 payload = query['payload'] 653 if len(payload) < 2: 654 continue 655 (category, action) = struct.unpack('BB', payload[0:2]) 656 if category != ACTION_CATEG_PUBLIC or action not in GAS_ACTIONS: 657 continue 658 return query 659 raise Exception("No Action frame received") 660 661def parse_gas(payload): 662 pos = payload 663 (category, action, dialog_token) = struct.unpack('BBB', pos[0:3]) 664 if category != ACTION_CATEG_PUBLIC: 665 return None 666 if action not in GAS_ACTIONS: 667 return None 668 gas = {} 669 gas['action'] = action 670 pos = pos[3:] 671 672 if len(pos) < 1 and action != GAS_COMEBACK_REQUEST: 673 return None 674 675 gas['dialog_token'] = dialog_token 676 677 if action == GAS_INITIAL_RESPONSE: 678 if len(pos) < 4: 679 return None 680 (status_code, comeback_delay) = struct.unpack('<HH', pos[0:4]) 681 gas['status_code'] = status_code 682 gas['comeback_delay'] = comeback_delay 683 684 if action == GAS_COMEBACK_RESPONSE: 685 if len(pos) < 5: 686 return None 687 (status_code, frag, comeback_delay) = struct.unpack('<HBH', pos[0:5]) 688 gas['status_code'] = status_code 689 gas['frag'] = frag 690 gas['comeback_delay'] = comeback_delay 691 692 return gas 693 694def action_response(req): 695 resp = {} 696 resp['fc'] = req['fc'] 697 resp['da'] = req['sa'] 698 resp['sa'] = req['da'] 699 resp['bssid'] = req['bssid'] 700 return resp 701 702def send_gas_resp(hapd, resp): 703 hapd.mgmt_tx(resp) 704 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 705 if ev is None: 706 raise Exception("Missing TX status for GAS response") 707 if "ok=1" not in ev: 708 raise Exception("GAS response not acknowledged") 709 710def test_gas_invalid_response_type(dev, apdev): 711 """GAS invalid response type""" 712 hapd = start_ap(apdev[0]) 713 bssid = apdev[0]['bssid'] 714 715 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 716 hapd.set("ext_mgmt_frame_handling", "1") 717 718 anqp_get(dev[0], bssid, 263) 719 720 query = gas_rx(hapd) 721 gas = parse_gas(query['payload']) 722 723 resp = action_response(query) 724 # GAS Comeback Response instead of GAS Initial Response 725 resp['payload'] = anqp_comeback_resp(gas['dialog_token']) + struct.pack('<H', 0) 726 send_gas_resp(hapd, resp) 727 728 # station drops the invalid frame, so this needs to result in GAS timeout 729 expect_gas_result(dev[0], "TIMEOUT") 730 731def test_gas_failure_status_code(dev, apdev): 732 """GAS failure status code""" 733 hapd = start_ap(apdev[0]) 734 bssid = apdev[0]['bssid'] 735 736 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 737 hapd.set("ext_mgmt_frame_handling", "1") 738 739 anqp_get(dev[0], bssid, 263) 740 741 query = gas_rx(hapd) 742 gas = parse_gas(query['payload']) 743 744 resp = action_response(query) 745 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 61) + struct.pack('<H', 0) 746 send_gas_resp(hapd, resp) 747 748 expect_gas_result(dev[0], "FAILURE") 749 750def test_gas_malformed(dev, apdev): 751 """GAS malformed response frames""" 752 hapd = start_ap(apdev[0]) 753 bssid = apdev[0]['bssid'] 754 755 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 756 hapd.set("ext_mgmt_frame_handling", "1") 757 758 anqp_get(dev[0], bssid, 263) 759 760 query = gas_rx(hapd) 761 gas = parse_gas(query['payload']) 762 763 resp = action_response(query) 764 765 resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC, 766 GAS_COMEBACK_RESPONSE, 767 gas['dialog_token'], 0) 768 hapd.mgmt_tx(resp) 769 770 resp['payload'] = struct.pack('<BBBHB', ACTION_CATEG_PUBLIC, 771 GAS_COMEBACK_RESPONSE, 772 gas['dialog_token'], 0, 0) 773 hapd.mgmt_tx(resp) 774 775 hdr = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE, 776 gas['dialog_token'], 0, 0) 777 resp['payload'] = hdr + struct.pack('B', 108) 778 hapd.mgmt_tx(resp) 779 resp['payload'] = hdr + struct.pack('BB', 108, 0) 780 hapd.mgmt_tx(resp) 781 resp['payload'] = hdr + struct.pack('BB', 108, 1) 782 hapd.mgmt_tx(resp) 783 resp['payload'] = hdr + struct.pack('BB', 108, 255) 784 hapd.mgmt_tx(resp) 785 resp['payload'] = hdr + struct.pack('BBB', 108, 1, 127) 786 hapd.mgmt_tx(resp) 787 resp['payload'] = hdr + struct.pack('BBB', 108, 2, 127) 788 hapd.mgmt_tx(resp) 789 resp['payload'] = hdr + struct.pack('BBBB', 0, 2, 127, 0) 790 hapd.mgmt_tx(resp) 791 792 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<H', 1) 793 hapd.mgmt_tx(resp) 794 795 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<HB', 2, 0) 796 hapd.mgmt_tx(resp) 797 798 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<H', 65535) 799 hapd.mgmt_tx(resp) 800 801 resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + struct.pack('<HBB', 1, 0, 0) 802 hapd.mgmt_tx(resp) 803 804 # Station drops invalid frames, but the last of the responses is valid from 805 # GAS view point even though it has an extra octet in the end and the ANQP 806 # part of the response is not valid. This is reported as successfully 807 # completed GAS exchange. 808 expect_gas_result(dev[0], "SUCCESS") 809 810 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5) 811 if ev is None: 812 raise Exception("ANQP-QUERY-DONE not reported") 813 if "result=INVALID_FRAME" not in ev: 814 raise Exception("Unexpected result: " + ev) 815 816def init_gas(hapd, bssid, dev): 817 anqp_get(dev, bssid, 263) 818 query = gas_rx(hapd) 819 gas = parse_gas(query['payload']) 820 dialog_token = gas['dialog_token'] 821 822 resp = action_response(query) 823 resp['payload'] = anqp_initial_resp(dialog_token, 0, comeback_delay=1) + struct.pack('<H', 0) 824 send_gas_resp(hapd, resp) 825 826 query = gas_rx(hapd) 827 gas = parse_gas(query['payload']) 828 if gas['action'] != GAS_COMEBACK_REQUEST: 829 raise Exception("Unexpected request action") 830 if gas['dialog_token'] != dialog_token: 831 raise Exception("Unexpected dialog token change") 832 return query, dialog_token 833 834def allow_gas_initial_req(hapd, dialog_token): 835 msg = hapd.mgmt_rx(timeout=1) 836 if msg is not None: 837 gas = parse_gas(msg['payload']) 838 if gas['action'] != GAS_INITIAL_REQUEST or dialog_token == gas['dialog_token']: 839 raise Exception("Unexpected management frame") 840 841def test_gas_malformed_comeback_resp(dev, apdev): 842 """GAS malformed comeback response frames""" 843 hapd = start_ap(apdev[0]) 844 bssid = apdev[0]['bssid'] 845 846 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 847 hapd.set("ext_mgmt_frame_handling", "1") 848 849 logger.debug("Non-zero status code 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, status_code=2) + struct.pack('<H', 0) 853 send_gas_resp(hapd, resp) 854 expect_gas_result(dev[0], "FAILURE", status=2) 855 856 logger.debug("Different advertisement protocol in comeback response") 857 query, dialog_token = init_gas(hapd, bssid, dev[0]) 858 resp = action_response(query) 859 resp['payload'] = anqp_comeback_resp(dialog_token, bogus_adv_proto=True) + struct.pack('<H', 0) 860 send_gas_resp(hapd, resp) 861 expect_gas_result(dev[0], "PEER_ERROR") 862 863 logger.debug("Non-zero frag id and comeback delay in comeback response") 864 query, dialog_token = init_gas(hapd, bssid, dev[0]) 865 resp = action_response(query) 866 resp['payload'] = anqp_comeback_resp(dialog_token, id=1, comeback_delay=1) + struct.pack('<H', 0) 867 send_gas_resp(hapd, resp) 868 expect_gas_result(dev[0], "PEER_ERROR") 869 870 logger.debug("Unexpected frag id in comeback response") 871 query, dialog_token = init_gas(hapd, bssid, dev[0]) 872 resp = action_response(query) 873 resp['payload'] = anqp_comeback_resp(dialog_token, id=1) + struct.pack('<H', 0) 874 send_gas_resp(hapd, resp) 875 expect_gas_result(dev[0], "PEER_ERROR") 876 877 logger.debug("Empty fragment and replay in comeback response") 878 query, dialog_token = init_gas(hapd, bssid, dev[0]) 879 resp = action_response(query) 880 resp['payload'] = anqp_comeback_resp(dialog_token, more=True) + struct.pack('<H', 0) 881 send_gas_resp(hapd, resp) 882 query = gas_rx(hapd) 883 gas = parse_gas(query['payload']) 884 if gas['action'] != GAS_COMEBACK_REQUEST: 885 raise Exception("Unexpected request action") 886 if gas['dialog_token'] != dialog_token: 887 raise Exception("Unexpected dialog token change") 888 resp = action_response(query) 889 resp['payload'] = anqp_comeback_resp(dialog_token) + struct.pack('<H', 0) 890 send_gas_resp(hapd, resp) 891 resp['payload'] = anqp_comeback_resp(dialog_token, id=1) + struct.pack('<H', 0) 892 send_gas_resp(hapd, resp) 893 expect_gas_result(dev[0], "SUCCESS") 894 895 logger.debug("Unexpected initial response when waiting for comeback response") 896 query, dialog_token = init_gas(hapd, bssid, dev[0]) 897 resp = action_response(query) 898 resp['payload'] = anqp_initial_resp(dialog_token, 0) + struct.pack('<H', 0) 899 send_gas_resp(hapd, resp) 900 allow_gas_initial_req(hapd, dialog_token) 901 expect_gas_result(dev[0], "TIMEOUT") 902 903 logger.debug("Too short comeback response") 904 query, dialog_token = init_gas(hapd, bssid, dev[0]) 905 resp = action_response(query) 906 resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC, 907 GAS_COMEBACK_RESPONSE, dialog_token, 0) 908 send_gas_resp(hapd, resp) 909 allow_gas_initial_req(hapd, dialog_token) 910 expect_gas_result(dev[0], "TIMEOUT") 911 912 logger.debug("Too short comeback response(2)") 913 query, dialog_token = init_gas(hapd, bssid, dev[0]) 914 resp = action_response(query) 915 resp['payload'] = struct.pack('<BBBHBB', ACTION_CATEG_PUBLIC, 916 GAS_COMEBACK_RESPONSE, dialog_token, 0, 0x80, 917 0) 918 send_gas_resp(hapd, resp) 919 allow_gas_initial_req(hapd, dialog_token) 920 expect_gas_result(dev[0], "TIMEOUT") 921 922 logger.debug("Maximum comeback response fragment claiming more fragments") 923 query, dialog_token = init_gas(hapd, bssid, dev[0]) 924 resp = action_response(query) 925 resp['payload'] = anqp_comeback_resp(dialog_token, more=True) + struct.pack('<H', 0) 926 send_gas_resp(hapd, resp) 927 for i in range(1, 129): 928 query = gas_rx(hapd) 929 gas = parse_gas(query['payload']) 930 if gas['action'] != GAS_COMEBACK_REQUEST: 931 raise Exception("Unexpected request action") 932 if gas['dialog_token'] != dialog_token: 933 raise Exception("Unexpected dialog token change") 934 resp = action_response(query) 935 resp['payload'] = anqp_comeback_resp(dialog_token, id=i, more=True) + struct.pack('<H', 0) 936 send_gas_resp(hapd, resp) 937 expect_gas_result(dev[0], "PEER_ERROR") 938 939def test_gas_comeback_resp_additional_delay(dev, apdev): 940 """GAS comeback response requesting additional delay""" 941 hapd = start_ap(apdev[0]) 942 bssid = apdev[0]['bssid'] 943 944 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 945 hapd.set("ext_mgmt_frame_handling", "1") 946 947 query, dialog_token = init_gas(hapd, bssid, dev[0]) 948 for i in range(0, 2): 949 resp = action_response(query) 950 resp['payload'] = anqp_comeback_resp(dialog_token, status_code=95, comeback_delay=50) + struct.pack('<H', 0) 951 send_gas_resp(hapd, resp) 952 query = gas_rx(hapd) 953 gas = parse_gas(query['payload']) 954 if gas['action'] != GAS_COMEBACK_REQUEST: 955 raise Exception("Unexpected request action") 956 if gas['dialog_token'] != dialog_token: 957 raise Exception("Unexpected dialog token change") 958 resp = action_response(query) 959 resp['payload'] = anqp_comeback_resp(dialog_token, status_code=0) + struct.pack('<H', 0) 960 send_gas_resp(hapd, resp) 961 expect_gas_result(dev[0], "SUCCESS") 962 963def test_gas_unknown_adv_proto(dev, apdev): 964 """Unknown advertisement protocol id""" 965 bssid = apdev[0]['bssid'] 966 params = hs20_ap_params() 967 params['hessid'] = bssid 968 hostapd.add_ap(apdev[0], params) 969 970 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 971 req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101") 972 if "FAIL" in req: 973 raise Exception("GAS query request rejected") 974 expect_gas_result(dev[0], "FAILURE", "59") 975 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 976 if ev is None: 977 raise Exception("GAS query timed out") 978 exp = r'<.>(GAS-RESPONSE-INFO) addr=([0-9a-f:]*) dialog_token=([0-9]*) status_code=([0-9]*) resp_len=([\-0-9]*)' 979 res = re.split(exp, ev) 980 if len(res) < 6: 981 raise Exception("Could not parse GAS-RESPONSE-INFO") 982 if res[2] != bssid: 983 raise Exception("Unexpected BSSID in response") 984 status = res[4] 985 if status != "59": 986 raise Exception("Unexpected GAS-RESPONSE-INFO status") 987 988def test_gas_request_oom(dev, apdev): 989 """GAS_REQUEST OOM""" 990 bssid = apdev[0]['bssid'] 991 params = hs20_ap_params() 992 params['hessid'] = bssid 993 hostapd.add_ap(apdev[0], params) 994 995 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 996 997 with alloc_fail(dev[0], 1, "gas_build_req;gas_send_request"): 998 if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"): 999 raise Exception("GAS query request rejected") 1000 1001 with alloc_fail(dev[0], 1, "gas_query_req;gas_send_request"): 1002 if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"): 1003 raise Exception("GAS query request rejected") 1004 1005 with alloc_fail(dev[0], 1, "wpabuf_dup;gas_resp_cb"): 1006 if "OK" not in dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101"): 1007 raise Exception("GAS query request rejected") 1008 ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10) 1009 if ev is None: 1010 raise Exception("No GAS response") 1011 if "status_code=0" not in ev: 1012 raise Exception("GAS response indicated a failure") 1013 1014def test_gas_max_pending(dev, apdev): 1015 """GAS and maximum pending query limit""" 1016 hapd = start_ap(apdev[0]) 1017 hapd.set("gas_frag_limit", "50") 1018 bssid = apdev[0]['bssid'] 1019 1020 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1021 wpas.interface_add("wlan5") 1022 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1023 raise Exception("Failed to set listen channel") 1024 if "OK" not in wpas.p2p_listen(): 1025 raise Exception("Failed to start listen state") 1026 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1027 raise Exception("Failed to enable external management frame handling") 1028 1029 anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268) 1030 gas = struct.pack('<H', len(anqp_query)) + anqp_query 1031 1032 for dialog_token in range(1, 10): 1033 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 1034 dialog_token) + anqp_adv_proto() + gas 1035 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1036 if "OK" not in wpas.request(req): 1037 raise Exception("Could not send management frame") 1038 resp = wpas.mgmt_rx() 1039 if resp is None: 1040 raise Exception("MGMT-RX timeout") 1041 if 'payload' not in resp: 1042 raise Exception("Missing payload") 1043 gresp = parse_gas(resp['payload']) 1044 if gresp['dialog_token'] != dialog_token: 1045 raise Exception("Dialog token mismatch") 1046 status_code = gresp['status_code'] 1047 if dialog_token < 9 and status_code != 0: 1048 raise Exception("Unexpected failure status code {} for dialog token {}".format(status_code, dialog_token)) 1049 if dialog_token > 8 and status_code == 0: 1050 raise Exception("Unexpected success status code {} for dialog token {}".format(status_code, dialog_token)) 1051 1052def test_gas_no_pending(dev, apdev): 1053 """GAS and no pending query for comeback request""" 1054 hapd = start_ap(apdev[0]) 1055 bssid = apdev[0]['bssid'] 1056 1057 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1058 wpas.interface_add("wlan5") 1059 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1060 raise Exception("Failed to set listen channel") 1061 if "OK" not in wpas.p2p_listen(): 1062 raise Exception("Failed to start listen state") 1063 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1064 raise Exception("Failed to enable external management frame handling") 1065 1066 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1) 1067 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1068 if "OK" not in wpas.request(req): 1069 raise Exception("Could not send management frame") 1070 resp = wpas.mgmt_rx() 1071 if resp is None: 1072 raise Exception("MGMT-RX timeout") 1073 if 'payload' not in resp: 1074 raise Exception("Missing payload") 1075 gresp = parse_gas(resp['payload']) 1076 status_code = gresp['status_code'] 1077 if status_code != 60: 1078 raise Exception("Unexpected status code {} (expected 60)".format(status_code)) 1079 1080def test_gas_delete_at_deinit(dev, apdev): 1081 """GAS query deleted at deinit""" 1082 hapd = start_ap(apdev[0]) 1083 hapd.set("gas_comeback_delay", "1000") 1084 bssid = apdev[0]['bssid'] 1085 1086 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1087 wpas.interface_add("wlan5") 1088 wpas.scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) 1089 wpas.request("ANQP_GET " + bssid + " 258") 1090 1091 wpas.global_request("INTERFACE_REMOVE " + wpas.ifname) 1092 ev = wpas.wait_event(["GAS-QUERY-DONE"], timeout=2) 1093 del wpas 1094 if ev is None: 1095 raise Exception("GAS-QUERY-DONE not seen") 1096 if "result=DELETED_AT_DEINIT" not in ev: 1097 raise Exception("Unexpected result code: " + ev) 1098 1099def test_gas_missing_payload(dev, apdev): 1100 """No action code in the query frame""" 1101 bssid = apdev[0]['bssid'] 1102 params = hs20_ap_params() 1103 params['hessid'] = bssid 1104 hostapd.add_ap(apdev[0], params) 1105 1106 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1107 1108 cmd = "MGMT_TX {} {} freq=2412 action=040A".format(bssid, bssid) 1109 if "FAIL" in dev[0].request(cmd): 1110 raise Exception("Could not send test Action frame") 1111 ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10) 1112 if ev is None: 1113 raise Exception("Timeout on MGMT-TX-STATUS") 1114 if "result=SUCCESS" not in ev: 1115 raise Exception("AP did not ack Action frame") 1116 1117 cmd = "MGMT_TX {} {} freq=2412 action=04".format(bssid, bssid) 1118 if "FAIL" in dev[0].request(cmd): 1119 raise Exception("Could not send test Action frame") 1120 ev = dev[0].wait_event(["MGMT-TX-STATUS"], timeout=10) 1121 if ev is None: 1122 raise Exception("Timeout on MGMT-TX-STATUS") 1123 if "result=SUCCESS" not in ev: 1124 raise Exception("AP did not ack Action frame") 1125 1126def test_gas_query_deinit(dev, apdev): 1127 """Pending GAS/ANQP query during deinit""" 1128 hapd = start_ap(apdev[0]) 1129 bssid = apdev[0]['bssid'] 1130 1131 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1132 wpas.interface_add("wlan5") 1133 1134 wpas.scan_for_bss(bssid, freq="2412", force_scan=True) 1135 id = wpas.request("RADIO_WORK add block-work") 1136 if "OK" not in wpas.request("ANQP_GET " + bssid + " 258"): 1137 raise Exception("ANQP_GET command failed") 1138 1139 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5) 1140 if ev is None: 1141 raise Exception("Timeout while waiting radio work to start") 1142 ev = wpas.wait_event(["GAS-QUERY-START", "EXT-RADIO-WORK-START"], timeout=5) 1143 if ev is None: 1144 raise Exception("Timeout while waiting radio work to start (2)") 1145 1146 # Remove the interface while the gas-query radio work is still pending and 1147 # GAS query has not yet been started. 1148 wpas.interface_remove("wlan5") 1149 1150@remote_compatible 1151def test_gas_anqp_oom_wpas(dev, apdev): 1152 """GAS/ANQP query and OOM in wpa_supplicant""" 1153 hapd = start_ap(apdev[0]) 1154 bssid = apdev[0]['bssid'] 1155 1156 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1157 1158 with alloc_fail(dev[0], 1, "wpa_bss_anqp_alloc"): 1159 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1160 raise Exception("ANQP_GET command failed") 1161 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5) 1162 if ev is None: 1163 raise Exception("ANQP query did not complete") 1164 1165 with alloc_fail(dev[0], 1, "gas_build_req"): 1166 if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1167 raise Exception("Unexpected ANQP_GET command success (OOM)") 1168 1169def test_gas_anqp_oom_hapd(dev, apdev): 1170 """GAS/ANQP query and OOM in hostapd""" 1171 hapd = start_ap(apdev[0]) 1172 bssid = apdev[0]['bssid'] 1173 1174 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1175 1176 with alloc_fail(hapd, 1, "gas_build_resp"): 1177 # This query will time out due to the AP not sending a response (OOM). 1178 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1179 raise Exception("ANQP_GET command failed") 1180 1181 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1182 if ev is None: 1183 raise Exception("GAS query start timed out") 1184 1185 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1186 if ev is None: 1187 raise Exception("GAS query timed out") 1188 if "result=TIMEOUT" not in ev: 1189 raise Exception("Unexpected result: " + ev) 1190 1191 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1192 if ev is None: 1193 raise Exception("ANQP-QUERY-DONE event not seen") 1194 if "result=FAILURE" not in ev: 1195 raise Exception("Unexpected result: " + ev) 1196 1197 with alloc_fail(hapd, 1, "gas_anqp_build_comeback_resp"): 1198 hapd.set("gas_frag_limit", "50") 1199 1200 # The first attempt of this query will time out due to the AP not 1201 # sending a response (OOM), but the retry succeeds. 1202 dev[0].request("FETCH_ANQP") 1203 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1204 if ev is None: 1205 raise Exception("GAS query start timed out") 1206 1207 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1208 if ev is None: 1209 raise Exception("GAS query timed out") 1210 if "result=SUCCESS" not in ev: 1211 raise Exception("Unexpected result: " + ev) 1212 1213 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1214 if ev is None: 1215 raise Exception("ANQP-QUERY-DONE event not seen") 1216 if "result=SUCCESS" not in ev: 1217 raise Exception("Unexpected result: " + ev) 1218 1219def test_gas_anqp_extra_elements(dev, apdev): 1220 """GAS/ANQP and extra ANQP elements""" 1221 geo_loc = "001052834d12efd2b08b9b4bf1cc2c00004104050000000000060100" 1222 civic_loc = "0000f9555302f50102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5" 1223 held_uri = "https://held.example.com/location" 1224 held = struct.pack('BBB', 0, 1 + len(held_uri), 1) + held_uri.encode() 1225 supl_fqdn = "supl.example.com" 1226 supl = struct.pack('BBB', 0, 1 + len(supl_fqdn), 1) + supl_fqdn.encode() 1227 public_id = binascii.hexlify(held + supl).decode() 1228 params = {"ssid": "gas/anqp", 1229 "interworking": "1", 1230 "anqp_elem": ["265:" + geo_loc, 1231 "266:" + civic_loc, 1232 "262:1122334455", 1233 "267:" + public_id, 1234 "279:01020304", 1235 "60000:01", 1236 "299:0102"]} 1237 hapd = hostapd.add_ap(apdev[0], params) 1238 bssid = apdev[0]['bssid'] 1239 1240 dev[0].flush_scan_cache() 1241 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1242 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 265,266"): 1243 raise Exception("ANQP_GET command failed") 1244 1245 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1246 if ev is None: 1247 raise Exception("GAS query timed out") 1248 1249 bss = dev[0].get_bss(bssid) 1250 1251 if 'anqp[265]' not in bss: 1252 raise Exception("AP Geospatial Location ANQP-element not seen") 1253 if bss['anqp[265]'] != geo_loc: 1254 raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]']) 1255 1256 if 'anqp[266]' not in bss: 1257 raise Exception("AP Civic Location ANQP-element not seen") 1258 if bss['anqp[266]'] != civic_loc: 1259 raise Exception("Unexpected AP Civic Location ANQP-element value: " + bss['anqp[266]']) 1260 1261 dev[1].scan_for_bss(bssid, freq="2412", force_scan=True) 1262 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"): 1263 raise Exception("ANQP_GET command failed") 1264 1265 ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=10) 1266 if ev is None: 1267 raise Exception("GAS query timed out") 1268 1269 bss = dev[1].get_bss(bssid) 1270 1271 if 'anqp[265]' not in bss: 1272 raise Exception("AP Geospatial Location ANQP-element not seen") 1273 if bss['anqp[265]'] != geo_loc: 1274 raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]']) 1275 1276 if 'anqp[266]' in bss: 1277 raise Exception("AP Civic Location ANQP-element unexpectedly seen") 1278 1279 if 'anqp[267]' not in bss: 1280 raise Exception("AP Location Public Identifier ANQP-element not seen") 1281 if bss['anqp[267]'] != public_id: 1282 raise Exception("Unexpected AP Location Public Identifier ANQP-element value: " + bss['anqp[267]']) 1283 1284 if 'anqp[279]' not in bss: 1285 raise Exception("ANQP-element Info ID 279 not seen") 1286 if bss['anqp[279]'] != "01020304": 1287 raise Exception("Unexpected AP ANQP-element Info ID 279 value: " + bss['anqp[279]']) 1288 1289 if 'anqp[299]' not in bss: 1290 raise Exception("ANQP-element Info ID 299 not seen") 1291 if bss['anqp[299]'] != "0102": 1292 raise Exception("Unexpected AP ANQP-element Info ID 299 value: " + bss['anqp[299]']) 1293 1294 if 'anqp_ip_addr_type_availability' not in bss: 1295 raise Exception("ANQP-element Info ID 292 not seen") 1296 if bss['anqp_ip_addr_type_availability'] != "1122334455": 1297 raise Exception("Unexpected AP ANQP-element Info ID 262 value: " + bss['anqp_ip_addr_type_availability']) 1298 1299def test_gas_anqp_address3_not_assoc(dev, apdev, params): 1300 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when not associated""" 1301 try: 1302 _test_gas_anqp_address3_not_assoc(dev, apdev, params) 1303 finally: 1304 dev[0].request("SET gas_address3 0") 1305 1306def _test_gas_anqp_address3_not_assoc(dev, apdev, params): 1307 hapd = start_ap(apdev[0]) 1308 bssid = apdev[0]['bssid'] 1309 1310 if "OK" not in dev[0].request("SET gas_address3 1"): 1311 raise Exception("Failed to set gas_address3") 1312 1313 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1314 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1315 raise Exception("ANQP_GET command failed") 1316 1317 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1318 if ev is None: 1319 raise Exception("GAS query start timed out") 1320 1321 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1322 if ev is None: 1323 raise Exception("GAS query timed out") 1324 1325 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1326 if ev is None or "Venue Name" not in ev: 1327 raise Exception("Did not receive Venue Name") 1328 1329 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1330 if ev is None: 1331 raise Exception("ANQP-QUERY-DONE event not seen") 1332 if "result=SUCCESS" not in ev: 1333 raise Exception("Unexpected result: " + ev) 1334 1335 time.sleep(1) 1336 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1337 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1338 display=["wlan.bssid"]) 1339 logger.info("tshark output:\n" + out) 1340 res = out.splitlines() 1341 if len(res) != 2: 1342 logger.info("res: " + str(res)) 1343 raise Exception("Unexpected number of GAS frames") 1344 if res[0] != 'ff:ff:ff:ff:ff:ff': 1345 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1346 if res[1] != 'ff:ff:ff:ff:ff:ff': 1347 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1348 1349def test_gas_anqp_address3_assoc(dev, apdev, params): 1350 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when associated""" 1351 try: 1352 _test_gas_anqp_address3_assoc(dev, apdev, params) 1353 finally: 1354 dev[0].request("SET gas_address3 0") 1355 1356def _test_gas_anqp_address3_assoc(dev, apdev, params): 1357 hapd = start_ap(apdev[0]) 1358 bssid = apdev[0]['bssid'] 1359 1360 if "OK" not in dev[0].request("SET gas_address3 1"): 1361 raise Exception("Failed to set gas_address3") 1362 1363 dev[0].scan_for_bss(bssid, freq="2412") 1364 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 1365 identity="DOMAIN\mschapv2 user", anonymous_identity="ttls", 1366 password="password", phase2="auth=MSCHAPV2", 1367 ca_cert="auth_serv/ca.pem", scan_freq="2412") 1368 hapd.wait_sta() 1369 1370 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1371 raise Exception("ANQP_GET command failed") 1372 1373 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1374 if ev is None: 1375 raise Exception("GAS query start timed out") 1376 1377 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1378 if ev is None: 1379 raise Exception("GAS query timed out") 1380 1381 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1382 if ev is None or "Venue Name" not in ev: 1383 raise Exception("Did not receive Venue Name") 1384 1385 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1386 if ev is None: 1387 raise Exception("ANQP-QUERY-DONE event not seen") 1388 if "result=SUCCESS" not in ev: 1389 raise Exception("Unexpected result: " + ev) 1390 1391 time.sleep(1) 1392 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1393 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1394 display=["wlan.bssid"]) 1395 logger.info("tshark output:\n" + out) 1396 res = out.splitlines() 1397 if len(res) != 2: 1398 logger.info("res: " + str(res)) 1399 raise Exception("Unexpected number of GAS frames") 1400 if res[0] != bssid: 1401 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1402 if res[1] != bssid: 1403 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1404 1405def test_gas_anqp_address3_ap_forced(dev, apdev, params): 1406 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value on AP""" 1407 hapd = start_ap(apdev[0]) 1408 bssid = apdev[0]['bssid'] 1409 hapd.set("gas_address3", "1") 1410 1411 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1412 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1413 raise Exception("ANQP_GET command failed") 1414 1415 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1416 if ev is None: 1417 raise Exception("GAS query start timed out") 1418 1419 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1420 if ev is None: 1421 raise Exception("GAS query timed out") 1422 1423 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1424 if ev is None or "Venue Name" not in ev: 1425 raise Exception("Did not receive Venue Name") 1426 1427 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1428 if ev is None: 1429 raise Exception("ANQP-QUERY-DONE event not seen") 1430 if "result=SUCCESS" not in ev: 1431 raise Exception("Unexpected result: " + ev) 1432 1433 time.sleep(1) 1434 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1435 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1436 display=["wlan.bssid"]) 1437 logger.info("tshark output:\n" + out) 1438 res = out.splitlines() 1439 if len(res) != 2: 1440 logger.info("res: " + str(res)) 1441 raise Exception("Unexpected number of GAS frames") 1442 if res[0] != bssid: 1443 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1444 if res[1] != 'ff:ff:ff:ff:ff:ff': 1445 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1446 1447def test_gas_anqp_address3_ap_non_compliant(dev, apdev, params): 1448 """GAS/ANQP query using IEEE 802.11 non-compliant Address 3 (AP)""" 1449 try: 1450 _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params) 1451 finally: 1452 dev[0].request("SET gas_address3 0") 1453 1454def _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params): 1455 hapd = start_ap(apdev[0]) 1456 bssid = apdev[0]['bssid'] 1457 hapd.set("gas_address3", "2") 1458 1459 if "OK" not in dev[0].request("SET gas_address3 1"): 1460 raise Exception("Failed to set gas_address3") 1461 1462 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1463 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1464 raise Exception("ANQP_GET command failed") 1465 1466 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1467 if ev is None: 1468 raise Exception("GAS query start timed out") 1469 1470 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1471 if ev is None: 1472 raise Exception("GAS query timed out") 1473 1474 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1475 if ev is None or "Venue Name" not in ev: 1476 raise Exception("Did not receive Venue Name") 1477 1478 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1479 if ev is None: 1480 raise Exception("ANQP-QUERY-DONE event not seen") 1481 if "result=SUCCESS" not in ev: 1482 raise Exception("Unexpected result: " + ev) 1483 1484 time.sleep(1) 1485 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 1486 "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)", 1487 display=["wlan.bssid"]) 1488 logger.info("tshark output:\n" + out) 1489 res = out.splitlines() 1490 if len(res) != 2: 1491 logger.info("res: " + str(res)) 1492 raise Exception("Unexpected number of GAS frames") 1493 if res[0] != 'ff:ff:ff:ff:ff:ff': 1494 raise Exception("GAS request used unexpected Address3 field value: " + res[0]) 1495 if res[1] != bssid: 1496 raise Exception("GAS response used unexpected Address3 field value: " + res[1]) 1497 1498def test_gas_anqp_address3_pmf(dev, apdev): 1499 """GAS/ANQP query using IEEE 802.11 compliant Address 3 value with PMF""" 1500 try: 1501 _test_gas_anqp_address3_pmf(dev, apdev) 1502 finally: 1503 dev[0].request("SET gas_address3 0") 1504 1505def _test_gas_anqp_address3_pmf(dev, apdev): 1506 hapd = start_ap(apdev[0]) 1507 bssid = apdev[0]['bssid'] 1508 hapd.set("gas_comeback_delay", "2") 1509 hapd.set("gas_address3", "1") 1510 1511 if "OK" not in dev[0].request("SET gas_address3 1"): 1512 raise Exception("Failed to set gas_address3") 1513 1514 dev[0].scan_for_bss(bssid, freq="2412") 1515 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 1516 identity="DOMAIN\mschapv2 user", anonymous_identity="ttls", 1517 password="password", phase2="auth=MSCHAPV2", 1518 ca_cert="auth_serv/ca.pem", scan_freq="2412", 1519 ieee80211w="2") 1520 hapd.wait_sta() 1521 1522 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1523 raise Exception("ANQP_GET command failed") 1524 1525 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 1526 if ev is None: 1527 raise Exception("GAS query start timed out") 1528 1529 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1530 if ev is None: 1531 raise Exception("GAS query timed out") 1532 1533 ev = dev[0].wait_event(["RX-ANQP"], timeout=1) 1534 if ev is None or "Venue Name" not in ev: 1535 raise Exception("Did not receive Venue Name") 1536 1537 ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) 1538 if ev is None: 1539 raise Exception("ANQP-QUERY-DONE event not seen") 1540 if "result=SUCCESS" not in ev: 1541 raise Exception("Unexpected result: " + ev) 1542 1543 req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101") 1544 if "FAIL" in req: 1545 raise Exception("GAS query request rejected") 1546 expect_gas_result(dev[0], "FAILURE", "59") 1547 1548def test_gas_prot_vs_not_prot(dev, apdev, params): 1549 """GAS/ANQP query protected vs. not protected""" 1550 hapd = start_ap(apdev[0]) 1551 bssid = apdev[0]['bssid'] 1552 1553 dev[0].scan_for_bss(bssid, freq="2412") 1554 dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS", 1555 identity="DOMAIN\mschapv2 user", anonymous_identity="ttls", 1556 password="password", phase2="auth=MSCHAPV2", 1557 ca_cert="auth_serv/ca.pem", scan_freq="2412", 1558 ieee80211w="2") 1559 hapd.wait_sta() 1560 1561 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1562 raise Exception("ANQP_GET command failed") 1563 1564 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1565 if ev is None: 1566 raise Exception("No GAS-QUERY-DONE event") 1567 if "result=SUCCESS" not in ev: 1568 raise Exception("Unexpected GAS result: " + ev) 1569 1570 # GAS: Drop unexpected unprotected GAS frame when PMF is enabled 1571 dev[0].request("SET ext_mgmt_frame_handling 1") 1572 res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000") 1573 dev[0].request("SET ext_mgmt_frame_handling 0") 1574 if "OK" not in res: 1575 raise Exception("MGMT_RX_PROCESS failed") 1576 1577 dev[0].request("DISCONNECT") 1578 dev[0].wait_disconnected() 1579 1580 # GAS: No pending query found for 02:00:00:00:03:00 dialog token 0 1581 dev[0].request("SET ext_mgmt_frame_handling 1") 1582 res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000") 1583 dev[0].request("SET ext_mgmt_frame_handling 0") 1584 if "OK" not in res: 1585 raise Exception("MGMT_RX_PROCESS failed") 1586 1587 # GAS: Drop unexpected protected GAS frame when PMF is disabled 1588 dev[0].request("SET ext_mgmt_frame_handling 1") 1589 res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000090b00000005006c027f000000") 1590 dev[0].request("SET ext_mgmt_frame_handling 0") 1591 if "OK" not in res: 1592 raise Exception("MGMT_RX_PROCESS failed") 1593 1594def test_gas_failures(dev, apdev): 1595 """GAS failure cases""" 1596 hapd = start_ap(apdev[0]) 1597 hapd.set("gas_comeback_delay", "5") 1598 bssid = apdev[0]['bssid'] 1599 1600 hapd2 = start_ap(apdev[1]) 1601 bssid2 = apdev[1]['bssid'] 1602 1603 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1604 dev[0].scan_for_bss(bssid2, freq="2412") 1605 1606 tests = [(bssid, "gas_build_req;gas_query_tx_comeback_req"), 1607 (bssid, "gas_query_tx;gas_query_tx_comeback_req"), 1608 (bssid, "gas_query_append;gas_query_rx_comeback"), 1609 (bssid2, "gas_query_append;gas_query_rx_initial"), 1610 (bssid2, "wpabuf_alloc_copy;gas_query_rx_initial"), 1611 (bssid, "gas_query_tx;gas_query_tx_initial_req")] 1612 for addr, func in tests: 1613 with alloc_fail(dev[0], 1, func): 1614 dev[0].request("ANQP_GET " + addr + " 258") 1615 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1616 if ev is None: 1617 raise Exception("No GAS-QUERY-DONE seen") 1618 if "result=INTERNAL_ERROR" not in ev: 1619 raise Exception("Unexpected result code: " + ev) 1620 dev[0].dump_monitor() 1621 1622 tests = ["=gas_query_req", "radio_add_work;gas_query_req"] 1623 for func in tests: 1624 with alloc_fail(dev[0], 1, func): 1625 if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1626 raise Exception("ANQP_GET succeeded unexpectedly during OOM") 1627 dev[0].dump_monitor() 1628 1629 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1630 wpas.interface_add("wlan5") 1631 wpas.scan_for_bss(bssid2, freq="2412") 1632 wpas.request("SET preassoc_mac_addr 1") 1633 with fail_test(wpas, 1, "random_mac_addr"): 1634 wpas.request("ANQP_GET " + bssid2 + " 258") 1635 ev = wpas.wait_event(["Failed to assign random MAC address for GAS"], 1636 timeout=5) 1637 wpas.request("SET preassoc_mac_addr 0") 1638 if ev is None: 1639 raise Exception("No random MAC address error seen") 1640 1641def test_gas_anqp_venue_url(dev, apdev): 1642 """GAS/ANQP and Venue URL""" 1643 venue_group = 1 1644 venue_type = 13 1645 venue_info = struct.pack('BB', venue_group, venue_type) 1646 lang1 = "eng" 1647 name1 = "Example venue" 1648 lang2 = "fin" 1649 name2 = "Esimerkkipaikka" 1650 venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode() 1651 venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode() 1652 venue_name = binascii.hexlify(venue_info + venue1 + venue2).decode() 1653 1654 url1 = b"http://example.com/venue" 1655 url2 = b"https://example.org/venue-info/" 1656 duple1 = struct.pack('BB', 1 + len(url1), 1) + url1 1657 duple2 = struct.pack('BB', 1 + len(url2), 2) + url2 1658 venue_url = binascii.hexlify(duple1 + duple2).decode() 1659 1660 params = {"ssid": "gas/anqp", 1661 "interworking": "1", 1662 "venue_group": str(venue_group), 1663 "venue_type": str(venue_type), 1664 "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2], 1665 "anqp_elem": ["277:" + venue_url]} 1666 hapd = hostapd.add_ap(apdev[0], params) 1667 bssid = apdev[0]['bssid'] 1668 1669 dev[0].flush_scan_cache() 1670 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1671 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,277"): 1672 raise Exception("ANQP_GET command failed") 1673 1674 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1675 if ev is None: 1676 raise Exception("GAS query timed out") 1677 1678 ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=0.1) 1679 if ev is not None: 1680 raise Exception("Unexpected Venue URL indication without PMF") 1681 1682 bss = dev[0].get_bss(bssid) 1683 1684 if 'anqp_venue_name' not in bss: 1685 raise Exception("Venue Name ANQP-element not seen") 1686 if bss['anqp_venue_name'] != venue_name: 1687 raise Exception("Unexpected Venue Name ANQP-element value: " + bss['anqp_venue_name']) 1688 if 'anqp[277]' not in bss: 1689 raise Exception("Venue URL ANQP-element not seen") 1690 if bss['anqp[277]'] != venue_url: 1691 raise Exception("Unexpected Venue URL ANQP-element value: " + bss['anqp[277]']) 1692 1693 if 'anqp_capability_list' not in bss: 1694 raise Exception("Capability List ANQP-element not seen") 1695 ids = struct.pack('<HHH', 257, 258, 277) 1696 if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()): 1697 raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list']) 1698 1699 if "anqp[277]" not in bss: 1700 raise Exception("Venue-URL ANQP info not available") 1701 if "protected-anqp-info[277]" in bss: 1702 raise Exception("Unexpected Venue-URL protection info") 1703 1704def test_gas_anqp_venue_url2(dev, apdev): 1705 """GAS/ANQP and Venue URL (hostapd venue_url)""" 1706 venue_group = 1 1707 venue_type = 13 1708 venue_info = struct.pack('BB', venue_group, venue_type) 1709 lang1 = "eng" 1710 name1 = "Example venue" 1711 lang2 = "fin" 1712 name2 = "Esimerkkipaikka" 1713 venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode() 1714 venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode() 1715 venue_name = binascii.hexlify(venue_info + venue1 + venue2).decode() 1716 1717 url1 = "http://example.com/venue" 1718 url2 = "https://example.org/venue-info/" 1719 duple1 = struct.pack('BB', 1 + len(url1.encode()), 1) + url1.encode() 1720 duple2 = struct.pack('BB', 1 + len(url2.encode()), 2) + url2.encode() 1721 venue_url = binascii.hexlify(duple1 + duple2).decode() 1722 1723 params = {"ssid": "gas/anqp", 1724 "interworking": "1", 1725 "venue_group": str(venue_group), 1726 "venue_type": str(venue_type), 1727 "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2], 1728 "venue_url": ["1:" + url1, "2:" + url2]} 1729 hapd = hostapd.add_ap(apdev[0], params) 1730 bssid = apdev[0]['bssid'] 1731 1732 dev[0].flush_scan_cache() 1733 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1734 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,277"): 1735 raise Exception("ANQP_GET command failed") 1736 1737 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1738 if ev is None: 1739 raise Exception("GAS query timed out") 1740 1741 bss = dev[0].get_bss(bssid) 1742 1743 if 'anqp_venue_name' not in bss: 1744 raise Exception("Venue Name ANQP-element not seen") 1745 if bss['anqp_venue_name'] != venue_name: 1746 raise Exception("Unexpected Venue Name ANQP-element value: " + bss['anqp_venue_name']) 1747 if 'anqp[277]' not in bss: 1748 raise Exception("Venue URL ANQP-element not seen") 1749 if bss['anqp[277]'] != venue_url: 1750 print(venue_url) 1751 raise Exception("Unexpected Venue URL ANQP-element value: " + bss['anqp[277]']) 1752 1753 if 'anqp_capability_list' not in bss: 1754 raise Exception("Capability List ANQP-element not seen") 1755 ids = struct.pack('<HHH', 257, 258, 277) 1756 if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()): 1757 raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list']) 1758 1759def test_gas_anqp_venue_url_pmf(dev, apdev): 1760 """GAS/ANQP and Venue URL with PMF""" 1761 venue_group = 1 1762 venue_type = 13 1763 venue_info = struct.pack('BB', venue_group, venue_type) 1764 lang1 = "eng" 1765 name1 = "Example venue" 1766 lang2 = "fin" 1767 name2 = "Esimerkkipaikka" 1768 venue1 = struct.pack('B', len(lang1 + name1)) + lang1.encode() + name1.encode() 1769 venue2 = struct.pack('B', len(lang2 + name2)) + lang2.encode() + name2.encode() 1770 venue_name = binascii.hexlify(venue_info + venue1 + venue2) 1771 1772 url1 = "http://example.com/venue" 1773 url2 = "https://example.org/venue-info/" 1774 1775 params = {"ssid": "gas/anqp/pmf", 1776 "wpa": "2", 1777 "wpa_key_mgmt": "WPA-PSK", 1778 "rsn_pairwise": "CCMP", 1779 "wpa_passphrase": "12345678", 1780 "ieee80211w": "2", 1781 "interworking": "1", 1782 "venue_group": str(venue_group), 1783 "venue_type": str(venue_type), 1784 "venue_name": [lang1 + ":" + name1, lang2 + ":" + name2], 1785 "venue_url": ["1:" + url1, "2:" + url2]} 1786 hapd = hostapd.add_ap(apdev[0], params) 1787 bssid = apdev[0]['bssid'] 1788 1789 dev[0].flush_scan_cache() 1790 dev[0].connect("gas/anqp/pmf", psk="12345678", ieee80211w="2", 1791 scan_freq="2412") 1792 hapd.wait_sta() 1793 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 277"): 1794 raise Exception("ANQP_GET command failed") 1795 1796 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1797 if ev is None: 1798 raise Exception("GAS query timed out") 1799 1800 ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=5) 1801 if ev is None: 1802 raise Exception("No Venue URL indication seen") 1803 if "1 " + url1 not in ev: 1804 raise Exception("Unexpected Venue URL information: " + ev) 1805 1806 ev = dev[0].wait_event(["RX-VENUE-URL"], timeout=5) 1807 if ev is None: 1808 raise Exception("No Venue URL indication seen (2)") 1809 if "2 " + url2 not in ev: 1810 raise Exception("Unexpected Venue URL information (2): " + ev) 1811 1812 bss = dev[0].get_bss(bssid) 1813 if "anqp[277]" not in bss: 1814 raise Exception("Venue-URL ANQP info not available") 1815 if "protected-anqp-info[277]" not in bss: 1816 raise Exception("Venue-URL protection info not available") 1817 if bss["protected-anqp-info[277]"] != "1": 1818 raise Exception("Venue-URL was not indicated to be protected") 1819 1820def test_gas_anqp_capab_list(dev, apdev): 1821 """GAS/ANQP and Capability List ANQP-element""" 1822 params = {"ssid": "gas/anqp", 1823 "interworking": "1"} 1824 params["anqp_elem"] = [] 1825 for i in range(0, 400): 1826 if i not in [257]: 1827 params["anqp_elem"] += ["%d:010203" % i] 1828 hapd = hostapd.add_ap(apdev[0], params) 1829 bssid = apdev[0]['bssid'] 1830 1831 dev[0].flush_scan_cache() 1832 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1833 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257"): 1834 raise Exception("ANQP_GET command failed") 1835 1836 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1837 if ev is None: 1838 raise Exception("GAS query timed out") 1839 1840 bss = dev[0].get_bss(bssid) 1841 1842 if 'anqp_capability_list' not in bss: 1843 raise Exception("Capability List ANQP-element not seen") 1844 val = bss['anqp_capability_list'] 1845 logger.info("anqp_capability_list: " + val) 1846 ids = [] 1847 while len(val) >= 4: 1848 id_bin = binascii.unhexlify(val[0:4]) 1849 id = struct.unpack('<H', id_bin)[0] 1850 if id == 0xdddd: 1851 break 1852 ids.append(id) 1853 val = val[4:] 1854 logger.info("InfoIDs: " + str(ids)) 1855 for i in range(257, 300): 1856 if i in [273, 274]: 1857 continue 1858 if i not in ids: 1859 raise Exception("Unexpected Capability List ANQP-element value (missing %d): %s" % (i, bss['anqp_capability_list'])) 1860 1861def test_gas_server_oom(dev, apdev): 1862 """GAS server OOM""" 1863 bssid = apdev[0]['bssid'] 1864 params = hs20_ap_params() 1865 params['hessid'] = bssid 1866 params['gas_comeback_delay'] = "5" 1867 hapd = hostapd.add_ap(apdev[0], params) 1868 1869 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1870 1871 tests = ["ap_sta_add;gas_dialog_create", 1872 "=gas_dialog_create", 1873 "wpabuf_alloc_copy;gas_serv_rx_gas_comeback_req"] 1874 for t in tests: 1875 with alloc_fail(hapd, 1, t): 1876 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1877 raise Exception("ANQP_GET command failed") 1878 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1879 if ev is None: 1880 raise Exception("No GAS-QUERY-DONE seen") 1881 dev[0].dump_monitor() 1882 1883 hapd.set("gas_comeback_delay", "0") 1884 1885 tests = ["gas_serv_build_gas_resp_payload"] 1886 for t in tests: 1887 with alloc_fail(hapd, 1, t): 1888 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"): 1889 raise Exception("ANQP_GET command failed") 1890 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1891 if ev is None: 1892 raise Exception("No GAS-QUERY-DONE seen") 1893 dev[0].dump_monitor() 1894 1895 with alloc_fail(hapd, 1, 1896 "gas_build_initial_resp;gas_serv_rx_gas_initial_req"): 1897 req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101") 1898 if "FAIL" in req: 1899 raise Exception("GAS query request rejected") 1900 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 1901 if ev is None: 1902 raise Exception("No GAS-QUERY-DONE seen") 1903 dev[0].dump_monitor() 1904 1905 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1906 wpas.interface_add("wlan5") 1907 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1908 raise Exception("Failed to set listen channel") 1909 if "OK" not in wpas.p2p_listen(): 1910 raise Exception("Failed to start listen state") 1911 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1912 raise Exception("Failed to enable external management frame handling") 1913 1914 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1) 1915 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1916 with alloc_fail(hapd, 1, 1917 "gas_anqp_build_comeback_resp_buf;gas_serv_rx_gas_comeback_req"): 1918 if "OK" not in wpas.request(req): 1919 raise Exception("Could not send management frame") 1920 wait_fail_trigger(hapd, "GET_ALLOC_FAIL") 1921 1922def test_gas_anqp_overrides(dev, apdev): 1923 """GAS and ANQP overrides""" 1924 params = {"ssid": "gas/anqp", 1925 "interworking": "1", 1926 "anqp_elem": ["257:111111", 1927 "258:222222", 1928 "260:333333", 1929 "261:444444", 1930 "262:555555", 1931 "263:666666", 1932 "264:777777", 1933 "268:888888", 1934 "275:999999"]} 1935 hapd = hostapd.add_ap(apdev[0], params) 1936 bssid = apdev[0]['bssid'] 1937 1938 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 1939 if "OK" not in dev[0].request("ANQP_GET " + bssid + " 257,258,260,261,262,263,264,268,275"): 1940 raise Exception("ANQP_GET command failed") 1941 1942 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10) 1943 if ev is None: 1944 raise Exception("GAS query timed out") 1945 elems = 9 1946 capa = dev[0].get_capability("fils") 1947 if capa is None or "FILS" not in capa: 1948 # FILS Realm Info not supported in the build 1949 elems -= 1 1950 for i in range(elems): 1951 ev = dev[0].wait_event(["RX-ANQP"], timeout=5) 1952 if ev is None: 1953 raise Exception("ANQP response not seen") 1954 1955def test_gas_no_dialog_token_match(dev, apdev): 1956 """GAS and no dialog token match for comeback request""" 1957 hapd = start_ap(apdev[0]) 1958 hapd.set("gas_frag_limit", "50") 1959 bssid = apdev[0]['bssid'] 1960 1961 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1962 wpas.interface_add("wlan5") 1963 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 1964 raise Exception("Failed to set listen channel") 1965 if "OK" not in wpas.p2p_listen(): 1966 raise Exception("Failed to start listen state") 1967 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 1968 raise Exception("Failed to enable external management frame handling") 1969 1970 anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268) 1971 gas = struct.pack('<H', len(anqp_query)) + anqp_query 1972 1973 dialog_token = 100 1974 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 1975 dialog_token) + anqp_adv_proto() + gas 1976 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1977 if "OK" not in wpas.request(req): 1978 raise Exception("Could not send management frame") 1979 resp = wpas.mgmt_rx() 1980 if resp is None: 1981 raise Exception("MGMT-RX timeout") 1982 if 'payload' not in resp: 1983 raise Exception("Missing payload") 1984 gresp = parse_gas(resp['payload']) 1985 if gresp['dialog_token'] != dialog_token: 1986 raise Exception("Dialog token mismatch") 1987 status_code = gresp['status_code'] 1988 if status_code != 0: 1989 raise Exception("Unexpected status code {}".format(status_code)) 1990 1991 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST, 1992 dialog_token + 1) 1993 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(msg).decode()) 1994 if "OK" not in wpas.request(req): 1995 raise Exception("Could not send management frame") 1996 resp = wpas.mgmt_rx() 1997 if resp is None: 1998 raise Exception("MGMT-RX timeout") 1999 if 'payload' not in resp: 2000 raise Exception("Missing payload") 2001 gresp = parse_gas(resp['payload']) 2002 status_code = gresp['status_code'] 2003 if status_code != 60: 2004 raise Exception("Unexpected failure status code {}".format(status_code)) 2005 2006def test_gas_vendor_spec_errors(dev, apdev): 2007 """GAS and vendor specific request error cases""" 2008 bssid = apdev[0]['bssid'] 2009 params = hs20_ap_params() 2010 params['hessid'] = bssid 2011 params['osu_server_uri'] = "uri" 2012 params['hs20_icon'] = "32:32:eng:image/png:icon32:/tmp/icon32.png" 2013 del params['nai_realm'] 2014 hapd = hostapd.add_ap(apdev[0], params) 2015 2016 dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) 2017 tests = ["00 12340000", 2018 "00 dddd0300506fff", 2019 "00 dddd0400506fffff", 2020 "00 dddd0400506f9aff", 2021 "00 dddd0400506f9a11", 2022 "00 dddd0600506f9a11ff00", 2023 "00 dddd0600506f9a110600", 2024 "00 dddd0600506f9a110600", 2025 "00 dddd0700506f9a11060000", 2026 "00 dddd0700506f9a110600ff", 2027 "00 dddd0800506f9a110600ff00", 2028 "00 dddd0900506f9a110600ff0000", 2029 "00 dddd0900506f9a110600ff0001", 2030 "00 dddd0900506f9a110600ffff00", 2031 "00 dddd0a00506f9a110600ff00013b", 2032 "00 dddd0700506f9a110100ff", 2033 "00 dddd0700506f9a11010008", 2034 "00 dddd14", 2035 "00 dddd1400506f9a11"] 2036 for t in tests: 2037 req = dev[0].request("GAS_REQUEST " + bssid + " " + t) 2038 if "FAIL" in req: 2039 raise Exception("GAS query request rejected") 2040 ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) 2041 if ev is None: 2042 raise Exception("GAS query did not start") 2043 ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) 2044 if ev is None: 2045 raise Exception("GAS query did not complete") 2046 if t == "00 dddd0600506f9a110600": 2047 hapd.set("nai_realm", "0,another.example.com") 2048 2049 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 2050 wpas.interface_add("wlan5") 2051 if "OK" not in wpas.request("P2P_SET listen_channel 1"): 2052 raise Exception("Failed to set listen channel") 2053 if "OK" not in wpas.p2p_listen(): 2054 raise Exception("Failed to start listen state") 2055 if "FAIL" in wpas.request("SET ext_mgmt_frame_handling 1"): 2056 raise Exception("Failed to enable external management frame handling") 2057 2058 anqp_query = struct.pack('<HHHHHHHHHH', 256, 16, 257, 258, 260, 261, 262, 263, 264, 268) 2059 gas = struct.pack('<H', len(anqp_query)) + anqp_query 2060 2061 dialog_token = 100 2062 adv = struct.pack('BBBB', 109, 2, 0, 0) 2063 adv2 = struct.pack('BBB', 108, 1, 0) 2064 adv3 = struct.pack('BBBB', 108, 3, 0, 0) 2065 msg = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2066 dialog_token) + adv + gas 2067 msg2 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2068 dialog_token) + adv2 + gas 2069 msg3 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2070 dialog_token) + adv3 2071 msg4 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2072 dialog_token) + anqp_adv_proto() 2073 msg5 = struct.pack('<BBB', ACTION_CATEG_PUBLIC, GAS_INITIAL_REQUEST, 2074 dialog_token) + anqp_adv_proto() + struct.pack('<H', 1) 2075 msg6 = struct.pack('<BB', ACTION_CATEG_PUBLIC, GAS_COMEBACK_REQUEST) 2076 tests = [msg, msg2, msg3, msg4, msg5, msg6] 2077 for t in tests: 2078 req = "MGMT_TX {} {} freq=2412 wait_time=10 action={}".format(bssid, bssid, binascii.hexlify(t).decode()) 2079 if "OK" not in wpas.request(req): 2080 raise Exception("Could not send management frame") 2081 ev = wpas.wait_event(["MGMT-TX-STATUS"], timeout=5) 2082 if ev is None: 2083 raise Exception("No ACK frame seen") 2084