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 */