]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Wait for EAPOL-Start unless WPS 2.0 station as workaround
authorJouni Malinen <j@w1.fi>
Sun, 28 Aug 2011 16:16:59 +0000 (19:16 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 28 Aug 2011 16:16:59 +0000 (19:16 +0300)
Extend the code that waits for the station to send EAPOL-Start before
initiating EAPOL authenticator operations to cover the case where the
station includes WPS IE in (Re)Association Request frame if that IE
does not include support for WPS 2.0. While this should not really
be needed, this may help with some deployed WPS 1.0 stations that do
not support EAPOL operations correctly and may get confused of the
EAP-Request/Identity packets that would show up twice if EAPOL-Start
is transmitted.

hostapd/dump_state.c
src/ap/drv_callbacks.c
src/ap/ieee802_11.c
src/ap/ieee802_1x.c
src/ap/sta_info.h
src/wps/wps.c
src/wps/wps.h

index 73aa93dfbd599484b3d8b8515b60065cd5575373..408c4f1518a0f8eaed409466dff59bfa04287720 100644 (file)
@@ -106,7 +106,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
                fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
 
                fprintf(f,
-                       "  AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
+                       "  AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
+                       "\n"
                        "  capability=0x%x listen_interval=%d\n",
                        sta->aid,
                        sta->flags,
@@ -127,6 +128,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
                        (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
                        (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
                        (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
+                       (sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
                        sta->capability,
                        sta->listen_interval);
 
index db2d5f226b3fae8d20f48f55b116aeed89ca9a9e..443c1fa6a51c3a8961c4f99f02afd2b78e244455 100644 (file)
@@ -93,7 +93,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                if (sta == NULL)
                        return -1;
        }
-       sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+       sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
 
 #ifdef CONFIG_P2P
        if (elems.p2p) {
@@ -118,7 +118,18 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                }
                if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
                    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+                       struct wpabuf *wps;
                        sta->flags |= WLAN_STA_WPS;
+                       wps = ieee802_11_vendor_ie_concat(ie, ielen,
+                                                         WPS_IE_VENDOR_TYPE);
+                       if (wps) {
+                               if (wps_is_20(wps)) {
+                                       wpa_printf(MSG_DEBUG, "WPS: STA "
+                                                  "supports WPS 2.0");
+                                       sta->flags |= WLAN_STA_WPS2;
+                               }
+                               wpabuf_free(wps);
+                       }
                        goto skip_wpa_check;
                }
 
@@ -156,11 +167,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                        return -1;
                }
        } else if (hapd->conf->wps_state) {
+               struct wpabuf *wps;
+               wps = ieee802_11_vendor_ie_concat(ie, ielen,
+                                                 WPS_IE_VENDOR_TYPE);
 #ifdef CONFIG_WPS_STRICT
                if (ie) {
-                       struct wpabuf *wps;
-                       wps = ieee802_11_vendor_ie_concat(ie, ielen,
-                                                         WPS_IE_VENDOR_TYPE);
                        if (wps && wps_validate_assoc_req(wps) < 0) {
                                hostapd_drv_sta_disassoc(
                                        hapd, sta->addr,
@@ -175,8 +186,14 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
                if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
                    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
                        sta->flags |= WLAN_STA_WPS;
+                       if (wps && wps_is_20(wps)) {
+                               wpa_printf(MSG_DEBUG, "WPS: STA supports "
+                                          "WPS 2.0");
+                               sta->flags |= WLAN_STA_WPS2;
+                       }
                } else
                        sta->flags |= WLAN_STA_MAYBE_WPS;
+               wpabuf_free(wps);
        }
 skip_wpa_check:
 
index 227a0a52f67b4e221620d857e665c6f826aaaeae..c1c4314ac132e0b0ec707559ffb0e70669413b0f 100644 (file)
@@ -701,7 +701,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
        }
 
 #ifdef CONFIG_WPS
-       sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+       sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
        if (hapd->conf->wps_state && elems.wps_ie) {
                wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
                           "Request - assume WPS is used");
@@ -709,6 +709,10 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
                wpabuf_free(sta->wps_ie);
                sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
                                                          WPS_IE_VENDOR_TYPE);
+               if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
+                       wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
+                       sta->flags |= WLAN_STA_WPS2;
+               }
                wpa_ie = NULL;
                wpa_ie_len = 0;
                if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
