diff options
Diffstat (limited to 'tests')
39 files changed, 1650 insertions, 173 deletions
diff --git a/tests/fuzzing/p2p/p2p.c b/tests/fuzzing/p2p/p2p.c index 8ffcbbd..fc83c35 100644 --- a/tests/fuzzing/p2p/p2p.c +++ b/tests/fuzzing/p2p/p2p.c @@ -115,7 +115,7 @@ static void test_send(void *eloop_data, void *user_ctx) os_memset(&rx_time, 0, sizeof(rx_time)); p2p_scan_res_handler(ctx->p2p, (u8 *) "\x02\x00\x00\x00\x01\x00", 2412, &rx_time, 0, ctx->data, ctx->data_len); - p2p_scan_res_handled(ctx->p2p); + p2p_scan_res_handled(ctx->p2p, 0); p2p_probe_req_rx(ctx->p2p, (u8 *) "\x02\x00\x00\x00\x01\x00", (u8 *) "\x02\x00\x00\x00\x00\x00", diff --git a/tests/fuzzing/wnm/Makefile b/tests/fuzzing/wnm/Makefile index 73eab53..60d27b3 100644 --- a/tests/fuzzing/wnm/Makefile +++ b/tests/fuzzing/wnm/Makefile @@ -20,7 +20,7 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -OBJS += $(WPAS_SRC)/blacklist.o +OBJS += $(WPAS_SRC)/bssid_ignore.o OBJS += $(WPAS_SRC)/bss.o OBJS += $(WPAS_SRC)/config.o OBJS += $(WPAS_SRC)/config_file.o diff --git a/tests/fuzzing/wnm/wnm.c b/tests/fuzzing/wnm/wnm.c index 9c0d541..7afc648 100644 --- a/tests/fuzzing/wnm/wnm.c +++ b/tests/fuzzing/wnm/wnm.c @@ -16,7 +16,7 @@ #include "wpa_supplicant_i.h" #include "bss.h" #include "wnm_sta.h" -#include "config.h" +#include "../../../wpa_supplicant/config.h" #include "../fuzzer-common.h" diff --git a/tests/hwsim/build.sh b/tests/hwsim/build.sh index 2a3dd70..cb47001 100755 --- a/tests/hwsim/build.sh +++ b/tests/hwsim/build.sh @@ -26,13 +26,18 @@ while [ "$1" != "" ]; do esac done +JOBS=`nproc` +if [ -z "$ABC" ]; then + JOBS=8 +fi + echo "Building TNC testing tools" cd tnc -make QUIET=1 -j8 +make QUIET=1 -j$JOBS echo "Building wlantest" cd ../../../wlantest -make QUIET=1 -j8 > /dev/null +make QUIET=1 -j$JOBS > /dev/null echo "Building hs20-osu-client" cd ../hs20/client/ @@ -54,7 +59,7 @@ if [ $use_lcov -eq 1 ]; then fi fi -make QUIET=1 -j8 hostapd hostapd_cli hlr_auc_gw +make QUIET=1 -j$JOBS hostapd hostapd_cli hlr_auc_gw echo "Building wpa_supplicant" cd ../wpa_supplicant @@ -75,4 +80,4 @@ fi if [ -z $FIPSLD_CC ]; then export FIPSLD_CC=gcc fi -make QUIET=1 -j8 +make QUIET=1 -j$JOBS diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config index 972d35c..8b466e8 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -112,3 +112,4 @@ CONFIG_OWE=y CONFIG_DPP=y CONFIG_DPP2=y CONFIG_WEP=y +CONFIG_PASN=y diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config index 9e3cc67..a579289 100644 --- a/tests/hwsim/example-wpa_supplicant.config +++ b/tests/hwsim/example-wpa_supplicant.config @@ -112,6 +112,7 @@ CONFIG_AUTOSCAN_EXPONENTIAL=y CONFIG_AUTOSCAN_PERIODIC=y CONFIG_EXT_PASSWORD_TEST=y +CONFIG_EXT_PASSWORD_FILE=y CONFIG_EAP_UNAUTH_TLS=y @@ -155,3 +156,4 @@ CONFIG_OWE=y CONFIG_DPP=y CONFIG_DPP2=y CONFIG_WEP=y +CONFIG_PASN=y diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index 5717575..de9263b 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -535,6 +535,23 @@ class Hostapd: def send_file(self, src, dst): self.host.send_file(src, dst) + def get_ptksa(self, bssid, cipher): + res = self.request("PTKSA_CACHE_LIST") + lines = res.splitlines() + for l in lines: + if bssid not in l or cipher not in l: + continue + vals = dict() + [index, addr, cipher, expiration, tk, kdk] = l.split(' ', 5) + vals['index'] = index + vals['addr'] = addr + vals['cipher'] = cipher + vals['expiration'] = expiration + vals['tk'] = tk + vals['kdk'] = kdk + return vals + return None + def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30, global_ctrl_override=None, driver=False): if isinstance(apdev, dict): diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index dec1ad5..0799b95 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -9,6 +9,8 @@ import subprocess import threading import tempfile import os +import traceback +import select logger = logging.getLogger() @@ -99,7 +101,7 @@ class Host(): return status, buf.decode() # async execute - def execute_run(self, command, res, use_reaper=True): + def thread_run(self, command, res, use_reaper=True): if use_reaper: filename = gen_reaper_file("reaper") self.send_file(filename, filename) @@ -113,51 +115,132 @@ class Host(): cmd = _command else: cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] - _cmd = self.name + " execute_run: " + ' '.join(cmd) + _cmd = self.name + " thread_run: " + ' '.join(cmd) logger.debug(_cmd) t = threading.Thread(target=execute_thread, name=filename, args=(cmd, res)) t.start() return t - def execute_stop(self, t): + def thread_stop(self, t): if t.name.find("reaper") == -1: raise Exception("use_reaper required") pid_file = t.name + ".pid" - if t.isAlive(): + if t.is_alive(): cmd = ["kill `cat " + pid_file + "`"] self.execute(cmd) # try again - self.wait_execute_complete(t, 5) - if t.isAlive(): + self.thread_wait(t, 5) + if t.is_alive(): cmd = ["kill `cat " + pid_file + "`"] self.execute(cmd) # try with -9 - self.wait_execute_complete(t, 5) - if t.isAlive(): + self.thread_wait(t, 5) + if t.is_alive(): cmd = ["kill -9 `cat " + pid_file + "`"] self.execute(cmd) - self.wait_execute_complete(t, 5) - if t.isAlive(): + self.thread_wait(t, 5) + if t.is_alive(): raise Exception("thread still alive") self.execute(["rm", pid_file]) self.execute(["rm", t.name]) + self.local_execute(["rm", t.name]) - def wait_execute_complete(self, t, wait=None): + def thread_wait(self, t, wait=None): if wait == None: wait_str = "infinite" else: wait_str = str(wait) + "s" - logger.debug(self.name + " wait_execute_complete(" + wait_str + "): ") - if t.isAlive(): + logger.debug(self.name + " thread_wait(" + wait_str + "): ") + if t.is_alive(): t.join(wait) + def pending(self, s, timeout=0): + [r, w, e] = select.select([s], [], [], timeout) + if r: + return True + return False + + def proc_run(self, command): + filename = gen_reaper_file("reaper") + self.send_file(filename, filename) + self.execute(["chmod", "755", filename]) + _command = [filename] + command + + if self.host: + cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] + else: + cmd = _command + + _cmd = self.name + " proc_run: " + ' '.join(cmd) + logger.debug(_cmd) + err = tempfile.TemporaryFile() + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=err) + proc.reaper_file = filename + return proc + + def proc_wait_event(self, proc, events, timeout=10): + if not isinstance(events, list): + raise Exception("proc_wait_event() events not a list") + + logger.debug(self.name + " proc_wait_event: " + ' '.join(events) + " timeout: " + str(timeout)) + start = os.times()[4] + try: + while True: + while self.pending(proc.stdout): + line = proc.stdout.readline() + if not line: + return None + line = line.decode() + logger.debug(line.strip('\n')) + for event in events: + if event in line: + return line + now = os.times()[4] + remaining = start + timeout - now + if remaining <= 0: + break + if not self.pending(proc.stdout, timeout=remaining): + break + except: + logger.debug(traceback.format_exc()) + pass + return None + + def proc_stop(self, proc): + if not proc: + return + + self.execute(["kill `cat " + proc.reaper_file + ".pid`"]) + self.execute(["rm", proc.reaper_file + ".pid"]) + self.execute(["rm", proc.reaper_file]) + self.local_execute(["rm", proc.reaper_file]) + proc.kill() + + def proc_dump(self, proc): + if not proc: + return "" + return proc.stdout.read() + + def execute_and_wait_event(self, command, events, timeout=10): + proc = None + ev = None + + try: + proc = self.proc_run(command) + ev = self.proc_wait_event(proc, events, timeout) + except: + pass + + self.proc_stop(proc) + return ev + def add_log(self, log_file): self.logs.append(log_file) diff --git a/tests/hwsim/rfkill.py b/tests/hwsim/rfkill.py index f08cf50..72b2527 100755 --- a/tests/hwsim/rfkill.py +++ b/tests/hwsim/rfkill.py @@ -126,7 +126,7 @@ class RFKill(object): @classmethod def list(cls): res = [] - rfk = open('/dev/rfkill', 'rb') + rfk = open('/dev/rfkill', 'rb', buffering=0) fd = rfk.fileno() flgs = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, flgs | os.O_NONBLOCK) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index eb245e7..08eaee5 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -622,3 +622,43 @@ def test_ap_acs_rx_during(dev, apdev): finally: for i in range(3): dev[i].request("SCAN_INTERVAL 5") + +def test_ap_acs_he_24g(dev, apdev): + """Automatic channel selection on 2.4 GHz with HE""" + clear_scan_cache(apdev[0]) + force_prev_ap_on_24g(apdev[0]) + + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['ieee80211ax'] = '1' + params['ht_capab'] = '[HT40+]' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + + freq = hapd.get_status_field("freq") + if int(freq) < 2400: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + +def test_ap_acs_he_24g_overlap(dev, apdev): + """Automatic channel selection on 2.4 GHz with HE (overlap)""" + clear_scan_cache(apdev[0]) + force_prev_ap_on_24g(apdev[0]) + + params = {"ssid": "overlapping", + "channel": "6", "ieee80211n": "1"} + hostapd.add_ap(apdev[1], params) + + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['ieee80211ax'] = '1' + params['ht_capab'] = '[HT40+]' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + + freq = hapd.get_status_field("freq") + if int(freq) < 2400: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index d9f827a..eea17c1 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -415,6 +415,35 @@ def test_ap_cipher_mixed_wpa_wpa2(dev, apdev): hwsim_utils.test_connectivity(dev[0], dev[1]) @remote_compatible +def test_ap_cipher_wpa_sae(dev, apdev): + """WPA-PSK/TKIP and SAE mixed AP - WPA IE and RSNXE coexistence""" + skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) + ssid = "test-wpa-sae" + passphrase = "12345678" + params = {"ssid": ssid, + "wpa_passphrase": passphrase, + "wpa": "3", + "wpa_key_mgmt": "WPA-PSK SAE", + "rsn_pairwise": "CCMP", + "wpa_pairwise": "TKIP", + "sae_pwe": "1"} + hapd = hostapd.add_ap(apdev[0], params) + dev[0].flush_scan_cache() + + dev[0].connect(ssid, psk=passphrase, proto="WPA", + pairwise="TKIP", group="TKIP", scan_freq="2412") + status = dev[0].get_status() + if status['key_mgmt'] != 'WPA-PSK': + raise Exception("Incorrect key_mgmt reported") + if status['pairwise_cipher'] != 'TKIP': + raise Exception("Incorrect pairwise_cipher reported") + if status['group_cipher'] != 'TKIP': + raise Exception("Incorrect group_cipher reported") + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + +@remote_compatible def test_ap_cipher_bip(dev, apdev): """WPA2-PSK with BIP""" check_group_mgmt_cipher(dev[0], apdev[0], "AES-128-CMAC") diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 96d35b9..d23cf0c 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -37,6 +37,44 @@ def test_ap_change_ssid(dev, apdev): dev[0].set_network_quoted(id, "ssid", "test-wpa2-psk-new") dev[0].connect_network(id) +def test_ap_change_ssid_wps(dev, apdev): + """Dynamic SSID change with hostapd and WPA2-PSK using WPS""" + params = hostapd.wpa2_params(ssid="test-wpa2-psk-start", + passphrase="12345678") + # Use a PSK and not the passphrase, because the PSK will have to be computed + # again if we use a passphrase. + del params["wpa_passphrase"] + params["wpa_psk"] = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + + params.update({"wps_state": "2", "eap_server": "1"}) + bssid = apdev[0]['bssid'] + hapd = hostapd.add_ap(apdev[0], params) + + new_ssid = "test-wpa2-psk-new" + logger.info("Change SSID dynamically (WPS)") + res = hapd.request("SET ssid " + new_ssid) + if "OK" not in res: + raise Exception("SET command failed") + res = hapd.request("RELOAD") + if "OK" not in res: + raise Exception("RELOAD command failed") + + # Connect to the new ssid using wps: + hapd.request("WPS_PBC") + if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"): + raise Exception("PBC status not shown correctly") + + dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) + dev[0].request("WPS_PBC") + dev[0].wait_connected(timeout=20) + status = dev[0].get_status() + if status['wpa_state'] != 'COMPLETED' or status['bssid'] != bssid: + raise Exception("Not fully connected") + if status['ssid'] != new_ssid: + raise Exception("Unexpected SSID %s != %s" % (status['ssid'], new_ssid)) + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + def multi_check(apdev, dev, check, scan_opt=True): id = [] num_bss = len(check) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 7395c79..88e03df 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -5922,6 +5922,55 @@ def test_ap_wpa2_eap_tls_13(dev, apdev): dev[0].request("RECONNECT") dev[0].wait_connected() +def test_ap_wpa2_eap_ttls_13(dev, apdev): + """EAP-TTLS and TLS 1.3""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hapd = hostapd.add_ap(apdev[0], params) + + tls = dev[0].request("GET tls_library") + if "run=OpenSSL 1.1.1" not in tls: + raise HwsimSkip("TLS v1.3 not supported") + id = eap_connect(dev[0], hapd, "TTLS", "pap user", + anonymous_identity="ttls", password="password", + ca_cert="auth_serv/ca.pem", + phase1="tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", + phase2="auth=PAP") + ver = dev[0].get_status_field("eap_tls_version") + if ver != "TLSv1.3": + raise Exception("Unexpected TLS version") + + eap_reauth(dev[0], "TTLS") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("PMKSA_FLUSH") + dev[0].request("RECONNECT") + dev[0].wait_connected() + +def test_ap_wpa2_eap_peap_13(dev, apdev): + """PEAP and TLS 1.3""" + check_eap_capa(dev[0], "MSCHAPV2") + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + hapd = hostapd.add_ap(apdev[0], params) + + tls = dev[0].request("GET tls_library") + if "run=OpenSSL 1.1.1" not in tls: + raise HwsimSkip("TLS v1.3 not supported") + id = eap_connect(dev[0], hapd, "PEAP", "user", + anonymous_identity="peap", password="password", + ca_cert="auth_serv/ca.pem", + phase1="tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", + phase2="auth=MSCHAPV2") + ver = dev[0].get_status_field("eap_tls_version") + if ver != "TLSv1.3": + raise Exception("Unexpected TLS version") + + eap_reauth(dev[0], "PEAP") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("PMKSA_FLUSH") + dev[0].request("RECONNECT") + dev[0].wait_connected() + def test_ap_wpa2_eap_tls_13_ec(dev, apdev): """EAP-TLS and TLS 1.3 (EC certificates)""" params = {"ssid": "test-wpa2-eap", diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index f2ca6f1..1598c89 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -136,7 +136,8 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, group_mgmt=None, ocv=None, sae_password=None, sae_password_id=None, sae_and_psk=False, pmksa_caching=False, roam_with_reassoc=False, also_non_ft=False, only_one_way=False, - wait_before_roam=0, return_after_initial=False, ieee80211w="1"): + wait_before_roam=0, return_after_initial=False, ieee80211w="1", + sae_transition=False): logger.info("Connect to first AP") copts = {} @@ -161,7 +162,9 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, copts["identity"] = eap_identity copts["password"] = "abcdefghijklmnop0123456789abcdef" else: - if sae: + if sae_transition: + copts["key_mgmt"] = "FT-SAE FT-PSK" + elif sae: copts["key_mgmt"] = "SAE FT-SAE" if sae_and_psk else "FT-SAE" else: copts["key_mgmt"] = "FT-PSK" @@ -998,7 +1001,8 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, rsne_override=None, rsnxe_override=None, no_beacon_rsnxe2=False, ext_key_id=False, - skip_prune_assoc=False, ft_rsnxe_used=False): + skip_prune_assoc=False, ft_rsnxe_used=False, + sae_transition=False): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -1022,7 +1026,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['ft_rsnxe_used'] = '1' hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) - params['wpa_key_mgmt'] = "FT-SAE" + if not sae_transition: + params['wpa_key_mgmt'] = "FT-SAE" if wpa_ptk_rekey: params['wpa_ptk_rekey'] = str(wpa_ptk_rekey) if sae_pwe is not None: @@ -1041,7 +1046,7 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['ft_rsnxe_used'] = '1' hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] - if key_mgmt.split(' ')[0] != "FT-SAE": + if key_mgmt.split(' ')[0] != "FT-SAE" and not sae_transition: raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) dev.request("SET sae_groups ") @@ -1052,6 +1057,12 @@ def test_ap_ft_sae(dev, apdev): hapd0, hapd1 = start_ft_sae(dev[0], apdev) run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) +def test_ap_ft_sae_transition(dev, apdev): + """WPA2-PSK-FT-SAE/PSK AP""" + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_transition=True) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", + sae_transition=True) + def test_ap_ft_sae_h2e(dev, apdev): """WPA2-PSK-FT-SAE AP (H2E)""" try: @@ -1595,7 +1606,14 @@ def test_ap_ft_eap_pull_wildcard_multi_bss(dev, apdev, params): f.write("interface=%s\n" % ifname2) f.write("bssid=%s\n" % bssid2) f.write("ctrl_interface=/var/run/hostapd\n") + + fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt", + "wpa", "rsn_pairwise", "auth_server_addr"] + for name in fields: + f.write("%s=%s\n" % (name, params[name])) for name, val in params.items(): + if name in fields: + continue f.write("%s=%s\n" % (name, val)) hapd2 = hostapd.add_bss(apdev[0], ifname2, bssconf) @@ -3334,9 +3352,11 @@ def test_ap_ft_r0_key_expiration(dev, apdev): passphrase = "12345678" params = ft_params1(ssid=ssid, passphrase=passphrase) + params.pop('r0_key_lifetime', None) params['ft_r0_key_lifetime'] = "2" hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) + params.pop('r0_key_lifetime', None) params['ft_r0_key_lifetime'] = "2" hapd1 = hostapd.add_ap(apdev[1], params) diff --git a/tests/hwsim/test_ap_open.py b/tests/hwsim/test_ap_open.py index 62b4446..a3bea76 100644 --- a/tests/hwsim/test_ap_open.py +++ b/tests/hwsim/test_ap_open.py @@ -198,19 +198,15 @@ def test_ap_open_unexpected_assoc_event(dev, apdev): dev[0].request("DISCONNECT") dev[0].wait_disconnected(timeout=15) dev[0].dump_monitor() - # This will be accepted due to matching network + # This association will be ignored by wpa_supplicant since the current + # state is not to try to connect after that DISCONNECT command. dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412", apdev[0]['bssid']]) - dev[0].wait_connected(timeout=15) - dev[0].dump_monitor() - - dev[0].request("REMOVE_NETWORK all") - dev[0].wait_disconnected(timeout=5) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.3) + dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, 'disconnect']) dev[0].dump_monitor() - # This will result in disconnection due to no matching network - dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412", - apdev[0]['bssid']]) - dev[0].wait_disconnected(timeout=15) + if ev is not None: + raise Exception("Unexpected connection") def test_ap_open_external_assoc(dev, apdev): """AP with open mode and external association""" @@ -301,18 +297,18 @@ def test_ap_open_out_of_memory(dev, apdev): # not fail hostapd.add_ap(apdev[1], {"ssid": "open"}) -def test_bssid_black_white_list(dev, apdev): - """BSSID black/white list""" +def test_bssid_ignore_accept(dev, apdev): + """BSSID ignore/accept list""" hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) hapd2 = hostapd.add_ap(apdev[1], {"ssid": "open"}) dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", - bssid_whitelist=apdev[1]['bssid']) + bssid_accept=apdev[1]['bssid']) dev[1].connect("open", key_mgmt="NONE", scan_freq="2412", - bssid_blacklist=apdev[1]['bssid']) + bssid_ignore=apdev[1]['bssid']) dev[2].connect("open", key_mgmt="NONE", scan_freq="2412", - bssid_whitelist="00:00:00:00:00:00/00:00:00:00:00:00", - bssid_blacklist=apdev[1]['bssid']) + bssid_accept="00:00:00:00:00:00/00:00:00:00:00:00", + bssid_ignore=apdev[1]['bssid']) if dev[0].get_status_field('bssid') != apdev[1]['bssid']: raise Exception("dev[0] connected to unexpected AP") if dev[1].get_status_field('bssid') != apdev[0]['bssid']: @@ -324,11 +320,11 @@ def test_bssid_black_white_list(dev, apdev): dev[2].request("REMOVE_NETWORK all") dev[2].connect("open", key_mgmt="NONE", scan_freq="2412", - bssid_whitelist="00:00:00:00:00:00", wait_connect=False) + bssid_accept="00:00:00:00:00:00", wait_connect=False) dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", - bssid_whitelist="11:22:33:44:55:66/ff:00:00:00:00:00 " + apdev[1]['bssid'] + " aa:bb:cc:dd:ee:ff") + bssid_accept="11:22:33:44:55:66/ff:00:00:00:00:00 " + apdev[1]['bssid'] + " aa:bb:cc:dd:ee:ff") dev[1].connect("open", key_mgmt="NONE", scan_freq="2412", - bssid_blacklist="11:22:33:44:55:66/ff:00:00:00:00:00 " + apdev[1]['bssid'] + " aa:bb:cc:dd:ee:ff") + bssid_ignore="11:22:33:44:55:66/ff:00:00:00:00:00 " + apdev[1]['bssid'] + " aa:bb:cc:dd:ee:ff") if dev[0].get_status_field('bssid') != apdev[1]['bssid']: raise Exception("dev[0] connected to unexpected AP") if dev[1].get_status_field('bssid') != apdev[0]['bssid']: @@ -586,17 +582,17 @@ def test_ap_open_select_network(dev, apdev): dev[0].select_network(id1) dev[0].wait_connected() - res = dev[0].request("BLACKLIST") + res = dev[0].request("BSSID_IGNORE") if bssid1 in res or bssid2 in res: - raise Exception("Unexpected blacklist entry") + raise Exception("Unexpected BSSID ignore list entry") hwsim_utils.test_connectivity(dev[0], hapd1) dev[0].select_network(id2) dev[0].wait_connected() hwsim_utils.test_connectivity(dev[0], hapd2) - res = dev[0].request("BLACKLIST") + res = dev[0].request("BSSID_IGNORE") if bssid1 in res or bssid2 in res: - raise Exception("Unexpected blacklist entry(2)") + raise Exception("Unexpected BSSID ignore list entry(2)") @remote_compatible def test_ap_open_disable_enable(dev, apdev): @@ -917,9 +913,9 @@ def test_ap_open_disable_select(dev, apdev): dev[0].request("DISABLE_NETWORK %d" % id) dev[0].wait_disconnected() - res = dev[0].request("BLACKLIST") + res = dev[0].request("BSSID_IGNORE") if hapd1.own_addr() in res or hapd2.own_addr() in res: - raise Exception("Unexpected blacklist entry added") + raise Exception("Unexpected BSSID ignore list entry added") dev[0].request("SELECT_NETWORK %d" % id) dev[0].wait_connected() diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index 7918057..0735127 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -254,6 +254,29 @@ def test_ap_acl_mgmt(dev, apdev): if filename.startswith('/tmp/'): os.unlink(filename) +def test_ap_acl_accept_changes(dev, apdev): + """MAC ACL accept list changes""" + ssid = "acl" + params = {} + params['ssid'] = ssid + params['macaddr_acl'] = "1" + hapd = hostapd.add_ap(apdev[0], params) + hapd.request("ACCEPT_ACL ADD_MAC " + dev[0].own_addr()) + hapd.request("ACCEPT_ACL ADD_MAC " + dev[1].own_addr()) + dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") + dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") + dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412") + dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") + hapd.request("ACCEPT_ACL DEL_MAC " + dev[0].own_addr()) + dev[0].wait_disconnected() + dev[0].request("DISCONNECT") + ev = dev[1].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.1) + if ev is not None: + raise Exception("Unexpected disconnection") + hapd.request("ACCEPT_ACL CLEAR") + dev[1].wait_disconnected() + dev[1].request("DISCONNECT") + @remote_compatible def test_ap_wds_sta(dev, apdev): """WPA2-PSK AP with STA using 4addr mode""" @@ -843,3 +866,29 @@ def test_ap_wowlan_triggers(dev, apdev): dev[0].scan_for_bss(bssid, freq="2412") dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") hwsim_utils.test_connectivity(dev[0], hapd) + +def test_ap_notify_mgmt_frames(dev, apdev): + """hostapd notify_mgmt_frames configuration enabled""" + ssid = "mgmt_frames" + params = {'ssid': ssid, 'notify_mgmt_frames': "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") + ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=5) + if ev is None: + raise Exception("AP-MGMT-FRAME-RECEIVED wait timed out") + if "buf=b0" not in ev: + raise Exception("Expected auth request in AP-MGMT-FRAME-RECEIVED") + +def test_ap_notify_mgmt_frames_disabled(dev, apdev): + """hostapd notify_mgmt_frames configuration disabled""" + ssid = "mgmt_frames" + params = {'ssid': ssid, 'notify_mgmt_frames': "0"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") + ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=0.1) + if ev is not None: + raise Exception("Unexpected AP-MGMT-FRAME-RECEIVED") diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index 9bc1414..db10377 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -685,6 +685,8 @@ def setup_psk_ext(dev, apdev, wpa_ptk_rekey=None): def ext_4way_hs(hapd, dev): bssid = hapd.own_addr() addr = dev.own_addr() + first = None + last = None while True: ev = hapd.wait_event(["EAPOL-TX", "AP-STA-CONNECTED"], timeout=15) if ev is None: @@ -692,6 +694,9 @@ def ext_4way_hs(hapd, dev): if "AP-STA-CONNECTED" in ev: dev.wait_connected(timeout=15) break + if not first: + first = ev.split(' ')[2] + last = ev.split(' ')[2] res = dev.request("EAPOL_RX " + bssid + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to wpa_supplicant failed") @@ -703,12 +708,41 @@ def ext_4way_hs(hapd, dev): res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to hostapd failed") + return first, last def test_ap_wpa2_psk_ext(dev, apdev): """WPA2-PSK AP using external EAPOL I/O""" hapd = setup_psk_ext(dev[0], apdev[0]) ext_4way_hs(hapd, dev[0]) +def test_ap_wpa2_psk_unexpected(dev, apdev): + """WPA2-PSK and supplicant receiving unexpected EAPOL-Key frames""" + hapd = setup_psk_ext(dev[0], apdev[0]) + first, last = ext_4way_hs(hapd, dev[0]) + + # Not associated - Delay processing of received EAPOL frame (state=COMPLETED + # bssid=02:00:00:00:03:00) + other = "02:11:22:33:44:55" + res = dev[0].request("EAPOL_RX " + other + " " + first) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + # WPA: EAPOL-Key Replay Counter did not increase - dropping packet + bssid = hapd.own_addr() + res = dev[0].request("EAPOL_RX " + bssid + " " + last) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + # WPA: Invalid EAPOL-Key MIC - dropping packet + msg = last[0:18] + '01' + last[20:] + res = dev[0].request("EAPOL_RX " + bssid + " " + msg) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=12) + if ev is not None: + raise Exception("Unexpected disconnection") + def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4""" hapd = setup_psk_ext(dev[0], apdev[0]) diff --git a/tests/hwsim/test_ap_roam.py b/tests/hwsim/test_ap_roam.py index fca3b57..8488889 100644 --- a/tests/hwsim/test_ap_roam.py +++ b/tests/hwsim/test_ap_roam.py @@ -26,8 +26,8 @@ def test_ap_roam_open(dev, apdev): dev[0].roam(apdev[0]['bssid']) hwsim_utils.test_connectivity(dev[0], hapd0) -def test_ap_blacklist_all(dev, apdev, params): - """Ensure we clear the blacklist if all visible APs reject""" +def test_ap_ignore_bssid_all(dev, apdev, params): + """Ensure we clear the ignore BSSID list if all visible APs reject""" hapd0 = hostapd.add_ap(apdev[0], {"ssid": "test-open", "max_num_sta": "0"}) hapd1 = hostapd.add_ap(apdev[1], {"ssid": "test-open", "max_num_sta": "0"}) bss0 = hapd0.own_addr() @@ -43,13 +43,13 @@ def test_ap_blacklist_all(dev, apdev, params): wait_connect=False, bssid=bss1) if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): raise Exception("AP 1 didn't reject us") - blacklist = get_blacklist(dev[0]) - logger.info("blacklist: " + str(blacklist)) + ignore_list = get_bssid_ignore_list(dev[0]) + logger.info("ignore list: " + str(ignore_list)) dev[0].request("REMOVE_NETWORK all") dev[0].dump_monitor() hapd0.set("max_num_sta", "1") - # All visible APs were blacklisted; we should clear the blacklist and find + # All visible APs were ignored; we should clear the ignore list and find # the AP that now accepts us. dev[0].scan_for_bss(bss0, freq=2412) dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", bssid=bss0) @@ -141,8 +141,8 @@ def test_ap_roam_wpa2_psk_pmf_mismatch(dev, apdev): raise Exception("Unexpected BSSID reported after failed roam attempt: " + bssid) hwsim_utils.test_connectivity(dev[0], hapd0) -def get_blacklist(dev): - return dev.request("BLACKLIST").splitlines() +def get_bssid_ignore_list(dev): + return dev.request("BSSID_IGNORE").splitlines() def test_ap_reconnect_auth_timeout(dev, apdev, params): """Reconnect to 2nd AP and authentication times out""" @@ -162,7 +162,7 @@ def test_ap_reconnect_auth_timeout(dev, apdev, params): hapd1 = hostapd.add_ap(apdev[1], params) bssid1 = hapd1.own_addr() - wpas.request("BLACKLIST " + bssid0) + wpas.request("BSSID_IGNORE " + bssid0) wpas.scan_for_bss(bssid1, freq=2412) wpas.request("DISCONNECT") @@ -179,11 +179,11 @@ def test_ap_reconnect_auth_timeout(dev, apdev, params): if not ev: raise Exception("CTRL-EVENT-SCAN-STARTED not seen") - b = get_blacklist(wpas) + b = get_bssid_ignore_list(wpas) if '00:00:00:00:00:00' in b: - raise Exception("Unexpected blacklist contents: " + str(b)) + raise Exception("Unexpected ignore list contents: " + str(b)) if bssid1 not in b: - raise Exception("Unexpected blacklist contents: " + str(b)) + raise Exception("Unexpected ignore list contents: " + str(b)) def test_ap_roam_with_reassoc_auth_timeout(dev, apdev, params): """Roam using reassoc between two APs and authentication times out""" @@ -216,9 +216,9 @@ def test_ap_roam_with_reassoc_auth_timeout(dev, apdev, params): if not ev: raise Exception("CTRL-EVENT-SCAN-STARTED not seen") - b = get_blacklist(wpas) + b = get_bssid_ignore_list(wpas) if bssid0 in b: - raise Exception("Unexpected blacklist contents: " + str(b)) + raise Exception("Unexpected ignore list contents: " + str(b)) def test_ap_roam_wpa2_psk_failed(dev, apdev, params): """Roam failure with WPA2-PSK AP due to wrong passphrase""" diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index a2bf6d4..8cdd002 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -639,6 +639,8 @@ def test_ap_sae_tdls(dev, apdev): """SAE AP and two stations using TDLS""" check_sae_capab(dev[0]) check_sae_capab(dev[1]) + dev[0].request("SET sae_groups ") + dev[1].request("SET sae_groups ") params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") params['wpa_key_mgmt'] = 'SAE' params["ieee80211w"] = "2" diff --git a/tests/hwsim/test_dfs.py b/tests/hwsim/test_dfs.py index 3efe6bb..c587653 100644 --- a/tests/hwsim/test_dfs.py +++ b/tests/hwsim/test_dfs.py @@ -652,3 +652,116 @@ def test_dfs_chan_switch(dev, apdev): hwsim_utils.test_connectivity(dev[0], hapd) finally: clear_regdom(hapd, dev) + +@long_duration_test +def test_dfs_no_available_channel(dev, apdev): + """DFS and no available channel after radar detection""" + try: + hapd = None + hapd = start_dfs_ap(apdev[0], chanlist="56") + + ev = hapd.wait_event(["AP-ENABLED"], timeout=70) + if not ev: + raise Exception("AP2 setup timed out") + + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5260 ht_enabled=1 chan_offset=0 chan_width=1" not in ev: + raise Exception("Unexpected DFS radar detection freq from AP") + + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5280 chan=56" not in ev: + raise Exception("Unexpected DFS new freq: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) + if "freq=5280" not in ev: + raise Exception("Unexpected channel: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5280" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5280 ht_enabled=1 chan_offset=0 chan_width=1" not in ev: + raise Exception("Unexpected DFS radar detection freq from AP [2]") + + ev = hapd.wait_event(["AP-DISABLED"], timeout=10) + if ev is None: + raise Exception("AP was not disabled") + finally: + clear_regdom(hapd, dev) + +def dfs_chan_switch_precac(dev, apdev, country): + """DFS channel switch pre CAC""" + try: + hapd = None + + # Toggle regulatory - clean all preCAC + hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', 'US']) + + hapd = start_dfs_ap(apdev[0], country=country) + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5260" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + freq = hapd.get_status_field("freq") + if freq != "5260": + raise Exception("Unexpected frequency") + + # TODO add/connect station here + # Today skip this step while dev[0].connect() + # for some reason toggle regulatory to US + # and clean preCAC + + # Back to non DFS channel + if "OK" not in hapd.request("CHAN_SWITCH 5 5180 ht"): + raise Exception("CHAN_SWITCH 5180 failed") + + ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=5) + if not ev: + raise Exception("No CSA finished event - 5180") + freq = hapd.get_status_field("freq") + if freq != "5180": + raise Exception("Unexpected frequency") + + # Today cfg80211 first send AP-CSA-FINISHED and next + # DFS-PRE-CAC-EXPIRED + ev = hapd.wait_event(["DFS-PRE-CAC-EXPIRED"], timeout=3) + if not ev and country == 'US': + raise Exception("US - no CAC-EXPIRED event") + + # Back again to DFS channel (CAC passed) + if "OK" not in hapd.request("CHAN_SWITCH 5 5260 ht"): + raise Exception("CHAN_SWITCH 5260 failed") + + if country == 'US': + # For non EU we should start CAC again + ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) + if not ev: + raise Exception("No DFS CAC start event") + else: + # For EU preCAC should be used + ev = wait_dfs_event(hapd, "AP-CSA-FINISHED", 5) + if not ev: + raise Exception("No CSA finished event - 5260") + finally: + clear_regdom(hapd, dev) + +@long_duration_test +def test_dfs_eu_chan_switch_precac(dev, apdev): + """DFS channel switch pre CAC - ETSI domain""" + dfs_chan_switch_precac(dev, apdev, 'PL') + +@long_duration_test +def test_dfs_us_chan_switch_precac(dev, apdev): + """DFS channel switch pre CAC - FCC domain""" + dfs_chan_switch_precac(dev, apdev, 'US') diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index ff03814..233c6a5 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -2821,6 +2821,7 @@ def run_dpp_proto_init(dev, test_dev, test, mutual=False, unicast=True, own = id1b dev[1].dpp_auth_init(uri=uri0, role=role, configurator=configurator, conf=conf, own=own) + return uri0, role, configurator, conf, own def test_dpp_proto_after_wrapped_data_auth_req(dev, apdev): """DPP protocol testing - attribute after Wrapped Data in Auth Req""" @@ -3249,7 +3250,7 @@ def test_dpp_proto_stop_at_auth_req(dev, apdev): def test_dpp_proto_stop_at_auth_resp(dev, apdev): """DPP protocol testing - stop when receiving Auth Resp""" - run_dpp_proto_init(dev, 1, 88) + uri0, role, configurator, conf, own = run_dpp_proto_init(dev, 1, 88) ev = dev[1].wait_event(["DPP-TX "], timeout=5) if ev is None: @@ -3263,6 +3264,18 @@ def test_dpp_proto_stop_at_auth_resp(dev, apdev): if ev is not None: raise Exception("Unexpected Auth Conf TX") + ev = dev[0].wait_event(["DPP-FAIL"], timeout=2) + if ev is None or "No Auth Confirm received" not in ev: + raise Exception("DPP-FAIL for missing Auth Confirm not reported") + time.sleep(0.1) + + # Try again without special testing behavior to confirm Responder is able + # to accept a new provisioning attempt. + dev[1].set("dpp_test", "0") + dev[1].dpp_auth_init(uri=uri0, role=role, configurator=configurator, + conf=conf, own=own) + wait_auth_success(dev[0], dev[1]) + def test_dpp_proto_stop_at_auth_conf(dev, apdev): """DPP protocol testing - stop when receiving Auth Conf""" run_dpp_proto_init(dev, 0, 89, init_enrollee=True) @@ -5378,6 +5391,14 @@ def test_dpp_chirp_configurator(dev, apdev): if "type=13" not in ev: raise Exception("Unexpected DPP frame received: " + ev) + ev = dev[1].wait_event(["DPP-TX"], timeout=10) + if ev is None: + raise Exception("Authentication Request TX not seen") + if "type=0" not in ev: + raise Exception("Unexpected DPP frame TX: " + ev) + if "dst=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected Authentication Request destination: " + ev) + wait_auth_success(dev[0], dev[1], dev[1], dev[0]) def test_dpp_chirp_configurator_inits(dev, apdev): @@ -5967,6 +5988,9 @@ def test_dpp_enterprise_reject(dev, apdev, params): def test_dpp_enterprise_tcp(dev, apdev, params): """DPP over TCP for enterprise provisioning""" + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + try: run_dpp_enterprise_tcp(dev, apdev, params) finally: @@ -6054,6 +6078,9 @@ def run_dpp_enterprise_tcp_end(params, dev, wt): def test_dpp_enterprise_tcp2(dev, apdev, params): """DPP over TCP for enterprise provisioning (Controller initiating)""" + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + try: run_dpp_enterprise_tcp2(dev, apdev, params) finally: diff --git a/tests/hwsim/test_eap_proto.py b/tests/hwsim/test_eap_proto.py index 7494b42..3401749 100644 --- a/tests/hwsim/test_eap_proto.py +++ b/tests/hwsim/test_eap_proto.py @@ -5629,8 +5629,7 @@ def test_eap_proto_aka_errors(dev, apdev): tests = [(1, "=eap_aka_learn_ids"), (2, "=eap_aka_learn_ids"), (1, "eap_sim_parse_encr;eap_aka_process_challenge"), - (1, "wpabuf_dup;eap_aka_add_id_msg"), - (1, "wpabuf_resize;eap_aka_add_id_msg"), + (1, "wpabuf_alloc;eap_aka_add_id_msg"), (1, "eap_aka_getKey"), (1, "eap_aka_get_emsk"), (1, "eap_aka_get_session_id")] diff --git a/tests/hwsim/test_ext_password.py b/tests/hwsim/test_ext_password.py index dfaf3ea..789b673 100644 --- a/tests/hwsim/test_ext_password.py +++ b/tests/hwsim/test_ext_password.py @@ -7,6 +7,8 @@ from remotehost import remote_compatible import logging logger = logging.getLogger() +import os +import tempfile import hostapd from utils import skip_with_fips @@ -79,3 +81,32 @@ def test_ext_password_interworking(dev, apdev): dev[0].set_cred(id, "password", "ext:pw1") interworking_select(dev[0], bssid, freq="2412") interworking_connect(dev[0], bssid, "TTLS") + +def test_ext_password_file_psk(dev, apdev): + """External password (file) storage for PSK""" + params = hostapd.wpa2_params(ssid="ext-pw-psk", passphrase="12345678") + hostapd.add_ap(apdev[0], params) + fd, fn = tempfile.mkstemp() + with open(fn, "w") as f: + f.write("psk1=12345678\n") + os.close(fd) + dev[0].request("SET ext_password_backend file:%s" % fn) + dev[0].connect("ext-pw-psk", raw_psk="ext:psk1", scan_freq="2412") + for i in range(2): + dev[0].request("REMOVE_NETWORK all") + if i == 0: + dev[0].wait_disconnected() + dev[0].connect("ext-pw-psk", raw_psk="ext:psk2", scan_freq="2412", + wait_connect=False) + else: + dev[0].connect("ext-pw-psk", raw_psk="ext:psk1", scan_freq="2412", + wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "EXT PW: No PSK found from external storage"], + timeout=10) + if i == 0: + os.unlink(fn) + if ev is None: + raise Exception("No connection result reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py index 8e4df65..4616ca3 100644 --- a/tests/hwsim/test_fils.py +++ b/tests/hwsim/test_fils.py @@ -2330,3 +2330,37 @@ def test_fils_auth_ptk_rekey_ap_ext_key_id(dev, apdev, params): hwsim_utils.test_connectivity(dev[0], hapd) finally: dev[0].set("extended_key_id", "0") + +def test_fils_discovery_frame(dev, apdev, params): + """FILS Discovery frame generation""" + check_fils_capa(dev[0]) + check_erp_capa(dev[0]) + + start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst")) + + bssid = apdev[0]['bssid'] + params = hostapd.wpa2_eap_params(ssid="fils") + params['wpa_key_mgmt'] = "FILS-SHA256" + params['auth_server_port'] = "18128" + params['erp_send_reauth_start'] = '1' + params['erp_domain'] = 'example.com' + params['fils_realm'] = 'example.com' + params['wpa_group_rekey'] = '1' + params['fils_discovery_min_interval'] = '20' + params['fils_discovery_max_interval'] = '20' + hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True) + + if "OK" not in hapd.request("ENABLE"): + raise HwsimSkip("FILS Discovery frame transmission not supported") + + ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=5) + if ev is None: + raise Exception("AP startup timed out") + if "AP-ENABLED" not in ev: + raise Exception("AP startup failed") + + dev[0].request("ERP_FLUSH") + dev[0].connect("fils", key_mgmt="FILS-SHA256", + eap="PSK", identity="psk.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + erp="1", scan_freq="2412") diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index 28123e8..21c1b55 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -67,6 +67,12 @@ def test_he_params(dev, apdev): "he_spr_non_srg_obss_pd_max_offset": "0", "he_spr_srg_obss_pd_min_offset": "0", "he_spr_srg_obss_pd_max_offset": "0", + "he_spr_srg_bss_colors": "1 2 10 63", + "he_spr_srg_partial_bssid": "0 1 3 63", + "he_6ghz_max_ampdu_len_exp": "7", + "he_6ghz_rx_ant_pat": "1", + "he_6ghz_tx_ant_pat": "1", + "he_6ghz_max_mpdu": "2", "he_oper_chwidth": "0", "he_oper_centr_freq_seg0_idx": "1", "he_oper_centr_freq_seg1_idx": "0"} @@ -154,27 +160,19 @@ def test_he80(dev, apdev): dev[0].request("DISCONNECT") clear_regdom(hapd, dev) -def test_he_wifi_generation(dev, apdev): +def _test_he_wifi_generation(dev, apdev, conf, scan_freq): """HE and wifi_generation""" try: hapd = None params = {"ssid": "he", "country_code": "FI", - "hw_mode": "a", - "channel": "36", - "ht_capab": "[HT40+]", "ieee80211n": "1", - "ieee80211ac": "1", - "ieee80211ax": "1", - "vht_oper_chwidth": "1", - "vht_capab": "[MAX-MPDU-11454]", - "vht_oper_centr_freq_seg0_idx": "42", - "he_oper_chwidth": "1", - "he_oper_centr_freq_seg0_idx": "42"} + "ieee80211ax": "1"} + params.update(conf) hapd = hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] - dev[0].connect("he", key_mgmt="NONE", scan_freq="5180") + dev[0].connect("he", key_mgmt="NONE", scan_freq=scan_freq) status = dev[0].get_status() if 'wifi_generation' not in status: # For now, assume this is because of missing kernel support @@ -185,7 +183,7 @@ def test_he_wifi_generation(dev, apdev): wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") - wpas.connect("he", key_mgmt="NONE", scan_freq="5180") + wpas.connect("he", key_mgmt="NONE", scan_freq=scan_freq) status = wpas.get_status() if 'wifi_generation' not in status: # For now, assume this is because of missing kernel support @@ -202,6 +200,27 @@ def test_he_wifi_generation(dev, apdev): dev[0].request("DISCONNECT") clear_regdom(hapd, dev) +def test_he_wifi_generation(dev, apdev): + conf = { + "vht_oper_chwidth": "1", + "hw_mode": "a", + "channel": "36", + "ht_capab": "[HT40+]", + "vht_oper_centr_freq_seg0_idx": "42", + "he_oper_chwidth": "1", + "he_oper_centr_freq_seg0_idx": "42", + "vht_capab": "[MAX-MPDU-11454]", + "ieee80211ac": "1", + } + _test_he_wifi_generation(dev, apdev, conf, "5180") + +def test_he_wifi_generation_24(dev, apdev): + conf = { + "hw_mode": "g", + "channel": "1", + } + _test_he_wifi_generation(dev, apdev, conf, "2412") + def he80_test(apdev, dev, channel, ht_capab): clear_scan_cache(apdev) try: @@ -992,7 +1011,7 @@ def test_he_tkip(dev, apdev): raise Exception("Unexpected STATUS ieee80211n value") if status["ieee80211ac"] != "0": raise Exception("Unexpected STATUS ieee80211ac value") - if status["ieee80211ax"] != "1": + if status["ieee80211ax"] != "0": raise Exception("Unexpected STATUS ieee80211ax value") if status["secondary_channel"] != "0": raise Exception("Unexpected STATUS secondary_channel value") diff --git a/tests/hwsim/test_multi_ap.py b/tests/hwsim/test_multi_ap.py index 4070d3e..ff761f3 100644 --- a/tests/hwsim/test_multi_ap.py +++ b/tests/hwsim/test_multi_ap.py @@ -5,6 +5,7 @@ # See README for more details. import hostapd +from wpasupplicant import WpaSupplicant from utils import * def test_multi_ap_association(dev, apdev): @@ -38,6 +39,42 @@ def run_multi_ap_association(dev, apdev, multi_ap, wait_connect=True): dev[0].connect("multi-ap", psk="12345678", scan_freq="2412", multi_ap_backhaul_sta="1", wait_connect=wait_connect) +def test_multi_ap_backhaul_roam_with_bridge(dev, apdev): + """Multi-AP backhaul BSS reassociation to another BSS with bridge""" + br_ifname = 'sta-br0' + ifname = 'wlan5' + try: + run_multi_ap_backhaul_roam_with_bridge(dev, apdev) + finally: + subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down']) + subprocess.call(['brctl', 'delif', br_ifname, ifname]) + subprocess.call(['brctl', 'delbr', br_ifname]) + subprocess.call(['iw', ifname, 'set', '4addr', 'off']) + +def run_multi_ap_backhaul_roam_with_bridge(dev, apdev): + br_ifname = 'sta-br0' + ifname = 'wlan5' + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + subprocess.call(['brctl', 'addbr', br_ifname]) + subprocess.call(['brctl', 'setfd', br_ifname, '0']) + subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up']) + subprocess.call(['iw', ifname, 'set', '4addr', 'on']) + subprocess.check_call(['brctl', 'addif', br_ifname, ifname]) + wpas.interface_add(ifname, br_ifname=br_ifname) + wpas.flush_scan_cache() + + params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678") + params["multi_ap"] = "1" + hapd = hostapd.add_ap(apdev[0], params) + + wpas.connect("multi-ap", psk="12345678", scan_freq="2412", + multi_ap_backhaul_sta="1") + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + wpas.scan_for_bss(bssid2, freq="2412", force_scan=True) + wpas.roam(bssid2) + def test_multi_ap_disabled_on_ap(dev, apdev): """Multi-AP association attempt when disabled on AP""" run_multi_ap_association(dev, apdev, 0, wait_connect=False) @@ -63,7 +100,8 @@ def test_multi_ap_fronthaul_on_ap(dev, apdev): if "CTRL-EVENT-DISCONNECTED" not in ev: raise Exception("Unexpected connection result") -def run_multi_ap_wps(dev, apdev, params, multi_ap_bssid=None): +def run_multi_ap_wps(dev, apdev, params, params_backhaul=None, add_apdev=False, + run_csa=False, allow_csa_fail=False): """Helper for running Multi-AP WPS tests dev[0] does multi_ap WPS, dev[1] does normal WPS. apdev[0] is the fronthaul @@ -72,8 +110,14 @@ def run_multi_ap_wps(dev, apdev, params, multi_ap_bssid=None): the WPS parameters. multi_ap_bssid must be given if it is not equal to the fronthaul BSSID.""" - if multi_ap_bssid is None: + wpas_apdev = None + + if params_backhaul: + hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul) + multi_ap_bssid = hapd_backhaul.own_addr() + else: multi_ap_bssid = apdev[0]['bssid'] + params.update({"wps_state": "2", "eap_server": "1"}) # WPS with multi-ap station dev[0] @@ -130,6 +174,42 @@ def run_multi_ap_wps(dev, apdev, params, multi_ap_bssid=None): if len(dev[1].list_networks()) != 1: raise Exception("Unexpected number of network blocks") + try: + # Add apdev to the same phy that dev[0] + if add_apdev: + wpas_apdev = {} + wpas_apdev['ifname'] = dev[0].ifname + "_ap" + status, buf = dev[0].cmd_execute(['iw', dev[0].ifname, + 'interface', 'add', + wpas_apdev['ifname'], + 'type', 'managed']) + if status != 0: + raise Exception("iw interface add failed") + wpas_hapd = hostapd.add_ap(wpas_apdev, params) + + if run_csa: + if 'OK' not in hapd.request("CHAN_SWITCH 5 2462 ht"): + raise Exception("chan switch request failed") + + ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=5) + if not ev: + raise Exception("chan switch failed") + + # now check station + ev = dev[0].wait_event(["CTRL-EVENT-CHANNEL-SWITCH", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + if not ev: + raise Exception("sta - no chanswitch event") + if "CTRL-EVENT-CHANNEL-SWITCH" not in ev and not allow_csa_fail: + raise Exception("Received disconnection event instead of channel switch event") + + if add_apdev: + dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del']) + except: + if wpas_apdev: + dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del']) + raise + def test_multi_ap_wps_shared(dev, apdev): """WPS on shared fronthaul/backhaul AP""" ssid = "multi-ap-wps" @@ -140,6 +220,30 @@ def test_multi_ap_wps_shared(dev, apdev): "multi_ap_backhaul_wpa_passphrase": passphrase}) run_multi_ap_wps(dev, apdev, params) +def test_multi_ap_wps_shared_csa(dev, apdev): + """WPS on shared fronthaul/backhaul AP, run CSA""" + ssid = "multi-ap-wps-csa" + passphrase = "12345678" + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params.update({"multi_ap": "3", + "multi_ap_backhaul_ssid": '"%s"' % ssid, + "multi_ap_backhaul_wpa_passphrase": passphrase}) + run_multi_ap_wps(dev, apdev, params, run_csa=True) + +def test_multi_ap_wps_shared_apdev_csa(dev, apdev): + """WPS on shared fronthaul/backhaul AP add apdev on same phy and run CSA""" + ssid = "multi-ap-wps-apdev-csa" + passphrase = "12345678" + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params.update({"multi_ap": "3", + "multi_ap_backhaul_ssid": '"%s"' % ssid, + "multi_ap_backhaul_wpa_passphrase": passphrase}) + # This case is currently failing toc omplete CSA on the station interface. + # For the time being, ignore that to avoid always failing tests. Full + # validation can be enabled once the issue behind this is fixed. + run_multi_ap_wps(dev, apdev, params, add_apdev=True, run_csa=True, + allow_csa_fail=True) + def test_multi_ap_wps_shared_psk(dev, apdev): """WPS on shared fronthaul/backhaul AP using PSK""" ssid = "multi-ap-wps" @@ -163,9 +267,8 @@ def test_multi_ap_wps_split(dev, apdev): params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid, passphrase=backhaul_passphrase) params_backhaul.update({"multi_ap": "1"}) - hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul) - run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr()) + run_multi_ap_wps(dev, apdev, params, params_backhaul) def test_multi_ap_wps_split_psk(dev, apdev): """WPS on split fronthaul and backhaul AP""" @@ -178,9 +281,8 @@ def test_multi_ap_wps_split_psk(dev, apdev): "multi_ap_backhaul_wpa_psk": backhaul_psk}) params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid) params_backhaul.update({"multi_ap": "1", "wpa_psk": backhaul_psk}) - hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul) - run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr()) + run_multi_ap_wps(dev, apdev, params, params_backhaul) def test_multi_ap_wps_split_mixed(dev, apdev): """WPS on split fronthaul and backhaul AP with mixed-mode fronthaul""" @@ -195,9 +297,8 @@ def test_multi_ap_wps_split_mixed(dev, apdev): params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid, passphrase=backhaul_passphrase) params_backhaul.update({"multi_ap": "1"}) - hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul) - run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr()) + run_multi_ap_wps(dev, apdev, params, params_backhaul) def test_multi_ap_wps_split_open(dev, apdev): """WPS on split fronthaul and backhaul AP with open fronthaul""" @@ -209,9 +310,8 @@ def test_multi_ap_wps_split_open(dev, apdev): params_backhaul = hostapd.wpa2_params(ssid=backhaul_ssid, passphrase=backhaul_passphrase) params_backhaul.update({"multi_ap": "1"}) - hapd_backhaul = hostapd.add_ap(apdev[1], params_backhaul) - run_multi_ap_wps(dev, apdev, params, hapd_backhaul.own_addr()) + run_multi_ap_wps(dev, apdev, params, params_backhaul) def test_multi_ap_wps_fail_non_multi_ap(dev, apdev): """Multi-AP WPS on non-WPS AP fails""" diff --git a/tests/hwsim/test_p2p_channel.py b/tests/hwsim/test_p2p_channel.py index 87a1a24..d57234d 100644 --- a/tests/hwsim/test_p2p_channel.py +++ b/tests/hwsim/test_p2p_channel.py @@ -17,7 +17,7 @@ from tshark import run_tshark from wpasupplicant import WpaSupplicant from hwsim import HWSimRadio from p2p_utils import * -from utils import clear_regdom_dev +from utils import * def set_country(country, dev=None): subprocess.call(['iw', 'reg', 'set', country]) @@ -226,6 +226,7 @@ def test_p2p_channel_avoid2(dev): def test_p2p_channel_avoid3(dev): """P2P and avoid frequencies driver event on 5 GHz""" try: + dev[0].global_request("SET p2p_pref_chan 128:44") set_country("CN", dev[0]) form(dev[0], dev[1]) set_country("CN", dev[0]) @@ -251,6 +252,7 @@ def test_p2p_channel_avoid3(dev): finally: set_country("00") dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES") + dev[0].global_request("SET p2p_pref_chan ") dev[1].flush_scan_cache() @remote_compatible @@ -603,7 +605,7 @@ def test_p2p_autogo_pref_chan_not_in_regulatory(dev, apdev): raise Exception("Unexpected number of network blocks: " + str(netw)) id = netw[0]['id'] - set_country("SE", dev[0]) + set_country("JP", dev[0]) res = autogo(dev[0], persistent=id) if res['freq'] == "5745": raise Exception("Unexpected channel selected(2): " + res['freq']) @@ -950,7 +952,8 @@ def _test_p2p_go_move_scm_peer_supports(dev, apdev): dev[0].remove_group() finally: dev[0].global_request("SET p2p_go_freq_change_policy 2") - set_country("00") + disable_hapd(hapd) + clear_regdom_dev(dev, 1) def test_p2p_go_move_scm_peer_does_not_support(dev, apdev): """No P2P GO move due to SCM operation (peer does not supports)""" @@ -996,6 +999,7 @@ def _test_p2p_go_move_scm_peer_does_not_support(dev, apdev): finally: dev[0].global_request("SET p2p_go_freq_change_policy 2") dev[1].request("DRIVER_EVENT AVOID_FREQUENCIES") + disable_hapd(hapd) clear_regdom_dev(dev, 2) def test_p2p_go_move_scm_multi(dev, apdev): diff --git a/tests/hwsim/test_p2p_discovery.py b/tests/hwsim/test_p2p_discovery.py index f4353e8..4bce4ec 100644 --- a/tests/hwsim/test_p2p_discovery.py +++ b/tests/hwsim/test_p2p_discovery.py @@ -7,9 +7,12 @@ from remotehost import remote_compatible import logging logger = logging.getLogger() +import binascii import os +import struct import time +import hostapd import hwsim_utils from wpasupplicant import WpaSupplicant from p2p_utils import * @@ -776,3 +779,42 @@ def test_discovery_device_name_change(dev): raise Exception("Unexpected device name(2): " + ev) wpas.p2p_stop_find() dev[0].p2p_stop_find() + +def test_p2p_group_cli_invalid(dev, apdev): + """P2P device discovery with invalid group client info""" + attr = struct.pack('<BHBB', 2, 2, 0x25, 0x09) + + attr += struct.pack('<BH', 3, 6) + "\x02\x02\x02\x02\x02\x00".encode() + + cli = bytes() + cli += "\x02\x02\x02\x02\x02\x03".encode() + cli += "\x02\x02\x02\x02\x02\x04".encode() + cli += struct.pack('>BH', 0, 0x3148) + dev_type = "\x00\x00\x00\x00\x00\x00\x00\x01".encode() + cli += dev_type + num_sec = 25 + cli += struct.pack('B', num_sec) + cli += num_sec * dev_type + name = "TEST".encode() + cli += struct.pack('>HH', 0x1011, len(name)) + name + desc = struct.pack('B', len(cli)) + cli + attr += struct.pack('<BH', 14, len(desc)) + desc + + p2p_ie = struct.pack('>BBL', 0xdd, 4 + len(attr), 0x506f9a09) + attr + ie = binascii.hexlify(p2p_ie).decode() + + params = {"ssid": "DIRECT-test", + "eap_server": "1", + "wps_state": "2", + "wpa_passphrase": "12345678", + "wpa": "2", + "wpa_key_mgmt": "WPA-PSK", + "rsn_pairwise": "CCMP", + "vendor_elements": ie} + hapd = hostapd.add_ap(apdev[0], params) + + for i in range(2): + dev[i].p2p_find(social=True) + ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5) + if not ev: + raise Exception("P2P device not found") diff --git a/tests/hwsim/test_pasn.py b/tests/hwsim/test_pasn.py new file mode 100644 index 0000000..3ee8cf5 --- /dev/null +++ b/tests/hwsim/test_pasn.py @@ -0,0 +1,638 @@ +# Test cases for PASN +# Copyright (C) 2019 Intel Corporation +# +# This software may be distributed under the terms of the BSD license. +# See README for more details. + +from remotehost import remote_compatible +import binascii +import os +import time +import logging +logger = logging.getLogger() +import socket +import struct +import subprocess + +import hwsim_utils +import hostapd +from wpasupplicant import WpaSupplicant +from utils import * +from hwsim import HWSimRadio +from test_erp import check_erp_capa, start_erp_as +from test_fils import check_fils_capa +from test_ap_ft import run_roams, ft_params1, ft_params2 + +def check_pasn_capab(dev): + if "PASN" not in dev.get_capability("auth_alg"): + raise HwsimSkip("PASN not supported") + +def pasn_ap_params(akmp="PASN", cipher="CCMP", group="19"): + params = {"ssid": "test-wpa2-pasn", + "wpa_passphrase": "12345678", + "wpa": "2", + "ieee80211w": "2", + "wpa_key_mgmt": "WPA-PSK " + akmp, + "rsn_pairwise": cipher, + "pasn_groups" : group} + + return params + +def start_pasn_ap(apdev, params): + try: + return hostapd.add_ap(apdev, params) + except Exception as e: + if "Failed to set hostapd parameter wpa_key_mgmt" in str(e) or \ + "Failed to set hostapd parameter force_kdk_derivation" in str(e): + raise HwsimSkip("PASN not supported") + raise + +def check_pasn_ptk(dev, hapd, cipher): + sta_ptksa = dev.get_ptksa(hapd.own_addr(), cipher) + ap_ptksa = hapd.get_ptksa(dev.own_addr(), cipher) + if not (sta_ptksa and ap_ptksa): + raise Exception("Could not get PTKSA entry") + + logger.info("sta: TK: %s KDK: %s" % (sta_ptksa['tk'], sta_ptksa['kdk'])) + logger.info("ap : TK: %s KDK: %s" % (ap_ptksa['tk'], ap_ptksa['kdk'])) + + if sta_ptksa['tk'] != ap_ptksa['tk'] or sta_ptksa['kdk'] != ap_ptksa['kdk']: + raise Exception("TK/KDK mismatch") + +def check_pasn_akmp_cipher(dev, hapd, akmp="PASN", cipher="CCMP", + group="19", status=0, fail=0, nid=""): + dev.flush_scan_cache() + dev.scan(type="ONLY", freq=2412) + + cmd = "PASN_START bssid=%s akmp=%s cipher=%s group=%s" % (hapd.own_addr(), akmp, cipher, group) + + resp = dev.request(cmd) + if nid != "": + cmd += " nid=%s" % nid + + if fail: + if "OK" in resp: + raise Exception("Unexpected success to start PASN authentication") + return + + if "OK" not in resp: + raise Exception("Failed to start PASN authentication") + + ev = dev.wait_event(["PASN-AUTH-STATUS"], 3) + if not ev: + raise Exception("PASN: PASN-AUTH-STATUS not seen") + + if hapd.own_addr() + " akmp=" + akmp + ", status=" + str(status) not in ev: + raise Exception("PASN: unexpected status") + + if status: + return + + check_pasn_ptk(dev, hapd, cipher) + +@remote_compatible +def test_pasn_ccmp(dev, apdev): + """PASN authentication with WPA2/CCMP AP""" + check_pasn_capab(dev[0]) + + params = pasn_ap_params("PASN", "CCMP", "19") + hapd = start_pasn_ap(apdev[0], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP") + +@remote_compatible +def test_pasn_gcmp(dev, apdev): + """PASN authentication with WPA2/GCMP AP""" + check_pasn_capab(dev[0]) + + params = pasn_ap_params("PASN", "GCMP", "19") + hapd = start_pasn_ap(apdev[0], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "GCMP") + +@remote_compatible +def test_pasn_ccmp_256(dev, apdev): + """PASN authentication with WPA2/CCMP256 AP""" + check_pasn_capab(dev[0]) + + params = pasn_ap_params("PASN", "CCMP-256", "19") + hapd = start_pasn_ap(apdev[0], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP-256") + +@remote_compatible +def test_pasn_gcmp_256(dev, apdev): + """PASN authentication with WPA2/GCMP-256 AP""" + check_pasn_capab(dev[0]) + + params = pasn_ap_params("PASN", "GCMP-256", "19") + hapd = start_pasn_ap(apdev[0], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "GCMP-256") + +@remote_compatible +def test_pasn_group_mismatch(dev, apdev): + """PASN authentication with WPA2/CCMP AP with group mismatch""" + check_pasn_capab(dev[0]) + + params = pasn_ap_params("PASN", "CCMP", "20") + hapd = start_pasn_ap(apdev[0], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP", status=77) + +@remote_compatible +def test_pasn_channel_mismatch(dev, apdev): + """PASN authentication with WPA2/CCMP AP with channel mismatch""" + check_pasn_capab(dev[0]) + + params = pasn_ap_params("PASN", "CCMP") + params['channel'] = "6" + hapd = start_pasn_ap(apdev[0], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP", fail=1) + +@remote_compatible +def test_pasn_while_connected_same_channel(dev, apdev): + """PASN authentication with WPA2/CCMP AP while connected same channel""" + check_pasn_capab(dev[0]) + + ssid = "test-wpa2-psk" + psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_psk'] = psk + hapd = start_pasn_ap(apdev[0], params) + + dev[0].connect(ssid, raw_psk=psk, scan_freq="2412") + + params = pasn_ap_params("PASN", "CCMP") + hapd = start_pasn_ap(apdev[1], params) + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP") + +@remote_compatible +def test_pasn_while_connected_same_ap(dev, apdev): + """PASN authentication with WPA2/CCMP AP while connected to it""" + check_pasn_capab(dev[0]) + + params = hostapd.wpa2_params(ssid="test-wpa2-psk", + passphrase="12345678") + hapd = start_pasn_ap(apdev[0], params) + + dev[0].connect("test-wpa2-psk", psk="12345678", scan_freq="2412") + + check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP", fail=1) + +@remote_compatible +def test_pasn_while_connected_diff_channel(dev, apdev): + """PASN authentication with WPA2/CCMP AP while connected diff channel""" + check_pasn_capab(dev[0]) + + with HWSimRadio(n_channels=2) as (radio, iface): + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add(iface) + + if wpas.get_mcc() < 2: + raise HwsimSkip("PASN: New radio does not support MCC") + + params = hostapd.wpa2_params(ssid="test-wpa2-psk", + passphrase="12345678") + params['channel'] = "6" + hapd = start_pasn_ap(apdev[0], params) + wpas.connect("test-wpa2-psk", psk="12345678", scan_freq="2437") + + params = pasn_ap_params("PASN", "CCMP") + hapd2 = start_pasn_ap(apdev[1], params) + + check_pasn_akmp_cipher(wpas, hapd2, "PASN", "CCMP") + +@remote_compatible +def test_pasn_sae_pmksa_cache(dev, apdev): + """PASN authentication with SAE AP with PMKSA caching""" + check_pasn_capab(dev[0]) + check_sae_capab(dev[0]) + + params = hostapd.wpa2_params(ssid="test-sae", + passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE PASN' + hapd = start_pasn_ap(apdev[0], params) + + dev[0].set("sae_groups", "19") + dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") + + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP") + +def check_pasn_fils_pmksa_cache(dev, apdev, params, key_mgmt): + check_fils_capa(dev[0]) + check_erp_capa(dev[0]) + check_pasn_capab(dev[0]) + + start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst")) + + bssid = apdev[0]['bssid'] + params = hostapd.wpa2_eap_params(ssid="fils") + params['wpa_key_mgmt'] = key_mgmt + " PASN" + params['auth_server_port'] = "18128" + params['erp_domain'] = 'example.com' + params['fils_realm'] = 'example.com' + hapd = start_pasn_ap(apdev[0], params) + + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].request("ERP_FLUSH") + + id = dev[0].connect("fils", key_mgmt=key_mgmt, + eap="PSK", identity="psk.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + erp="1", scan_freq="2412") + pmksa = dev[0].get_pmksa(bssid) + if pmksa is None: + raise Exception("No PMKSA cache entry created") + + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + check_pasn_akmp_cipher(dev[0], hapd, key_mgmt, "CCMP") + +@remote_compatible +def test_pasn_fils_sha256_pmksa_cache(dev, apdev, params): + """PASN authentication with FILS-SHA256 with PMKSA caching""" + check_pasn_fils_pmksa_cache(dev, apdev, params, "FILS-SHA256") + +@remote_compatible +def test_pasn_fils_sha384_pmksa_cache(dev, apdev, params): + """PASN authentication with FILS-SHA384 with PMKSA caching""" + check_pasn_fils_pmksa_cache(dev, apdev, params, "FILS-SHA384") + +@remote_compatible +def test_pasn_sae_kdk(dev, apdev): + """Station authentication with SAE AP with KDK derivation during connection""" + check_pasn_capab(dev[0]) + check_sae_capab(dev[0]) + + try: + params = hostapd.wpa2_params(ssid="test-sae", + passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE PASN' + params['force_kdk_derivation'] = "1" + hapd = start_pasn_ap(apdev[0], params) + + dev[0].set("force_kdk_derivation", "1") + dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", + scan_freq="2412") + + check_pasn_ptk(dev[0], hapd, "CCMP") + finally: + dev[0].set("force_kdk_derivation", "0") + + +def check_pasn_fils_kdk(dev, apdev, params, key_mgmt): + check_fils_capa(dev[0]) + check_erp_capa(dev[0]) + check_pasn_capab(dev[0]) + + start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst")) + + try: + bssid = apdev[0]['bssid'] + params = hostapd.wpa2_eap_params(ssid="fils") + params['wpa_key_mgmt'] = key_mgmt + params['auth_server_port'] = "18128" + params['erp_domain'] = 'example.com' + params['fils_realm'] = 'example.com' + params['disable_pmksa_caching'] = '1' + params['force_kdk_derivation'] = "1" + hapd = start_pasn_ap(apdev[0], params) + + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].request("ERP_FLUSH") + dev[0].set("force_kdk_derivation", "1") + + id = dev[0].connect("fils", key_mgmt=key_mgmt, + eap="PSK", identity="psk.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + erp="1", scan_freq="2412") + + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + + check_pasn_ptk(dev[0], hapd, "CCMP") + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + dev[0].dump_monitor() + dev[0].select_network(id, freq=2412) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "EVENT-ASSOC-REJECT", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Connection using FILS/ERP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange") + if "EVENT-ASSOC-REJECT" in ev: + raise Exception("Association failed") + + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + + check_pasn_ptk(dev[0], hapd, "CCMP") + finally: + dev[0].set("force_kdk_derivation", "0") + +@remote_compatible +def test_pasn_fils_sha256_kdk(dev, apdev, params): + """Station authentication with FILS-SHA256 with KDK derivation during connection""" + check_pasn_fils_kdk(dev, apdev, params, "FILS-SHA256") + +@remote_compatible +def test_pasn_fils_sha384_kdk(dev, apdev, params): + """Station authentication with FILS-SHA384 with KDK derivation during connection""" + check_pasn_fils_kdk(dev, apdev, params, "FILS-SHA384") + +@remote_compatible +def test_pasn_sae(dev, apdev): + """PASN authentication with SAE AP with PMK derivation + PMKSA caching""" + check_pasn_capab(dev[0]) + check_sae_capab(dev[0]) + + params = hostapd.wpa2_params(ssid="test-pasn-sae", + passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE PASN' + hapd = start_pasn_ap(apdev[0], params) + + dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412", + only_add_network=True) + + # first test with a valid PSK + check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0") + + # And now with PMKSA caching + check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP") + + # And now with a wrong passphrase + if "FAIL" in dev[0].request("PMKSA_FLUSH"): + raise Exception("PMKSA_FLUSH failed") + + dev[0].set_network_quoted(0, "psk", "12345678787") + check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0") + +@remote_compatible +def test_pasn_sae_while_connected_same_channel(dev, apdev): + """PASN SAE authentication while connected same channel""" + check_pasn_capab(dev[0]) + check_sae_capab(dev[0]) + + params = hostapd.wpa2_params(ssid="test-pasn-wpa2-psk", + passphrase="12345678") + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412") + + params = hostapd.wpa2_params(ssid="test-pasn-sae", + passphrase="12345678") + + params['wpa_key_mgmt'] = 'SAE PASN' + hapd = start_pasn_ap(apdev[1], params) + + dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE", + scan_freq="2412", only_add_network=True) + + check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="1") + +@remote_compatible +def test_pasn_sae_while_connected_diff_channel(dev, apdev): + """PASN SAE authentication while connected diff channel""" + check_pasn_capab(dev[0]) + check_sae_capab(dev[0]) + + with HWSimRadio(n_channels=2) as (radio, iface): + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add(iface) + + if wpas.get_mcc() < 2: + raise HwsimSkip("PASN: New radio does not support MCC") + + params = hostapd.wpa2_params(ssid="test-pasn-wpa2-psk", + passphrase="12345678") + params['channel'] = "6" + hapd = hostapd.add_ap(apdev[0], params) + + wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437") + + params = hostapd.wpa2_params(ssid="test-pasn-sae", + passphrase="12345678") + + params['wpa_key_mgmt'] = 'SAE PASN' + hapd = start_pasn_ap(apdev[1], params) + + wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE", + scan_freq="2412", only_add_network=True) + + check_pasn_akmp_cipher(wpas, hapd, "SAE", "CCMP", nid="1") + +def pasn_fils_setup(wpas, apdev, params, key_mgmt): + check_fils_capa(wpas) + check_erp_capa(wpas) + + wpas.flush_scan_cache() + + start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst")) + + bssid = apdev[0]['bssid'] + params = hostapd.wpa2_eap_params(ssid="fils") + params['wpa_key_mgmt'] = key_mgmt + " PASN" + params['auth_server_port'] = "18128" + params['erp_domain'] = 'example.com' + params['fils_realm'] = 'example.com' + params['disable_pmksa_caching'] = '1' + hapd = hostapd.add_ap(apdev[0]['ifname'], params) + + id = wpas.connect("fils", key_mgmt=key_mgmt, + eap="PSK", identity="psk.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + erp="1", scan_freq="2412") + + wpas.request("DISCONNECT") + wpas.wait_disconnected() + wpas.dump_monitor() + + if "FAIL" in wpas.request("PMKSA_FLUSH"): + raise Exception("PMKSA_FLUSH failed") + + return hapd + +def check_pasn_fils(dev, apdev, params, key_mgmt): + check_pasn_capab(dev[0]) + + hapd = pasn_fils_setup(dev[0], apdev, params, key_mgmt); + check_pasn_akmp_cipher(dev[0], hapd, key_mgmt, "CCMP", nid="0") + +@remote_compatible +def test_pasn_fils_sha256(dev, apdev, params): + """PASN FILS authentication using SHA-256""" + check_pasn_fils(dev, apdev, params, "FILS-SHA256") + +@remote_compatible +def test_pasn_fils_sha384(dev, apdev, params): + """PASN FILS authentication using SHA-384""" + check_pasn_fils(dev, apdev, params, "FILS-SHA384") + +def check_pasn_fils_connected_same_channel(dev, apdev, params, key_mgmt): + check_pasn_capab(dev[0]) + + hapd = pasn_fils_setup(dev[0], apdev, params, key_mgmt); + + # Connect to another AP on the same channel + hapd1 = hostapd.add_ap(apdev[1], {"ssid": "open"}) + dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", + bg_scan_period="0") + + hwsim_utils.test_connectivity(dev[0], hapd1) + + # And perform the PASN authentication with FILS + check_pasn_akmp_cipher(dev[0], hapd, key_mgmt, "CCMP", nid="0") + +@remote_compatible +def test_pasn_fils_sha256_connected_same_channel(dev, apdev, params): + """PASN FILS authentication using SHA-256 while connected same channel""" + check_pasn_fils_connected_same_channel(dev, apdev, params, "FILS-SHA256") + +@remote_compatible +def test_pasn_fils_sha384_connected_same_channel(dev, apdev, params): + """PASN FILS authentication using SHA-384 while connected same channel""" + check_pasn_fils_connected_same_channel(dev, apdev, params, "FILS-SHA384") + +def check_pasn_fils_connected_diff_channel(dev, apdev, params, key_mgmt): + check_pasn_capab(dev[0]) + + with HWSimRadio(n_channels=2) as (radio, iface): + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add(iface) + if wpas.get_mcc() < 2: + raise Exception("New radio does not support MCC") + + hapd = pasn_fils_setup(wpas, apdev, params, key_mgmt); + + # Connect to another AP on a different channel + hapd1 = hostapd.add_ap(apdev[1], {"ssid": "open", "channel" : "6"}) + wpas.connect("open", key_mgmt="NONE", scan_freq="2437", + bg_scan_period="0") + + hwsim_utils.test_connectivity(wpas, hapd1) + + # And perform the PASN authentication with FILS + check_pasn_akmp_cipher(wpas, hapd, key_mgmt, "CCMP", nid="0") + +@remote_compatible +def test_pasn_fils_sha256_connected_diff_channel(dev, apdev, params): + """PASN FILS authentication using SHA-256 while connected diff channel""" + check_pasn_fils_connected_diff_channel(dev, apdev, params, "FILS-SHA256") + +@remote_compatible +def test_pasn_fils_sha384_connected_diff_channel(dev, apdev, params): + """PASN FILS authentication using SHA-384 while connected diff channel""" + check_pasn_fils_connected_diff_channel(dev, apdev, params, "FILS-SHA384") + +def test_pasn_ft_psk(dev, apdev): + """PASN authentication with FT-PSK""" + check_pasn_capab(dev[0]) + + ssid = "test-pasn-ft-psk" + passphrase = "12345678" + + params = ft_params1(ssid=ssid, passphrase=passphrase) + params['wpa_key_mgmt'] += " PASN" + hapd0 = hostapd.add_ap(apdev[0], params) + params = ft_params2(ssid=ssid, passphrase=passphrase) + params['wpa_key_mgmt'] += " PASN" + hapd1 = hostapd.add_ap(apdev[1], params) + + run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase) + + if dev[0].get_status_field('bssid') == apdev[0]['bssid']: + pasn_hapd = hapd1 + else: + pasn_hapd = hapd0 + + check_pasn_akmp_cipher(dev[0], pasn_hapd, "FT-PSK", "CCMP") + + run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, only_one_way=1) + + if dev[0].get_status_field('bssid') == apdev[0]['bssid']: + pasn_hapd = hapd1 + else: + pasn_hapd = hapd0 + + check_pasn_akmp_cipher(dev[0], pasn_hapd, "FT-PSK", "CCMP") + +def test_pasn_ft_eap(dev, apdev): + """PASN authentication with FT-EAP""" + check_pasn_capab(dev[0]) + + ssid = "test-pasn-ft-psk" + passphrase = "12345678" + identity = "gpsk user" + + radius = hostapd.radius_params() + params = ft_params1(ssid=ssid, passphrase=passphrase) + params['wpa_key_mgmt'] = "FT-EAP PASN" + params["ieee8021x"] = "1" + params = dict(list(radius.items()) + list(params.items())) + hapd0 = hostapd.add_ap(apdev[0], params) + + params = ft_params2(ssid=ssid, passphrase=passphrase) + params['wpa_key_mgmt'] = "FT-EAP PASN" + params["ieee8021x"] = "1" + params = dict(list(radius.items()) + list(params.items())) + hapd1 = hostapd.add_ap(apdev[1], params) + + run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True, + eap_identity=identity) + + if dev[0].get_status_field('bssid') == apdev[0]['bssid']: + pasn_hapd = hapd1 + else: + pasn_hapd = hapd0 + + check_pasn_akmp_cipher(dev[0], pasn_hapd, "FT-EAP", "CCMP") + +def test_pasn_ft_eap_sha384(dev, apdev): + """PASN authentication with FT-EAP-SHA-384""" + check_pasn_capab(dev[0]) + + ssid = "test-pasn-ft-psk" + passphrase = "12345678" + identity = "gpsk user" + + radius = hostapd.radius_params() + params = ft_params1(ssid=ssid, passphrase=passphrase) + params["ieee80211w"] = "2" + params['wpa_key_mgmt'] = "FT-EAP-SHA384 PASN" + params["ieee8021x"] = "1" + params = dict(list(radius.items()) + list(params.items())) + hapd0 = hostapd.add_ap(apdev[0], params) + + params = ft_params2(ssid=ssid, passphrase=passphrase) + params["ieee80211w"] = "2" + params['wpa_key_mgmt'] = "FT-EAP-SHA384 PASN" + params["ieee8021x"] = "1" + params = dict(list(radius.items()) + list(params.items())) + hapd1 = hostapd.add_ap(apdev[1], params) + + run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True, + sha384=True) + + if dev[0].get_status_field('bssid') == apdev[0]['bssid']: + pasn_hapd = hapd1 + else: + pasn_hapd = hapd0 + + check_pasn_akmp_cipher(dev[0], pasn_hapd, "FT-EAP-SHA384", "CCMP") diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 2e64cee..24a7903 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -654,6 +654,10 @@ def test_scan_reqs_with_non_scan_radio_work(dev, apdev): def test_scan_setband(dev, apdev): """Band selection for scan operations""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5") + devs = [ dev[0], dev[1], dev[2], wpas ] + try: hapd = None hapd2 = None @@ -678,21 +682,26 @@ def test_scan_setband(dev, apdev): raise Exception("Failed to set setband") if "OK" not in dev[2].request("SET setband 2G"): raise Exception("Failed to set setband") + if "OK" not in wpas.request("SET setband 2G,5G"): + raise Exception("Failed to set setband") # Allow a retry to avoid reporting errors during heavy load for j in range(5): - for i in range(3): - dev[i].request("SCAN only_new=1") + for d in devs: + d.request("SCAN only_new=1") - for i in range(3): - ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15) + for d in devs: + ev = d.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15) if ev is None: raise Exception("Scan timed out") res0 = dev[0].request("SCAN_RESULTS") res1 = dev[1].request("SCAN_RESULTS") res2 = dev[2].request("SCAN_RESULTS") - if bssid in res0 and bssid2 in res0 and bssid in res1 and bssid2 in res2: + res3 = wpas.request("SCAN_RESULTS") + if bssid in res0 and bssid2 in res0 and \ + bssid in res1 and bssid2 in res2 and \ + bssid in res3 and bssid2 in res3: break res = dev[0].request("SCAN_RESULTS") @@ -710,15 +719,19 @@ def test_scan_setband(dev, apdev): raise Exception("Missing scan result(2)") if bssid in res: raise Exception("Unexpected scan result(2)") + + res = wpas.request("SCAN_RESULTS") + if bssid not in res or bssid2 not in res: + raise Exception("Missing scan result(3)") finally: if hapd: hapd.request("DISABLE") if hapd2: hapd2.request("DISABLE") subprocess.call(['iw', 'reg', 'set', '00']) - for i in range(3): - dev[i].request("SET setband AUTO") - dev[i].flush_scan_cache() + for d in devs: + d.request("SET setband AUTO") + d.flush_scan_cache() @remote_compatible def test_scan_hidden_many(dev, apdev): @@ -1137,7 +1150,7 @@ def test_scan_fail(dev, apdev): try: if "OK" not in dev[0].request("SET setband 2G"): raise Exception("SET setband failed") - with alloc_fail(dev[0], 1, "=wpa_setband_scan_freqs_list"): + with alloc_fail(dev[0], 1, "=wpa_add_scan_freqs_list"): # While the frequency list cannot be created due to memory # allocation failure, this scan is expected to be completed without # frequency filtering. @@ -1976,6 +1989,9 @@ def test_scan_ssid_list(dev, apdev): break finally: dev[0].request("VENDOR_ELEM_REMOVE 14 *") + hapd.disable() + dev[0].flush_scan_cache(freq=2432) + dev[0].flush_scan_cache() if not found: raise Exception("AP not found in scan results") @@ -2001,6 +2017,9 @@ def test_scan_short_ssid_list(dev, apdev): break finally: dev[0].request("VENDOR_ELEM_REMOVE 14 *") + hapd.disable() + dev[0].flush_scan_cache(freq=2432) + dev[0].flush_scan_cache() if not found: raise Exception("AP not found in scan results") diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index e2151cf..8bf06e0 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2240,7 +2240,7 @@ def test_sigma_dut_ap_dpp_qr_enrollee_chirp(dev, apdev, params): dev[1].dpp_listen(2437) dev[0].dpp_auth_init(uri=uri, conf="sta-dpp", ssid="DPPNET01", configurator=conf_id) - dev[1].wait_connected() + dev[1].wait_connected(timeout=20) sigma_dut_cmd_check("ap_reset_default,program,DPP") finally: @@ -2334,7 +2334,7 @@ def run_sigma_dut_ap_dpp_qr(dev, apdev, params, ap_conf, sta_conf, extra=""): cmd = "DPP_AUTH_INIT peer=%d conf=%s %s configurator=%d" % (id0b, sta_conf, extra, conf_id) if "OK" not in dev[0].request(cmd): raise Exception("Failed to initiate DPP Authentication") - dev[1].wait_connected() + dev[1].wait_connected(timeout=20) sigma_dut_cmd_check("ap_reset_default") finally: @@ -2389,7 +2389,7 @@ def test_sigma_dut_ap_dpp_offchannel(dev, apdev, params): cmd = "DPP_AUTH_INIT peer=%d conf=sta-dpp ssid=%s configurator=%d" % (id0b, to_hex("DPPNET01"), conf_id) if "OK" not in dev[0].request(cmd): raise Exception("Failed to initiate DPP Authentication") - dev[1].wait_connected() + dev[1].wait_connected(timeout=20) sigma_dut_cmd_check("ap_reset_default") finally: @@ -2914,7 +2914,7 @@ def run_sigma_dut_ap_dpp_self_config(dev, apdev): res = sigma_dut_cmd(cmd) if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: raise Exception("Unexpected result: " + res) - dev[0].wait_connected() + dev[0].wait_connected(timeout=20) dev[0].request("DISCONNECT") dev[0].wait_disconnected() sigma_dut_cmd_check("ap_reset_default") @@ -3391,7 +3391,7 @@ def test_sigma_dut_dpp_reconfig_enrollee(dev, apdev): if ev is None: raise Exception("DPP Config Response (reconfig) not transmitted") - dev[0].wait_connected() + dev[0].wait_connected(timeout=20) ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20) if ev is None: raise Exception("No connection status reported") @@ -3413,7 +3413,7 @@ def test_sigma_dut_dpp_reconfig_enrollee(dev, apdev): if ev is None: raise Exception("DPP Config Response (reconfig) not transmitted [2]") - dev[0].wait_connected() + dev[0].wait_connected(timeout=20) finally: dev[0].set("dpp_config_processing", "0") stop_sigma_dut(sigma) @@ -5214,11 +5214,12 @@ def test_sigma_dut_client_privacy(dev, apdev, params): sigma_dut_cmd_check("sta_reset_default,interface," + ifname) finally: stop_sigma_dut(sigma) - dev[1].set("mac_addr", "0", allow_fail=True) - dev[1].set("rand_addr_lifetime", "60", allow_fail=True) - dev[1].set("preassoc_mac_addr", "0", allow_fail=True) - dev[1].set("gas_rand_mac_addr", "0", allow_fail=True) - dev[1].set("gas_rand_addr_lifetime", "60", allow_fail=True) + dev[0].set("mac_addr", "0", allow_fail=True) + dev[0].set("rand_addr_lifetime", "60", allow_fail=True) + dev[0].request("MAC_RAND_SCAN enable=0 all") + dev[0].set("preassoc_mac_addr", "0", allow_fail=True) + dev[0].set("gas_rand_mac_addr", "0", allow_fail=True) + dev[0].set("gas_rand_addr_lifetime", "60", allow_fail=True) out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"), "wlan.addr == " + addr, diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index 04418f0..bb8ca1a 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -266,14 +266,14 @@ def test_wpas_ctrl_network(dev): "f2:99:88:77:66:55 02:11:22:33:44:55/ff:00:ff:00:ff:00 12:34:56:78:90:ab", "02:11:22:33:44:55/ff:ff:ff:00:00:00 02:ae:be:ce:53:77/00:00:00:00:00:ff"] for val in tests: - dev[0].set_network(id, "bssid_blacklist", val) - res = dev[0].get_network(id, "bssid_blacklist") + dev[0].set_network(id, "bssid_ignore", val) + res = dev[0].get_network(id, "bssid_ignore") if res != val: - raise Exception("Unexpected bssid_blacklist value: %s != %s" % (res, val)) - dev[0].set_network(id, "bssid_whitelist", val) - res = dev[0].get_network(id, "bssid_whitelist") + raise Exception("Unexpected bssid_ignore value: %s != %s" % (res, val)) + dev[0].set_network(id, "bssid_accept", val) + res = dev[0].get_network(id, "bssid_accept") if res != val: - raise Exception("Unexpected bssid_whitelist value: %s != %s" % (res, val)) + raise Exception("Unexpected bssid_accept value: %s != %s" % (res, val)) tests = ["foo", "00:11:22:33:44:5", @@ -281,8 +281,8 @@ def test_wpas_ctrl_network(dev): "00:11:22:33:44:55/", "00:11:22:33:44:55/66:77:88:99:aa:b"] for val in tests: - if "FAIL" not in dev[0].request("SET_NETWORK %d bssid_blacklist %s" % (id, val)): - raise Exception("Invalid bssid_blacklist value accepted") + if "FAIL" not in dev[0].request("SET_NETWORK %d bssid_ignore %s" % (id, val)): + raise Exception("Invalid bssid_ignore value accepted") @remote_compatible def test_wpas_ctrl_network_oom(dev): @@ -687,8 +687,8 @@ def test_wpas_ctrl_addr(dev): raise Exception("Unexpected success on invalid WPS_REG") if "FAIL" not in dev[0].request("IBSS_RSN 00:11:22:33:44"): raise Exception("Unexpected success on invalid IBSS_RSN") - if "FAIL" not in dev[0].request("BLACKLIST 00:11:22:33:44"): - raise Exception("Unexpected success on invalid BLACKLIST") + if "FAIL" not in dev[0].request("BSSID_IGNORE 00:11:22:33:44"): + raise Exception("Unexpected success on invalid BSSID_IGNORE") @remote_compatible def test_wpas_ctrl_wps_errors(dev): @@ -1078,43 +1078,43 @@ def test_wpas_ctrl_nfc_get_handover(dev): if "FAIL" in dev[0].request("NFC_GET_HANDOVER_SEL " + v): raise Exception("Unexpected NFC_GET_HANDOVER_SEL failure for " + v) -def get_blacklist(dev): - return dev.request("BLACKLIST").splitlines() +def get_bssid_ignore_list(dev): + return dev.request("BSSID_IGNORE").splitlines() @remote_compatible -def test_wpas_ctrl_blacklist(dev): - """wpa_supplicant ctrl_iface BLACKLIST""" - if "OK" not in dev[0].request("BLACKLIST clear"): - raise Exception("BLACKLIST clear failed") - b = get_blacklist(dev[0]) +def test_wpas_ctrl_bssid_ignore(dev): + """wpa_supplicant ctrl_iface BSSID_IGNORE""" + if "OK" not in dev[0].request("BSSID_IGNORE clear"): + raise Exception("BSSID_IGNORE clear failed") + b = get_bssid_ignore_list(dev[0]) if len(b) != 0: - raise Exception("Unexpected blacklist contents: " + str(b)) - if "OK" not in dev[0].request("BLACKLIST 00:11:22:33:44:55"): - raise Exception("BLACKLIST add failed") - b = get_blacklist(dev[0]) + raise Exception("Unexpected BSSID ignore list contents: " + str(b)) + if "OK" not in dev[0].request("BSSID_IGNORE 00:11:22:33:44:55"): + raise Exception("BSSID_IGNORE add failed") + b = get_bssid_ignore_list(dev[0]) if "00:11:22:33:44:55" not in b: - raise Exception("Unexpected blacklist contents: " + str(b)) - if "OK" not in dev[0].request("BLACKLIST 00:11:22:33:44:56"): - raise Exception("BLACKLIST add failed") - b = get_blacklist(dev[0]) + raise Exception("Unexpected BSSID ignore list contents: " + str(b)) + if "OK" not in dev[0].request("BSSID_IGNORE 00:11:22:33:44:56"): + raise Exception("BSSID_IGNORE add failed") + b = get_bssid_ignore_list(dev[0]) if "00:11:22:33:44:55" not in b or "00:11:22:33:44:56" not in b: - raise Exception("Unexpected blacklist contents: " + str(b)) - if "OK" not in dev[0].request("BLACKLIST 00:11:22:33:44:56"): - raise Exception("BLACKLIST add failed") - b = get_blacklist(dev[0]) + raise Exception("Unexpected BSSID ignore list contents: " + str(b)) + if "OK" not in dev[0].request("BSSID_IGNORE 00:11:22:33:44:56"): + raise Exception("BSSID_IGNORE add failed") + b = get_bssid_ignore_list(dev[0]) if "00:11:22:33:44:55" not in b or "00:11:22:33:44:56" not in b or len(b) != 2: - raise Exception("Unexpected blacklist contents: " + str(b)) + raise Exception("Unexpected BSSID ignore list contents: " + str(b)) - if "OK" not in dev[0].request("BLACKLIST clear"): - raise Exception("BLACKLIST clear failed") - if dev[0].request("BLACKLIST") != "": - raise Exception("Unexpected blacklist contents") + if "OK" not in dev[0].request("BSSID_IGNORE clear"): + raise Exception("BSSID_IGNORE clear failed") + if dev[0].request("BSSID_IGNORE") != "": + raise Exception("Unexpected BSSID ignore list contents") @remote_compatible -def test_wpas_ctrl_blacklist_oom(dev): - """wpa_supplicant ctrl_iface BLACKLIST and out-of-memory""" - with alloc_fail(dev[0], 1, "wpa_blacklist_add"): - if "FAIL" not in dev[0].request("BLACKLIST aa:bb:cc:dd:ee:ff"): +def test_wpas_ctrl_bssid_ignore_oom(dev): + """wpa_supplicant ctrl_iface BSSID_IGNORE and out-of-memory""" + with alloc_fail(dev[0], 1, "wpa_bssid_ignore_add"): + if "FAIL" not in dev[0].request("BSSID_IGNORE aa:bb:cc:dd:ee:ff"): raise Exception("Unexpected success with allocation failure") def test_wpas_ctrl_log_level(dev): diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index b7f9846..75bc021 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -80,8 +80,24 @@ def check_mesh_scan(dev, params, other_started=False, beacon_int=0): if '[MESH]' not in bss['flags']: raise Exception("BSS output did not include MESH flag") -def check_mesh_group_added(dev): - ev = dev.wait_event(["MESH-GROUP-STARTED"]) +def check_dfs_started(dev, timeout=10): + ev = dev.wait_event(["DFS-CAC-START"], timeout=timeout) + if ev is None: + raise Exception("Test exception: CAC did not start") + +def check_dfs_finished(dev, timeout=70): + ev = dev.wait_event(["DFS-CAC-COMPLETED"], timeout=timeout) + if ev is None: + raise Exception("Test exception: CAC did not finish") + +def check_mesh_radar_handling_finished(dev, timeout=75): + ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH", "MESH-GROUP-STARTED"], + timeout=timeout) + if ev is None: + raise Exception("Test exception: Couldn't join mesh") + +def check_mesh_group_added(dev, timeout=10): + ev = dev.wait_event(["MESH-GROUP-STARTED"], timeout=timeout) if ev is None: raise Exception("Test exception: Couldn't join mesh") @@ -91,6 +107,10 @@ def check_mesh_group_removed(dev): if ev is None: raise Exception("Test exception: Couldn't leave mesh") +def check_regdom_change(dev, timeout=10): + ev = dev.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=timeout) + if ev is None: + raise Exception("Test exception: No regdom change happened.") def check_mesh_peer_connected(dev, timeout=10): ev = dev.wait_event(["MESH-PEER-CONNECTED"], timeout=timeout) @@ -167,6 +187,39 @@ def test_wpas_mesh_group_remove(dev): check_mesh_group_removed(dev[0]) dev[0].mesh_group_remove() +def dfs_simulate_radar(dev): + logger.info("Trigger a simulated radar event") + phyname = dev.get_driver_status_field("phyname") + radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar' + with open(radar_file, 'w') as f: + f.write('1') + +@long_duration_test +def test_mesh_peer_connected_dfs(dev): + """Mesh peer connected (DFS)""" + dev[0].set("country", "DE") + dev[1].set("country", "DE") + + check_regdom_change(dev[0]) + check_regdom_change(dev[1]) + + check_mesh_support(dev[0]) + add_open_mesh_network(dev[0], freq="5500", beacon_int=160) + add_open_mesh_network(dev[1], freq="5500", beacon_int=160) + check_dfs_started(dev[0]) + check_dfs_finished(dev[0]) + check_mesh_joined_connected(dev, timeout0=10) + + dfs_simulate_radar(dev[0]) + + check_mesh_radar_handling_finished(dev[0], timeout=75) + + dev[0].set("country", "00") + dev[1].set("country", "00") + + check_regdom_change(dev[0]) + check_regdom_change(dev[1]) + def test_wpas_mesh_peer_connected(dev): """wpa_supplicant MESH peer connected""" check_mesh_support(dev[0]) diff --git a/tests/hwsim/tshark.py b/tests/hwsim/tshark.py index d6a57f0..32cdf47 100644 --- a/tests/hwsim/tshark.py +++ b/tests/hwsim/tshark.py @@ -12,6 +12,8 @@ import subprocess import logging logger = logging.getLogger() +from utils import * + class UnknownFieldsException(Exception): def __init__(self, fields): Exception.__init__(self, "unknown tshark fields %s" % ','.join(fields)) @@ -41,6 +43,8 @@ def _run_tshark(filename, filter, display=None, wait=True): stderr=subprocess.PIPE) except Exception as e: logger.info("Could run run tshark check: " + str(e)) + if "No such file or directory: 'tshark'" in str(e): + raise HwsimSkip("No tshark available") cmd = None return None @@ -111,6 +115,8 @@ def run_tshark_json(filename, filter): stderr=subprocess.PIPE) except Exception as e: logger.info("Could run run tshark: " + str(e)) + if "No such file or directory: 'tshark'" in str(e): + raise HwsimSkip("No tshark available") return None output = cmd.communicate() out = output[0].decode() diff --git a/tests/hwsim/wlantest.py b/tests/hwsim/wlantest.py index 6d4343b..16765d2 100644 --- a/tests/hwsim/wlantest.py +++ b/tests/hwsim/wlantest.py @@ -29,7 +29,7 @@ class Wlantest: return cls.remote_host.execute(["killall", "-9", "wlantest"]) - cls.remote_host.wait_execute_complete(cls.exe_thread, 5) + cls.remote_host.thread_wait(cls.exe_thread, 5) cls.exe_thread = None cls.exe_res = [] @@ -64,7 +64,7 @@ class Wlantest: pcap_file, log_file) cls.remote_host.add_log(log_file) cls.remote_host.add_log(pcap_file) - cls.exe_thread = cls.remote_host.execute_run(cmd.split(), cls.exe_res) + cls.exe_thread = cls.remote_host.thread_run(cmd.split(), cls.exe_res) # Give wlantest a chance to start working time.sleep(1) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 92c8552..fed1d10 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1095,8 +1095,8 @@ class WpaSupplicant: "disable_max_amsdu", "ampdu_factor", "ampdu_density", "disable_ht40", "disable_sgi", "disable_ldpc", "ht40_intolerant", "update_identifier", "mac_addr", - "erp", "bg_scan_period", "bssid_blacklist", - "bssid_whitelist", "mem_only_psk", "eap_workaround", + "erp", "bg_scan_period", "bssid_ignore", + "bssid_accept", "mem_only_psk", "eap_workaround", "engine", "fils_dh_group", "bssid_hint", "dpp_csign", "dpp_csign_expiry", "dpp_netaccesskey", "dpp_netaccesskey_expiry", "dpp_pfs", @@ -1628,3 +1628,21 @@ class WpaSupplicant: res = self.request("DPP_CONFIGURATOR_REMOVE %d" % conf_id) if "OK" not in res: raise Exception("DPP_CONFIGURATOR_REMOVE failed") + + def get_ptksa(self, bssid, cipher): + res = self.request("PTKSA_CACHE_LIST") + lines = res.splitlines() + for l in lines: + if bssid not in l or cipher not in l: + continue + + vals = dict() + [index, addr, cipher, expiration, tk, kdk] = l.split(' ', 5) + vals['index'] = index + vals['addr'] = addr + vals['cipher'] = cipher + vals['expiration'] = expiration + vals['tk'] = tk + vals['kdk'] = kdk + return vals + return None diff --git a/tests/remote/monitor.py b/tests/remote/monitor.py index 5bd801c..0f77d50 100644 --- a/tests/remote/monitor.py +++ b/tests/remote/monitor.py @@ -110,7 +110,7 @@ def run(host, setup_params): log = log_dir + tc_name + "_" + host.name + log_monitor + ".pcap" host.add_log(log) - thread = host.execute_run([tshark, "-w", log], monitor_res) + thread = host.thread_run([tshark, "-w", log], monitor_res) host.thread = thread @@ -122,7 +122,7 @@ def stop(host): if host.thread is None: return - host.execute_stop(host.thread) + host.thread_stop(host.thread) host.thread = None # Add monitor to existing interface diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index e26e348..67993a3 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -13,6 +13,7 @@ import time import traceback import getopt from datetime import datetime +from random import shuffle import logging logger = logging.getLogger() @@ -32,7 +33,7 @@ from hwsim_wrapper import run_hwsim_test def usage(): print("USAGE: " + sys.argv[0] + " -t devices") print("USAGE: " + sys.argv[0] + " -t check_devices") - print("USAGE: " + sys.argv[0] + " -d <dut_name> -t <all|sanity|tests_to_run> [-r <ref_name>] [-c <cfg_file.py>] [-m <all|monitor_name>] [-h hwsim_tests] [-f hwsim_modules][-R][-T][-P][-v]") + print("USAGE: " + sys.argv[0] + " -d <dut_name> -t <all|sanity|tests_to_run> [-r <ref_name>] [-c <cfg_file.py>] [-m <all|monitor_name>] [-h hwsim_tests] [-f hwsim_modules][-R][-T][-P][-S][-v]") print("USAGE: " + sys.argv[0]) def get_devices(devices, duts, refs, monitors): @@ -79,10 +80,11 @@ def main(): trace = False restart = False perf = False + shuffle_tests = False # parse input parameters try: - opts, args = getopt.getopt(sys.argv[1:], "d:f:r:t:l:k:c:m:h:vRPT", + opts, args = getopt.getopt(sys.argv[1:], "d:f:r:t:l:k:c:m:h:vRPTS", ["dut=", "modules=", "ref=", "tests=", "log-dir=", "cfg=", "key=", "monitor=", "hwsim="]) @@ -100,6 +102,8 @@ def main(): trace = True elif option == "-P": perf = True + elif option == "-S": + shuffle_tests = True elif option in ("-d", "--dut"): duts.append(argument) elif option in ("-r", "--ref"): @@ -283,6 +287,10 @@ def main(): continue tests_to_run.append(t) + if shuffle_tests: + shuffle(tests_to_run) + shuffle(hwsim_tests_to_run) + # lock devices try: get_devices(devices, duts, refs, monitors) diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py index e80901b..6902991 100644 --- a/tests/remote/rutils.py +++ b/tests/remote/rutils.py @@ -342,12 +342,12 @@ def ping_run(host, ip, result, ifname=None, addr_type="ipv4", deadline="5", qos= flush_arp_cache(host) - thread = host.execute_run(ping, result) + thread = host.thread_run(ping, result) return thread def ping_wait(host, thread, timeout=None): - host.wait_execute_complete(thread, timeout) - if thread.isAlive(): + host.thread_wait(thread, timeout) + if thread.is_alive(): raise Exception("ping thread still alive") def flush_arp_cache(host): @@ -496,24 +496,24 @@ def iperf_run(server, client, server_ip, client_res, server_res, flush_arp_cache(server) flush_arp_cache(client) - server_thread = server.execute_run(iperf_server, server_res) + server_thread = server.thread_run(iperf_server, server_res) time.sleep(1) - client_thread = client.execute_run(iperf_client, client_res) + client_thread = client.thread_run(iperf_client, client_res) return server_thread, client_thread def iperf_wait(server, client, server_thread, client_thread, timeout=None, iperf="iperf"): - client.wait_execute_complete(client_thread, timeout) - if client_thread.isAlive(): + client.thread_wait(client_thread, timeout) + if client_thread.is_alive(): raise Exception("iperf client thread still alive") - server.wait_execute_complete(server_thread, 5) - if server_thread.isAlive(): + server.thread_wait(server_thread, 5) + if server_thread.is_alive(): server.execute(["killall", "-s", "INT", iperf]) time.sleep(1) - server.wait_execute_complete(server_thread, 5) - if server_thread.isAlive(): + server.thread_wait(server_thread, 5) + if server_thread.is_alive(): raise Exception("iperf server thread still alive") return |