]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Add testing option to delay EAPOL Tx
authorDaniel Gabay <daniel.gabay@intel.com>
Thu, 1 Dec 2022 16:54:35 +0000 (18:54 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 2 Dec 2022 11:07:03 +0000 (13:07 +0200)
Add a testing option to delay EAPOL-Key messages 1/4 and 3/4. By setting
delay_eapol_tx=1, the actual EAPOL Tx will occur on the last possible
attempt (wpa_pairwise_update_count) thus all previous attempts will fail
on timeout which is the wanted delay.

In addition, add an hwsim test that uses this testing option to verify
that non protected Robust Action frames are dropped prior to keys
installation in MFP.

Signed-off-by: Daniel Gabay <daniel.gabay@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c
tests/hwsim/test_ap_pmf.py

index a37d86ad5c0081694ea5ee260dd7cf90963c51dd..9ce604f4903ac2e92ac311d0df1cbfb422ce9960 100644 (file)
@@ -4271,6 +4271,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                bss->oci_freq_override_wnm_sleep = atoi(pos);
        } else if (os_strcmp(buf, "eap_skip_prot_success") == 0) {
                bss->eap_skip_prot_success = atoi(pos);
+       } else if (os_strcmp(buf, "delay_eapol_tx") == 0) {
+               conf->delay_eapol_tx = atoi(pos);
 #endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_SAE
        } else if (os_strcmp(buf, "sae_password") == 0) {
index 427a49e0c174cb3934c235c533ac9c3096c1088b..c3c03bba9b217bd479a13ef7cfca1f850ea22a36 100644 (file)
@@ -3086,6 +3086,11 @@ own_ip_addr=127.0.0.1
 # Include only ECSA IE without CSA IE where possible
 # (channel switch operating class is needed)
 #ecsa_ie_only=0
+#
+# Delay EAPOL-Key messages 1/4 and 3/4 by not sending the frame until the last
+# attempt (wpa_pairwise_update_count). This will trigger a timeout on all
+# previous attempts and thus delays the frame. (testing only)
+#delay_eapol_tx=0
 
 ##### Multiple BSSID support ##################################################
 #
index 98ed81a9845edb742ad685eda8922a0d29ff1088..4e14bc6f22683dc8039b7c9dd4dd178f55e8f5da 100644 (file)
@@ -1076,6 +1076,7 @@ struct hostapd_config {
        double ignore_reassoc_probability;
        double corrupt_gtk_rekey_mic_probability;
        int ecsa_ie_only;
+       bool delay_eapol_tx;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #ifdef CONFIG_ACS
index e3dfd8a6a99a7011e62daa206e9fe6ae0226ad4b..d9acf101d46e2a1f0d923a69f0c8f89a31912efc 100644 (file)
@@ -1736,10 +1736,25 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
        if (!sm)
                return;
 
+       ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
+
+#ifdef CONFIG_TESTING_OPTIONS
+       /* When delay_eapol_tx is true, delay the EAPOL-Key transmission by
+        * sending it only on the last attempt after all timeouts for the prior
+        * skipped attemps. */
+       if (wpa_auth->conf.delay_eapol_tx &&
+           ctr != wpa_auth->conf.wpa_pairwise_update_count) {
+               wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
+                       "DELAY-EAPOL-TX-%d", ctr);
+               goto skip_tx;
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
        __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
                         keyidx, encr, 0);
+#ifdef CONFIG_TESTING_OPTIONS
+skip_tx:
+#endif /* CONFIG_TESTING_OPTIONS */
 
-       ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
        if (ctr == 1 && wpa_auth->conf.tx_status)
                timeout_ms = pairwise ? eapol_key_timeout_first :
                        eapol_key_timeout_first_group;
index d95b2567e018f4a42947f14f0156b1d8c198052b..eed016accb4a88267f9e8784d367eef61936e5e2 100644 (file)
@@ -240,6 +240,7 @@ struct wpa_auth_config {
        unsigned int gtk_rsc_override_set:1;
        unsigned int igtk_rsc_override_set:1;
        int ft_rsnxe_used;
+       bool delay_eapol_tx;
 #endif /* CONFIG_TESTING_OPTIONS */
        unsigned int oci_freq_override_eapol_m3;
        unsigned int oci_freq_override_eapol_g1;
index 250d5a1580dccc65079259884eb45229288fb247..a87d2f38999a0a189583879472b9bfd7784201ee 100644 (file)
@@ -117,6 +117,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
 #ifdef CONFIG_TESTING_OPTIONS
        wconf->corrupt_gtk_rekey_mic_probability =
                iconf->corrupt_gtk_rekey_mic_probability;
+       wconf->delay_eapol_tx = iconf->delay_eapol_tx;
        if (conf->own_ie_override &&
            wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) {
                wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override);
index d83df5d74e3ff5ae119165ca67c2ec7972d1171a..2486a90d79bb107dbc1a4b7e429482a28103192b 100644 (file)
@@ -1470,3 +1470,47 @@ def test_ap_pmf_sta_global_require2(dev, apdev):
             raise Exception("Unexpected connection")
     finally:
         dev[0].set("pmf", "0")
+
+def test_ap_pmf_drop_robust_mgmt_prior_to_keys_installation(dev, apdev):
+    """Drop non protected Robust Action frames prior to keys installation"""
+    ssid = "test-pmf-required"
+    passphrase = '12345678'
+    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+    params['delay_eapol_tx'] = '1'
+    params['ieee80211w'] = '2'
+    params['wpa_pairwise_update_count'] = '5'
+    hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+
+    # Spectrum management with Channel Switch element
+    msg = {'fc': 0x00d0,
+           'sa': hapd.own_addr(),
+           'da': dev[0].own_addr(),
+           'bssid': hapd.own_addr(),
+           'payload': binascii.unhexlify('00042503000608')
+           }
+
+    dev[0].connect(ssid, psk=passphrase, scan_freq='2412', ieee80211w='1',
+                   wait_connect=False)
+
+    # wait for the first delay before sending the frame
+    ev = hapd.wait_event(['DELAY-EAPOL-TX-1'], timeout=10)
+    if ev is None:
+        raise Exception("EAPOL is not delayed")
+
+    # send the Action frame while connecting (prior to keys installation)
+    hapd.mgmt_tx(msg)
+
+    dev[0].wait_connected(timeout=10, error="Timeout on connection")
+    hapd.wait_sta()
+    hwsim_utils.test_connectivity(dev[0], hapd)
+
+    # Verify no channel switch event
+    ev = dev[0].wait_event(['CTRL-EVENT-STARTED-CHANNEL-SWITCH'], timeout=5)
+    if ev is not None:
+        raise Exception("Unexpected CSA prior to keys installation")
+
+    # Send the frame after keys installation and verify channel switch event
+    hapd.mgmt_tx(msg)
+    ev = dev[0].wait_event(['CTRL-EVENT-STARTED-CHANNEL-SWITCH'], timeout=5)
+    if ev is None:
+        raise Exception("Expected CSA handling after keys installation")