]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add an EAPOL payload length workaround for a WPS implementation
authorJouni Malinen <jouni.malinen@atheros.com>
Fri, 23 Jan 2009 16:01:03 +0000 (18:01 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 23 Jan 2009 16:01:03 +0000 (18:01 +0200)
Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS packets with too short
EAPOL header length field (14 octets regardless of EAP frame length).
This is fixed in firmware Ver.1.49, but the broken version is included
in many deployed APs. As a workaround, fix the EAPOL header based on the
correct length in the EAP packet. This workaround can be disabled with
eap_workaround=0 option in the network configuration.

src/eapol_supp/eapol_supp_sm.c

index f382ee655f8f5315a20ac10f3d663d6307733dc0..c832b5ae2cbf630f98ae0a7e354953fc05180d82 100644 (file)
@@ -1165,6 +1165,31 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
                sm->dot1xSuppEapLengthErrorFramesRx++;
                return 0;
        }
+#ifdef CONFIG_WPS
+       if (sm->conf.workaround &&
+           plen < len - sizeof(*hdr) &&
+           hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
+           len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
+               const struct eap_hdr *ehdr =
+                       (const struct eap_hdr *) (hdr + 1);
+               u16 elen;
+
+               elen = be_to_host16(ehdr->length);
+               if (elen > plen && elen <= len - sizeof(*hdr)) {
+                       /*
+                        * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
+                        * packets with too short EAPOL header length field
+                        * (14 octets). This is fixed in firmware Ver.1.49.
+                        * As a workaround, fix the EAPOL header based on the
+                        * correct length in the EAP packet.
+                        */
+                       wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
+                                  "payload length based on EAP header: "
+                                  "%d -> %d", (int) plen, elen);
+                       plen = elen;
+               }
+       }
+#endif /* CONFIG_WPS */
        data_len = plen + sizeof(*hdr);
 
        switch (hdr->type) {
@@ -1349,6 +1374,7 @@ void eapol_sm_notify_config(struct eapol_sm *sm,
        sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
        sm->conf.required_keys = conf->required_keys;
        sm->conf.fast_reauth = conf->fast_reauth;
+       sm->conf.workaround = conf->workaround;
        if (sm->eap) {
                eap_set_fast_reauth(sm->eap, conf->fast_reauth);
                eap_set_workaround(sm->eap, conf->workaround);