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