]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Allow RSNE/RSNXE/RSNOE/RSNO2E/RSNXOE to be replace for testing
authorJouni Malinen <quic_jouni@quicinc.com>
Wed, 24 Jul 2024 00:04:15 +0000 (00:04 +0000)
committerJouni Malinen <j@w1.fi>
Wed, 24 Jul 2024 01:01:29 +0000 (01:01 +0000)
This is convenient for testing STA behavior with various RSN element
combinations and special cases.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
hostapd/config_file.c
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/beacon.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c
src/ap/wpa_auth_ie.c
tests/hwsim/test_rsn_override.py

index a98e417f7705d4f166ce1450bd0f16eea697a206..c5aa2dc368d7c3b114273f3fafe67577841d0b1d 100644 (file)
@@ -2436,6 +2436,31 @@ static int get_u16(const char *pos, int line, u16 *ret_val)
 #endif /* CONFIG_IEEE80211BE */
 
 
+#ifdef CONFIG_TESTING_OPTIONS
+static bool get_hexstream(const char *val, struct wpabuf **var,
+                         const char *name, int line)
+{
+       struct wpabuf *tmp;
+       size_t len = os_strlen(val) / 2;
+
+       tmp = wpabuf_alloc(len);
+       if (!tmp)
+               return false;
+
+       if (hexstr2bin(val, wpabuf_put(tmp, len), len)) {
+               wpabuf_free(tmp);
+               wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
+                          line, name, val);
+               return false;
+       }
+
+       wpabuf_free(*var);
+       *var = tmp;
+       return true;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 static int hostapd_config_fill(struct hostapd_config *conf,
                               struct hostapd_bss_config *bss,
                               const char *buf, char *pos, int line)
