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

📄 eapol_supp_sm.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * EAPOL supplicant state machines * Copyright (c) 2004-2008, Jouni Malinen <j@w1.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 "common.h"#include "eapol_supp_sm.h"#include "eap_peer/eap.h"#include "eloop.h"#include "eapol_common.h"#include "md5.h"#include "rc4.h"#include "state_machine.h"#include "wpabuf.h"#define STATE_MACHINE_DATA struct eapol_sm#define STATE_MACHINE_DEBUG_PREFIX "EAPOL"/* IEEE 802.1X-2004 - Supplicant - EAPOL state machines *//** * struct eapol_sm - Internal data for EAPOL state machines */struct eapol_sm {	/* Timers */	unsigned int authWhile;	unsigned int heldWhile;	unsigned int startWhen;	unsigned int idleWhile; /* for EAP state machine */	int timer_tick_enabled;	/* Global variables */	Boolean eapFail;	Boolean eapolEap;	Boolean eapSuccess;	Boolean initialize;	Boolean keyDone;	Boolean keyRun;	PortControl portControl;	Boolean portEnabled;	PortStatus suppPortStatus;  /* dot1xSuppControlledPortStatus */	Boolean portValid;	Boolean suppAbort;	Boolean suppFail;	Boolean suppStart;	Boolean suppSuccess;	Boolean suppTimeout;	/* Supplicant PAE state machine */	enum {		SUPP_PAE_UNKNOWN = 0,		SUPP_PAE_DISCONNECTED = 1,		SUPP_PAE_LOGOFF = 2,		SUPP_PAE_CONNECTING = 3,		SUPP_PAE_AUTHENTICATING = 4,		SUPP_PAE_AUTHENTICATED = 5,		/* unused(6) */		SUPP_PAE_HELD = 7,		SUPP_PAE_RESTART = 8,		SUPP_PAE_S_FORCE_AUTH = 9,		SUPP_PAE_S_FORCE_UNAUTH = 10	} SUPP_PAE_state; /* dot1xSuppPaeState */	/* Variables */	Boolean userLogoff;	Boolean logoffSent;	unsigned int startCount;	Boolean eapRestart;	PortControl sPortMode;	/* Constants */	unsigned int heldPeriod; /* dot1xSuppHeldPeriod */	unsigned int startPeriod; /* dot1xSuppStartPeriod */	unsigned int maxStart; /* dot1xSuppMaxStart */	/* Key Receive state machine */	enum {		KEY_RX_UNKNOWN = 0,		KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE	} KEY_RX_state;	/* Variables */	Boolean rxKey;	/* Supplicant Backend state machine */	enum {		SUPP_BE_UNKNOWN = 0,		SUPP_BE_INITIALIZE = 1,		SUPP_BE_IDLE = 2,		SUPP_BE_REQUEST = 3,		SUPP_BE_RECEIVE = 4,		SUPP_BE_RESPONSE = 5,		SUPP_BE_FAIL = 6,		SUPP_BE_TIMEOUT = 7, 		SUPP_BE_SUCCESS = 8	} SUPP_BE_state; /* dot1xSuppBackendPaeState */	/* Variables */	Boolean eapNoResp;	Boolean eapReq;	Boolean eapResp;	/* Constants */	unsigned int authPeriod; /* dot1xSuppAuthPeriod */	/* Statistics */	unsigned int dot1xSuppEapolFramesRx;	unsigned int dot1xSuppEapolFramesTx;	unsigned int dot1xSuppEapolStartFramesTx;	unsigned int dot1xSuppEapolLogoffFramesTx;	unsigned int dot1xSuppEapolRespFramesTx;	unsigned int dot1xSuppEapolReqIdFramesRx;	unsigned int dot1xSuppEapolReqFramesRx;	unsigned int dot1xSuppInvalidEapolFramesRx;	unsigned int dot1xSuppEapLengthErrorFramesRx;	unsigned int dot1xSuppLastEapolFrameVersion;	unsigned char dot1xSuppLastEapolFrameSource[6];	/* Miscellaneous variables (not defined in IEEE 802.1X-2004) */	Boolean changed;	struct eap_sm *eap;	struct eap_peer_config *config;	Boolean initial_req;	u8 *last_rx_key;	size_t last_rx_key_len;	struct wpabuf *eapReqData; /* for EAP */	Boolean altAccept; /* for EAP */	Boolean altReject; /* for EAP */	Boolean replay_counter_valid;	u8 last_replay_counter[16];	struct eapol_config conf;	struct eapol_ctx *ctx;	enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }		cb_status;	Boolean cached_pmk;	Boolean unicast_key_received, broadcast_key_received;};#define IEEE8021X_REPLAY_COUNTER_LEN 8#define IEEE8021X_KEY_SIGN_LEN 16#define IEEE8021X_KEY_IV_LEN 16#define IEEE8021X_KEY_INDEX_FLAG 0x80#define IEEE8021X_KEY_INDEX_MASK 0x03#ifdef _MSC_VER#pragma pack(push, 1)#endif /* _MSC_VER */struct ieee802_1x_eapol_key {	u8 type;	/* Note: key_length is unaligned */	u8 key_length[2];	/* does not repeat within the life of the keying material used to	 * encrypt the Key field; 64-bit NTP timestamp MAY be used here */	u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];	u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */	u8 key_index; /* key flag in the most significant bit:		       * 0 = broadcast (default key),		       * 1 = unicast (key mapping key); key index is in the		       * 7 least significant bits */	/* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as	 * the key */	u8 key_signature[IEEE8021X_KEY_SIGN_LEN];	/* followed by key: if packet body length = 44 + key length, then the	 * key field (of key_length bytes) contains the key in encrypted form;	 * if packet body length = 44, key field is absent and key_length	 * represents the number of least significant octets from	 * MS-MPPE-Send-Key attribute to be used as the keying material;	 * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */} STRUCT_PACKED;#ifdef _MSC_VER#pragma pack(pop)#endif /* _MSC_VER */static void eapol_sm_txLogoff(struct eapol_sm *sm);static void eapol_sm_txStart(struct eapol_sm *sm);static void eapol_sm_processKey(struct eapol_sm *sm);static void eapol_sm_getSuppRsp(struct eapol_sm *sm);static void eapol_sm_txSuppRsp(struct eapol_sm *sm);static void eapol_sm_abortSupp(struct eapol_sm *sm);static void eapol_sm_abort_cached(struct eapol_sm *sm);static void eapol_sm_step_timeout(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_sm *sm = timeout_ctx;	if (sm->authWhile > 0) {		sm->authWhile--;		if (sm->authWhile == 0)			wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");	}	if (sm->heldWhile > 0) {		sm->heldWhile--;		if (sm->heldWhile == 0)			wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");	}	if (sm->startWhen > 0) {		sm->startWhen--;		if (sm->startWhen == 0)			wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");	}	if (sm->idleWhile > 0) {		sm->idleWhile--;		if (sm->idleWhile == 0)			wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");	}	if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {		eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,				       sm);	} else {		wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");		sm->timer_tick_enabled = 0;	}	eapol_sm_step(sm);}static void eapol_enable_timer_tick(struct eapol_sm *sm){	if (sm->timer_tick_enabled)		return;	wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");	sm->timer_tick_enabled = 1;	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);}SM_STATE(SUPP_PAE, LOGOFF){	SM_ENTRY(SUPP_PAE, LOGOFF);	eapol_sm_txLogoff(sm);	sm->logoffSent = TRUE;	sm->suppPortStatus = Unauthorized;}SM_STATE(SUPP_PAE, DISCONNECTED){	SM_ENTRY(SUPP_PAE, DISCONNECTED);	sm->sPortMode = Auto;	sm->startCount = 0;	sm->logoffSent = FALSE;	sm->suppPortStatus = Unauthorized;	sm->suppAbort = TRUE;	sm->unicast_key_received = FALSE;	sm->broadcast_key_received = FALSE;}SM_STATE(SUPP_PAE, CONNECTING){	int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;	SM_ENTRY(SUPP_PAE, CONNECTING);	if (send_start) {		sm->startWhen = sm->startPeriod;		sm->startCount++;	} else {		/*		 * Do not send EAPOL-Start immediately since in most cases,		 * Authenticator is going to start authentication immediately		 * after association and an extra EAPOL-Start is just going to		 * delay authentication. Use a short timeout to send the first		 * EAPOL-Start if Authenticator does not start authentication.		 */		sm->startWhen = 3;	}	eapol_enable_timer_tick(sm);	sm->eapolEap = FALSE;	if (send_start)		eapol_sm_txStart(sm);}SM_STATE(SUPP_PAE, AUTHENTICATING){	SM_ENTRY(SUPP_PAE, AUTHENTICATING);	sm->startCount = 0;	sm->suppSuccess = FALSE;	sm->suppFail = FALSE;	sm->suppTimeout = FALSE;	sm->keyRun = FALSE;	sm->keyDone = FALSE;	sm->suppStart = TRUE;}SM_STATE(SUPP_PAE, HELD){	SM_ENTRY(SUPP_PAE, HELD);	sm->heldWhile = sm->heldPeriod;	eapol_enable_timer_tick(sm);	sm->suppPortStatus = Unauthorized;	sm->cb_status = EAPOL_CB_FAILURE;}SM_STATE(SUPP_PAE, AUTHENTICATED){	SM_ENTRY(SUPP_PAE, AUTHENTICATED);	sm->suppPortStatus = Authorized;	sm->cb_status = EAPOL_CB_SUCCESS;}SM_STATE(SUPP_PAE, RESTART){	SM_ENTRY(SUPP_PAE, RESTART);	sm->eapRestart = TRUE;}SM_STATE(SUPP_PAE, S_FORCE_AUTH){	SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);	sm->suppPortStatus = Authorized;	sm->sPortMode = ForceAuthorized;}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_STEP(SUPP_PAE){	if ((sm->userLogoff && !sm->logoffSent) &&	    !(sm->initialize || !sm->portEnabled))		SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);	else if (((sm->portControl == Auto) &&		  (sm->sPortMode != sm->portControl)) ||		 sm->initialize || !sm->portEnabled)		SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);	else if ((sm->portControl == ForceAuthorized) &&		 (sm->sPortMode != sm->portControl) &&		 !(sm->initialize || !sm->portEnabled))		SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);	else if ((sm->portControl == ForceUnauthorized) &&		 (sm->sPortMode != sm->portControl) &&		 !(sm->initialize || !sm->portEnabled))		SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);	else switch (sm->SUPP_PAE_state) {	case SUPP_PAE_UNKNOWN:		break;	case SUPP_PAE_LOGOFF:		if (!sm->userLogoff)			SM_ENTER(SUPP_PAE, DISCONNECTED);		break;	case SUPP_PAE_DISCONNECTED:		SM_ENTER(SUPP_PAE, CONNECTING);		break;	case SUPP_PAE_CONNECTING:		if (sm->startWhen == 0 && sm->startCount < sm->maxStart)			SM_ENTER(SUPP_PAE, CONNECTING);		else if (sm->startWhen == 0 &&			 sm->startCount >= sm->maxStart &&			 sm->portValid)			SM_ENTER(SUPP_PAE, AUTHENTICATED);		else if (sm->eapSuccess || sm->eapFail)			SM_ENTER(SUPP_PAE, AUTHENTICATING);		else if (sm->eapolEap)			SM_ENTER(SUPP_PAE, RESTART);		else if (sm->startWhen == 0 &&			 sm->startCount >= sm->maxStart &&			 !sm->portValid)			SM_ENTER(SUPP_PAE, HELD);		break;	case SUPP_PAE_AUTHENTICATING:		if (sm->eapSuccess && !sm->portValid &&		    sm->conf.accept_802_1x_keys &&		    sm->conf.required_keys == 0) {			wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "				   "plaintext connection; no EAPOL-Key frames "				   "required");			sm->portValid = TRUE;			if (sm->ctx->eapol_done_cb)				sm->ctx->eapol_done_cb(sm->ctx->ctx);		}		if (sm->eapSuccess && sm->portValid)			SM_ENTER(SUPP_PAE, AUTHENTICATED);		else if (sm->eapFail || (sm->keyDone && !sm->portValid))			SM_ENTER(SUPP_PAE, HELD);		else if (sm->suppTimeout)			SM_ENTER(SUPP_PAE, CONNECTING);		break;	case SUPP_PAE_HELD:		if (sm->heldWhile == 0)			SM_ENTER(SUPP_PAE, CONNECTING);		else if (sm->eapolEap)			SM_ENTER(SUPP_PAE, RESTART);		break;	case SUPP_PAE_AUTHENTICATED:		if (sm->eapolEap && sm->portValid)			SM_ENTER(SUPP_PAE, RESTART);		else if (!sm->portValid)			SM_ENTER(SUPP_PAE, DISCONNECTED);		break;	case SUPP_PAE_RESTART:		if (!sm->eapRestart)			SM_ENTER(SUPP_PAE, AUTHENTICATING);		break;	case SUPP_PAE_S_FORCE_AUTH:		break;	case SUPP_PAE_S_FORCE_UNAUTH:		break;	}}SM_STATE(KEY_RX, NO_KEY_RECEIVE){	SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);}SM_STATE(KEY_RX, KEY_RECEIVE){	SM_ENTRY(KEY_RX, KEY_RECEIVE);	eapol_sm_processKey(sm);	sm->rxKey = FALSE;}SM_STEP(KEY_RX){	if (sm->initialize || !sm->portEnabled)		SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);	switch (sm->KEY_RX_state) {	case KEY_RX_UNKNOWN:		break;	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);

⌨️ 快捷键说明

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