diff options
Diffstat (limited to 'freebsd/contrib/wpa/src/common/wpa_common.c')
-rw-r--r-- | freebsd/contrib/wpa/src/common/wpa_common.c | 141 |
1 files changed, 92 insertions, 49 deletions
diff --git a/freebsd/contrib/wpa/src/common/wpa_common.c b/freebsd/contrib/wpa/src/common/wpa_common.c index f2c2d56d..f1802c36 100644 --- a/freebsd/contrib/wpa/src/common/wpa_common.c +++ b/freebsd/contrib/wpa/src/common/wpa_common.c @@ -294,38 +294,47 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, pos = ie + sizeof(struct rsn_ftie); end = ie + ie_len; - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { + while (end - pos >= 2) { + u8 id, len; + + id = *pos++; + len = *pos++; + if (len > end - pos) + break; + + switch (id) { case FTIE_SUBELEM_R1KH_ID: - if (pos[1] != FT_R1KH_ID_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " - "length in FTIE: %d", pos[1]); + if (len != FT_R1KH_ID_LEN) { + wpa_printf(MSG_DEBUG, + "FT: Invalid R1KH-ID length in FTIE: %d", + len); return -1; } - parse->r1kh_id = pos + 2; + parse->r1kh_id = pos; break; case FTIE_SUBELEM_GTK: - parse->gtk = pos + 2; - parse->gtk_len = pos[1]; + parse->gtk = pos; + parse->gtk_len = len; break; case FTIE_SUBELEM_R0KH_ID: - if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " - "length in FTIE: %d", pos[1]); + if (len < 1 || len > FT_R0KH_ID_MAX_LEN) { + wpa_printf(MSG_DEBUG, + "FT: Invalid R0KH-ID length in FTIE: %d", + len); return -1; } - parse->r0kh_id = pos + 2; - parse->r0kh_id_len = pos[1]; + parse->r0kh_id = pos; + parse->r0kh_id_len = len; break; #ifdef CONFIG_IEEE80211W case FTIE_SUBELEM_IGTK: - parse->igtk = pos + 2; - parse->igtk_len = pos[1]; + parse->igtk = pos; + parse->igtk_len = len; break; #endif /* CONFIG_IEEE80211W */ } - pos += 2 + pos[1]; + pos += len; } return 0; @@ -347,11 +356,18 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, pos = ies; end = ies + ies_len; - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { + while (end - pos >= 2) { + u8 id, len; + + id = *pos++; + len = *pos++; + if (len > end - pos) + break; + + switch (id) { case WLAN_EID_RSN: - parse->rsn = pos + 2; - parse->rsn_len = pos[1]; + parse->rsn = pos; + parse->rsn_len = len; ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, parse->rsn_len + 2, &data); @@ -364,32 +380,32 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, parse->rsn_pmkid = data.pmkid; break; case WLAN_EID_MOBILITY_DOMAIN: - if (pos[1] < sizeof(struct rsn_mdie)) + if (len < sizeof(struct rsn_mdie)) return -1; - parse->mdie = pos + 2; - parse->mdie_len = pos[1]; + parse->mdie = pos; + parse->mdie_len = len; break; case WLAN_EID_FAST_BSS_TRANSITION: - if (pos[1] < sizeof(*ftie)) + if (len < sizeof(*ftie)) return -1; - ftie = (const struct rsn_ftie *) (pos + 2); + ftie = (const struct rsn_ftie *) pos; prot_ie_count = ftie->mic_control[1]; - if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) + if (wpa_ft_parse_ftie(pos, len, parse) < 0) return -1; break; case WLAN_EID_TIMEOUT_INTERVAL: - if (pos[1] != 5) + if (len != 5) break; - parse->tie = pos + 2; - parse->tie_len = pos[1]; + parse->tie = pos; + parse->tie_len = len; break; case WLAN_EID_RIC_DATA: if (parse->ric == NULL) - parse->ric = pos; + parse->ric = pos - 2; break; } - pos += 2 + pos[1]; + pos += len; } if (prot_ie_count == 0) @@ -418,13 +434,15 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, } /* Determine the end of the RIC IE(s) */ - pos = parse->ric; - while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && - prot_ie_count) { - prot_ie_count--; - pos += 2 + pos[1]; + if (parse->ric) { + pos = parse->ric; + while (end - pos >= 2 && 2 + pos[1] <= end - pos && + prot_ie_count) { + prot_ie_count--; + pos += 2 + pos[1]; + } + parse->ric_len = pos - parse->ric; } - parse->ric_len = pos - parse->ric; if (prot_ie_count) { wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " "frame", (int) prot_ie_count); @@ -584,8 +602,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, if (left >= RSN_SELECTOR_LEN) { data->group_cipher = rsn_selector_to_bitfield(pos); if (!wpa_cipher_valid_group(data->group_cipher)) { - wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x", - __func__, data->group_cipher); + wpa_printf(MSG_DEBUG, + "%s: invalid group cipher 0x%x (%08x)", + __func__, data->group_cipher, + WPA_GET_BE32(pos)); return -1; } pos += RSN_SELECTOR_LEN; @@ -673,9 +693,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, if (left >= 4) { data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { - wpa_printf(MSG_DEBUG, "%s: Unsupported management " - "group cipher 0x%x", __func__, - data->mgmt_group_cipher); + wpa_printf(MSG_DEBUG, + "%s: Unsupported management group cipher 0x%x (%08x)", + __func__, data->mgmt_group_cipher, + WPA_GET_BE32(pos)); return -10; } pos += RSN_SELECTOR_LEN; @@ -1165,6 +1186,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) "WPA2-PSK" : "WPA-PSK"; case WPA_KEY_MGMT_NONE: return "NONE"; + case WPA_KEY_MGMT_WPA_NONE: + return "WPA-NONE"; case WPA_KEY_MGMT_IEEE8021X_NO_WPA: return "IEEE 802.1X (no WPA)"; #ifdef CONFIG_IEEE80211R @@ -1263,13 +1286,13 @@ int wpa_compare_rsn_ie(int ft_initial_assoc, #ifdef CONFIG_IEEE80211R -int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) +int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid) { u8 *start, *end, *rpos, *rend; int added = 0; start = ies; - end = ies + ies_len; + end = ies + *ies_len; while (start < end) { if (*start == WLAN_EID_RSN) @@ -1322,11 +1345,29 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) added += 2 + PMKID_LEN; start[1] += 2 + PMKID_LEN; } else { - /* PMKID-Count was included; use it */ - if (WPA_GET_LE16(rpos) != 0) { - wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " - "in RSN IE in EAPOL-Key data"); + u16 num_pmkid; + + if (rend - rpos < 2) return -1; + num_pmkid = WPA_GET_LE16(rpos); + /* PMKID-Count was included; use it */ + if (num_pmkid != 0) { + u8 *after; + + if (num_pmkid * PMKID_LEN > rend - rpos - 2) + return -1; + /* + * PMKID may have been included in RSN IE in + * (Re)Association Request frame, so remove the old + * PMKID(s) first before adding the new one. + */ + wpa_printf(MSG_DEBUG, + "FT: Remove %u old PMKID(s) from RSN IE", + num_pmkid); + after = rpos + 2 + num_pmkid * PMKID_LEN; + os_memmove(rpos + 2, after, rend - after); + start[1] -= num_pmkid * PMKID_LEN; + added -= num_pmkid * PMKID_LEN; } WPA_PUT_LE16(rpos, 1); rpos += 2; @@ -1339,7 +1380,9 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " "(PMKID inserted)", start, 2 + start[1]); - return added; + *ies_len += added; + + return 0; } #endif /* CONFIG_IEEE80211R */ |