SM_STATE(SUPP_PAE, LOGOFF) { SM_ENTRY(SUPP_PAE, LOGOFF); eapol_sm_txLogoff(sm); sm->logoffSent = TRUE; sm->suppPortStatus = Unauthorized; }
SM_STATE(EAP, RECEIVED2) { SM_ENTRY(EAP, RECEIVED2); /* parse rxResp, respId, respMethod */ eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); }
SM_STATE(EAP, FAILURE2) { SM_ENTRY(EAP, FAILURE2); eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); sm->eap_if.eapFail = TRUE; }
SM_STATE(EAP, NAK) { const struct eap_hdr *nak; size_t len = 0; const u8 *pos; const u8 *nak_list = NULL; SM_ENTRY(EAP, NAK); if (sm->eap_method_priv) { sm->m->reset(sm, sm->eap_method_priv); sm->eap_method_priv = NULL; } sm->m = NULL; nak = wpabuf_head(sm->eap_if.eapRespData); if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) { len = be_to_host16(nak->length); if (len > wpabuf_len(sm->eap_if.eapRespData)) len = wpabuf_len(sm->eap_if.eapRespData); pos = (const u8 *) (nak + 1); len -= sizeof(*nak); if (*pos == EAP_TYPE_NAK) { pos++; len--; nak_list = pos; } } eap_sm_Policy_update(sm, nak_list, len); }
SM_STATE(EAP, INITIALIZE_PASSTHROUGH) { SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH); wpabuf_free(sm->eap_if.aaaEapRespData); sm->eap_if.aaaEapRespData = NULL; }
SM_STATE(EAP, INITIALIZE) { SM_ENTRY(EAP, INITIALIZE); if (sm->fast_reauth && sm->m && sm->m->has_reauth_data && sm->m->has_reauth_data(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for " "fast reauthentication"); sm->m->deinit_for_reauth(sm, sm->eap_method_priv); } else { eap_deinit_prev_method(sm, "INITIALIZE"); } sm->selectedMethod = EAP_TYPE_NONE; sm->methodState = METHOD_NONE; sm->allowNotifications = TRUE; sm->decision = DECISION_FAIL; eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); eapol_set_bool(sm, EAPOL_eapFail, FALSE); free(sm->eapKeyData); sm->eapKeyData = NULL; sm->eapKeyAvailable = FALSE; eapol_set_bool(sm, EAPOL_eapRestart, FALSE); sm->lastId = -1; /* new session - make sure this does not match with * the first EAP-Packet */ /* draft-ietf-eap-statemachine-02.pdf does not reset eapResp and * eapNoResp here. However, this seemed to be able to trigger cases * where both were set and if EAPOL state machine uses eapNoResp first, * it may end up not sending a real reply correctly. This occurred * when the workaround in FAIL state set eapNoResp = TRUE.. Maybe that * workaround needs to be fixed to do something else(?) */ eapol_set_bool(sm, EAPOL_eapResp, FALSE); eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); sm->num_rounds = 0; }
SM_STATE(EAP, PICK_UP_METHOD) { SM_ENTRY(EAP, PICK_UP_METHOD); if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) { sm->currentMethod = sm->respMethod; if (sm->m && sm->eap_method_priv) { sm->m->reset(sm, sm->eap_method_priv); sm->eap_method_priv = NULL; } sm->m = eap_sm_get_eap_methods(sm->currentMethod); if (sm->m && sm->m->initPickUp) { sm->eap_method_priv = sm->m->initPickUp(sm); if (sm->eap_method_priv == NULL) { wpa_printf(MSG_DEBUG, "EAP: Failed to " "initialize EAP method %d", sm->currentMethod); sm->m = NULL; sm->currentMethod = EAP_TYPE_NONE; } } else { sm->m = NULL; sm->currentMethod = EAP_TYPE_NONE; } } }
SM_STATE(EAP, NAK) { struct eap_hdr *nak; size_t len = 0; u8 *pos, *nak_list = NULL; SM_ENTRY(EAP, NAK); if (sm->eap_method_priv) { sm->m->reset(sm, sm->eap_method_priv); sm->eap_method_priv = NULL; } sm->m = NULL; nak = (struct eap_hdr *) sm->eapRespData; if (nak && sm->eapRespDataLen > sizeof(*nak)) { len = ntohs(nak->length); if (len > sm->eapRespDataLen) len = sm->eapRespDataLen; pos = (u8 *) (nak + 1); len -= sizeof(*nak); if (*pos == EAP_TYPE_NAK) { pos++; len--; nak_list = pos; } } eap_sm_Policy_update(sm, nak_list, len); }
SM_STATE(EAP, PICK_UP_METHOD) { SM_ENTRY(EAP, PICK_UP_METHOD); if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) { sm->currentMethod = sm->respMethod; if (sm->m && sm->eap_method_priv) { sm->m->reset(sm, sm->eap_method_priv); sm->eap_method_priv = NULL; } sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF, sm->currentMethod); if (sm->m && sm->m->initPickUp) { sm->eap_method_priv = sm->m->initPickUp(sm); if (sm->eap_method_priv == NULL) { wpa_printf(MSG_DEBUG, "EAP: Failed to " "initialize EAP method %d", sm->currentMethod); sm->m = NULL; sm->currentMethod = EAP_TYPE_NONE; } } else { sm->m = NULL; sm->currentMethod = EAP_TYPE_NONE; } } wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD "method=%u", sm->currentMethod); }
SM_STATE(EAP, IDLE) { SM_ENTRY(EAP, IDLE); #if 0 /* original */ sm->retransWhile = eap_sm_calculateTimeout(sm, sm->retransCount, sm->eapSRTT, sm->eapRTTVAR, sm->methodTimeout); #else /* Per RFC 4137, retransWhile is an external timeout counter * that counts down to zero. * We substitute an eloop timer callback instead; * retransWhile is simply sampled as being nonzero (not timed out) * or zero (timed out). * * Retries are only done if methodTimeout value has been * returned nonzero from the application. */ sm->retransWhile = 1; /* no retransmits will happen while nonzero */ if (sm->methodTimeout > 0) { eloop_cancel_timeout(eap_idle_timeout_handler, sm, NULL); eloop_register_timeout(sm->methodTimeout /*seconds*/, 0, eap_idle_timeout_handler, sm, NULL); } else { eloop_cancel_timeout(eap_idle_timeout_handler, sm, NULL); } #endif }
SM_STATE(EAP, RETRANSMIT) { SM_ENTRY(EAP, RETRANSMIT); #if 0 /* original */ /* TODO: Is this needed since EAPOL state machines take care of * retransmit? */ #else /* Hmmm... EAPOL s.m. isn't retransmitting. Do it here. * Hope this is the right place to do it. * Maybe it really should be done in eapol. */ if (++sm->retransCount > sm->MaxRetrans) { } else if (sm->lastReqData) { eapol_set_eapReqData(sm, sm->lastReqData, sm->lastReqDataLen); eapol_set_bool(sm, EAPOL_eapResp, FALSE); eapol_set_bool(sm, EAPOL_eapReq, TRUE); } else { wpa_printf(MSG_INFO, "EAP: RETRANSMIT - no lastReqData"); eapol_set_bool(sm, EAPOL_eapResp, FALSE); eapol_set_bool(sm, EAPOL_eapReq, FALSE); eapol_set_bool(sm, EAPOL_eapNoReq, TRUE); } #endif }
SM_STATE(SUPP_BE, REQUEST) { SM_ENTRY(SUPP_BE, REQUEST); sm->authWhile = 0; sm->eapReq = TRUE; eapol_sm_getSuppRsp(sm); }
SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) { SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); sm->suppPortStatus = Unauthorized; sm->sPortMode = ForceUnauthorized; eapol_sm_txLogoff(sm); }
SM_STATE(SUPP_PAE, HELD) { SM_ENTRY(SUPP_PAE, HELD); sm->heldWhile = sm->heldPeriod; sm->suppPortStatus = Unauthorized; sm->cb_status = EAPOL_CB_FAILURE; }
SM_STATE(BE_AUTH, IDLE) { SM_ENTRY(BE_AUTH, IDLE, be_auth); sm->authStart = FALSE; sm->be_auth.reqCount = 0; }
SM_STATE(EAP, METHOD_REQUEST) { SM_ENTRY(EAP, METHOD_REQUEST); if (sm->m == NULL) { asd_printf(ASD_DEFAULT,MSG_DEBUG, "EAP: method not initialized"); return; } sm->currentId = eap_sm_nextId(sm, sm->currentId); asd_printf(ASD_DEFAULT,MSG_DEBUG, "EAP: building EAP-Request: Identifier %d", sm->currentId); sm->lastId = sm->currentId; wpabuf_free(sm->eap_if.eapReqData); sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv, sm->currentId); if(!sm->alive_flag){ if(sm->eap_if.eapReqData == NULL) { sm->alive_flag = FALSE; } else{ if(eap_copy_buf(&sm->eap_if.aliveData,sm->eap_if.eapReqData) == 0) sm->alive_flag = TRUE; else sm->alive_flag = FALSE; } } if (sm->m->getTimeout) sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv); else sm->methodTimeout = 0; }
SM_STATE(AUTH_PAE, DISCONNECTED) { int from_initialize = sm->auth_pae.state == AUTH_PAE_INITIALIZE; if (sm->auth_pae.state == AUTH_PAE_CONNECTING && sm->auth_pae.eapLogoff) sm->auth_pae.authEapLogoffsWhileConnecting++; SM_ENTRY(AUTH_PAE, DISCONNECTED, auth_pae); sm->portStatus = Unauthorized; setPortUnauthorized(); sm->auth_pae.eapLogoff = FALSE; sm->auth_pae.reAuthCount = 0; /* IEEE 802.1X state machine uses txCannedFail() always in this state. * However, sending EAP packet with failure code seems to cause WinXP * Supplicant to deauthenticate, which will set portEnabled = FALSE and * state machines end back to INITIALIZE and then back here to send * canned failure, and so on.. Avoid this by not sending failure packet * when DISCONNECTED state is entered from INITIALIZE state. */ if (!from_initialize) { txCannedFail(sm->currentId); sm->currentId++; } }
SM_STATE(EAP, PROPOSE_METHOD) { int vendor; EapType type; SM_ENTRY(EAP, PROPOSE_METHOD); type = eap_sm_Policy_getNextMethod(sm, &vendor); if (vendor == EAP_VENDOR_IETF) sm->currentMethod = type; else sm->currentMethod = EAP_TYPE_EXPANDED; if (sm->m && sm->eap_method_priv) { sm->m->reset(sm, sm->eap_method_priv); sm->eap_method_priv = NULL; } sm->m = eap_server_get_eap_method(vendor, type); if (sm->m) { sm->eap_method_priv = sm->m->init(sm); if (sm->eap_method_priv == NULL) { asd_printf(ASD_DEFAULT,MSG_DEBUG, "EAP: Failed to initialize EAP " "method %d", sm->currentMethod); sm->m = NULL; sm->currentMethod = EAP_TYPE_NONE; } } if (sm->currentMethod == EAP_TYPE_IDENTITY || sm->currentMethod == EAP_TYPE_NOTIFICATION) sm->methodState = METHOD_CONTINUE; else sm->methodState = METHOD_PROPOSED; }
SM_STATE(EAP, INITIALIZE) { SM_ENTRY(EAP, INITIALIZE); sm->currentId = -1; eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); eapol_set_bool(sm, EAPOL_eapFail, FALSE); eapol_set_bool(sm, EAPOL_eapTimeout, FALSE); free(sm->eapKeyData); sm->eapKeyData = NULL; sm->eapKeyDataLen = 0; /* eapKeyAvailable = FALSE */ eapol_set_bool(sm, EAPOL_eapRestart, FALSE); /* This is not defined in draft-ietf-eap-statemachine-05.txt, but * method state needs to be reseted here so that it does not remain in * success state when re-authentication starts. */ if (sm->m && sm->eap_method_priv) { sm->m->reset(sm, sm->eap_method_priv); sm->eap_method_priv = NULL; } sm->m = NULL; sm->user_eap_method_index = 0; if (sm->backend_auth) { sm->currentMethod = EAP_TYPE_NONE; /* parse rxResp, respId, respMethod */ eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen); if (sm->rxResp) { sm->currentId = sm->respId; } } }
SM_STATE(BE_AUTH, INITIALIZE) { SM_ENTRY(BE_AUTH, INITIALIZE, be_auth); abortAuth; sm->authAbort = FALSE; }
SM_STATE(EAP, RETRANSMIT) { SM_ENTRY(EAP, RETRANSMIT); /* TODO: Is this needed since EAPOL state machines take care of * retransmit? */ }
SM_STATE(EAP, IDLE2) { SM_ENTRY(EAP, IDLE2); sm->eap_if.retransWhile = eap_sm_calculateTimeout( sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, sm->methodTimeout); }
SM_STATE(EAP, AAA_RESPONSE) { SM_ENTRY(EAP, AAA_RESPONSE); eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); sm->currentId = eap_sm_getId(sm->eap_if.eapReqData); sm->methodTimeout = sm->eap_if.aaaMethodTimeout; }
SM_STATE(EAP, RECEIVED) { SM_ENTRY(EAP, RECEIVED); /* parse rxResp, respId, respMethod */ eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); sm->num_rounds++; }
SM_STATE(SUPP_BE, RECEIVE) { SM_ENTRY(SUPP_BE, RECEIVE); sm->authWhile = sm->authPeriod; sm->eapolEap = FALSE; sm->eapNoResp = FALSE; sm->initial_req = FALSE; }
SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) { DBGPRINT(RT_DEBUG_INFO,"(AUTH_KEY_TX, KEY_TRANSMIT)\n"); SM_ENTRY(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); txKey(sm->currentId); sm->keyAvailable = FALSE; }
SM_STATE(BE_AUTH, TIMEOUT) { SM_ENTRY(BE_AUTH, TIMEOUT, be_auth); if (sm->portStatus == Unauthorized) txCannedFail(sm->currentId); sm->authTimeout = TRUE; }
SM_STATE(BE_AUTH, FAIL) { SM_ENTRY(BE_AUTH, FAIL, be_auth); sm->currentId = sm->be_auth.idFromServer; txReq(sm->currentId); sm->authFail = TRUE; }
SM_STATE(BE_AUTH, SUCCESS) { SM_ENTRY(BE_AUTH, SUCCESS, be_auth); sm->currentId = sm->be_auth.idFromServer; txReq(sm->currentId); sm->authSuccess = TRUE; }
SM_STATE(EAP, INTEGRITY_CHECK) { SM_ENTRY(EAP, INTEGRITY_CHECK); if (sm->m->check) { sm->ignore = sm->m->check(sm, sm->eap_method_priv, sm->eap_if.eapRespData); } }