]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
RSN: Verify RSNXE match between Beacon/ProbeResp and EAPOL-Key msg 3/4
authorJouni Malinen <jouni@codeaurora.org>
Fri, 6 Sep 2019 11:51:31 +0000 (14:51 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 15 Oct 2019 12:39:22 +0000 (15:39 +0300)
If the AP advertises RSN Extension element, it has to be advertised
consistently in the unprotected (Beacon and Probe Response) and
protected (EAPOL-Key msg 3/4) frames. Verify that this is the case.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
src/rsn_supp/wpa_ie.c
src/rsn_supp/wpa_ie.h
wpa_supplicant/events.c
wpa_supplicant/ibss_rsn.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpas_glue.c

index 9707ae7ab6f307ad390dd7801f840ab637df6e05..f5231c138b908dbf16d39e6ffa695a129d51b5a9 100644 (file)
@@ -1365,6 +1365,16 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
                return -1;
        }
 
+       if ((sm->ap_rsnxe && !ie->rsnxe) ||
+           (!sm->ap_rsnxe && ie->rsnxe) ||
+           (sm->ap_rsnxe && ie->rsnxe &&
+            (sm->ap_rsnxe_len != ie->rsnxe_len ||
+             os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0))) {
+               wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+                       "WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
+               return -1;
+       }
+
 #ifdef CONFIG_IEEE80211R
        if (wpa_key_mgmt_ft(sm->key_mgmt) &&
            wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
@@ -2664,6 +2674,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
        os_free(sm->assoc_wpa_ie);
        os_free(sm->ap_wpa_ie);
        os_free(sm->ap_rsn_ie);
+       os_free(sm->ap_rsnxe);
        wpa_sm_drop_sa(sm);
        os_free(sm->ctx);
 #ifdef CONFIG_IEEE80211R
@@ -3283,6 +3294,39 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
 }
 
 