@@ -4504,23 +4529,29 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                        bss->radio_measurements[0] |=
                                WLAN_RRM_CAPS_NEIGHBOR_REPORT;
        } else if (os_strcmp(buf, "own_ie_override") == 0) {
-               struct wpabuf *tmp;
-               size_t len = os_strlen(pos) / 2;
-
-               tmp = wpabuf_alloc(len);
-               if (!tmp)
+               if (!get_hexstream(pos, &bss->own_ie_override,
+                                  "own_ie_override", line))
                        return 1;
-
-               if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
-                       wpabuf_free(tmp);
-                       wpa_printf(MSG_ERROR,
-                                  "Line %d: Invalid own_ie_override '%s'",
-                                  line, pos);
+       } else if (os_strcmp(buf, "rsne_override") == 0) {
+               if (!get_hexstream(pos, &bss->rsne_override,
+                                  "rsne_override", line))
+                       return 1;
+       } else if (os_strcmp(buf, "rsnoe_override") == 0) {
+               if (!get_hexstream(pos, &bss->rsnoe_override,
+                                  "rsnoe_override", line))
+                       return 1;
+       } else if (os_strcmp(buf, "rsno2e_override") == 0) {
+               if (!get_hexstream(pos, &bss->rsno2e_override,
+                                  "rsno2e_override", line))
+                       return 1;
+       } else if (os_strcmp(buf, "rsnxe_override") == 0) {
+               if (!get_hexstream(pos, &bss->rsnxe_override,
+                                  "rsnxe_override", line))
+                       return 1;
+       } else if (os_strcmp(buf, "rsnxoe_override") == 0) {
+               if (!get_hexstream(pos, &bss->rsnxoe_override,
+                                  "rsnxoe_override", line))
                        return 1;
-               }
-
-               wpabuf_free(bss->own_ie_override);
-               bss->own_ie_override = tmp;
        } else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
                bss->sae_reflection_attack = atoi(pos);
        } else if (os_strcmp(buf, "sae_commit_status") == 0) {
index f7117b599e64a9cbdd0ddd6ce057a3b5bad9051b..c6aa496106134fec80d7dc5e7e6aaa5ca69f39b7 100644 (file)
@@ -964,6 +964,11 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 
 #ifdef CONFIG_TESTING_OPTIONS
        wpabuf_free(conf->own_ie_override);
+       wpabuf_free(conf->rsne_override);
+       wpabuf_free(conf->rsnoe_override);
+       wpabuf_free(conf->rsno2e_override);
+       wpabuf_free(conf->rsnxe_override);
+       wpabuf_free(conf->rsnxoe_override);
        wpabuf_free(conf->sae_commit_override);
        wpabuf_free(conf->rsne_override_eapol);
        wpabuf_free(conf->rsnxe_override_eapol);
index 1027de978f950c2f8bd0150f9a7af653f22550d4..cae2f97be3490aa122c542c5f287c818a891aa32 100644 (file)
@@ -696,6 +696,11 @@ struct hostapd_bss_config {
        u8 bss_load_test[5];
        u8 bss_load_test_set;
        struct wpabuf *own_ie_override;
+       struct wpabuf *rsne_override;
+       struct wpabuf *rsnoe_override;
+       struct wpabuf *rsno2e_override;
+       struct wpabuf *rsnxe_override;
+       struct wpabuf *rsnxoe_override;
        int sae_reflection_attack;
        int sae_commit_status;
        int sae_pk_omit;
index f8ce8103f0ad29166425c5727a246097f1da89c7..ddb99ca22313e2dca366425630baa6f62129cd41 100644 (file)
@@ -2188,7 +2188,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 
 #ifdef NEED_AP_MLME
 #define BEACON_HEAD_BUF_SIZE 256
-#define BEACON_TAIL_BUF_SIZE 512
+#define BEACON_TAIL_BUF_SIZE 1500
        head = os_zalloc(BEACON_HEAD_BUF_SIZE);
        tail_len = BEACON_TAIL_BUF_SIZE;
 #ifdef CONFIG_WPS
index 832d2e70e6e4180a159fb30a29704e8383bff767..39e3f0e1c0274465da5bee38034b32af0f038564 100644 (file)
@@ -230,6 +230,21 @@ struct wpa_auth_config {
        double corrupt_gtk_rekey_mic_probability;
        u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
        size_t own_ie_override_len;
+       bool rsne_override_set;
+       u8 rsne_override[MAX_OWN_IE_OVERRIDE];
+       size_t rsne_override_len;
+       bool rsnoe_override_set;
+       u8 rsnoe_override[MAX_OWN_IE_OVERRIDE];
+       size_t rsnoe_override_len;
+       bool rsno2e_override_set;
+       u8 rsno2e_override[MAX_OWN_IE_OVERRIDE];
+       size_t rsno2e_override_len;
+       bool rsnxe_override_set;
+       u8 rsnxe_override[MAX_OWN_IE_OVERRIDE];
+       size_t rsnxe_override_len;
+       bool rsnxoe_override_set;
+       u8 rsnxoe_override[MAX_OWN_IE_OVERRIDE];
+       size_t rsnxoe_override_len;
        u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE];
        size_t rsne_override_eapol_len;
        u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
index 2e7e6f25af87119c5ddbd3c34e05c659d5dc16c9..b31ff75a4fff4b662221d42f3bc205fc049fb07c 100644 (file)
@@ -132,6 +132,46 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
                          wpabuf_head(conf->own_ie_override),
                          wconf->own_ie_override_len);
        }