index 6b6fd4bdf24595641fd301e5bf3e1a5cb40e159c..ea8ca11476f7de5fb0ebf972ccce18dc7301ce0f 100644 (file)
@@ -752,14 +752,24 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
                        return;
 
 #ifdef CONFIG_WPS
-               if (!hapd->conf->ieee802_1x &&
-                   ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
-                    WLAN_STA_MAYBE_WPS)) {
-                       /*
-                        * Delay EAPOL frame transmission until a possible WPS
-                        * STA initiates the handshake with EAPOL-Start.
-                        */
-                       sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+               if (!hapd->conf->ieee802_1x) {
+                       u32 wflags = sta->flags & (WLAN_STA_WPS |
+                                                  WLAN_STA_WPS2 |
+                                                  WLAN_STA_MAYBE_WPS);
+                       if (wflags == WLAN_STA_MAYBE_WPS ||
+                           wflags == (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) {
+                               /*
+                                * Delay EAPOL frame transmission until a
+                                * possible WPS STA initiates the handshake
+                                * with EAPOL-Start. Only allow the wait to be
+                                * skipped if the STA is known to support WPS
+                                * 2.0.
+                                */
+                               wpa_printf(MSG_DEBUG, "WPS: Do not start "
+                                          "EAPOL until EAPOL-Start is "
+                                          "received");
+                               sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+                       }
                }
 #endif /* CONFIG_WPS */
 
@@ -888,11 +898,14 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
 
 #ifdef CONFIG_WPS
        sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
-       if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
+       if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS2)) {
                /*
-                * Delay EAPOL frame transmission until a possible WPS
-                * initiates the handshake with EAPOL-Start.
+                * Delay EAPOL frame transmission until a possible WPS STA
+                * initiates the handshake with EAPOL-Start. Only allow the
+                * wait to be skipped if the STA is known to support WPS 2.0.
                 */
+               wpa_printf(MSG_DEBUG, "WPS: Do not start EAPOL until "
+                          "EAPOL-Start is received");
                sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
        }
 #endif /* CONFIG_WPS */
index 9ec4fe33e40ee924ba6145d9fcf15c5c16c29c39..318481f2753473c6bb19977e25c1dc0b2f21736e 100644 (file)
@@ -32,6 +32,7 @@
 #define WLAN_STA_MAYBE_WPS BIT(13)
 #define WLAN_STA_WDS BIT(14)
 #define WLAN_STA_ASSOC_REQ_OK BIT(15)
+#define WLAN_STA_WPS2 BIT(16)
 #define WLAN_STA_NONERP BIT(31)
 
 /* Maximum number of supported rates (from both Supported Rates and Extended
index 5c8c25fea61dfa7742f7140035b0617b4452d43d..101ae1d0b94eb4b19b2b3a5e9e6dfed7dce41492 100644 (file)
@@ -354,6 +354,19 @@ const u8 * wps_get_uuid_e(const struct wpabuf *msg)
 }
 
 
+/**
+ * wps_is_20 - Check whether WPS attributes claim support for WPS 2.0
+ */
+int wps_is_20(const struct wpabuf *msg)
+{
+       struct wps_parse_attr attr;
+
+       if (msg == NULL || wps_parse_msg(msg, &attr) < 0)
+               return 0;
+       return attr.version2 != NULL;
+}
+
+
 /**
  * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request
  * @req_type: Value for Request Type attribute
index 3e4c2185b6989825307dcf3148d24d927fbc6343..2cbbc1855ab1a67f88e607fcbc5e49de66088d19 100644 (file)
@@ -239,6 +239,7 @@ int wps_ap_priority_compar(const struct wpabuf *wps_a,
 int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
                           int ver1_compat);
 const u8 * wps_get_uuid_e(const struct wpabuf *msg);
+int wps_is_20(const struct wpabuf *msg);
 
 struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type);
 struct wpabuf * wps_build_assoc_resp_ie(void);