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 2928 : static int eap_get_erp_send_reauth_start(struct eap_sm *sm)
49 : {
50 2928 : if (sm->eapol_cb->get_erp_send_reauth_start)
51 2912 : return sm->eapol_cb->get_erp_send_reauth_start(sm->eapol_ctx);
52 16 : return 0;
53 : }
54 :
55 :
56 106 : static const char * eap_get_erp_domain(struct eap_sm *sm)
57 : {
58 106 : if (sm->eapol_cb->get_erp_domain)
59 106 : return sm->eapol_cb->get_erp_domain(sm->eapol_ctx);
60 0 : return NULL;
61 : }
62 :
63 :
64 : #ifdef CONFIG_ERP
65 :
66 27 : static struct eap_server_erp_key * eap_erp_get_key(struct eap_sm *sm,
67 : const char *keyname)
68 : {
69 27 : if (sm->eapol_cb->erp_get_key)
70 27 : return sm->eapol_cb->erp_get_key(sm->eapol_ctx, keyname);
71 0 : return NULL;
72 : }
73 :
74 :
75 38 : static int eap_erp_add_key(struct eap_sm *sm, struct eap_server_erp_key *erp)
76 : {
77 38 : if (sm->eapol_cb->erp_add_key)
78 38 : return sm->eapol_cb->erp_add_key(sm->eapol_ctx, erp);
79 0 : return -1;
80 : }
81 :
82 : #endif /* CONFIG_ERP */
83 :
84 :
85 68 : static struct wpabuf * eap_sm_buildInitiateReauthStart(struct eap_sm *sm,
86 : u8 id)
87 : {
88 : const char *domain;
89 68 : size_t plen = 1;
90 : struct wpabuf *msg;
91 68 : size_t domain_len = 0;
92 :
93 68 : domain = eap_get_erp_domain(sm);
94 68 : if (domain) {
95 68 : domain_len = os_strlen(domain);
96 68 : plen += 2 + domain_len;
97 : }
98 :
99 68 : msg = eap_msg_alloc(EAP_VENDOR_IETF,
100 : (EapType) EAP_ERP_TYPE_REAUTH_START, plen,
101 : EAP_CODE_INITIATE, id);
102 68 : if (msg == NULL)
103 0 : return NULL;
104 68 : wpabuf_put_u8(msg, 0); /* Reserved */
105 68 : if (domain) {
106 : /* Domain name TLV */
107 68 : wpabuf_put_u8(msg, EAP_ERP_TLV_DOMAIN_NAME);
108 68 : wpabuf_put_u8(msg, domain_len);
109 68 : wpabuf_put_data(msg, domain, domain_len);
110 : }
111 :
112 68 : return msg;
113 : }
114 :
115 :
116 32191 : static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
117 : {
118 32191 : if (src == NULL)
119 5 : return -1;
120 :
121 32186 : wpabuf_free(*dst);
122 32186 : *dst = wpabuf_dup(src);
123 32186 : return *dst ? 0 : -1;
124 : }
125 :
126 :
127 1102 : static int eap_copy_data(u8 **dst, size_t *dst_len,
128 : const u8 *src, size_t src_len)
129 : {
130 1102 : if (src == NULL)
131 0 : return -1;
132 :
133 1102 : os_free(*dst);
134 1102 : *dst = os_malloc(src_len);
135 1102 : if (*dst) {
136 1101 : os_memcpy(*dst, src, src_len);
137 1101 : *dst_len = src_len;
138 1101 : 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 3586 : 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 7172 : if (sm == NULL || sm->eapol_cb == NULL ||
168 3586 : sm->eapol_cb->get_eap_user == NULL)
169 0 : return -1;
170 :
171 3586 : eap_user_free(sm->user);
172 3586 : sm->user = NULL;
173 :
174 3586 : user = os_zalloc(sizeof(*user));
175 3586 : if (user == NULL)
176 3 : return -1;
177 :
178 3583 : if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
179 : identity_len, phase2, user) != 0) {
180 8 : eap_user_free(user);
181 8 : return -1;
182 : }
183 :
184 3575 : sm->user = user;
185 3575 : sm->user_eap_method_index = 0;
186 :
187 3575 : return 0;
188 : }
189 :
190 :
191 10784 : void eap_log_msg(struct eap_sm *sm, const char *fmt, ...)
192 : {
193 : va_list ap;
194 : char *buf;
195 : int buflen;
196 :
197 10784 : if (sm == NULL || sm->eapol_cb == NULL || sm->eapol_cb->log_msg == NULL)
198 13818 : return;
199 :
200 3875 : va_start(ap, fmt);
201 3875 : buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
202 3875 : va_end(ap);
203 :
204 3875 : buf = os_malloc(buflen);
205 3875 : if (buf == NULL)
206 0 : return;
207 3875 : va_start(ap, fmt);
208 3875 : vsnprintf(buf, buflen, fmt, ap);
209 3875 : va_end(ap);
210 :
211 3875 : sm->eapol_cb->log_msg(sm->eapol_ctx, buf);
212 :
213 3875 : os_free(buf);
214 : }
215 :
216 :
217 3862 : SM_STATE(EAP, DISABLED)
218 : {
219 3862 : SM_ENTRY(EAP, DISABLED);
220 3862 : sm->num_rounds = 0;
221 3862 : }
222 :
223 :
224 4663 : SM_STATE(EAP, INITIALIZE)
225 : {
226 4663 : SM_ENTRY(EAP, INITIALIZE);
227 :
228 4663 : 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 97 : eap_server_clear_identity(sm);
234 : }
235 :
236 4663 : sm->try_initiate_reauth = FALSE;
237 4663 : sm->currentId = -1;
238 4663 : sm->eap_if.eapSuccess = FALSE;
239 4663 : sm->eap_if.eapFail = FALSE;
240 4663 : sm->eap_if.eapTimeout = FALSE;
241 4663 : bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
242 4663 : sm->eap_if.eapKeyData = NULL;
243 4663 : sm->eap_if.eapKeyDataLen = 0;
244 4663 : os_free(sm->eap_if.eapSessionId);
245 4663 : sm->eap_if.eapSessionId = NULL;
246 4663 : sm->eap_if.eapSessionIdLen = 0;
247 4663 : sm->eap_if.eapKeyAvailable = FALSE;
248 4663 : 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 4663 : if (sm->m && sm->eap_method_priv) {
256 298 : sm->m->reset(sm, sm->eap_method_priv);
257 298 : sm->eap_method_priv = NULL;
258 : }
259 4663 : sm->m = NULL;
260 4663 : sm->user_eap_method_index = 0;
261 :
262 4663 : if (sm->backend_auth) {
263 1656 : sm->currentMethod = EAP_TYPE_NONE;
264 : /* parse rxResp, respId, respMethod */
265 1656 : eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
266 1656 : if (sm->rxResp) {
267 1640 : sm->currentId = sm->respId;
268 : }
269 : }
270 4663 : sm->num_rounds = 0;
271 4663 : sm->method_pending = METHOD_PENDING_NONE;
272 :
273 27978 : wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
274 27978 : MACSTR, MAC2STR(sm->peer_addr));
275 4663 : }
276 :
277 :
278 1640 : SM_STATE(EAP, PICK_UP_METHOD)
279 : {
280 1640 : SM_ENTRY(EAP, PICK_UP_METHOD);
281 :
282 1640 : if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
283 1640 : sm->currentMethod = sm->respMethod;
284 1640 : 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 1640 : sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF,
289 : sm->currentMethod);
290 1640 : if (sm->m && sm->m->initPickUp) {
291 1640 : sm->eap_method_priv = sm->m->initPickUp(sm);
292 3280 : 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 1640 : wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
306 1640 : "method=%u", sm->currentMethod);
307 1640 : }
308 :
309 :
310 11954 : SM_STATE(EAP, IDLE)
311 : {
312 11954 : SM_ENTRY(EAP, IDLE);
313 :
314 11954 : sm->eap_if.retransWhile = eap_sm_calculateTimeout(
315 : sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
316 : sm->methodTimeout);
317 11954 : }
318 :
319 :
320 4 : SM_STATE(EAP, RETRANSMIT)
321 : {
322 4 : SM_ENTRY(EAP, RETRANSMIT);
323 :
324 4 : sm->retransCount++;
325 4 : if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
326 4 : if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
327 4 : sm->eap_if.eapReq = TRUE;
328 : }
329 4 : }
330 :
331 :
332 11490 : SM_STATE(EAP, RECEIVED)
333 : {
334 11490 : SM_ENTRY(EAP, RECEIVED);
335 :
336 : /* parse rxResp, respId, respMethod */
337 11490 : eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
338 11490 : sm->num_rounds++;
339 11490 : }
340 :
341 :
342 9 : SM_STATE(EAP, DISCARD)
343 : {
344 9 : SM_ENTRY(EAP, DISCARD);
345 9 : sm->eap_if.eapResp = FALSE;
346 9 : sm->eap_if.eapNoReq = TRUE;
347 9 : }
348 :
349 :
350 11962 : SM_STATE(EAP, SEND_REQUEST)
351 : {
352 11962 : SM_ENTRY(EAP, SEND_REQUEST);
353 :
354 11962 : sm->retransCount = 0;
355 11962 : if (sm->eap_if.eapReqData) {
356 11942 : if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
357 : {
358 11937 : sm->eap_if.eapResp = FALSE;
359 11937 : sm->eap_if.eapReq = TRUE;
360 : } else {
361 5 : sm->eap_if.eapResp = FALSE;
362 5 : sm->eap_if.eapReq = FALSE;
363 : }
364 : } else {
365 20 : wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
366 20 : sm->eap_if.eapResp = FALSE;
367 20 : sm->eap_if.eapReq = FALSE;
368 20 : sm->eap_if.eapNoReq = TRUE;
369 : }
370 11962 : }
371 :
372 :
373 11058 : SM_STATE(EAP, INTEGRITY_CHECK)
374 : {
375 11058 : SM_ENTRY(EAP, INTEGRITY_CHECK);
376 :
377 11058 : if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) {
378 0 : sm->ignore = TRUE;
379 11058 : return;
380 : }
381 :
382 11058 : if (sm->m->check) {
383 11058 : sm->ignore = sm->m->check(sm, sm->eap_method_priv,
384 : sm->eap_if.eapRespData);
385 : }
386 : }
387 :
388 :
389 11898 : SM_STATE(EAP, METHOD_REQUEST)
390 : {
391 11898 : SM_ENTRY(EAP, METHOD_REQUEST);
392 :
393 11898 : if (sm->m == NULL) {
394 4 : wpa_printf(MSG_DEBUG, "EAP: method not initialized");
395 11902 : return;
396 : }
397 :
398 11894 : sm->currentId = eap_sm_nextId(sm, sm->currentId);
399 11894 : wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
400 : sm->currentId);
401 11894 : sm->lastId = sm->currentId;
402 11894 : wpabuf_free(sm->eap_if.eapReqData);
403 23788 : sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
404 11894 : sm->currentId);
405 11894 : if (sm->m->getTimeout)
406 2190 : sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
407 : else
408 9704 : sm->methodTimeout = 0;
409 : }
410 :
411 :
412 38 : static void eap_server_erp_init(struct eap_sm *sm)
413 : {
414 : #ifdef CONFIG_ERP
415 38 : u8 *emsk = NULL;
416 38 : 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 38 : struct eap_server_erp_key *erp = NULL;
422 : int pos;
423 :
424 38 : domain = eap_get_erp_domain(sm);
425 38 : if (!domain)
426 0 : return;
427 :
428 38 : domain_len = os_strlen(domain);
429 :
430 38 : nai_buf_len = 2 * EAP_EMSK_NAME_LEN + 1 + domain_len;
431 38 : 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 38 : nai_buf_len++; /* null termination */
441 38 : erp = os_zalloc(sizeof(*erp) + nai_buf_len);
442 38 : if (erp == NULL)
443 0 : goto fail;
444 38 : erp->recv_seq = (u32) -1;
445 :
446 38 : emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
447 38 : 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 38 : wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len);
454 :
455 38 : WPA_PUT_BE16(len, 8);
456 38 : 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 38 : wpa_hexdump(MSG_DEBUG, "EAP: EMSKname", EMSKname, EAP_EMSK_NAME_LEN);
463 :
464 38 : pos = wpa_snprintf_hex(erp->keyname_nai, nai_buf_len,
465 : EMSKname, EAP_EMSK_NAME_LEN);
466 38 : erp->keyname_nai[pos] = '@';
467 38 : os_memcpy(&erp->keyname_nai[pos + 1], domain, domain_len);
468 :
469 38 : WPA_PUT_BE16(len, emsk_len);
470 76 : if (hmac_sha256_kdf(emsk, emsk_len,
471 : "EAP Re-authentication Root Key@ietf.org",
472 38 : 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 38 : erp->rRK_len = emsk_len;
477 38 : wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len);
478 :
479 76 : if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
480 : "EAP Re-authentication Integrity Key@ietf.org",
481 38 : 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 38 : erp->rIK_len = erp->rRK_len;
486 38 : wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rIK", erp->rIK, erp->rIK_len);
487 :
488 38 : if (eap_erp_add_key(sm, erp) == 0) {
489 38 : wpa_printf(MSG_DEBUG, "EAP: Stored ERP keys %s",
490 38 : erp->keyname_nai);
491 38 : erp = NULL;
492 : }
493 :
494 : fail:
495 38 : bin_clear_free(emsk, emsk_len);
496 38 : bin_clear_free(erp, sizeof(*erp));
497 : #endif /* CONFIG_ERP */
498 : }
499 :
500 :
501 12883 : SM_STATE(EAP, METHOD_RESPONSE)
502 : {
503 12883 : SM_ENTRY(EAP, METHOD_RESPONSE);
504 :
505 12883 : if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
506 12883 : return;
507 :
508 12883 : sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
509 12883 : if (sm->m->isDone(sm, sm->eap_method_priv)) {
510 6509 : eap_sm_Policy_update(sm, NULL, 0);
511 6509 : bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
512 6509 : if (sm->m->getKey) {
513 1525 : sm->eap_if.eapKeyData = sm->m->getKey(
514 : sm, sm->eap_method_priv,
515 : &sm->eap_if.eapKeyDataLen);
516 : } else {
517 4984 : sm->eap_if.eapKeyData = NULL;
518 4984 : sm->eap_if.eapKeyDataLen = 0;
519 : }
520 6509 : os_free(sm->eap_if.eapSessionId);
521 6509 : sm->eap_if.eapSessionId = NULL;
522 6509 : if (sm->m->getSessionId) {
523 1514 : sm->eap_if.eapSessionId = sm->m->getSessionId(
524 : sm, sm->eap_method_priv,
525 : &sm->eap_if.eapSessionIdLen);
526 3028 : wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
527 1514 : sm->eap_if.eapSessionId,
528 : sm->eap_if.eapSessionIdLen);
529 : }
530 6509 : if (sm->erp && sm->m->get_emsk && sm->eap_if.eapSessionId)
531 38 : eap_server_erp_init(sm);
532 6509 : sm->methodState = METHOD_END;
533 : } else {
534 6374 : sm->methodState = METHOD_CONTINUE;
535 : }
536 : }
537 :
538 :
539 5710 : SM_STATE(EAP, PROPOSE_METHOD)
540 : {
541 : int vendor;
542 : EapType type;
543 :
544 5710 : SM_ENTRY(EAP, PROPOSE_METHOD);
545 :
546 5710 : sm->try_initiate_reauth = FALSE;
547 : try_another_method:
548 5716 : type = eap_sm_Policy_getNextMethod(sm, &vendor);
549 5716 : if (vendor == EAP_VENDOR_IETF)
550 5158 : sm->currentMethod = type;
551 : else
552 558 : sm->currentMethod = EAP_TYPE_EXPANDED;
553 5716 : if (sm->m && sm->eap_method_priv) {
554 2478 : sm->m->reset(sm, sm->eap_method_priv);
555 2478 : sm->eap_method_priv = NULL;
556 : }
557 5716 : sm->m = eap_server_get_eap_method(vendor, type);
558 5716 : if (sm->m) {
559 5712 : sm->eap_method_priv = sm->m->init(sm);
560 5712 : if (sm->eap_method_priv == NULL) {
561 6 : wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
562 6 : "method %d", sm->currentMethod);
563 6 : sm->m = NULL;
564 6 : sm->currentMethod = EAP_TYPE_NONE;
565 6 : goto try_another_method;
566 : }
567 : }
568 5710 : if (sm->m == NULL) {
569 4 : wpa_printf(MSG_DEBUG, "EAP: Could not find suitable EAP method");
570 4 : eap_log_msg(sm, "Could not find suitable EAP method");
571 4 : sm->decision = DECISION_FAILURE;
572 5714 : return;
573 : }
574 8473 : if (sm->currentMethod == EAP_TYPE_IDENTITY ||
575 2767 : sm->currentMethod == EAP_TYPE_NOTIFICATION)
576 2939 : sm->methodState = METHOD_CONTINUE;
577 : else
578 2767 : sm->methodState = METHOD_PROPOSED;
579 :
580 5706 : wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
581 5706 : "vendor=%u method=%u", vendor, sm->currentMethod);
582 5706 : eap_log_msg(sm, "Propose EAP method vendor=%u method=%u",
583 5706 : vendor, sm->currentMethod);
584 : }
585 :
586 :
587 396 : SM_STATE(EAP, NAK)
588 : {
589 : const struct eap_hdr *nak;
590 396 : size_t len = 0;
591 : const u8 *pos;
592 396 : const u8 *nak_list = NULL;
593 :
594 396 : SM_ENTRY(EAP, NAK);
595 :
596 396 : if (sm->eap_method_priv) {
597 396 : sm->m->reset(sm, sm->eap_method_priv);
598 396 : sm->eap_method_priv = NULL;
599 : }
600 396 : sm->m = NULL;
601 :
602 396 : if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1))
603 396 : return;
604 :
605 396 : nak = wpabuf_head(sm->eap_if.eapRespData);
606 396 : if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
607 396 : len = be_to_host16(nak->length);
608 396 : if (len > wpabuf_len(sm->eap_if.eapRespData))
609 0 : len = wpabuf_len(sm->eap_if.eapRespData);
610 396 : pos = (const u8 *) (nak + 1);
611 396 : len -= sizeof(*nak);
612 396 : if (*pos == EAP_TYPE_NAK) {
613 377 : pos++;
614 377 : len--;
615 377 : nak_list = pos;
616 : }
617 : }
618 396 : eap_sm_Policy_update(sm, nak_list, len);
619 : }
620 :
621 :
622 9944 : SM_STATE(EAP, SELECT_ACTION)
623 : {
624 9944 : SM_ENTRY(EAP, SELECT_ACTION);
625 :
626 9944 : sm->decision = eap_sm_Policy_getDecision(sm);
627 9944 : }
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 832 : SM_STATE(EAP, FAILURE)
639 : {
640 832 : SM_ENTRY(EAP, FAILURE);
641 :
642 832 : wpabuf_free(sm->eap_if.eapReqData);
643 832 : sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId);
644 832 : wpabuf_free(sm->lastReqData);
645 832 : sm->lastReqData = NULL;
646 832 : sm->eap_if.eapFail = TRUE;
647 :
648 4992 : wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
649 4992 : MACSTR, MAC2STR(sm->peer_addr));
650 832 : }
651 :
652 :
653 1265 : SM_STATE(EAP, SUCCESS)
654 : {
655 1265 : SM_ENTRY(EAP, SUCCESS);
656 :
657 1265 : wpabuf_free(sm->eap_if.eapReqData);
658 1265 : sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId);
659 1265 : wpabuf_free(sm->lastReqData);
660 1265 : sm->lastReqData = NULL;
661 1265 : if (sm->eap_if.eapKeyData)
662 1263 : sm->eap_if.eapKeyAvailable = TRUE;
663 1265 : sm->eap_if.eapSuccess = TRUE;
664 :
665 7590 : wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
666 7590 : MACSTR, MAC2STR(sm->peer_addr));
667 1265 : }
668 :
669 :
670 68 : SM_STATE(EAP, INITIATE_REAUTH_START)
671 : {
672 68 : SM_ENTRY(EAP, INITIATE_REAUTH_START);
673 :
674 68 : sm->initiate_reauth_start_sent = TRUE;
675 68 : sm->try_initiate_reauth = TRUE;
676 68 : sm->currentId = eap_sm_nextId(sm, sm->currentId);
677 68 : wpa_printf(MSG_DEBUG,
678 : "EAP: building EAP-Initiate-Re-auth-Start: Identifier %d",
679 : sm->currentId);
680 68 : sm->lastId = sm->currentId;
681 68 : wpabuf_free(sm->eap_if.eapReqData);
682 68 : sm->eap_if.eapReqData = eap_sm_buildInitiateReauthStart(sm,
683 68 : sm->currentId);
684 68 : wpabuf_free(sm->lastReqData);
685 68 : sm->lastReqData = NULL;
686 68 : }
687 :
688 :
689 : #ifdef CONFIG_ERP
690 :
691 27 : 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 27 : if (erp) {
702 26 : 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 26 : hash_len = 16;
708 26 : break;
709 : default:
710 1 : return;
711 : }
712 : } else
713 1 : hash_len = 0;
714 :
715 27 : plen = 1 + 2 + 2 + os_strlen(nai);
716 27 : if (hash_len)
717 26 : plen += 1 + hash_len;
718 27 : msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
719 : plen, EAP_CODE_FINISH, id);
720 27 : if (msg == NULL)
721 0 : return;
722 27 : wpabuf_put_u8(msg, flags);
723 27 : wpabuf_put_be16(msg, seq);
724 :
725 27 : wpabuf_put_u8(msg, EAP_ERP_TLV_KEYNAME_NAI);
726 27 : wpabuf_put_u8(msg, os_strlen(nai));
727 27 : wpabuf_put_str(msg, nai);
728 :
729 27 : if (erp) {
730 26 : wpabuf_put_u8(msg, erp->cryptosuite);
731 52 : if (hmac_sha256(erp->rIK, erp->rIK_len,
732 26 : wpabuf_head(msg), wpabuf_len(msg), hash) < 0) {
733 0 : wpabuf_free(msg);
734 0 : return;
735 : }
736 26 : wpabuf_put_data(msg, hash, hash_len);
737 : }
738 :
739 27 : wpa_printf(MSG_DEBUG, "EAP: Send EAP-Finish/Re-auth (%s)",
740 27 : flags & 0x80 ? "failure" : "success");
741 :
742 27 : sm->lastId = sm->currentId;
743 27 : sm->currentId = id;
744 27 : wpabuf_free(sm->eap_if.eapReqData);
745 27 : sm->eap_if.eapReqData = msg;
746 27 : wpabuf_free(sm->lastReqData);
747 27 : sm->lastReqData = NULL;
748 :
749 27 : 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 26 : bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
757 26 : sm->eap_if.eapKeyDataLen = 0;
758 26 : sm->eap_if.eapKeyData = os_malloc(erp->rRK_len);
759 26 : if (!sm->eap_if.eapKeyData)
760 0 : return;
761 :
762 26 : WPA_PUT_BE16(seed, seq);
763 26 : WPA_PUT_BE16(&seed[2], erp->rRK_len);
764 26 : 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 26 : sm->eap_if.eapKeyDataLen = erp->rRK_len;
774 26 : sm->eap_if.eapKeyAvailable = TRUE;
775 52 : wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK",
776 26 : sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
777 26 : sm->eap_if.eapSuccess = TRUE;
778 :
779 156 : wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
780 156 : MACSTR, MAC2STR(sm->peer_addr));
781 : }
782 :
783 :
784 43 : 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 43 : u8 resp_flags = 0x80; /* default to failure; cleared on success */
798 :
799 43 : SM_ENTRY(EAP, INITIATE_RECEIVED);
800 :
801 43 : sm->rxInitiate = FALSE;
802 :
803 43 : pos = eap_hdr_validate(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
804 43 : sm->eap_if.eapRespData, &len);
805 43 : if (pos == NULL) {
806 0 : wpa_printf(MSG_INFO, "EAP-Initiate: Invalid frame");
807 0 : goto fail;
808 : }
809 43 : hdr = wpabuf_head(sm->eap_if.eapRespData);
810 43 : ehdr = wpabuf_head(sm->eap_if.eapRespData);
811 :
812 43 : wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-Auth", pos, len);
813 43 : if (len < 4) {
814 0 : wpa_printf(MSG_INFO, "EAP: Too short EAP-Initiate/Re-auth");
815 0 : goto fail;
816 : }
817 43 : end = pos + len;
818 :
819 43 : flags = *pos++;
820 43 : seq = WPA_GET_BE16(pos);
821 43 : pos += 2;
822 43 : wpa_printf(MSG_DEBUG, "EAP: Flags=0x%x SEQ=%u", flags, seq);
823 43 : 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 43 : if (erp_parse_tlvs(tlvs, end, &parse, 1) < 0)
832 0 : goto fail;
833 :
834 43 : 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 86 : wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth - keyName-NAI",
841 86 : parse.keyname, parse.keyname_len);
842 43 : 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 43 : os_memcpy(nai, parse.keyname, parse.keyname_len);
848 43 : nai[parse.keyname_len] = '\0';
849 :
850 43 : 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 59 : return;
866 : }
867 :
868 27 : erp = eap_erp_get_key(sm, nai);
869 27 : 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 26 : 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 26 : start = parse.keyname + parse.keyname_len;
884 26 : max_len = end - start;
885 26 : if (max_len <
886 26 : 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 26 : 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 6 : if (end[-17] != erp->cryptosuite) {
903 0 : wpa_printf(MSG_DEBUG,
904 : "EAP: Different Cryptosuite used");
905 0 : goto fail;
906 : }
907 6 : hash_len = 16;
908 6 : break;
909 : default:
910 20 : hash_len = 0;
911 20 : break;
912 : }
913 :
914 26 : if (hash_len) {
915 6 : if (hmac_sha256(erp->rIK, erp->rIK_len, hdr,
916 6 : end - hdr - hash_len, hash) < 0)
917 0 : goto fail;
918 6 : 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 26 : 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 26 : if (!hash_len && end[-17] == EAP_ERP_CS_HMAC_SHA256_128) {
940 20 : if (hmac_sha256(erp->rIK, erp->rIK_len, hdr,
941 20 : end - hdr - 16, hash) < 0)
942 0 : goto fail;
943 20 : if (os_memcmp(end - 16, hash, 16) == 0) {
944 20 : wpa_printf(MSG_DEBUG,
945 : "EAP: Authentication Tag match using HMAC-SHA256-128");
946 20 : hash_len = 16;
947 20 : erp->cryptosuite = EAP_ERP_CS_HMAC_SHA256_128;
948 : }
949 : }
950 :
951 26 : if (!hash_len) {
952 0 : wpa_printf(MSG_DEBUG,
953 : "EAP: No supported cryptosuite matched Authentication Tag");
954 0 : goto fail;
955 : }
956 26 : 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 26 : wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-Auth TVs/TLVs",
963 26 : tlvs, end - tlvs);
964 26 : if (erp_parse_tlvs(tlvs, end, &parse, 0) < 0)
965 0 : goto fail;
966 :
967 52 : wpa_printf(MSG_DEBUG, "EAP: ERP key %s SEQ updated to %u",
968 26 : erp->keyname_nai, seq);
969 26 : erp->recv_seq = seq;
970 26 : resp_flags &= ~0x80; /* R=0 - success */
971 :
972 : report_error:
973 27 : erp_send_finish_reauth(sm, erp, ehdr->identifier, resp_flags, seq, nai);
974 27 : return;
975 :
976 : fail:
977 0 : sm->ignore = TRUE;
978 : }
979 :
980 : #endif /* CONFIG_ERP */
981 :
982 :
983 2079 : SM_STATE(EAP, INITIALIZE_PASSTHROUGH)
984 : {
985 2079 : SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
986 :
987 2079 : wpabuf_free(sm->eap_if.aaaEapRespData);
988 2079 : sm->eap_if.aaaEapRespData = NULL;
989 2079 : sm->try_initiate_reauth = FALSE;
990 2079 : }
991 :
992 :
993 5837 : SM_STATE(EAP, IDLE2)
994 : {
995 5837 : SM_ENTRY(EAP, IDLE2);
996 :
997 5837 : sm->eap_if.retransWhile = eap_sm_calculateTimeout(
998 : sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
999 : sm->methodTimeout);
1000 5837 : }
1001 :
1002 :
1003 6 : SM_STATE(EAP, RETRANSMIT2)
1004 : {
1005 6 : SM_ENTRY(EAP, RETRANSMIT2);
1006 :
1007 6 : sm->retransCount++;
1008 6 : if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
1009 6 : if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
1010 6 : sm->eap_if.eapReq = TRUE;
1011 : }
1012 6 : }
1013 :
1014 :
1015 5201 : SM_STATE(EAP, RECEIVED2)
1016 : {
1017 5201 : SM_ENTRY(EAP, RECEIVED2);
1018 :
1019 : /* parse rxResp, respId, respMethod */
1020 5201 : eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
1021 5201 : }
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 5829 : SM_STATE(EAP, SEND_REQUEST2)
1033 : {
1034 5829 : SM_ENTRY(EAP, SEND_REQUEST2);
1035 :
1036 5829 : sm->retransCount = 0;
1037 5829 : if (sm->eap_if.eapReqData) {
1038 5827 : if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
1039 : {
1040 5827 : sm->eap_if.eapResp = FALSE;
1041 5827 : 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 5829 : }
1053 :
1054 :
1055 7278 : SM_STATE(EAP, AAA_REQUEST)
1056 : {
1057 7278 : SM_ENTRY(EAP, AAA_REQUEST);
1058 :
1059 7278 : if (sm->eap_if.eapRespData == NULL) {
1060 0 : wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData");
1061 7278 : 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 7278 : eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData);
1072 : }
1073 :
1074 :
1075 5829 : SM_STATE(EAP, AAA_RESPONSE)
1076 : {
1077 5829 : SM_ENTRY(EAP, AAA_RESPONSE);
1078 :
1079 5829 : eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
1080 5829 : sm->currentId = eap_sm_getId(sm->eap_if.eapReqData);
1081 5829 : sm->methodTimeout = sm->eap_if.aaaMethodTimeout;
1082 5829 : }
1083 :
1084 :
1085 7278 : SM_STATE(EAP, AAA_IDLE)
1086 : {
1087 7278 : SM_ENTRY(EAP, AAA_IDLE);
1088 :
1089 7278 : sm->eap_if.aaaFail = FALSE;
1090 7278 : sm->eap_if.aaaSuccess = FALSE;
1091 7278 : sm->eap_if.aaaEapReq = FALSE;
1092 7278 : sm->eap_if.aaaEapNoReq = FALSE;
1093 7278 : sm->eap_if.aaaEapResp = TRUE;
1094 7278 : }
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 186 : SM_STATE(EAP, FAILURE2)
1106 : {
1107 186 : SM_ENTRY(EAP, FAILURE2);
1108 :
1109 186 : eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
1110 186 : sm->eap_if.eapFail = TRUE;
1111 186 : }
1112 :
1113 :
1114 1119 : SM_STATE(EAP, SUCCESS2)
1115 : {
1116 1119 : SM_ENTRY(EAP, SUCCESS2);
1117 :
1118 1119 : eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
1119 :
1120 1119 : sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable;
1121 1119 : if (sm->eap_if.aaaEapKeyAvailable) {
1122 1102 : EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
1123 : } else {
1124 17 : bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
1125 17 : sm->eap_if.eapKeyData = NULL;
1126 17 : sm->eap_if.eapKeyDataLen = 0;
1127 : }
1128 :
1129 1119 : 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 1119 : sm->start_reauth = TRUE;
1137 1119 : }
1138 :
1139 :
1140 201213 : SM_STEP(EAP)
1141 : {
1142 201213 : if (sm->eap_if.eapRestart && sm->eap_if.portEnabled)
1143 4663 : SM_ENTER_GLOBAL(EAP, INITIALIZE);
1144 196550 : else if (!sm->eap_if.portEnabled)
1145 3862 : SM_ENTER_GLOBAL(EAP, DISABLED);
1146 192688 : 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 192688 : } else switch (sm->EAP_state) {
1155 : case EAP_INITIALIZE:
1156 4663 : if (sm->backend_auth) {
1157 1656 : if (!sm->rxResp)
1158 16 : SM_ENTER(EAP, SELECT_ACTION);
1159 3280 : else if (sm->rxResp &&
1160 3280 : (sm->respMethod == EAP_TYPE_NAK ||
1161 1640 : (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 1640 : SM_ENTER(EAP, PICK_UP_METHOD);
1167 : } else {
1168 3007 : SM_ENTER(EAP, SELECT_ACTION);
1169 : }
1170 4663 : break;
1171 : case EAP_PICK_UP_METHOD:
1172 1640 : if (sm->currentMethod == EAP_TYPE_NONE) {
1173 0 : SM_ENTER(EAP, SELECT_ACTION);
1174 : } else {
1175 1640 : SM_ENTER(EAP, METHOD_RESPONSE);
1176 : }
1177 1640 : 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 39264 : if (sm->eap_if.retransWhile == 0) {
1184 4 : if (sm->try_initiate_reauth) {
1185 0 : sm->try_initiate_reauth = FALSE;
1186 0 : SM_ENTER(EAP, SELECT_ACTION);
1187 : } else {
1188 4 : SM_ENTER(EAP, RETRANSMIT);
1189 : }
1190 39260 : } else if (sm->eap_if.eapResp)
1191 11490 : SM_ENTER(EAP, RECEIVED);
1192 39264 : break;
1193 : case EAP_RETRANSMIT:
1194 4 : if (sm->retransCount > sm->MaxRetrans)
1195 0 : SM_ENTER(EAP, TIMEOUT_FAILURE);
1196 : else
1197 4 : SM_ENTER(EAP, IDLE);
1198 4 : break;
1199 : case EAP_RECEIVED:
1200 22944 : if (sm->rxResp && (sm->respId == sm->currentId) &&
1201 22531 : (sm->respMethod == EAP_TYPE_NAK ||
1202 13212 : (sm->respMethod == EAP_TYPE_EXPANDED &&
1203 2154 : sm->respVendor == EAP_VENDOR_IETF &&
1204 19 : sm->respVendorMethod == EAP_TYPE_NAK))
1205 396 : && (sm->methodState == METHOD_PROPOSED))
1206 396 : SM_ENTER(EAP, NAK);
1207 22152 : else if (sm->rxResp && (sm->respId == sm->currentId) &&
1208 11058 : ((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 11058 : SM_ENTER(EAP, INTEGRITY_CHECK);
1213 : #ifdef CONFIG_ERP
1214 36 : else if (sm->rxInitiate)
1215 27 : SM_ENTER(EAP, INITIATE_RECEIVED);
1216 : #endif /* CONFIG_ERP */
1217 : else {
1218 18 : wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
1219 : "rxResp=%d respId=%d currentId=%d "
1220 : "respMethod=%d currentMethod=%d",
1221 9 : sm->rxResp, sm->respId, sm->currentId,
1222 9 : sm->respMethod, sm->currentMethod);
1223 9 : eap_log_msg(sm, "Discard received EAP message");
1224 9 : SM_ENTER(EAP, DISCARD);
1225 : }
1226 11490 : break;
1227 : case EAP_DISCARD:
1228 9 : SM_ENTER(EAP, IDLE);
1229 9 : break;
1230 : case EAP_SEND_REQUEST:
1231 11941 : SM_ENTER(EAP, IDLE);
1232 11941 : break;
1233 : case EAP_INTEGRITY_CHECK:
1234 11058 : if (sm->ignore)
1235 0 : SM_ENTER(EAP, DISCARD);
1236 : else
1237 11058 : SM_ENTER(EAP, METHOD_RESPONSE);
1238 11058 : break;
1239 : case EAP_METHOD_REQUEST:
1240 11898 : 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 4 : SM_ENTER(EAP, FAILURE);
1247 4 : break;
1248 : }
1249 11894 : SM_ENTER(EAP, SEND_REQUEST);
1250 11894 : 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 21 : wpa_printf(MSG_DEBUG,
1257 : "EAP: Method did not return a request");
1258 21 : SM_ENTER(EAP, FAILURE);
1259 21 : break;
1260 : }
1261 11873 : 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 13131 : if (sm->methodState == METHOD_END)
1270 6509 : SM_ENTER(EAP, SELECT_ACTION);
1271 6622 : else if (sm->method_pending == METHOD_PENDING_WAIT) {
1272 248 : wpa_printf(MSG_DEBUG, "EAP: Method has pending "
1273 : "processing - wait before proceeding to "
1274 : "METHOD_REQUEST state");
1275 6374 : } else if (sm->method_pending == METHOD_PENDING_CONT) {
1276 185 : wpa_printf(MSG_DEBUG, "EAP: Method has completed "
1277 : "pending processing - reprocess pending "
1278 : "EAP message");
1279 185 : sm->method_pending = METHOD_PENDING_NONE;
1280 185 : SM_ENTER(EAP, METHOD_RESPONSE);
1281 : } else
1282 6189 : SM_ENTER(EAP, METHOD_REQUEST);
1283 13131 : 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 5712 : if (sm->method_pending == METHOD_PENDING_WAIT) {
1292 2 : wpa_printf(MSG_DEBUG, "EAP: Method has pending "
1293 : "processing - wait before proceeding to "
1294 : "METHOD_REQUEST state");
1295 2 : if (sm->user_eap_method_index > 0)
1296 1 : sm->user_eap_method_index--;
1297 5710 : } else if (sm->method_pending == METHOD_PENDING_CONT) {
1298 1 : wpa_printf(MSG_DEBUG, "EAP: Method has completed "
1299 : "pending processing - reprocess pending "
1300 : "EAP message");
1301 1 : sm->method_pending = METHOD_PENDING_NONE;
1302 1 : SM_ENTER(EAP, PROPOSE_METHOD);
1303 : } else
1304 5709 : SM_ENTER(EAP, METHOD_REQUEST);
1305 5712 : break;
1306 : case EAP_NAK:
1307 396 : SM_ENTER(EAP, SELECT_ACTION);
1308 396 : break;
1309 : case EAP_SELECT_ACTION:
1310 9944 : if (sm->decision == DECISION_FAILURE)
1311 807 : SM_ENTER(EAP, FAILURE);
1312 9137 : else if (sm->decision == DECISION_SUCCESS)
1313 1265 : SM_ENTER(EAP, SUCCESS);
1314 7872 : else if (sm->decision == DECISION_PASSTHROUGH)
1315 2079 : SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
1316 5793 : else if (sm->decision == DECISION_INITIATE_REAUTH_START)
1317 68 : SM_ENTER(EAP, INITIATE_REAUTH_START);
1318 : #ifdef CONFIG_ERP
1319 5725 : else if (sm->eap_server && sm->erp && sm->rxInitiate)
1320 16 : SM_ENTER(EAP, INITIATE_RECEIVED);
1321 : #endif /* CONFIG_ERP */
1322 : else
1323 5709 : SM_ENTER(EAP, PROPOSE_METHOD);
1324 9944 : break;
1325 : case EAP_INITIATE_REAUTH_START:
1326 68 : SM_ENTER(EAP, SEND_REQUEST);
1327 68 : break;
1328 : case EAP_INITIATE_RECEIVED:
1329 60 : if (!sm->eap_server)
1330 16 : SM_ENTER(EAP, SELECT_ACTION);
1331 60 : break;
1332 : case EAP_TIMEOUT_FAILURE:
1333 0 : break;
1334 : case EAP_FAILURE:
1335 832 : break;
1336 : case EAP_SUCCESS:
1337 1716 : break;
1338 :
1339 : case EAP_INITIALIZE_PASSTHROUGH:
1340 2079 : if (sm->currentId == -1)
1341 0 : SM_ENTER(EAP, AAA_IDLE);
1342 : else
1343 2079 : SM_ENTER(EAP, AAA_REQUEST);
1344 2079 : break;
1345 : case EAP_IDLE2:
1346 16919 : if (sm->eap_if.eapResp)
1347 5201 : SM_ENTER(EAP, RECEIVED2);
1348 11718 : else if (sm->eap_if.retransWhile == 0)
1349 6 : SM_ENTER(EAP, RETRANSMIT2);
1350 16919 : break;
1351 : case EAP_RETRANSMIT2:
1352 6 : if (sm->retransCount > sm->MaxRetrans)
1353 0 : SM_ENTER(EAP, TIMEOUT_FAILURE2);
1354 : else
1355 6 : SM_ENTER(EAP, IDLE2);
1356 6 : break;
1357 : case EAP_RECEIVED2:
1358 5201 : if (sm->rxResp && (sm->respId == sm->currentId))
1359 5199 : SM_ENTER(EAP, AAA_REQUEST);
1360 : else
1361 2 : SM_ENTER(EAP, DISCARD2);
1362 5201 : break;
1363 : case EAP_DISCARD2:
1364 2 : SM_ENTER(EAP, IDLE2);
1365 2 : break;
1366 : case EAP_SEND_REQUEST2:
1367 5829 : SM_ENTER(EAP, IDLE2);
1368 5829 : break;
1369 : case EAP_AAA_REQUEST:
1370 7278 : SM_ENTER(EAP, AAA_IDLE);
1371 7278 : break;
1372 : case EAP_AAA_RESPONSE:
1373 5829 : SM_ENTER(EAP, SEND_REQUEST2);
1374 5829 : break;
1375 : case EAP_AAA_IDLE:
1376 22035 : if (sm->eap_if.aaaFail)
1377 186 : SM_ENTER(EAP, FAILURE2);
1378 21849 : else if (sm->eap_if.aaaSuccess)
1379 1119 : SM_ENTER(EAP, SUCCESS2);
1380 20730 : else if (sm->eap_if.aaaEapReq)
1381 5829 : SM_ENTER(EAP, AAA_RESPONSE);
1382 14901 : else if (sm->eap_if.aaaTimeout)
1383 0 : SM_ENTER(EAP, TIMEOUT_FAILURE2);
1384 22035 : break;
1385 : case EAP_TIMEOUT_FAILURE2:
1386 0 : break;
1387 : case EAP_FAILURE2:
1388 186 : break;
1389 : case EAP_SUCCESS2:
1390 3498 : break;
1391 : }
1392 201213 : }
1393 :
1394 :
1395 17791 : 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 17791 : if (sm->try_initiate_reauth) {
1402 68 : wpa_printf(MSG_DEBUG,
1403 : "EAP: retransmit timeout 1 second for EAP-Initiate-Re-auth-Start");
1404 68 : return 1;
1405 : }
1406 :
1407 17723 : 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 2185 : wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
1414 : "(from EAP method hint)", methodTimeout);
1415 2185 : 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 15538 : rto = 3;
1437 15548 : for (i = 0; i < retransCount; i++) {
1438 10 : rto *= 2;
1439 10 : if (rto >= 20) {
1440 0 : rto = 20;
1441 0 : break;
1442 : }
1443 : }
1444 :
1445 15538 : wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
1446 : "(from dynamic back off; retransCount=%d)",
1447 : rto, retransCount);
1448 :
1449 15538 : return rto;
1450 : }
1451 :
1452 :
1453 18347 : 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 18347 : sm->rxResp = FALSE;
1460 18347 : sm->rxInitiate = FALSE;
1461 18347 : sm->respId = -1;
1462 18347 : sm->respMethod = EAP_TYPE_NONE;
1463 18347 : sm->respVendor = EAP_VENDOR_IETF;
1464 18347 : sm->respVendorMethod = EAP_TYPE_NONE;
1465 :
1466 18347 : 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 18347 : hdr = wpabuf_head(resp);
1474 18347 : plen = be_to_host16(hdr->length);
1475 18347 : 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 18347 : sm->respId = hdr->identifier;
1484 :
1485 18347 : if (hdr->code == EAP_CODE_RESPONSE)
1486 18304 : sm->rxResp = TRUE;
1487 43 : else if (hdr->code == EAP_CODE_INITIATE)
1488 43 : sm->rxInitiate = TRUE;
1489 :
1490 18347 : if (plen > sizeof(*hdr)) {
1491 18347 : u8 *pos = (u8 *) (hdr + 1);
1492 18347 : sm->respMethod = *pos++;
1493 18347 : if (sm->respMethod == EAP_TYPE_EXPANDED) {
1494 2172 : 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 2172 : sm->respVendor = WPA_GET_BE24(pos);
1501 2172 : pos += 3;
1502 2172 : sm->respVendorMethod = WPA_GET_BE32(pos);
1503 : }
1504 : }
1505 :
1506 55041 : wpa_printf(MSG_DEBUG,
1507 : "EAP: parseEapResp: rxResp=%d rxInitiate=%d respId=%d respMethod=%u respVendor=%u respVendorMethod=%u",
1508 36694 : sm->rxResp, sm->rxInitiate, sm->respId, sm->respMethod,
1509 : sm->respVendor, sm->respVendorMethod);
1510 : }
1511 :
1512 :
1513 5829 : static int eap_sm_getId(const struct wpabuf *data)
1514 : {
1515 : const struct eap_hdr *hdr;
1516 :
1517 5829 : if (data == NULL || wpabuf_len(data) < sizeof(*hdr))
1518 2 : return -1;
1519 :
1520 5827 : hdr = wpabuf_head(data);
1521 5827 : wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
1522 5827 : return hdr->identifier;
1523 : }
1524 :
1525 :
1526 1265 : static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
1527 : {
1528 : struct wpabuf *msg;
1529 : struct eap_hdr *resp;
1530 1265 : wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
1531 :
1532 1265 : msg = wpabuf_alloc(sizeof(*resp));
1533 1265 : if (msg == NULL)
1534 0 : return NULL;
1535 1265 : resp = wpabuf_put(msg, sizeof(*resp));
1536 1265 : resp->code = EAP_CODE_SUCCESS;
1537 1265 : resp->identifier = id;
1538 1265 : resp->length = host_to_be16(sizeof(*resp));
1539 :
1540 1265 : return msg;
1541 : }
1542 :
1543 :
1544 832 : static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id)
1545 : {
1546 : struct wpabuf *msg;
1547 : struct eap_hdr *resp;
1548 832 : wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
1549 :
1550 832 : msg = wpabuf_alloc(sizeof(*resp));
1551 832 : if (msg == NULL)
1552 0 : return NULL;
1553 832 : resp = wpabuf_put(msg, sizeof(*resp));
1554 832 : resp->code = EAP_CODE_FAILURE;
1555 832 : resp->identifier = id;
1556 832 : resp->length = host_to_be16(sizeof(*resp));
1557 :
1558 832 : return msg;
1559 : }
1560 :
1561 :
1562 11962 : static int eap_sm_nextId(struct eap_sm *sm, int id)
1563 : {
1564 11962 : if (id < 0) {
1565 : /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
1566 : * random number */
1567 3007 : id = rand() & 0xff;
1568 3007 : if (id != sm->lastId)
1569 2999 : return id;
1570 : }
1571 8963 : 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 422 : 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 422 : if (sm->user == NULL)
1590 422 : return;
1591 :
1592 422 : wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
1593 : "index %d)", sm->user_eap_method_index);
1594 :
1595 422 : wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
1596 422 : (u8 *) sm->user->methods,
1597 : EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
1598 422 : wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
1599 : nak_list, len);
1600 :
1601 422 : i = sm->user_eap_method_index;
1602 5104 : while (i < EAP_MAX_METHODS &&
1603 4682 : (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
1604 2341 : sm->user->methods[i].method != EAP_TYPE_NONE)) {
1605 1919 : if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
1606 0 : goto not_found;
1607 3501 : for (j = 0; j < len; j++) {
1608 1919 : if (nak_list[j] == sm->user->methods[i].method) {
1609 337 : break;
1610 : }
1611 : }
1612 :
1613 1919 : if (j < len) {
1614 : /* found */
1615 337 : i++;
1616 337 : continue;
1617 : }
1618 :
1619 : not_found:
1620 : /* not found - remove from the list */
1621 1582 : if (i + 1 < EAP_MAX_METHODS) {
1622 1582 : 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 1582 : sm->user->methods[EAP_MAX_METHODS - 1].vendor =
1628 : EAP_VENDOR_IETF;
1629 1582 : sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
1630 : }
1631 :
1632 422 : wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
1633 422 : (u8 *) sm->user->methods, EAP_MAX_METHODS *
1634 : sizeof(sm->user->methods[0]));
1635 : }
1636 :
1637 :
1638 6905 : static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
1639 : size_t len)
1640 : {
1641 6905 : if (nak_list == NULL || sm == NULL || sm->user == NULL)
1642 6528 : return;
1643 :
1644 377 : 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 377 : eap_sm_process_nak(sm, nak_list, len);
1652 : }
1653 :
1654 :
1655 5716 : static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
1656 : {
1657 : EapType next;
1658 5716 : 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 5716 : if (sm->identity == NULL || sm->currentId == -1) {
1668 2941 : *vendor = EAP_VENDOR_IETF;
1669 2941 : next = EAP_TYPE_IDENTITY;
1670 2941 : sm->update_user = TRUE;
1671 5550 : } else if (sm->user && idx < EAP_MAX_METHODS &&
1672 4992 : (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
1673 2217 : sm->user->methods[idx].method != EAP_TYPE_NONE)) {
1674 2771 : *vendor = sm->user->methods[idx].vendor;
1675 2771 : next = sm->user->methods[idx].method;
1676 2771 : sm->user_eap_method_index++;
1677 : } else {
1678 4 : *vendor = EAP_VENDOR_IETF;
1679 4 : next = EAP_TYPE_NONE;
1680 : }
1681 5716 : wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
1682 : *vendor, next);
1683 5716 : return next;
1684 : }
1685 :
1686 :
1687 9944 : static int eap_sm_Policy_getDecision(struct eap_sm *sm)
1688 : {
1689 9944 : if (!sm->eap_server && sm->identity && !sm->start_reauth) {
1690 2079 : wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
1691 2079 : return DECISION_PASSTHROUGH;
1692 : }
1693 :
1694 9830 : if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
1695 1965 : sm->m->isSuccess(sm, sm->eap_method_priv)) {
1696 1265 : wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
1697 : "SUCCESS");
1698 1265 : sm->update_user = TRUE;
1699 1265 : return DECISION_SUCCESS;
1700 : }
1701 :
1702 9781 : if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
1703 3181 : !sm->m->isSuccess(sm, sm->eap_method_priv)) {
1704 703 : wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
1705 : "FAILURE");
1706 703 : sm->update_user = TRUE;
1707 703 : return DECISION_FAILURE;
1708 : }
1709 :
1710 8435 : if ((sm->user == NULL || sm->update_user) && sm->identity &&
1711 2538 : !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 2538 : int id_req = 0;
1719 2634 : if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
1720 190 : sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
1721 94 : sm->user->methods[0].method == EAP_TYPE_IDENTITY)
1722 0 : id_req = 1;
1723 2538 : 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 2537 : 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 2537 : sm->update_user = FALSE;
1737 : }
1738 5896 : sm->start_reauth = FALSE;
1739 :
1740 8869 : if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
1741 2973 : (sm->user->methods[sm->user_eap_method_index].vendor !=
1742 2413 : EAP_VENDOR_IETF ||
1743 2413 : sm->user->methods[sm->user_eap_method_index].method !=
1744 : EAP_TYPE_NONE)) {
1745 2865 : wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
1746 : "available -> CONTINUE");
1747 2865 : return DECISION_CONTINUE;
1748 : }
1749 :
1750 3143 : if (!sm->identity && eap_get_erp_send_reauth_start(sm) &&
1751 112 : !sm->initiate_reauth_start_sent) {
1752 68 : wpa_printf(MSG_DEBUG,
1753 : "EAP: getDecision: send EAP-Initiate/Re-auth-Start");
1754 68 : return DECISION_INITIATE_REAUTH_START;
1755 : }
1756 :
1757 2963 : if (sm->identity == NULL || sm->currentId == -1) {
1758 2860 : wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
1759 : "yet -> CONTINUE");
1760 2860 : return DECISION_CONTINUE;
1761 : }
1762 :
1763 103 : wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
1764 : "FAILURE");
1765 103 : return DECISION_FAILURE;
1766 : }
1767 :
1768 :
1769 1640 : static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
1770 : {
1771 1640 : 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 63992 : int eap_server_sm_step(struct eap_sm *sm)
1785 : {
1786 63992 : int res = 0;
1787 : do {
1788 201213 : sm->changed = FALSE;
1789 201213 : SM_STEP_RUN(EAP);
1790 201213 : if (sm->changed)
1791 137221 : res = 1;
1792 201213 : } while (sm->changed);
1793 63992 : return res;
1794 : }
1795 :
1796 :
1797 7953 : static void eap_user_free(struct eap_user *user)
1798 : {
1799 7953 : if (user == NULL)
1800 12323 : return;
1801 3583 : bin_clear_free(user->password, user->password_len);
1802 3583 : user->password = NULL;
1803 3583 : 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 4359 : 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 4359 : sm = os_zalloc(sizeof(*sm));
1823 4359 : if (sm == NULL)
1824 0 : return NULL;
1825 4359 : sm->eapol_ctx = eapol_ctx;
1826 4359 : sm->eapol_cb = eapol_cb;
1827 4359 : sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
1828 4359 : sm->ssl_ctx = conf->ssl_ctx;
1829 4359 : sm->msg_ctx = conf->msg_ctx;
1830 4359 : sm->eap_sim_db_priv = conf->eap_sim_db_priv;
1831 4359 : sm->backend_auth = conf->backend_auth;
1832 4359 : sm->eap_server = conf->eap_server;
1833 4359 : if (conf->pac_opaque_encr_key) {
1834 1654 : sm->pac_opaque_encr_key = os_malloc(16);
1835 1654 : if (sm->pac_opaque_encr_key) {
1836 1654 : os_memcpy(sm->pac_opaque_encr_key,
1837 : conf->pac_opaque_encr_key, 16);
1838 : }
1839 : }
1840 4359 : if (conf->eap_fast_a_id) {
1841 1654 : sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
1842 1654 : if (sm->eap_fast_a_id) {
1843 1654 : os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
1844 : conf->eap_fast_a_id_len);
1845 1654 : sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
1846 : }
1847 : }
1848 4359 : if (conf->eap_fast_a_id_info)
1849 1654 : sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
1850 4359 : sm->eap_fast_prov = conf->eap_fast_prov;
1851 4359 : sm->pac_key_lifetime = conf->pac_key_lifetime;
1852 4359 : sm->pac_key_refresh_time = conf->pac_key_refresh_time;
1853 4359 : sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
1854 4359 : sm->tnc = conf->tnc;
1855 4359 : sm->wps = conf->wps;
1856 4359 : if (conf->assoc_wps_ie)
1857 535 : sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
1858 4359 : if (conf->assoc_p2p_ie)
1859 242 : sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie);
1860 4359 : if (conf->peer_addr)
1861 2698 : os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
1862 4359 : sm->fragment_size = conf->fragment_size;
1863 4359 : sm->pwd_group = conf->pwd_group;
1864 4359 : sm->pbc_in_m1 = conf->pbc_in_m1;
1865 4359 : sm->server_id = conf->server_id;
1866 4359 : sm->server_id_len = conf->server_id_len;
1867 4359 : sm->erp = conf->erp;
1868 4359 : sm->tls_session_lifetime = conf->tls_session_lifetime;
1869 :
1870 : #ifdef CONFIG_TESTING_OPTIONS
1871 4359 : sm->tls_test_flags = conf->tls_test_flags;
1872 : #endif /* CONFIG_TESTING_OPTIONS */
1873 :
1874 4359 : wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
1875 :
1876 4359 : 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 4359 : void eap_server_sm_deinit(struct eap_sm *sm)
1888 : {
1889 4359 : if (sm == NULL)
1890 4359 : return;
1891 4359 : wpa_printf(MSG_DEBUG, "EAP: Server state machine removed");
1892 4359 : if (sm->m && sm->eap_method_priv)
1893 4174 : sm->m->reset(sm, sm->eap_method_priv);
1894 4359 : wpabuf_free(sm->eap_if.eapReqData);
1895 4359 : bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
1896 4359 : os_free(sm->eap_if.eapSessionId);
1897 4359 : wpabuf_free(sm->lastReqData);
1898 4359 : wpabuf_free(sm->eap_if.eapRespData);
1899 4359 : os_free(sm->identity);
1900 4359 : os_free(sm->pac_opaque_encr_key);
1901 4359 : os_free(sm->eap_fast_a_id);
1902 4359 : os_free(sm->eap_fast_a_id_info);
1903 4359 : wpabuf_free(sm->eap_if.aaaEapReqData);
1904 4359 : wpabuf_free(sm->eap_if.aaaEapRespData);
1905 4359 : bin_clear_free(sm->eap_if.aaaEapKeyData, sm->eap_if.aaaEapKeyDataLen);
1906 4359 : eap_user_free(sm->user);
1907 4359 : wpabuf_free(sm->assoc_wps_ie);
1908 4359 : wpabuf_free(sm->assoc_p2p_ie);
1909 4359 : 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 41 : void eap_sm_notify_cached(struct eap_sm *sm)
1921 : {
1922 41 : if (sm == NULL)
1923 41 : return;
1924 :
1925 41 : 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 187 : void eap_sm_pending_cb(struct eap_sm *sm)
1936 : {
1937 187 : if (sm == NULL)
1938 187 : return;
1939 187 : wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
1940 187 : if (sm->method_pending == METHOD_PENDING_WAIT)
1941 186 : 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 134 : int eap_sm_method_pending(struct eap_sm *sm)
1951 : {
1952 134 : if (sm == NULL)
1953 0 : return 0;
1954 134 : 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 2079 : const u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
1965 : {
1966 2079 : *len = sm->identity_len;
1967 2079 : 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 4359 : struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
1977 : {
1978 4359 : 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 292 : void eap_server_clear_identity(struct eap_sm *sm)
1991 : {
1992 292 : os_free(sm->identity);
1993 292 : sm->identity = NULL;
1994 292 : }
1995 :
1996 :
1997 : #ifdef CONFIG_TESTING_OPTIONS
1998 265 : 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 265 : if (username)
2006 265 : printf_encode(user, sizeof(user), username, username_len);
2007 : else
2008 0 : user[0] = '\0';
2009 265 : wpa_snprintf_hex_sep(hex_challenge, sizeof(hex_challenge),
2010 : challenge, sizeof(challenge), ':');
2011 265 : wpa_snprintf_hex_sep(hex_response, sizeof(hex_response), response, 24,
2012 : ':');
2013 265 : wpa_printf(MSG_DEBUG, "[%s/user=%s] asleap -C %s -R %s",
2014 : source, user, hex_challenge, hex_response);
2015 265 : }
2016 : #endif /* CONFIG_TESTING_OPTIONS */
|