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

📄 eapol_sm.c

📁 802.1x 源码,基于linux平台开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *
 * 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. See README and COPYING for
 * more details.

	Module Name:
	eapol_sm.c

	Revision History:
	Who         When          What
	--------    ----------    ----------------------------------------------
	Jan, Lee    Dec --2003    modified

*/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>

#include "rt61apd.h"
#include "ieee802_1x.h"
#include "eapol_sm.h"
#include "eloop.h"
#include "mac2port.h"

/* TODO:
 * implement state machines: Controlled Directions and Key Receive
 */


/* EAPOL state machines are described in IEEE Std 802.1X-2001, Chap. 8.5 */

#define setPortAuthorized() \
ieee802_1x_set_sta_authorized(1)
#define setPortUnauthorized() \
ieee802_1x_set_sta_authorized(0)

/* procedures */
#define txCannedFail(x) ieee802_1x_tx_canned_eap(sm->rtapd, sm->sta, (x), 0)
#define txCannedSuccess(x) ieee802_1x_tx_canned_eap(sm->rtapd, sm->sta, (x), 1)
/* TODO: IEEE 802.1aa/D4 replaces txReqId(x) with txInitialMsg(x); value of
 * initialEAPMsg should be used to select which type of EAP packet is sent;
 * Currently, hostapd only supports EAP Request/Identity, so this can be
 * hardcoded. */
#define txInitialMsg(x) ieee802_1x_request_identity(sm->rtapd, sm->sta, (x))
#define txReq(x) ieee802_1x_tx_req(sm->rtapd, sm->sta, (x))
#define sendRespToServer ieee802_1x_send_resp_to_server(sm->rtapd, sm->sta)
/* TODO: check if abortAuth would be needed for something */
#define abortAuth do { } while (0)
#define txKey(x) ieee802_1x_tx_key(sm->rtapd, sm->sta, (x))

/* 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->rtapd->conf->debug >= HOSTAPD_DEBUG_MINIMAL) \
	DBGPRINT(RT_DEBUG_ERROR,"IEEE 802.1X: " MACSTR " " #machine " entering state " #_state \
		"\n", MAC2STR(sm->sta->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->txWhen > 0)
		state->txWhen--;
DBGPRINT(RT_DEBUG_INFO,"  eapol_port_timers_tick call eapol_sm_step\n");
	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)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, INITIALIZE\n");
	SM_ENTRY(AUTH_PAE, INITIALIZE, auth_pae);
	sm->currentId = 1;
	sm->auth_pae.portMode = Auto;
}


SM_STATE(AUTH_PAE, DISCONNECTED)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, DISCONNECTED\n");
	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);
    
    if((sm->portStatus != Unauthorized) || (!from_initialize))
    {
        int lPort;
        lPort = Mac2Port_FindPortByMac(sm->sta->addr);
        if(lPort != -1)
        {
            ieee802_1x_set_sta_port_status(1, lPort);
        }    
        Mac2Port_DelMac(sm->sta->addr);
        eloop_cancel_timeout(eapol_port_timers_tick, sm->rtapd, sm);
    }

	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(AUTH_PAE, CONNECTING)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_CONNECTING\n");

	if (sm->auth_pae.state != AUTH_PAE_CONNECTING)
		sm->auth_pae.authEntersConnecting++;

	if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATED) {
		if (sm->reAuthenticate)
			sm->auth_pae.authAuthReauthsWhileAuthenticated++;
		if (sm->auth_pae.eapStart)
			sm->auth_pae.authAuthEapStartsWhileAuthenticated++;
		if (sm->auth_pae.eapLogoff)
			sm->auth_pae.authAuthEapLogoffWhileAuthenticated++;
	}

	SM_ENTRY(AUTH_PAE, CONNECTING, auth_pae);

	sm->auth_pae.eapStart = FALSE;
	sm->reAuthenticate = FALSE;
	sm->txWhen = sm->auth_pae.txPeriod;
	sm->auth_pae.rxInitialRsp = FALSE;
	txInitialMsg(sm->currentId);
	sm->auth_pae.reAuthCount++;
}


SM_STATE(AUTH_PAE, HELD)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_HELD\n");
	if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authFail)
		sm->auth_pae.authAuthFailWhileAuthenticating++;

	SM_ENTRY(AUTH_PAE, HELD, auth_pae);

	sm->portStatus = Unauthorized;
	setPortUnauthorized();
        {
            int lPort;
            lPort = Mac2Port_FindPortByMac(sm->sta->addr);
            if(lPort != -1)
            {
                ieee802_1x_set_sta_port_status(1, lPort);
            }
        }
	sm->quietWhile = sm->auth_pae.quietPeriod;
	sm->auth_pae.eapLogoff = FALSE;
	sm->currentId++;

}


SM_STATE(AUTH_PAE, AUTHENTICATED)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_AUTHENTICATED\n");
    if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
        sm->auth_pae.authAuthSuccessesWhileAuthenticating++;
    						
    SM_ENTRY(AUTH_PAE, AUTHENTICATED, auth_pae);

    if(sm->portStatus != Authorized)
    {
        int lPort;
        lPort = Mac2Port_FindPortByMac(sm->sta->addr);
        if(lPort != -1)
        {
            ieee802_1x_set_sta_port_status(FALSE, lPort);
        }
    }
    sm->portStatus = Authorized;
    setPortAuthorized();
    sm->auth_pae.reAuthCount = 0;
    sm->currentId++;
}


SM_STATE(AUTH_PAE, AUTHENTICATING)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_AUTHENTICATING\n");
	if (sm->auth_pae.state == AUTH_PAE_CONNECTING &&
	    sm->auth_pae.rxInitialRsp)
		sm->auth_pae.authEntersAuthenticating++;

	SM_ENTRY(AUTH_PAE, AUTHENTICATING, auth_pae);

	sm->authSuccess = FALSE;
	sm->authFail = FALSE;
	sm->authTimeout = FALSE;
	sm->authStart = TRUE;
}


SM_STATE(AUTH_PAE, ABORTING)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_ABORTING\n");
	if (sm->auth_pae.state == AUTH_PAE_AUTHENTICATING) {
		if (sm->authTimeout)
			sm->auth_pae.authAuthTimeoutsWhileAuthenticating++;
		if (sm->reAuthenticate)
			sm->auth_pae.authAuthReauthsWhileAuthenticating++;
		if (sm->auth_pae.eapStart)
			sm->auth_pae.authAuthEapStartsWhileAuthenticating++;
		if (sm->auth_pae.eapLogoff)
			sm->auth_pae.authAuthEapLogoffWhileAuthenticating++;
	}

	SM_ENTRY(AUTH_PAE, ABORTING, auth_pae);

	sm->authAbort = TRUE;
	sm->currentId++;
}


SM_STATE(AUTH_PAE, FORCE_AUTH)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_FORCE_AUTH\n");
	SM_ENTRY(AUTH_PAE, FORCE_AUTH, auth_pae);

	sm->portStatus = Authorized;
	setPortAuthorized();
    /*强制认证状态下端口不一定学到了MAC地址*/
    /*{
        int lPort;
        lPort = Mac2Port_FindPortByMac(sm->sta->addr);
        if(lPort != -1)
        {
            ieee802_1x_set_sta_port_status(FALSE, lPort);
        }
    }*/
	sm->auth_pae.portMode = ForceAuthorized;
	sm->auth_pae.eapStart = FALSE;
	txCannedSuccess(sm->currentId);
	sm->currentId++;
}


