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