📄 eapol_sm.c
字号:
sm->eap_if->eapNoReq = FALSE; sm->authAbort = FALSE;}SM_STATE(BE_AUTH, REQUEST){ SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); txReq(); sm->eap_if->eapReq = FALSE; sm->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;}SM_STATE(BE_AUTH, RESPONSE){ SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); sm->authTimeout = FALSE; sm->eapolEap = FALSE; sm->eap_if->eapNoReq = FALSE; sm->aWhile = sm->serverTimeout; sm->eap_if->eapResp = TRUE; /* sendRespToServer(); */ sm->backendResponses++;}SM_STATE(BE_AUTH, SUCCESS){ SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); txReq(); sm->authSuccess = TRUE; sm->keyRun = TRUE;}SM_STATE(BE_AUTH, FAIL){ SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); txReq(); sm->authFail = TRUE;}SM_STATE(BE_AUTH, TIMEOUT){ SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); sm->authTimeout = TRUE;}SM_STATE(BE_AUTH, IDLE){ SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); sm->authStart = FALSE;}SM_STATE(BE_AUTH, IGNORE){ SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); sm->eap_if->eapNoReq = FALSE;}SM_STEP(BE_AUTH){ if (sm->portControl != Auto || sm->initialize || sm->authAbort) { SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE); return; } switch (sm->be_auth_state) { case BE_AUTH_INITIALIZE: SM_ENTER(BE_AUTH, IDLE); break; case BE_AUTH_REQUEST: if (sm->eapolEap) SM_ENTER(BE_AUTH, RESPONSE); else if (sm->eap_if->eapReq) SM_ENTER(BE_AUTH, REQUEST); else if (sm->eap_if->eapTimeout) SM_ENTER(BE_AUTH, TIMEOUT); break; case BE_AUTH_RESPONSE: if (sm->eap_if->eapNoReq) SM_ENTER(BE_AUTH, IGNORE); if (sm->eap_if->eapReq) { sm->backendAccessChallenges++; SM_ENTER(BE_AUTH, REQUEST); } else if (sm->aWhile == 0) SM_ENTER(BE_AUTH, TIMEOUT); else if (sm->eap_if->eapFail) { sm->backendAuthFails++; SM_ENTER(BE_AUTH, FAIL); } else if (sm->eap_if->eapSuccess) { sm->backendAuthSuccesses++; SM_ENTER(BE_AUTH, SUCCESS); } break; case BE_AUTH_SUCCESS: SM_ENTER(BE_AUTH, IDLE); break; case BE_AUTH_FAIL: SM_ENTER(BE_AUTH, IDLE); break; case BE_AUTH_TIMEOUT: SM_ENTER(BE_AUTH, IDLE); break; case BE_AUTH_IDLE: if (sm->eap_if->eapFail && sm->authStart) SM_ENTER(BE_AUTH, FAIL); else if (sm->eap_if->eapReq && sm->authStart) SM_ENTER(BE_AUTH, REQUEST); else if (sm->eap_if->eapSuccess && sm->authStart) SM_ENTER(BE_AUTH, SUCCESS); break; case BE_AUTH_IGNORE: if (sm->eapolEap) SM_ENTER(BE_AUTH, RESPONSE); else if (sm->eap_if->eapReq) SM_ENTER(BE_AUTH, REQUEST); else if (sm->eap_if->eapTimeout) SM_ENTER(BE_AUTH, TIMEOUT); break; }}/* Reauthentication Timer state machine */SM_STATE(REAUTH_TIMER, INITIALIZE){ SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer); sm->reAuthWhen = sm->reAuthPeriod;}SM_STATE(REAUTH_TIMER, REAUTHENTICATE){ SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); sm->reAuthenticate = TRUE; wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL);}SM_STEP(REAUTH_TIMER){ if (sm->portControl != Auto || sm->initialize || sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE); return; } switch (sm->reauth_timer_state) { case REAUTH_TIMER_INITIALIZE: if (sm->reAuthWhen == 0) SM_ENTER(REAUTH_TIMER, REAUTHENTICATE); break; case REAUTH_TIMER_REAUTHENTICATE: SM_ENTER(REAUTH_TIMER, INITIALIZE); break; }}/* Authenticator Key Transmit state machine */SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT){ SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);}SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT){ SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); txKey(); sm->eap_if->eapKeyAvailable = FALSE; sm->keyDone = TRUE;}SM_STEP(AUTH_KEY_TX){ if (sm->initialize || sm->portControl != Auto) { SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT); return; } switch (sm->auth_key_tx_state) { case AUTH_KEY_TX_NO_KEY_TRANSMIT: if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable && sm->keyRun && !wpa_auth_sta_wpa_version(sm->sta->wpa_sm)) SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); break; case AUTH_KEY_TX_KEY_TRANSMIT: if (!sm->keyTxEnabled || !sm->keyRun) SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); else if (sm->eap_if->eapKeyAvailable) SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); break; }}/* Key Receive state machine */SM_STATE(KEY_RX, NO_KEY_RECEIVE){ SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);}SM_STATE(KEY_RX, KEY_RECEIVE){ SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); processKey(); sm->rxKey = FALSE;}SM_STEP(KEY_RX){ if (sm->initialize || !sm->eap_if->portEnabled) { SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); return; } switch (sm->key_rx_state) { case KEY_RX_NO_KEY_RECEIVE: if (sm->rxKey) SM_ENTER(KEY_RX, KEY_RECEIVE); break; case KEY_RX_KEY_RECEIVE: if (sm->rxKey) SM_ENTER(KEY_RX, KEY_RECEIVE); break; }}/* Controlled Directions state machine */SM_STATE(CTRL_DIR, FORCE_BOTH){ SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir); sm->operControlledDirections = Both;}SM_STATE(CTRL_DIR, IN_OR_BOTH){ SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir); sm->operControlledDirections = sm->adminControlledDirections;}SM_STEP(CTRL_DIR){ if (sm->initialize) { SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH); return; } switch (sm->ctrl_dir_state) { case CTRL_DIR_FORCE_BOTH: if (sm->eap_if->portEnabled && sm->operEdge) SM_ENTER(CTRL_DIR, IN_OR_BOTH); break; case CTRL_DIR_IN_OR_BOTH: if (sm->operControlledDirections != sm->adminControlledDirections) SM_ENTER(CTRL_DIR, IN_OR_BOTH); if (!sm->eap_if->portEnabled || !sm->operEdge) SM_ENTER(CTRL_DIR, FORCE_BOTH); break; }}struct eapol_state_machine *eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, int preauth, struct sta_info *sta){ struct eapol_state_machine *sm; struct hostapd_data *hapd; /* TODO: to be removed */ struct eap_config eap_conf; if (eapol == NULL) return NULL; hapd = eapol->conf.hapd; sm = os_zalloc(sizeof(*sm)); if (sm == NULL) { wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation " "failed"); return NULL; } sm->radius_identifier = -1; os_memcpy(sm->addr, addr, ETH_ALEN); if (preauth) sm->flags |= EAPOL_SM_PREAUTH; sm->hapd = hapd; sm->eapol = eapol; sm->sta = sta; /* Set default values for state machine constants */ sm->auth_pae_state = AUTH_PAE_INITIALIZE; sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod; sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax; sm->be_auth_state = BE_AUTH_INITIALIZE; sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout; sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; sm->reAuthPeriod = eapol->conf.eap_reauth_period; sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE; sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH; sm->portControl = Auto; if (!eapol->conf.wpa && (hapd->default_wep_key || eapol->conf.individual_wep_key_len > 0)) sm->keyTxEnabled = TRUE; else sm->keyTxEnabled = FALSE; if (eapol->conf.wpa) sm->portValid = FALSE; else sm->portValid = TRUE; os_memset(&eap_conf, 0, sizeof(eap_conf)); eap_conf.eap_server = eapol->conf.eap_server; eap_conf.ssl_ctx = eapol->conf.ssl_ctx; eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv; eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key; eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id; eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len; eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info; eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov; eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime; eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time; eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind; eap_conf.tnc = eapol->conf.tnc; eap_conf.wps = eapol->conf.wps; eap_conf.assoc_wps_ie = sta->wps_ie; sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf); if (sm->eap == NULL) { eapol_auth_free(sm); return NULL; } sm->eap_if = eap_get_interface(sm->eap); eapol_auth_initialize(sm); return sm;}void eapol_auth_free(struct eapol_state_machine *sm){ if (sm == NULL) return; eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); if (sm->eap) eap_server_sm_deinit(sm->eap); os_free(sm);}static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol, const u8 *addr){ return eapol->cb.sta_entry_alive(eapol->conf.hapd, addr);}static void eapol_sm_step_run(struct eapol_state_machine *sm){ struct eapol_authenticator *eapol = sm->eapol; u8 addr[ETH_ALEN]; unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; int max_steps = 100; os_memcpy(addr, sm->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: 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(eapol, addr)) SM_STEP_RUN(BE_AUTH); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(REAUTH_TIMER); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(AUTH_KEY_TX); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(KEY_RX);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -