summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJouni Malinen <quic_jouni@quicinc.com>2023-05-04 10:18:34 +0300
committerJouni Malinen <j@w1.fi>2023-05-04 11:10:16 +0300
commit386d59e00d6da29f95dd2253cb9b44ff4e8ae7f1 (patch)
tree5304889d4818004f0a86ca4698df6d28726f3c71
parent73372322038d2617f2be4542c0f2a5fa846fe911 (diff)
downloadhostap-386d59e00d6da29f95dd2253cb9b44ff4e8ae7f1.tar.gz
Do not disconnect EAPOL-Logoff before authentication
Some station devices are apparently sending the EAPOL-Logoff message in some cases before the initial authentication for WPA2/WPA3-Enterprise. hostapd would have forced a "post EAP-Failure" disconnection in 10 ms for such cases while still allowing the EAP authentication to try to complete. This is not ideal and could result in interoperability issues, so skip the forced disconnection in the particular case where the EAPOL-Logoff message is received before the first authentication is completed. In addition, disconnect the STA without starting new EAP authentication and the 10 ms delay if an EAPOL-Logoff message is received after authentication has been completed successfully. This results in cleaner behavior by avoiding the extra start of a new EAP authentication in a case where the STA is going to be disconnected shortly. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
-rw-r--r--src/ap/ieee802_1x.c27
-rw-r--r--src/ap/sta_info.c9
-rw-r--r--src/ap/sta_info.h3
-rw-r--r--src/eapol_auth/eapol_auth_sm.c26
-rw-r--r--src/eapol_auth/eapol_auth_sm.h4
-rw-r--r--src/eapol_auth/eapol_auth_sm_i.h4
6 files changed, 49 insertions, 24 deletions
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 46a47d06e..8b67669bb 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -43,9 +43,9 @@
#ifdef CONFIG_HS20
static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx);
#endif /* CONFIG_HS20 */
-static void ieee802_1x_finished(struct hostapd_data *hapd,
+static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
- int remediation);
+ int remediation, bool logoff);
static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
@@ -2287,16 +2287,18 @@ static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx,
}
-static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
- int preauth, int remediation)
+static bool _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
+ int preauth, int remediation, bool logoff)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta = sta_ctx;
- if (preauth)
+ if (preauth) {
rsn_preauth_finished(hapd, sta, success);
- else
- ieee802_1x_finished(hapd, sta, success, remediation);
+ return false;
+ }
+
+ return ieee802_1x_finished(hapd, sta, success, remediation, logoff);
}
@@ -2977,9 +2979,9 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
#endif /* CONFIG_HS20 */
-static void ieee802_1x_finished(struct hostapd_data *hapd,
+static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
- int remediation)
+ int remediation, bool logoff)
{
const u8 *key;
size_t len;
@@ -3039,6 +3041,11 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
* EAP-FAST with anonymous provisioning, may require another
* EAPOL authentication to be started to complete connection.
*/
- ap_sta_delayed_1x_auth_fail_disconnect(hapd, sta);
+ ap_sta_delayed_1x_auth_fail_disconnect(hapd, sta,
+ logoff ? 0 : 10);
+ if (logoff && sta->wpa_sm)
+ return true;
}
+
+ return false;
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 63f514c9e..0897bcda4 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -1536,11 +1536,12 @@ static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
- struct sta_info *sta)
+ struct sta_info *sta,
+ unsigned timeout)
{
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"IEEE 802.1X: Force disconnection of " MACSTR
- " after EAP-Failure in 10 ms", MAC2STR(sta->addr));
+ " after EAP-Failure in %u ms", MAC2STR(sta->addr), timeout);
/*
* Add a small sleep to increase likelihood of previously requested
@@ -1548,8 +1549,8 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
* operations.
*/
eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
- eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
- hapd, sta);
+ eloop_register_timeout(0, timeout * 1000,
+ ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index b59b7584b..8433ff8d6 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -373,7 +373,8 @@ void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
- struct sta_info *sta);
+ struct sta_info *sta,
+ unsigned timeout);
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta);
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c
index 1c11cb613..e1b82ebe3 100644
--- a/src/eapol_auth/eapol_auth_sm.c
+++ b/src/eapol_auth/eapol_auth_sm.c
@@ -217,6 +217,9 @@ SM_STATE(AUTH_PAE, INITIALIZE)
SM_STATE(AUTH_PAE, DISCONNECTED)
{
int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
+ bool pre_auth_logoff = sm->auth_pae_state == AUTH_PAE_ABORTING &&
+ sm->eapolLogoff && !sm->authenticated;
+ bool logoff = sm->eapolLogoff;
if (sm->eapolLogoff) {
if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
@@ -231,10 +234,14 @@ SM_STATE(AUTH_PAE, DISCONNECTED)
setPortUnauthorized();
sm->reAuthCount = 0;
sm->eapolLogoff = false;
- if (!from_initialize) {
- sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
- sm->flags & EAPOL_SM_PREAUTH,
- sm->remediation);
+ if (!from_initialize && !pre_auth_logoff) {
+ if (sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
+ sm->flags & EAPOL_SM_PREAUTH,
+ sm->remediation, logoff)) {
+ wpa_printf(MSG_DEBUG,
+ "EAPOL: Do not restart since lower layers will disconnect the port after EAPOL-Logoff");
+ sm->stopped = true;
+ }
}
}
@@ -291,7 +298,8 @@ SM_STATE(AUTH_PAE, HELD)
eap_server_get_name(0, sm->eap_type_supp));
}
sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
- sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
+ sm->flags & EAPOL_SM_PREAUTH, sm->remediation,
+ false);
}
@@ -316,8 +324,11 @@ SM_STATE(AUTH_PAE, AUTHENTICATED)
sm->eap_type_authsrv,
eap_server_get_name(0, sm->eap_type_authsrv),
extra);
+ if (sm->authSuccess)
+ sm->authenticated++;
sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
- sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
+ sm->flags & EAPOL_SM_PREAUTH, sm->remediation,
+ false);
}
@@ -397,7 +408,8 @@ SM_STEP(AUTH_PAE)
SM_ENTER(AUTH_PAE, DISCONNECTED);
break;
case AUTH_PAE_DISCONNECTED:
- SM_ENTER(AUTH_PAE, RESTART);
+ if (!sm->stopped)
+ SM_ENTER(AUTH_PAE, RESTART);
break;
case AUTH_PAE_RESTART:
if (!sm->eap_if->eapRestart)
diff --git a/src/eapol_auth/eapol_auth_sm.h b/src/eapol_auth/eapol_auth_sm.h
index 61b7039d6..7296a3aca 100644
--- a/src/eapol_auth/eapol_auth_sm.h
+++ b/src/eapol_auth/eapol_auth_sm.h
@@ -46,8 +46,8 @@ struct eapol_auth_cb {
size_t datalen);
void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data,
size_t datalen);
- void (*finished)(void *ctx, void *sta_ctx, int success, int preauth,
- int remediation);
+ bool (*finished)(void *ctx, void *sta_ctx, int success, int preauth,
+ int remediation, bool logoff);
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
int phase2, struct eap_user *user);
int (*sta_entry_alive)(void *ctx, const u8 *addr);
diff --git a/src/eapol_auth/eapol_auth_sm_i.h b/src/eapol_auth/eapol_auth_sm_i.h
index 3c6898310..a0cef0f8e 100644
--- a/src/eapol_auth/eapol_auth_sm_i.h
+++ b/src/eapol_auth/eapol_auth_sm_i.h
@@ -171,6 +171,10 @@ struct eapol_state_machine {
int remediation;
u64 acct_multi_session_id;
+
+ unsigned int authenticated; /* The number of times authentication has
+ * been completed successfully. */
+ bool stopped;
};
#endif /* EAPOL_AUTH_SM_I_H */