1845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
2845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP peer state machines (RFC 4137)
3845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
5845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This program is free software; you can redistribute it and/or modify
6845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * it under the terms of the GNU General Public License version 2 as
7845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * published by the Free Software Foundation.
8845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
9845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Alternatively, this software may be distributed under the terms of BSD
10845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * license.
11845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
12845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * See README and COPYING for more details.
13845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
14845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This file implements the Peer State Machine as defined in RFC 4137. The used
15845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * states and state transitions match mostly with the RFC. However, there are
16845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * couple of additional transitions for working around small issues noticed
17845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * during testing. These exceptions are explained in comments within the
18845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * functions in this file. The method functions, m.func(), are similar to the
19845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * ones used in RFC 4137, but some small changes have used here to optimize
20845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * operations and to add functionality needed for fast re-authentication
21845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * (session resumption).
22845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
23845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
24845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "includes.h"
25845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
26845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "common.h"
27845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eap_i.h"
28845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "config_ssid.h"
29845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "tls.h"
30845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "crypto.h"
31845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "pcsc_funcs.h"
32845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "wpa_ctrl.h"
33845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "state_machine.h"
34845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
35845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define STATE_MACHINE_DATA struct eap_sm
36845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define STATE_MACHINE_DEBUG_PREFIX "EAP"
37845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
38845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define EAP_MAX_AUTH_ROUNDS 50
39845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
40845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
41845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
42845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  EapType method);
43845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len);
44845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req);
45845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_processNotify(struct eap_sm *sm, const u8 *req);
46845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_sm_buildNotify(int id, size_t *len);
47845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len);
48845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
49845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic const char * eap_sm_method_state_txt(EapMethodState state);
50845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic const char * eap_sm_decision_txt(EapDecision decision);
51845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
52845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
53845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
54845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
55845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
56845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
57845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
58845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
59845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
60845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
61845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
62845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   Boolean value)
63845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
64845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
65845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
66845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
67845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
68845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
69845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
70845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm->eapol_cb->get_int(sm->eapol_ctx, var);
71845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
72845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
73845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
74845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
75845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  unsigned int value)
76845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
77845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
78845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
79845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
80845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
81845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eapol_get_eapReqData(struct eap_sm *sm, size_t *len)
82845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
83845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm->eapol_cb->get_eapReqData(sm->eapol_ctx, len);
84845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
85845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
86845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
87845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
88845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
89845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->m == NULL || sm->eap_method_priv == NULL)
90845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
91845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
92845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
93845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
94845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->m->deinit(sm, sm->eap_method_priv);
95845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eap_method_priv = NULL;
96845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->m = NULL;
97845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
98845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
99845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state initializes state machine variables when the machine is
102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * activated (portEnabled = TRUE). This is also used when re-starting
103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * authentication (eapRestart == TRUE).
104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, INITIALIZE)
106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, INITIALIZE);
108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "fast reauthentication");
112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else {
114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_deinit_prev_method(sm, "INITIALIZE");
115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->selectedMethod = EAP_TYPE_NONE;
117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->methodState = METHOD_NONE;
118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->allowNotifications = TRUE;
119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->decision = DECISION_FAIL;
120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapFail, FALSE);
123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapKeyData);
124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapKeyData = NULL;
125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapKeyAvailable = FALSE;
126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->lastId = -1; /* new session - make sure this does not match with
128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  * the first EAP-Packet */
129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 does not reset eapResp and eapNoResp here. However, this
131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * seemed to be able to trigger cases where both were set and if EAPOL
132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * state machine uses eapNoResp first, it may end up not sending a real
133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * reply correctly. This occurred when the workaround in FAIL state set
134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * something else(?)
136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapResp, FALSE);
138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->num_rounds = 0;
140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state is reached whenever service from the lower layer is interrupted
145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * occurs when the port becomes enabled.
147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, DISABLED)
149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, DISABLED);
151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->num_rounds = 0;
152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * The state machine spends most of its time here, waiting for something to
157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * SEND_RESPONSE states.
159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, IDLE)
161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, IDLE);
163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state is entered when an EAP packet is received (eapReq == TRUE) to
168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * parse the packet header.
169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, RECEIVED)
171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *eapReqData;
173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t eapReqDataLen;
174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, RECEIVED);
176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_parseEapReq(sm, eapReqData, eapReqDataLen);
179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->num_rounds++;
180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state is entered when a request for a new type comes in. Either the
185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * correct method is started, or a Nak response is built.
186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, GET_METHOD)
188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int reinit;
190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	EapType method;
191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, GET_METHOD);
193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->reqMethod == EAP_TYPE_EXPANDED)
195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		method = sm->reqVendorMethod;
196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	else
197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		method = sm->reqMethod;
198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   sm->reqVendor, method);
202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto nak;
203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 does not define specific operation for fast
207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * re-authentication (session resumption). The design here is to allow
208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * the previously used method data to be maintained for
209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * re-authentication if the method support session resumption.
210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * Otherwise, the previously used method data is freed and a new method
211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * is allocated here.
212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->fast_reauth &&
214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->m && sm->m->vendor == sm->reqVendor &&
215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->m->method == method &&
216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->m->has_reauth_data &&
217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   " for fast re-authentication");
220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		reinit = 1;
221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else {
222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_deinit_prev_method(sm, "GET_METHOD");
223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		reinit = 0;
224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->selectedMethod = sm->reqMethod;
227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->m == NULL)
228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->m = eap_sm_get_eap_methods(sm->reqVendor, method);
229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (!sm->m) {
230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "vendor %d method %d",
232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   sm->reqVendor, method);
233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto nak;
234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "vendor %u method %u (%s)",
238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   sm->reqVendor, method, sm->m->name);
239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (reinit)
240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eap_method_priv = sm->m->init_for_reauth(
241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm, sm->eap_method_priv);
242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	else
243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eap_method_priv = sm->m->init(sm);
244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->eap_method_priv == NULL) {
246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		struct wpa_ssid *config = eap_get_config(sm);
247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_msg(sm->msg_ctx, MSG_INFO,
248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			"EAP: Failed to initialize EAP method: vendor %u "
249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			"method %u (%s)",
250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->reqVendor, method, sm->m->name);
251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->m = NULL;
252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->methodState = METHOD_NONE;
253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->selectedMethod = EAP_TYPE_NONE;
254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->reqMethod == EAP_TYPE_TLS && config &&
255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    (config->pending_req_pin ||
256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		     config->pending_req_passphrase)) {
257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			/*
258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * Return without generating Nak in order to allow
259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * entering of PIN code or passphrase to retry the
260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * current EAP packet.
261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 */
262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "request - skip Nak");
264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return;
265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		goto nak;
268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->methodState = METHOD_INIT;
271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		"EAP vendor %u method %u (%s) selected",
273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->reqVendor, method, sm->m->name);
274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return;
275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectnak:
277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapRespData);
278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = NULL;
279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen);
280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * The method processing happens here. The request from the authenticator is
285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * processed, and an appropriate response packet is built.
286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, METHOD)
288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *eapReqData;
290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t eapReqDataLen;
291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_method_ret ret;
292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, METHOD);
294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->m == NULL) {
295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * Get ignore, methodState, decision, allowNotifications, and
303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * eapRespData. RFC 4137 uses three separate method procedure (check,
304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * process, and buildResp) in this state. These have been combined into
305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * a single function call to m->process() in order to optimize EAP
306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * method implementation interface a bit. These procedures are only
307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * used from within this METHOD state, so there is no need to keep
308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * these as separate C functions.
309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 *
310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * The RFC 4137 procedures return values as follows:
311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * ignore = m.check(eapReqData)
312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * (methodState, decision, allowNotifications) = m.process(eapReqData)
313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * eapRespData = m.buildResp(reqId)
314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(&ret, 0, sizeof(ret));
316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret.ignore = sm->ignore;
317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret.methodState = sm->methodState;
318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret.decision = sm->decision;
319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ret.allowNotifications = sm->allowNotifications;
320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapRespData);
321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = NULL;
322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					 eapReqData, eapReqDataLen,
324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					 &sm->eapRespDataLen);
325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "methodState=%s decision=%s",
327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   ret.ignore ? "TRUE" : "FALSE",
328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   eap_sm_method_state_txt(ret.methodState),
329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   eap_sm_decision_txt(ret.decision));
330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->ignore = ret.ignore;
332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->ignore)
333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->methodState = ret.methodState;
335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->decision = ret.decision;
336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->allowNotifications = ret.allowNotifications;
337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->m->isKeyAvailable && sm->m->getKey &&
339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(sm->eapKeyData);
341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					       &sm->eapKeyDataLen);
343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state signals the lower layer that a response packet is ready to be
349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * sent.
350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, SEND_RESPONSE)
352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, SEND_RESPONSE);
354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->lastRespData);
355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->eapRespData) {
356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->workaround)
357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_memcpy(sm->last_md5, sm->req_md5, 16);
358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->lastId = sm->reqId;
359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->lastRespData = os_malloc(sm->eapRespDataLen);
360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->lastRespData) {
361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_memcpy(sm->lastRespData, sm->eapRespData,
362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  sm->eapRespDataLen);
363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->lastRespDataLen = sm->eapRespDataLen;
364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eapol_set_bool(sm, EAPOL_eapResp, TRUE);
366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else
367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->lastRespData = NULL;
368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state signals the lower layer that the request was discarded, and no
375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * response packet will be sent at this time.
376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, DISCARD)
378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, DISCARD);
380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Handles requests for Identity method and builds a response.
387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, IDENTITY)
389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *eapReqData;
391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t eapReqDataLen;
392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, IDENTITY);
394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_processIdentity(sm, eapReqData);
396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapRespData);
397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = NULL;
398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId,
399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					       &sm->eapRespDataLen, 0);
400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Handles requests for Notification method and builds a response.
405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, NOTIFICATION)
407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *eapReqData;
409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t eapReqDataLen;
410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, NOTIFICATION);
412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_processNotify(sm, eapReqData);
414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapRespData);
415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = NULL;
416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = eap_sm_buildNotify(sm->reqId, &sm->eapRespDataLen);
417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state retransmits the previous response packet.
422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, RETRANSMIT)
424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, RETRANSMIT);
426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapRespData);
427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->lastRespData) {
428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eapRespData = os_malloc(sm->lastRespDataLen);
429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->eapRespData) {
430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_memcpy(sm->eapRespData, sm->lastRespData,
431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  sm->lastRespDataLen);
432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->eapRespDataLen = sm->lastRespDataLen;
433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else
435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eapRespData = NULL;
436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state is entered in case of a successful completion of authentication
441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * and state machine waits here until port is disabled or EAP authentication is
442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * restarted.
443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, SUCCESS)
445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, SUCCESS);
447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->eapKeyData != NULL)
448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eapKeyAvailable = TRUE;
449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 does not clear eapReq here, but this seems to be required
453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * to avoid processing the same request twice when state machine is
454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * initialized.
455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 does not set eapNoResp here, but this seems to be required
460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * to get EAPOL Supplicant backend state machine into SUCCESS state. In
461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * addition, either eapResp or eapNoResp is required to be set after
462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * processing the received EAP frame.
463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		"EAP authentication completed successfully");
468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This state is entered in case of a failure and state machine waits here
473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * until port is disabled or EAP authentication is restarted.
474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STATE(EAP, FAILURE)
476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	SM_ENTRY(EAP, FAILURE);
478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapFail, TRUE);
479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 does not clear eapReq here, but this seems to be required
482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * to avoid processing the same request twice when state machine is
483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * initialized.
484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapReq, FALSE);
486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 does not set eapNoResp here. However, either eapResp or
489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * eapNoResp is required to be set after processing the received EAP
490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * frame.
491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		"EAP authentication failed");
496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * At least Microsoft IAS and Meetinghouse Aegis seem to be sending
503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * EAP-Success/Failure with lastId + 1 even though RFC 3748 and
504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 4137 require that reqId == lastId. In addition, it looks like
505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 *
507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * Accept this kind of Id if EAP workarounds are enabled. These are
508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * unauthenticated plaintext messages, so this should have minimal
509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * security implications (bit easier to fake EAP-Success/Failure).
510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       reqId == ((lastId + 2) & 0xff))) {
513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "identifier field in EAP Success: "
515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "reqId=%d lastId=%d (these are supposed to be "
516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "same)", reqId, lastId);
517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return 1;
518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "lastId=%d", reqId, lastId);
521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source ProjectSM_STEP(EAP)
529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int duplicate;
531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eapol_get_bool(sm, EAPOL_eapRestart) &&
533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    eapol_get_bool(sm, EAPOL_portEnabled))
534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER_GLOBAL(EAP, INITIALIZE);
535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER_GLOBAL(EAP, DISABLED);
537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		/* RFC 4137 does not place any limit on number of EAP messages
539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * in an authentication session. However, some error cases have
540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * ended up in a state were EAP messages were sent between the
541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * peer and server in a loop (e.g., TLS ACK frame in both
542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * direction). Since this is quite undesired outcome, limit the
543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * total number of EAP round-trips and abort authentication if
544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * this limit is exceeded.
545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 */
546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				"authentication rounds - abort",
549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				EAP_MAX_AUTH_ROUNDS);
550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->num_rounds++;
551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER_GLOBAL(EAP, FAILURE);
552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else switch (sm->EAP_state) {
554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_INITIALIZE:
555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER(EAP, IDLE);
556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_DISABLED:
558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (eapol_get_bool(sm, EAPOL_portEnabled) &&
559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    !sm->force_disabled)
560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, INITIALIZE);
561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
562845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_IDLE:
563845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		/*
564845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * The first three transitions are from RFC 4137. The last two
565845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * are local additions to handle special cases with LEAP and
566845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * PEAP server not sending EAP-Success in some cases.
567845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 */
568845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (eapol_get_bool(sm, EAPOL_eapReq))
569845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, RECEIVED);
570845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
571845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  sm->decision != DECISION_FAIL) ||
572845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
573845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  sm->decision == DECISION_UNCOND_SUCC))
574845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, SUCCESS);
575845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (eapol_get_bool(sm, EAPOL_altReject) ||
576845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
577845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  sm->decision != DECISION_UNCOND_SUCC) ||
578845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 (eapol_get_bool(sm, EAPOL_altAccept) &&
579845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  sm->methodState != METHOD_CONT &&
580845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  sm->decision == DECISION_FAIL))
581845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, FAILURE);
582845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->selectedMethod == EAP_TYPE_LEAP &&
583845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->leap_done && sm->decision != DECISION_FAIL &&
584845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->methodState == METHOD_DONE)
585845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, SUCCESS);
586845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->selectedMethod == EAP_TYPE_PEAP &&
587845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->peap_done && sm->decision != DECISION_FAIL &&
588845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->methodState == METHOD_DONE)
589845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, SUCCESS);
590845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
591845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_RECEIVED:
592845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
593845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->workaround && duplicate &&
594845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
595845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			/*
596845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * RFC 4137 uses (reqId == lastId) as the only
597845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * verification for duplicate EAP requests. However,
598845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * this misses cases where the AS is incorrectly using
599845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * the same id again; and unfortunately, such
600845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * implementations exist. Use MD5 hash as an extra
601845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * verification for the packets being duplicate to
602845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * workaround these issues.
603845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 */
604845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again,"
605845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   " but EAP packets were not identical");
606845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP: workaround - assume this "
607845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "is not a duplicate packet");
608845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			duplicate = 0;
609845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
610845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
611845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		/*
612845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * Two special cases below for LEAP are local additions to work
613845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * around odd LEAP behavior (EAP-Success in the middle of
614845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * authentication and then swapped roles). Other transitions
615845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * are based on RFC 4137.
616845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 */
617845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
618845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    (sm->reqId == sm->lastId ||
619845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		     eap_success_workaround(sm, sm->reqId, sm->lastId)))
620845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, SUCCESS);
621845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->methodState != METHOD_CONT &&
622845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 ((sm->rxFailure &&
623845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   sm->decision != DECISION_UNCOND_SUCC) ||
624845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  (sm->rxSuccess && sm->decision == DECISION_FAIL &&
625845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   (sm->selectedMethod != EAP_TYPE_LEAP ||
626845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    sm->methodState != METHOD_MAY_CONT))) &&
627845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 (sm->reqId == sm->lastId ||
628845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  eap_success_workaround(sm, sm->reqId, sm->lastId)))
629845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, FAILURE);
630845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->rxReq && duplicate)
631845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, RETRANSMIT);
632845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->rxReq && !duplicate &&
633845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->reqMethod == EAP_TYPE_NOTIFICATION &&
634845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->allowNotifications)
635845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, NOTIFICATION);
636845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->rxReq && !duplicate &&
637845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->selectedMethod == EAP_TYPE_NONE &&
638845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->reqMethod == EAP_TYPE_IDENTITY)
639845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, IDENTITY);
640845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->rxReq && !duplicate &&
641845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->selectedMethod == EAP_TYPE_NONE &&
642845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->reqMethod != EAP_TYPE_IDENTITY &&
643845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->reqMethod != EAP_TYPE_NOTIFICATION)
644845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, GET_METHOD);
645845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->rxReq && !duplicate &&
646845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->reqMethod == sm->selectedMethod &&
647845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 sm->methodState != METHOD_DONE)
648845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, METHOD);
649845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else if (sm->selectedMethod == EAP_TYPE_LEAP &&
650845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 (sm->rxSuccess || sm->rxResp))
651845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, METHOD);
652845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else
653845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, DISCARD);
654845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
655845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_GET_METHOD:
656845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->selectedMethod == sm->reqMethod)
657845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, METHOD);
658845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else
659845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, SEND_RESPONSE);
660845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
661845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_METHOD:
662845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->ignore)
663845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, DISCARD);
664845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		else
665845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			SM_ENTER(EAP, SEND_RESPONSE);
666845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
667845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SEND_RESPONSE:
668845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER(EAP, IDLE);
669845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
670845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_DISCARD:
671845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER(EAP, IDLE);
672845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
673845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_IDENTITY:
674845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER(EAP, SEND_RESPONSE);
675845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
676845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_NOTIFICATION:
677845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER(EAP, SEND_RESPONSE);
678845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
679845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_RETRANSMIT:
680845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_ENTER(EAP, SEND_RESPONSE);
681845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
682845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SUCCESS:
683845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
684845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_FAILURE:
685845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
686845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
687845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
688845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
689845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
690845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
691845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  EapType method)
692845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
693845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
694845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
695845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (!wpa_config_allowed_eap_method(config, vendor, method)) {
696845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
697845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "vendor %u method %u", vendor, method);
698845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return FALSE;
699845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
700845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_sm_get_eap_methods(vendor, method))
701845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return TRUE;
702845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: not included in build: "
703845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "vendor %u method %u", vendor, method);
704845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return FALSE;
705845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
706845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
707845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
708845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_sm_build_expanded_nak(struct eap_sm *sm, int id, size_t *len,
709845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				      const struct eap_method *methods,
710845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				      size_t count)
711845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
712845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
713845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *resp;
714845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos;
715845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int found = 0;
716845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_method *m;
717845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
718845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
719845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
720845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* RFC 3748 - 5.3.2: Expanded Nak */
721845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sizeof(struct eap_hdr) + 8;
722845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = os_malloc(*len + 8 * (count + 1));
723845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
724845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
725845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
726845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->code = EAP_CODE_RESPONSE;
727845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->identifier = id;
728845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (u8 *) (resp + 1);
729845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = EAP_TYPE_EXPANDED;
730845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
731845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 3;
732845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE32(pos, EAP_TYPE_NAK);
733845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 4;
734845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
735845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	for (m = methods; m; m = m->next) {
736845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->reqVendor == m->vendor &&
737845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    sm->reqVendorMethod == m->method)
738845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			continue; /* do not allow the current method again */
739845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (wpa_config_allowed_eap_method(config, m->vendor,
740845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						  m->method)) {
741845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP: allowed type: "
742845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "vendor=%u method=%u",
743845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   m->vendor, m->method);
744845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			*pos++ = EAP_TYPE_EXPANDED;
745845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			WPA_PUT_BE24(pos, m->vendor);
746845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			pos += 3;
747845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			WPA_PUT_BE32(pos, m->method);
748845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			pos += 4;
749845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
750845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			(*len) += 8;
751845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			found++;
752845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
753845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
754845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (!found) {
755845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
756845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*pos++ = EAP_TYPE_EXPANDED;
757845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
758845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += 3;
759845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		WPA_PUT_BE32(pos, EAP_TYPE_NONE);
760845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += 4;
761845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
762845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		(*len) += 8;
763845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
764845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
765845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->length = host_to_be16(*len);
766845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
767845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
768845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
769845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
770845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
771845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
772845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
773845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
774845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *resp;
775845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos;
776845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int found = 0, expanded_found = 0;
777845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t count;
778845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_method *methods, *m;
779845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
780845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
781845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "vendor=%u method=%u not allowed)", sm->reqMethod,
782845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   sm->reqVendor, sm->reqVendorMethod);
783845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	methods = eap_peer_get_methods(&count);
784845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (methods == NULL)
785845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
786845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->reqMethod == EAP_TYPE_EXPANDED)
787845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return eap_sm_build_expanded_nak(sm, id, len, methods, count);
788845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
789845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* RFC 3748 - 5.3.1: Legacy Nak */
790845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sizeof(struct eap_hdr) + 1;
791845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = os_malloc(*len + count + 1);
792845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
793845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
794845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
795845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->code = EAP_CODE_RESPONSE;
796845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->identifier = id;
797845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (u8 *) (resp + 1);
798845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = EAP_TYPE_NAK;
799845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
800845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	for (m = methods; m; m = m->next) {
801845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
802845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			continue; /* do not allow the current method again */
803845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (wpa_config_allowed_eap_method(config, m->vendor,
804845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						  m->method)) {
805845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (m->vendor != EAP_VENDOR_IETF) {
806845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				if (expanded_found)
807845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					continue;
808845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				expanded_found = 1;
809845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				*pos++ = EAP_TYPE_EXPANDED;
810845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			} else
811845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				*pos++ = m->method;
812845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			(*len)++;
813845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			found++;
814845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
815845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
816845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (!found) {
817845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*pos = EAP_TYPE_NONE;
818845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		(*len)++;
819845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
820845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP: allowed methods",
821845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    ((u8 *) (resp + 1)) + 1, found);
822845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
823845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->length = host_to_be16(*len);
824845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
825845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
826845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
827845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
828845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
829845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req)
830845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
831845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_hdr *hdr = (const struct eap_hdr *) req;
832845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos = (const u8 *) (hdr + 1);
833845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos++;
834845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
835845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
836845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		"EAP authentication started");
837845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
838845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/*
839845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * RFC 3748 - 5.1: Identity
840845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * Data field may contain a displayable message in UTF-8. If this
841845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * includes NUL-character, only the data before that should be
842845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * displayed. Some EAP implementasitons may piggy-back additional
843845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * options after the NUL.
844845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 */
845845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* TODO: could save displayable message so that it can be shown to the
846845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * user in case of interaction is required */
847845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
848845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  pos, be_to_host16(hdr->length) - 5);
849845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
850845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
851845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
852845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifdef PCSC_FUNCS
853845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
854845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
855845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int aka = 0;
856845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char imsi[100];
857845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t imsi_len;
858845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_method_type *m = ssid->eap_methods;
859845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int i;
860845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
861845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	imsi_len = sizeof(imsi);
862845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
863845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
864845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
865845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
866845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
867845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
868845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
869845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
870845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  m[i].method != EAP_TYPE_NONE); i++) {
871845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (m[i].vendor == EAP_VENDOR_IETF &&
872845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    m[i].method == EAP_TYPE_AKA) {
873845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			aka = 1;
874845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
875845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
876845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
877845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
878845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(ssid->identity);
879845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ssid->identity = os_malloc(1 + imsi_len);
880845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (ssid->identity == NULL) {
881845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
882845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "IMSI-based identity");
883845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
884845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
885845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
886845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ssid->identity[0] = aka ? '0' : '1';
887845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(ssid->identity + 1, imsi, imsi_len);
888845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	ssid->identity_len = 1 + imsi_len;
889845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
890845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
891845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
892845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* PCSC_FUNCS */
893845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
894845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
895dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidtstatic int eap_sm_set_scard_pin(struct eap_sm *sm, struct wpa_ssid *ssid)
896845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
897845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifdef PCSC_FUNCS
898845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
899845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		/*
900845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * Make sure the same PIN is not tried again in order to avoid
901845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 * blocking SIM.
902845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		 */
903845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(ssid->pin);
904845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ssid->pin = NULL;
905845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
906845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "PIN validation failed");
907845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_pin(sm);
908845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
909845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
910dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt	return 0;
911dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt#else /* PCSC_FUNCS */
912dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt	return -1;
913dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt#endif /* PCSC_FUNCS */
914dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt}
915dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt
916dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidtstatic int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
917dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt{
918dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt#ifdef PCSC_FUNCS
919dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt	if (eap_sm_set_scard_pin(sm, ssid))
920dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt		return -1;
921845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
922845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return eap_sm_imsi_identity(sm, ssid);
923845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#else /* PCSC_FUNCS */
924845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return -1;
925845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* PCSC_FUNCS */
926845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
927845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
928845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
929845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
930845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
931845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
932845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @id: EAP identifier for the packet
933845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Pointer to a variable that will be set to the length of the response
934845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
935845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
936845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * failure
937845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
938845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function allocates and builds an EAP-Identity/Response packet for the
939845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * current network. The caller is responsible for freeing the returned data.
940845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
941845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
942845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  int encrypted)
943845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
944845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
945845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *resp;
946845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos;
947845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *identity;
948845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t identity_len;
949845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
950845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL) {
951845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
952845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "was not available");
953845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
954845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
955845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
956845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->m && sm->m->get_identity &&
957845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    (identity = sm->m->get_identity(sm, sm->eap_method_priv,
958845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					    &identity_len)) != NULL) {
959845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
960845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  "identity", identity, identity_len);
961845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else if (!encrypted && config->anonymous_identity) {
962845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		identity = config->anonymous_identity;
963845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		identity_len = config->anonymous_identity_len;
964845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
965845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  identity, identity_len);
966845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else {
967845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		identity = config->identity;
968845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		identity_len = config->identity_len;
969845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
970845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  identity, identity_len);
971845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
972845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
973845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (identity == NULL) {
974845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
975845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "configuration was not available");
976845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (config->pcsc) {
977845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (eap_sm_get_scard_identity(sm, config) < 0)
978845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return NULL;
979845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			identity = config->identity;
980845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			identity_len = config->identity_len;
981845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
982845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					  "IMSI", identity, identity_len);
983845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		} else {
984845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			eap_sm_request_identity(sm);
985845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return NULL;
986845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
987dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt	} else if (config->pcsc) {
988dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt		if (eap_sm_set_scard_pin(sm, config) < 0)
989dc9507e42030320bf0a3dbb7d3f733d43bc94edeDmitry Shmidt			return NULL;
990845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
991845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
992845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sizeof(struct eap_hdr) + 1 + identity_len;
993845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = os_malloc(*len);
994845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
995845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
996845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
997845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->code = EAP_CODE_RESPONSE;
998845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->identifier = id;
999845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->length = host_to_be16(*len);
1000845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (u8 *) (resp + 1);
1001845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = EAP_TYPE_IDENTITY;
1002845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(pos, identity, identity_len);
1003845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1004845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
1005845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1006845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1007845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1008845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_processNotify(struct eap_sm *sm, const u8 *req)
1009845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1010845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_hdr *hdr = (const struct eap_hdr *) req;
1011845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos;
1012845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *msg;
1013845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t i, msg_len;
1014845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1015845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (const u8 *) (hdr + 1);
1016845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos++;
1017845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1018845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg_len = be_to_host16(hdr->length);
1019845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg_len < 5)
1020845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1021845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg_len -= 5;
1022845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
1023845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  pos, msg_len);
1024845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1025845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg = os_malloc(msg_len + 1);
1026845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg == NULL)
1027845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1028845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	for (i = 0; i < msg_len; i++)
1029845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
1030845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg[msg_len] = '\0';
1031845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
1032845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		WPA_EVENT_EAP_NOTIFICATION, msg);
1033845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(msg);
1034845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1035845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1036845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1037845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic u8 * eap_sm_buildNotify(int id, size_t *len)
1038845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1039845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *resp;
1040845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos;
1041845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1042845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
1043845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sizeof(struct eap_hdr) + 1;
1044845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = os_malloc(*len);
1045845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (resp == NULL)
1046845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1047845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1048845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->code = EAP_CODE_RESPONSE;
1049845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->identifier = id;
1050845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp->length = host_to_be16(*len);
1051845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (u8 *) (resp + 1);
1052845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos = EAP_TYPE_NOTIFICATION;
1053845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1054845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (u8 *) resp;
1055845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1056845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1057845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1058845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len)
1059845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1060845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_hdr *hdr;
1061845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t plen;
1062845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos;
1063845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1064845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
1065845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->reqId = 0;
1066845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->reqMethod = EAP_TYPE_NONE;
1067845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->reqVendor = EAP_VENDOR_IETF;
1068845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->reqVendorMethod = EAP_TYPE_NONE;
1069845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1070845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (req == NULL || len < sizeof(*hdr))
1071845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1072845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1073845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	hdr = (const struct eap_hdr *) req;
1074845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	plen = be_to_host16(hdr->length);
1075845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (plen > len) {
1076845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
1077845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "(len=%lu plen=%lu)",
1078845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   (unsigned long) len, (unsigned long) plen);
1079845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1080845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1081845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1082845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->reqId = hdr->identifier;
1083845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1084845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->workaround) {
1085845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		md5_vector(1, (const u8 **) &req, &plen, sm->req_md5);
1086845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1087845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1088845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (hdr->code) {
1089845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_CODE_REQUEST:
1090845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (plen < sizeof(*hdr) + 1) {
1091845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
1092845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "no Type field");
1093845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return;
1094845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1095845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->rxReq = TRUE;
1096845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos = (const u8 *) (hdr + 1);
1097845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->reqMethod = *pos++;
1098845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->reqMethod == EAP_TYPE_EXPANDED) {
1099845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (plen < sizeof(*hdr) + 8) {
1100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
1101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "expanded EAP-Packet (plen=%lu)",
1102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) plen);
1103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return;
1104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
1105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->reqVendor = WPA_GET_BE24(pos);
1106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			pos += 3;
1107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->reqVendorMethod = WPA_GET_BE32(pos);
1108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
1110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "method=%u vendor=%u vendorMethod=%u",
1111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   sm->reqId, sm->reqMethod, sm->reqVendor,
1112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   sm->reqVendorMethod);
1113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_CODE_RESPONSE:
1115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->selectedMethod == EAP_TYPE_LEAP) {
1116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			/*
1117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * LEAP differs from RFC 4137 by using reversed roles
1118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * for mutual authentication and because of this, we
1119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 * need to accept EAP-Response frames if LEAP is used.
1120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			 */
1121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (plen < sizeof(*hdr) + 1) {
1122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_DEBUG, "EAP: Too short "
1123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "EAP-Response - no Type field");
1124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return;
1125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
1126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->rxResp = TRUE;
1127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			pos = (const u8 *) (hdr + 1);
1128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			sm->reqMethod = *pos;
1129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
1130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "LEAP method=%d id=%d",
1131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   sm->reqMethod, sm->reqId);
1132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
1133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
1135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_CODE_SUCCESS:
1137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
1138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->rxSuccess = TRUE;
1139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_CODE_FAILURE:
1141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
1142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->rxFailure = TRUE;
1143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
1145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
1146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "code %d", hdr->code);
1147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_init - Allocate and initialize EAP state machine
1154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @eapol_ctx: Context data to be used with eapol_cb calls
1155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @eapol_cb: Pointer to EAPOL callback functions
1156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @msg_ctx: Context data for wpa_msg() calls
1157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @conf: EAP configuration
1158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the allocated EAP state machine or %NULL on failure
1159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function allocates and initializes an EAP state machine. In addition,
1161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * this initializes TLS library for the new EAP state machine. eapol_cb pointer
1162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * will be in use until eap_sm_deinit() is used to deinitialize this EAP state
1163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * machine. Consequently, the caller must make sure that this data structure
1164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * remains alive while the EAP state machine is active.
1165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
1167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    void *msg_ctx, struct eap_config *conf)
1168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_sm *sm;
1170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct tls_config tlsconf;
1171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm = os_zalloc(sizeof(*sm));
1173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL)
1174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapol_ctx = eapol_ctx;
1176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapol_cb = eapol_cb;
1177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->msg_ctx = msg_ctx;
1178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->ClientTimeout = 60;
1179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(&tlsconf, 0, sizeof(tlsconf));
1181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	tlsconf.opensc_engine_path = conf->opensc_engine_path;
1182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
1183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
1184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->ssl_ctx = tls_init(&tlsconf);
1185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->ssl_ctx == NULL) {
1186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
1187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "context.");
1188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(sm);
1189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm;
1193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_deinit - Deinitialize and free an EAP state machine
1198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function deinitializes EAP state machine and frees all allocated
1201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * resources.
1202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_deinit(struct eap_sm *sm)
1204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL)
1206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_deinit_prev_method(sm, "EAP deinit");
1208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_abort(sm);
1209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	tls_deinit(sm->ssl_ctx);
1210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm);
1211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_step - Step EAP state machine
1216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: 1 if EAP state was changed or 0 if not
1218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function advances EAP state machine to a new state to match with the
1220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * current variables. This should be called whenever variables used by the EAP
1221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * state machine have changed.
1222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sm_step(struct eap_sm *sm)
1224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int res = 0;
1226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	do {
1227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->changed = FALSE;
1228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		SM_STEP_RUN(EAP);
1229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->changed)
1230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			res = 1;
1231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} while (sm->changed);
1232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return res;
1233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_abort - Abort EAP authentication
1238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Release system resources that have been allocated for the authentication
1241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * session without fully deinitializing the EAP state machine.
1242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_abort(struct eap_sm *sm)
1244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->lastRespData);
1246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->lastRespData = NULL;
1247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapRespData);
1248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = NULL;
1249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(sm->eapKeyData);
1250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapKeyData = NULL;
1251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* This is not clearly specified in the EAP statemachines draft, but
1253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * it seems necessary to make sure that some of the EAPOL variables get
1254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * cleared for the next authentication. */
1255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
1256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifdef CONFIG_CTRL_IFACE
1260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic const char * eap_sm_state_txt(int state)
1261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (state) {
1263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_INITIALIZE:
1264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "INITIALIZE";
1265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_DISABLED:
1266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "DISABLED";
1267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_IDLE:
1268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "IDLE";
1269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_RECEIVED:
1270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "RECEIVED";
1271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_GET_METHOD:
1272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "GET_METHOD";
1273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_METHOD:
1274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "METHOD";
1275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SEND_RESPONSE:
1276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "SEND_RESPONSE";
1277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_DISCARD:
1278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "DISCARD";
1279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_IDENTITY:
1280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "IDENTITY";
1281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_NOTIFICATION:
1282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "NOTIFICATION";
1283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_RETRANSMIT:
1284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "RETRANSMIT";
1285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SUCCESS:
1286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "SUCCESS";
1287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_FAILURE:
1288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "FAILURE";
1289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
1290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "UNKNOWN";
1291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_CTRL_IFACE */
1294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic const char * eap_sm_method_state_txt(EapMethodState state)
1298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (state) {
1300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case METHOD_NONE:
1301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "NONE";
1302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case METHOD_INIT:
1303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "INIT";
1304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case METHOD_CONT:
1305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "CONT";
1306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case METHOD_MAY_CONT:
1307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "MAY_CONT";
1308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case METHOD_DONE:
1309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "DONE";
1310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
1311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "UNKNOWN";
1312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic const char * eap_sm_decision_txt(EapDecision decision)
1317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (decision) {
1319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case DECISION_FAIL:
1320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "FAIL";
1321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case DECISION_COND_SUCC:
1322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "COND_SUCC";
1323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case DECISION_UNCOND_SUCC:
1324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "UNCOND_SUCC";
1325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
1326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return "UNKNOWN";
1327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifdef CONFIG_CTRL_IFACE
1333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_get_status - Get EAP state machine status
1336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @buf: Buffer for status information
1338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @buflen: Maximum buffer length
1339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @verbose: Whether to include verbose status information
1340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Number of bytes written to buf.
1341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Query EAP state machine for status information. This function fills in a
1343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * text area with current status information from the EAPOL state machine. If
1344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the buffer (buf) is not large enough, status information will be truncated
1345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * to fit the buffer.
1346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
1348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int len, ret;
1350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL)
1352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return 0;
1353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len = os_snprintf(buf, buflen,
1355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  "EAP state=%s\n",
1356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  eap_sm_state_txt(sm->EAP_state));
1357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (len < 0 || (size_t) len >= buflen)
1358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return 0;
1359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->selectedMethod != EAP_TYPE_NONE) {
1361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		const char *name;
1362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->m) {
1363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			name = sm->m->name;
1364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		} else {
1365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			const struct eap_method *m =
1366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				eap_sm_get_eap_methods(EAP_VENDOR_IETF,
1367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						       sm->selectedMethod);
1368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (m)
1369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				name = m->name;
1370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			else
1371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				name = "?";
1372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ret = os_snprintf(buf + len, buflen - len,
1374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  "selectedMethod=%d (EAP-%s)\n",
1375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  sm->selectedMethod, name);
1376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (ret < 0 || (size_t) ret >= buflen - len)
1377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return len;
1378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		len += ret;
1379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (sm->m && sm->m->get_status) {
1381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			len += sm->m->get_status(sm, sm->eap_method_priv,
1382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						 buf + len, buflen - len,
1383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						 verbose);
1384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (verbose) {
1388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		ret = os_snprintf(buf + len, buflen - len,
1389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  "reqMethod=%d\n"
1390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  "methodState=%s\n"
1391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  "decision=%s\n"
1392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  "ClientTimeout=%d\n",
1393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  sm->reqMethod,
1394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  eap_sm_method_state_txt(sm->methodState),
1395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  eap_sm_decision_txt(sm->decision),
1396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				  sm->ClientTimeout);
1397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (ret < 0 || (size_t) ret >= buflen - len)
1398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return len;
1399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		len += ret;
1400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return len;
1403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_CTRL_IFACE */
1405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projecttypedef enum {
1409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
1410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	TYPE_PASSPHRASE
1411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} eap_ctrl_req_type;
1412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
1414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   const char *msg, size_t msglen)
1415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config;
1417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *buf;
1418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t buflen;
1419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int len;
1420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *field;
1421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	char *txt, *tmp;
1422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL)
1424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	config = eap_get_config(sm);
1426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (type) {
1430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case TYPE_IDENTITY:
1431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		field = "IDENTITY";
1432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		txt = "Identity";
1433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		config->pending_req_identity++;
1434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case TYPE_PASSWORD:
1436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		field = "PASSWORD";
1437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		txt = "Password";
1438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		config->pending_req_password++;
1439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case TYPE_NEW_PASSWORD:
1441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		field = "NEW_PASSWORD";
1442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		txt = "New Password";
1443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		config->pending_req_new_password++;
1444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case TYPE_PIN:
1446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		field = "PIN";
1447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		txt = "PIN";
1448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		config->pending_req_pin++;
1449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case TYPE_OTP:
1451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		field = "OTP";
1452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (msg) {
1453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			tmp = os_malloc(msglen + 3);
1454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (tmp == NULL)
1455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return;
1456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			tmp[0] = '[';
1457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_memcpy(tmp + 1, msg, msglen);
1458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			tmp[msglen + 1] = ']';
1459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			tmp[msglen + 2] = '\0';
1460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			txt = tmp;
1461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			os_free(config->pending_req_otp);
1462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			config->pending_req_otp = tmp;
1463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			config->pending_req_otp_len = msglen + 3;
1464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		} else {
1465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (config->pending_req_otp == NULL)
1466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return;
1467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			txt = config->pending_req_otp;
1468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case TYPE_PASSPHRASE:
1471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		field = "PASSPHRASE";
1472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		txt = "Private key passphrase";
1473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		config->pending_req_passphrase++;
1474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
1475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
1476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buflen = 100 + os_strlen(txt) + config->ssid_len;
1480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buf = os_malloc(buflen);
1481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (buf == NULL)
1482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len = os_snprintf(buf, buflen,
1484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
1485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  field, config->id, txt);
1486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (len < 0 || (size_t) len >= buflen) {
1487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(buf);
1488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->ssid && buflen > len + config->ssid_len) {
1491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(buf + len, config->ssid, config->ssid_len);
1492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		len += config->ssid_len;
1493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		buf[len] = '\0';
1494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buf[buflen - 1] = '\0';
1496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf);
1497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(buf);
1498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
1501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_request_identity - Request identity from user (ctrl_iface)
1506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP methods can call this function to request identity information for the
1509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * current network. This is normally called when the identity is not included
1510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * in the network configuration. The request will be sent to monitor programs
1511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * through the control interface.
1512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_request_identity(struct eap_sm *sm)
1514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_request(sm, TYPE_IDENTITY, NULL, 0);
1516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_request_password - Request password from user (ctrl_iface)
1521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP methods can call this function to request password information for the
1524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * current network. This is normally called when the password is not included
1525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * in the network configuration. The request will be sent to monitor programs
1526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * through the control interface.
1527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_request_password(struct eap_sm *sm)
1529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_request(sm, TYPE_PASSWORD, NULL, 0);
1531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_request_new_password - Request new password from user (ctrl_iface)
1536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP methods can call this function to request new password information for
1539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the current network. This is normally called when the EAP method indicates
1540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * that the current password has expired and password change is required. The
1541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * request will be sent to monitor programs through the control interface.
1542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_request_new_password(struct eap_sm *sm)
1544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0);
1546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
1551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP methods can call this function to request SIM or smart card PIN
1554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * information for the current network. This is normally called when the PIN is
1555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * not included in the network configuration. The request will be sent to
1556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * monitor programs through the control interface.
1557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_request_pin(struct eap_sm *sm)
1559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_request(sm, TYPE_PIN, NULL, 0);
1561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1562845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1563845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1564845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1565845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_request_otp - Request one time password from user (ctrl_iface)
1566845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1567845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @msg: Message to be displayed to the user when asking for OTP
1568845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @msg_len: Length of the user displayable message
1569845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1570845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP methods can call this function to request open time password (OTP) for
1571845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the current network. The request will be sent to monitor programs through
1572845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the control interface.
1573845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1574845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
1575845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1576845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_request(sm, TYPE_OTP, msg, msg_len);
1577845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1578845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1579845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1580845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1581845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
1582845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1583845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1584845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP methods can call this function to request passphrase for a private key
1585845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * for the current network. This is normally called when the passphrase is not
1586845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * included in the network configuration. The request will be sent to monitor
1587845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * programs through the control interface.
1588845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1589845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_request_passphrase(struct eap_sm *sm)
1590845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1591845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0);
1592845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1593845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1594845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1595845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1596845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_notify_ctrl_attached - Notification of attached monitor
1597845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1598845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1599845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Notify EAP state machines that a monitor was attached to the control
1600845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * interface to trigger re-sending of pending requests for user input.
1601845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1602845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sm_notify_ctrl_attached(struct eap_sm *sm)
1603845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1604845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
1605845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1606845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1607845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1608845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1609845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* Re-send any pending requests for user data since a new control
1610845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * interface was added. This handles cases where the EAP authentication
1611845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * starts immediately after system startup when the user interface is
1612845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	 * not yet running. */
1613845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->pending_req_identity)
1614845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_identity(sm);
1615845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->pending_req_password)
1616845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_password(sm);
1617845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->pending_req_new_password)
1618845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_new_password(sm);
1619845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->pending_req_otp)
1620845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_otp(sm, NULL, 0);
1621845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->pending_req_pin)
1622845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_pin(sm);
1623845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config->pending_req_passphrase)
1624845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sm_request_passphrase(sm);
1625845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1626845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1627845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1628845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int eap_allowed_phase2_type(int vendor, int type)
1629845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1630845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (vendor != EAP_VENDOR_IETF)
1631845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return 0;
1632845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
1633845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		type != EAP_TYPE_FAST;
1634845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1635845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1636845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1637845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1638845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
1639845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @name: EAP method name, e.g., MD5
1640845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @vendor: Buffer for returning EAP Vendor-Id
1641845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: EAP method type or %EAP_TYPE_NONE if not found
1642845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1643845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function maps EAP type names into EAP type numbers that are allowed for
1644845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
1645845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP-PEAP, EAP-TTLS, and EAP-FAST.
1646845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1647845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu32 eap_get_phase2_type(const char *name, int *vendor)
1648845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1649845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int v;
1650845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 type = eap_get_type(name, &v);
1651845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_allowed_phase2_type(v, type)) {
1652845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*vendor = v;
1653845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return type;
1654845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1655845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*vendor = EAP_VENDOR_IETF;
1656845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return EAP_TYPE_NONE;
1657845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1658845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1659845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1660845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1661845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_phase2_types - Get list of allowed EAP phase 2 types
1662845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @config: Pointer to a network configuration
1663845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @count: Pointer to a variable to be filled with number of returned EAP types
1664845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to allocated type list or %NULL on failure
1665845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1666845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function generates an array of allowed EAP phase 2 (tunneled) types for
1667845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the given network configuration.
1668845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1669845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct eap_method_type * eap_get_phase2_types(struct wpa_ssid *config,
1670845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					      size_t *count)
1671845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1672845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_method_type *buf;
1673845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u32 method;
1674845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int vendor;
1675845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t mcount;
1676845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_method *methods, *m;
1677845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1678845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	methods = eap_peer_get_methods(&mcount);
1679845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (methods == NULL)
1680845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1681845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*count = 0;
1682845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buf = os_malloc(mcount * sizeof(struct eap_method_type));
1683845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (buf == NULL)
1684845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1685845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1686845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	for (m = methods; m; m = m->next) {
1687845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		vendor = m->vendor;
1688845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		method = m->method;
1689845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (eap_allowed_phase2_type(vendor, method)) {
1690845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (vendor == EAP_VENDOR_IETF &&
1691845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    method == EAP_TYPE_TLS && config &&
1692845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    config->private_key2 == NULL)
1693845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				continue;
1694845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			buf[*count].vendor = vendor;
1695845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			buf[*count].method = method;
1696845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			(*count)++;
1697845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1698845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1699845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1700845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return buf;
1701845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1702845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1703845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1704845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1705845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_set_fast_reauth - Update fast_reauth setting
1706845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1707845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
1708845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1709845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_set_fast_reauth(struct eap_sm *sm, int enabled)
1710845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1711845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->fast_reauth = enabled;
1712845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1713845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1714845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1715845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1716845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_set_workaround - Update EAP workarounds setting
1717845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1718845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
1719845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1720845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
1721845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1722845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->workaround = workaround;
1723845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1724845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1725845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1726845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1727845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config - Get current network configuration
1728845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1729845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the current network configuration or %NULL if not found
1730845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1731845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP peer methods should avoid using this function if they can use other
1732845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * access functions, like eap_get_config_identity() and
1733845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config_password(), that do not require direct access to
1734845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * struct wpa_ssid.
1735845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1736845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct wpa_ssid * eap_get_config(struct eap_sm *sm)
1737845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1738845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm->eapol_cb->get_config(sm->eapol_ctx);
1739845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1740845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1741845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1742845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1743845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config_password - Get identity from the network configuration
1744845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1745845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Buffer for the length of the identity
1746845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the identity or %NULL if not found
1747845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1748845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
1749845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1750845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
1751845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1752845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1753845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = config->identity_len;
1754845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return config->identity;
1755845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1756845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1757845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1758845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1759845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config_password - Get password from the network configuration
1760845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1761845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Buffer for the length of the password
1762845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the password or %NULL if not found
1763845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1764845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
1765845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1766845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
1767845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1768845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1769845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = config->password_len;
1770845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return config->password;
1771845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1772845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1773845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1774845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1775845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config_new_password - Get new password from network configuration
1776845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1777845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Buffer for the length of the new password
1778845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the new password or %NULL if not found
1779845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1780845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
1781845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1782845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
1783845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1784845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1785845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = config->new_password_len;
1786845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return config->new_password;
1787845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1788845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1789845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1790845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1791845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config_otp - Get one-time password from the network configuration
1792845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1793845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Buffer for the length of the one-time password
1794845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the one-time password or %NULL if not found
1795845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1796845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
1797845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1798845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
1799845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1800845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1801845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = config->otp_len;
1802845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return config->otp;
1803845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1804845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1805845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1806845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1807845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_clear_config_otp - Clear used one-time password
1808845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1809845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1810845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function clears a used one-time password (OTP) from the current network
1811845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * configuration. This should be called when the OTP has been used and is not
1812845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * needed anymore.
1813845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1814845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_clear_config_otp(struct eap_sm *sm)
1815845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1816845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct wpa_ssid *config = eap_get_config(sm);
1817845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (config == NULL)
1818845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1819845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(config->otp, 0, config->otp_len);
1820845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(config->otp);
1821845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	config->otp = NULL;
1822845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	config->otp_len = 0;
1823845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1824845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1825845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1826845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1827845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_key_available - Get key availability (eapKeyAvailable variable)
1828845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1829845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: 1 if EAP keying material is available, 0 if not
1830845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1831845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_key_available(struct eap_sm *sm)
1832845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1833845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm ? sm->eapKeyAvailable : 0;
1834845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1835845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1836845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1837845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1838845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_notify_success - Notify EAP state machine about external success trigger
1839845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1840845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1841845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function is called when external event, e.g., successful completion of
1842845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * WPA-PSK key handshake, is indicating that EAP state machine should move to
1843845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * success state. This is mainly used with security modes that do not use EAP
1844845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * state machine (e.g., WPA-PSK).
1845845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1846845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_notify_success(struct eap_sm *sm)
1847845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1848845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm) {
1849845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->decision = DECISION_COND_SUCC;
1850845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->EAP_state = EAP_SUCCESS;
1851845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1852845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1853845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1854845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1855845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1856845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_notify_lower_layer_success - Notification of lower layer success
1857845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1858845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1859845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Notify EAP state machines that a lower layer has detected a successful
1860845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * authentication. This is used to recover from dropped EAP-Success messages.
1861845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1862845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_notify_lower_layer_success(struct eap_sm *sm)
1863845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1864845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL)
1865845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1866845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1867845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
1868845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    sm->decision == DECISION_FAIL ||
1869845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    (sm->methodState != METHOD_MAY_CONT &&
1870845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	     sm->methodState != METHOD_DONE))
1871845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return;
1872845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1873845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm->eapKeyData != NULL)
1874845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->eapKeyAvailable = TRUE;
1875845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
1876845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
1877845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		"EAP authentication completed successfully (based on lower "
1878845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		"layer success)");
1879845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1880845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1881845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1882845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1883845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
1884845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1885845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Pointer to variable that will be set to number of bytes in the key
1886845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the EAP keying data or %NULL on failure
1887845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1888845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
1889845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * key is available only after a successful authentication. EAP state machine
1890845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * continues to manage the key data and the caller must not change or free the
1891845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * returned data.
1892845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1893845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
1894845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1895845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL || sm->eapKeyData == NULL) {
1896845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*len = 0;
1897845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1898845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1899845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1900845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sm->eapKeyDataLen;
1901845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm->eapKeyData;
1902845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1903845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1904845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1905845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1906845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_eapKeyData - Get EAP response data
1907845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1908845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Pointer to variable that will be set to the length of the response
1909845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
1910845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1911845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Fetch EAP response (eapRespData) from the EAP state machine. This data is
1912845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * available when EAP state machine has processed an incoming EAP request. The
1913845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP state machine does not maintain a reference to the response after this
1914845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * function is called and the caller is responsible for freeing the data.
1915845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1916845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len)
1917845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1918845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *resp;
1919845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1920845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm == NULL || sm->eapRespData == NULL) {
1921845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*len = 0;
1922845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1923845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1924845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1925845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	resp = sm->eapRespData;
1926845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sm->eapRespDataLen;
1927845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespData = NULL;
1928845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapRespDataLen = 0;
1929845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1930845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return resp;
1931845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1932845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1933845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1934845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1935845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_sm_register_scard_ctx - Notification of smart card context
1936845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1937845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @ctx: Context data for smart card operations
1938845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1939845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Notify EAP state machines of context data for smart card operations. This
1940845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * context data will be used as a parameter for scard_*() functions.
1941845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1942845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
1943845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1944845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm)
1945845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		sm->scard_ctx = ctx;
1946845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
1947845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1948845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1949845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
1950845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_hdr_validate - Validate EAP header
1951845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @vendor: Expected EAP Vendor-Id (0 = IETF)
1952845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @eap_type: Expected EAP type number
1953845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @msg: EAP frame (starting with EAP header)
1954845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @msglen: Length of msg
1955845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @plen: Pointer to variable to contain the returned payload length
1956845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to EAP payload (after type field), or %NULL on failure
1957845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
1958845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This is a helper function for EAP method implementations. This is usually
1959845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * called in the beginning of struct eap_method::process() function to verify
1960845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * that the received EAP request packet has a valid header. This function is
1961845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * able to process both legacy and expanded EAP headers and in most cases, the
1962845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * caller can just use the returned payload pointer (into *plen) for processing
1963845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the payload regardless of whether the packet used the expanded EAP header or
1964845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * not.
1965845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
1966845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst u8 * eap_hdr_validate(int vendor, EapType eap_type,
1967845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    const u8 *msg, size_t msglen, size_t *plen)
1968845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
1969845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const struct eap_hdr *hdr;
1970845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos;
1971845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len;
1972845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1973845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	hdr = (const struct eap_hdr *) msg;
1974845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1975845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msglen < sizeof(*hdr)) {
1976845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP: Too short EAP frame");
1977845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1978845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1979845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1980845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len = be_to_host16(hdr->length);
1981845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (len < sizeof(*hdr) + 1 || len > msglen) {
1982845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
1983845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
1984845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
1985845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1986845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (const u8 *) (hdr + 1);
1987845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
1988845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (*pos == EAP_TYPE_EXPANDED) {
1989845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		int exp_vendor;
1990845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		u32 exp_type;
1991845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (len < sizeof(*hdr) + 8) {
1992845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP "
1993845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "length");
1994845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return NULL;
1995845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
1996845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos++;
1997845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		exp_vendor = WPA_GET_BE24(pos);
1998845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += 3;
1999845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		exp_type = WPA_GET_BE32(pos);
2000845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += 4;
2001845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (exp_vendor != vendor || exp_type != (u32) eap_type) {
2002845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP: Invalid expanded frame "
2003845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "type");
2004845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return NULL;
2005845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
2006845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2007845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*plen = len - sizeof(*hdr) - 8;
2008845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return pos;
2009845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	} else {
2010845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (vendor != EAP_VENDOR_IETF || *pos != eap_type) {
2011845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP: Invalid frame type");
2012845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return NULL;
2013845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
2014845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		*plen = len - sizeof(*hdr) - 1;
2015845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return pos + 1;
2016845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
2017845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2018845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2019845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2020845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
2021845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_set_config_blob - Set or add a named configuration blob
2022845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
2023845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @blob: New value for the blob
2024845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
2025845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Adds a new configuration blob or replaces the current value of an existing
2026845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * blob.
2027845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
2028845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
2029845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
2030845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
2031845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2032845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2033845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2034845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
2035845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_get_config_blob - Get a named configuration blob
2036845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
2037845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @name: Name of the blob
2038845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to blob data or %NULL if not found
2039845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
2040845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectconst struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
2041845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						   const char *name)
2042845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
2043845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
2044845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2045845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2046845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2047845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
2048845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_set_force_disabled - Set force_disabled flag
2049845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
2050845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @disabled: 1 = EAP disabled, 0 = EAP enabled
2051845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
2052845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function is used to force EAP state machine to be disabled when it is
2053845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * not in use (e.g., with WPA-PSK or plaintext connections).
2054845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
2055845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_set_force_disabled(struct eap_sm *sm, int disabled)
2056845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
2057845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->force_disabled = disabled;
2058845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2059845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2060845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2061845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
2062845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_msg_alloc - Allocate a buffer for an EAP message
2063845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @vendor: Vendor-Id (0 = IETF)
2064845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @type: EAP type
2065845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Buffer for returning message length
2066845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @payload_len: Payload length in bytes (data after Type)
2067845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @code: Message Code (EAP_CODE_*)
2068845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @identifier: Identifier
2069845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @payload: Pointer to payload pointer that will be set to point to the
2070845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * beginning of the payload or %NULL if payload pointer is not needed
2071845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the allocated message buffer or %NULL on error
2072845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
2073845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This function can be used to allocate a buffer for an EAP message and fill
2074845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * in the EAP header. This function is automatically using expanded EAP header
2075845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * if the selected Vendor-Id is not IETF. In other words, most EAP methods do
2076845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * not need to separately select which header type to use when using this
2077845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * function to allocate the message buffers.
2078845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
2079845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len,
2080845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       size_t payload_len, u8 code, u8 identifier,
2081845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       u8 **payload)
2082845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
2083845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *hdr;
2084845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos;
2085845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2086845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) +
2087845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		payload_len;
2088845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	hdr = os_malloc(*len);
2089845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (hdr) {
2090845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		hdr->code = code;
2091845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		hdr->identifier = identifier;
2092845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		hdr->length = host_to_be16(*len);
2093845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos = (u8 *) (hdr + 1);
2094845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (vendor == EAP_VENDOR_IETF) {
2095845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			*pos++ = type;
2096845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		} else {
2097845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			*pos++ = EAP_TYPE_EXPANDED;
2098845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			WPA_PUT_BE24(pos, vendor);
2099845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			pos += 3;
2100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			WPA_PUT_BE32(pos, type);
2101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			pos += 4;
2102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
2103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (payload)
2104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			*payload = pos;
2105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
2106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return hdr;
2108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /**
2112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_notify_pending - Notify that EAP method is ready to re-process a request
2113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
2114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
2115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * An EAP method can perform a pending operation (e.g., to get a response from
2116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * an external process). Once the response is available, this function can be
2117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * used to request EAPOL state machine to retry delivering the previously
2118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * received (and still unanswered) EAP request to EAP state machine.
2119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
2120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_notify_pending(struct eap_sm *sm)
2121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
2122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sm->eapol_cb->notify_pending(sm->eapol_ctx);
2123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
2126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/**
2127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * eap_invalidate_cached_session - Mark cached session data invalid
2128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @sm: Pointer to EAP state machine allocated with eap_sm_init()
2129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
2130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_invalidate_cached_session(struct eap_sm *sm)
2131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
2132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (sm)
2133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_deinit_prev_method(sm, "invalidate");
2134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
2135