+       if (conf->rsne_override &&
+           wpabuf_len(conf->rsne_override) <= MAX_OWN_IE_OVERRIDE) {
+               wconf->rsne_override_len = wpabuf_len(conf->rsne_override);
+               os_memcpy(wconf->rsne_override,
+                         wpabuf_head(conf->rsne_override),
+                         wconf->rsne_override_len);
+               wconf->rsne_override_set = true;
+       }
+       if (conf->rsnoe_override &&
+           wpabuf_len(conf->rsnoe_override) <= MAX_OWN_IE_OVERRIDE) {
+               wconf->rsnoe_override_len = wpabuf_len(conf->rsnoe_override);
+               os_memcpy(wconf->rsnoe_override,
+                         wpabuf_head(conf->rsnoe_override),
+                         wconf->rsnoe_override_len);
+               wconf->rsnoe_override_set = true;
+       }
+       if (conf->rsno2e_override &&
+           wpabuf_len(conf->rsno2e_override) <= MAX_OWN_IE_OVERRIDE) {
+               wconf->rsno2e_override_len = wpabuf_len(conf->rsno2e_override);
+               os_memcpy(wconf->rsno2e_override,
+                         wpabuf_head(conf->rsno2e_override),
+                         wconf->rsno2e_override_len);
+               wconf->rsno2e_override_set = true;
+       }
+       if (conf->rsnxe_override &&
+           wpabuf_len(conf->rsnxe_override) <= MAX_OWN_IE_OVERRIDE) {
+               wconf->rsnxe_override_len = wpabuf_len(conf->rsnxe_override);
+               os_memcpy(wconf->rsnxe_override,
+                         wpabuf_head(conf->rsnxe_override),
+                         wconf->rsnxe_override_len);
+               wconf->rsnxe_override_set = true;
+       }
+       if (conf->rsnxoe_override &&
+           wpabuf_len(conf->rsnxoe_override) <= MAX_OWN_IE_OVERRIDE) {
+               wconf->rsnxoe_override_len = wpabuf_len(conf->rsnxoe_override);
+               os_memcpy(wconf->rsnxoe_override,
+                         wpabuf_head(conf->rsnxoe_override),
+                         wconf->rsnxoe_override_len);
+               wconf->rsnxoe_override_set = true;
+       }
        if (conf->rsne_override_eapol &&
            wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
                wconf->rsne_override_eapol_set = 1;
index 9a02f8e5dff576363a2a02afa59207ad3d1d4faf..6161edef1756981cbd15616d07e4cf07fe1a7946 100644 (file)
@@ -632,7 +632,7 @@ static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
 
 int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
 {
-       u8 *pos, buf[256];
+       u8 *pos, buf[1500];
        int res;
 
 #ifdef CONFIG_TESTING_OPTIONS
@@ -658,11 +658,42 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
                pos = wpa_write_osen(&wpa_auth->conf, pos);
        }
        if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsne_override_set) {
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Forced own RSNE for testing",
+                                   wpa_auth->conf.rsne_override,
+                                   wpa_auth->conf.rsne_override_len);
+                       if (sizeof(buf) - (pos - buf) <
+                           wpa_auth->conf.rsne_override_len)
+                               return -1;
+                       os_memcpy(pos, wpa_auth->conf.rsne_override,
+                                 wpa_auth->conf.rsne_override_len);
+                       pos += wpa_auth->conf.rsne_override_len;
+                       goto rsnxe;
+               }
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsn_ie(&wpa_auth->conf,
                                       pos, buf + sizeof(buf) - pos, NULL);
                if (res < 0)
                        return res;
                pos += res;
+#ifdef CONFIG_TESTING_OPTIONS
+       rsnxe:
+               if (wpa_auth->conf.rsnxe_override_set) {
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Forced own RSNXE for testing",
+                                   wpa_auth->conf.rsnxe_override,
+                                   wpa_auth->conf.rsnxe_override_len);
+                       if (sizeof(buf) - (pos - buf) <
+                           wpa_auth->conf.rsnxe_override_len)
+                               return -1;
+                       os_memcpy(pos, wpa_auth->conf.rsnxe_override,
+                                 wpa_auth->conf.rsnxe_override_len);
+                       pos += wpa_auth->conf.rsnxe_override_len;
+                       goto fte;
+               }
+#endif /* CONFIG_TESTING_OPTIONS */
                if (wpa_auth->conf.rsn_override_omit_rsnxe)
                        res = 0;
                else
@@ -672,6 +703,9 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
                        return res;
                pos += res;
        }
+#ifdef CONFIG_TESTING_OPTIONS
+fte:
+#endif /* CONFIG_TESTING_OPTIONS */
 #ifdef CONFIG_IEEE80211R_AP
        if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
                res = wpa_write_mdie(&wpa_auth->conf, pos,
@@ -690,30 +724,85 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
        }
        if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
            wpa_auth->conf.rsn_override_key_mgmt) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsnoe_override_set) {
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Forced own RSNOE for testing",
+                                   wpa_auth->conf.rsnoe_override,
+                                   wpa_auth->conf.rsnoe_override_len);
+                       if (sizeof(buf) - (pos - buf) <
+                           wpa_auth->conf.rsnoe_override_len)
+                               return -1;
+                       os_memcpy(pos, wpa_auth->conf.rsnoe_override,
+                                 wpa_auth->conf.rsnoe_override_len);
+                       pos += wpa_auth->conf.rsnoe_override_len;
+                       goto rsno2e;
+               }
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsne_override(&wpa_auth->conf,
                                              pos, buf + sizeof(buf) - pos);
                if (res < 0)
                        return res;
                pos += res;
        }
