#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,
}
-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);
}
#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;
* 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;
}
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
* 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);
}
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);
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)
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;
+ }
}
}
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);
}
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);
}
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)
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);
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 */