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