+#ifdef CONFIG_TESTING_OPTIONS
+rsno2e:
+#endif /* CONFIG_TESTING_OPTIONS */
        if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
            wpa_auth->conf.rsn_override_key_mgmt_2) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsno2e_override_set) {
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Forced own RSNO2E for testing",
+                                   wpa_auth->conf.rsno2e_override,
+                                   wpa_auth->conf.rsno2e_override_len);
+                       if (sizeof(buf) - (pos - buf) <
+                           wpa_auth->conf.rsno2e_override_len)
+                               return -1;
+                       os_memcpy(pos, wpa_auth->conf.rsno2e_override,
+                                 wpa_auth->conf.rsno2e_override_len);
+                       pos += wpa_auth->conf.rsno2e_override_len;
+                       goto rsnxoe;
+               }
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsne_override_2(&wpa_auth->conf, pos,
                                                buf + sizeof(buf) - pos);
                if (res < 0)
                        return res;
                pos += res;
        }
+#ifdef CONFIG_TESTING_OPTIONS
+rsnxoe:
+#endif /* CONFIG_TESTING_OPTIONS */
        if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
            (wpa_auth->conf.rsn_override_key_mgmt ||
             wpa_auth->conf.rsn_override_key_mgmt_2)) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsnxoe_override_set) {
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Forced own RSNXOE for testing",
+                                   wpa_auth->conf.rsnxoe_override,
+                                   wpa_auth->conf.rsnxoe_override_len);
+                       if (sizeof(buf) - (pos - buf) <
+                           wpa_auth->conf.rsnxoe_override_len)
+                               return -1;
+                       os_memcpy(pos, wpa_auth->conf.rsnxoe_override,
+                                 wpa_auth->conf.rsnxoe_override_len);
+                       pos += wpa_auth->conf.rsnxoe_override_len;
+                       goto done;
+               }
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsnxe_override(&wpa_auth->conf, pos,
                                               buf + sizeof(buf) - pos);
                if (res < 0)
                        return res;
                pos += res;
        }
+#ifdef CONFIG_TESTING_OPTIONS
+done:
+#endif /* CONFIG_TESTING_OPTIONS */
 
+       wpa_hexdump(MSG_DEBUG, "RSN: Own IEs", buf, pos - buf);
        os_free(wpa_auth->wpa_ie);
        wpa_auth->wpa_ie = os_malloc(pos - buf);
        if (wpa_auth->wpa_ie == NULL)
@@ -723,6 +812,13 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
 
        if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
            wpa_auth->conf.rsn_override_key_mgmt) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsnoe_override_set) {
+                       os_memcpy(buf, wpa_auth->conf.rsnoe_override,
+                                 wpa_auth->conf.rsnoe_override_len);
+                       res = wpa_auth->conf.rsnoe_override_len;
+               } else
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsne_override(&wpa_auth->conf, buf,
                                              sizeof(buf));
                if (res < 0)
@@ -739,6 +835,13 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
 
        if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
            wpa_auth->conf.rsn_override_key_mgmt_2) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsno2e_override_set) {
+                       os_memcpy(buf, wpa_auth->conf.rsno2e_override,
+                                 wpa_auth->conf.rsno2e_override_len);
+                       res = wpa_auth->conf.rsno2e_override_len;
+               } else
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsne_override_2(&wpa_auth->conf, buf,
                                                sizeof(buf));
                if (res < 0)
