eapol_auth_sm.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng * IEEE 802.1X-2004 Authenticator - EAPOL state machine 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng * This program is free software; you can redistribute it and/or modify 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng * it under the terms of the GNU General Public License version 2 as 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng * published by the Free Software Foundation. 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng * Alternatively, this software may be distributed under the terms of BSD 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng * license. 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng * See README and COPYING for more details. 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "includes.h" 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "common.h" 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "eloop.h" 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "state_machine.h" 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "common/eapol_common.h" 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "eap_common/eap_defs.h" 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "eap_common/eap_common.h" 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "eap_server/eap.h" 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "eapol_auth_sm.h" 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "eapol_auth_sm_i.h" 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define STATE_MACHINE_DATA struct eapol_state_machine 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X" 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define STATE_MACHINE_ADDR sm->addr 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct eapol_callbacks eapol_cb; 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */ 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define setPortAuthorized() \ 3625b3c049e70834cf33790a28643ab058b507b35cBen Chengsm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1) 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define setPortUnauthorized() \ 3825b3c049e70834cf33790a28643ab058b507b35cBen Chengsm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0) 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* procedures */ 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define txCannedFail() eapol_auth_tx_canned_eap(sm, 0) 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1) 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define txReq() eapol_auth_tx_req(sm) 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta) 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta) 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define processKey() do { } while (0) 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_sm_step_run(struct eapol_state_machine *sm); 5025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx); 5125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_initialize(struct eapol_state_machine *sm); 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_logger(struct eapol_authenticator *eapol, 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const u8 *addr, eapol_logger_level level, 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *txt) 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol->cb.logger == NULL) 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.logger(eapol->conf.ctx, addr, level, txt); 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_vlogger(struct eapol_authenticator *eapol, 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const u8 *addr, eapol_logger_level level, 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fmt, ...) 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *format; 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int maxlen; 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng va_list ap; 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol->cb.logger == NULL) 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng maxlen = os_strlen(fmt) + 100; 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng format = os_malloc(maxlen); 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!format) 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng va_start(ap, fmt); 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng vsnprintf(format, maxlen, fmt, ap); 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng va_end(ap); 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_logger(eapol, addr, level, format); 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(format); 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm, 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int success) 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eap_hdr eap; 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memset(&eap, 0, sizeof(eap)); 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap.identifier = ++sm->last_eap_id; 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap.length = host_to_be16(sizeof(eap)); 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng "Sending canned EAP packet %s (identifier %d)", 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng success ? "SUCCESS" : "FAILURE", eap.identifier); 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng IEEE802_1X_TYPE_EAP_PACKET, 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng (u8 *) &eap, sizeof(eap)); 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->dot1xAuthEapolFramesTx++; 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_tx_req(struct eapol_state_machine *sm) 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->eapReqData == NULL || 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) { 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_logger(sm->eapol, sm->addr, 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng EAPOL_LOGGER_DEBUG, 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng "TxReq called, but there is no EAP request " 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng "from authentication server"); 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->flags & EAPOL_SM_WAIT_START) { 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng " while waiting for EAPOL-Start", 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAC2STR(sm->addr)); 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData); 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng "Sending EAP Packet (identifier %d)", 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->last_eap_id); 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng IEEE802_1X_TYPE_EAP_PACKET, 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpabuf_head(sm->eap_if->eapReqData), 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpabuf_len(sm->eap_if->eapReqData)); 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->dot1xAuthEapolFramesTx++; 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY) 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->dot1xAuthEapolReqIdFramesTx++; 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->dot1xAuthEapolReqFramesTx++; 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/** 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng * eapol_port_timers_tick - Port Timers state machine 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng * @eloop_ctx: struct eapol_state_machine * 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng * @timeout_ctx: Not used 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng * This statemachine is implemented as a function that will be called 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng * once a second as a registered event loop timeout. 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 15325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_state_machine *state = timeout_ctx; 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->aWhile > 0) { 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng state->aWhile--; 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->aWhile == 0) { 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng " - aWhile --> 0", 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAC2STR(state->addr)); 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->quietWhile > 0) { 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng state->quietWhile--; 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->quietWhile == 0) { 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng " - quietWhile --> 0", 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAC2STR(state->addr)); 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->reAuthWhen > 0) { 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng state->reAuthWhen--; 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->reAuthWhen == 0) { 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng " - reAuthWhen --> 0", 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAC2STR(state->addr)); 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->eap_if->retransWhile > 0) { 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng state->eap_if->retransWhile--; 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (state->eap_if->retransWhile == 0) { 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng " - (EAP) retransWhile --> 0", 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAC2STR(state->addr)); 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_sm_step_run(state); 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state); 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Authenticator PAE state machine */ 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, INITIALIZE) 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae); 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portMode = Auto; 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20925b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, DISCONNECTED) 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE; 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolLogoff) { 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->auth_pae_state == AUTH_PAE_CONNECTING) 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authEapLogoffsWhileConnecting++; 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthEapLogoffWhileAuthenticated++; 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae); 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authPortStatus = Unauthorized; 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng setPortUnauthorized(); 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthCount = 0; 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolLogoff = FALSE; 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!from_initialize) { 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->flags & EAPOL_SM_PREAUTH); 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23325b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, RESTART) 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) { 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->reAuthenticate) 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthReauthsWhileAuthenticated++; 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolStart) 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthEapStartsWhileAuthenticated++; 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolLogoff) 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthEapLogoffWhileAuthenticated++; 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapRestart = TRUE; 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25025b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, CONNECTING) 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->auth_pae_state != AUTH_PAE_CONNECTING) 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authEntersConnecting++; 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthenticate = FALSE; 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthCount++; 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, HELD) 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail) 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthFailWhileAuthenticating++; 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae); 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authPortStatus = Unauthorized; 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng setPortUnauthorized(); 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->quietWhile = sm->quietPeriod; 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolLogoff = FALSE; 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng "authentication failed - EAP type: %d (%s)", 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_type_authsrv, 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_server_get_name(0, sm->eap_type_authsrv)); 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_type_authsrv != sm->eap_type_supp) { 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng "Supplicant used different EAP type: " 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng "%d (%s)", sm->eap_type_supp, 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_server_get_name(0, sm->eap_type_supp)); 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->flags & EAPOL_SM_PREAUTH); 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28925b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, AUTHENTICATED) 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *extra = ""; 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess) 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthSuccessesWhileAuthenticating++; 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae); 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authPortStatus = Authorized; 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng setPortAuthorized(); 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthCount = 0; 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->flags & EAPOL_SM_PREAUTH) 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng extra = " (pre-authentication)"; 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE) 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng extra = " (PMKSA cache)"; 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng "authenticated - EAP type: %d (%s)%s", 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_type_authsrv, 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_server_get_name(0, sm->eap_type_authsrv), 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng extra); 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1, 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->flags & EAPOL_SM_PREAUTH); 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31525b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, AUTHENTICATING) 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolStart = FALSE; 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authSuccess = FALSE; 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authFail = FALSE; 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authTimeout = FALSE; 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authStart = TRUE; 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyRun = FALSE; 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyDone = FALSE; 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32925b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, ABORTING) 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) { 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->authTimeout) 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthTimeoutsWhileAuthenticating++; 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolStart) 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthEapStartsWhileAuthenticating++; 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolLogoff) 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAuthEapLogoffWhileAuthenticating++; 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAbort = TRUE; 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyRun = FALSE; 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyDone = FALSE; 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34825b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, FORCE_AUTH) 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae); 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authPortStatus = Authorized; 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng setPortAuthorized(); 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portMode = ForceAuthorized; 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolStart = FALSE; 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng txCannedSuccess(); 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36025b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_PAE, FORCE_UNAUTH) 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae); 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authPortStatus = Unauthorized; 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng setPortUnauthorized(); 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portMode = ForceUnauthorized; 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolStart = FALSE; 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng txCannedFail(); 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STEP(AUTH_PAE) 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((sm->portControl == Auto && sm->portMode != sm->portControl) || 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->initialize || !sm->eap_if->portEnabled) 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE); 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->portControl == ForceAuthorized && 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portMode != sm->portControl && 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng !(sm->initialize || !sm->eap_if->portEnabled)) 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH); 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->portControl == ForceUnauthorized && 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portMode != sm->portControl && 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng !(sm->initialize || !sm->eap_if->portEnabled)) 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH); 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else { 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (sm->auth_pae_state) { 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_INITIALIZE: 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, DISCONNECTED); 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_DISCONNECTED: 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, RESTART); 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_RESTART: 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!sm->eap_if->eapRestart) 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, CONNECTING); 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_HELD: 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->quietWhile == 0) 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, RESTART); 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_CONNECTING: 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax) 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, DISCONNECTED); 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((sm->eap_if->eapReq && 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthCount <= sm->reAuthMax) || 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapSuccess || sm->eap_if->eapFail) 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, AUTHENTICATING); 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_AUTHENTICATED: 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolStart || sm->reAuthenticate) 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, RESTART); 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eapolLogoff || !sm->portValid) 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, DISCONNECTED); 41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_AUTHENTICATING: 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->authSuccess && sm->portValid) 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, AUTHENTICATED); 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->authFail || 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (sm->keyDone && !sm->portValid)) 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, HELD); 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eapolStart || sm->eapolLogoff || 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authTimeout) 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, ABORTING); 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_ABORTING: 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolLogoff && !sm->authAbort) 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, DISCONNECTED); 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (!sm->eapolLogoff && !sm->authAbort) 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, RESTART); 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_FORCE_AUTH: 43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolStart) 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, FORCE_AUTH); 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_PAE_FORCE_UNAUTH: 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolStart) 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_PAE, FORCE_UNAUTH); 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Backend Authentication state machine */ 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44725b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, INITIALIZE) 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng abortAuth(); 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapNoReq = FALSE; 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authAbort = FALSE; 45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45725b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, REQUEST) 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng txReq(); 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapReq = FALSE; 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->backendOtherRequestsToSupplicant++; 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng * it looks like this would be logical thing to do there since the old 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng * EAP response would not be valid anymore after the new EAP request 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng * was sent out. 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng * A race condition has been reported, in which hostapd ended up 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng * sending out EAP-Response/Identity as a response to the first 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng * EAP-Request from the main EAP method. This can be avoided by 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng * clearing eapolEap here. 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolEap = FALSE; 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48025b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, RESPONSE) 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authTimeout = FALSE; 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapolEap = FALSE; 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapNoReq = FALSE; 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->aWhile = sm->serverTimeout; 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapResp = TRUE; 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* sendRespToServer(); */ 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->backendResponses++; 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49425b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, SUCCESS) 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng txReq(); 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authSuccess = TRUE; 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyRun = TRUE; 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50425b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, FAIL) 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng txReq(); 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authFail = TRUE; 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51325b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, TIMEOUT) 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authTimeout = TRUE; 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52125b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, IDLE) 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authStart = FALSE; 52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52925b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(BE_AUTH, IGNORE) 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapNoReq = FALSE; 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53725b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STEP(BE_AUTH) 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->portControl != Auto || sm->initialize || sm->authAbort) { 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE); 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (sm->be_auth_state) { 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_INITIALIZE: 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, IDLE); 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_REQUEST: 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolEap) 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, RESPONSE); 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapReq) 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, REQUEST); 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapTimeout) 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, TIMEOUT); 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_RESPONSE: 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->eapNoReq) 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, IGNORE); 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->eapReq) { 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->backendAccessChallenges++; 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, REQUEST); 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } else if (sm->aWhile == 0) 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, TIMEOUT); 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapFail) { 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->backendAuthFails++; 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, FAIL); 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } else if (sm->eap_if->eapSuccess) { 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->backendAuthSuccesses++; 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, SUCCESS); 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_SUCCESS: 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, IDLE); 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_FAIL: 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, IDLE); 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_TIMEOUT: 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, IDLE); 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_IDLE: 58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->eapFail && sm->authStart) 58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, FAIL); 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapReq && sm->authStart) 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, REQUEST); 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapSuccess && sm->authStart) 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, SUCCESS); 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case BE_AUTH_IGNORE: 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eapolEap) 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, RESPONSE); 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapReq) 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, REQUEST); 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapTimeout) 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(BE_AUTH, TIMEOUT); 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Reauthentication Timer state machine */ 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60425b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(REAUTH_TIMER, INITIALIZE) 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer); 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthWhen = sm->reAuthPeriod; 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(REAUTH_TIMER, REAUTHENTICATE) 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthenticate = TRUE; 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng EAPOL_AUTH_REAUTHENTICATE); 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STEP(REAUTH_TIMER) 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->portControl != Auto || sm->initialize || 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE); 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (sm->reauth_timer_state) { 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case REAUTH_TIMER_INITIALIZE: 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->reAuthWhen == 0) 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(REAUTH_TIMER, REAUTHENTICATE); 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case REAUTH_TIMER_REAUTHENTICATE: 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(REAUTH_TIMER, INITIALIZE); 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Authenticator Key Transmit state machine */ 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64525b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) 64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx); 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65125b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng txKey(); 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->eapKeyAvailable = FALSE; 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyDone = TRUE; 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66125b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STEP(AUTH_KEY_TX) 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initialize || sm->portControl != Auto) { 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT); 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (sm->auth_key_tx_state) { 66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_KEY_TX_NO_KEY_TRANSMIT: 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable && 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA)) 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case AUTH_KEY_TX_KEY_TRANSMIT: 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!sm->keyTxEnabled || !sm->keyRun) 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (sm->eap_if->eapKeyAvailable) 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Key Receive state machine */ 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68725b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(KEY_RX, NO_KEY_RECEIVE) 68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx); 69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69325b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(KEY_RX, KEY_RECEIVE) 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng processKey(); 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->rxKey = FALSE; 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STEP(KEY_RX) 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initialize || !sm->eap_if->portEnabled) { 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (sm->key_rx_state) { 71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case KEY_RX_NO_KEY_RECEIVE: 71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->rxKey) 71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(KEY_RX, KEY_RECEIVE); 71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case KEY_RX_KEY_RECEIVE: 71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->rxKey) 71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(KEY_RX, KEY_RECEIVE); 71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Controlled Directions state machine */ 72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72525b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(CTRL_DIR, FORCE_BOTH) 72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir); 72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->operControlledDirections = Both; 72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73225b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STATE(CTRL_DIR, IN_OR_BOTH) 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir); 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->operControlledDirections = sm->adminControlledDirections; 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73925b3c049e70834cf33790a28643ab058b507b35cBen ChengSM_STEP(CTRL_DIR) 74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initialize) { 74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH); 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (sm->ctrl_dir_state) { 74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case CTRL_DIR_FORCE_BOTH: 74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->portEnabled && sm->operEdge) 74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(CTRL_DIR, IN_OR_BOTH); 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case CTRL_DIR_IN_OR_BOTH: 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->operControlledDirections != 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->adminControlledDirections) 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(CTRL_DIR, IN_OR_BOTH); 75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!sm->eap_if->portEnabled || !sm->operEdge) 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_ENTER(CTRL_DIR, FORCE_BOTH); 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76325b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct eapol_state_machine * 76425b3c049e70834cf33790a28643ab058b507b35cBen Chengeapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int flags, const struct wpabuf *assoc_wps_ie, 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const struct wpabuf *assoc_p2p_ie, void *sta_ctx) 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_state_machine *sm; 76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eap_config eap_conf; 77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol == NULL) 77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm = os_zalloc(sizeof(*sm)); 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm == NULL) { 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation " 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng "failed"); 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->radius_identifier = -1; 78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memcpy(sm->addr, addr, ETH_ALEN); 78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->flags = flags; 78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol = eapol; 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->sta = sta_ctx; 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Set default values for state machine constants */ 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->auth_pae_state = AUTH_PAE_INITIALIZE; 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod; 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax; 79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->be_auth_state = BE_AUTH_INITIALIZE; 79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout; 79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; 79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthPeriod = eapol->conf.eap_reauth_period; 79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; 79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; 80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE; 80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH; 80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portControl = Auto; 80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!eapol->conf.wpa && 80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) 80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyTxEnabled = TRUE; 81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->keyTxEnabled = FALSE; 81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol->conf.wpa) 81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portValid = FALSE; 81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->portValid = TRUE; 81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memset(&eap_conf, 0, sizeof(eap_conf)); 81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_server = eapol->conf.eap_server; 81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.ssl_ctx = eapol->conf.ssl_ctx; 82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.msg_ctx = eapol->conf.msg_ctx; 82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv; 82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key; 82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id; 82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len; 82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info; 82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov; 82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime; 82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time; 82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind; 83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.tnc = eapol->conf.tnc; 83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.wps = eapol->conf.wps; 83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.assoc_wps_ie = assoc_wps_ie; 83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.assoc_p2p_ie = assoc_p2p_ie; 83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.peer_addr = addr; 83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.fragment_size = eapol->conf.fragment_size; 83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_conf.pwd_group = eapol->conf.pwd_group; 83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf); 83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap == NULL) { 83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_free(sm); 84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if = eap_get_interface(sm->eap); 84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_initialize(sm); 84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return sm; 84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 85025b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid eapol_auth_free(struct eapol_state_machine *sm) 85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm == NULL) 85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); 85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap) 85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_server_sm_deinit(sm->eap); 85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(sm); 86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 86325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol, 86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const u8 *addr) 86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr); 86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_sm_step_run(struct eapol_state_machine *sm) 87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_authenticator *eapol = sm->eapol; 87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng u8 addr[ETH_ALEN]; 87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, 87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; 87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int max_steps = 100; 87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memcpy(addr, sm->addr, ETH_ALEN); 87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng * Allow EAPOL state machines to run as long as there are state 88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng * changes, but exit and return here through event loop if more than 88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 100 steps is needed as a precaution against infinite loops inside 88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng * eloop callback. 88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 88625b3c049e70834cf33790a28643ab058b507b35cBen Chengrestart: 88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_auth_pae = sm->auth_pae_state; 88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_be_auth = sm->be_auth_state; 88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_reauth_timer = sm->reauth_timer_state; 89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_auth_key_tx = sm->auth_key_tx_state; 89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_key_rx = sm->key_rx_state; 89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_ctrl_dir = sm->ctrl_dir_state; 89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_STEP_RUN(AUTH_PAE); 89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_STEP_RUN(BE_AUTH); 89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_STEP_RUN(REAUTH_TIMER); 89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_STEP_RUN(AUTH_KEY_TX); 90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_STEP_RUN(KEY_RX); 90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng SM_STEP_RUN(CTRL_DIR); 90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prev_auth_pae != sm->auth_pae_state || 90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_be_auth != sm->be_auth_state || 90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_reauth_timer != sm->reauth_timer_state || 90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_auth_key_tx != sm->auth_key_tx_state || 91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_key_rx != sm->key_rx_state || 91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng prev_ctrl_dir != sm->ctrl_dir_state) { 91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (--max_steps > 0) 91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto restart; 91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Re-run from eloop timeout */ 91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_step(sm); 91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) { 92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eap_server_sm_step(sm->eap)) { 92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (--max_steps > 0) 92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto restart; 92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Re-run from eloop timeout */ 92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_step(sm); 92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* TODO: find a better location for this */ 92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->aaaEapResp) { 93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eap_if->aaaEapResp = FALSE; 93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm->eap_if->aaaEapRespData == NULL) { 93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " 93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng "but no aaaEapRespData available"); 93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.aaa_send( 93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->conf.ctx, sm->sta, 93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpabuf_head(sm->eap_if->aaaEapRespData), 93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng wpabuf_len(sm->eap_if->aaaEapRespData)); 94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol_sm_sta_entry_alive(eapol, addr)) 94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, 94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng EAPOL_AUTH_SM_CHANGE); 94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx) 95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_state_machine *sm = eloop_ctx; 95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_sm_step_run(sm); 95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/** 95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng * eapol_auth_step - Advance EAPOL state machines 95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng * @sm: EAPOL state machine 95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng * 96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng * This function is called to advance EAPOL state machines after any change 96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng * that could affect their state. 96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 96325b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid eapol_auth_step(struct eapol_state_machine *sm) 96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng * Run eapol_sm_step_run from a registered timeout to make sure that 96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng * other possible timeouts/events are processed and to avoid long 96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng * function call chains. 96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL); 97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_initialize(struct eapol_state_machine *sm) 97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->initializing = TRUE; 97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Initialize the state machines by asserting initialize and then 97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng * deasserting it after one step */ 98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->initialize = TRUE; 98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_sm_step_run(sm); 98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->initialize = FALSE; 98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_sm_step_run(sm); 98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng sm->initializing = FALSE; 98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Start one second tick for port timers state machine */ 98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); 98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int eapol_sm_get_eap_user(void *ctx, const u8 *identity, 99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t identity_len, int phase2, 99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eap_user *user) 99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_state_machine *sm = ctx; 99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity, 99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng identity_len, phase2, user); 99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len) 100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_state_machine *sm = ctx; 100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *len = sm->eapol->conf.eap_req_id_text_len; 100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return sm->eapol->conf.eap_req_id_text; 100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct eapol_callbacks eapol_cb = 101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_sm_get_eap_user, 101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_sm_get_eap_req_id_text 101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101725b3c049e70834cf33790a28643ab058b507b35cBen Chengint eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx) 101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sm == NULL || ctx != sm->eap) 102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eap_sm_pending_cb(sm->eap); 102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_step(sm); 102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int eapol_auth_conf_clone(struct eapol_auth_config *dst, 103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_auth_config *src) 103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->ctx = src->ctx; 103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_reauth_period = src->eap_reauth_period; 103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->wpa = src->wpa; 103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->individual_wep_key_len = src->individual_wep_key_len; 103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_server = src->eap_server; 103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->ssl_ctx = src->ssl_ctx; 103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->msg_ctx = src->msg_ctx; 103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_sim_db_priv = src->eap_sim_db_priv; 104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(dst->eap_req_id_text); 104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->pwd_group = src->pwd_group; 104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (src->eap_req_id_text) { 104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len); 104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dst->eap_req_id_text == NULL) 104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memcpy(dst->eap_req_id_text, src->eap_req_id_text, 104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng src->eap_req_id_text_len); 104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_req_id_text_len = src->eap_req_id_text_len; 104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } else { 105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_req_id_text = NULL; 105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_req_id_text_len = 0; 105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (src->pac_opaque_encr_key) { 105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->pac_opaque_encr_key = os_malloc(16); 105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key, 105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16); 105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } else 105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->pac_opaque_encr_key = NULL; 105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (src->eap_fast_a_id) { 106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len); 106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dst->eap_fast_a_id == NULL) { 106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(dst->eap_req_id_text); 106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id, 106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng src->eap_fast_a_id_len); 106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_fast_a_id_len = src->eap_fast_a_id_len; 106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } else 106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_fast_a_id = NULL; 107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (src->eap_fast_a_id_info) { 107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info); 107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dst->eap_fast_a_id_info == NULL) { 107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(dst->eap_req_id_text); 107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(dst->eap_fast_a_id); 107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } else 107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_fast_a_id_info = NULL; 107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_fast_prov = src->eap_fast_prov; 108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->pac_key_lifetime = src->pac_key_lifetime; 108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->pac_key_refresh_time = src->pac_key_refresh_time; 108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind; 108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->tnc = src->tnc; 108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->wps = src->wps; 108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng dst->fragment_size = src->fragment_size; 108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 109025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void eapol_auth_conf_free(struct eapol_auth_config *conf) 109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(conf->eap_req_id_text); 109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng conf->eap_req_id_text = NULL; 109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(conf->pac_opaque_encr_key); 109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng conf->pac_opaque_encr_key = NULL; 109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(conf->eap_fast_a_id); 109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng conf->eap_fast_a_id = NULL; 109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(conf->eap_fast_a_id_info); 109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng conf->eap_fast_a_id_info = NULL; 110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110325b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, 110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_auth_cb *cb) 110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct eapol_authenticator *eapol; 110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol = os_zalloc(sizeof(*eapol)); 110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol == NULL) 111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) { 111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(eapol); 111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (conf->individual_wep_key_len > 0) { 111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* use key0 in individual key and key1 in broadcast key */ 111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->default_wep_key_idx = 1; 112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.eapol_send = cb->eapol_send; 112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.aaa_send = cb->aaa_send; 112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.finished = cb->finished; 112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.get_eap_user = cb->get_eap_user; 112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.sta_entry_alive = cb->sta_entry_alive; 112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.logger = cb->logger; 112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.set_port_authorized = cb->set_port_authorized; 112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.abort_auth = cb->abort_auth; 113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.tx_key = cb->tx_key; 113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol->cb.eapol_event = cb->eapol_event; 113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return eapol; 113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113725b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid eapol_auth_deinit(struct eapol_authenticator *eapol) 113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (eapol == NULL) 114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return; 114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng eapol_auth_conf_free(&eapol->conf); 114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(eapol->default_wep_key); 114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng os_free(eapol); 114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng