WPS: Wait for EAPOL-Start unless WPS 2.0 station as workaround
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.
This commit is contained in:
parent
fb91db5639
commit
17f6b90056
7 changed files with 68 additions and 17 deletions
|
@ -106,7 +106,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||||
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
||||||
|
|
||||||
fprintf(f,
|
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",
|
" capability=0x%x listen_interval=%d\n",
|
||||||
sta->aid,
|
sta->aid,
|
||||||
sta->flags,
|
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_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
||||||
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
||||||
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
||||||
|
(sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
|
||||||
sta->capability,
|
sta->capability,
|
||||||
sta->listen_interval);
|
sta->listen_interval);
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
if (sta == NULL)
|
if (sta == NULL)
|
||||||
return -1;
|
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
|
#ifdef CONFIG_P2P
|
||||||
if (elems.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 &&
|
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||||
|
struct wpabuf *wps;
|
||||||
sta->flags |= WLAN_STA_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;
|
goto skip_wpa_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +167,11 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if (hapd->conf->wps_state) {
|
} else if (hapd->conf->wps_state) {
|
||||||
#ifdef CONFIG_WPS_STRICT
|
|
||||||
if (ie) {
|
|
||||||
struct wpabuf *wps;
|
struct wpabuf *wps;
|
||||||
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
wps = ieee802_11_vendor_ie_concat(ie, ielen,
|
||||||
WPS_IE_VENDOR_TYPE);
|
WPS_IE_VENDOR_TYPE);
|
||||||
|
#ifdef CONFIG_WPS_STRICT
|
||||||
|
if (ie) {
|
||||||
if (wps && wps_validate_assoc_req(wps) < 0) {
|
if (wps && wps_validate_assoc_req(wps) < 0) {
|
||||||
hostapd_drv_sta_disassoc(
|
hostapd_drv_sta_disassoc(
|
||||||
hapd, sta->addr,
|
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 &&
|
if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
|
||||||
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
||||||
sta->flags |= WLAN_STA_WPS;
|
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
|
} else
|
||||||
sta->flags |= WLAN_STA_MAYBE_WPS;
|
sta->flags |= WLAN_STA_MAYBE_WPS;
|
||||||
|
wpabuf_free(wps);
|
||||||
}
|
}
|
||||||
skip_wpa_check:
|
skip_wpa_check:
|
||||||
|
|
||||||
|
|
|
@ -701,7 +701,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WPS
|
#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) {
|
if (hapd->conf->wps_state && elems.wps_ie) {
|
||||||
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
|
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
|
||||||
"Request - assume WPS is used");
|
"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);
|
wpabuf_free(sta->wps_ie);
|
||||||
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
|
sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
|
||||||
WPS_IE_VENDOR_TYPE);
|
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 = NULL;
|
||||||
wpa_ie_len = 0;
|
wpa_ie_len = 0;
|
||||||
if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
|
if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
|
||||||
|
|
|
@ -752,15 +752,25 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef CONFIG_WPS
|
#ifdef CONFIG_WPS
|
||||||
if (!hapd->conf->ieee802_1x &&
|
if (!hapd->conf->ieee802_1x) {
|
||||||
((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
|
u32 wflags = sta->flags & (WLAN_STA_WPS |
|
||||||
WLAN_STA_MAYBE_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
|
* Delay EAPOL frame transmission until a
|
||||||
* STA initiates the handshake with EAPOL-Start.
|
* 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;
|
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
sta->eapol_sm->eap_if->portEnabled = TRUE;
|
sta->eapol_sm->eap_if->portEnabled = TRUE;
|
||||||
|
@ -888,11 +898,14 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
|
|
||||||
#ifdef CONFIG_WPS
|
#ifdef CONFIG_WPS
|
||||||
sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
|
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
|
* Delay EAPOL frame transmission until a possible WPS STA
|
||||||
* initiates the handshake with EAPOL-Start.
|
* 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;
|
sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define WLAN_STA_MAYBE_WPS BIT(13)
|
#define WLAN_STA_MAYBE_WPS BIT(13)
|
||||||
#define WLAN_STA_WDS BIT(14)
|
#define WLAN_STA_WDS BIT(14)
|
||||||
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
|
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
|
||||||
|
#define WLAN_STA_WPS2 BIT(16)
|
||||||
#define WLAN_STA_NONERP BIT(31)
|
#define WLAN_STA_NONERP BIT(31)
|
||||||
|
|
||||||
/* Maximum number of supported rates (from both Supported Rates and Extended
|
/* Maximum number of supported rates (from both Supported Rates and Extended
|
||||||
|
|
|
@ -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
|
* wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request
|
||||||
* @req_type: Value for Request Type attribute
|
* @req_type: Value for Request Type attribute
|
||||||
|
|
|
@ -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 wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
|
||||||
int ver1_compat);
|
int ver1_compat);
|
||||||
const u8 * wps_get_uuid_e(const struct wpabuf *msg);
|
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_req_ie(enum wps_request_type req_type);
|
||||||
struct wpabuf * wps_build_assoc_resp_ie(void);
|
struct wpabuf * wps_build_assoc_resp_ie(void);
|
||||||
|
|
Loading…
Reference in a new issue