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

📄 eapol_sm.c

📁 hostapd无线AP工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Host AP (software wireless LAN access point) user space daemon for * Host AP kernel driver / 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 <stdlib.h>#include <stdio.h>#include <unistd.h>#include <netinet/in.h>#include <string.h>#include <sys/socket.h>#include "hostapd.h"#include "ieee802_1x.h"#include "eapol_sm.h"#include "eloop.h"#include "wpa.h"#include "sta_info.h"#include "eap.h"static 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)/* Definitions for clarifying state machine implementation */#define SM_STATE(machine, state) \static void sm_ ## machine ## _ ## state ## _Enter(struct eapol_state_machine \*sm)#define SM_ENTRY(machine, _state, _data) \sm->_data.state = machine ## _ ## _state; \if (sm->hapd->conf->debug >= HOSTAPD_DEBUG_MINIMAL) \	printf("IEEE 802.1X: " MACSTR " " #machine " entering state " #_state \		"\n", MAC2STR(sm->addr));#define SM_ENTER(machine, state) sm_ ## machine ## _ ## state ## _Enter(sm)#define SM_STEP(machine) \static void sm_ ## machine ## _Step(struct eapol_state_machine *sm)#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)/* 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->quietWhile > 0)		state->quietWhile--;	if (state->reAuthWhen > 0)		state->reAuthWhen--;	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);	eapol_sm_step(state);	eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);}/* Authenticator PAE state machine */SM_STATE(AUTH_PAE, INITIALIZE){	SM_ENTRY(AUTH_PAE, INITIALIZE, auth_pae);	sm->auth_pae.portMode = Auto;	sm->currentId = 255;}SM_STATE(AUTH_PAE, DISCONNECTED){	int from_initialize = sm->auth_pae.state == AUTH_PAE_INITIALIZE;	if (sm->auth_pae.eapolLogoff) {		if (sm->auth_pae.state == AUTH_PAE_CONNECTING)			sm->auth_pae.authEapLogoffsWhileConnecting++;		else if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATED)			sm->auth_pae.authAuthEapLogoffWhileAuthenticated++;	}	SM_ENTRY(AUTH_PAE, DISCONNECTED, auth_pae);	sm->authPortStatus = Unauthorized;	setPortUnauthorized();	sm->auth_pae.reAuthCount = 0;	sm->auth_pae.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->auth_pae.authAuthReauthsWhileAuthenticated++;		if (sm->auth_pae.eapolStart)			sm->auth_pae.authAuthEapStartsWhileAuthenticated++;		if (sm->auth_pae.eapolLogoff)			sm->auth_pae.authAuthEapLogoffWhileAuthenticated++;	}	SM_ENTRY(AUTH_PAE, RESTART, auth_pae);	sm->auth_pae.eapRestart = TRUE;	ieee802_1x_request_identity(sm->hapd, sm->sta);}SM_STATE(AUTH_PAE, CONNECTING){	if (sm->auth_pae.state != AUTH_PAE_CONNECTING)		sm->auth_pae.authEntersConnecting++;	SM_ENTRY(AUTH_PAE, CONNECTING, auth_pae);	sm->reAuthenticate = FALSE;	sm->auth_pae.reAuthCount++;}SM_STATE(AUTH_PAE, HELD){	if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authFail)		sm->auth_pae.authAuthFailWhileAuthenticating++;	SM_ENTRY(AUTH_PAE, HELD, auth_pae);	sm->authPortStatus = Unauthorized;	setPortUnauthorized();	sm->quietWhile = sm->auth_pae.quietPeriod;	sm->auth_pae.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->auth_pae.authAuthSuccessesWhileAuthenticating++;								SM_ENTRY(AUTH_PAE, AUTHENTICATED, auth_pae);	sm->authPortStatus = Authorized;	setPortAuthorized();	sm->auth_pae.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->auth_pae.authEntersAuthenticating++;		sm->rx_identity = FALSE;	}	SM_ENTRY(AUTH_PAE, AUTHENTICATING, auth_pae);	sm->auth_pae.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->auth_pae.authAuthTimeoutsWhileAuthenticating++;		if (sm->auth_pae.eapolStart)			sm->auth_pae.authAuthEapStartsWhileAuthenticating++;		if (sm->auth_pae.eapolLogoff)			sm->auth_pae.authAuthEapLogoffWhileAuthenticating++;	}	SM_ENTRY(AUTH_PAE, ABORTING, auth_pae);	sm->authAbort = TRUE;	sm->keyRun = FALSE;	sm->keyDone = FALSE;}SM_STATE(AUTH_PAE, FORCE_AUTH){	SM_ENTRY(AUTH_PAE, FORCE_AUTH, auth_pae);	sm->authPortStatus = Authorized;	setPortAuthorized();	sm->auth_pae.portMode = ForceAuthorized;	sm->auth_pae.eapolStart = FALSE;	txCannedSuccess();}SM_STATE(AUTH_PAE, FORCE_UNAUTH){	SM_ENTRY(AUTH_PAE, FORCE_UNAUTH, auth_pae);	sm->authPortStatus = Unauthorized;	setPortUnauthorized();	sm->auth_pae.portMode = ForceUnauthorized;	sm->auth_pae.eapolStart = FALSE;	txCannedFail();}SM_STEP(AUTH_PAE){	if ((sm->portControl == Auto &&	     sm->auth_pae.portMode != sm->portControl) ||	    sm->initialize || !sm->portEnabled)		SM_ENTER(AUTH_PAE, INITIALIZE);	else if (sm->portControl == ForceAuthorized &&		 sm->auth_pae.portMode != sm->portControl &&		 !(sm->initialize || !sm->portEnabled))		SM_ENTER(AUTH_PAE, FORCE_AUTH);	else if (sm->portControl == ForceUnauthorized &&		 sm->auth_pae.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->auth_pae.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->auth_pae.eapolLogoff ||			    sm->auth_pae.reAuthCount > sm->auth_pae.reAuthMax)				SM_ENTER(AUTH_PAE, DISCONNECTED);			else if ((sm->be_auth.eapReq &&				  sm->auth_pae.reAuthCount <=				  sm->auth_pae.reAuthMax) ||				 sm->eapSuccess || sm->eapFail)				SM_ENTER(AUTH_PAE, AUTHENTICATING);			break;		case AUTH_PAE_AUTHENTICATED:			if (sm->auth_pae.eapolStart || sm->reAuthenticate)				SM_ENTER(AUTH_PAE, RESTART);			else if (sm->auth_pae.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->auth_pae.eapolStart ||				 sm->auth_pae.eapolLogoff || sm->authTimeout)				SM_ENTER(AUTH_PAE, ABORTING);			break;		case AUTH_PAE_ABORTING:			if (sm->auth_pae.eapolLogoff && !sm->authAbort)				SM_ENTER(AUTH_PAE, DISCONNECTED);			else if (!sm->auth_pae.eapolLogoff && !sm->authAbort)				SM_ENTER(AUTH_PAE, RESTART);			break;		case AUTH_PAE_FORCE_AUTH:			if (sm->auth_pae.eapolStart)				SM_ENTER(AUTH_PAE, FORCE_AUTH);			break;		case AUTH_PAE_FORCE_UNAUTH:			if (sm->auth_pae.eapolStart)				SM_ENTER(AUTH_PAE, FORCE_UNAUTH);			break;		}	}}/* Backend Authentication state machine */SM_STATE(BE_AUTH, INITIALIZE){	SM_ENTRY(BE_AUTH, INITIALIZE, be_auth);	abortAuth();	sm->be_auth.eapNoReq = FALSE;	sm->authAbort = FALSE;}SM_STATE(BE_AUTH, REQUEST){	SM_ENTRY(BE_AUTH, REQUEST, be_auth);	txReq();	sm->be_auth.eapReq = FALSE;	sm->be_auth.backendOtherRequestsToSupplicant++;}SM_STATE(BE_AUTH, RESPONSE){	SM_ENTRY(BE_AUTH, RESPONSE, be_auth);	sm->authTimeout = FALSE;	sm->eapolEap = FALSE;	sm->be_auth.eapNoReq = FALSE;	sm->aWhile = sm->be_auth.serverTimeout;	sm->be_auth.eapResp = TRUE;	sendRespToServer();	sm->be_auth.backendResponses++;}SM_STATE(BE_AUTH, SUCCESS){	SM_ENTRY(BE_AUTH, SUCCESS, be_auth);	txReq();	sm->authSuccess = TRUE;	sm->keyRun = TRUE;}SM_STATE(BE_AUTH, FAIL){	SM_ENTRY(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(BE_AUTH, TIMEOUT, be_auth);	sm->authTimeout = TRUE;}SM_STATE(BE_AUTH, IDLE){	SM_ENTRY(BE_AUTH, IDLE, be_auth);	sm->authStart = FALSE;}SM_STATE(BE_AUTH, IGNORE){	SM_ENTRY(BE_AUTH, IGNORE, be_auth);	sm->be_auth.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->be_auth.eapReq)			SM_ENTER(BE_AUTH, REQUEST);		else if (sm->eapTimeout)			SM_ENTER(BE_AUTH, TIMEOUT);		break;	case BE_AUTH_RESPONSE:		if (sm->be_auth.eapNoReq)			SM_ENTER(BE_AUTH, IGNORE);		if (sm->be_auth.eapReq) {			sm->be_auth.backendAccessChallenges++;			SM_ENTER(BE_AUTH, REQUEST);		} else if (sm->aWhile == 0)			SM_ENTER(BE_AUTH, TIMEOUT);		else if (sm->eapFail) {			sm->be_auth.backendAuthFails++;			SM_ENTER(BE_AUTH, FAIL);		} else if (sm->eapSuccess) {			sm->be_auth.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->be_auth.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->be_auth.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(REAUTH_TIMER, INITIALIZE, reauth_timer);	sm->reAuthWhen = sm->reauth_timer.reAuthPeriod;}SM_STATE(REAUTH_TIMER, REAUTHENTICATE){	SM_ENTRY(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);	sm->reAuthenticate = TRUE;	wpa_sm_event(sm->hapd, sm->sta, WPA_REAUTH_EAPOL);}SM_STEP(REAUTH_TIMER){	if (sm->portControl != Auto || sm->initialize ||	    sm->authPortStatus == Unauthorized ||	    !sm->reauth_timer.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(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);}SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT){	SM_ENTRY(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 &&		    !sm->sta->wpa)			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(KEY_RX, NO_KEY_RECEIVE, key_rx);}SM_STATE(KEY_RX, KEY_RECEIVE){	SM_ENTRY(KEY_RX, KEY_RECEIVE, key_rx);	processKey();	sm->key_rx.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->key_rx.rxKey)

⌨️ 快捷键说明

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