summaryrefslogtreecommitdiffstats
path: root/contrib/hostapd/eapol_sm.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-03-07 05:51:52 +0000
committersam <sam@FreeBSD.org>2006-03-07 05:51:52 +0000
commit7ec4eb033d83d1150a5d461349c32d7113770a57 (patch)
tree4c08a6b60d0fad8945a0348eb843f0d8b2bd8d9d /contrib/hostapd/eapol_sm.c
parent8410a7ea6cb51f8974a9d5506dacff8d565158f5 (diff)
downloadFreeBSD-src-7ec4eb033d83d1150a5d461349c32d7113770a57.zip
FreeBSD-src-7ec4eb033d83d1150a5d461349c32d7113770a57.tar.gz
resolve merge conflicts
MFC after: 2 weeks
Diffstat (limited to 'contrib/hostapd/eapol_sm.c')
-rw-r--r--contrib/hostapd/eapol_sm.c160
1 files changed, 114 insertions, 46 deletions
diff --git a/contrib/hostapd/eapol_sm.c b/contrib/hostapd/eapol_sm.c
index 50c645a..4ded7e7 100644
--- a/contrib/hostapd/eapol_sm.c
+++ b/contrib/hostapd/eapol_sm.c
@@ -68,6 +68,9 @@ static void sm_ ## machine ## _Step(struct eapol_state_machine *sm)
#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
+static void eapol_sm_step_run(struct eapol_state_machine *sm);
+static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
+
/* Port Timers state machine - implemented as a function that will be called
* once a second as a registered event loop timeout */
@@ -76,19 +79,34 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
{
struct eapol_state_machine *state = timeout_ctx;
- if (state->aWhile > 0)
+ if (state->aWhile > 0) {
state->aWhile--;
- if (state->quietWhile > 0)
+ if (state->aWhile == 0) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
+ " - aWhile --> 0",
+ MAC2STR(state->addr));
+ }
+ }
+
+ if (state->quietWhile > 0) {
state->quietWhile--;
- if (state->reAuthWhen > 0)
- state->reAuthWhen--;
+ if (state->quietWhile == 0) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
+ " - quietWhile --> 0",
+ MAC2STR(state->addr));
+ }
+ }
- if (state->hapd->conf->debug >= HOSTAPD_DEBUG_MSGDUMPS)
- printf("IEEE 802.1X: " MACSTR " Port Timers TICK "
- "(timers: %d %d %d)\n", MAC2STR(state->addr),
- state->aWhile, state->quietWhile, state->reAuthWhen);
+ if (state->reAuthWhen > 0) {
+ state->reAuthWhen--;
+ if (state->reAuthWhen == 0) {
+ wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
+ " - reAuthWhen --> 0",
+ MAC2STR(state->addr));
+ }
+ }
- eapol_sm_step(state);
+ eapol_sm_step_run(state);
eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
}
@@ -359,6 +377,19 @@ SM_STATE(BE_AUTH, REQUEST)
txReq();
sm->be_auth.eapReq = FALSE;
sm->be_auth.backendOtherRequestsToSupplicant++;
+
+ /*
+ * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
+ * it looks like this would be logical thing to do there since the old
+ * EAP response would not be valid anymore after the new EAP request
+ * was sent out.
+ *
+ * A race condition has been reported, in which hostapd ended up
+ * sending out EAP-Response/Identity as a response to the first
+ * EAP-Request from the main EAP method. This can be avoided by
+ * clearing eapolEap here.
+ */
+ sm->eapolEap = FALSE;
}
@@ -705,7 +736,7 @@ eapol_sm_alloc(hostapd *hapd, struct sta_info *sta)
else
sm->portValid = TRUE;
- if (hapd->conf->eap_authenticator) {
+ if (hapd->conf->eap_server) {
struct eap_config eap_conf;
memset(&eap_conf, 0, sizeof(eap_conf));
eap_conf.ssl_ctx = hapd->ssl_ctx;
@@ -729,6 +760,7 @@ void eapol_sm_free(struct eapol_state_machine *sm)
return;
eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm);
+ eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
if (sm->eap)
eap_sm_deinit(sm->eap);
free(sm);
@@ -745,55 +777,63 @@ static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr)
}
-void eapol_sm_step(struct eapol_state_machine *sm)
+static void eapol_sm_step_run(struct eapol_state_machine *sm)
{
struct hostapd_data *hapd = sm->hapd;
u8 addr[ETH_ALEN];
int prev_auth_pae, prev_be_auth, prev_reauth_timer, prev_auth_key_tx,
prev_key_rx, prev_ctrl_dir;
-
- /* FIX: could re-run eapol_sm_step from registered timeout (after
- * 0 sec) to make sure that other possible timeouts/events are
- * processed */
+ int max_steps = 100;
memcpy(addr, sm->sta->addr, ETH_ALEN);
+
+ /*
+ * Allow EAPOL state machines to run as long as there are state
+ * changes, but exit and return here through event loop if more than
+ * 100 steps is needed as a precaution against infinite loops inside
+ * eloop callback.
+ */
restart:
- do {
- prev_auth_pae = sm->auth_pae.state;
- prev_be_auth = sm->be_auth.state;
- prev_reauth_timer = sm->reauth_timer.state;
- prev_auth_key_tx = sm->auth_key_tx.state;
- prev_key_rx = sm->key_rx.state;
- prev_ctrl_dir = sm->ctrl_dir.state;
-
- SM_STEP_RUN(AUTH_PAE);
- if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
- break;
+ prev_auth_pae = sm->auth_pae.state;
+ prev_be_auth = sm->be_auth.state;
+ prev_reauth_timer = sm->reauth_timer.state;
+ prev_auth_key_tx = sm->auth_key_tx.state;
+ prev_key_rx = sm->key_rx.state;
+ prev_ctrl_dir = sm->ctrl_dir.state;
+
+ SM_STEP_RUN(AUTH_PAE);
+ if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
SM_STEP_RUN(BE_AUTH);
- if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
- break;
+ if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
SM_STEP_RUN(REAUTH_TIMER);
- if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
- break;
+ if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
SM_STEP_RUN(AUTH_KEY_TX);
- if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
- break;
+ if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
SM_STEP_RUN(KEY_RX);
- if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
- break;
+ if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr))
SM_STEP_RUN(CTRL_DIR);
- if (!sm->initializing && !eapol_sm_sta_entry_alive(hapd, addr))
- break;
- } while (prev_auth_pae != sm->auth_pae.state ||
- prev_be_auth != sm->be_auth.state ||
- prev_reauth_timer != sm->reauth_timer.state ||
- prev_auth_key_tx != sm->auth_key_tx.state ||
- prev_key_rx != sm->key_rx.state ||
- prev_ctrl_dir != sm->ctrl_dir.state);
- if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) {
- if (eap_sm_step(sm->eap))
+ if (prev_auth_pae != sm->auth_pae.state ||
+ prev_be_auth != sm->be_auth.state ||
+ prev_reauth_timer != sm->reauth_timer.state ||
+ prev_auth_key_tx != sm->auth_key_tx.state ||
+ prev_key_rx != sm->key_rx.state ||
+ prev_ctrl_dir != sm->ctrl_dir.state) {
+ if (--max_steps > 0)
goto restart;
+ /* Re-run from eloop timeout */
+ eapol_sm_step(sm);
+ return;
+ }
+
+ if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) {
+ if (eap_sm_step(sm->eap)) {
+ if (--max_steps > 0)
+ goto restart;
+ /* Re-run from eloop timeout */
+ eapol_sm_step(sm);
+ return;
+ }
}
if (eapol_sm_sta_entry_alive(hapd, addr))
@@ -801,15 +841,34 @@ restart:
}
+static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
+{
+ struct eapol_state_machine *sm = eloop_ctx;
+ eapol_sm_step_run(sm);
+}
+
+
+void eapol_sm_step(struct eapol_state_machine *sm)
+{
+ /*
+ * Run eapol_sm_step_run from a registered timeout to make sure that
+ * other possible timeouts/events are processed and to avoid long
+ * function call chains.
+ */
+
+ eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
+}
+
+
void eapol_sm_initialize(struct eapol_state_machine *sm)
{
sm->initializing = TRUE;
/* Initialize the state machines by asserting initialize and then
* deasserting it after one step */
sm->initialize = TRUE;
- eapol_sm_step(sm);
+ eapol_sm_step_run(sm);
sm->initialize = FALSE;
- eapol_sm_step(sm);
+ eapol_sm_step_run(sm);
sm->initializing = FALSE;
/* Start one second tick for port timers state machine */
@@ -1183,6 +1242,14 @@ static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
}
+static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
+{
+ struct eapol_state_machine *sm = ctx;
+ *len = sm->hapd->conf->eap_req_id_text_len;
+ return sm->hapd->conf->eap_req_id_text;
+}
+
+
static struct eapol_callbacks eapol_cb =
{
.get_bool = eapol_sm_get_bool,
@@ -1190,4 +1257,5 @@ static struct eapol_callbacks eapol_cb =
.set_eapReqData = eapol_sm_set_eapReqData,
.set_eapKeyData = eapol_sm_set_eapKeyData,
.get_eap_user = eapol_sm_get_eap_user,
+ .get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
};
OpenPOWER on IntegriCloud