18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.1X-2004 Authenticator - EAPOL state machine
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "state_machine.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/eapol_common.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_defs.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_common.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth_sm.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth_sm_i.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DATA struct eapol_state_machine
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_ADDR sm->addr
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_callbacks eapol_cb;
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define setPortAuthorized() \
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1)
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define setPortUnauthorized() \
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* procedures */
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define txReq() eapol_auth_tx_req(sm)
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta)
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta)
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define processKey() do { } while (0)
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_sm_step_run(struct eapol_state_machine *sm);
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_initialize(struct eapol_state_machine *sm);
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_logger(struct eapol_authenticator *eapol,
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const u8 *addr, eapol_logger_level level,
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      const char *txt)
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol->cb.logger == NULL)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.logger(eapol->conf.ctx, addr, level, txt);
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_vlogger(struct eapol_authenticator *eapol,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *addr, eapol_logger_level level,
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const char *fmt, ...)
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *format;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxlen;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	va_list ap;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol->cb.logger == NULL)
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxlen = os_strlen(fmt) + 100;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	format = os_malloc(maxlen);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!format)
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	va_start(ap, fmt);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	vsnprintf(format, maxlen, fmt, ap);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	va_end(ap);
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_logger(eapol, addr, level, format);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(format);
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int success)
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr eap;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eap, 0, sizeof(eap));
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap.identifier = ++sm->last_eap_id;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap.length = host_to_be16(sizeof(eap));
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Sending canned EAP packet %s (identifier %d)",
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   success ? "SUCCESS" : "FAILURE", eap.identifier);
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 IEEE802_1X_TYPE_EAP_PACKET,
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) &eap, sizeof(eap));
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot1xAuthEapolFramesTx++;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_tx_req(struct eapol_state_machine *sm)
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if->eapReqData == NULL ||
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) {
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_auth_logger(sm->eapol, sm->addr,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  EAPOL_LOGGER_DEBUG,
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "TxReq called, but there is no EAP request "
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "from authentication server");
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->flags & EAPOL_SM_WAIT_START) {
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " while waiting for EAPOL-Start",
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(sm->addr));
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Sending EAP Packet (identifier %d)",
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->last_eap_id);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 IEEE802_1X_TYPE_EAP_PACKET,
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 wpabuf_head(sm->eap_if->eapReqData),
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 wpabuf_len(sm->eap_if->eapReqData));
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot1xAuthEapolFramesTx++;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY)
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot1xAuthEapolReqIdFramesTx++;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot1xAuthEapolReqFramesTx++;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eapol_port_timers_tick - Port Timers state machine
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: struct eapol_state_machine *
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: Not used
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This statemachine is implemented as a function that will be called
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * once a second as a registered event loop timeout.
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_state_machine *state = timeout_ctx;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (state->aWhile > 0) {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		state->aWhile--;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state->aWhile == 0) {
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " - aWhile --> 0",
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(state->addr));
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (state->quietWhile > 0) {
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		state->quietWhile--;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state->quietWhile == 0) {
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " - quietWhile --> 0",
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(state->addr));
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (state->reAuthWhen > 0) {
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		state->reAuthWhen--;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state->reAuthWhen == 0) {
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " - reAuthWhen --> 0",
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(state->addr));
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (state->eap_if->retransWhile > 0) {
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		state->eap_if->retransWhile--;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (state->eap_if->retransWhile == 0) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " - (EAP) retransWhile --> 0",
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(state->addr));
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_step_run(state);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Authenticator PAE state machine */
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, INITIALIZE)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->portMode = Auto;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, DISCONNECTED)
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapolLogoff) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authEapLogoffsWhileConnecting++;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthEapLogoffWhileAuthenticated++;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authPortStatus = Unauthorized;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setPortUnauthorized();
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthCount = 0;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolLogoff = FALSE;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!from_initialize) {
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->flags & EAPOL_SM_PREAUTH);
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, RESTART)
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reAuthenticate)
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthReauthsWhileAuthenticated++;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eapolStart)
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthEapStartsWhileAuthenticated++;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eapolLogoff)
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthEapLogoffWhileAuthenticated++;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapRestart = TRUE;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, CONNECTING)
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->authEntersConnecting++;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthenticate = FALSE;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthCount++;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, HELD)
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->authAuthFailWhileAuthenticating++;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authPortStatus = Unauthorized;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setPortUnauthorized();
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->quietWhile = sm->quietPeriod;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolLogoff = FALSE;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING,
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "authentication failed - EAP type: %d (%s)",
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->eap_type_authsrv,
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   eap_server_get_name(0, sm->eap_type_authsrv));
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_type_authsrv != sm->eap_type_supp) {
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Supplicant used different EAP type: "
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "%d (%s)", sm->eap_type_supp,
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   eap_server_get_name(0, sm->eap_type_supp));
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       sm->flags & EAPOL_SM_PREAUTH);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, AUTHENTICATED)
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *extra = "";
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->authAuthSuccessesWhileAuthenticating++;
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authPortStatus = Authorized;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setPortAuthorized();
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthCount = 0;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->flags & EAPOL_SM_PREAUTH)
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		extra = " (pre-authentication)";
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE)
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		extra = " (PMKSA cache)";
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "authenticated - EAP type: %d (%s)%s",
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->eap_type_authsrv,
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   eap_server_get_name(0, sm->eap_type_authsrv),
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   extra);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       sm->flags & EAPOL_SM_PREAUTH);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, AUTHENTICATING)
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolStart = FALSE;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authSuccess = FALSE;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authFail = FALSE;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authTimeout = FALSE;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authStart = TRUE;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->keyRun = FALSE;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->keyDone = FALSE;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, ABORTING)
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->authTimeout)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthTimeoutsWhileAuthenticating++;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eapolStart)
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthEapStartsWhileAuthenticating++;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eapolLogoff)
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->authAuthEapLogoffWhileAuthenticating++;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authAbort = TRUE;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->keyRun = FALSE;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->keyDone = FALSE;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, FORCE_AUTH)
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authPortStatus = Authorized;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setPortAuthorized();
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->portMode = ForceAuthorized;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolStart = FALSE;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	txCannedSuccess();
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_PAE, FORCE_UNAUTH)
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authPortStatus = Unauthorized;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	setPortUnauthorized();
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->portMode = ForceUnauthorized;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolStart = FALSE;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	txCannedFail();
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(AUTH_PAE)
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->initialize || !sm->eap_if->portEnabled)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE);
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->portControl == ForceAuthorized &&
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->portMode != sm->portControl &&
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 !(sm->initialize || !sm->eap_if->portEnabled))
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH);
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->portControl == ForceUnauthorized &&
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->portMode != sm->portControl &&
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 !(sm->initialize || !sm->eap_if->portEnabled))
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH);
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (sm->auth_pae_state) {
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_INITIALIZE:
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(AUTH_PAE, DISCONNECTED);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_DISCONNECTED:
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(AUTH_PAE, RESTART);
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_RESTART:
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!sm->eap_if->eapRestart)
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, CONNECTING);
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_HELD:
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->quietWhile == 0)
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, RESTART);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_CONNECTING:
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, DISCONNECTED);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else if ((sm->eap_if->eapReq &&
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->reAuthCount <= sm->reAuthMax) ||
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sm->eap_if->eapSuccess || sm->eap_if->eapFail)
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, AUTHENTICATING);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_AUTHENTICATED:
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eapolStart || sm->reAuthenticate)
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, RESTART);
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else if (sm->eapolLogoff || !sm->portValid)
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, DISCONNECTED);
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_AUTHENTICATING:
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->authSuccess && sm->portValid)
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, AUTHENTICATED);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else if (sm->authFail ||
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (sm->keyDone && !sm->portValid))
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, HELD);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else if (sm->eapolStart || sm->eapolLogoff ||
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sm->authTimeout)
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, ABORTING);
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_ABORTING:
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eapolLogoff && !sm->authAbort)
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, DISCONNECTED);
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else if (!sm->eapolLogoff && !sm->authAbort)
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, RESTART);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_FORCE_AUTH:
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eapolStart)
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, FORCE_AUTH);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case AUTH_PAE_FORCE_UNAUTH:
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eapolStart)
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Backend Authentication state machine */
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, INITIALIZE)
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	abortAuth();
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapNoReq = FALSE;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authAbort = FALSE;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, REQUEST)
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	txReq();
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapReq = FALSE;
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->backendOtherRequestsToSupplicant++;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * it looks like this would be logical thing to do there since the old
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP response would not be valid anymore after the new EAP request
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * was sent out.
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * A race condition has been reported, in which hostapd ended up
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * sending out EAP-Response/Identity as a response to the first
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP-Request from the main EAP method. This can be avoided by
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * clearing eapolEap here.
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolEap = FALSE;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, RESPONSE)
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authTimeout = FALSE;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapolEap = FALSE;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapNoReq = FALSE;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->aWhile = sm->serverTimeout;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapResp = TRUE;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* sendRespToServer(); */
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->backendResponses++;
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, SUCCESS)
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	txReq();
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authSuccess = TRUE;
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->keyRun = TRUE;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, FAIL)
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	txReq();
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authFail = TRUE;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, TIMEOUT)
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authTimeout = TRUE;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, IDLE)
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->authStart = FALSE;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(BE_AUTH, IGNORE)
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapNoReq = FALSE;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(BE_AUTH)
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE);
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->be_auth_state) {
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_INITIALIZE:
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(BE_AUTH, IDLE);
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_REQUEST:
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eapolEap)
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, RESPONSE);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapReq)
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, REQUEST);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapTimeout)
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, TIMEOUT);
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_RESPONSE:
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if->eapNoReq)
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, IGNORE);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if->eapReq) {
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->backendAccessChallenges++;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, REQUEST);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (sm->aWhile == 0)
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, TIMEOUT);
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapFail) {
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->backendAuthFails++;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, FAIL);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (sm->eap_if->eapSuccess) {
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->backendAuthSuccesses++;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, SUCCESS);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_SUCCESS:
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(BE_AUTH, IDLE);
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_FAIL:
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(BE_AUTH, IDLE);
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_TIMEOUT:
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(BE_AUTH, IDLE);
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_IDLE:
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if->eapFail && sm->authStart)
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, FAIL);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapReq && sm->authStart)
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, REQUEST);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapSuccess && sm->authStart)
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, SUCCESS);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case BE_AUTH_IGNORE:
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eapolEap)
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, RESPONSE);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapReq)
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, REQUEST);
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapTimeout)
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(BE_AUTH, TIMEOUT);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Reauthentication Timer state machine */
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(REAUTH_TIMER, INITIALIZE)
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthWhen = sm->reAuthPeriod;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(REAUTH_TIMER, REAUTHENTICATE)
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthenticate = TRUE;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  EAPOL_AUTH_REAUTHENTICATE);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(REAUTH_TIMER)
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->portControl != Auto || sm->initialize ||
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE);
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->reauth_timer_state) {
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case REAUTH_TIMER_INITIALIZE:
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reAuthWhen == 0)
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case REAUTH_TIMER_REAUTHENTICATE:
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(REAUTH_TIMER, INITIALIZE);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Authenticator Key Transmit state machine */
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	txKey();
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if->eapKeyAvailable = FALSE;
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->keyDone = TRUE;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(AUTH_KEY_TX)
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initialize || sm->portControl != Auto) {
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT);
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->auth_key_tx_state) {
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case AUTH_KEY_TX_NO_KEY_TRANSMIT:
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA))
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case AUTH_KEY_TX_KEY_TRANSMIT:
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->keyTxEnabled || !sm->keyRun)
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if->eapKeyAvailable)
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Key Receive state machine */
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(KEY_RX, NO_KEY_RECEIVE)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(KEY_RX, KEY_RECEIVE)
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	processKey();
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rxKey = FALSE;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(KEY_RX)
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initialize || !sm->eap_if->portEnabled) {
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->key_rx_state) {
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case KEY_RX_NO_KEY_RECEIVE:
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->rxKey)
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(KEY_RX, KEY_RECEIVE);
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case KEY_RX_KEY_RECEIVE:
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->rxKey)
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(KEY_RX, KEY_RECEIVE);
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Controlled Directions state machine */
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(CTRL_DIR, FORCE_BOTH)
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->operControlledDirections = Both;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(CTRL_DIR, IN_OR_BOTH)
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->operControlledDirections = sm->adminControlledDirections;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(CTRL_DIR)
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initialize) {
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->ctrl_dir_state) {
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CTRL_DIR_FORCE_BOTH:
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if->portEnabled && sm->operEdge)
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(CTRL_DIR, IN_OR_BOTH);
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CTRL_DIR_IN_OR_BOTH:
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->operControlledDirections !=
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->adminControlledDirections)
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(CTRL_DIR, IN_OR_BOTH);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->eap_if->portEnabled || !sm->operEdge)
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(CTRL_DIR, FORCE_BOTH);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eapol_state_machine *
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 int flags, const struct wpabuf *assoc_wps_ie,
76061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		 const struct wpabuf *assoc_p2p_ie, void *sta_ctx,
76161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		 const char *identity, const char *radius_cui)
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_state_machine *sm;
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_config eap_conf;
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol == NULL)
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL) {
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation "
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failed");
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->radius_identifier = -1;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->addr, addr, ETH_ALEN);
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->flags = flags;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol = eapol;
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->sta = sta_ctx;
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set default values for state machine constants */
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->auth_pae_state = AUTH_PAE_INITIALIZE;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->be_auth_state = BE_AUTH_INITIALIZE;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthPeriod = eapol->conf.eap_reauth_period;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->portControl = Auto;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!eapol->conf.wpa &&
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->keyTxEnabled = TRUE;
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->keyTxEnabled = FALSE;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol->conf.wpa)
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->portValid = FALSE;
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->portValid = TRUE;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eap_conf, 0, sizeof(eap_conf));
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_server = eapol->conf.eap_server;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.msg_ctx = eapol->conf.msg_ctx;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.tnc = eapol->conf.tnc;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.wps = eapol->conf.wps;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.assoc_wps_ie = assoc_wps_ie;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.assoc_p2p_ie = assoc_p2p_ie;
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.peer_addr = addr;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.fragment_size = eapol->conf.fragment_size;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_conf.pwd_group = eapol->conf.pwd_group;
83287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	eap_conf.pbc_in_m1 = eapol->conf.pbc_in_m1;
83334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_conf.server_id = eapol->conf.server_id;
83434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	eap_conf.server_id_len = eapol->conf.server_id_len;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap == NULL) {
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_auth_free(sm);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if = eap_get_interface(sm->eap);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_initialize(sm);
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
84461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (identity) {
84561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sm->identity = (u8 *) os_strdup(identity);
84661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (sm->identity)
84761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			sm->identity_len = os_strlen(identity);
84861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
84961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (radius_cui)
85061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sm->radius_cui = wpabuf_alloc_copy(radius_cui,
85161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						   os_strlen(radius_cui));
85261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eapol_auth_free(struct eapol_state_machine *sm)
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap)
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_server_sm_deinit(sm->eap);
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *addr)
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_sm_step_run(struct eapol_state_machine *sm)
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_authenticator *eapol = sm->eapol;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 addr[ETH_ALEN];
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int max_steps = 100;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(addr, sm->addr, ETH_ALEN);
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Allow EAPOL state machines to run as long as there are state
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * changes, but exit and return here through event loop if more than
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * 100 steps is needed as a precaution against infinite loops inside
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eloop callback.
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtrestart:
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_auth_pae = sm->auth_pae_state;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_be_auth = sm->be_auth_state;
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_reauth_timer = sm->reauth_timer_state;
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_auth_key_tx = sm->auth_key_tx_state;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_key_rx = sm->key_rx_state;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev_ctrl_dir = sm->ctrl_dir_state;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_STEP_RUN(AUTH_PAE);
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(BE_AUTH);
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(REAUTH_TIMER);
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(AUTH_KEY_TX);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(KEY_RX);
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(CTRL_DIR);
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev_auth_pae != sm->auth_pae_state ||
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    prev_be_auth != sm->be_auth_state ||
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    prev_reauth_timer != sm->reauth_timer_state ||
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    prev_auth_key_tx != sm->auth_key_tx_state ||
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    prev_key_rx != sm->key_rx_state ||
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    prev_ctrl_dir != sm->ctrl_dir_state) {
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (--max_steps > 0)
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto restart;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Re-run from eloop timeout */
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_auth_step(sm);
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_server_sm_step(sm->eap)) {
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (--max_steps > 0)
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto restart;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Re-run from eloop timeout */
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_auth_step(sm);
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: find a better location for this */
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if->aaaEapResp) {
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if->aaaEapResp = FALSE;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eap_if->aaaEapRespData == NULL) {
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "but no aaaEapRespData available");
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eapol->cb.aaa_send(
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->eapol->conf.ctx, sm->sta,
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_head(sm->eap_if->aaaEapRespData),
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_len(sm->eap_if->aaaEapRespData));
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_sm_sta_entry_alive(eapol, addr))
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  EAPOL_AUTH_SM_CHANGE);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_state_machine *sm = eloop_ctx;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_step_run(sm);
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eapol_auth_step - Advance EAPOL state machines
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: EAPOL state machine
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to advance EAPOL state machines after any change
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that could affect their state.
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eapol_auth_step(struct eapol_state_machine *sm)
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Run eapol_sm_step_run from a registered timeout to make sure that
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * other possible timeouts/events are processed and to avoid long
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * function call chains.
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_initialize(struct eapol_state_machine *sm)
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->initializing = TRUE;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initialize the state machines by asserting initialize and then
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * deasserting it after one step */
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->initialize = TRUE;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_step_run(sm);
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->initialize = FALSE;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_step_run(sm);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->initializing = FALSE;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Start one second tick for port timers state machine */
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 size_t identity_len, int phase2,
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct eap_user *user)
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_state_machine *sm = ctx;
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity,
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  identity_len, phase2, user);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_state_machine *sm = ctx;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = sm->eapol->conf.eap_req_id_text_len;
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol->conf.eap_req_id_text;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_callbacks eapol_cb =
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_get_eap_user,
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_get_eap_req_id_text
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (sm == NULL || ctx == NULL || ctx != sm->eap)
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_pending_cb(sm->eap);
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_step(sm);
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_auth_conf_clone(struct eapol_auth_config *dst,
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct eapol_auth_config *src)
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->ctx = src->ctx;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->eap_reauth_period = src->eap_reauth_period;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->wpa = src->wpa;
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->individual_wep_key_len = src->individual_wep_key_len;
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->eap_server = src->eap_server;
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->ssl_ctx = src->ssl_ctx;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->msg_ctx = src->msg_ctx;
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->eap_sim_db_priv = src->eap_sim_db_priv;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dst->eap_req_id_text);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->pwd_group = src->pwd_group;
104987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	dst->pbc_in_m1 = src->pbc_in_m1;
105034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	dst->server_id = src->server_id;
105134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	dst->server_id_len = src->server_id_len;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (src->eap_req_id_text) {
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dst->eap_req_id_text == NULL)
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  src->eap_req_id_text_len);
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_req_id_text_len = src->eap_req_id_text_len;
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_req_id_text = NULL;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_req_id_text_len = 0;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (src->pac_opaque_encr_key) {
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->pac_opaque_encr_key = os_malloc(16);
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  16);
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->pac_opaque_encr_key = NULL;
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (src->eap_fast_a_id) {
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dst->eap_fast_a_id == NULL) {
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(dst->eap_req_id_text);
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  src->eap_fast_a_id_len);
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_fast_a_id = NULL;
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (src->eap_fast_a_id_info) {
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dst->eap_fast_a_id_info == NULL) {
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(dst->eap_req_id_text);
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(dst->eap_fast_a_id);
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dst->eap_fast_a_id_info = NULL;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->eap_fast_prov = src->eap_fast_prov;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->pac_key_lifetime = src->pac_key_lifetime;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->pac_key_refresh_time = src->pac_key_refresh_time;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->tnc = src->tnc;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->wps = src->wps;
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dst->fragment_size = src->fragment_size;
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_auth_conf_free(struct eapol_auth_config *conf)
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conf->eap_req_id_text);
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->eap_req_id_text = NULL;
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conf->pac_opaque_encr_key);
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->pac_opaque_encr_key = NULL;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conf->eap_fast_a_id);
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->eap_fast_a_id = NULL;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conf->eap_fast_a_id_info);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->eap_fast_a_id_info = NULL;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct eapol_auth_cb *cb)
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_authenticator *eapol;
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol = os_zalloc(sizeof(*eapol));
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol == NULL)
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(eapol);
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->individual_wep_key_len > 0) {
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* use key0 in individual key and key1 in broadcast key */
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol->default_wep_key_idx = 1;
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.eapol_send = cb->eapol_send;
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.aaa_send = cb->aaa_send;
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.finished = cb->finished;
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.get_eap_user = cb->get_eap_user;
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.sta_entry_alive = cb->sta_entry_alive;
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.logger = cb->logger;
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.set_port_authorized = cb->set_port_authorized;
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.abort_auth = cb->abort_auth;
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.tx_key = cb->tx_key;
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol->cb.eapol_event = cb->eapol_event;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eapol;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eapol_auth_deinit(struct eapol_authenticator *eapol)
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol == NULL)
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_auth_conf_free(&eapol->conf);
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eapol->default_wep_key);
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eapol);
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1156