⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eapol_sm.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * hostapd / IEEE 802.1X Authenticator - EAPOL state machine * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "hostapd.h"#include "ieee802_1x.h"#include "eapol_sm.h"#include "eloop.h"#include "wpa.h"#include "preauth.h"#include "sta_info.h"#include "eap.h"#include "state_machine.h"#define STATE_MACHINE_DATA struct eapol_state_machine#define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"#define STATE_MACHINE_ADDR sm->addrstatic struct eapol_callbacks eapol_cb;/* EAPOL state machines are described in IEEE Std 802.1X-REV-d11, Chap. 8.2 */#define setPortAuthorized() \ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 1)#define setPortUnauthorized() \ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 0)/* procedures */#define txCannedFail() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 0)#define txCannedSuccess() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 1)#define txReq() ieee802_1x_tx_req(sm->hapd, sm->sta)#define sendRespToServer() ieee802_1x_send_resp_to_server(sm->hapd, sm->sta)#define abortAuth() ieee802_1x_abort_auth(sm->hapd, sm->sta)#define txKey() ieee802_1x_tx_key(sm->hapd, sm->sta)#define processKey() do { } while (0)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 */static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx){	struct eapol_state_machine *state = timeout_ctx;	if (state->aWhile > 0) {		state->aWhile--;		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->quietWhile == 0) {			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR				   " - quietWhile --> 0",				   MAC2STR(state->addr));		}	}	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_run(state);	eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);}/* Authenticator PAE state machine */SM_STATE(AUTH_PAE, INITIALIZE){	SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);	sm->portMode = Auto;	sm->currentId = 255;}SM_STATE(AUTH_PAE, DISCONNECTED){	int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;	if (sm->eapolLogoff) {		if (sm->auth_pae_state == AUTH_PAE_CONNECTING)			sm->authEapLogoffsWhileConnecting++;		else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)			sm->authAuthEapLogoffWhileAuthenticated++;	}	SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);	sm->authPortStatus = Unauthorized;	setPortUnauthorized();	sm->reAuthCount = 0;	sm->eapolLogoff = FALSE;	if (!from_initialize) {		if (sm->flags & EAPOL_SM_PREAUTH)			rsn_preauth_finished(sm->hapd, sm->sta, 0);		else			ieee802_1x_finished(sm->hapd, sm->sta, 0);	}}SM_STATE(AUTH_PAE, RESTART){	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {		if (sm->reAuthenticate)			sm->authAuthReauthsWhileAuthenticated++;		if (sm->eapolStart)			sm->authAuthEapStartsWhileAuthenticated++;		if (sm->eapolLogoff)			sm->authAuthEapLogoffWhileAuthenticated++;	}	SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);	sm->eapRestart = TRUE;	ieee802_1x_request_identity(sm->hapd, sm->sta);}SM_STATE(AUTH_PAE, CONNECTING){	if (sm->auth_pae_state != AUTH_PAE_CONNECTING)		sm->authEntersConnecting++;	SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);	sm->reAuthenticate = FALSE;	sm->reAuthCount++;}SM_STATE(AUTH_PAE, HELD){	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)		sm->authAuthFailWhileAuthenticating++;	SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);	sm->authPortStatus = Unauthorized;	setPortUnauthorized();	sm->quietWhile = sm->quietPeriod;	sm->eapolLogoff = FALSE;	hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,		       HOSTAPD_LEVEL_WARNING, "authentication failed");	if (sm->flags & EAPOL_SM_PREAUTH)		rsn_preauth_finished(sm->hapd, sm->sta, 0);	else		ieee802_1x_finished(sm->hapd, sm->sta, 0);}SM_STATE(AUTH_PAE, AUTHENTICATED){	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)		sm->authAuthSuccessesWhileAuthenticating++;								SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);	sm->authPortStatus = Authorized;	setPortAuthorized();	sm->reAuthCount = 0;	hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,		       HOSTAPD_LEVEL_INFO, "authenticated");	if (sm->flags & EAPOL_SM_PREAUTH)		rsn_preauth_finished(sm->hapd, sm->sta, 1);	else		ieee802_1x_finished(sm->hapd, sm->sta, 1);}SM_STATE(AUTH_PAE, AUTHENTICATING){	if (sm->auth_pae_state == AUTH_PAE_CONNECTING && sm->rx_identity) {		sm->authEntersAuthenticating++;		sm->rx_identity = FALSE;	}	SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);	sm->eapolStart = FALSE;	sm->authSuccess = FALSE;	sm->authFail = FALSE;	sm->authTimeout = FALSE;	sm->authStart = TRUE;	sm->keyRun = FALSE;	sm->keyDone = FALSE;}SM_STATE(AUTH_PAE, ABORTING){	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {		if (sm->authTimeout)			sm->authAuthTimeoutsWhileAuthenticating++;		if (sm->eapolStart)			sm->authAuthEapStartsWhileAuthenticating++;		if (sm->eapolLogoff)			sm->authAuthEapLogoffWhileAuthenticating++;	}	SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);	sm->authAbort = TRUE;	sm->keyRun = FALSE;	sm->keyDone = FALSE;}SM_STATE(AUTH_PAE, FORCE_AUTH){	SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);	sm->authPortStatus = Authorized;	setPortAuthorized();	sm->portMode = ForceAuthorized;	sm->eapolStart = FALSE;	txCannedSuccess();}SM_STATE(AUTH_PAE, FORCE_UNAUTH){	SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);	sm->authPortStatus = Unauthorized;	setPortUnauthorized();	sm->portMode = ForceUnauthorized;	sm->eapolStart = FALSE;	txCannedFail();}SM_STEP(AUTH_PAE){	if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||	    sm->initialize || !sm->portEnabled)		SM_ENTER(AUTH_PAE, INITIALIZE);	else if (sm->portControl == ForceAuthorized &&		 sm->portMode != sm->portControl &&		 !(sm->initialize || !sm->portEnabled))		SM_ENTER(AUTH_PAE, FORCE_AUTH);	else if (sm->portControl == ForceUnauthorized &&		 sm->portMode != sm->portControl &&		 !(sm->initialize || !sm->portEnabled))		SM_ENTER(AUTH_PAE, FORCE_UNAUTH);	else {		switch (sm->auth_pae_state) {		case AUTH_PAE_INITIALIZE:			SM_ENTER(AUTH_PAE, DISCONNECTED);			break;		case AUTH_PAE_DISCONNECTED:			SM_ENTER(AUTH_PAE, RESTART);			break;		case AUTH_PAE_RESTART:			if (!sm->eapRestart)				SM_ENTER(AUTH_PAE, CONNECTING);			break;		case AUTH_PAE_HELD:			if (sm->quietWhile == 0)				SM_ENTER(AUTH_PAE, RESTART);			break;		case AUTH_PAE_CONNECTING:			if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)				SM_ENTER(AUTH_PAE, DISCONNECTED);			else if ((sm->eapReq &&				  sm->reAuthCount <= sm->reAuthMax) ||				 sm->eapSuccess || sm->eapFail)				SM_ENTER(AUTH_PAE, AUTHENTICATING);			break;		case AUTH_PAE_AUTHENTICATED:			if (sm->eapolStart || sm->reAuthenticate)				SM_ENTER(AUTH_PAE, RESTART);			else if (sm->eapolLogoff || !sm->portValid)				SM_ENTER(AUTH_PAE, DISCONNECTED);			break;		case AUTH_PAE_AUTHENTICATING:			if (sm->authSuccess && sm->portValid)				SM_ENTER(AUTH_PAE, AUTHENTICATED);			else if (sm->authFail ||				 (sm->keyDone && !sm->portValid))				SM_ENTER(AUTH_PAE, HELD);			else if (sm->eapolStart || sm->eapolLogoff ||				 sm->authTimeout)				SM_ENTER(AUTH_PAE, ABORTING);			break;		case AUTH_PAE_ABORTING:			if (sm->eapolLogoff && !sm->authAbort)				SM_ENTER(AUTH_PAE, DISCONNECTED);			else if (!sm->eapolLogoff && !sm->authAbort)				SM_ENTER(AUTH_PAE, RESTART);			break;		case AUTH_PAE_FORCE_AUTH:			if (sm->eapolStart)				SM_ENTER(AUTH_PAE, FORCE_AUTH);			break;		case AUTH_PAE_FORCE_UNAUTH:			if (sm->eapolStart)				SM_ENTER(AUTH_PAE, FORCE_UNAUTH);			break;		}	}}/* Backend Authentication state machine */SM_STATE(BE_AUTH, INITIALIZE){	SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);	abortAuth();	sm->eapNoReq = FALSE;	sm->authAbort = FALSE;}SM_STATE(BE_AUTH, REQUEST){	SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);	txReq();	sm->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->eapNoReq = FALSE;	sm->aWhile = sm->serverTimeout;	sm->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);	/* Note: IEEE 802.1X-REV-d11 has unconditional txReq() here.	 * txCannelFail() is used as a workaround for the case where	 * authentication server does not include EAP-Message with	 * Access-Reject. */	if (sm->last_eap_radius == NULL)		txCannedFail();	else		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->eapNoReq = FALSE;}SM_STEP(BE_AUTH){	if (sm->portControl != Auto || sm->initialize || sm->authAbort) {		SM_ENTER(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->eapReq)			SM_ENTER(BE_AUTH, REQUEST);		else if (sm->eapTimeout)			SM_ENTER(BE_AUTH, TIMEOUT);		break;	case BE_AUTH_RESPONSE:		if (sm->eapNoReq)			SM_ENTER(BE_AUTH, IGNORE);		if (sm->eapReq) {			sm->backendAccessChallenges++;			SM_ENTER(BE_AUTH, REQUEST);		} else if (sm->aWhile == 0)			SM_ENTER(BE_AUTH, TIMEOUT);		else if (sm->eapFail) {			sm->backendAuthFails++;			SM_ENTER(BE_AUTH, FAIL);		} else if (sm->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->eapFail && sm->authStart)			SM_ENTER(BE_AUTH, FAIL);		else if (sm->eapReq && sm->authStart)			SM_ENTER(BE_AUTH, REQUEST);		else if (sm->eapSuccess && sm->authStart)			SM_ENTER(BE_AUTH, SUCCESS);		break;	case BE_AUTH_IGNORE:		if (sm->eapolEap)			SM_ENTER(BE_AUTH, RESPONSE);		else if (sm->eapReq)			SM_ENTER(BE_AUTH, REQUEST);		else if (sm->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(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->keyAvailable = FALSE;	sm->keyDone = TRUE;}SM_STEP(AUTH_KEY_TX){	if (sm->initialize || sm->portControl != Auto) {		SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);		return;	}	switch (sm->auth_key_tx_state) {	case AUTH_KEY_TX_NO_KEY_TRANSMIT:		if (sm->keyTxEnabled && sm->keyAvailable && 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->keyAvailable)			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->portEnabled) {		SM_ENTER(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){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -