1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd / EAP Full Authenticator state machine (RFC 4137)
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This state machine is based on the full authenticator state machine defined
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * in RFC 4137. However, to support backend authentication in RADIUS
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * authentication server functionality, parts of backend authenticator (also
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * from RFC 4137) are mixed in. This functionality is enabled by setting
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * backend_auth configuration variable to TRUE.
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h"
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "state_machine.h"
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define STATE_MACHINE_DATA struct eap_sm
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "EAP"
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_MAX_AUTH_ROUNDS 50
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_user_free(struct eap_user *user);
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* EAP state machines are described in RFC 4137 */
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int eapSRTT, int eapRTTVAR,
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int methodTimeout);
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp);
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_getId(const struct wpabuf *data);
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id);
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id);
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_nextId(struct eap_sm *sm, int id);
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				 size_t len);
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor);
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_Policy_getDecision(struct eap_sm *sm);
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (src == NULL)
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(*dst);
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*dst = wpabuf_dup(src);
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return *dst ? 0 : -1;
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_copy_data(u8 **dst, size_t *dst_len,
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 const u8 *src, size_t src_len)
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (src == NULL)
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(*dst);
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*dst = os_malloc(src_len);
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (*dst) {
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(*dst, src, src_len);
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*dst_len = src_len;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*dst_len = 0;
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define EAP_COPY(dst, src) \
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_user_get - Fetch user information from the database
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @identity: Identity (User-Name) of the user
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @identity_len: Length of identity in bytes
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, or -1 on failure
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function is used to fetch user information for EAP. The user will be
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * selected based on the specified identity. sm->user and
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * sm->user_eap_method_index are updated for the new user when a matching user
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * is found. sm->user can be used to get user information (e.g., password).
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 int phase2)
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_user *user;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm == NULL || sm->eapol_cb == NULL ||
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    sm->eapol_cb->get_eap_user == NULL)
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_user_free(sm->user);
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->user = NULL;
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	user = os_zalloc(sizeof(*user));
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (user == NULL)
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    return -1;
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       identity_len, phase2, user) != 0) {
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eap_user_free(user);
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->user = user;
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->user_eap_method_index = 0;
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, DISABLED)
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, DISABLED);
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->num_rounds = 0;
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, INITIALIZE)
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, INITIALIZE);
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->currentId = -1;
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapSuccess = FALSE;
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapFail = FALSE;
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapTimeout = FALSE;
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->eap_if.eapKeyData);
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapKeyData = NULL;
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapKeyDataLen = 0;
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapKeyAvailable = FALSE;
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapRestart = FALSE;
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * This is not defined in RFC 4137, but method state needs to be
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * reseted here so that it does not remain in success state when
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * re-authentication starts.
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m && sm->eap_method_priv) {
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_method_priv = NULL;
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->m = NULL;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->user_eap_method_index = 0;
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->backend_auth) {
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->currentMethod = EAP_TYPE_NONE;
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* parse rxResp, respId, respMethod */
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->rxResp) {
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->currentId = sm->respId;
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->num_rounds = 0;
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->method_pending = METHOD_PENDING_NONE;
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, PICK_UP_METHOD)
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, PICK_UP_METHOD);
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->currentMethod = sm->respMethod;
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->m && sm->eap_method_priv) {
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->m->reset(sm, sm->eap_method_priv);
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_method_priv = NULL;
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF,
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						  sm->currentMethod);
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->m && sm->m->initPickUp) {
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_method_priv = sm->m->initPickUp(sm);
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (sm->eap_method_priv == NULL) {
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Failed to "
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "initialize EAP method %d",
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   sm->currentMethod);
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				sm->m = NULL;
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				sm->currentMethod = EAP_TYPE_NONE;
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->m = NULL;
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->currentMethod = EAP_TYPE_NONE;
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, IDLE)
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, IDLE);
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.retransWhile = eap_sm_calculateTimeout(
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodTimeout);
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, RETRANSMIT)
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, RETRANSMIT);
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->retransCount++;
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapReq = TRUE;
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, RECEIVED)
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, RECEIVED);
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* parse rxResp, respId, respMethod */
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->num_rounds++;
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, DISCARD)
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, DISCARD);
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapResp = FALSE;
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapNoReq = TRUE;
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, SEND_REQUEST)
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, SEND_REQUEST);
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->retransCount = 0;
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_if.eapReqData) {
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		{
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapResp = FALSE;
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapReq = TRUE;
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapResp = FALSE;
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapReq = FALSE;
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapResp = FALSE;
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapReq = FALSE;
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapNoReq = TRUE;
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, INTEGRITY_CHECK)
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, INTEGRITY_CHECK);
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m->check) {
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->ignore = sm->m->check(sm, sm->eap_method_priv,
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  sm->eap_if.eapRespData);
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, METHOD_REQUEST)
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, METHOD_REQUEST);
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m == NULL) {
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: method not initialized");
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->currentId = eap_sm_nextId(sm, sm->currentId);
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   sm->currentId);
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->lastId = sm->currentId;
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						sm->currentId);
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m->getTimeout)
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodTimeout = 0;
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, METHOD_RESPONSE)
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, METHOD_RESPONSE);
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m->isDone(sm, sm->eap_method_priv)) {
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		eap_sm_Policy_update(sm, NULL, 0);
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(sm->eap_if.eapKeyData);
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->m->getKey) {
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapKeyData = sm->m->getKey(
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				sm, sm->eap_method_priv,
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				&sm->eap_if.eapKeyDataLen);
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapKeyData = NULL;
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapKeyDataLen = 0;
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodState = METHOD_END;
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodState = METHOD_CONTINUE;
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, PROPOSE_METHOD)
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int vendor;
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EapType type;
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, PROPOSE_METHOD);
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	type = eap_sm_Policy_getNextMethod(sm, &vendor);
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (vendor == EAP_VENDOR_IETF)
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->currentMethod = type;
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->currentMethod = EAP_TYPE_EXPANDED;
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m && sm->eap_method_priv) {
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_method_priv = NULL;
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->m = eap_server_get_eap_method(vendor, type);
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m) {
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_method_priv = sm->m->init(sm);
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->eap_method_priv == NULL) {
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "method %d", sm->currentMethod);
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->m = NULL;
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->currentMethod = EAP_TYPE_NONE;
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->currentMethod == EAP_TYPE_IDENTITY ||
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    sm->currentMethod == EAP_TYPE_NOTIFICATION)
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodState = METHOD_CONTINUE;
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodState = METHOD_PROPOSED;
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, NAK)
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const struct eap_hdr *nak;
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len = 0;
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const u8 *pos;
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const u8 *nak_list = NULL;
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, NAK);
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_method_priv) {
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_method_priv = NULL;
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->m = NULL;
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	nak = wpabuf_head(sm->eap_if.eapRespData);
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		len = be_to_host16(nak->length);
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (len > wpabuf_len(sm->eap_if.eapRespData))
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			len = wpabuf_len(sm->eap_if.eapRespData);
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = (const u8 *) (nak + 1);
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		len -= sizeof(*nak);
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == EAP_TYPE_NAK) {
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			len--;
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			nak_list = pos;
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_sm_Policy_update(sm, nak_list, len);
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, SELECT_ACTION)
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, SELECT_ACTION);
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->decision = eap_sm_Policy_getDecision(sm);
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, TIMEOUT_FAILURE)
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, TIMEOUT_FAILURE);
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapTimeout = TRUE;
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, FAILURE)
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, FAILURE);
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId);
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->lastReqData);
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->lastReqData = NULL;
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapFail = TRUE;
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, SUCCESS)
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, SUCCESS);
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId);
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->lastReqData);
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->lastReqData = NULL;
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_if.eapKeyData)
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapKeyAvailable = TRUE;
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapSuccess = TRUE;
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, INITIALIZE_PASSTHROUGH)
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.aaaEapRespData);
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.aaaEapRespData = NULL;
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, IDLE2)
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, IDLE2);
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.retransWhile = eap_sm_calculateTimeout(
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->methodTimeout);
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, RETRANSMIT2)
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, RETRANSMIT2);
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->retransCount++;
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapReq = TRUE;
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, RECEIVED2)
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, RECEIVED2);
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* parse rxResp, respId, respMethod */
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, DISCARD2)
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, DISCARD2);
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapResp = FALSE;
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapNoReq = TRUE;
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, SEND_REQUEST2)
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, SEND_REQUEST2);
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->retransCount = 0;
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_if.eapReqData) {
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		{
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapResp = FALSE;
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapReq = TRUE;
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapResp = FALSE;
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_if.eapReq = FALSE;
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData");
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapResp = FALSE;
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapReq = FALSE;
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapNoReq = TRUE;
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, AAA_REQUEST)
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, AAA_REQUEST);
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_if.eapRespData == NULL) {
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData");
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * if (respMethod == IDENTITY)
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 *	aaaIdentity = eapRespData
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * This is already taken care of by the EAP-Identity method which
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * stores the identity into sm->identity.
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData);
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, AAA_RESPONSE)
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, AAA_RESPONSE);
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->currentId = eap_sm_getId(sm->eap_if.eapReqData);
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->methodTimeout = sm->eap_if.aaaMethodTimeout;
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, AAA_IDLE)
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, AAA_IDLE);
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.aaaFail = FALSE;
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.aaaSuccess = FALSE;
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.aaaEapReq = FALSE;
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.aaaEapNoReq = FALSE;
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.aaaEapResp = TRUE;
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, TIMEOUT_FAILURE2)
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, TIMEOUT_FAILURE2);
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapTimeout = TRUE;
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, FAILURE2)
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, FAILURE2);
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapFail = TRUE;
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STATE(EAP, SUCCESS2)
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SM_ENTRY(EAP, SUCCESS2);
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable;
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_if.aaaEapKeyAvailable) {
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(sm->eap_if.eapKeyData);
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapKeyData = NULL;
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_if.eapKeyDataLen = 0;
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_if.eapSuccess = TRUE;
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Start reauthentication with identity request even though we know the
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * previously used identity. This is needed to get reauthentication
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * started properly.
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->start_reauth = TRUE;
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtSM_STEP(EAP)
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->eap_if.eapRestart && sm->eap_if.portEnabled)
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER_GLOBAL(EAP, INITIALIZE);
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else if (!sm->eap_if.portEnabled)
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER_GLOBAL(EAP, DISABLED);
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: more than %d "
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "authentication rounds - abort",
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   EAP_MAX_AUTH_ROUNDS);
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->num_rounds++;
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER_GLOBAL(EAP, FAILURE);
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else switch (sm->EAP_state) {
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_INITIALIZE:
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->backend_auth) {
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (!sm->rxResp)
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				SM_ENTER(EAP, SELECT_ACTION);
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			else if (sm->rxResp &&
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				 (sm->respMethod == EAP_TYPE_NAK ||
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  (sm->respMethod == EAP_TYPE_EXPANDED &&
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   sm->respVendor == EAP_VENDOR_IETF &&
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   sm->respVendorMethod == EAP_TYPE_NAK)))
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				SM_ENTER(EAP, NAK);
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			else
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				SM_ENTER(EAP, PICK_UP_METHOD);
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, SELECT_ACTION);
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_PICK_UP_METHOD:
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->currentMethod == EAP_TYPE_NONE) {
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, SELECT_ACTION);
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, METHOD_RESPONSE);
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_DISABLED:
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->eap_if.portEnabled)
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, INITIALIZE);
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_IDLE:
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->eap_if.retransWhile == 0)
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, RETRANSMIT);
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->eap_if.eapResp)
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, RECEIVED);
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_RETRANSMIT:
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->retransCount > sm->MaxRetrans)
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, TIMEOUT_FAILURE);
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, IDLE);
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_RECEIVED:
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->rxResp && (sm->respId == sm->currentId) &&
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    (sm->respMethod == EAP_TYPE_NAK ||
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		     (sm->respMethod == EAP_TYPE_EXPANDED &&
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		      sm->respVendor == EAP_VENDOR_IETF &&
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		      sm->respVendorMethod == EAP_TYPE_NAK))
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    && (sm->methodState == METHOD_PROPOSED))
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, NAK);
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->rxResp && (sm->respId == sm->currentId) &&
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 ((sm->respMethod == sm->currentMethod) ||
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  (sm->respMethod == EAP_TYPE_EXPANDED &&
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   sm->respVendor == EAP_VENDOR_IETF &&
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   sm->respVendorMethod == sm->currentMethod)))
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, INTEGRITY_CHECK);
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else {
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "rxResp=%d respId=%d currentId=%d "
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "respMethod=%d currentMethod=%d",
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   sm->rxResp, sm->respId, sm->currentId,
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   sm->respMethod, sm->currentMethod);
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, DISCARD);
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_DISCARD:
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, IDLE);
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_SEND_REQUEST:
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, IDLE);
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_INTEGRITY_CHECK:
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->ignore)
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, DISCARD);
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, METHOD_RESPONSE);
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_METHOD_REQUEST:
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, SEND_REQUEST);
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_METHOD_RESPONSE:
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Note: Mechanism to allow EAP methods to wait while going
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * through pending processing is an extension to RFC 4137
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * which only defines the transits to SELECT_ACTION and
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * METHOD_REQUEST from this METHOD_RESPONSE state.
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->methodState == METHOD_END)
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, SELECT_ACTION);
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->method_pending == METHOD_PENDING_WAIT) {
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has pending "
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "processing - wait before proceeding to "
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "METHOD_REQUEST state");
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (sm->method_pending == METHOD_PENDING_CONT) {
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has completed "
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "pending processing - reprocess pending "
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "EAP message");
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->method_pending = METHOD_PENDING_NONE;
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, METHOD_RESPONSE);
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, METHOD_REQUEST);
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_PROPOSE_METHOD:
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Note: Mechanism to allow EAP methods to wait while going
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * through pending processing is an extension to RFC 4137
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * which only defines the transit to METHOD_REQUEST from this
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * PROPOSE_METHOD state.
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->method_pending == METHOD_PENDING_WAIT) {
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has pending "
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "processing - wait before proceeding to "
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "METHOD_REQUEST state");
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (sm->user_eap_method_index > 0)
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				sm->user_eap_method_index--;
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (sm->method_pending == METHOD_PENDING_CONT) {
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Method has completed "
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "pending processing - reprocess pending "
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "EAP message");
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->method_pending = METHOD_PENDING_NONE;
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, PROPOSE_METHOD);
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, METHOD_REQUEST);
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_NAK:
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, SELECT_ACTION);
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_SELECT_ACTION:
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->decision == DECISION_FAILURE)
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, FAILURE);
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->decision == DECISION_SUCCESS)
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, SUCCESS);
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->decision == DECISION_PASSTHROUGH)
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, PROPOSE_METHOD);
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_TIMEOUT_FAILURE:
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_FAILURE:
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_SUCCESS:
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_INITIALIZE_PASSTHROUGH:
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->currentId == -1)
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, AAA_IDLE);
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, AAA_REQUEST);
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_IDLE2:
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->eap_if.eapResp)
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, RECEIVED2);
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->eap_if.retransWhile == 0)
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, RETRANSMIT2);
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_RETRANSMIT2:
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->retransCount > sm->MaxRetrans)
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, TIMEOUT_FAILURE2);
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, IDLE2);
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_RECEIVED2:
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->rxResp && (sm->respId == sm->currentId))
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, AAA_REQUEST);
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, DISCARD2);
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_DISCARD2:
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, IDLE2);
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_SEND_REQUEST2:
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, IDLE2);
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_AAA_REQUEST:
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, AAA_IDLE);
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_AAA_RESPONSE:
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_ENTER(EAP, SEND_REQUEST2);
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_AAA_IDLE:
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->eap_if.aaaFail)
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, FAILURE2);
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->eap_if.aaaSuccess)
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, SUCCESS2);
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->eap_if.aaaEapReq)
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, AAA_RESPONSE);
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else if (sm->eap_if.aaaTimeout)
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SM_ENTER(EAP, TIMEOUT_FAILURE2);
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_TIMEOUT_FAILURE2:
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_FAILURE2:
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case EAP_SUCCESS2:
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int eapSRTT, int eapRTTVAR,
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int methodTimeout)
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int rto, i;
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (methodTimeout) {
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * EAP method (either internal or through AAA server, provided
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * timeout hint. Use that as-is as a timeout for retransmitting
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * the EAP request if no response is received.
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "(from EAP method hint)", methodTimeout);
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return methodTimeout;
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * RFC 3748 recommends algorithms described in RFC 2988 for estimation
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * of the retransmission timeout. This should be implemented once
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * round-trip time measurements are available. For nowm a simple
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * backoff mechanism is used instead if there are no EAP method
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * specific hints.
821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 *
822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * SRTT = smoothed round-trip time
823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * RTTVAR = round-trip time variation
824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * RTO = retransmission timeout
825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * initial retransmission and then double the RTO to provide back off
830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * modified RTOmax.
832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	rto = 3;
834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < retransCount; i++) {
835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rto *= 2;
836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (rto >= 20) {
837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			rto = 20;
838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "(from dynamic back off; retransCount=%d)",
844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   rto, retransCount);
845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return rto;
847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp)
851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const struct eap_hdr *hdr;
853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t plen;
854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* parse rxResp, respId, respMethod */
856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->rxResp = FALSE;
857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->respId = -1;
858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->respMethod = EAP_TYPE_NONE;
859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->respVendor = EAP_VENDOR_IETF;
860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->respVendorMethod = EAP_TYPE_NONE;
861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) {
863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p "
864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "len=%lu", resp,
865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   resp ? (unsigned long) wpabuf_len(resp) : 0);
866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hdr = wpabuf_head(resp);
870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	plen = be_to_host16(hdr->length);
871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (plen > wpabuf_len(resp)) {
872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "(len=%lu plen=%lu)",
874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) wpabuf_len(resp),
875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) plen);
876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->respId = hdr->identifier;
880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (hdr->code == EAP_CODE_RESPONSE)
882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->rxResp = TRUE;
883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (plen > sizeof(*hdr)) {
885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		u8 *pos = (u8 *) (hdr + 1);
886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->respMethod = *pos++;
887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->respMethod == EAP_TYPE_EXPANDED) {
888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (plen < sizeof(*hdr) + 8) {
889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "expanded EAP-Packet (plen=%lu)",
891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   (unsigned long) plen);
892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				return;
893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->respVendor = WPA_GET_BE24(pos);
895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos += 3;
896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->respVendorMethod = WPA_GET_BE32(pos);
897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "
901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "respMethod=%u respVendor=%u respVendorMethod=%u",
902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   sm->rxResp, sm->respId, sm->respMethod, sm->respVendor,
903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   sm->respVendorMethod);
904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_getId(const struct wpabuf *data)
908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const struct eap_hdr *hdr;
910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data == NULL || wpabuf_len(data) < sizeof(*hdr))
912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hdr = wpabuf_head(data);
915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return hdr->identifier;
917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpabuf *msg;
923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_hdr *resp;
924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	msg = wpabuf_alloc(sizeof(*resp));
927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (msg == NULL)
928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp = wpabuf_put(msg, sizeof(*resp));
930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp->code = EAP_CODE_SUCCESS;
931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp->identifier = id;
932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp->length = host_to_be16(sizeof(*resp));
933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return msg;
935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id)
939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpabuf *msg;
941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_hdr *resp;
942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	msg = wpabuf_alloc(sizeof(*resp));
945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (msg == NULL)
946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp = wpabuf_put(msg, sizeof(*resp));
948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp->code = EAP_CODE_FAILURE;
949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp->identifier = id;
950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	resp->length = host_to_be16(sizeof(*resp));
951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return msg;
953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_nextId(struct eap_sm *sm, int id)
957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (id < 0) {
959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * random number */
961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		id = rand() & 0xff;
962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (id != sm->lastId)
963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return id;
964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return (id + 1) & 0xff;
966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_sm_process_nak - Process EAP-Response/Nak
971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @nak_list: Nak list (allowed methods) from the supplicant
973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @len: Length of nak_list in bytes
974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function is called when EAP-Response/Nak is received from the
976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * supplicant. This can happen for both phase 1 and phase 2 authentications.
977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len)
979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t j;
982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->user == NULL)
984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "index %d)", sm->user_eap_method_index);
988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    (u8 *) sm->user->methods,
991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    nak_list, len);
994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	i = sm->user_eap_method_index;
996526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (i < EAP_MAX_METHODS &&
997526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->user->methods[i].method != EAP_TYPE_NONE)) {
999526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			goto not_found;
1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (j = 0; j < len; j++) {
1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (nak_list[j] == sm->user->methods[i].method) {
1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				break;
1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (j < len) {
1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			/* found */
1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			i++;
1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	not_found:
1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* not found - remove from the list */
1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1],
1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (EAP_MAX_METHODS - i - 1) *
1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   sizeof(sm->user->methods[0]));
1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->user->methods[EAP_MAX_METHODS - 1].vendor =
1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			EAP_VENDOR_IETF;
1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    (u8 *) sm->user->methods, EAP_MAX_METHODS *
1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    sizeof(sm->user->methods[0]));
1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				 size_t len)
1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (nak_list == NULL || sm == NULL || sm->user == NULL)
1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->user->phase2) {
1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   " info was selected - reject");
1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->decision = DECISION_FAILURE;
1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_sm_process_nak(sm, nak_list, len);
1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EapType next;
1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int idx = sm->user_eap_method_index;
1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* In theory, there should be no problems with starting
1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * re-authentication with something else than EAP-Request/Identity and
1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * this does indeed work with wpa_supplicant. However, at least Funk
1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Supplicant seemed to ignore re-auth if it skipped
1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * EAP-Request/Identity.
1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Re-auth sets currentId == -1, so that can be used here to select
1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * whether Identity needs to be requested again. */
1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->identity == NULL || sm->currentId == -1) {
1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*vendor = EAP_VENDOR_IETF;
1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = EAP_TYPE_IDENTITY;
1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->update_user = TRUE;
1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else if (sm->user && idx < EAP_MAX_METHODS &&
1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    sm->user->methods[idx].method != EAP_TYPE_NONE)) {
1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*vendor = sm->user->methods[idx].vendor;
1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = sm->user->methods[idx].method;
1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->user_eap_method_index++;
1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*vendor = EAP_VENDOR_IETF;
1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = EAP_TYPE_NONE;
1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   *vendor, next);
1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return next;
1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_sm_Policy_getDecision(struct eap_sm *sm)
1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!sm->eap_server && sm->identity && !sm->start_reauth) {
1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return DECISION_PASSTHROUGH;
1083526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1084526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1085526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
1086526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    sm->m->isSuccess(sm, sm->eap_method_priv)) {
1087526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
1088526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "SUCCESS");
1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->update_user = TRUE;
1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return DECISION_SUCCESS;
1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !sm->m->isSuccess(sm, sm->eap_method_priv)) {
1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "FAILURE");
1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->update_user = TRUE;
1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return DECISION_FAILURE;
1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((sm->user == NULL || sm->update_user) && sm->identity &&
1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !sm->start_reauth) {
1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Allow Identity method to be started once to allow identity
1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * selection hint to be sent from the authentication server,
1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * but prevent a loop of Identity requests by only allowing
1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * this to happen once.
1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		int id_req = 0;
1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    sm->user->methods[0].method == EAP_TYPE_IDENTITY)
1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			id_req = 1;
1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "found from database -> FAILURE");
1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return DECISION_FAILURE;
1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (id_req && sm->user &&
1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    sm->user->methods[0].method == EAP_TYPE_IDENTITY) {
1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: getDecision: stop "
1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "identity request loop -> FAILURE");
1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->update_user = TRUE;
1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return DECISION_FAILURE;
1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->update_user = FALSE;
1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->start_reauth = FALSE;
1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    (sm->user->methods[sm->user_eap_method_index].vendor !=
1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	     EAP_VENDOR_IETF ||
1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	     sm->user->methods[sm->user_eap_method_index].method !=
1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	     EAP_TYPE_NONE)) {
1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "available -> CONTINUE");
1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return DECISION_CONTINUE;
1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->identity == NULL || sm->currentId == -1) {
1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "yet -> CONTINUE");
1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return DECISION_CONTINUE;
1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "FAILURE");
1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return DECISION_FAILURE;
1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_server_sm_step - Step EAP server state machine
1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 1 if EAP state was changed or 0 if not
1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function advances EAP state machine to a new state to match with the
1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * current variables. This should be called whenever variables used by the EAP
1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * state machine have changed.
1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_server_sm_step(struct eap_sm *sm)
1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res = 0;
1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	do {
1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->changed = FALSE;
1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SM_STEP_RUN(EAP);
1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->changed)
1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			res = 1;
1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} while (sm->changed);
1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return res;
1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_user_free(struct eap_user *user)
1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (user == NULL)
1184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
1185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(user->password);
1186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	user->password = NULL;
1187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(user);
1188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_server_sm_init - Allocate and initialize EAP server state machine
1193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @eapol_ctx: Context data to be used with eapol_cb calls
1194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @eapol_cb: Pointer to EAPOL callback functions
1195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @conf: EAP configuration
1196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to the allocated EAP state machine or %NULL on failure
1197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
1198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function allocates and initializes an EAP state machine.
1199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_sm * eap_server_sm_init(void *eapol_ctx,
1201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   struct eapol_callbacks *eapol_cb,
1202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   struct eap_config *conf)
1203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct eap_sm *sm;
1205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm = os_zalloc(sizeof(*sm));
1207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm == NULL)
1208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
1209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eapol_ctx = eapol_ctx;
1210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eapol_cb = eapol_cb;
1211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
1212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->ssl_ctx = conf->ssl_ctx;
1213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_sim_db_priv = conf->eap_sim_db_priv;
1214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->backend_auth = conf->backend_auth;
1215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_server = conf->eap_server;
1216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conf->pac_opaque_encr_key) {
1217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->pac_opaque_encr_key = os_malloc(16);
1218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->pac_opaque_encr_key) {
1219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(sm->pac_opaque_encr_key,
1220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  conf->pac_opaque_encr_key, 16);
1221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
1222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conf->eap_fast_a_id) {
1224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sm->eap_fast_a_id) {
1226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
1227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  conf->eap_fast_a_id_len);
1228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
1230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
1231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conf->eap_fast_a_id_info)
1232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_fast_prov = conf->eap_fast_prov;
1234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->pac_key_lifetime = conf->pac_key_lifetime;
1235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->pac_key_refresh_time = conf->pac_key_refresh_time;
1236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->tnc = conf->tnc;
1238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->wps = conf->wps;
1239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (conf->assoc_wps_ie)
1240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
1241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
1243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return sm;
1245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_server_sm_deinit - Deinitialize and free an EAP server state machine
1250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
1252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function deinitializes EAP state machine and frees all allocated
1253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * resources.
1254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid eap_server_sm_deinit(struct eap_sm *sm)
1256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm == NULL)
1258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
1259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Server state machine removed");
1260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->m && sm->eap_method_priv)
1261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->m->reset(sm, sm->eap_method_priv);
1262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.eapReqData);
1263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->eap_if.eapKeyData);
1264dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt	wpabuf_free(sm->lastReqData);
1265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.eapRespData);
1266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->identity);
1267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->pac_opaque_encr_key);
1268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->eap_fast_a_id);
1269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->eap_fast_a_id_info);
1270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.aaaEapReqData);
1271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->eap_if.aaaEapRespData);
1272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm->eap_if.aaaEapKeyData);
1273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eap_user_free(sm->user);
1274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpabuf_free(sm->assoc_wps_ie);
1275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(sm);
1276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_sm_notify_cached - Notify EAP state machine of cached PMK
1281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
1283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function is called when PMKSA caching is used to skip EAP
1284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * authentication.
1285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid eap_sm_notify_cached(struct eap_sm *sm)
1287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm == NULL)
1289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
1290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	sm->EAP_state = EAP_SUCCESS;
1292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_sm_pending_cb - EAP state machine callback for a pending EAP request
1297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
1299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function is called when data for a pending EAP-Request is received.
1300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid eap_sm_pending_cb(struct eap_sm *sm)
1302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm == NULL)
1304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
1305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
1306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm->method_pending == METHOD_PENDING_WAIT)
1307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sm->method_pending = METHOD_PENDING_CONT;
1308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_sm_method_pending - Query whether EAP method is waiting for pending data
1313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 1 if method is waiting for pending data or 0 if not
1315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_sm_method_pending(struct eap_sm *sm)
1317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (sm == NULL)
1319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
1320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return sm->method_pending == METHOD_PENDING_WAIT;
1321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_get_identity - Get the user identity (from EAP-Response/Identity)
1326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @len: Buffer for returning identity length
1328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to the user identity or %NULL if not available
1329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtconst u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
1331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*len = sm->identity_len;
1333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return sm->identity;
1334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
1338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_get_interface - Get pointer to EAP-EAPOL interface data
1339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to the EAP-EAPOL interface data
1341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
1342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
1343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
1344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return &sm->eap_if;
1345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1346