@@ -756,6 +859,13 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
        if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
            (wpa_auth->conf.rsn_override_key_mgmt ||
             wpa_auth->conf.rsn_override_key_mgmt_2)) {
+#ifdef CONFIG_TESTING_OPTIONS
+               if (wpa_auth->conf.rsnxoe_override_set) {
+                       os_memcpy(buf, wpa_auth->conf.rsnxoe_override,
+                                 wpa_auth->conf.rsnxoe_override_len);
+                       res = wpa_auth->conf.rsnxoe_override_len;
+               } else
+#endif /* CONFIG_TESTING_OPTIONS */
                res = wpa_write_rsnxe_override(&wpa_auth->conf, buf,
                                               sizeof(buf));
                if (res < 0)
index 0e989bebb1d3aee46dad86e6b65cf2247be0eb13..0ff0b1951b9560d22417a16c97c3313caa90f5ab 100644 (file)
@@ -246,3 +246,74 @@ def test_rsn_override_omit_rsnxe(dev, apdev):
     finally:
         dev[0].set("sae_pwe", "0")
         dev[0].set("rsn_overriding", "0")
+
+def test_rsn_override_replace_ies(dev, apdev):
+    """RSN overriding and replaced AP IEs"""
+    check_sae_capab(dev[0])
+
+    ssid = "test-rsn-override"
+    params = hostapd.wpa2_params(ssid=ssid,
+                                 passphrase="12345678",
+                                 ieee80211w='1')
+    params['rsn_override_key_mgmt'] = 'SAE'
+    params['rsn_override_key_mgmt_2'] = 'SAE-EXT-KEY'
+    params['rsn_override_pairwise'] = 'CCMP'
+    params['rsn_override_pairwise_2'] = 'GCMP-256'
+    params['rsn_override_mfp'] = '1'
+    params['rsn_override_mfp_2'] = '2'
+    params['beacon_prot'] = '1'
+    params['sae_groups'] = '19 20'
+    params['sae_require_mfp'] = '1'
+    params['sae_pwe'] = '2'
+    params['ssid_protection'] = '1'
+    params['rsne_override'] = '30180100000fac040100000fac040200000facff000fac020c00'
+    params['rsnxe_override'] = 'f40320eeee'
+    params['rsnoe_override'] = 'dd1c506f9a290100000fac040100000fac040200000facff000fac088c00'
+    params['rsno2e_override'] = 'dd1c506f9a2a0100000fac040100000fac090200000facff000fac18cc00'
+    params['rsnxoe_override'] = 'dd07506f9a2b20bbbb'
+    hapd = hostapd.add_ap(apdev[0], params)
+    bssid = hapd.own_addr()
+
+    try:
+        dev[0].set("rsn_overriding", "1")
+        dev[0].scan_for_bss(bssid, freq=2412)
+        dev[0].set("sae_pwe", "2")
+        dev[0].set("sae_groups", "")
+        dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
+                       ieee80211w="2", ssid_protection="1",
+                       scan_freq="2412")
+    finally:
+        dev[0].set("sae_pwe", "0")
+        dev[0].set("rsn_overriding", "0")
+
+def test_rsn_override_rsnxe_extensibility(dev, apdev):
+    """RSN overriding and RSNXE extensibility"""
+    check_sae_capab(dev[0])
+
+    ssid = "test-rsn-override"
+    params = hostapd.wpa2_params(ssid=ssid,
+                                 passphrase="12345678",
+                                 ieee80211w='1')
+    params['rsn_override_key_mgmt'] = 'SAE SAE-EXT-KEY'
+    params['rsn_override_pairwise'] = 'CCMP GCMP-256'
+    params['rsn_override_mfp'] = '2'
+    params['beacon_prot'] = '1'
+    params['sae_groups'] = '19 20'
+    params['sae_require_mfp'] = '1'
+    params['sae_pwe'] = '2'
+    params['rsnxe_override'] = 'f4182f0000ffffffffffffffffffffffffffeeeeeeeeeeeeeeee'
+    params['rsnxoe_override'] = 'dd1c506f9a2b2f0000ffffffffffffffffffffffffffeeeeeeeeeeeeeeee'
+    hapd = hostapd.add_ap(apdev[0], params)
+    bssid = hapd.own_addr()
+
+    try:
+        dev[0].set("rsn_overriding", "1")
+        dev[0].scan_for_bss(bssid, freq=2412)
+        dev[0].set("sae_pwe", "2")
+        dev[0].set("sae_groups", "")
+        dev[0].connect(ssid, sae_password="12345678", key_mgmt="SAE",
+                       ieee80211w="2", ssid_protection="1",
+                       scan_freq="2412")
+    finally:
+        dev[0].set("sae_pwe", "0")
+        dev[0].set("rsn_overriding", "0")