aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-01-07 04:15:42 (GMT)
committerJouni Malinen <j@w1.fi>2008-01-07 04:15:42 (GMT)
commitc41bf46f976606bfcdb3d1e88e27eda034a4f25c (patch)
tree8f1d48d92333971f774fee2c14d24858df61317c /hostapd
parent47bd1fb0872559dec39d96d09f236c170d15e3f7 (diff)
downloadhostap-history-c41bf46f976606bfcdb3d1e88e27eda034a4f25c.zip
hostap-history-c41bf46f976606bfcdb3d1e88e27eda034a4f25c.tar.gz
hostap-history-c41bf46f976606bfcdb3d1e88e27eda034a4f25c.tar.bz2
WPS: Allow non-WPA association if WPS is enabled and start EAPOL
If WPS is enabled, allow non-WPA association even when the BSS is configured to use WPA in order to allow WPS handshake to be used. Start EAPOL handshake in this kind of case even if IEEE 802.1X is disabled for authentication. However, delay sending of EAP-Request/Identity until an EAPOL-Start is received unless the STA included WPS IE in (Re)Association Request (in which case the normal EAPOL processing is started). WPA state machines are not initialized for the STA if WPA/RSN IE is not included in (Re)Association Request, so this special case is used to start EAPOL state machines for EAP-WSC regardless of WPA/EAPOL configuration.
Diffstat (limited to 'hostapd')
-rw-r--r--hostapd/ap.h2
-rw-r--r--hostapd/config.h2
-rw-r--r--hostapd/eapol_sm.c9
-rw-r--r--hostapd/eapol_sm.h1
-rw-r--r--hostapd/hostapd.c4
-rw-r--r--hostapd/ieee802_11.c24
-rw-r--r--hostapd/ieee802_11.h2
-rw-r--r--hostapd/ieee802_1x.c46
8 files changed, 81 insertions, 9 deletions
diff --git a/hostapd/ap.h b/hostapd/ap.h
index b73c5b4..f32ac55 100644
--- a/hostapd/ap.h
+++ b/hostapd/ap.h
@@ -26,6 +26,8 @@
#define WLAN_STA_SHORT_PREAMBLE BIT(7)
#define WLAN_STA_PREAUTH BIT(8)
#define WLAN_STA_WME BIT(9)
+#define WLAN_STA_WPS BIT(10)
+#define WLAN_STA_MAYBE_WPS BIT(11)
#define WLAN_STA_NONERP BIT(31)
/* Maximum number of supported rates (from both Supported Rates and Extended
diff --git a/hostapd/config.h b/hostapd/config.h
index fd92fc7..668e204 100644
--- a/hostapd/config.h
+++ b/hostapd/config.h
@@ -263,8 +263,8 @@ struct hostapd_bss_config {
macaddr bssid;
-#ifdef CONFIG_WPS
int wps_state;
+#ifdef CONFIG_WPS
u8 uuid[16];
#endif /* CONFIG_WPS */
};
diff --git a/hostapd/eapol_sm.c b/hostapd/eapol_sm.c
index c8ee62c..c489909 100644
--- a/hostapd/eapol_sm.c
+++ b/hostapd/eapol_sm.c
@@ -1,6 +1,6 @@
/*
* hostapd / IEEE 802.1X-2004 Authenticator - EAPOL state machine
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -118,6 +118,13 @@ static void eapol_auth_tx_req(struct eapol_state_machine *sm)
return;
}
+ if (sm->flags & EAPOL_SM_WAIT_START) {
+ wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR
+ " while waiting for EAPOL-Start",
+ MAC2STR(sm->addr));
+ return;
+ }
+
sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData);
eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
"Sending EAP Packet (identifier %d)",
diff --git a/hostapd/eapol_sm.h b/hostapd/eapol_sm.h
index aff32f9..9a561f8 100644
--- a/hostapd/eapol_sm.h
+++ b/hostapd/eapol_sm.h
@@ -201,6 +201,7 @@ struct eapol_state_machine {
/* Other variables - not defined in IEEE 802.1X */
u8 addr[ETH_ALEN]; /* Supplicant address */
#define EAPOL_SM_PREAUTH BIT(0)
+#define EAPOL_SM_WAIT_START BIT(1)
int flags; /* EAPOL_SM_* */
/* EAPOL/AAA <-> EAP full authenticator interface */
diff --git a/hostapd/hostapd.c b/hostapd/hostapd.c
index a8d5487..2351c0a 100644
--- a/hostapd/hostapd.c
+++ b/hostapd/hostapd.c
@@ -397,7 +397,7 @@ 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\n"
+ " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s\n"
" capability=0x%x listen_interval=%d\n",
sta->aid,
sta->flags,
@@ -413,6 +413,8 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
(sta->flags & WLAN_STA_SHORT_PREAMBLE ?
"[SHORT_PREAMBLE]" : ""),
(sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
+ (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
+ (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
sta->capability,
sta->listen_interval);
diff --git a/hostapd/ieee802_11.c b/hostapd/ieee802_11.c
index a41e2b1..1925d23 100644
--- a/hostapd/ieee802_11.c
+++ b/hostapd/ieee802_11.c
@@ -1,6 +1,6 @@
/*
* hostapd / IEEE 802.11 Management
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -209,6 +209,11 @@ static int ieee802_11_parse_vendor_specific(struct hostapd_data *hapd,
return -1;
}
break;
+ case 4:
+ /* Wi-Fi Protected Setup (WPS) IE */
+ elems->wps_ie = pos;
+ elems->wps_ie_len = elen;
+ break;
default:
wpa_printf(MSG_MSGDUMP, "Unknown Microsoft "
"information element ignored "
@@ -945,6 +950,21 @@ static void handle_assoc(struct hostapd_data *hapd,
wpa_ie = NULL;
wpa_ie_len = 0;
}
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && wpa_ie == NULL) {
+ if (elems.wps_ie) {
+ wpa_printf(MSG_DEBUG, "STA included WPS IE in "
+ "(Re)Association Request - assume WPS is "
+ "used");
+ sta->flags |= WLAN_STA_WPS;
+ } else {
+ wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE "
+ "in (Re)Association Request - possible WPS "
+ "use");
+ sta->flags |= WLAN_STA_MAYBE_WPS;
+ }
+ } else
+#endif /* CONFIG_WPS */
if (hapd->conf->wpa && wpa_ie == NULL) {
printf("STA " MACSTR ": No WPA/RSN IE in association "
"request\n", MAC2STR(sta->addr));
@@ -952,7 +972,7 @@ static void handle_assoc(struct hostapd_data *hapd,
goto fail;
}
- if (hapd->conf->wpa) {
+ if (hapd->conf->wpa && wpa_ie) {
int res;
wpa_ie -= 2;
wpa_ie_len += 2;
diff --git a/hostapd/ieee802_11.h b/hostapd/ieee802_11.h
index 9f2a4d8..566a154 100644
--- a/hostapd/ieee802_11.h
+++ b/hostapd/ieee802_11.h
@@ -47,6 +47,8 @@ struct ieee802_11_elems {
u8 wme_len;
u8 *wme_tspec;
u8 wme_tspec_len;
+ u8 *wps_ie;
+ u8 wps_ie_len;
u8 *power_cap;
u8 power_cap_len;
u8 *supp_channels;
diff --git a/hostapd/ieee802_1x.c b/hostapd/ieee802_1x.c
index 7ecf965..2688a92 100644
--- a/hostapd/ieee802_1x.c
+++ b/hostapd/ieee802_1x.c
@@ -1,6 +1,6 @@
/*
* hostapd / IEEE 802.1X-2004 Authenticator
- * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -670,7 +670,8 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
u16 datalen;
struct rsn_pmksa_cache_entry *pmksa;
- if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
+ if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
+ !hapd->conf->wps_state)
return;
wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
@@ -718,7 +719,8 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
return;
}
- if (!hapd->conf->ieee802_1x ||
+ if ((!hapd->conf->ieee802_1x &&
+ !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) ||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK ||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_FT_PSK)
return;
@@ -729,6 +731,18 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
sta);
if (!sta->eapol_sm)
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;
+ }
+#endif /* CONFIG_WPS */
}
/* since we support version 1, we can ignore version field and proceed
@@ -747,6 +761,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start "
"from STA");
+ sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START;
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
if (pmksa) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
@@ -798,8 +813,21 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
{
struct rsn_pmksa_cache_entry *pmksa;
int reassoc = 1;
+ int force_1x = 0;
- if (!hapd->conf->ieee802_1x ||
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state &&
+ (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) {
+ /*
+ * Need to enable IEEE 802.1X/EAPOL state machines for possible
+ * WPS handshake even if IEEE 802.1X/EAPOL is not used for
+ * authentication in this BSS.
+ */
+ force_1x = 1;
+ }
+#endif /* CONFIG_WPS */
+
+ if ((!force_1x && !hapd->conf->ieee802_1x) ||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK ||
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_FT_PSK)
return;
@@ -820,6 +848,16 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
reassoc = 0;
}
+#ifdef CONFIG_WPS
+ if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) {
+ /*
+ * Delay EAPOL frame transmission until a possible WPS
+ * initiates the handshake with EAPOL-Start.
+ */
+ sta->eapol_sm->flags |= EAPOL_SM_WAIT_START;
+ }
+#endif /* CONFIG_WPS */
+
sta->eapol_sm->eap_if->portEnabled = TRUE;
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);