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