18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP Full Authenticator state machine (RFC 4137)
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2007, 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 * This state machine is based on the full authenticator state machine defined
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in RFC 4137. However, to support backend authentication in RADIUS
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication server functionality, parts of backend authenticator (also
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * from RFC 4137) are mixed in. This functionality is enabled by setting
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * backend_auth configuration variable to TRUE.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "state_machine.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DATA struct eap_sm
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "EAP"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_MAX_AUTH_ROUNDS 50
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_user_free(struct eap_user *user);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* EAP state machines are described in RFC 4137 */
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int eapSRTT, int eapRTTVAR,
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int methodTimeout);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_getId(const struct wpabuf *data);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id);
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_nextId(struct eap_sm *sm, int id);
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 size_t len);
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_Policy_getDecision(struct eap_sm *sm);
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (src == NULL)
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(*dst);
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dst = wpabuf_dup(src);
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return *dst ? 0 : -1;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_copy_data(u8 **dst, size_t *dst_len,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 const u8 *src, size_t src_len)
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (src == NULL)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(*dst);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*dst = os_malloc(src_len);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*dst) {
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(*dst, src, src_len);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst_len = src_len;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*dst_len = 0;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_COPY(dst, src) \
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_user_get - Fetch user information from the database
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity: Identity (User-Name) of the user
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity_len: Length of identity in bytes
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to fetch user information for EAP. The user will be
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * selected based on the specified identity. sm->user and
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sm->user_eap_method_index are updated for the new user when a matching user
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is found. sm->user can be used to get user information (e.g., password).
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 int phase2)
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_user *user;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL || sm->eapol_cb == NULL ||
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->eapol_cb->get_eap_user == NULL)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_user_free(sm->user);
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->user = NULL;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	user = os_zalloc(sizeof(*user));
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (user == NULL)
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    return -1;
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       identity_len, phase2, user) != 0) {
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_user_free(user);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->user = user;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->user_eap_method_index = 0;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISABLED)
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISABLED);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds = 0;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, INITIALIZE)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, INITIALIZE);
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (sm->eap_if.eapRestart && !sm->eap_server && sm->identity) {
1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * Need to allow internal Identity method to be used instead
1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * of passthrough at the beginning of reauthentication.
1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eap_server_clear_identity(sm);
1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->currentId = -1;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapSuccess = FALSE;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapFail = FALSE;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapTimeout = FALSE;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eap_if.eapKeyData);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapKeyData = NULL;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapKeyDataLen = 0;
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapKeyAvailable = FALSE;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapRestart = FALSE;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * This is not defined in RFC 4137, but method state needs to be
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * reseted here so that it does not remain in success state when
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * re-authentication starts.
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->eap_method_priv) {
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = NULL;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m = NULL;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->user_eap_method_index = 0;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->backend_auth) {
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->currentMethod = EAP_TYPE_NONE;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* parse rxResp, respId, respMethod */
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->rxResp) {
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->currentId = sm->respId;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds = 0;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->method_pending = METHOD_PENDING_NONE;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR, MAC2STR(sm->peer_addr));
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, PICK_UP_METHOD)
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, PICK_UP_METHOD);
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->currentMethod = sm->respMethod;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m && sm->eap_method_priv) {
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->m->reset(sm, sm->eap_method_priv);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_method_priv = NULL;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  sm->currentMethod);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m && sm->m->initPickUp) {
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_method_priv = sm->m->initPickUp(sm);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->eap_method_priv == NULL) {
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Failed to "
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "initialize EAP method %d",
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   sm->currentMethod);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->m = NULL;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->currentMethod = EAP_TYPE_NONE;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->m = NULL;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->currentMethod = EAP_TYPE_NONE;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"method=%u", sm->currentMethod);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, IDLE)
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, IDLE);
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.retransWhile = eap_sm_calculateTimeout(
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodTimeout);
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RETRANSMIT)
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RETRANSMIT);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->retransCount++;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapReq = TRUE;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RECEIVED)
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RECEIVED);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* parse rxResp, respId, respMethod */
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds++;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISCARD)
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISCARD);
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapResp = FALSE;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapNoReq = TRUE;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SEND_REQUEST)
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SEND_REQUEST);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->retransCount = 0;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if.eapReqData) {
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapResp = FALSE;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapReq = TRUE;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapResp = FALSE;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapReq = FALSE;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapResp = FALSE;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapReq = FALSE;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapNoReq = TRUE;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, INTEGRITY_CHECK)
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, INTEGRITY_CHECK);
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) {
27961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		sm->ignore = TRUE;
28061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m->check) {
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ignore = sm->m->check(sm, sm->eap_method_priv,
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sm->eap_if.eapRespData);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, METHOD_REQUEST)
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, METHOD_REQUEST);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL) {
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: method not initialized");
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->currentId = eap_sm_nextId(sm, sm->currentId);
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->currentId);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastId = sm->currentId;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						sm->currentId);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m->getTimeout)
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodTimeout = 0;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, METHOD_RESPONSE)
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, METHOD_RESPONSE);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
31761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
31861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
31961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m->isDone(sm, sm->eap_method_priv)) {
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_Policy_update(sm, NULL, 0);
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm->eap_if.eapKeyData);
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m->getKey) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapKeyData = sm->m->getKey(
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm, sm->eap_method_priv,
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				&sm->eap_if.eapKeyDataLen);
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapKeyData = NULL;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapKeyDataLen = 0;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodState = METHOD_END;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodState = METHOD_CONTINUE;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, PROPOSE_METHOD)
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int vendor;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EapType type;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, PROPOSE_METHOD);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = eap_sm_Policy_getNextMethod(sm, &vendor);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor == EAP_VENDOR_IETF)
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->currentMethod = type;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->currentMethod = EAP_TYPE_EXPANDED;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->eap_method_priv) {
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = NULL;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m = eap_server_get_eap_method(vendor, type);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m) {
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = sm->m->init(sm);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_method_priv == NULL) {
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "method %d", sm->currentMethod);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->m = NULL;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->currentMethod = EAP_TYPE_NONE;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->currentMethod == EAP_TYPE_IDENTITY ||
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->currentMethod == EAP_TYPE_NOTIFICATION)
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodState = METHOD_CONTINUE;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodState = METHOD_PROPOSED;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"vendor=%u method=%u", vendor, sm->currentMethod);
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, NAK)
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *nak;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = 0;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *nak_list = NULL;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, NAK);
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_method_priv) {
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = NULL;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m = NULL;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
39261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
39361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nak = wpabuf_head(sm->eap_if.eapRespData);
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = be_to_host16(nak->length);
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > wpabuf_len(sm->eap_if.eapRespData))
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = wpabuf_len(sm->eap_if.eapRespData);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (const u8 *) (nak + 1);
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len -= sizeof(*nak);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos == EAP_TYPE_NAK) {
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len--;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			nak_list = pos;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_Policy_update(sm, nak_list, len);
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SELECT_ACTION)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SELECT_ACTION);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->decision = eap_sm_Policy_getDecision(sm);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, TIMEOUT_FAILURE)
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, TIMEOUT_FAILURE);
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapTimeout = TRUE;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, FAILURE)
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, FAILURE);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastReqData);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastReqData = NULL;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapFail = TRUE;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR, MAC2STR(sm->peer_addr));
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SUCCESS)
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SUCCESS);
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastReqData);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastReqData = NULL;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if.eapKeyData)
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapKeyAvailable = TRUE;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapSuccess = TRUE;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR, MAC2STR(sm->peer_addr));
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, INITIALIZE_PASSTHROUGH)
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.aaaEapRespData);
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.aaaEapRespData = NULL;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, IDLE2)
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, IDLE2);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.retransWhile = eap_sm_calculateTimeout(
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodTimeout);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RETRANSMIT2)
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RETRANSMIT2);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->retransCount++;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapReq = TRUE;
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RECEIVED2)
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RECEIVED2);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* parse rxResp, respId, respMethod */
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISCARD2)
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISCARD2);
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapResp = FALSE;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapNoReq = TRUE;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SEND_REQUEST2)
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SEND_REQUEST2);
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->retransCount = 0;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if.eapReqData) {
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapResp = FALSE;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapReq = TRUE;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapResp = FALSE;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_if.eapReq = FALSE;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData");
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapResp = FALSE;
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapReq = FALSE;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapNoReq = TRUE;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, AAA_REQUEST)
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, AAA_REQUEST);
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if.eapRespData == NULL) {
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData");
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * if (respMethod == IDENTITY)
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *	aaaIdentity = eapRespData
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * This is already taken care of by the EAP-Identity method which
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * stores the identity into sm->identity.
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, AAA_RESPONSE)
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, AAA_RESPONSE);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->currentId = eap_sm_getId(sm->eap_if.eapReqData);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodTimeout = sm->eap_if.aaaMethodTimeout;
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, AAA_IDLE)
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, AAA_IDLE);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.aaaFail = FALSE;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.aaaSuccess = FALSE;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.aaaEapReq = FALSE;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.aaaEapNoReq = FALSE;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.aaaEapResp = TRUE;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, TIMEOUT_FAILURE2)
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, TIMEOUT_FAILURE2);
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapTimeout = TRUE;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, FAILURE2)
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, FAILURE2);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapFail = TRUE;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SUCCESS2)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SUCCESS2);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if.aaaEapKeyAvailable) {
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm->eap_if.eapKeyData);
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapKeyData = NULL;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_if.eapKeyDataLen = 0;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_if.eapSuccess = TRUE;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Start reauthentication with identity request even though we know the
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * previously used identity. This is needed to get reauthentication
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * started properly.
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->start_reauth = TRUE;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(EAP)
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_if.eapRestart && sm->eap_if.portEnabled)
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(EAP, INITIALIZE);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (!sm->eap_if.portEnabled)
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(EAP, DISABLED);
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: more than %d "
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "authentication rounds - abort",
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   EAP_MAX_AUTH_ROUNDS);
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->num_rounds++;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER_GLOBAL(EAP, FAILURE);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else switch (sm->EAP_state) {
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INITIALIZE:
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->backend_auth) {
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!sm->rxResp)
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(EAP, SELECT_ACTION);
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else if (sm->rxResp &&
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (sm->respMethod == EAP_TYPE_NAK ||
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (sm->respMethod == EAP_TYPE_EXPANDED &&
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sm->respVendor == EAP_VENDOR_IETF &&
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sm->respVendorMethod == EAP_TYPE_NAK)))
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(EAP, NAK);
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				SM_ENTER(EAP, PICK_UP_METHOD);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SELECT_ACTION);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_PICK_UP_METHOD:
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->currentMethod == EAP_TYPE_NONE) {
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SELECT_ACTION);
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD_RESPONSE);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISABLED:
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if.portEnabled)
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, INITIALIZE);
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDLE:
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if.retransWhile == 0)
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, RETRANSMIT);
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if.eapResp)
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, RECEIVED);
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RETRANSMIT:
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->retransCount > sm->MaxRetrans)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, TIMEOUT_FAILURE);
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, IDLE);
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RECEIVED:
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->rxResp && (sm->respId == sm->currentId) &&
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (sm->respMethod == EAP_TYPE_NAK ||
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     (sm->respMethod == EAP_TYPE_EXPANDED &&
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      sm->respVendor == EAP_VENDOR_IETF &&
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      sm->respVendorMethod == EAP_TYPE_NAK))
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    && (sm->methodState == METHOD_PROPOSED))
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, NAK);
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->rxResp && (sm->respId == sm->currentId) &&
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ((sm->respMethod == sm->currentMethod) ||
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (sm->respMethod == EAP_TYPE_EXPANDED &&
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->respVendor == EAP_VENDOR_IETF &&
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->respVendorMethod == sm->currentMethod)))
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, INTEGRITY_CHECK);
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "rxResp=%d respId=%d currentId=%d "
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "respMethod=%d currentMethod=%d",
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sm->rxResp, sm->respId, sm->currentId,
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sm->respMethod, sm->currentMethod);
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, DISCARD);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISCARD:
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SEND_REQUEST:
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INTEGRITY_CHECK:
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ignore)
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, DISCARD);
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD_RESPONSE);
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_METHOD_REQUEST:
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_REQUEST);
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_METHOD_RESPONSE:
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Note: Mechanism to allow EAP methods to wait while going
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * through pending processing is an extension to RFC 4137
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * which only defines the transits to SELECT_ACTION and
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * METHOD_REQUEST from this METHOD_RESPONSE state.
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->methodState == METHOD_END)
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SELECT_ACTION);
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->method_pending == METHOD_PENDING_WAIT) {
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has pending "
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "processing - wait before proceeding to "
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "METHOD_REQUEST state");
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (sm->method_pending == METHOD_PENDING_CONT) {
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has completed "
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "pending processing - reprocess pending "
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "EAP message");
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->method_pending = METHOD_PENDING_NONE;
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD_RESPONSE);
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD_REQUEST);
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_PROPOSE_METHOD:
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Note: Mechanism to allow EAP methods to wait while going
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * through pending processing is an extension to RFC 4137
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * which only defines the transit to METHOD_REQUEST from this
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * PROPOSE_METHOD state.
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->method_pending == METHOD_PENDING_WAIT) {
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has pending "
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "processing - wait before proceeding to "
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "METHOD_REQUEST state");
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->user_eap_method_index > 0)
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->user_eap_method_index--;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (sm->method_pending == METHOD_PENDING_CONT) {
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has completed "
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "pending processing - reprocess pending "
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "EAP message");
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->method_pending = METHOD_PENDING_NONE;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, PROPOSE_METHOD);
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD_REQUEST);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_NAK:
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SELECT_ACTION);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SELECT_ACTION:
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->decision == DECISION_FAILURE)
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, FAILURE);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->decision == DECISION_SUCCESS)
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SUCCESS);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->decision == DECISION_PASSTHROUGH)
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, PROPOSE_METHOD);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TIMEOUT_FAILURE:
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_FAILURE:
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SUCCESS:
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INITIALIZE_PASSTHROUGH:
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->currentId == -1)
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, AAA_IDLE);
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, AAA_REQUEST);
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDLE2:
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if.eapResp)
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, RECEIVED2);
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if.retransWhile == 0)
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, RETRANSMIT2);
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RETRANSMIT2:
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->retransCount > sm->MaxRetrans)
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, TIMEOUT_FAILURE2);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, IDLE2);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RECEIVED2:
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->rxResp && (sm->respId == sm->currentId))
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, AAA_REQUEST);
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, DISCARD2);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISCARD2:
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE2);
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SEND_REQUEST2:
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE2);
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_AAA_REQUEST:
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, AAA_IDLE);
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_AAA_RESPONSE:
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_REQUEST2);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_AAA_IDLE:
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_if.aaaFail)
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, FAILURE2);
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if.aaaSuccess)
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SUCCESS2);
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if.aaaEapReq)
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, AAA_RESPONSE);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (sm->eap_if.aaaTimeout)
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, TIMEOUT_FAILURE2);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TIMEOUT_FAILURE2:
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_FAILURE2:
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SUCCESS2:
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int eapSRTT, int eapRTTVAR,
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int methodTimeout)
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rto, i;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (methodTimeout) {
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * EAP method (either internal or through AAA server, provided
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * timeout hint. Use that as-is as a timeout for retransmitting
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the EAP request if no response is received.
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(from EAP method hint)", methodTimeout);
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return methodTimeout;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 3748 recommends algorithms described in RFC 2988 for estimation
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * of the retransmission timeout. This should be implemented once
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * round-trip time measurements are available. For nowm a simple
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * backoff mechanism is used instead if there are no EAP method
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * specific hints.
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SRTT = smoothed round-trip time
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RTTVAR = round-trip time variation
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RTO = retransmission timeout
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * initial retransmission and then double the RTO to provide back off
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * modified RTOmax.
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rto = 3;
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < retransCount; i++) {
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rto *= 2;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rto >= 20) {
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rto = 20;
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "(from dynamic back off; retransCount=%d)",
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   rto, retransCount);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return rto;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp)
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *hdr;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t plen;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* parse rxResp, respId, respMethod */
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rxResp = FALSE;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->respId = -1;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->respMethod = EAP_TYPE_NONE;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->respVendor = EAP_VENDOR_IETF;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->respVendorMethod = EAP_TYPE_NONE;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) {
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p "
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "len=%lu", resp,
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   resp ? (unsigned long) wpabuf_len(resp) : 0);
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = wpabuf_head(resp);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = be_to_host16(hdr->length);
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (plen > wpabuf_len(resp)) {
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu plen=%lu)",
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_len(resp),
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) plen);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->respId = hdr->identifier;
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code == EAP_CODE_RESPONSE)
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxResp = TRUE;
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (plen > sizeof(*hdr)) {
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *pos = (u8 *) (hdr + 1);
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->respMethod = *pos++;
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->respMethod == EAP_TYPE_EXPANDED) {
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (plen < sizeof(*hdr) + 8) {
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "expanded EAP-Packet (plen=%lu)",
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned long) plen);
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->respVendor = WPA_GET_BE24(pos);
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 3;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->respVendorMethod = WPA_GET_BE32(pos);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "respMethod=%u respVendor=%u respVendorMethod=%u",
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->rxResp, sm->respId, sm->respMethod, sm->respVendor,
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->respVendorMethod);
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_getId(const struct wpabuf *data)
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *hdr;
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL || wpabuf_len(data) < sizeof(*hdr))
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = wpabuf_head(data);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return hdr->identifier;
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *msg;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *resp;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = wpabuf_alloc(sizeof(*resp));
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(msg, sizeof(*resp));
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->code = EAP_CODE_SUCCESS;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->identifier = id;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->length = host_to_be16(sizeof(*resp));
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id)
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *msg;
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *resp;
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = wpabuf_alloc(sizeof(*resp));
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = wpabuf_put(msg, sizeof(*resp));
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->code = EAP_CODE_FAILURE;
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->identifier = id;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp->length = host_to_be16(sizeof(*resp));
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_nextId(struct eap_sm *sm, int id)
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (id < 0) {
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * random number */
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		id = rand() & 0xff;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (id != sm->lastId)
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return id;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (id + 1) & 0xff;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_process_nak - Process EAP-Response/Nak
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nak_list: Nak list (allowed methods) from the supplicant
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of nak_list in bytes
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when EAP-Response/Nak is received from the
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supplicant. This can happen for both phase 1 and phase 2 authentications.
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len)
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user == NULL)
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "index %d)", sm->user_eap_method_index);
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) sm->user->methods,
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    nak_list, len);
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	i = sm->user_eap_method_index;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (i < EAP_MAX_METHODS &&
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->user->methods[i].method != EAP_TYPE_NONE)) {
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto not_found;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++) {
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (nak_list[j] == sm->user->methods[i].method) {
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (j < len) {
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* found */
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			i++;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	not_found:
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* not found - remove from the list */
10441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (i + 1 < EAP_MAX_METHODS) {
10451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_memmove(&sm->user->methods[i],
10461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   &sm->user->methods[i + 1],
10471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   (EAP_MAX_METHODS - i - 1) *
10481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   sizeof(sm->user->methods[0]));
10491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->user->methods[EAP_MAX_METHODS - 1].vendor =
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			EAP_VENDOR_IETF;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) sm->user->methods, EAP_MAX_METHODS *
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sizeof(sm->user->methods[0]));
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 size_t len)
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (nak_list == NULL || sm == NULL || sm->user == NULL)
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user->phase2) {
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " info was selected - reject");
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->decision = DECISION_FAILURE;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_process_nak(sm, nak_list, len);
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EapType next;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int idx = sm->user_eap_method_index;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* In theory, there should be no problems with starting
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * re-authentication with something else than EAP-Request/Identity and
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * this does indeed work with wpa_supplicant. However, at least Funk
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Supplicant seemed to ignore re-auth if it skipped
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP-Request/Identity.
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Re-auth sets currentId == -1, so that can be used here to select
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * whether Identity needs to be requested again. */
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->identity == NULL || sm->currentId == -1) {
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*vendor = EAP_VENDOR_IETF;
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = EAP_TYPE_IDENTITY;
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->update_user = TRUE;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (sm->user && idx < EAP_MAX_METHODS &&
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[idx].method != EAP_TYPE_NONE)) {
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*vendor = sm->user->methods[idx].vendor;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = sm->user->methods[idx].method;
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->user_eap_method_index++;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*vendor = EAP_VENDOR_IETF;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		next = EAP_TYPE_NONE;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   *vendor, next);
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return next;
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_Policy_getDecision(struct eap_sm *sm)
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->eap_server && sm->identity && !sm->start_reauth) {
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return DECISION_PASSTHROUGH;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->isSuccess(sm, sm->eap_method_priv)) {
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "SUCCESS");
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->update_user = TRUE;
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return DECISION_SUCCESS;
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !sm->m->isSuccess(sm, sm->eap_method_priv)) {
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "FAILURE");
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->update_user = TRUE;
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return DECISION_FAILURE;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((sm->user == NULL || sm->update_user) && sm->identity &&
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !sm->start_reauth) {
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Allow Identity method to be started once to allow identity
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * selection hint to be sent from the authentication server,
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * but prevent a loop of Identity requests by only allowing
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this to happen once.
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int id_req = 0;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[0].method == EAP_TYPE_IDENTITY)
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			id_req = 1;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "found from database -> FAILURE");
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return DECISION_FAILURE;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (id_req && sm->user &&
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->user->methods[0].method == EAP_TYPE_IDENTITY) {
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: getDecision: stop "
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "identity request loop -> FAILURE");
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->update_user = TRUE;
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return DECISION_FAILURE;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->update_user = FALSE;
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->start_reauth = FALSE;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->user->methods[sm->user_eap_method_index].vendor !=
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     EAP_VENDOR_IETF ||
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     sm->user->methods[sm->user_eap_method_index].method !=
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     EAP_TYPE_NONE)) {
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available -> CONTINUE");
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return DECISION_CONTINUE;
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->identity == NULL || sm->currentId == -1) {
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "yet -> CONTINUE");
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return DECISION_CONTINUE;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "FAILURE");
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return DECISION_FAILURE;
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_server_sm_step - Step EAP server state machine
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if EAP state was changed or 0 if not
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function advances EAP state machine to a new state to match with the
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current variables. This should be called whenever variables used by the EAP
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine have changed.
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_sm_step(struct eap_sm *sm)
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res = 0;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->changed = FALSE;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(EAP);
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->changed)
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = 1;
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (sm->changed);
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_user_free(struct eap_user *user)
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (user == NULL)
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(user->password);
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	user->password = NULL;
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(user);
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_server_sm_init - Allocate and initialize EAP server state machine
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol_ctx: Context data to be used with eapol_cb calls
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol_cb: Pointer to EAPOL callback functions
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: EAP configuration
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated EAP state machine or %NULL on failure
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function allocates and initializes an EAP state machine.
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sm * eap_server_sm_init(void *eapol_ctx,
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct eapol_callbacks *eapol_cb,
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct eap_config *conf)
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm;
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_ctx = eapol_ctx;
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb = eapol_cb;
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ssl_ctx = conf->ssl_ctx;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->msg_ctx = conf->msg_ctx;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_sim_db_priv = conf->eap_sim_db_priv;
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->backend_auth = conf->backend_auth;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_server = conf->eap_server;
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->pac_opaque_encr_key) {
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pac_opaque_encr_key = os_malloc(16);
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->pac_opaque_encr_key) {
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->pac_opaque_encr_key,
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  conf->pac_opaque_encr_key, 16);
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->eap_fast_a_id) {
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->eap_fast_a_id) {
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  conf->eap_fast_a_id_len);
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->eap_fast_a_id_info)
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_fast_prov = conf->eap_fast_prov;
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pac_key_lifetime = conf->pac_key_lifetime;
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pac_key_refresh_time = conf->pac_key_refresh_time;
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tnc = conf->tnc;
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->wps = conf->wps;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->assoc_wps_ie)
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->assoc_p2p_ie)
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie);
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->peer_addr)
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->fragment_size = conf->fragment_size;
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pwd_group = conf->pwd_group;
128087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	sm->pbc_in_m1 = conf->pbc_in_m1;
128134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	sm->server_id = conf->server_id;
128234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	sm->server_id_len = conf->server_id_len;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_server_sm_deinit - Deinitialize and free an EAP server state machine
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitializes EAP state machine and frees all allocated
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * resources.
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_server_sm_deinit(struct eap_sm *sm)
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Server state machine removed");
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->eap_method_priv)
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eap_if.eapKeyData);
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastReqData);
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.eapRespData);
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->identity);
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->pac_opaque_encr_key);
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eap_fast_a_id);
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eap_fast_a_id_info);
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.aaaEapReqData);
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eap_if.aaaEapRespData);
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eap_if.aaaEapKeyData);
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_user_free(sm->user);
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->assoc_wps_ie);
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->assoc_p2p_ie);
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_notify_cached - Notify EAP state machine of cached PMK
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when PMKSA caching is used to skip EAP
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication.
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_notify_cached(struct eap_sm *sm)
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->EAP_state = EAP_SUCCESS;
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_pending_cb - EAP state machine callback for a pending EAP request
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when data for a pending EAP-Request is received.
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_pending_cb(struct eap_sm *sm)
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->method_pending == METHOD_PENDING_WAIT)
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->method_pending = METHOD_PENDING_CONT;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_method_pending - Query whether EAP method is waiting for pending data
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if method is waiting for pending data or 0 if not
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_sm_method_pending(struct eap_sm *sm)
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->method_pending == METHOD_PENDING_WAIT;
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_identity - Get the user identity (from EAP-Response/Identity)
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for returning identity length
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the user identity or %NULL if not available
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = sm->identity_len;
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->identity;
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_interface - Get pointer to EAP-EAPOL interface data
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the EAP-EAPOL interface data
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return &sm->eap_if;
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_server_clear_identity - Clear EAP identity information
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to clear the EAP identity information in the EAP
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * server context. This allows the EAP/Identity method to be used again after
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAPOL-Start or EAPOL-Logoff.
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_server_clear_identity(struct eap_sm *sm)
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->identity);
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->identity = NULL;
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1404