1# Test a few kernel bugs and functionality 2# Copyright (c) 2016, Intel Deutschland GmbH 3# 4# Author: Johannes Berg <johannes.berg@intel.com> 5# 6# This software may be distributed under the terms of the BSD license. 7# See README for more details. 8 9import hostapd 10import binascii 11import os 12import struct 13from test_wnm import expect_ack 14from tshark import run_tshark 15 16def _test_kernel_bss_leak(dev, apdev, deauth): 17 ssid = "test-bss-leak" 18 passphrase = 'qwertyuiop' 19 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) 20 hapd = hostapd.add_ap(apdev[0], params) 21 hapd.set("ext_mgmt_frame_handling", "1") 22 dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) 23 while True: 24 pkt = hapd.mgmt_rx() 25 if not pkt: 26 raise Exception("MGMT RX wait timed out for auth frame") 27 if pkt['fc'] & 0xc: 28 continue 29 if pkt['subtype'] == 0: # assoc request 30 if deauth: 31 # return a deauth immediately 32 hapd.mgmt_tx({ 33 'fc': 0xc0, 34 'sa': pkt['da'], 35 'da': pkt['sa'], 36 'bssid': pkt['bssid'], 37 'payload': b'\x01\x00', 38 }) 39 break 40 else: 41 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % ( 42 binascii.hexlify(pkt['frame']).decode(), )) 43 hapd.set("ext_mgmt_frame_handling", "0") 44 45 hapd.request("STOP_AP") 46 47 dev[0].request("REMOVE_NETWORK all") 48 dev[0].wait_disconnected() 49 50 dev[0].flush_scan_cache(freq=5180) 51 res = dev[0].request("SCAN_RESULTS") 52 if len(res.splitlines()) > 1: 53 raise Exception("BSS entry should no longer be around") 54 55def test_kernel_bss_leak_deauth(dev, apdev): 56 """cfg80211/mac80211 BSS leak on deauthentication""" 57 return _test_kernel_bss_leak(dev, apdev, deauth=True) 58 59def test_kernel_bss_leak_timeout(dev, apdev): 60 """cfg80211/mac80211 BSS leak on timeout""" 61 return _test_kernel_bss_leak(dev, apdev, deauth=False) 62 63MGMT_SUBTYPE_ACTION = 13 64 65def expect_no_ack(hapd): 66 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 67 if ev is None: 68 raise Exception("Missing TX status") 69 if "ok=0" not in ev: 70 raise Exception("Action frame unexpectedly acknowledged") 71 72def test_kernel_unknown_action_frame_rejection_sta(dev, apdev, params): 73 """mac80211 and unknown Action frame rejection in STA mode""" 74 hapd = hostapd.add_ap(apdev[0], {"ssid": "unknown-action"}) 75 dev[0].connect("unknown-action", key_mgmt="NONE", scan_freq="2412") 76 bssid = hapd.own_addr() 77 addr = dev[0].own_addr() 78 79 hapd.set("ext_mgmt_frame_handling", "1") 80 81 # Unicast Action frame with unknown category (response expected) 82 msg = {} 83 msg['fc'] = MGMT_SUBTYPE_ACTION << 4 84 msg['da'] = addr 85 msg['sa'] = bssid 86 msg['bssid'] = bssid 87 msg['payload'] = struct.pack("<BB", 0x70, 0) 88 hapd.mgmt_tx(msg) 89 expect_ack(hapd) 90 91 # Note: mac80211 does not allow group-addressed Action frames in unknown 92 # categories to be transmitted in AP mode, so for now, these steps are 93 # commented out. 94 95 # Multicast Action frame with unknown category (no response expected) 96 #msg['da'] = "01:ff:ff:ff:ff:ff" 97 #msg['payload'] = struct.pack("<BB", 0x71, 1) 98 #hapd.mgmt_tx(msg) 99 #expect_no_ack(hapd) 100 101 # Broadcast Action frame with unknown category (no response expected) 102 #msg['da'] = "ff:ff:ff:ff:ff:ff" 103 #msg['payload'] = struct.pack("<BB", 0x72, 2) 104 #hapd.mgmt_tx(msg) 105 #expect_no_ack(hapd) 106 107 # Unicast Action frame with error indication category (no response expected) 108 msg['da'] = addr 109 msg['payload'] = struct.pack("<BB", 0xf3, 3) 110 hapd.mgmt_tx(msg) 111 expect_ack(hapd) 112 113 # Unicast Action frame with unknown category (response expected) 114 msg['da'] = addr 115 msg['payload'] = struct.pack("<BB", 0x74, 4) 116 hapd.mgmt_tx(msg) 117 expect_ack(hapd) 118 119 out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"), 120 "wlan.sa == %s && wlan.fc.type_subtype == 0x0d" % addr, 121 display=["wlan_mgt.fixed.category_code"]) 122 res = out.splitlines() 123 categ = [int(x) for x in res] 124 125 if 0xf2 in categ or 0xf3 in categ: 126 raise Exception("Unexpected Action frame rejection: " + str(categ)) 127 if 0xf0 not in categ or 0xf4 not in categ: 128 raise Exception("Action frame rejection missing: " + str(categ)) 129