1 /*
2  * hostapd / EAP Full Authenticator state machine (RFC 4137)
3  * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  *
8  * This state machine is based on the full authenticator state machine defined
9  * in RFC 4137. However, to support backend authentication in RADIUS
10  * authentication server functionality, parts of backend authenticator (also
11  * from RFC 4137) are mixed in. This functionality is enabled by setting
12  * backend_auth configuration variable to TRUE.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "crypto/sha256.h"
19 #include "eap_i.h"
20 #include "state_machine.h"
21 #include "common/wpa_ctrl.h"
22 
23 #define STATE_MACHINE_DATA struct eap_sm
24 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
25 
26 #define EAP_MAX_AUTH_ROUNDS 50
27 
28 static void eap_user_free(struct eap_user *user);
29 
30 
31 /* EAP state machines are described in RFC 4137 */
32 
33 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
34 				   int eapSRTT, int eapRTTVAR,
35 				   int methodTimeout);
36 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp);
37 static int eap_sm_getId(const struct wpabuf *data);
38 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id);
39 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id);
40 static int eap_sm_nextId(struct eap_sm *sm, int id);
41 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
42 				 size_t len);
43 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor);
44 static int eap_sm_Policy_getDecision(struct eap_sm *sm);
45 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
46 
47 
eap_get_erp_send_reauth_start(struct eap_sm * sm)48 static int eap_get_erp_send_reauth_start(struct eap_sm *sm)
49 {
50 	if (sm->eapol_cb->get_erp_send_reauth_start)
51 		return sm->eapol_cb->get_erp_send_reauth_start(sm->eapol_ctx);
52 	return 0;
53 }
54 
55 
eap_get_erp_domain(struct eap_sm * sm)56 static const char * eap_get_erp_domain(struct eap_sm *sm)
57 {
58 	if (sm->eapol_cb->get_erp_domain)
59 		return sm->eapol_cb->get_erp_domain(sm->eapol_ctx);
60 	return NULL;
61 }
62 
63 
64 #ifdef CONFIG_ERP
65 
eap_erp_get_key(struct eap_sm * sm,const char * keyname)66 static struct eap_server_erp_key * eap_erp_get_key(struct eap_sm *sm,
67 						   const char *keyname)
68 {
69 	if (sm->eapol_cb->erp_get_key)
70 		return sm->eapol_cb->erp_get_key(sm->eapol_ctx, keyname);
71 	return NULL;
72 }
73 
74 
eap_erp_add_key(struct eap_sm * sm,struct eap_server_erp_key * erp)75 static int eap_erp_add_key(struct eap_sm *sm, struct eap_server_erp_key *erp)
76 {
77 	if (sm->eapol_cb->erp_add_key)
78 		return sm->eapol_cb->erp_add_key(sm->eapol_ctx, erp);
79 	return -1;
80 }
81 
82 #endif /* CONFIG_ERP */
83 
84 
eap_sm_buildInitiateReauthStart(struct eap_sm * sm,u8 id)85 static struct wpabuf * eap_sm_buildInitiateReauthStart(struct eap_sm *sm,
86 						       u8 id)
87 {
88 	const char *domain;
89 	size_t plen = 1;
90 	struct wpabuf *msg;
91 	size_t domain_len = 0;
92 
93 	domain = eap_get_erp_domain(sm);
94 	if (domain) {
95 		domain_len = os_strlen(domain);
96 		plen += 2 + domain_len;
97 	}
98 
99 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_ERP_TYPE_REAUTH_START, plen,
100 			    EAP_CODE_INITIATE, id);
101 	if (msg == NULL)
102 		return NULL;
103 	wpabuf_put_u8(msg, 0); /* Reserved */
104 	if (domain) {
105 		/* Domain name TLV */
106 		wpabuf_put_u8(msg, EAP_ERP_TLV_DOMAIN_NAME);
107 		wpabuf_put_u8(msg, domain_len);
108 		wpabuf_put_data(msg, domain, domain_len);
109 	}
110 
111 	return msg;
112 }
113 
114 
eap_copy_buf(struct wpabuf ** dst,const struct wpabuf * src)115 static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
116 {
117 	if (src == NULL)
118 		return -1;
119 
120 	wpabuf_free(*dst);
121 	*dst = wpabuf_dup(src);
122 	return *dst ? 0 : -1;
123 }
124 
125 
eap_copy_data(u8 ** dst,size_t * dst_len,const u8 * src,size_t src_len)126 static int eap_copy_data(u8 **dst, size_t *dst_len,
127 			 const u8 *src, size_t src_len)
128 {
129 	if (src == NULL)
130 		return -1;
131 
132 	os_free(*dst);
133 	*dst = os_malloc(src_len);
134 	if (*dst) {
135 		os_memcpy(*dst, src, src_len);
136 		*dst_len = src_len;
137 		return 0;
138 	} else {
139 		*dst_len = 0;
140 		return -1;
141 	}
142 }
143 
144 #define EAP_COPY(dst, src) \
145 	eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
146 
147 
148 /**
149  * eap_user_get - Fetch user information from the database
150  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
151  * @identity: Identity (User-Name) of the user
152  * @identity_len: Length of identity in bytes
153  * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user
154  * Returns: 0 on success, or -1 on failure
155  *
156  * This function is used to fetch user information for EAP. The user will be
157  * selected based on the specified identity. sm->user and
158  * sm->user_eap_method_index are updated for the new user when a matching user
159  * is found. sm->user can be used to get user information (e.g., password).
160  */
eap_user_get(struct eap_sm * sm,const u8 * identity,size_t identity_len,int phase2)161 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
162 		 int phase2)
163 {
164 	struct eap_user *user;
165 
166 	if (sm == NULL || sm->eapol_cb == NULL ||
167 	    sm->eapol_cb->get_eap_user == NULL)
168 		return -1;
169 
170 	eap_user_free(sm->user);
171 	sm->user = NULL;
172 
173 	user = os_zalloc(sizeof(*user));
174 	if (user == NULL)
175 	    return -1;
176 
177 	if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
178 				       identity_len, phase2, user) != 0) {
179 		eap_user_free(user);
180 		return -1;
181 	}
182 
183 	sm->user = user;
184 	sm->user_eap_method_index = 0;
185 
186 	return 0;
187 }
188 
189 
eap_log_msg(struct eap_sm * sm,const char * fmt,...)190 void eap_log_msg(struct eap_sm *sm, const char *fmt, ...)
191 {
192 	va_list ap;
193 	char *buf;
194 	int buflen;
195 
196 	if (sm == NULL || sm->eapol_cb == NULL || sm->eapol_cb->log_msg == NULL)
197 		return;
198 
199 	va_start(ap, fmt);
200 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
201 	va_end(ap);
202 
203 	buf = os_malloc(buflen);
204 	if (buf == NULL)
205 		return;
206 	va_start(ap, fmt);
207 	vsnprintf(buf, buflen, fmt, ap);
208 	va_end(ap);
209 
210 	sm->eapol_cb->log_msg(sm->eapol_ctx, buf);
211 
212 	os_free(buf);
213 }
214 
215 
SM_STATE(EAP,DISABLED)216 SM_STATE(EAP, DISABLED)
217 {
218 	SM_ENTRY(EAP, DISABLED);
219 	sm->num_rounds = 0;
220 }
221 
222 
SM_STATE(EAP,INITIALIZE)223 SM_STATE(EAP, INITIALIZE)
224 {
225 	SM_ENTRY(EAP, INITIALIZE);
226 
227 	if (sm->eap_if.eapRestart && !sm->eap_server && sm->identity) {
228 		/*
229 		 * Need to allow internal Identity method to be used instead
230 		 * of passthrough at the beginning of reauthentication.
231 		 */
232 		eap_server_clear_identity(sm);
233 	}
234 
235 	sm->try_initiate_reauth = FALSE;
236 	sm->currentId = -1;
237 	sm->eap_if.eapSuccess = FALSE;
238 	sm->eap_if.eapFail = FALSE;
239 	sm->eap_if.eapTimeout = FALSE;
240 	bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
241 	sm->eap_if.eapKeyData = NULL;
242 	sm->eap_if.eapKeyDataLen = 0;
243 	os_free(sm->eap_if.eapSessionId);
244 	sm->eap_if.eapSessionId = NULL;
245 	sm->eap_if.eapSessionIdLen = 0;
246 	sm->eap_if.eapKeyAvailable = FALSE;
247 	sm->eap_if.eapRestart = FALSE;
248 
249 	/*
250 	 * This is not defined in RFC 4137, but method state needs to be
251 	 * reseted here so that it does not remain in success state when
252 	 * re-authentication starts.
253 	 */
254 	if (sm->m && sm->eap_method_priv) {
255 		sm->m->reset(sm, sm->eap_method_priv);
256 		sm->eap_method_priv = NULL;
257 	}
258 	sm->m = NULL;
259 	sm->user_eap_method_index = 0;
260 
261 	if (sm->backend_auth) {
262 		sm->currentMethod = EAP_TYPE_NONE;
263 		/* parse rxResp, respId, respMethod */
264 		eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
265 		if (sm->rxResp) {
266 			sm->currentId = sm->respId;
267 		}
268 	}
269 	sm->num_rounds = 0;
270 	sm->method_pending = METHOD_PENDING_NONE;
271 
272 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
273 		MACSTR, MAC2STR(sm->peer_addr));
274 }
275 
276 
SM_STATE(EAP,PICK_UP_METHOD)277 SM_STATE(EAP, PICK_UP_METHOD)
278 {
279 	SM_ENTRY(EAP, PICK_UP_METHOD);
280 
281 	if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
282 		sm->currentMethod = sm->respMethod;
283 		if (sm->m && sm->eap_method_priv) {
284 			sm->m->reset(sm, sm->eap_method_priv);
285 			sm->eap_method_priv = NULL;
286 		}
287 		sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF,
288 						  sm->currentMethod);
289 		if (sm->m && sm->m->initPickUp) {
290 			sm->eap_method_priv = sm->m->initPickUp(sm);
291 			if (sm->eap_method_priv == NULL) {
292 				wpa_printf(MSG_DEBUG, "EAP: Failed to "
293 					   "initialize EAP method %d",
294 					   sm->currentMethod);
295 				sm->m = NULL;
296 				sm->currentMethod = EAP_TYPE_NONE;
297 			}
298 		} else {
299 			sm->m = NULL;
300 			sm->currentMethod = EAP_TYPE_NONE;
301 		}
302 	}
303 
304 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
305 		"method=%u", sm->currentMethod);
306 }
307 
308 
SM_STATE(EAP,IDLE)309 SM_STATE(EAP, IDLE)
310 {
311 	SM_ENTRY(EAP, IDLE);
312 
313 	sm->eap_if.retransWhile = eap_sm_calculateTimeout(
314 		sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
315 		sm->methodTimeout);
316 }
317 
318 
SM_STATE(EAP,RETRANSMIT)319 SM_STATE(EAP, RETRANSMIT)
320 {
321 	SM_ENTRY(EAP, RETRANSMIT);
322 
323 	sm->retransCount++;
324 	if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
325 		if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
326 			sm->eap_if.eapReq = TRUE;
327 	}
328 }
329 
330 
SM_STATE(EAP,RECEIVED)331 SM_STATE(EAP, RECEIVED)
332 {
333 	SM_ENTRY(EAP, RECEIVED);
334 
335 	/* parse rxResp, respId, respMethod */
336 	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
337 	sm->num_rounds++;
338 }
339 
340 
SM_STATE(EAP,DISCARD)341 SM_STATE(EAP, DISCARD)
342 {
343 	SM_ENTRY(EAP, DISCARD);
344 	sm->eap_if.eapResp = FALSE;
345 	sm->eap_if.eapNoReq = TRUE;
346 }
347 
348 
SM_STATE(EAP,SEND_REQUEST)349 SM_STATE(EAP, SEND_REQUEST)
350 {
351 	SM_ENTRY(EAP, SEND_REQUEST);
352 
353 	sm->retransCount = 0;
354 	if (sm->eap_if.eapReqData) {
355 		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
356 		{
357 			sm->eap_if.eapResp = FALSE;
358 			sm->eap_if.eapReq = TRUE;
359 		} else {
360 			sm->eap_if.eapResp = FALSE;
361 			sm->eap_if.eapReq = FALSE;
362 		}
363 	} else {
364 		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
365 		sm->eap_if.eapResp = FALSE;
366 		sm->eap_if.eapReq = FALSE;
367 		sm->eap_if.eapNoReq = TRUE;
368 	}
369 }
370 
371 
SM_STATE(EAP,INTEGRITY_CHECK)372 SM_STATE(EAP, INTEGRITY_CHECK)
373 {
374 	SM_ENTRY(EAP, INTEGRITY_CHECK);
375 
376 	if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) {
377 		sm->ignore = TRUE;
378 		return;
379 	}
380 
381 	if (sm->m->check) {
382 		sm->ignore = sm->m->check(sm, sm->eap_method_priv,
383 					  sm->eap_if.eapRespData);
384 	}
385 }
386 
387 
SM_STATE(EAP,METHOD_REQUEST)388 SM_STATE(EAP, METHOD_REQUEST)
389 {
390 	SM_ENTRY(EAP, METHOD_REQUEST);
391 
392 	if (sm->m == NULL) {
393 		wpa_printf(MSG_DEBUG, "EAP: method not initialized");
394 		return;
395 	}
396 
397 	sm->currentId = eap_sm_nextId(sm, sm->currentId);
398 	wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
399 		   sm->currentId);
400 	sm->lastId = sm->currentId;
401 	wpabuf_free(sm->eap_if.eapReqData);
402 	sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
403 						sm->currentId);
404 	if (sm->m->getTimeout)
405 		sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
406 	else
407 		sm->methodTimeout = 0;
408 }
409 
410 
eap_server_erp_init(struct eap_sm * sm)411 static void eap_server_erp_init(struct eap_sm *sm)
412 {
413 #ifdef CONFIG_ERP
414 	u8 *emsk = NULL;
415 	size_t emsk_len = 0;
416 	u8 EMSKname[EAP_EMSK_NAME_LEN];
417 	u8 len[2];
418 	const char *domain;
419 	size_t domain_len, nai_buf_len;
420 	struct eap_server_erp_key *erp = NULL;
421 	int pos;
422 
423 	domain = eap_get_erp_domain(sm);
424 	if (!domain)
425 		return;
426 
427 	domain_len = os_strlen(domain);
428 
429 	nai_buf_len = 2 * EAP_EMSK_NAME_LEN + 1 + domain_len;
430 	if (nai_buf_len > 253) {
431 		/*
432 		 * keyName-NAI has a maximum length of 253 octet to fit in
433 		 * RADIUS attributes.
434 		 */
435 		wpa_printf(MSG_DEBUG,
436 			   "EAP: Too long realm for ERP keyName-NAI maximum length");
437 		return;
438 	}
439 	nai_buf_len++; /* null termination */
440 	erp = os_zalloc(sizeof(*erp) + nai_buf_len);
441 	if (erp == NULL)
442 		goto fail;
443 	erp->recv_seq = (u32) -1;
444 
445 	emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
446 	if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) {
447 		wpa_printf(MSG_DEBUG,
448 			   "EAP: No suitable EMSK available for ERP");
449 		goto fail;
450 	}
451 
452 	wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len);
453 
454 	WPA_PUT_BE16(len, 8);
455 	if (hmac_sha256_kdf(sm->eap_if.eapSessionId, sm->eap_if.eapSessionIdLen,
456 			    "EMSK", len, sizeof(len),
457 			    EMSKname, EAP_EMSK_NAME_LEN) < 0) {
458 		wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname");
459 		goto fail;
460 	}
461 	wpa_hexdump(MSG_DEBUG, "EAP: EMSKname", EMSKname, EAP_EMSK_NAME_LEN);
462 
463 	pos = wpa_snprintf_hex(erp->keyname_nai, nai_buf_len,
464 			       EMSKname, EAP_EMSK_NAME_LEN);
465 	erp->keyname_nai[pos] = '@';
466 	os_memcpy(&erp->keyname_nai[pos + 1], domain, domain_len);
467 
468 	WPA_PUT_BE16(len, emsk_len);
469 	if (hmac_sha256_kdf(emsk, emsk_len,
470 			    "EAP Re-authentication Root Key@ietf.org",
471 			    len, sizeof(len), erp->rRK, emsk_len) < 0) {
472 		wpa_printf(MSG_DEBUG, "EAP: Could not derive rRK for ERP");
473 		goto fail;
474 	}
475 	erp->rRK_len = emsk_len;
476 	wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len);
477 
478 	if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
479 			    "EAP Re-authentication Integrity Key@ietf.org",
480 			    len, sizeof(len), erp->rIK, erp->rRK_len) < 0) {
481 		wpa_printf(MSG_DEBUG, "EAP: Could not derive rIK for ERP");
482 		goto fail;
483 	}
484 	erp->rIK_len = erp->rRK_len;
485 	wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rIK", erp->rIK, erp->rIK_len);
486 
487 	if (eap_erp_add_key(sm, erp) == 0) {
488 		wpa_printf(MSG_DEBUG, "EAP: Stored ERP keys %s",
489 			   erp->keyname_nai);
490 		erp = NULL;
491 	}
492 
493 fail:
494 	bin_clear_free(emsk, emsk_len);
495 	bin_clear_free(erp, sizeof(*erp));
496 #endif /* CONFIG_ERP */
497 }
498 
499 
SM_STATE(EAP,METHOD_RESPONSE)500 SM_STATE(EAP, METHOD_RESPONSE)
501 {
502 	SM_ENTRY(EAP, METHOD_RESPONSE);
503 
504 	if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
505 		return;
506 
507 	sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
508 	if (sm->m->isDone(sm, sm->eap_method_priv)) {
509 		eap_sm_Policy_update(sm, NULL, 0);
510 		bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
511 		if (sm->m->getKey) {
512 			sm->eap_if.eapKeyData = sm->m->getKey(
513 				sm, sm->eap_method_priv,
514 				&sm->eap_if.eapKeyDataLen);
515 		} else {
516 			sm->eap_if.eapKeyData = NULL;
517 			sm->eap_if.eapKeyDataLen = 0;
518 		}
519 		os_free(sm->eap_if.eapSessionId);
520 		sm->eap_if.eapSessionId = NULL;
521 		if (sm->m->getSessionId) {
522 			sm->eap_if.eapSessionId = sm->m->getSessionId(
523 				sm, sm->eap_method_priv,
524 				&sm->eap_if.eapSessionIdLen);
525 			wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
526 				    sm->eap_if.eapSessionId,
527 				    sm->eap_if.eapSessionIdLen);
528 		}
529 		if (sm->erp && sm->m->get_emsk && sm->eap_if.eapSessionId)
530 			eap_server_erp_init(sm);
531 		sm->methodState = METHOD_END;
532 	} else {
533 		sm->methodState = METHOD_CONTINUE;
534 	}
535 }
536 
537 
SM_STATE(EAP,PROPOSE_METHOD)538 SM_STATE(EAP, PROPOSE_METHOD)
539 {
540 	int vendor;
541 	EapType type;
542 
543 	SM_ENTRY(EAP, PROPOSE_METHOD);
544 
545 	sm->try_initiate_reauth = FALSE;
546 try_another_method:
547 	type = eap_sm_Policy_getNextMethod(sm, &vendor);
548 	if (vendor == EAP_VENDOR_IETF)
549 		sm->currentMethod = type;
550 	else
551 		sm->currentMethod = EAP_TYPE_EXPANDED;
552 	if (sm->m && sm->eap_method_priv) {
553 		sm->m->reset(sm, sm->eap_method_priv);
554 		sm->eap_method_priv = NULL;
555 	}
556 	sm->m = eap_server_get_eap_method(vendor, type);
557 	if (sm->m) {
558 		sm->eap_method_priv = sm->m->init(sm);
559 		if (sm->eap_method_priv == NULL) {
560 			wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
561 				   "method %d", sm->currentMethod);
562 			sm->m = NULL;
563 			sm->currentMethod = EAP_TYPE_NONE;
564 			goto try_another_method;
565 		}
566 	}
567 	if (sm->m == NULL) {
568 		wpa_printf(MSG_DEBUG, "EAP: Could not find suitable EAP method");
569 		eap_log_msg(sm, "Could not find suitable EAP method");
570 		sm->decision = DECISION_FAILURE;
571 		return;
572 	}
573 	if (sm->currentMethod == EAP_TYPE_IDENTITY ||
574 	    sm->currentMethod == EAP_TYPE_NOTIFICATION)
575 		sm->methodState = METHOD_CONTINUE;
576 	else
577 		sm->methodState = METHOD_PROPOSED;
578 
579 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
580 		"vendor=%u method=%u", vendor, sm->currentMethod);
581 	eap_log_msg(sm, "Propose EAP method vendor=%u method=%u",
582 		    vendor, sm->currentMethod);
583 }
584 
585 
SM_STATE(EAP,NAK)586 SM_STATE(EAP, NAK)
587 {
588 	const struct eap_hdr *nak;
589 	size_t len = 0;
590 	const u8 *pos;
591 	const u8 *nak_list = NULL;
592 
593 	SM_ENTRY(EAP, NAK);
594 
595 	if (sm->eap_method_priv) {
596 		sm->m->reset(sm, sm->eap_method_priv);
597 		sm->eap_method_priv = NULL;
598 	}
599 	sm->m = NULL;
600 
601 	if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
602 		return;
603 
604 	nak = wpabuf_head(sm->eap_if.eapRespData);
605 	if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
606 		len = be_to_host16(nak->length);
607 		if (len > wpabuf_len(sm->eap_if.eapRespData))
608 			len = wpabuf_len(sm->eap_if.eapRespData);
609 		pos = (const u8 *) (nak + 1);
610 		len -= sizeof(*nak);
611 		if (*pos == EAP_TYPE_NAK) {
612 			pos++;
613 			len--;
614 			nak_list = pos;
615 		}
616 	}
617 	eap_sm_Policy_update(sm, nak_list, len);
618 }
619 
620 
SM_STATE(EAP,SELECT_ACTION)621 SM_STATE(EAP, SELECT_ACTION)
622 {
623 	SM_ENTRY(EAP, SELECT_ACTION);
624 
625 	sm->decision = eap_sm_Policy_getDecision(sm);
626 }
627 
628 
SM_STATE(EAP,TIMEOUT_FAILURE)629 SM_STATE(EAP, TIMEOUT_FAILURE)
630 {
631 	SM_ENTRY(EAP, TIMEOUT_FAILURE);
632 
633 	sm->eap_if.eapTimeout = TRUE;
634 }
635 
636 
SM_STATE(EAP,FAILURE)637 SM_STATE(EAP, FAILURE)
638 {
639 	SM_ENTRY(EAP, FAILURE);
640 
641 	wpabuf_free(sm->eap_if.eapReqData);
642 	sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId);
643 	wpabuf_free(sm->lastReqData);
644 	sm->lastReqData = NULL;
645 	sm->eap_if.eapFail = TRUE;
646 
647 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
648 		MACSTR, MAC2STR(sm->peer_addr));
649 }
650 
651 
SM_STATE(EAP,SUCCESS)652 SM_STATE(EAP, SUCCESS)
653 {
654 	SM_ENTRY(EAP, SUCCESS);
655 
656 	wpabuf_free(sm->eap_if.eapReqData);
657 	sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId);
658 	wpabuf_free(sm->lastReqData);
659 	sm->lastReqData = NULL;
660 	if (sm->eap_if.eapKeyData)
661 		sm->eap_if.eapKeyAvailable = TRUE;
662 	sm->eap_if.eapSuccess = TRUE;
663 
664 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
665 		MACSTR, MAC2STR(sm->peer_addr));
666 }
667 
668 
SM_STATE(EAP,INITIATE_REAUTH_START)669 SM_STATE(EAP, INITIATE_REAUTH_START)
670 {
671 	SM_ENTRY(EAP, INITIATE_REAUTH_START);
672 
673 	sm->initiate_reauth_start_sent = TRUE;
674 	sm->try_initiate_reauth = TRUE;
675 	sm->currentId = eap_sm_nextId(sm, sm->currentId);
676 	wpa_printf(MSG_DEBUG,
677 		   "EAP: building EAP-Initiate-Re-auth-Start: Identifier %d",
678 		   sm->currentId);
679 	sm->lastId = sm->currentId;
680 	wpabuf_free(sm->eap_if.eapReqData);
681 	sm->eap_if.eapReqData = eap_sm_buildInitiateReauthStart(sm,
682 								sm->currentId);
683 	wpabuf_free(sm->lastReqData);
684 	sm->lastReqData = NULL;
685 }
686 
687 
688 #ifdef CONFIG_ERP
689 
erp_send_finish_reauth(struct eap_sm * sm,struct eap_server_erp_key * erp,u8 id,u8 flags,u16 seq,const char * nai)690 static void erp_send_finish_reauth(struct eap_sm *sm,
691 				   struct eap_server_erp_key *erp, u8 id,
692 				   u8 flags, u16 seq, const char *nai)
693 {
694 	size_t plen;
695 	struct wpabuf *msg;
696 	u8 hash[SHA256_MAC_LEN];
697 	size_t hash_len;
698 	u8 seed[4];
699 
700 	if (erp) {
701 		switch (erp->cryptosuite) {
702 		case EAP_ERP_CS_HMAC_SHA256_256:
703 			hash_len = 32;
704 			break;
705 		case EAP_ERP_CS_HMAC_SHA256_128:
706 			hash_len = 16;
707 			break;
708 		default:
709 			return;
710 		}
711 	} else
712 		hash_len = 0;
713 
714 	plen = 1 + 2 + 2 + os_strlen(nai);
715 	if (hash_len)
716 		plen += 1 + hash_len;
717 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_ERP_TYPE_REAUTH, plen,
718 			    EAP_CODE_FINISH, id);
719 	if (msg == NULL)
720 		return;
721 	wpabuf_put_u8(msg, flags);
722 	wpabuf_put_be16(msg, seq);
723 
724 	wpabuf_put_u8(msg, EAP_ERP_TLV_KEYNAME_NAI);
725 	wpabuf_put_u8(msg, os_strlen(nai));
726 	wpabuf_put_str(msg, nai);
727 
728 	if (erp) {
729 		wpabuf_put_u8(msg, erp->cryptosuite);
730 		if (hmac_sha256(erp->rIK, erp->rIK_len,
731 				wpabuf_head(msg), wpabuf_len(msg), hash) < 0) {
732 			wpabuf_free(msg);
733 			return;
734 		}
735 		wpabuf_put_data(msg, hash, hash_len);
736 	}
737 
738 	wpa_printf(MSG_DEBUG, "EAP: Send EAP-Finish/Re-auth (%s)",
739 		   flags & 0x80 ? "failure" : "success");
740 
741 	sm->lastId = sm->currentId;
742 	sm->currentId = id;
743 	wpabuf_free(sm->eap_if.eapReqData);
744 	sm->eap_if.eapReqData = msg;
745 	wpabuf_free(sm->lastReqData);
746 	sm->lastReqData = NULL;
747 
748 	if ((flags & 0x80) || !erp) {
749 		sm->eap_if.eapFail = TRUE;
750 		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
751 			MACSTR, MAC2STR(sm->peer_addr));
752 		return;
753 	}
754 
755 	bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
756 	sm->eap_if.eapKeyDataLen = 0;
757 	sm->eap_if.eapKeyData = os_malloc(erp->rRK_len);
758 	if (!sm->eap_if.eapKeyData)
759 		return;
760 
761 	WPA_PUT_BE16(seed, seq);
762 	WPA_PUT_BE16(&seed[2], erp->rRK_len);
763 	if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
764 			    "Re-authentication Master Session Key@ietf.org",
765 			    seed, sizeof(seed),
766 			    sm->eap_if.eapKeyData, erp->rRK_len) < 0) {
767 		wpa_printf(MSG_DEBUG, "EAP: Could not derive rMSK for ERP");
768 		bin_clear_free(sm->eap_if.eapKeyData, erp->rRK_len);
769 		sm->eap_if.eapKeyData = NULL;
770 		return;
771 	}
772 	sm->eap_if.eapKeyDataLen = erp->rRK_len;
773 	sm->eap_if.eapKeyAvailable = TRUE;
774 	wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK",
775 			sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
776 	sm->eap_if.eapSuccess = TRUE;
777 
778 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
779 		MACSTR, MAC2STR(sm->peer_addr));
780 }
781 
782 
SM_STATE(EAP,INITIATE_RECEIVED)783 SM_STATE(EAP, INITIATE_RECEIVED)
784 {
785 	const u8 *pos, *end, *start, *tlvs, *hdr;
786 	const struct eap_hdr *ehdr;
787 	size_t len;
788 	u8 flags;
789 	u16 seq;
790 	char nai[254];
791 	struct eap_server_erp_key *erp;
792 	int max_len;
793 	u8 hash[SHA256_MAC_LEN];
794 	size_t hash_len;
795 	struct erp_tlvs parse;
796 	u8 resp_flags = 0x80; /* default to failure; cleared on success */
797 
798 	SM_ENTRY(EAP, INITIATE_RECEIVED);
799 
800 	sm->rxInitiate = FALSE;
801 
802 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_ERP_TYPE_REAUTH,
803 			       sm->eap_if.eapRespData, &len);
804 	if (pos == NULL) {
805 		wpa_printf(MSG_INFO, "EAP-Initiate: Invalid frame");
806 		goto fail;
807 	}
808 	hdr = wpabuf_head(sm->eap_if.eapRespData);
809 	ehdr = wpabuf_head(sm->eap_if.eapRespData);
810 
811 	wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-Auth", pos, len);
812 	if (len < 4) {
813 		wpa_printf(MSG_INFO, "EAP: Too short EAP-Initiate/Re-auth");
814 		goto fail;
815 	}
816 	end = pos + len;
817 
818 	flags = *pos++;
819 	seq = WPA_GET_BE16(pos);
820 	pos += 2;
821 	wpa_printf(MSG_DEBUG, "EAP: Flags=0x%x SEQ=%u", flags, seq);
822 	tlvs = pos;
823 
824 	/*
825 	 * Parse TVs/TLVs. Since we do not yet know the length of the
826 	 * Authentication Tag, stop parsing if an unknown TV/TLV is seen and
827 	 * just try to find the keyName-NAI first so that we can check the
828 	 * Authentication Tag.
829 	 */
830 	if (erp_parse_tlvs(tlvs, end, &parse, 1) < 0)
831 		goto fail;
832 
833 	if (!parse.keyname) {
834 		wpa_printf(MSG_DEBUG,
835 			   "EAP: No keyName-NAI in EAP-Initiate/Re-auth Packet");
836 		goto fail;
837 	}
838 
839 	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth - keyName-NAI",
840 			  parse.keyname, parse.keyname_len);
841 	if (parse.keyname_len > 253) {
842 		wpa_printf(MSG_DEBUG,
843 			   "EAP: Too long keyName-NAI in EAP-Initiate/Re-auth");
844 		goto fail;
845 	}
846 	os_memcpy(nai, parse.keyname, parse.keyname_len);
847 	nai[parse.keyname_len] = '\0';
848 
849 	if (!sm->eap_server) {
850 		/*
851 		 * In passthrough case, EAP-Initiate/Re-auth replaces
852 		 * EAP Identity exchange. Use keyName-NAI as the user identity
853 		 * and forward EAP-Initiate/Re-auth to the backend
854 		 * authentication server.
855 		 */
856 		wpa_printf(MSG_DEBUG,
857 			   "EAP: Use keyName-NAI as user identity for backend authentication");
858 		eap_server_clear_identity(sm);
859 		sm->identity = (u8 *) dup_binstr(parse.keyname,
860 						 parse.keyname_len);
861 		if (!sm->identity)
862 			goto fail;
863 		sm->identity_len = parse.keyname_len;
864 		return;
865 	}
866 
867 	erp = eap_erp_get_key(sm, nai);
868 	if (!erp) {
869 		wpa_printf(MSG_DEBUG, "EAP: No matching ERP key found for %s",
870 			   nai);
871 		goto report_error;
872 	}
873 
874 	if (erp->recv_seq != (u32) -1 && erp->recv_seq >= seq) {
875 		wpa_printf(MSG_DEBUG,
876 			   "EAP: SEQ=%u replayed (already received SEQ=%u)",
877 			   seq, erp->recv_seq);
878 		goto fail;
879 	}
880 
881 	/* Is there enough room for Cryptosuite and Authentication Tag? */
882 	start = parse.keyname + parse.keyname_len;
883 	max_len = end - start;
884 	if (max_len <
885 	    1 + (erp->cryptosuite == EAP_ERP_CS_HMAC_SHA256_256 ? 32 : 16)) {
886 		wpa_printf(MSG_DEBUG,
887 			   "EAP: Not enough room for Authentication Tag");
888 		goto fail;
889 	}
890 
891 	switch (erp->cryptosuite) {
892 	case EAP_ERP_CS_HMAC_SHA256_256:
893 		if (end[-33] != erp->cryptosuite) {
894 			wpa_printf(MSG_DEBUG,
895 				   "EAP: Different Cryptosuite used");
896 			goto fail;
897 		}
898 		hash_len = 32;
899 		break;
900 	case EAP_ERP_CS_HMAC_SHA256_128:
901 		if (end[-17] != erp->cryptosuite) {
902 			wpa_printf(MSG_DEBUG,
903 				   "EAP: Different Cryptosuite used");
904 			goto fail;
905 		}
906 		hash_len = 16;
907 		break;
908 	default:
909 		hash_len = 0;
910 		break;
911 	}
912 
913 	if (hash_len) {
914 		if (hmac_sha256(erp->rIK, erp->rIK_len, hdr,
915 				end - hdr - hash_len, hash) < 0)
916 			goto fail;
917 		if (os_memcmp(end - hash_len, hash, hash_len) != 0) {
918 			wpa_printf(MSG_DEBUG,
919 				   "EAP: Authentication Tag mismatch");
920 			goto fail;
921 		}
922 	}
923 
924 	/* Check if any supported CS results in matching tag */
925 	if (!hash_len && max_len >= 1 + 32 &&
926 	    end[-33] == EAP_ERP_CS_HMAC_SHA256_256) {
927 		if (hmac_sha256(erp->rIK, erp->rIK_len, hdr,
928 				end - hdr - 32, hash) < 0)
929 			goto fail;
930 		if (os_memcmp(end - 32, hash, 32) == 0) {
931 			wpa_printf(MSG_DEBUG,
932 				   "EAP: Authentication Tag match using HMAC-SHA256-256");
933 			hash_len = 32;
934 			erp->cryptosuite = EAP_ERP_CS_HMAC_SHA256_256;
935 		}
936 	}
937 
938 	if (!hash_len && end[-17] == EAP_ERP_CS_HMAC_SHA256_128) {
939 		if (hmac_sha256(erp->rIK, erp->rIK_len, hdr,
940 				end - hdr - 16, hash) < 0)
941 			goto fail;
942 		if (os_memcmp(end - 16, hash, 16) == 0) {
943 			wpa_printf(MSG_DEBUG,
944 				   "EAP: Authentication Tag match using HMAC-SHA256-128");
945 			hash_len = 16;
946 			erp->cryptosuite = EAP_ERP_CS_HMAC_SHA256_128;
947 		}
948 	}
949 
950 	if (!hash_len) {
951 		wpa_printf(MSG_DEBUG,
952 			   "EAP: No supported cryptosuite matched Authentication Tag");
953 		goto fail;
954 	}
955 	end -= 1 + hash_len;
956 
957 	/*
958 	 * Parse TVs/TLVs again now that we know the exact part of the buffer
959 	 * that contains them.
960 	 */
961 	wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-Auth TVs/TLVs",
962 		    tlvs, end - tlvs);
963 	if (erp_parse_tlvs(tlvs, end, &parse, 0) < 0)
964 		goto fail;
965 
966 	wpa_printf(MSG_DEBUG, "EAP: ERP key %s SEQ updated to %u",
967 		   erp->keyname_nai, seq);
968 	erp->recv_seq = seq;
969 	resp_flags &= ~0x80; /* R=0 - success */
970 
971 report_error:
972 	erp_send_finish_reauth(sm, erp, ehdr->identifier, resp_flags, seq, nai);
973 	return;
974 
975 fail:
976 	sm->ignore = TRUE;
977 }
978 
979 #endif /* CONFIG_ERP */
980 
981 
SM_STATE(EAP,INITIALIZE_PASSTHROUGH)982 SM_STATE(EAP, INITIALIZE_PASSTHROUGH)
983 {
984 	SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
985 
986 	wpabuf_free(sm->eap_if.aaaEapRespData);
987 	sm->eap_if.aaaEapRespData = NULL;
988 	sm->try_initiate_reauth = FALSE;
989 }
990 
991 
SM_STATE(EAP,IDLE2)992 SM_STATE(EAP, IDLE2)
993 {
994 	SM_ENTRY(EAP, IDLE2);
995 
996 	sm->eap_if.retransWhile = eap_sm_calculateTimeout(
997 		sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
998 		sm->methodTimeout);
999 }
1000 
1001 
SM_STATE(EAP,RETRANSMIT2)1002 SM_STATE(EAP, RETRANSMIT2)
1003 {
1004 	SM_ENTRY(EAP, RETRANSMIT2);
1005 
1006 	sm->retransCount++;
1007 	if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
1008 		if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
1009 			sm->eap_if.eapReq = TRUE;
1010 	}
1011 }
1012 
1013 
SM_STATE(EAP,RECEIVED2)1014 SM_STATE(EAP, RECEIVED2)
1015 {
1016 	SM_ENTRY(EAP, RECEIVED2);
1017 
1018 	/* parse rxResp, respId, respMethod */
1019 	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
1020 }
1021 
1022 
SM_STATE(EAP,DISCARD2)1023 SM_STATE(EAP, DISCARD2)
1024 {
1025 	SM_ENTRY(EAP, DISCARD2);
1026 	sm->eap_if.eapResp = FALSE;
1027 	sm->eap_if.eapNoReq = TRUE;
1028 }
1029 
1030 
SM_STATE(EAP,SEND_REQUEST2)1031 SM_STATE(EAP, SEND_REQUEST2)
1032 {
1033 	SM_ENTRY(EAP, SEND_REQUEST2);
1034 
1035 	sm->retransCount = 0;
1036 	if (sm->eap_if.eapReqData) {
1037 		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
1038 		{
1039 			sm->eap_if.eapResp = FALSE;
1040 			sm->eap_if.eapReq = TRUE;
1041 		} else {
1042 			sm->eap_if.eapResp = FALSE;
1043 			sm->eap_if.eapReq = FALSE;
1044 		}
1045 	} else {
1046 		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData");
1047 		sm->eap_if.eapResp = FALSE;
1048 		sm->eap_if.eapReq = FALSE;
1049 		sm->eap_if.eapNoReq = TRUE;
1050 	}
1051 }
1052 
1053 
SM_STATE(EAP,AAA_REQUEST)1054 SM_STATE(EAP, AAA_REQUEST)
1055 {
1056 	SM_ENTRY(EAP, AAA_REQUEST);
1057 
1058 	if (sm->eap_if.eapRespData == NULL) {
1059 		wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData");
1060 		return;
1061 	}
1062 
1063 	/*
1064 	 * if (respMethod == IDENTITY)
1065 	 *	aaaIdentity = eapRespData
1066 	 * This is already taken care of by the EAP-Identity method which
1067 	 * stores the identity into sm->identity.
1068 	 */
1069 
1070 	eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData);
1071 }
1072 
1073 
SM_STATE(EAP,AAA_RESPONSE)1074 SM_STATE(EAP, AAA_RESPONSE)
1075 {
1076 	SM_ENTRY(EAP, AAA_RESPONSE);
1077 
1078 	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
1079 	sm->currentId = eap_sm_getId(sm->eap_if.eapReqData);
1080 	sm->methodTimeout = sm->eap_if.aaaMethodTimeout;
1081 }
1082 
1083 
SM_STATE(EAP,AAA_IDLE)1084 SM_STATE(EAP, AAA_IDLE)
1085 {
1086 	SM_ENTRY(EAP, AAA_IDLE);
1087 
1088 	sm->eap_if.aaaFail = FALSE;
1089 	sm->eap_if.aaaSuccess = FALSE;
1090 	sm->eap_if.aaaEapReq = FALSE;
1091 	sm->eap_if.aaaEapNoReq = FALSE;
1092 	sm->eap_if.aaaEapResp = TRUE;
1093 }
1094 
1095 
SM_STATE(EAP,TIMEOUT_FAILURE2)1096 SM_STATE(EAP, TIMEOUT_FAILURE2)
1097 {
1098 	SM_ENTRY(EAP, TIMEOUT_FAILURE2);
1099 
1100 	sm->eap_if.eapTimeout = TRUE;
1101 }
1102 
1103 
SM_STATE(EAP,FAILURE2)1104 SM_STATE(EAP, FAILURE2)
1105 {
1106 	SM_ENTRY(EAP, FAILURE2);
1107 
1108 	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
1109 	sm->eap_if.eapFail = TRUE;
1110 }
1111 
1112 
SM_STATE(EAP,SUCCESS2)1113 SM_STATE(EAP, SUCCESS2)
1114 {
1115 	SM_ENTRY(EAP, SUCCESS2);
1116 
1117 	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
1118 
1119 	sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable;
1120 	if (sm->eap_if.aaaEapKeyAvailable) {
1121 		EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
1122 	} else {
1123 		bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
1124 		sm->eap_if.eapKeyData = NULL;
1125 		sm->eap_if.eapKeyDataLen = 0;
1126 	}
1127 
1128 	sm->eap_if.eapSuccess = TRUE;
1129 
1130 	/*
1131 	 * Start reauthentication with identity request even though we know the
1132 	 * previously used identity. This is needed to get reauthentication
1133 	 * started properly.
1134 	 */
1135 	sm->start_reauth = TRUE;
1136 }
1137 
1138 
SM_STEP(EAP)1139 SM_STEP(EAP)
1140 {
1141 	if (sm->eap_if.eapRestart && sm->eap_if.portEnabled)
1142 		SM_ENTER_GLOBAL(EAP, INITIALIZE);
1143 	else if (!sm->eap_if.portEnabled)
1144 		SM_ENTER_GLOBAL(EAP, DISABLED);
1145 	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
1146 		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
1147 			wpa_printf(MSG_DEBUG, "EAP: more than %d "
1148 				   "authentication rounds - abort",
1149 				   EAP_MAX_AUTH_ROUNDS);
1150 			sm->num_rounds++;
1151 			SM_ENTER_GLOBAL(EAP, FAILURE);
1152 		}
1153 	} else switch (sm->EAP_state) {
1154 	case EAP_INITIALIZE:
1155 		if (sm->backend_auth) {
1156 			if (!sm->rxResp)
1157 				SM_ENTER(EAP, SELECT_ACTION);
1158 			else if (sm->rxResp &&
1159 				 (sm->respMethod == EAP_TYPE_NAK ||
1160 				  (sm->respMethod == EAP_TYPE_EXPANDED &&
1161 				   sm->respVendor == EAP_VENDOR_IETF &&
1162 				   sm->respVendorMethod == EAP_TYPE_NAK)))
1163 				SM_ENTER(EAP, NAK);
1164 			else
1165 				SM_ENTER(EAP, PICK_UP_METHOD);
1166 		} else {
1167 			SM_ENTER(EAP, SELECT_ACTION);
1168 		}
1169 		break;
1170 	case EAP_PICK_UP_METHOD:
1171 		if (sm->currentMethod == EAP_TYPE_NONE) {
1172 			SM_ENTER(EAP, SELECT_ACTION);
1173 		} else {
1174 			SM_ENTER(EAP, METHOD_RESPONSE);
1175 		}
1176 		break;
1177 	case EAP_DISABLED:
1178 		if (sm->eap_if.portEnabled)
1179 			SM_ENTER(EAP, INITIALIZE);
1180 		break;
1181 	case EAP_IDLE:
1182 		if (sm->eap_if.retransWhile == 0) {
1183 			if (sm->try_initiate_reauth) {
1184 				sm->try_initiate_reauth = FALSE;
1185 				SM_ENTER(EAP, SELECT_ACTION);
1186 			} else {
1187 				SM_ENTER(EAP, RETRANSMIT);
1188 			}
1189 		} else if (sm->eap_if.eapResp)
1190 			SM_ENTER(EAP, RECEIVED);
1191 		break;
1192 	case EAP_RETRANSMIT:
1193 		if (sm->retransCount > sm->MaxRetrans)
1194 			SM_ENTER(EAP, TIMEOUT_FAILURE);
1195 		else
1196 			SM_ENTER(EAP, IDLE);
1197 		break;
1198 	case EAP_RECEIVED:
1199 		if (sm->rxResp && (sm->respId == sm->currentId) &&
1200 		    (sm->respMethod == EAP_TYPE_NAK ||
1201 		     (sm->respMethod == EAP_TYPE_EXPANDED &&
1202 		      sm->respVendor == EAP_VENDOR_IETF &&
1203 		      sm->respVendorMethod == EAP_TYPE_NAK))
1204 		    && (sm->methodState == METHOD_PROPOSED))
1205 			SM_ENTER(EAP, NAK);
1206 		else if (sm->rxResp && (sm->respId == sm->currentId) &&
1207 			 ((sm->respMethod == sm->currentMethod) ||
1208 			  (sm->respMethod == EAP_TYPE_EXPANDED &&
1209 			   sm->respVendor == EAP_VENDOR_IETF &&
1210 			   sm->respVendorMethod == sm->currentMethod)))
1211 			SM_ENTER(EAP, INTEGRITY_CHECK);
1212 #ifdef CONFIG_ERP
1213 		else if (sm->rxInitiate)
1214 			SM_ENTER(EAP, INITIATE_RECEIVED);
1215 #endif /* CONFIG_ERP */
1216 		else {
1217 			wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
1218 				   "rxResp=%d respId=%d currentId=%d "
1219 				   "respMethod=%d currentMethod=%d",
1220 				   sm->rxResp, sm->respId, sm->currentId,
1221 				   sm->respMethod, sm->currentMethod);
1222 			eap_log_msg(sm, "Discard received EAP message");
1223 			SM_ENTER(EAP, DISCARD);
1224 		}
1225 		break;
1226 	case EAP_DISCARD:
1227 		SM_ENTER(EAP, IDLE);
1228 		break;
1229 	case EAP_SEND_REQUEST:
1230 		SM_ENTER(EAP, IDLE);
1231 		break;
1232 	case EAP_INTEGRITY_CHECK:
1233 		if (sm->ignore)
1234 			SM_ENTER(EAP, DISCARD);
1235 		else
1236 			SM_ENTER(EAP, METHOD_RESPONSE);
1237 		break;
1238 	case EAP_METHOD_REQUEST:
1239 		if (sm->m == NULL) {
1240 			/*
1241 			 * This transition is not mentioned in RFC 4137, but it
1242 			 * is needed to handle cleanly a case where EAP method
1243 			 * initialization fails.
1244 			 */
1245 			SM_ENTER(EAP, FAILURE);
1246 			break;
1247 		}
1248 		SM_ENTER(EAP, SEND_REQUEST);
1249 		break;
1250 	case EAP_METHOD_RESPONSE:
1251 		/*
1252 		 * Note: Mechanism to allow EAP methods to wait while going
1253 		 * through pending processing is an extension to RFC 4137
1254 		 * which only defines the transits to SELECT_ACTION and
1255 		 * METHOD_REQUEST from this METHOD_RESPONSE state.
1256 		 */
1257 		if (sm->methodState == METHOD_END)
1258 			SM_ENTER(EAP, SELECT_ACTION);
1259 		else if (sm->method_pending == METHOD_PENDING_WAIT) {
1260 			wpa_printf(MSG_DEBUG, "EAP: Method has pending "
1261 				   "processing - wait before proceeding to "
1262 				   "METHOD_REQUEST state");
1263 		} else if (sm->method_pending == METHOD_PENDING_CONT) {
1264 			wpa_printf(MSG_DEBUG, "EAP: Method has completed "
1265 				   "pending processing - reprocess pending "
1266 				   "EAP message");
1267 			sm->method_pending = METHOD_PENDING_NONE;
1268 			SM_ENTER(EAP, METHOD_RESPONSE);
1269 		} else
1270 			SM_ENTER(EAP, METHOD_REQUEST);
1271 		break;
1272 	case EAP_PROPOSE_METHOD:
1273 		/*
1274 		 * Note: Mechanism to allow EAP methods to wait while going
1275 		 * through pending processing is an extension to RFC 4137
1276 		 * which only defines the transit to METHOD_REQUEST from this
1277 		 * PROPOSE_METHOD state.
1278 		 */
1279 		if (sm->method_pending == METHOD_PENDING_WAIT) {
1280 			wpa_printf(MSG_DEBUG, "EAP: Method has pending "
1281 				   "processing - wait before proceeding to "
1282 				   "METHOD_REQUEST state");
1283 			if (sm->user_eap_method_index > 0)
1284 				sm->user_eap_method_index--;
1285 		} else if (sm->method_pending == METHOD_PENDING_CONT) {
1286 			wpa_printf(MSG_DEBUG, "EAP: Method has completed "
1287 				   "pending processing - reprocess pending "
1288 				   "EAP message");
1289 			sm->method_pending = METHOD_PENDING_NONE;
1290 			SM_ENTER(EAP, PROPOSE_METHOD);
1291 		} else
1292 			SM_ENTER(EAP, METHOD_REQUEST);
1293 		break;
1294 	case EAP_NAK:
1295 		SM_ENTER(EAP, SELECT_ACTION);
1296 		break;
1297 	case EAP_SELECT_ACTION:
1298 		if (sm->decision == DECISION_FAILURE)
1299 			SM_ENTER(EAP, FAILURE);
1300 		else if (sm->decision == DECISION_SUCCESS)
1301 			SM_ENTER(EAP, SUCCESS);
1302 		else if (sm->decision == DECISION_PASSTHROUGH)
1303 			SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
1304 		else if (sm->decision == DECISION_INITIATE_REAUTH_START)
1305 			SM_ENTER(EAP, INITIATE_REAUTH_START);
1306 #ifdef CONFIG_ERP
1307 		else if (sm->eap_server && sm->erp && sm->rxInitiate)
1308 			SM_ENTER(EAP, INITIATE_RECEIVED);
1309 #endif /* CONFIG_ERP */
1310 		else
1311 			SM_ENTER(EAP, PROPOSE_METHOD);
1312 		break;
1313 	case EAP_INITIATE_REAUTH_START:
1314 		SM_ENTER(EAP, SEND_REQUEST);
1315 		break;
1316 	case EAP_INITIATE_RECEIVED:
1317 		if (!sm->eap_server)
1318 			SM_ENTER(EAP, SELECT_ACTION);
1319 		break;
1320 	case EAP_TIMEOUT_FAILURE:
1321 		break;
1322 	case EAP_FAILURE:
1323 		break;
1324 	case EAP_SUCCESS:
1325 		break;
1326 
1327 	case EAP_INITIALIZE_PASSTHROUGH:
1328 		if (sm->currentId == -1)
1329 			SM_ENTER(EAP, AAA_IDLE);
1330 		else
1331 			SM_ENTER(EAP, AAA_REQUEST);
1332 		break;
1333 	case EAP_IDLE2:
1334 		if (sm->eap_if.eapResp)
1335 			SM_ENTER(EAP, RECEIVED2);
1336 		else if (sm->eap_if.retransWhile == 0)
1337 			SM_ENTER(EAP, RETRANSMIT2);
1338 		break;
1339 	case EAP_RETRANSMIT2:
1340 		if (sm->retransCount > sm->MaxRetrans)
1341 			SM_ENTER(EAP, TIMEOUT_FAILURE2);
1342 		else
1343 			SM_ENTER(EAP, IDLE2);
1344 		break;
1345 	case EAP_RECEIVED2:
1346 		if (sm->rxResp && (sm->respId == sm->currentId))
1347 			SM_ENTER(EAP, AAA_REQUEST);
1348 		else
1349 			SM_ENTER(EAP, DISCARD2);
1350 		break;
1351 	case EAP_DISCARD2:
1352 		SM_ENTER(EAP, IDLE2);
1353 		break;
1354 	case EAP_SEND_REQUEST2:
1355 		SM_ENTER(EAP, IDLE2);
1356 		break;
1357 	case EAP_AAA_REQUEST:
1358 		SM_ENTER(EAP, AAA_IDLE);
1359 		break;
1360 	case EAP_AAA_RESPONSE:
1361 		SM_ENTER(EAP, SEND_REQUEST2);
1362 		break;
1363 	case EAP_AAA_IDLE:
1364 		if (sm->eap_if.aaaFail)
1365 			SM_ENTER(EAP, FAILURE2);
1366 		else if (sm->eap_if.aaaSuccess)
1367 			SM_ENTER(EAP, SUCCESS2);
1368 		else if (sm->eap_if.aaaEapReq)
1369 			SM_ENTER(EAP, AAA_RESPONSE);
1370 		else if (sm->eap_if.aaaTimeout)
1371 			SM_ENTER(EAP, TIMEOUT_FAILURE2);
1372 		break;
1373 	case EAP_TIMEOUT_FAILURE2:
1374 		break;
1375 	case EAP_FAILURE2:
1376 		break;
1377 	case EAP_SUCCESS2:
1378 		break;
1379 	}
1380 }
1381 
1382 
eap_sm_calculateTimeout(struct eap_sm * sm,int retransCount,int eapSRTT,int eapRTTVAR,int methodTimeout)1383 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
1384 				   int eapSRTT, int eapRTTVAR,
1385 				   int methodTimeout)
1386 {
1387 	int rto, i;
1388 
1389 	if (sm->try_initiate_reauth) {
1390 		wpa_printf(MSG_DEBUG,
1391 			   "EAP: retransmit timeout 1 second for EAP-Initiate-Re-auth-Start");
1392 		return 1;
1393 	}
1394 
1395 	if (methodTimeout) {
1396 		/*
1397 		 * EAP method (either internal or through AAA server, provided
1398 		 * timeout hint. Use that as-is as a timeout for retransmitting
1399 		 * the EAP request if no response is received.
1400 		 */
1401 		wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
1402 			   "(from EAP method hint)", methodTimeout);
1403 		return methodTimeout;
1404 	}
1405 
1406 	/*
1407 	 * RFC 3748 recommends algorithms described in RFC 2988 for estimation
1408 	 * of the retransmission timeout. This should be implemented once
1409 	 * round-trip time measurements are available. For nowm a simple
1410 	 * backoff mechanism is used instead if there are no EAP method
1411 	 * specific hints.
1412 	 *
1413 	 * SRTT = smoothed round-trip time
1414 	 * RTTVAR = round-trip time variation
1415 	 * RTO = retransmission timeout
1416 	 */
1417 
1418 	/*
1419 	 * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
1420 	 * initial retransmission and then double the RTO to provide back off
1421 	 * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
1422 	 * modified RTOmax.
1423 	 */
1424 	rto = 3;
1425 	for (i = 0; i < retransCount; i++) {
1426 		rto *= 2;
1427 		if (rto >= 20) {
1428 			rto = 20;
1429 			break;
1430 		}
1431 	}
1432 
1433 	wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
1434 		   "(from dynamic back off; retransCount=%d)",
1435 		   rto, retransCount);
1436 
1437 	return rto;
1438 }
1439 
1440 
eap_sm_parseEapResp(struct eap_sm * sm,const struct wpabuf * resp)1441 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp)
1442 {
1443 	const struct eap_hdr *hdr;
1444 	size_t plen;
1445 
1446 	/* parse rxResp, respId, respMethod */
1447 	sm->rxResp = FALSE;
1448 	sm->rxInitiate = FALSE;
1449 	sm->respId = -1;
1450 	sm->respMethod = EAP_TYPE_NONE;
1451 	sm->respVendor = EAP_VENDOR_IETF;
1452 	sm->respVendorMethod = EAP_TYPE_NONE;
1453 
1454 	if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) {
1455 		wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p "
1456 			   "len=%lu", resp,
1457 			   resp ? (unsigned long) wpabuf_len(resp) : 0);
1458 		return;
1459 	}
1460 
1461 	hdr = wpabuf_head(resp);
1462 	plen = be_to_host16(hdr->length);
1463 	if (plen > wpabuf_len(resp)) {
1464 		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
1465 			   "(len=%lu plen=%lu)",
1466 			   (unsigned long) wpabuf_len(resp),
1467 			   (unsigned long) plen);
1468 		return;
1469 	}
1470 
1471 	sm->respId = hdr->identifier;
1472 
1473 	if (hdr->code == EAP_CODE_RESPONSE)
1474 		sm->rxResp = TRUE;
1475 	else if (hdr->code == EAP_CODE_INITIATE)
1476 		sm->rxInitiate = TRUE;
1477 
1478 	if (plen > sizeof(*hdr)) {
1479 		u8 *pos = (u8 *) (hdr + 1);
1480 		sm->respMethod = *pos++;
1481 		if (sm->respMethod == EAP_TYPE_EXPANDED) {
1482 			if (plen < sizeof(*hdr) + 8) {
1483 				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
1484 					   "expanded EAP-Packet (plen=%lu)",
1485 					   (unsigned long) plen);
1486 				return;
1487 			}
1488 			sm->respVendor = WPA_GET_BE24(pos);
1489 			pos += 3;
1490 			sm->respVendorMethod = WPA_GET_BE32(pos);
1491 		}
1492 	}
1493 
1494 	wpa_printf(MSG_DEBUG,
1495 		   "EAP: parseEapResp: rxResp=%d rxInitiate=%d respId=%d respMethod=%u respVendor=%u respVendorMethod=%u",
1496 		   sm->rxResp, sm->rxInitiate, sm->respId, sm->respMethod,
1497 		   sm->respVendor, sm->respVendorMethod);
1498 }
1499 
1500 
eap_sm_getId(const struct wpabuf * data)1501 static int eap_sm_getId(const struct wpabuf *data)
1502 {
1503 	const struct eap_hdr *hdr;
1504 
1505 	if (data == NULL || wpabuf_len(data) < sizeof(*hdr))
1506 		return -1;
1507 
1508 	hdr = wpabuf_head(data);
1509 	wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
1510 	return hdr->identifier;
1511 }
1512 
1513 
eap_sm_buildSuccess(struct eap_sm * sm,u8 id)1514 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
1515 {
1516 	struct wpabuf *msg;
1517 	struct eap_hdr *resp;
1518 	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
1519 
1520 	msg = wpabuf_alloc(sizeof(*resp));
1521 	if (msg == NULL)
1522 		return NULL;
1523 	resp = wpabuf_put(msg, sizeof(*resp));
1524 	resp->code = EAP_CODE_SUCCESS;
1525 	resp->identifier = id;
1526 	resp->length = host_to_be16(sizeof(*resp));
1527 
1528 	return msg;
1529 }
1530 
1531 
eap_sm_buildFailure(struct eap_sm * sm,u8 id)1532 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id)
1533 {
1534 	struct wpabuf *msg;
1535 	struct eap_hdr *resp;
1536 	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
1537 
1538 	msg = wpabuf_alloc(sizeof(*resp));
1539 	if (msg == NULL)
1540 		return NULL;
1541 	resp = wpabuf_put(msg, sizeof(*resp));
1542 	resp->code = EAP_CODE_FAILURE;
1543 	resp->identifier = id;
1544 	resp->length = host_to_be16(sizeof(*resp));
1545 
1546 	return msg;
1547 }
1548 
1549 
eap_sm_nextId(struct eap_sm * sm,int id)1550 static int eap_sm_nextId(struct eap_sm *sm, int id)
1551 {
1552 	if (id < 0) {
1553 		/* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
1554 		 * random number */
1555 		id = rand() & 0xff;
1556 		if (id != sm->lastId)
1557 			return id;
1558 	}
1559 	return (id + 1) & 0xff;
1560 }
1561 
1562 
1563 /**
1564  * eap_sm_process_nak - Process EAP-Response/Nak
1565  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1566  * @nak_list: Nak list (allowed methods) from the supplicant
1567  * @len: Length of nak_list in bytes
1568  *
1569  * This function is called when EAP-Response/Nak is received from the
1570  * supplicant. This can happen for both phase 1 and phase 2 authentications.
1571  */
eap_sm_process_nak(struct eap_sm * sm,const u8 * nak_list,size_t len)1572 void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len)
1573 {
1574 	int i;
1575 	size_t j;
1576 
1577 	if (sm->user == NULL)
1578 		return;
1579 
1580 	wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
1581 		   "index %d)", sm->user_eap_method_index);
1582 
1583 	wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
1584 		    (u8 *) sm->user->methods,
1585 		    EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
1586 	wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
1587 		    nak_list, len);
1588 
1589 	i = sm->user_eap_method_index;
1590 	while (i < EAP_MAX_METHODS &&
1591 	       (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
1592 		sm->user->methods[i].method != EAP_TYPE_NONE)) {
1593 		if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
1594 			goto not_found;
1595 		for (j = 0; j < len; j++) {
1596 			if (nak_list[j] == sm->user->methods[i].method) {
1597 				break;
1598 			}
1599 		}
1600 
1601 		if (j < len) {
1602 			/* found */
1603 			i++;
1604 			continue;
1605 		}
1606 
1607 	not_found:
1608 		/* not found - remove from the list */
1609 		if (i + 1 < EAP_MAX_METHODS) {
1610 			os_memmove(&sm->user->methods[i],
1611 				   &sm->user->methods[i + 1],
1612 				   (EAP_MAX_METHODS - i - 1) *
1613 				   sizeof(sm->user->methods[0]));
1614 		}
1615 		sm->user->methods[EAP_MAX_METHODS - 1].vendor =
1616 			EAP_VENDOR_IETF;
1617 		sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
1618 	}
1619 
1620 	wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
1621 		    (u8 *) sm->user->methods, EAP_MAX_METHODS *
1622 		    sizeof(sm->user->methods[0]));
1623 }
1624 
1625 
eap_sm_Policy_update(struct eap_sm * sm,const u8 * nak_list,size_t len)1626 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
1627 				 size_t len)
1628 {
1629 	if (nak_list == NULL || sm == NULL || sm->user == NULL)
1630 		return;
1631 
1632 	if (sm->user->phase2) {
1633 		wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
1634 			   " info was selected - reject");
1635 		sm->decision = DECISION_FAILURE;
1636 		return;
1637 	}
1638 
1639 	eap_sm_process_nak(sm, nak_list, len);
1640 }
1641 
1642 
eap_sm_Policy_getNextMethod(struct eap_sm * sm,int * vendor)1643 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
1644 {
1645 	EapType next;
1646 	int idx = sm->user_eap_method_index;
1647 
1648 	/* In theory, there should be no problems with starting
1649 	 * re-authentication with something else than EAP-Request/Identity and
1650 	 * this does indeed work with wpa_supplicant. However, at least Funk
1651 	 * Supplicant seemed to ignore re-auth if it skipped
1652 	 * EAP-Request/Identity.
1653 	 * Re-auth sets currentId == -1, so that can be used here to select
1654 	 * whether Identity needs to be requested again. */
1655 	if (sm->identity == NULL || sm->currentId == -1) {
1656 		*vendor = EAP_VENDOR_IETF;
1657 		next = EAP_TYPE_IDENTITY;
1658 		sm->update_user = TRUE;
1659 	} else if (sm->user && idx < EAP_MAX_METHODS &&
1660 		   (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
1661 		    sm->user->methods[idx].method != EAP_TYPE_NONE)) {
1662 		*vendor = sm->user->methods[idx].vendor;
1663 		next = sm->user->methods[idx].method;
1664 		sm->user_eap_method_index++;
1665 	} else {
1666 		*vendor = EAP_VENDOR_IETF;
1667 		next = EAP_TYPE_NONE;
1668 	}
1669 	wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
1670 		   *vendor, next);
1671 	return next;
1672 }
1673 
1674 
eap_sm_Policy_getDecision(struct eap_sm * sm)1675 static int eap_sm_Policy_getDecision(struct eap_sm *sm)
1676 {
1677 	if (!sm->eap_server && sm->identity && !sm->start_reauth) {
1678 		wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
1679 		return DECISION_PASSTHROUGH;
1680 	}
1681 
1682 	if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
1683 	    sm->m->isSuccess(sm, sm->eap_method_priv)) {
1684 		wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
1685 			   "SUCCESS");
1686 		sm->update_user = TRUE;
1687 		return DECISION_SUCCESS;
1688 	}
1689 
1690 	if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
1691 	    !sm->m->isSuccess(sm, sm->eap_method_priv)) {
1692 		wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
1693 			   "FAILURE");
1694 		sm->update_user = TRUE;
1695 		return DECISION_FAILURE;
1696 	}
1697 
1698 	if ((sm->user == NULL || sm->update_user) && sm->identity &&
1699 	    !sm->start_reauth) {
1700 		/*
1701 		 * Allow Identity method to be started once to allow identity
1702 		 * selection hint to be sent from the authentication server,
1703 		 * but prevent a loop of Identity requests by only allowing
1704 		 * this to happen once.
1705 		 */
1706 		int id_req = 0;
1707 		if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
1708 		    sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1709 		    sm->user->methods[0].method == EAP_TYPE_IDENTITY)
1710 			id_req = 1;
1711 		if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
1712 			wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
1713 				   "found from database -> FAILURE");
1714 			return DECISION_FAILURE;
1715 		}
1716 		if (id_req && sm->user &&
1717 		    sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1718 		    sm->user->methods[0].method == EAP_TYPE_IDENTITY) {
1719 			wpa_printf(MSG_DEBUG, "EAP: getDecision: stop "
1720 				   "identity request loop -> FAILURE");
1721 			sm->update_user = TRUE;
1722 			return DECISION_FAILURE;
1723 		}
1724 		sm->update_user = FALSE;
1725 	}
1726 	sm->start_reauth = FALSE;
1727 
1728 	if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
1729 	    (sm->user->methods[sm->user_eap_method_index].vendor !=
1730 	     EAP_VENDOR_IETF ||
1731 	     sm->user->methods[sm->user_eap_method_index].method !=
1732 	     EAP_TYPE_NONE)) {
1733 		wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
1734 			   "available -> CONTINUE");
1735 		return DECISION_CONTINUE;
1736 	}
1737 
1738 	if (!sm->identity && eap_get_erp_send_reauth_start(sm) &&
1739 	    !sm->initiate_reauth_start_sent) {
1740 		wpa_printf(MSG_DEBUG,
1741 			   "EAP: getDecision: send EAP-Initiate/Re-auth-Start");
1742 		return DECISION_INITIATE_REAUTH_START;
1743 	}
1744 
1745 	if (sm->identity == NULL || sm->currentId == -1) {
1746 		wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
1747 			   "yet -> CONTINUE");
1748 		return DECISION_CONTINUE;
1749 	}
1750 
1751 	wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
1752 		   "FAILURE");
1753 	return DECISION_FAILURE;
1754 }
1755 
1756 
eap_sm_Policy_doPickUp(struct eap_sm * sm,EapType method)1757 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
1758 {
1759 	return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
1760 }
1761 
1762 
1763 /**
1764  * eap_server_sm_step - Step EAP server state machine
1765  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1766  * Returns: 1 if EAP state was changed or 0 if not
1767  *
1768  * This function advances EAP state machine to a new state to match with the
1769  * current variables. This should be called whenever variables used by the EAP
1770  * state machine have changed.
1771  */
eap_server_sm_step(struct eap_sm * sm)1772 int eap_server_sm_step(struct eap_sm *sm)
1773 {
1774 	int res = 0;
1775 	do {
1776 		sm->changed = FALSE;
1777 		SM_STEP_RUN(EAP);
1778 		if (sm->changed)
1779 			res = 1;
1780 	} while (sm->changed);
1781 	return res;
1782 }
1783 
1784 
eap_user_free(struct eap_user * user)1785 static void eap_user_free(struct eap_user *user)
1786 {
1787 	if (user == NULL)
1788 		return;
1789 	bin_clear_free(user->password, user->password_len);
1790 	user->password = NULL;
1791 	os_free(user);
1792 }
1793 
1794 
1795 /**
1796  * eap_server_sm_init - Allocate and initialize EAP server state machine
1797  * @eapol_ctx: Context data to be used with eapol_cb calls
1798  * @eapol_cb: Pointer to EAPOL callback functions
1799  * @conf: EAP configuration
1800  * Returns: Pointer to the allocated EAP state machine or %NULL on failure
1801  *
1802  * This function allocates and initializes an EAP state machine.
1803  */
eap_server_sm_init(void * eapol_ctx,const struct eapol_callbacks * eapol_cb,struct eap_config * conf)1804 struct eap_sm * eap_server_sm_init(void *eapol_ctx,
1805 				   const struct eapol_callbacks *eapol_cb,
1806 				   struct eap_config *conf)
1807 {
1808 	struct eap_sm *sm;
1809 
1810 	sm = os_zalloc(sizeof(*sm));
1811 	if (sm == NULL)
1812 		return NULL;
1813 	sm->eapol_ctx = eapol_ctx;
1814 	sm->eapol_cb = eapol_cb;
1815 	sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
1816 	sm->ssl_ctx = conf->ssl_ctx;
1817 	sm->msg_ctx = conf->msg_ctx;
1818 	sm->eap_sim_db_priv = conf->eap_sim_db_priv;
1819 	sm->backend_auth = conf->backend_auth;
1820 	sm->eap_server = conf->eap_server;
1821 	if (conf->pac_opaque_encr_key) {
1822 		sm->pac_opaque_encr_key = os_malloc(16);
1823 		if (sm->pac_opaque_encr_key) {
1824 			os_memcpy(sm->pac_opaque_encr_key,
1825 				  conf->pac_opaque_encr_key, 16);
1826 		}
1827 	}
1828 	if (conf->eap_fast_a_id) {
1829 		sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1830 		if (sm->eap_fast_a_id) {
1831 			os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
1832 				  conf->eap_fast_a_id_len);
1833 			sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1834 		}
1835 	}
1836 	if (conf->eap_fast_a_id_info)
1837 		sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1838 	sm->eap_fast_prov = conf->eap_fast_prov;
1839 	sm->pac_key_lifetime = conf->pac_key_lifetime;
1840 	sm->pac_key_refresh_time = conf->pac_key_refresh_time;
1841 	sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1842 	sm->tnc = conf->tnc;
1843 	sm->wps = conf->wps;
1844 	if (conf->assoc_wps_ie)
1845 		sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
1846 	if (conf->assoc_p2p_ie)
1847 		sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie);
1848 	if (conf->peer_addr)
1849 		os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
1850 	sm->fragment_size = conf->fragment_size;
1851 	sm->pwd_group = conf->pwd_group;
1852 	sm->pbc_in_m1 = conf->pbc_in_m1;
1853 	sm->server_id = conf->server_id;
1854 	sm->server_id_len = conf->server_id_len;
1855 	sm->erp = conf->erp;
1856 
1857 #ifdef CONFIG_TESTING_OPTIONS
1858 	sm->tls_test_flags = conf->tls_test_flags;
1859 #endif /* CONFIG_TESTING_OPTIONS */
1860 
1861 	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
1862 
1863 	return sm;
1864 }
1865 
1866 
1867 /**
1868  * eap_server_sm_deinit - Deinitialize and free an EAP server state machine
1869  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1870  *
1871  * This function deinitializes EAP state machine and frees all allocated
1872  * resources.
1873  */
eap_server_sm_deinit(struct eap_sm * sm)1874 void eap_server_sm_deinit(struct eap_sm *sm)
1875 {
1876 	if (sm == NULL)
1877 		return;
1878 	wpa_printf(MSG_DEBUG, "EAP: Server state machine removed");
1879 	if (sm->m && sm->eap_method_priv)
1880 		sm->m->reset(sm, sm->eap_method_priv);
1881 	wpabuf_free(sm->eap_if.eapReqData);
1882 	bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
1883 	os_free(sm->eap_if.eapSessionId);
1884 	wpabuf_free(sm->lastReqData);
1885 	wpabuf_free(sm->eap_if.eapRespData);
1886 	os_free(sm->identity);
1887 	os_free(sm->pac_opaque_encr_key);
1888 	os_free(sm->eap_fast_a_id);
1889 	os_free(sm->eap_fast_a_id_info);
1890 	wpabuf_free(sm->eap_if.aaaEapReqData);
1891 	wpabuf_free(sm->eap_if.aaaEapRespData);
1892 	bin_clear_free(sm->eap_if.aaaEapKeyData, sm->eap_if.aaaEapKeyDataLen);
1893 	eap_user_free(sm->user);
1894 	wpabuf_free(sm->assoc_wps_ie);
1895 	wpabuf_free(sm->assoc_p2p_ie);
1896 	os_free(sm);
1897 }
1898 
1899 
1900 /**
1901  * eap_sm_notify_cached - Notify EAP state machine of cached PMK
1902  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1903  *
1904  * This function is called when PMKSA caching is used to skip EAP
1905  * authentication.
1906  */
eap_sm_notify_cached(struct eap_sm * sm)1907 void eap_sm_notify_cached(struct eap_sm *sm)
1908 {
1909 	if (sm == NULL)
1910 		return;
1911 
1912 	sm->EAP_state = EAP_SUCCESS;
1913 }
1914 
1915 
1916 /**
1917  * eap_sm_pending_cb - EAP state machine callback for a pending EAP request
1918  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1919  *
1920  * This function is called when data for a pending EAP-Request is received.
1921  */
eap_sm_pending_cb(struct eap_sm * sm)1922 void eap_sm_pending_cb(struct eap_sm *sm)
1923 {
1924 	if (sm == NULL)
1925 		return;
1926 	wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
1927 	if (sm->method_pending == METHOD_PENDING_WAIT)
1928 		sm->method_pending = METHOD_PENDING_CONT;
1929 }
1930 
1931 
1932 /**
1933  * eap_sm_method_pending - Query whether EAP method is waiting for pending data
1934  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1935  * Returns: 1 if method is waiting for pending data or 0 if not
1936  */
eap_sm_method_pending(struct eap_sm * sm)1937 int eap_sm_method_pending(struct eap_sm *sm)
1938 {
1939 	if (sm == NULL)
1940 		return 0;
1941 	return sm->method_pending == METHOD_PENDING_WAIT;
1942 }
1943 
1944 
1945 /**
1946  * eap_get_identity - Get the user identity (from EAP-Response/Identity)
1947  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1948  * @len: Buffer for returning identity length
1949  * Returns: Pointer to the user identity or %NULL if not available
1950  */
eap_get_identity(struct eap_sm * sm,size_t * len)1951 const u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
1952 {
1953 	*len = sm->identity_len;
1954 	return sm->identity;
1955 }
1956 
1957 
1958 /**
1959  * eap_get_interface - Get pointer to EAP-EAPOL interface data
1960  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1961  * Returns: Pointer to the EAP-EAPOL interface data
1962  */
eap_get_interface(struct eap_sm * sm)1963 struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
1964 {
1965 	return &sm->eap_if;
1966 }
1967 
1968 
1969 /**
1970  * eap_server_clear_identity - Clear EAP identity information
1971  * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
1972  *
1973  * This function can be used to clear the EAP identity information in the EAP
1974  * server context. This allows the EAP/Identity method to be used again after
1975  * EAPOL-Start or EAPOL-Logoff.
1976  */
eap_server_clear_identity(struct eap_sm * sm)1977 void eap_server_clear_identity(struct eap_sm *sm)
1978 {
1979 	os_free(sm->identity);
1980 	sm->identity = NULL;
1981 }
1982 
1983 
1984 #ifdef CONFIG_TESTING_OPTIONS
eap_server_mschap_rx_callback(struct eap_sm * sm,const char * source,const u8 * username,size_t username_len,const u8 * challenge,const u8 * response)1985 void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
1986 				   const u8 *username, size_t username_len,
1987 				   const u8 *challenge, const u8 *response)
1988 {
1989 	char hex_challenge[30], hex_response[90], user[100];
1990 
1991 	/* Print out Challenge and Response in format supported by asleap. */
1992 	if (username)
1993 		printf_encode(user, sizeof(user), username, username_len);
1994 	else
1995 		user[0] = '\0';
1996 	wpa_snprintf_hex_sep(hex_challenge, sizeof(hex_challenge),
1997 			     challenge, sizeof(challenge), ':');
1998 	wpa_snprintf_hex_sep(hex_response, sizeof(hex_response), response, 24,
1999 			     ':');
2000 	wpa_printf(MSG_DEBUG, "[%s/user=%s] asleap -C %s -R %s",
2001 		   source, user, hex_challenge, hex_response);
2002 }
2003 #endif /* CONFIG_TESTING_OPTIONS */
2004