18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer state machines (RFC 4137)
304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This file implements the Peer State Machine as defined in RFC 4137. The used
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * states and state transitions match mostly with the RFC. However, there are
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * couple of additional transitions for working around small issues noticed
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * during testing. These exceptions are explained in comments within the
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * functions in this file. The method functions, m.func(), are similar to the
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ones used in RFC 4137, but some small changes have used here to optimize
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * operations and to add functionality needed for fast re-authentication
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (session resumption).
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pcsc_funcs.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "state_machine.h"
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "ext_password.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_wsc_common.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DATA struct eap_sm
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define STATE_MACHINE_DEBUG_PREFIX "EAP"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_MAX_AUTH_ROUNDS 50
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_CLIENT_TIMEOUT_DEFAULT 60
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  EapType method);
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processIdentity(struct eap_sm *sm,
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const struct wpabuf *req);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req);
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNotify(int id);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_method_state_txt(EapMethodState state);
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_decision_txt(EapDecision decision);
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   Boolean value)
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_int(sm->eapol_ctx, var);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  unsigned int value)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_eapReqData(sm->eapol_ctx);
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void eap_notify_status(struct eap_sm *sm, const char *status,
8604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      const char *parameter)
8704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
8804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Status notification: %s (param=%s)",
8904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   status, parameter);
9004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sm->eapol_cb->notify_status)
9104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
9204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
9304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
9404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_free(sm->ext_pw_buf);
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw_buf = NULL;
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL || sm->eap_method_priv == NULL)
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m->deinit(sm, sm->eap_method_priv);
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eap_method_priv = NULL;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->m = NULL;
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_allowed_method - Check whether EAP method is allowed
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @method: EAP type
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = allowed EAP method, 0 = not allowed
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *m;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL || config->eap_methods == NULL)
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	m = config->eap_methods;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     m[i].method != EAP_TYPE_NONE; i++) {
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m[i].vendor == vendor && m[i].method == method)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state initializes state machine variables when the machine is
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * activated (portEnabled = TRUE). This is also used when re-starting
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication (eapRestart == TRUE).
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, INITIALIZE)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, INITIALIZE);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !sm->prev_failure) {
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "fast reauthentication");
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_deinit_prev_method(sm, "INITIALIZE");
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->selectedMethod = EAP_TYPE_NONE;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodState = METHOD_NONE;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->allowNotifications = TRUE;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->decision = DECISION_FAIL;
1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapFail, FALSE);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eapKeyData);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapKeyData = NULL;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapKeyAvailable = FALSE;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastId = -1; /* new session - make sure this does not match with
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  * the first EAP-Packet */
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not reset eapResp and eapNoResp here. However, this
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * seemed to be able to trigger cases where both were set and if EAPOL
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state machine uses eapNoResp first, it may end up not sending a real
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * reply correctly. This occurred when the workaround in FAIL state set
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * something else(?)
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapResp, FALSE);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds = 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->prev_failure = 0;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is reached whenever service from the lower layer is interrupted
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * occurs when the port becomes enabled.
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISABLED)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISABLED);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds = 0;
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/*
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * RFC 4137 does not describe clearing of idleWhile here, but doing so
19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * allows the timer tick to be stopped more quickly when EAP is not in
19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 * use.
19661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 */
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	eapol_set_int(sm, EAPOL_idleWhile, 0);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The state machine spends most of its time here, waiting for something to
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SEND_RESPONSE states.
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, IDLE)
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, IDLE);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered when an EAP packet is received (eapReq == TRUE) to
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parse the packet header.
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RECEIVED)
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpabuf *eapReqData;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RECEIVED);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_parseEapReq(sm, eapReqData);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->num_rounds++;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered when a request for a new type comes in. Either the
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * correct method is started, or a Nak response is built.
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, GET_METHOD)
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reinit;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EapType method;
23604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	const struct eap_method *eap_method;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, GET_METHOD);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->reqMethod == EAP_TYPE_EXPANDED)
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		method = sm->reqVendorMethod;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		method = sm->reqMethod;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
24604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqVendor, method);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"vendor=%u method=%u -> NAK",
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendor, method);
25304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "refuse proposed method",
25404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  eap_method ?  eap_method->name : "unknown");
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto nak;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"vendor=%u method=%u", sm->reqVendor, method);
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	eap_notify_status(sm, "accept proposed method",
26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  eap_method ?  eap_method->name : "unknown");
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not define specific operation for fast
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * re-authentication (session resumption). The design here is to allow
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * the previously used method data to be maintained for
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * re-authentication if the method support session resumption.
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Otherwise, the previously used method data is freed and a new method
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * is allocated here.
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->fast_reauth &&
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m && sm->m->vendor == sm->reqVendor &&
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->method == method &&
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->has_reauth_data &&
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " for fast re-authentication");
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reinit = 1;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_deinit_prev_method(sm, "GET_METHOD");
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reinit = 0;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->selectedMethod = sm->reqMethod;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL)
28604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sm->m = eap_method;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->m) {
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "vendor %d method %d",
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqVendor, method);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto nak;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "vendor %u method %u (%s)",
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->reqVendor, method, sm->m->name);
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (reinit)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = sm->m->init_for_reauth(
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, sm->eap_method_priv);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_method_priv = sm->m->init(sm);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eap_method_priv == NULL) {
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct eap_peer_config *config = eap_get_config(sm);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO,
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"EAP: Failed to initialize EAP method: vendor %u "
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"method %u (%s)",
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendor, method, sm->m->name);
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->m = NULL;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->methodState = METHOD_NONE;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->selectedMethod = EAP_TYPE_NONE;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reqMethod == EAP_TYPE_TLS && config &&
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (config->pending_req_pin ||
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     config->pending_req_passphrase)) {
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Return without generating Nak in order to allow
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * entering of PIN code or passphrase to retry the
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * current EAP packet.
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "request - skip Nak");
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto nak;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodState = METHOD_INIT;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP vendor %u method %u (%s) selected",
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->reqVendor, method, sm->m->name);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnak:
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = eap_sm_buildNak(sm, sm->reqId);
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The method processing happens here. The request from the authenticator is
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * processed, and an appropriate response packet is built.
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, METHOD)
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *eapReqData;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_ret ret;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, METHOD);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL) {
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(eapReqData, 1))
36061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Get ignore, methodState, decision, allowNotifications, and
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapRespData. RFC 4137 uses three separate method procedure (check,
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * process, and buildResp) in this state. These have been combined into
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * a single function call to m->process() in order to optimize EAP
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * method implementation interface a bit. These procedures are only
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * used from within this METHOD state, so there is no need to keep
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * these as separate C functions.
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * The RFC 4137 procedures return values as follows:
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * ignore = m.check(eapReqData)
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (methodState, decision, allowNotifications) = m.process(eapReqData)
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapRespData = m.buildResp(reqId)
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ret, 0, sizeof(ret));
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.ignore = sm->ignore;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.methodState = sm->methodState;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.decision = sm->decision;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret.allowNotifications = sm->allowNotifications;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 eapReqData);
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "methodState=%s decision=%s",
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ret.ignore ? "TRUE" : "FALSE",
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eap_sm_method_state_txt(ret.methodState),
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eap_sm_decision_txt(ret.decision));
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ignore = ret.ignore;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ignore)
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->methodState = ret.methodState;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->decision = ret.decision;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->allowNotifications = ret.allowNotifications;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m->isKeyAvailable && sm->m->getKey &&
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm->eapKeyData);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       &sm->eapKeyDataLen);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state signals the lower layer that a response packet is ready to be
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sent.
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SEND_RESPONSE)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SEND_RESPONSE);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastRespData);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapRespData) {
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->workaround)
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->last_md5, sm->req_md5, 16);
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->lastId = sm->reqId;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->lastRespData = wpabuf_dup(sm->eapRespData);
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_set_bool(sm, EAPOL_eapResp, TRUE);
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->lastRespData = NULL;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state signals the lower layer that the request was discarded, and no
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response packet will be sent at this time.
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, DISCARD)
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, DISCARD);
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Handles requests for Identity method and builds a response.
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, IDENTITY)
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpabuf *eapReqData;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, IDENTITY);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
44961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(eapReqData, 1))
45061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_processIdentity(sm, eapReqData);
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Handles requests for Notification method and builds a response.
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, NOTIFICATION)
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct wpabuf *eapReqData;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, NOTIFICATION);
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapReqData = eapol_get_eapReqData(sm);
46761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (!eap_hdr_len_valid(eapReqData, 1))
46861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_processNotify(sm, eapReqData);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = eap_sm_buildNotify(sm->reqId);
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state retransmits the previous response packet.
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, RETRANSMIT)
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, RETRANSMIT);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->lastRespData)
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapRespData = wpabuf_dup(sm->lastRespData);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapRespData = NULL;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered in case of a successful completion of authentication
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and state machine waits here until port is disabled or EAP authentication is
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * restarted.
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, SUCCESS)
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, SUCCESS);
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapKeyData != NULL)
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapKeyAvailable = TRUE;
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not clear eapReq here, but this seems to be required
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to avoid processing the same request twice when state machine is
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * initialized.
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not set eapNoResp here, but this seems to be required
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to get EAPOL Supplicant backend state machine into SUCCESS state. In
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * addition, either eapResp or eapNoResp is required to be set after
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * processing the received EAP frame.
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication completed successfully");
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This state is entered in case of a failure and state machine waits here
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * until port is disabled or EAP authentication is restarted.
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STATE(EAP, FAILURE)
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	SM_ENTRY(EAP, FAILURE);
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapFail, TRUE);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not clear eapReq here, but this seems to be required
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to avoid processing the same request twice when state machine is
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * initialized.
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 does not set eapNoResp here. However, either eapResp or
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapNoResp is required to be set after processing the received EAP
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * frame.
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication failed");
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->prev_failure = 1;
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * At least Microsoft IAS and Meetinghouse Aegis seem to be sending
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAP-Success/Failure with lastId + 1 even though RFC 3748 and
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 4137 require that reqId == lastId. In addition, it looks like
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Accept this kind of Id if EAP workarounds are enabled. These are
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * unauthenticated plaintext messages, so this should have minimal
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * security implications (bit easier to fake EAP-Success/Failure).
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       reqId == ((lastId + 2) & 0xff))) {
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "identifier field in EAP Success: "
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "reqId=%d lastId=%d (these are supposed to be "
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "same)", reqId, lastId);
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "lastId=%d", reqId, lastId);
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_step_idle(struct eap_sm *sm)
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * The first three transitions are from RFC 4137. The last two are
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * local additions to handle special cases with LEAP and PEAP server
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * not sending EAP-Success in some cases.
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_get_bool(sm, EAPOL_eapReq))
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, RECEIVED);
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision != DECISION_FAIL) ||
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision == DECISION_UNCOND_SUCC))
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (eapol_get_bool(sm, EAPOL_altReject) ||
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision != DECISION_UNCOND_SUCC) ||
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (eapol_get_bool(sm, EAPOL_altAccept) &&
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->methodState != METHOD_CONT &&
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sm->decision == DECISION_FAIL))
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, FAILURE);
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->selectedMethod == EAP_TYPE_LEAP &&
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->leap_done && sm->decision != DECISION_FAIL &&
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->methodState == METHOD_DONE)
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->selectedMethod == EAP_TYPE_PEAP &&
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->peap_done && sm->decision != DECISION_FAIL &&
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->methodState == METHOD_DONE)
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peer_req_is_duplicate(struct eap_sm *sm)
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int duplicate;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->workaround && duplicate &&
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * RFC 4137 uses (reqId == lastId) as the only verification for
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * duplicate EAP requests. However, this misses cases where the
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * AS is incorrectly using the same id again; and
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * unfortunately, such implementations exist. Use MD5 hash as
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * an extra verification for the packets being duplicate to
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * workaround these issues.
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but "
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "EAP packets were not identical");
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a "
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "duplicate packet");
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		duplicate = 0;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return duplicate;
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_step_received(struct eap_sm *sm)
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int duplicate = eap_peer_req_is_duplicate(sm);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Two special cases below for LEAP are local additions to work around
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * odd LEAP behavior (EAP-Success in the middle of authentication and
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * then swapped roles). Other transitions are based on RFC 4137.
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->reqId == sm->lastId ||
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     eap_success_workaround(sm, sm->reqId, sm->lastId)))
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SUCCESS);
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->methodState != METHOD_CONT &&
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 ((sm->rxFailure &&
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->decision != DECISION_UNCOND_SUCC) ||
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  (sm->rxSuccess && sm->decision == DECISION_FAIL &&
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (sm->selectedMethod != EAP_TYPE_LEAP ||
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->methodState != METHOD_MAY_CONT))) &&
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (sm->reqId == sm->lastId ||
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  eap_success_workaround(sm, sm->reqId, sm->lastId)))
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, FAILURE);
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && duplicate)
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, RETRANSMIT);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod == EAP_TYPE_NOTIFICATION &&
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->allowNotifications)
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, NOTIFICATION);
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->selectedMethod == EAP_TYPE_NONE &&
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod == EAP_TYPE_IDENTITY)
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDENTITY);
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->selectedMethod == EAP_TYPE_NONE &&
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod != EAP_TYPE_IDENTITY &&
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod != EAP_TYPE_NOTIFICATION)
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, GET_METHOD);
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->rxReq && !duplicate &&
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->reqMethod == sm->selectedMethod &&
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 sm->methodState != METHOD_DONE)
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, METHOD);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->selectedMethod == EAP_TYPE_LEAP &&
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (sm->rxSuccess || sm->rxResp))
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, METHOD);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, DISCARD);
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_step_local(struct eap_sm *sm)
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->EAP_state) {
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INITIALIZE:
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISABLED:
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eapol_get_bool(sm, EAPOL_portEnabled) &&
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !sm->force_disabled)
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, INITIALIZE);
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDLE:
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_sm_step_idle(sm);
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RECEIVED:
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_sm_step_received(sm);
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_GET_METHOD:
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->selectedMethod == sm->reqMethod)
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, METHOD);
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SEND_RESPONSE);
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_METHOD:
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ignore)
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, DISCARD);
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER(EAP, SEND_RESPONSE);
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SEND_RESPONSE:
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISCARD:
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, IDLE);
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDENTITY:
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_NOTIFICATION:
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RETRANSMIT:
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER(EAP, SEND_RESPONSE);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SUCCESS:
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_FAILURE:
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtSM_STEP(EAP)
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Global transitions */
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_get_bool(sm, EAPOL_eapRestart) &&
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    eapol_get_bool(sm, EAPOL_portEnabled))
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(EAP, INITIALIZE);
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_ENTER_GLOBAL(EAP, DISABLED);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RFC 4137 does not place any limit on number of EAP messages
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * in an authentication session. However, some error cases have
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * ended up in a state were EAP messages were sent between the
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * peer and server in a loop (e.g., TLS ACK frame in both
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * direction). Since this is quite undesired outcome, limit the
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * total number of EAP round-trips and abort authentication if
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this limit is exceeded.
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"authentication rounds - abort",
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				EAP_MAX_AUTH_ROUNDS);
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->num_rounds++;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			SM_ENTER_GLOBAL(EAP, FAILURE);
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Local transitions */
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_peer_sm_step_local(sm);
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  EapType method)
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!eap_allowed_method(sm, vendor, method)) {
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "vendor %u method %u", vendor, method);
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return FALSE;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_peer_get_eap_method(vendor, method))
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TRUE;
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: not included in build: "
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "vendor %u method %u", vendor, method);
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return FALSE;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_build_expanded_nak(
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm, int id, const struct eap_method *methods,
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count)
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *m;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 3748 - 5.3.2: Expanded Nak */
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be24(resp, EAP_VENDOR_IETF);
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be32(resp, EAP_TYPE_NAK);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = methods; m; m = m->next) {
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reqVendor == m->vendor &&
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    sm->reqVendorMethod == m->method)
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue; /* do not allow the current method again */
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_allowed_method(sm, m->vendor, m->method)) {
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: allowed type: "
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "vendor=%u method=%u",
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   m->vendor, m->method);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_be24(resp, m->vendor);
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_put_be32(resp, m->method);
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found++;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found) {
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be24(resp, EAP_VENDOR_IETF);
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be32(resp, EAP_TYPE_NONE);
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_update_len(resp);
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id)
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *start;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int found = 0, expanded_found = 0;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t count;
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *methods, *m;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "vendor=%u method=%u not allowed)", sm->reqMethod,
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sm->reqVendor, sm->reqVendorMethod);
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods = eap_peer_get_methods(&count);
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (methods == NULL)
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->reqMethod == EAP_TYPE_EXPANDED)
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return eap_sm_build_expanded_nak(sm, id, methods, count);
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 3748 - 5.3.1: Legacy Nak */
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     sizeof(struct eap_hdr) + 1 + count + 1,
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     EAP_CODE_RESPONSE, id);
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = wpabuf_put(resp, 0);
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = methods; m; m = m->next) {
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue; /* do not allow the current method again */
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_allowed_method(sm, m->vendor, m->method)) {
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (m->vendor != EAP_VENDOR_IETF) {
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (expanded_found)
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					continue;
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				expanded_found = 1;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_put_u8(resp, m->method);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found++;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found)
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(resp, EAP_TYPE_NONE);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found);
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_update_len(resp);
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
88661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *pos;
88761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t msg_len;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication started");
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
89261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req,
89361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       &msg_len);
89461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (pos == NULL)
89561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
89661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * RFC 3748 - 5.1: Identity
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Data field may contain a displayable message in UTF-8. If this
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * includes NUL-character, only the data before that should be
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * displayed. Some EAP implementasitons may piggy-back additional
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * options after the NUL.
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could save displayable message so that it can be shown to the
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * user in case of interaction is required */
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
90761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  pos, msg_len);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
912c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
913c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt/*
914c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Rules for figuring out MNC length based on IMSI for SIM cards that do not
915c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * include MNC length field.
916c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */
917c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int mnc_len_from_imsi(const char *imsi)
918c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
919c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	char mcc_str[4];
920c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	unsigned int mcc;
921c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
922c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memcpy(mcc_str, imsi, 3);
923c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mcc_str[3] = '\0';
924c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mcc = atoi(mcc_str);
925c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
926c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mcc == 244)
927c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 2; /* Networks in Finland use 2-digit MNC */
928c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
929c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return -1;
930c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
931c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
932c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
933c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
934c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    size_t max_len, size_t *imsi_len)
935c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
936c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int mnc_len;
937c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	char *pos, mnc[4];
938c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
939c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (*imsi_len + 36 > max_len) {
940c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
941c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
942c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
943c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
944c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	/* MNC (2 or 3 digits) */
945c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mnc_len = scard_get_mnc_len(sm->scard_ctx);
946c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mnc_len < 0)
947c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc_len = mnc_len_from_imsi(imsi);
948c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mnc_len < 0) {
949c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
950c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   "assuming 3");
951c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc_len = 3;
952c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
953c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
954c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (mnc_len == 2) {
955c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[0] = '0';
956c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[1] = imsi[3];
957c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[2] = imsi[4];
958c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	} else if (mnc_len == 3) {
959c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[0] = imsi[3];
960c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[1] = imsi[4];
961c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		mnc[2] = imsi[5];
962c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
963c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	mnc[3] = '\0';
964c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
965c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	pos = imsi + *imsi_len;
966c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	pos += os_snprintf(pos, imsi + max_len - pos,
967c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
968c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   mnc, imsi[0], imsi[1], imsi[2]);
969c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	*imsi_len = pos - imsi;
970c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
971c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
972c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
973c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
974c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_imsi_identity(struct eap_sm *sm,
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct eap_peer_config *conf)
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
97804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	enum { EAP_SM_SIM, EAP_SM_AKA, EAP_SM_AKA_PRIME } method = EAP_SM_SIM;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[100];
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t imsi_len;
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *m = conf->eap_methods;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	imsi_len = sizeof(imsi);
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
992c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (imsi_len < 7) {
993c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_WARNING, "Too short IMSI for SIM identity");
994c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
995c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
996c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
997c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
998c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
999c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
1000c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
1001c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "IMSI + realm", (u8 *) imsi, imsi_len);
1002c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  m[i].method != EAP_TYPE_NONE); i++) {
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (m[i].vendor == EAP_VENDOR_IETF &&
100604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    m[i].method == EAP_TYPE_AKA_PRIME) {
100704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			method = EAP_SM_AKA_PRIME;
100804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
100904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
101004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
101104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (m[i].vendor == EAP_VENDOR_IETF &&
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    m[i].method == EAP_TYPE_AKA) {
101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			method = EAP_SM_AKA;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conf->identity);
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->identity = os_malloc(1 + imsi_len);
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->identity == NULL) {
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "IMSI-based identity");
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SM_SIM:
102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		conf->identity[0] = '1';
102904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
103004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SM_AKA:
103104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		conf->identity[0] = '0';
103204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
103304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SM_AKA_PRIME:
103404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		conf->identity[0] = '6';
103504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conf->identity + 1, imsi, imsi_len);
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conf->identity_len = 1 + imsi_len;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1042c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_set_scard_pin(struct eap_sm *sm,
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct eap_peer_config *conf)
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_set_pin(sm->scard_ctx, conf->pin)) {
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Make sure the same PIN is not tried again in order to avoid
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * blocking SIM.
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conf->pin);
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conf->pin = NULL;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "PIN validation failed");
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_pin(sm);
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PCSC_FUNCS */
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sm_get_scard_identity(struct eap_sm *sm,
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct eap_peer_config *conf)
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sm_set_scard_pin(sm, conf))
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eap_sm_imsi_identity(sm, conf);
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* PCSC_FUNCS */
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the packet
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function allocates and builds an EAP-Identity/Response packet for the
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current network. The caller is responsible for freeing the returned data.
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *identity;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t identity_len;
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL) {
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "was not available");
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->m->get_identity &&
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (identity = sm->m->get_identity(sm, sm->eap_method_priv,
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &identity_len)) != NULL) {
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "identity", identity, identity_len);
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (!encrypted && config->anonymous_identity) {
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity = config->anonymous_identity;
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity_len = config->anonymous_identity_len;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  identity, identity_len);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity = config->identity;
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		identity_len = config->identity_len;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  identity, identity_len);
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (identity == NULL) {
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configuration was not available");
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->pcsc) {
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eap_sm_get_scard_identity(sm, config) < 0)
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return NULL;
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			identity = config->identity;
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			identity_len = config->identity_len;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "IMSI", identity, identity_len);
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sm_request_identity(sm);
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (config->pcsc) {
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sm_set_scard_pin(sm, config) < 0)
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     EAP_CODE_RESPONSE, id);
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(resp, identity, identity_len);
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *msg;
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i, msg_len;
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req,
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &msg_len);
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  pos, msg_len);
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = os_malloc(msg_len + 1);
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < msg_len; i++)
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg[msg_len] = '\0';
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_EVENT_EAP_NOTIFICATION, msg);
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(msg);
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sm_buildNotify(int id)
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     EAP_CODE_RESPONSE, id);
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL)
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *hdr;
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t plen;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqId = 0;
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqMethod = EAP_TYPE_NONE;
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqVendor = EAP_VENDOR_IETF;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqVendorMethod = EAP_TYPE_NONE;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL || wpabuf_len(req) < sizeof(*hdr))
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = wpabuf_head(req);
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = be_to_host16(hdr->length);
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (plen > wpabuf_len(req)) {
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu plen=%lu)",
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) wpabuf_len(req),
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) plen);
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->reqId = hdr->identifier;
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->workaround) {
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *addr[1];
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		addr[0] = wpabuf_head(req);
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md5_vector(1, addr, &plen, sm->req_md5);
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_REQUEST:
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (plen < sizeof(*hdr) + 1) {
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "no Type field");
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxReq = TRUE;
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (const u8 *) (hdr + 1);
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->reqMethod = *pos++;
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->reqMethod == EAP_TYPE_EXPANDED) {
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (plen < sizeof(*hdr) + 8) {
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "expanded EAP-Packet (plen=%lu)",
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   (unsigned long) plen);
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendor = WPA_GET_BE24(pos);
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 3;
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqVendorMethod = WPA_GET_BE32(pos);
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "method=%u vendor=%u vendorMethod=%u",
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqId, sm->reqMethod, sm->reqVendor,
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sm->reqVendorMethod);
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_RESPONSE:
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->selectedMethod == EAP_TYPE_LEAP) {
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * LEAP differs from RFC 4137 by using reversed roles
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * for mutual authentication and because of this, we
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * need to accept EAP-Response frames if LEAP is used.
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (plen < sizeof(*hdr) + 1) {
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "EAP: Too short "
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "EAP-Response - no Type field");
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->rxResp = TRUE;
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos = (const u8 *) (hdr + 1);
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->reqMethod = *pos;
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "LEAP method=%d id=%d",
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   sm->reqMethod, sm->reqId);
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_SUCCESS:
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
127504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "completion", "success");
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxSuccess = TRUE;
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_FAILURE:
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
128004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "completion", "failure");
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rxFailure = TRUE;
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "code %d", hdr->code);
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  union tls_event_data *data)
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm = ctx;
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *hash_hex = NULL;
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (ev) {
129804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case TLS_CERT_CHAIN_SUCCESS:
129904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "remote certificate verification",
130004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  "success");
130104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_CERT_CHAIN_FAILURE:
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"reason=%d depth=%d subject='%s' err='%s'",
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.reason,
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.depth,
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.subject,
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->cert_fail.reason_txt);
130904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eap_notify_status(sm, "remote certificate verification",
131004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  data->cert_fail.reason_txt);
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TLS_PEER_CERTIFICATE:
1313c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		if (!sm->eapol_cb->notify_cert)
1314c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			break;
1315c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->peer_cert.hash) {
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t len = data->peer_cert.hash_len * 2 + 1;
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hash_hex = os_malloc(len);
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (hash_hex) {
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_snprintf_hex(hash_hex, len,
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 data->peer_cert.hash,
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 data->peer_cert.hash_len);
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1325c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
1326c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		sm->eapol_cb->notify_cert(sm->eapol_ctx,
1327c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					  data->peer_cert.depth,
1328c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					  data->peer_cert.subject,
1329c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					  hash_hex, data->peer_cert.cert);
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
133104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case TLS_ALERT:
133204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (data->alert.is_local)
133304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			eap_notify_status(sm, "local TLS alert",
133404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  data->alert.description);
133504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		else
133604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			eap_notify_status(sm, "remote TLS alert",
133704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					  data->alert.description);
133804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(hash_hex);
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_sm_init - Allocate and initialize EAP peer state machine
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol_ctx: Context data to be used with eapol_cb calls
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol_cb: Pointer to EAPOL callback functions
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_ctx: Context data for wpa_msg() calls
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: EAP configuration
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated EAP state machine or %NULL on failure
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function allocates and initializes an EAP state machine. In addition,
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this initializes TLS library for the new EAP state machine. eapol_cb pointer
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine. Consequently, the caller must make sure that this data
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * structure remains alive while the EAP state machine is active.
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sm * eap_peer_sm_init(void *eapol_ctx,
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 struct eapol_callbacks *eapol_cb,
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 void *msg_ctx, struct eap_config *conf)
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sm *sm;
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tls_config tlsconf;
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_ctx = eapol_ctx;
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb = eapol_cb;
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->msg_ctx = msg_ctx;
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->wps = conf->wps;
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&tlsconf, 0, sizeof(tlsconf));
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.opensc_engine_path = conf->opensc_engine_path;
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_FIPS
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.fips_mode = 1;
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_FIPS */
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.event_cb = eap_peer_sm_tls_event;
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsconf.cb_ctx = sm;
13841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tlsconf.cert_in_cb = conf->cert_in_cb;
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ssl_ctx = tls_init(&tlsconf);
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ssl_ctx == NULL) {
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "context.");
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm);
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
139304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	sm->ssl_ctx2 = tls_init(&tlsconf);
139404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sm->ssl_ctx2 == NULL) {
139504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_INFO, "SSL: Failed to initialize TLS "
139604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "context (2).");
139704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/* Run without separate TLS context within TLS tunnel */
139804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
139904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitializes EAP state machine and frees all allocated
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * resources.
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_sm_deinit(struct eap_sm *sm)
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_deinit_prev_method(sm, "EAP deinit");
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sm_abort(sm);
141704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (sm->ssl_ctx2)
141804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		tls_deinit(sm->ssl_ctx2);
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_deinit(sm->ssl_ctx);
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_sm_step - Step EAP peer state machine
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if EAP state was changed or 0 if not
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function advances EAP state machine to a new state to match with the
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current variables. This should be called whenever variables used by the EAP
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine have changed.
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_sm_step(struct eap_sm *sm)
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res = 0;
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->changed = FALSE;
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SM_STEP_RUN(EAP);
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->changed)
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = 1;
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (sm->changed);
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return res;
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_abort - Abort EAP authentication
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Release system resources that have been allocated for the authentication
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * session without fully deinitializing the EAP state machine.
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_abort(struct eap_sm *sm)
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->lastRespData);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->lastRespData = NULL;
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(sm->eapRespData);
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->eapKeyData);
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapKeyData = NULL;
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* This is not clearly specified in the EAP statemachines draft, but
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * it seems necessary to make sure that some of the EAPOL variables get
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * cleared for the next authentication. */
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_state_txt(int state)
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_INITIALIZE:
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INITIALIZE";
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISABLED:
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "DISABLED";
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDLE:
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDLE";
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RECEIVED:
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "RECEIVED";
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_GET_METHOD:
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "GET_METHOD";
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_METHOD:
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "METHOD";
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SEND_RESPONSE:
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SEND_RESPONSE";
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_DISCARD:
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "DISCARD";
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_IDENTITY:
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "IDENTITY";
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_NOTIFICATION:
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "NOTIFICATION";
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_RETRANSMIT:
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "RETRANSMIT";
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_SUCCESS:
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "SUCCESS";
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_FAILURE:
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "FAILURE";
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_method_state_txt(EapMethodState state)
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (state) {
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_NONE:
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "NONE";
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_INIT:
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "INIT";
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_CONT:
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "CONT";
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_MAY_CONT:
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "MAY_CONT";
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case METHOD_DONE:
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "DONE";
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sm_decision_txt(EapDecision decision)
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (decision) {
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case DECISION_FAIL:
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "FAIL";
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case DECISION_COND_SUCC:
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "COND_SUCC";
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case DECISION_UNCOND_SUCC:
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNCOND_SUCC";
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_get_status - Get EAP state machine status
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf.
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query EAP state machine for status information. This function fills in a
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * text area with current status information from the EAPOL state machine. If
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the buffer (buf) is not large enough, status information will be truncated
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to fit the buffer.
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, ret;
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(buf, buflen,
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "EAP state=%s\n",
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  eap_sm_state_txt(sm->EAP_state));
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 0 || (size_t) len >= buflen)
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->selectedMethod != EAP_TYPE_NONE) {
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const char *name;
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m) {
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			name = sm->m->name;
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const struct eap_method *m =
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eap_peer_get_eap_method(EAP_VENDOR_IETF,
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							sm->selectedMethod);
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (m)
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				name = m->name;
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				name = "?";
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(buf + len, buflen - len,
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "selectedMethod=%d (EAP-%s)\n",
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->selectedMethod, name);
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || (size_t) ret >= buflen - len)
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return len;
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->m && sm->m->get_status) {
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len += sm->m->get_status(sm, sm->eap_method_priv,
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 buf + len, buflen - len,
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 verbose);
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (verbose) {
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(buf + len, buflen - len,
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "reqMethod=%d\n"
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "methodState=%s\n"
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "decision=%s\n"
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  "ClientTimeout=%d\n",
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->reqMethod,
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  eap_sm_method_state_txt(sm->methodState),
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  eap_sm_decision_txt(sm->decision),
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->ClientTimeout);
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || (size_t) ret >= buflen - len)
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return len;
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return len;
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
16181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const char *msg, size_t msglen)
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config;
16221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *txt = NULL, *tmp;
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config = eap_get_config(sm);
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	switch (field) {
16311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_IDENTITY:
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_identity++;
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSWORD:
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_password++;
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_new_password++;
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PIN:
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_pin++;
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_OTP:
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg) {
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = os_malloc(msglen + 3);
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tmp == NULL)
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp[0] = '[';
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(tmp + 1, msg, msglen);
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp[msglen + 1] = ']';
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp[msglen + 2] = '\0';
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			txt = tmp;
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(config->pending_req_otp);
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			config->pending_req_otp = tmp;
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			config->pending_req_otp_len = msglen + 3;
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (config->pending_req_otp == NULL)
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			txt = config->pending_req_otp;
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case WPA_CTRL_REQ_EAP_PASSPHRASE:
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		config->pending_req_passphrase++;
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapol_cb->eap_param_needed)
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * eap_sm_get_method_name(struct eap_sm *sm)
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m == NULL)
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return "UNKNOWN";
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->m->name;
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_identity - Request identity from user (ctrl_iface)
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request identity information for the
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current network. This is normally called when the identity is not included
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in the network configuration. The request will be sent to monitor programs
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * through the control interface.
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_identity(struct eap_sm *sm)
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_password - Request password from user (ctrl_iface)
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request password information for the
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current network. This is normally called when the password is not included
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in the network configuration. The request will be sent to monitor programs
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * through the control interface.
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_password(struct eap_sm *sm)
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_new_password - Request new password from user (ctrl_iface)
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request new password information for
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the current network. This is normally called when the EAP method indicates
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the current password has expired and password change is required. The
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * request will be sent to monitor programs through the control interface.
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_new_password(struct eap_sm *sm)
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request SIM or smart card PIN
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information for the current network. This is normally called when the PIN is
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not included in the network configuration. The request will be sent to
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * monitor programs through the control interface.
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_pin(struct eap_sm *sm)
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PIN, NULL, 0);
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_otp - Request one time password from user (ctrl_iface)
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Message to be displayed to the user when asking for OTP
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_len: Length of the user displayable message
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request open time password (OTP) for
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the current network. The request will be sent to monitor programs through
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the control interface.
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_OTP, msg, msg_len);
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP methods can call this function to request passphrase for a private key
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the current network. This is normally called when the passphrase is not
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * included in the network configuration. The request will be sent to monitor
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * programs through the control interface.
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_request_passphrase(struct eap_sm *sm)
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSPHRASE, NULL, 0);
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_notify_ctrl_attached - Notification of attached monitor
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify EAP state machines that a monitor was attached to the control
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface to trigger re-sending of pending requests for user input.
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sm_notify_ctrl_attached(struct eap_sm *sm)
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Re-send any pending requests for user data since a new control
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * interface was added. This handles cases where the EAP authentication
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * starts immediately after system startup when the user interface is
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * not yet running. */
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_identity)
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_identity(sm);
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_password)
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_password(sm);
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_new_password)
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_new_password(sm);
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_otp)
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_otp(sm, NULL, 0);
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_pin)
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_pin(sm);
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config->pending_req_passphrase)
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sm_request_passphrase(sm);
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_allowed_phase2_type(int vendor, int type)
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vendor != EAP_VENDOR_IETF)
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		type != EAP_TYPE_FAST;
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: EAP method name, e.g., MD5
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @vendor: Buffer for returning EAP Vendor-Id
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: EAP method type or %EAP_TYPE_NONE if not found
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function maps EAP type names into EAP type numbers that are allowed for
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-PEAP, EAP-TTLS, and EAP-FAST.
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu32 eap_get_phase2_type(const char *name, int *vendor)
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int v;
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type = eap_peer_get_type(name, &v);
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_allowed_phase2_type(v, type)) {
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*vendor = v;
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return type;
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*vendor = EAP_VENDOR_IETF;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_TYPE_NONE;
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_phase2_types - Get list of allowed EAP phase 2 types
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to a network configuration
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @count: Pointer to a variable to be filled with number of returned EAP types
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated type list or %NULL on failure
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function generates an array of allowed EAP phase 2 (tunneled) types for
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the given network configuration.
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      size_t *count)
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method_type *buf;
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 method;
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int vendor;
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t mcount;
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_method *methods, *m;
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	methods = eap_peer_get_methods(&mcount);
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (methods == NULL)
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*count = 0;
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(mcount * sizeof(struct eap_method_type));
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (m = methods; m; m = m->next) {
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		vendor = m->vendor;
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		method = m->method;
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_allowed_phase2_type(vendor, method)) {
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (vendor == EAP_VENDOR_IETF &&
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    method == EAP_TYPE_TLS && config &&
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    config->private_key2 == NULL)
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[*count].vendor = vendor;
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[*count].method = method;
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(*count)++;
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_fast_reauth - Update fast_reauth setting
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_fast_reauth(struct eap_sm *sm, int enabled)
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->fast_reauth = enabled;
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_workaround - Update EAP workarounds setting
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->workaround = workaround;
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config - Get current network configuration
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the current network configuration or %NULL if not found
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer methods should avoid using this function if they can use other
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * access functions, like eap_get_config_identity() and
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_password(), that do not require direct access to
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct eap_peer_config.
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_peer_config * eap_get_config(struct eap_sm *sm)
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_config(sm->eapol_ctx);
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_identity - Get identity from the network configuration
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the identity
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the identity or %NULL if not found
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->identity_len;
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->identity;
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
193861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int eap_get_ext_password(struct eap_sm *sm,
193961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				struct eap_peer_config *config)
194061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
194161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *name;
194261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
194361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (config->password == NULL)
194461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
194561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
194661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	name = os_zalloc(config->password_len + 1);
194761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (name == NULL)
194861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
194961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memcpy(name, config->password, config->password_len);
195061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
195161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_free(sm->ext_pw_buf);
195261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
195361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(name);
195461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
195561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return sm->ext_pw_buf == NULL ? -1 : 0;
195661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
195761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
195861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_password - Get password from the network configuration
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the password
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the password or %NULL if not found
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
197061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
197161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
197261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_get_ext_password(sm, config) < 0)
197361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return NULL;
197461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		*len = wpabuf_len(sm->ext_pw_buf);
197561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return wpabuf_head(sm->ext_pw_buf);
197661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
197761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->password_len;
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->password;
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_password2 - Get password from the network configuration
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the password
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hash: Buffer for returning whether the password is stored as a
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NtPasswordHash instead of plaintext password; can be %NULL if this
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * information is not needed
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the password or %NULL if not found
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
199761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
199861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
199961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_get_ext_password(sm, config) < 0)
200061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return NULL;
200161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		*len = wpabuf_len(sm->ext_pw_buf);
200261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return wpabuf_head(sm->ext_pw_buf);
200361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
200461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->password_len;
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hash)
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->password;
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_new_password - Get new password from network configuration
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the new password
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the new password or %NULL if not found
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->new_password_len;
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->new_password;
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_otp - Get one-time password from the network configuration
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for the length of the one-time password
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the one-time password or %NULL if not found
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = config->otp_len;
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->otp;
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_clear_config_otp - Clear used one-time password
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function clears a used one-time password (OTP) from the current network
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configuration. This should be called when the OTP has been used and is not
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed anymore.
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_clear_config_otp(struct eap_sm *sm)
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(config->otp, 0, config->otp_len);
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(config->otp);
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->otp = NULL;
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	config->otp_len = 0;
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_phase1 - Get phase1 data from the network configuration
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the phase1 data or %NULL if not found
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * eap_get_config_phase1(struct eap_sm *sm)
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->phase1;
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_phase2 - Get phase2 data from the network configuration
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the phase1 data or %NULL if not found
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * eap_get_config_phase2(struct eap_sm *sm)
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->phase2;
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_get_config_fragment_size(struct eap_sm *sm)
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_peer_config *config = eap_get_config(sm);
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config == NULL)
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return config->fragment_size;
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_key_available - Get key availability (eapKeyAvailable variable)
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if EAP keying material is available, 0 if not
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_key_available(struct eap_sm *sm)
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm ? sm->eapKeyAvailable : 0;
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_notify_success - Notify EAP state machine about external success trigger
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when external event, e.g., successful completion of
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA-PSK key handshake, is indicating that EAP state machine should move to
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * success state. This is mainly used with security modes that do not use EAP
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state machine (e.g., WPA-PSK).
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_notify_success(struct eap_sm *sm)
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm) {
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->decision = DECISION_COND_SUCC;
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->EAP_state = EAP_SUCCESS;
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_notify_lower_layer_success - Notification of lower layer success
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify EAP state machines that a lower layer has detected a successful
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication. This is used to recover from dropped EAP-Success messages.
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_notify_lower_layer_success(struct eap_sm *sm)
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->decision == DECISION_FAIL ||
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->methodState != METHOD_MAY_CONT &&
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     sm->methodState != METHOD_DONE))
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->eapKeyData != NULL)
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapKeyAvailable = TRUE;
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"EAP authentication completed successfully (based on lower "
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"layer success)");
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Pointer to variable that will be set to number of bytes in the key
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the EAP keying data or %NULL on failure
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * key is available only after a successful authentication. EAP state machine
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * continues to manage the key data and the caller must not change or free the
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned data.
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL || sm->eapKeyData == NULL) {
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 0;
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*len = sm->eapKeyDataLen;
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapKeyData;
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_eapKeyData - Get EAP response data
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Fetch EAP response (eapRespData) from the EAP state machine. This data is
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available when EAP state machine has processed an incoming EAP request. The
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP state machine does not maintain a reference to the response after this
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function is called and the caller is responsible for freeing the data.
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_get_eapRespData(struct eap_sm *sm)
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL || sm->eapRespData == NULL)
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = sm->eapRespData;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapRespData = NULL;
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return resp;
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sm_register_scard_ctx - Notification of smart card context
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context data for smart card operations
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify EAP state machines of context data for smart card operations. This
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * context data will be used as a parameter for scard_*() functions.
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->scard_ctx = ctx;
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_config_blob - Set or add a named configuration blob
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @blob: New value for the blob
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Adds a new configuration blob or replaces the current value of an existing
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * blob.
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_get_config_blob - Get a named configuration blob
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Name of the blob
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to blob data or %NULL if not found
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   const char *name)
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_CONFIG_BLOBS */
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_set_force_disabled - Set force_disabled flag
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @disabled: 1 = EAP disabled, 0 = EAP enabled
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to force EAP state machine to be disabled when it is
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not in use (e.g., with WPA-PSK or plaintext connections).
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_set_force_disabled(struct eap_sm *sm, int disabled)
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->force_disabled = disabled;
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /**
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_notify_pending - Notify that EAP method is ready to re-process a request
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * An EAP method can perform a pending operation (e.g., to get a response from
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * an external process). Once the response is available, this function can be
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used to request EAPOL state machine to retry delivering the previously
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received (and still unanswered) EAP request to EAP state machine.
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_notify_pending(struct eap_sm *sm)
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->eapol_cb->notify_pending(sm->eapol_ctx);
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_invalidate_cached_session - Mark cached session data invalid
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_invalidate_cached_session(struct eap_sm *sm)
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_deinit_prev_method(sm, "invalidate");
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_is_wps_pbc_enrollee(struct eap_peer_config *conf)
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not a WPS Enrollee */
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL)
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not using PBC */
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_is_wps_pin_enrollee(struct eap_peer_config *conf)
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not a WPS Enrollee */
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL)
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0; /* Not using PIN */
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
231661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
231761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
231861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext)
231961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
232061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_free(sm->ext_pw_buf);
232161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw_buf = NULL;
232261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	sm->ext_pw = ext;
232361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
23244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
23254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
23264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt/**
23274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * eap_set_anon_id - Set or add anonymous identity
23284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
23294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @id: Anonymous identity (e.g., EAP-SIM pseudonym) or %NULL to clear
23304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @len: Length of anonymous identity in octets
23314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */
23324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtvoid eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len)
23334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
23344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sm->eapol_cb->set_anon_id)
23354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
23364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2337