FT: Verify that MDIE and FTIE matches between AssocResp and EAPOL-Key 3/4
authorJouni Malinen <j@w1.fi>
Sat, 10 Apr 2010 19:06:13 +0000 (22:06 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 10 Apr 2010 19:06:13 +0000 (22:06 +0300)
src/rsn_supp/wpa.c

index b4c6e03..09b1619 100644 (file)
@@ -794,13 +794,11 @@ static void wpa_report_ie_mismatch(struct wpa_sm *sm,
 
 static int ft_validate_mdie(struct wpa_sm *sm,
                            const unsigned char *src_addr,
-                           struct wpa_eapol_ie_parse *ie)
+                           struct wpa_eapol_ie_parse *ie,
+                           const u8 *assoc_resp_mdie)
 {
        struct rsn_mdie *mdie;
 
-       /* TODO: verify that full MDIE matches with the one from scan
-        * results, not only mobility domain */
-
        mdie = (struct rsn_mdie *) (ie->mdie + 2);
        if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
            os_memcmp(mdie->mobility_domain, sm->mobility_domain,
@@ -810,6 +808,44 @@ static int ft_validate_mdie(struct wpa_sm *sm,
                return -1;
        }
 
+       if (assoc_resp_mdie &&
+           (assoc_resp_mdie[1] != ie->mdie[1] ||
+            os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
+               wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
+               wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
+                           ie->mdie, 2 + ie->mdie[1]);
+               wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
+                           assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int ft_validate_ftie(struct wpa_sm *sm,
+                           const unsigned char *src_addr,
+                           struct wpa_eapol_ie_parse *ie,
+                           const u8 *assoc_resp_ftie)
+{
+       if (ie->ftie == NULL) {
+               wpa_printf(MSG_DEBUG, "FT: No FTIE in EAPOL-Key msg 3/4");
+               return -1;
+       }
+
+       if (assoc_resp_ftie == NULL)
+               return 0;
+
+       if (assoc_resp_ftie[1] != ie->ftie[1] ||
+           os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
+               wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
+               wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
+                           ie->ftie, 2 + ie->ftie[1]);
+               wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
+                           assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
+               return -1;
+       }
+
        return 0;
 }
 
@@ -852,7 +888,28 @@ static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
                                         const unsigned char *src_addr,
                                         struct wpa_eapol_ie_parse *ie)
 {
-       if (ft_validate_mdie(sm, src_addr, ie) < 0 ||
+       const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
+
+       if (sm->assoc_resp_ies) {
+               pos = sm->assoc_resp_ies;
+               end = pos + sm->assoc_resp_ies_len;
+               while (pos + 2 < end) {
+                       if (pos + 2 + pos[1] > end)
+                               break;
+                       switch (*pos) {
+                       case WLAN_EID_MOBILITY_DOMAIN:
+                               mdie = pos;
+                               break;
+                       case WLAN_EID_FAST_BSS_TRANSITION:
+                               ftie = pos;
+                               break;
+                       }
+                       pos += 2 + pos[1];
+               }
+       }
+
+       if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
+           ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
            ft_validate_rsnie(sm, src_addr, ie) < 0)
                return -1;