]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPA: Fix wpa_parse_kde_ies() handling with vendor specific elements
authorJouni Malinen <jouni@codeaurora.org>
Thu, 23 Apr 2020 20:30:23 +0000 (23:30 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 24 Apr 2020 14:06:50 +0000 (17:06 +0300)
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>
src/common/wpa_common.c

index 46b647bcd05ec39399d7d4b4500767d1bcb2c7e8..eb1861a8724c7ed1891cd25f82d212636144b7d7 100644 (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",