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