SM_STATE(AUTH_PAE, FORCE_UNAUTH)
{
DBGPRINT(RT_DEBUG_INFO," SM_STATE, AUTH_PAE, CONNECTING_FORCE_UNAUTH\n");
	SM_ENTRY(AUTH_PAE, FORCE_UNAUTH, auth_pae);

	sm->portStatus = Unauthorized;
	setPortUnauthorized();
    /*强制非认证状态下端口不一定学到了MAC地址*/
        /*{
            int lPort;
            lPort = Mac2Port_FindPortByMac(sm->sta->addr);
            if(lPort != -1)
            {
                ieee802_1x_set_sta_port_status(1, lPort);
            }
        }*/
        Mac2Port_DelMac(sm->sta->addr);
	sm->auth_pae.portMode = ForceUnauthorized;
	sm->auth_pae.eapStart = FALSE;
	txCannedFail(sm->currentId);
	sm->currentId++;
}


SM_STEP(AUTH_PAE)
{
	DBGPRINT(RT_DEBUG_INFO," SM_STEP, AUTH_PAE, auth_pae.state(%d)\n",sm->auth_pae.state);
	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, CONNECTING);
			break;
		case AUTH_PAE_HELD:
			if (sm->quietWhile == 0)
				SM_ENTER(AUTH_PAE, CONNECTING);
			break;
		case AUTH_PAE_CONNECTING:
			if (sm->auth_pae.eapLogoff ||
			    sm->auth_pae.reAuthCount > sm->auth_pae.reAuthMax)
				SM_ENTER(AUTH_PAE, DISCONNECTED);
			else if (sm->auth_pae.rxInitialRsp &&
				 sm->auth_pae.reAuthCount <=
				 sm->auth_pae.reAuthMax)
				SM_ENTER(AUTH_PAE, AUTHENTICATING);
			else if ((sm->txWhen == 0 || sm->auth_pae.eapStart ||
				  sm->reAuthenticate) &&
				 sm->auth_pae.reAuthCount <=
				 sm->auth_pae.reAuthMax)
				SM_ENTER(AUTH_PAE, CONNECTING);
			break;
		case AUTH_PAE_AUTHENTICATED:
			if (sm->auth_pae.eapStart || sm->reAuthenticate)
				SM_ENTER(AUTH_PAE, CONNECTING);
			else if (sm->auth_pae.eapLogoff || !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_ENTER(AUTH_PAE, HELD);
			else if (sm->reAuthenticate || sm->auth_pae.eapStart ||
				 sm->auth_pae.eapLogoff ||
				 sm->authTimeout)
				SM_ENTER(AUTH_PAE, ABORTING);
			break;
		case AUTH_PAE_ABORTING:
			if (sm->auth_pae.eapLogoff && !sm->authAbort)
				SM_ENTER(AUTH_PAE, DISCONNECTED);
			else if (!sm->auth_pae.eapLogoff && !sm->authAbort)

⌨️ 快捷键说明

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