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