+/**
+ * wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
+ * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @ie: Pointer to IE data (starting from id)
+ * @len: IE length
+ * Returns: 0 on success, -1 on failure
+ *
+ * Inform WPA state machine about the RSNXE used in Beacon / Probe Response
+ * frame.
+ */
+int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
+{
+       if (!sm)
+               return -1;
+
+       os_free(sm->ap_rsnxe);
+       if (!ie || len == 0) {
+               wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
+               sm->ap_rsnxe = NULL;
+               sm->ap_rsnxe_len = 0;
+       } else {
+               wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
+               sm->ap_rsnxe = os_memdup(ie, len);
+               if (!sm->ap_rsnxe)
+                       return -1;
+
+               sm->ap_rsnxe_len = len;
+       }
+
+       return 0;
+}
+
+
 /**
  * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
index ae9cd6484baa3e3c043972b7ff3f990a83b8ed24..125d359ef6284e4e798cd5e5489a366fd2303e13 100644 (file)
@@ -136,6 +136,7 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
                                    size_t *wpa_ie_len);
 int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
 int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
+int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
 int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
 
 int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
@@ -260,6 +261,12 @@ static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie,
        return -1;
 }
 
+static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie,
+                                     size_t len)
+{
+       return -1;
+}
+
 static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
 {
        return 0;
index 129dfb14ac8be0a8eb77e3c7022925390698c85d..16224c9ef65fd5957bf783d852b64a0aecae8579 100644 (file)
@@ -88,8 +88,8 @@ struct wpa_sm {
 
        u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
        size_t assoc_wpa_ie_len;
-       u8 *ap_wpa_ie, *ap_rsn_ie;
-       size_t ap_wpa_ie_len, ap_rsn_ie_len;
+       u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
+       size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
 
 #ifdef CONFIG_TDLS
        struct wpa_tdls_peer *tdls;
index 809f208f0ef42435342f8e7121a5eba786b4cc2f..e6af6c10e7009ae6715329d827c31867393aa895 100644 (file)
@@ -506,6 +506,11 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
                        ie->rsn_ie_len = pos[1] + 2;
                        wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
                                    ie->rsn_ie, ie->rsn_ie_len);
+               } else if (*pos == WLAN_EID_RSNX) {
+                       ie->rsnxe = pos;
+                       ie->rsnxe_len = pos[1] + 2;
+                       wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
+                                   ie->rsnxe, ie->rsnxe_len);
                } else if (*pos == WLAN_EID_MOBILITY_DOMAIN &&
                           pos[1] >= sizeof(struct rsn_mdie)) {
                        ie->mdie = pos;
index 77ebe2172a74325f0846e652a1eda6b5ce2ff879..6f18bbe2ae58cece4c33ffee880dd2839921faa5 100644 (file)
@@ -23,6 +23,8 @@ struct wpa_eapol_ie_parse {
        size_t mac_addr_len;
        const u8 *igtk;
        size_t igtk_len;
+       const u8 *rsnxe;
+       size_t rsnxe_len;
        const u8 *mdie;
        size_t mdie_len;
        const u8 *ftie;
index 523b7bd4639bb6e71143f299c5d85953feb7b5be..c9ead080e8dba64ca8af0c920319856eab1ca59a 100644 (file)
@@ -2647,14 +2647,19 @@ no_pfs:
                        wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
                }
 
+               if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
+                       wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+
                l -= len;
                p += len;
        }
 
        if (!wpa_found && data->assoc_info.beacon_ies)
                wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
-       if (!rsn_found && data->assoc_info.beacon_ies)
+       if (!rsn_found && data->assoc_info.beacon_ies) {
                wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
+               wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+       }
        if (wpa_found || rsn_found)
                wpa_s->ap_ies_from_associnfo = 1;
 
@@ -2674,7 +2679,7 @@ no_pfs:
 
 static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
 {
-       const u8 *bss_wpa = NULL, *bss_rsn = NULL;
+       const u8 *bss_wpa = NULL, *bss_rsn = NULL, *bss_rsnx = NULL;
 
        if (!wpa_s->current_bss || !wpa_s->current_ssid)
                return -1;
@@ -2685,11 +2690,14 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
        bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
                                        WPA_IE_VENDOR_TYPE);
        bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
+       bss_rsnx = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSNX);
 
        if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
                                 bss_wpa ? 2 + bss_wpa[1] : 0) ||
            wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
-                                bss_rsn ? 2 + bss_rsn[1] : 0))
+                                bss_rsn ? 2 + bss_rsn[1] : 0) ||
+           wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
+                                bss_rsnx ? 2 + bss_rsnx[1] : 0))
                return -1;
 
        return 0;
index 6934c4725da3f4447764d689ed903686bff5ea89..2bf51c626d42056282e05cd992a488f61888532d 100644 (file)
@@ -111,6 +111,7 @@ static int supp_get_beacon_ie(void *ctx)
 
        wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
        /* TODO: get correct RSN IE */
+       wpa_sm_set_ap_rsnxe(peer->supp, NULL, 0);
        return wpa_sm_set_ap_rsn_ie(peer->supp,
                                    (u8 *) "\x30\x14\x01\x00"
                                    "\x00\x0f\xac\x04"
index 94cc8c76020edd2dd5442e4a0bfd183d30ffdb2c..ca8e1cc0b2c93e6eead3d05aa135b3bcf52026f8 100644 (file)
@@ -402,6 +402,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
                wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
        wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
        wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
+       wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
        wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
        wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
        wpa_s->group_cipher = WPA_CIPHER_NONE;
@@ -1233,14 +1234,16 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 {
        struct wpa_ie_data ie;
        int sel, proto;
-       const u8 *bss_wpa, *bss_rsn, *bss_osen;
+       const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
 
        if (bss) {
                bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
                bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+               bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
                bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
-       } else
-               bss_wpa = bss_rsn = bss_osen = NULL;
+       } else {
+               bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
+       }
 
        if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
            wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
@@ -1371,7 +1374,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
                                         bss_wpa ? 2 + bss_wpa[1] : 0) ||
                    wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
-                                        bss_rsn ? 2 + bss_rsn[1] : 0))
+                                        bss_rsn ? 2 + bss_rsn[1] : 0) ||
+                   wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
+                                       bss_rsnx ? 2 + bss_rsnx[1] : 0))
                        return -1;
        }
 
index 62af7f6b1013472d016a6d19e8bebe9a657c53a7..d80b8f28dda4e0b9fb0f6e17bdf137dae75f0abb 100644 (file)
@@ -396,6 +396,10 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
                ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
                if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
                        ret = -1;
+
+               ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
+               if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
+                       ret = -1;
        } else {
                ret = -1;
        }