WPA: Fix wpa_parse_kde_ies() handling with vendor specific elements

Documentation of the return values for wpa_parse_vendor_specific() and
wpa_parse_generic() were not accurate and the parsing results from these
were not really handled appropriately. There is no point in calling
wpa_parse_vendor_specific() if wpa_parse_generic() recognizes a KDE. Not
that this would break anything in practice, but still, it looks
confusing.

The part about handling wpa_parse_vendor_specific() return value can, at
least in theory, break some cases where an unexpectedly short KDE/vendor
specific element were present and something would need to be recognized
after it. That does not really happen with any standard compliant
implementation and this is unlikely to cause any real harm, but it is
clearer to handle this more appropriately even for any theoretical case,
including misbehavior of a peer device.

Instead of stopping parsing on too short vendor specific element,
continue parsing the following KDEs/IEs. Skip the
wpa_parse_vendor_specific() call when a KDE has been recognized. Also
fix the return value documentation for wpa_parse_generic() and remove
the useless return value from wpa_parse_vendor_specific().

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-04-23 23:30:23 +03:00 committed by Jouni Malinen
parent 1025a9052c
commit 4d9c313f2a

View file

@ -2655,10 +2655,9 @@ int fils_domain_name_hash(const char *domain, u8 *hash)
* @pos: Pointer to the IE header
* @end: Pointer to the end of the Key Data buffer
* @ie: Pointer to parsed IE data
* Returns: 0 on success, 1 if end mark is found, -1 on failure
*/
static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end,
struct wpa_eapol_ie_parse *ie)
static void wpa_parse_vendor_specific(const u8 *pos, const u8 *end,
struct wpa_eapol_ie_parse *ie)
{
unsigned int oui;
@ -2666,7 +2665,7 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end,
wpa_printf(MSG_MSGDUMP,
"Too short vendor specific IE ignored (len=%u)",
pos[1]);
return 1;
return;
}
oui = WPA_GET_BE24(&pos[2]);
@ -2683,7 +2682,6 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end,
ie->wmm, ie->wmm_len);
}
}
return 0;
}
@ -2691,7 +2689,7 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end,
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
* @pos: Pointer to the IE header
* @ie: Pointer to parsed IE data
* Returns: 0 on success, 1 if end mark is found, -1 on failure
* Returns: 0 on success, 1 if end mark is found, 2 if KDE is not recognized
*/
static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
{
@ -2803,7 +2801,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
return 0;
}
return 0;
return 2;
}
@ -2912,20 +2910,18 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
}
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, ie);
if (ret < 0)
break;
if (ret > 0) {
if (ret == 1) {
/* end mark found */
ret = 0;
break;
}
ret = wpa_parse_vendor_specific(pos, end, ie);
if (ret < 0)
break;
if (ret > 0) {
ret = 0;
break;
if (ret == 2) {
/* not a known KDE */
wpa_parse_vendor_specific(pos, end, ie);
}
ret = 0;
} else {
wpa_hexdump(MSG_DEBUG,
"WPA: Unrecognized EAPOL-Key Key Data IE",