eap_server.c revision fe31a9a8fff325bfddbf06fc3e9edaf480824bee
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 28static void eap_user_free(struct eap_user *user); 29 30 31/* EAP state machines are described in RFC 4137 */ 32 33static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, 34 int eapSRTT, int eapRTTVAR, 35 int methodTimeout); 36static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp); 37static int eap_sm_getId(const struct wpabuf *data); 38static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id); 39static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id); 40static int eap_sm_nextId(struct eap_sm *sm, int id); 41static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, 42 size_t len); 43static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor); 44static int eap_sm_Policy_getDecision(struct eap_sm *sm); 45static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method); 46 47 48static 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 56static 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 66static 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 75static 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 85static 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, 100 (EapType) EAP_ERP_TYPE_REAUTH_START, plen, 101 EAP_CODE_INITIATE, id); 102 if (msg == NULL) 103 return NULL; 104 wpabuf_put_u8(msg, 0); /* Reserved */ 105 if (domain) { 106 /* Domain name TLV */ 107 wpabuf_put_u8(msg, EAP_ERP_TLV_DOMAIN_NAME); 108 wpabuf_put_u8(msg, domain_len); 109 wpabuf_put_data(msg, domain, domain_len); 110 } 111 112 return msg; 113} 114 115 116static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src) 117{ 118 if (src == NULL) 119 return -1; 120 121 wpabuf_free(*dst); 122 *dst = wpabuf_dup(src); 123 return *dst ? 0 : -1; 124} 125 126 127static int eap_copy_data(u8 **dst, size_t *dst_len, 128 const u8 *src, size_t src_len) 129{ 130 if (src == NULL) 131 return -1; 132 133 os_free(*dst); 134 *dst = os_malloc(src_len); 135 if (*dst) { 136 os_memcpy(*dst, src, src_len); 137 *dst_len = src_len; 138 return 0; 139 } else { 140 *dst_len = 0; 141 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 */ 162int 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 if (sm == NULL || sm->eapol_cb == NULL || 168 sm->eapol_cb->get_eap_user == NULL) 169 return -1; 170 171 eap_user_free(sm->user); 172 sm->user = NULL; 173 174 user = os_zalloc(sizeof(*user)); 175 if (user == NULL) 176 return -1; 177 178 if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity, 179 identity_len, phase2, user) != 0) { 180 eap_user_free(user); 181 return -1; 182 } 183 184 sm->user = user; 185 sm->user_eap_method_index = 0; 186 187 return 0; 188} 189 190 191void eap_log_msg(struct eap_sm *sm, const char *fmt, ...) 192{ 193 va_list ap; 194 char *buf; 195 int buflen; 196 197 if (sm == NULL || sm->eapol_cb == NULL || sm->eapol_cb->log_msg == NULL) 198 return; 199 200 va_start(ap, fmt); 201 buflen = vsnprintf(NULL, 0, fmt, ap) + 1; 202 va_end(ap); 203 204 buf = os_malloc(buflen); 205 if (buf == NULL) 206 return; 207 va_start(ap, fmt); 208 vsnprintf(buf, buflen, fmt, ap); 209 va_end(ap); 210 211 sm->eapol_cb->log_msg(sm->eapol_ctx, buf); 212 213 os_free(buf); 214} 215 216 217SM_STATE(EAP, DISABLED) 218{ 219 SM_ENTRY(EAP, DISABLED); 220 sm->num_rounds = 0; 221} 222 223 224SM_STATE(EAP, INITIALIZE) 225{ 226 SM_ENTRY(EAP, INITIALIZE); 227 228 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 eap_server_clear_identity(sm); 234 } 235 236 sm->try_initiate_reauth = FALSE; 237 sm->currentId = -1; 238 sm->eap_if.eapSuccess = FALSE; 239 sm->eap_if.eapFail = FALSE; 240 sm->eap_if.eapTimeout = FALSE; 241 bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); 242 sm->eap_if.eapKeyData = NULL; 243 sm->eap_if.eapKeyDataLen = 0; 244 os_free(sm->eap_if.eapSessionId); 245 sm->eap_if.eapSessionId = NULL; 246 sm->eap_if.eapSessionIdLen = 0; 247 sm->eap_if.eapKeyAvailable = FALSE; 248 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 if (sm->m && sm->eap_method_priv) { 256 sm->m->reset(sm, sm->eap_method_priv); 257 sm->eap_method_priv = NULL; 258 } 259 sm->m = NULL; 260 sm->user_eap_method_index = 0; 261 262 if (sm->backend_auth) { 263 sm->currentMethod = EAP_TYPE_NONE; 264 /* parse rxResp, respId, respMethod */ 265 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); 266 if (sm->rxResp) { 267 sm->currentId = sm->respId; 268 } 269 } 270 sm->num_rounds = 0; 271 sm->method_pending = METHOD_PENDING_NONE; 272 273 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED 274 MACSTR, MAC2STR(sm->peer_addr)); 275} 276 277 278SM_STATE(EAP, PICK_UP_METHOD) 279{ 280 SM_ENTRY(EAP, PICK_UP_METHOD); 281 282 if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) { 283 sm->currentMethod = sm->respMethod; 284 if (sm->m && sm->eap_method_priv) { 285 sm->m->reset(sm, sm->eap_method_priv); 286 sm->eap_method_priv = NULL; 287 } 288 sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF, 289 sm->currentMethod); 290 if (sm->m && sm->m->initPickUp) { 291 sm->eap_method_priv = sm->m->initPickUp(sm); 292 if (sm->eap_method_priv == NULL) { 293 wpa_printf(MSG_DEBUG, "EAP: Failed to " 294 "initialize EAP method %d", 295 sm->currentMethod); 296 sm->m = NULL; 297 sm->currentMethod = EAP_TYPE_NONE; 298 } 299 } else { 300 sm->m = NULL; 301 sm->currentMethod = EAP_TYPE_NONE; 302 } 303 } 304 305 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD 306 "method=%u", sm->currentMethod); 307} 308 309 310SM_STATE(EAP, IDLE) 311{ 312 SM_ENTRY(EAP, IDLE); 313 314 sm->eap_if.retransWhile = eap_sm_calculateTimeout( 315 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, 316 sm->methodTimeout); 317} 318 319 320SM_STATE(EAP, RETRANSMIT) 321{ 322 SM_ENTRY(EAP, RETRANSMIT); 323 324 sm->retransCount++; 325 if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { 326 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) 327 sm->eap_if.eapReq = TRUE; 328 } 329} 330 331 332SM_STATE(EAP, RECEIVED) 333{ 334 SM_ENTRY(EAP, RECEIVED); 335 336 /* parse rxResp, respId, respMethod */ 337 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); 338 sm->num_rounds++; 339} 340 341 342SM_STATE(EAP, DISCARD) 343{ 344 SM_ENTRY(EAP, DISCARD); 345 sm->eap_if.eapResp = FALSE; 346 sm->eap_if.eapNoReq = TRUE; 347} 348 349 350SM_STATE(EAP, SEND_REQUEST) 351{ 352 SM_ENTRY(EAP, SEND_REQUEST); 353 354 sm->retransCount = 0; 355 if (sm->eap_if.eapReqData) { 356 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) 357 { 358 sm->eap_if.eapResp = FALSE; 359 sm->eap_if.eapReq = TRUE; 360 } else { 361 sm->eap_if.eapResp = FALSE; 362 sm->eap_if.eapReq = FALSE; 363 } 364 } else { 365 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); 366 sm->eap_if.eapResp = FALSE; 367 sm->eap_if.eapReq = FALSE; 368 sm->eap_if.eapNoReq = TRUE; 369 } 370} 371 372 373SM_STATE(EAP, INTEGRITY_CHECK) 374{ 375 SM_ENTRY(EAP, INTEGRITY_CHECK); 376 377 if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) { 378 sm->ignore = TRUE; 379 return; 380 } 381 382 if (sm->m->check) { 383 sm->ignore = sm->m->check(sm, sm->eap_method_priv, 384 sm->eap_if.eapRespData); 385 } 386} 387 388 389SM_STATE(EAP, METHOD_REQUEST) 390{ 391 SM_ENTRY(EAP, METHOD_REQUEST); 392 393 if (sm->m == NULL) { 394 wpa_printf(MSG_DEBUG, "EAP: method not initialized"); 395 return; 396 } 397 398 sm->currentId = eap_sm_nextId(sm, sm->currentId); 399 wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d", 400 sm->currentId); 401 sm->lastId = sm->currentId; 402 wpabuf_free(sm->eap_if.eapReqData); 403 sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv, 404 sm->currentId); 405 if (sm->m->getTimeout) 406 sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv); 407 else 408 sm->methodTimeout = 0; 409} 410 411 412static void eap_server_erp_init(struct eap_sm *sm) 413{ 414#ifdef CONFIG_ERP 415 u8 *emsk = NULL; 416 size_t emsk_len = 0; 417 u8 EMSKname[EAP_EMSK_NAME_LEN]; 418 u8 len[2]; 419 const char *domain; 420 size_t domain_len, nai_buf_len; 421 struct eap_server_erp_key *erp = NULL; 422 int pos; 423 424 domain = eap_get_erp_domain(sm); 425 if (!domain) 426 return; 427 428 domain_len = os_strlen(domain); 429 430 nai_buf_len = 2 * EAP_EMSK_NAME_LEN + 1 + domain_len; 431 if (nai_buf_len > 253) { 432 /* 433 * keyName-NAI has a maximum length of 253 octet to fit in 434 * RADIUS attributes. 435 */ 436 wpa_printf(MSG_DEBUG, 437 "EAP: Too long realm for ERP keyName-NAI maximum length"); 438 return; 439 } 440 nai_buf_len++; /* null termination */ 441 erp = os_zalloc(sizeof(*erp) + nai_buf_len); 442 if (erp == NULL) 443 goto fail; 444 erp->recv_seq = (u32) -1; 445 446 emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len); 447 if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) { 448 wpa_printf(MSG_DEBUG, 449 "EAP: No suitable EMSK available for ERP"); 450 goto fail; 451 } 452 453 wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len); 454 455 WPA_PUT_BE16(len, 8); 456 if (hmac_sha256_kdf(sm->eap_if.eapSessionId, sm->eap_if.eapSessionIdLen, 457 "EMSK", len, sizeof(len), 458 EMSKname, EAP_EMSK_NAME_LEN) < 0) { 459 wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname"); 460 goto fail; 461 } 462 wpa_hexdump(MSG_DEBUG, "EAP: EMSKname", EMSKname, EAP_EMSK_NAME_LEN); 463 464 pos = wpa_snprintf_hex(erp->keyname_nai, nai_buf_len, 465 EMSKname, EAP_EMSK_NAME_LEN); 466 erp->keyname_nai[pos] = '@'; 467 os_memcpy(&erp->keyname_nai[pos + 1], domain, domain_len); 468 469 WPA_PUT_BE16(len, emsk_len); 470 if (hmac_sha256_kdf(emsk, emsk_len, 471 "EAP Re-authentication Root Key@ietf.org", 472 len, sizeof(len), erp->rRK, emsk_len) < 0) { 473 wpa_printf(MSG_DEBUG, "EAP: Could not derive rRK for ERP"); 474 goto fail; 475 } 476 erp->rRK_len = emsk_len; 477 wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len); 478 479 if (hmac_sha256_kdf(erp->rRK, erp->rRK_len, 480 "EAP Re-authentication Integrity Key@ietf.org", 481 len, sizeof(len), erp->rIK, erp->rRK_len) < 0) { 482 wpa_printf(MSG_DEBUG, "EAP: Could not derive rIK for ERP"); 483 goto fail; 484 } 485 erp->rIK_len = erp->rRK_len; 486 wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rIK", erp->rIK, erp->rIK_len); 487 488 if (eap_erp_add_key(sm, erp) == 0) { 489 wpa_printf(MSG_DEBUG, "EAP: Stored ERP keys %s", 490 erp->keyname_nai); 491 erp = NULL; 492 } 493 494fail: 495 bin_clear_free(emsk, emsk_len); 496 bin_clear_free(erp, sizeof(*erp)); 497#endif /* CONFIG_ERP */ 498} 499 500 501SM_STATE(EAP, METHOD_RESPONSE) 502{ 503 SM_ENTRY(EAP, METHOD_RESPONSE); 504 505 if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) 506 return; 507 508 sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData); 509 if (sm->m->isDone(sm, sm->eap_method_priv)) { 510 eap_sm_Policy_update(sm, NULL, 0); 511 bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); 512 if (sm->m->getKey) { 513 sm->eap_if.eapKeyData = sm->m->getKey( 514 sm, sm->eap_method_priv, 515 &sm->eap_if.eapKeyDataLen); 516 } else { 517 sm->eap_if.eapKeyData = NULL; 518 sm->eap_if.eapKeyDataLen = 0; 519 } 520 os_free(sm->eap_if.eapSessionId); 521 sm->eap_if.eapSessionId = NULL; 522 if (sm->m->getSessionId) { 523 sm->eap_if.eapSessionId = sm->m->getSessionId( 524 sm, sm->eap_method_priv, 525 &sm->eap_if.eapSessionIdLen); 526 wpa_hexdump(MSG_DEBUG, "EAP: Session-Id", 527 sm->eap_if.eapSessionId, 528 sm->eap_if.eapSessionIdLen); 529 } 530 if (sm->erp && sm->m->get_emsk && sm->eap_if.eapSessionId) 531 eap_server_erp_init(sm); 532 sm->methodState = METHOD_END; 533 } else { 534 sm->methodState = METHOD_CONTINUE; 535 } 536} 537 538 539SM_STATE(EAP, PROPOSE_METHOD) 540{ 541 int vendor; 542 EapType type; 543 544 SM_ENTRY(EAP, PROPOSE_METHOD); 545 546 sm->try_initiate_reauth = FALSE; 547try_another_method: 548 type = eap_sm_Policy_getNextMethod(sm, &vendor); 549 if (vendor == EAP_VENDOR_IETF) 550 sm->currentMethod = type; 551 else 552 sm->currentMethod = EAP_TYPE_EXPANDED; 553 if (sm->m && sm->eap_method_priv) { 554 sm->m->reset(sm, sm->eap_method_priv); 555 sm->eap_method_priv = NULL; 556 } 557 sm->m = eap_server_get_eap_method(vendor, type); 558 if (sm->m) { 559 sm->eap_method_priv = sm->m->init(sm); 560 if (sm->eap_method_priv == NULL) { 561 wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP " 562 "method %d", sm->currentMethod); 563 sm->m = NULL; 564 sm->currentMethod = EAP_TYPE_NONE; 565 goto try_another_method; 566 } 567 } 568 if (sm->m == NULL) { 569 wpa_printf(MSG_DEBUG, "EAP: Could not find suitable EAP method"); 570 eap_log_msg(sm, "Could not find suitable EAP method"); 571 sm->decision = DECISION_FAILURE; 572 return; 573 } 574 if (sm->currentMethod == EAP_TYPE_IDENTITY || 575 sm->currentMethod == EAP_TYPE_NOTIFICATION) 576 sm->methodState = METHOD_CONTINUE; 577 else 578 sm->methodState = METHOD_PROPOSED; 579 580 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD 581 "vendor=%u method=%u", vendor, sm->currentMethod); 582 eap_log_msg(sm, "Propose EAP method vendor=%u method=%u", 583 vendor, sm->currentMethod); 584} 585 586 587SM_STATE(EAP, NAK) 588{ 589 const struct eap_hdr *nak; 590 size_t len = 0; 591 const u8 *pos; 592 const u8 *nak_list = NULL; 593 594 SM_ENTRY(EAP, NAK); 595 596 if (sm->eap_method_priv) { 597 sm->m->reset(sm, sm->eap_method_priv); 598 sm->eap_method_priv = NULL; 599 } 600 sm->m = NULL; 601 602 if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) 603 return; 604 605 nak = wpabuf_head(sm->eap_if.eapRespData); 606 if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) { 607 len = be_to_host16(nak->length); 608 if (len > wpabuf_len(sm->eap_if.eapRespData)) 609 len = wpabuf_len(sm->eap_if.eapRespData); 610 pos = (const u8 *) (nak + 1); 611 len -= sizeof(*nak); 612 if (*pos == EAP_TYPE_NAK) { 613 pos++; 614 len--; 615 nak_list = pos; 616 } 617 } 618 eap_sm_Policy_update(sm, nak_list, len); 619} 620 621 622SM_STATE(EAP, SELECT_ACTION) 623{ 624 SM_ENTRY(EAP, SELECT_ACTION); 625 626 sm->decision = eap_sm_Policy_getDecision(sm); 627} 628 629 630SM_STATE(EAP, TIMEOUT_FAILURE) 631{ 632 SM_ENTRY(EAP, TIMEOUT_FAILURE); 633 634 sm->eap_if.eapTimeout = TRUE; 635} 636 637 638SM_STATE(EAP, FAILURE) 639{ 640 SM_ENTRY(EAP, FAILURE); 641 642 wpabuf_free(sm->eap_if.eapReqData); 643 sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId); 644 wpabuf_free(sm->lastReqData); 645 sm->lastReqData = NULL; 646 sm->eap_if.eapFail = TRUE; 647 648 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE 649 MACSTR, MAC2STR(sm->peer_addr)); 650} 651 652 653SM_STATE(EAP, SUCCESS) 654{ 655 SM_ENTRY(EAP, SUCCESS); 656 657 wpabuf_free(sm->eap_if.eapReqData); 658 sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId); 659 wpabuf_free(sm->lastReqData); 660 sm->lastReqData = NULL; 661 if (sm->eap_if.eapKeyData) 662 sm->eap_if.eapKeyAvailable = TRUE; 663 sm->eap_if.eapSuccess = TRUE; 664 665 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS 666 MACSTR, MAC2STR(sm->peer_addr)); 667} 668 669 670SM_STATE(EAP, INITIATE_REAUTH_START) 671{ 672 SM_ENTRY(EAP, INITIATE_REAUTH_START); 673 674 sm->initiate_reauth_start_sent = TRUE; 675 sm->try_initiate_reauth = TRUE; 676 sm->currentId = eap_sm_nextId(sm, sm->currentId); 677 wpa_printf(MSG_DEBUG, 678 "EAP: building EAP-Initiate-Re-auth-Start: Identifier %d", 679 sm->currentId); 680 sm->lastId = sm->currentId; 681 wpabuf_free(sm->eap_if.eapReqData); 682 sm->eap_if.eapReqData = eap_sm_buildInitiateReauthStart(sm, 683 sm->currentId); 684 wpabuf_free(sm->lastReqData); 685 sm->lastReqData = NULL; 686} 687 688 689#ifdef CONFIG_ERP 690 691static 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 if (erp) { 702 switch (erp->cryptosuite) { 703 case EAP_ERP_CS_HMAC_SHA256_256: 704 hash_len = 32; 705 break; 706 case EAP_ERP_CS_HMAC_SHA256_128: 707 hash_len = 16; 708 break; 709 default: 710 return; 711 } 712 } else 713 hash_len = 0; 714 715 plen = 1 + 2 + 2 + os_strlen(nai); 716 if (hash_len) 717 plen += 1 + hash_len; 718 msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH, 719 plen, EAP_CODE_FINISH, id); 720 if (msg == NULL) 721 return; 722 wpabuf_put_u8(msg, flags); 723 wpabuf_put_be16(msg, seq); 724 725 wpabuf_put_u8(msg, EAP_ERP_TLV_KEYNAME_NAI); 726 wpabuf_put_u8(msg, os_strlen(nai)); 727 wpabuf_put_str(msg, nai); 728 729 if (erp) { 730 wpabuf_put_u8(msg, erp->cryptosuite); 731 if (hmac_sha256(erp->rIK, erp->rIK_len, 732 wpabuf_head(msg), wpabuf_len(msg), hash) < 0) { 733 wpabuf_free(msg); 734 return; 735 } 736 wpabuf_put_data(msg, hash, hash_len); 737 } 738 739 wpa_printf(MSG_DEBUG, "EAP: Send EAP-Finish/Re-auth (%s)", 740 flags & 0x80 ? "failure" : "success"); 741 742 sm->lastId = sm->currentId; 743 sm->currentId = id; 744 wpabuf_free(sm->eap_if.eapReqData); 745 sm->eap_if.eapReqData = msg; 746 wpabuf_free(sm->lastReqData); 747 sm->lastReqData = NULL; 748 749 if ((flags & 0x80) || !erp) { 750 sm->eap_if.eapFail = TRUE; 751 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE 752 MACSTR, MAC2STR(sm->peer_addr)); 753 return; 754 } 755 756 bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); 757 sm->eap_if.eapKeyDataLen = 0; 758 sm->eap_if.eapKeyData = os_malloc(erp->rRK_len); 759 if (!sm->eap_if.eapKeyData) 760 return; 761 762 WPA_PUT_BE16(seed, seq); 763 WPA_PUT_BE16(&seed[2], erp->rRK_len); 764 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 wpa_printf(MSG_DEBUG, "EAP: Could not derive rMSK for ERP"); 769 bin_clear_free(sm->eap_if.eapKeyData, erp->rRK_len); 770 sm->eap_if.eapKeyData = NULL; 771 return; 772 } 773 sm->eap_if.eapKeyDataLen = erp->rRK_len; 774 sm->eap_if.eapKeyAvailable = TRUE; 775 wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK", 776 sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); 777 sm->eap_if.eapSuccess = TRUE; 778 779 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS 780 MACSTR, MAC2STR(sm->peer_addr)); 781} 782 783 784SM_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 u8 resp_flags = 0x80; /* default to failure; cleared on success */ 798 799 SM_ENTRY(EAP, INITIATE_RECEIVED); 800 801 sm->rxInitiate = FALSE; 802 803 pos = eap_hdr_validate(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH, 804 sm->eap_if.eapRespData, &len); 805 if (pos == NULL) { 806 wpa_printf(MSG_INFO, "EAP-Initiate: Invalid frame"); 807 goto fail; 808 } 809 hdr = wpabuf_head(sm->eap_if.eapRespData); 810 ehdr = wpabuf_head(sm->eap_if.eapRespData); 811 812 wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-Auth", pos, len); 813 if (len < 4) { 814 wpa_printf(MSG_INFO, "EAP: Too short EAP-Initiate/Re-auth"); 815 goto fail; 816 } 817 end = pos + len; 818 819 flags = *pos++; 820 seq = WPA_GET_BE16(pos); 821 pos += 2; 822 wpa_printf(MSG_DEBUG, "EAP: Flags=0x%x SEQ=%u", flags, seq); 823 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 if (erp_parse_tlvs(tlvs, end, &parse, 1) < 0) 832 goto fail; 833 834 if (!parse.keyname) { 835 wpa_printf(MSG_DEBUG, 836 "EAP: No keyName-NAI in EAP-Initiate/Re-auth Packet"); 837 goto fail; 838 } 839 840 wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth - keyName-NAI", 841 parse.keyname, parse.keyname_len); 842 if (parse.keyname_len > 253) { 843 wpa_printf(MSG_DEBUG, 844 "EAP: Too long keyName-NAI in EAP-Initiate/Re-auth"); 845 goto fail; 846 } 847 os_memcpy(nai, parse.keyname, parse.keyname_len); 848 nai[parse.keyname_len] = '\0'; 849 850 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 wpa_printf(MSG_DEBUG, 858 "EAP: Use keyName-NAI as user identity for backend authentication"); 859 eap_server_clear_identity(sm); 860 sm->identity = (u8 *) dup_binstr(parse.keyname, 861 parse.keyname_len); 862 if (!sm->identity) 863 goto fail; 864 sm->identity_len = parse.keyname_len; 865 return; 866 } 867 868 erp = eap_erp_get_key(sm, nai); 869 if (!erp) { 870 wpa_printf(MSG_DEBUG, "EAP: No matching ERP key found for %s", 871 nai); 872 goto report_error; 873 } 874 875 if (erp->recv_seq != (u32) -1 && erp->recv_seq >= seq) { 876 wpa_printf(MSG_DEBUG, 877 "EAP: SEQ=%u replayed (already received SEQ=%u)", 878 seq, erp->recv_seq); 879 goto fail; 880 } 881 882 /* Is there enough room for Cryptosuite and Authentication Tag? */ 883 start = parse.keyname + parse.keyname_len; 884 max_len = end - start; 885 if (max_len < 886 1 + (erp->cryptosuite == EAP_ERP_CS_HMAC_SHA256_256 ? 32 : 16)) { 887 wpa_printf(MSG_DEBUG, 888 "EAP: Not enough room for Authentication Tag"); 889 goto fail; 890 } 891 892 switch (erp->cryptosuite) { 893 case EAP_ERP_CS_HMAC_SHA256_256: 894 if (end[-33] != erp->cryptosuite) { 895 wpa_printf(MSG_DEBUG, 896 "EAP: Different Cryptosuite used"); 897 goto fail; 898 } 899 hash_len = 32; 900 break; 901 case EAP_ERP_CS_HMAC_SHA256_128: 902 if (end[-17] != erp->cryptosuite) { 903 wpa_printf(MSG_DEBUG, 904 "EAP: Different Cryptosuite used"); 905 goto fail; 906 } 907 hash_len = 16; 908 break; 909 default: 910 hash_len = 0; 911 break; 912 } 913 914 if (hash_len) { 915 if (hmac_sha256(erp->rIK, erp->rIK_len, hdr, 916 end - hdr - hash_len, hash) < 0) 917 goto fail; 918 if (os_memcmp(end - hash_len, hash, hash_len) != 0) { 919 wpa_printf(MSG_DEBUG, 920 "EAP: Authentication Tag mismatch"); 921 goto fail; 922 } 923 } 924 925 /* Check if any supported CS results in matching tag */ 926 if (!hash_len && max_len >= 1 + 32 && 927 end[-33] == EAP_ERP_CS_HMAC_SHA256_256) { 928 if (hmac_sha256(erp->rIK, erp->rIK_len, hdr, 929 end - hdr - 32, hash) < 0) 930 goto fail; 931 if (os_memcmp(end - 32, hash, 32) == 0) { 932 wpa_printf(MSG_DEBUG, 933 "EAP: Authentication Tag match using HMAC-SHA256-256"); 934 hash_len = 32; 935 erp->cryptosuite = EAP_ERP_CS_HMAC_SHA256_256; 936 } 937 } 938 939 if (!hash_len && end[-17] == EAP_ERP_CS_HMAC_SHA256_128) { 940 if (hmac_sha256(erp->rIK, erp->rIK_len, hdr, 941 end - hdr - 16, hash) < 0) 942 goto fail; 943 if (os_memcmp(end - 16, hash, 16) == 0) { 944 wpa_printf(MSG_DEBUG, 945 "EAP: Authentication Tag match using HMAC-SHA256-128"); 946 hash_len = 16; 947 erp->cryptosuite = EAP_ERP_CS_HMAC_SHA256_128; 948 } 949 } 950 951 if (!hash_len) { 952 wpa_printf(MSG_DEBUG, 953 "EAP: No supported cryptosuite matched Authentication Tag"); 954 goto fail; 955 } 956 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 wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-Auth TVs/TLVs", 963 tlvs, end - tlvs); 964 if (erp_parse_tlvs(tlvs, end, &parse, 0) < 0) 965 goto fail; 966 967 wpa_printf(MSG_DEBUG, "EAP: ERP key %s SEQ updated to %u", 968 erp->keyname_nai, seq); 969 erp->recv_seq = seq; 970 resp_flags &= ~0x80; /* R=0 - success */ 971 972report_error: 973 erp_send_finish_reauth(sm, erp, ehdr->identifier, resp_flags, seq, nai); 974 return; 975 976fail: 977 sm->ignore = TRUE; 978} 979 980#endif /* CONFIG_ERP */ 981 982 983SM_STATE(EAP, INITIALIZE_PASSTHROUGH) 984{ 985 SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH); 986 987 wpabuf_free(sm->eap_if.aaaEapRespData); 988 sm->eap_if.aaaEapRespData = NULL; 989 sm->try_initiate_reauth = FALSE; 990} 991 992 993SM_STATE(EAP, IDLE2) 994{ 995 SM_ENTRY(EAP, IDLE2); 996 997 sm->eap_if.retransWhile = eap_sm_calculateTimeout( 998 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, 999 sm->methodTimeout); 1000} 1001 1002 1003SM_STATE(EAP, RETRANSMIT2) 1004{ 1005 SM_ENTRY(EAP, RETRANSMIT2); 1006 1007 sm->retransCount++; 1008 if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { 1009 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) 1010 sm->eap_if.eapReq = TRUE; 1011 } 1012} 1013 1014 1015SM_STATE(EAP, RECEIVED2) 1016{ 1017 SM_ENTRY(EAP, RECEIVED2); 1018 1019 /* parse rxResp, respId, respMethod */ 1020 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); 1021} 1022 1023 1024SM_STATE(EAP, DISCARD2) 1025{ 1026 SM_ENTRY(EAP, DISCARD2); 1027 sm->eap_if.eapResp = FALSE; 1028 sm->eap_if.eapNoReq = TRUE; 1029} 1030 1031 1032SM_STATE(EAP, SEND_REQUEST2) 1033{ 1034 SM_ENTRY(EAP, SEND_REQUEST2); 1035 1036 sm->retransCount = 0; 1037 if (sm->eap_if.eapReqData) { 1038 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) 1039 { 1040 sm->eap_if.eapResp = FALSE; 1041 sm->eap_if.eapReq = TRUE; 1042 } else { 1043 sm->eap_if.eapResp = FALSE; 1044 sm->eap_if.eapReq = FALSE; 1045 } 1046 } else { 1047 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData"); 1048 sm->eap_if.eapResp = FALSE; 1049 sm->eap_if.eapReq = FALSE; 1050 sm->eap_if.eapNoReq = TRUE; 1051 } 1052} 1053 1054 1055SM_STATE(EAP, AAA_REQUEST) 1056{ 1057 SM_ENTRY(EAP, AAA_REQUEST); 1058 1059 if (sm->eap_if.eapRespData == NULL) { 1060 wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData"); 1061 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 eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData); 1072} 1073 1074 1075SM_STATE(EAP, AAA_RESPONSE) 1076{ 1077 SM_ENTRY(EAP, AAA_RESPONSE); 1078 1079 eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); 1080 sm->currentId = eap_sm_getId(sm->eap_if.eapReqData); 1081 sm->methodTimeout = sm->eap_if.aaaMethodTimeout; 1082} 1083 1084 1085SM_STATE(EAP, AAA_IDLE) 1086{ 1087 SM_ENTRY(EAP, AAA_IDLE); 1088 1089 sm->eap_if.aaaFail = FALSE; 1090 sm->eap_if.aaaSuccess = FALSE; 1091 sm->eap_if.aaaEapReq = FALSE; 1092 sm->eap_if.aaaEapNoReq = FALSE; 1093 sm->eap_if.aaaEapResp = TRUE; 1094} 1095 1096 1097SM_STATE(EAP, TIMEOUT_FAILURE2) 1098{ 1099 SM_ENTRY(EAP, TIMEOUT_FAILURE2); 1100 1101 sm->eap_if.eapTimeout = TRUE; 1102} 1103 1104 1105SM_STATE(EAP, FAILURE2) 1106{ 1107 SM_ENTRY(EAP, FAILURE2); 1108 1109 eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); 1110 sm->eap_if.eapFail = TRUE; 1111} 1112 1113 1114SM_STATE(EAP, SUCCESS2) 1115{ 1116 SM_ENTRY(EAP, SUCCESS2); 1117 1118 eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); 1119 1120 sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable; 1121 if (sm->eap_if.aaaEapKeyAvailable) { 1122 EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData); 1123 } else { 1124 bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); 1125 sm->eap_if.eapKeyData = NULL; 1126 sm->eap_if.eapKeyDataLen = 0; 1127 } 1128 1129 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 sm->start_reauth = TRUE; 1137} 1138 1139 1140SM_STEP(EAP) 1141{ 1142 if (sm->eap_if.eapRestart && sm->eap_if.portEnabled) 1143 SM_ENTER_GLOBAL(EAP, INITIALIZE); 1144 else if (!sm->eap_if.portEnabled) 1145 SM_ENTER_GLOBAL(EAP, DISABLED); 1146 else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { 1147 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { 1148 wpa_printf(MSG_DEBUG, "EAP: more than %d " 1149 "authentication rounds - abort", 1150 EAP_MAX_AUTH_ROUNDS); 1151 sm->num_rounds++; 1152 SM_ENTER_GLOBAL(EAP, FAILURE); 1153 } 1154 } else switch (sm->EAP_state) { 1155 case EAP_INITIALIZE: 1156 if (sm->backend_auth) { 1157 if (!sm->rxResp) 1158 SM_ENTER(EAP, SELECT_ACTION); 1159 else if (sm->rxResp && 1160 (sm->respMethod == EAP_TYPE_NAK || 1161 (sm->respMethod == EAP_TYPE_EXPANDED && 1162 sm->respVendor == EAP_VENDOR_IETF && 1163 sm->respVendorMethod == EAP_TYPE_NAK))) 1164 SM_ENTER(EAP, NAK); 1165 else 1166 SM_ENTER(EAP, PICK_UP_METHOD); 1167 } else { 1168 SM_ENTER(EAP, SELECT_ACTION); 1169 } 1170 break; 1171 case EAP_PICK_UP_METHOD: 1172 if (sm->currentMethod == EAP_TYPE_NONE) { 1173 SM_ENTER(EAP, SELECT_ACTION); 1174 } else { 1175 SM_ENTER(EAP, METHOD_RESPONSE); 1176 } 1177 break; 1178 case EAP_DISABLED: 1179 if (sm->eap_if.portEnabled) 1180 SM_ENTER(EAP, INITIALIZE); 1181 break; 1182 case EAP_IDLE: 1183 if (sm->eap_if.retransWhile == 0) { 1184 if (sm->try_initiate_reauth) { 1185 sm->try_initiate_reauth = FALSE; 1186 SM_ENTER(EAP, SELECT_ACTION); 1187 } else { 1188 SM_ENTER(EAP, RETRANSMIT); 1189 } 1190 } else if (sm->eap_if.eapResp) 1191 SM_ENTER(EAP, RECEIVED); 1192 break; 1193 case EAP_RETRANSMIT: 1194 if (sm->retransCount > sm->MaxRetrans) 1195 SM_ENTER(EAP, TIMEOUT_FAILURE); 1196 else 1197 SM_ENTER(EAP, IDLE); 1198 break; 1199 case EAP_RECEIVED: 1200 if (sm->rxResp && (sm->respId == sm->currentId) && 1201 (sm->respMethod == EAP_TYPE_NAK || 1202 (sm->respMethod == EAP_TYPE_EXPANDED && 1203 sm->respVendor == EAP_VENDOR_IETF && 1204 sm->respVendorMethod == EAP_TYPE_NAK)) 1205 && (sm->methodState == METHOD_PROPOSED)) 1206 SM_ENTER(EAP, NAK); 1207 else if (sm->rxResp && (sm->respId == sm->currentId) && 1208 ((sm->respMethod == sm->currentMethod) || 1209 (sm->respMethod == EAP_TYPE_EXPANDED && 1210 sm->respVendor == EAP_VENDOR_IETF && 1211 sm->respVendorMethod == sm->currentMethod))) 1212 SM_ENTER(EAP, INTEGRITY_CHECK); 1213#ifdef CONFIG_ERP 1214 else if (sm->rxInitiate) 1215 SM_ENTER(EAP, INITIATE_RECEIVED); 1216#endif /* CONFIG_ERP */ 1217 else { 1218 wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: " 1219 "rxResp=%d respId=%d currentId=%d " 1220 "respMethod=%d currentMethod=%d", 1221 sm->rxResp, sm->respId, sm->currentId, 1222 sm->respMethod, sm->currentMethod); 1223 eap_log_msg(sm, "Discard received EAP message"); 1224 SM_ENTER(EAP, DISCARD); 1225 } 1226 break; 1227 case EAP_DISCARD: 1228 SM_ENTER(EAP, IDLE); 1229 break; 1230 case EAP_SEND_REQUEST: 1231 SM_ENTER(EAP, IDLE); 1232 break; 1233 case EAP_INTEGRITY_CHECK: 1234 if (sm->ignore) 1235 SM_ENTER(EAP, DISCARD); 1236 else 1237 SM_ENTER(EAP, METHOD_RESPONSE); 1238 break; 1239 case EAP_METHOD_REQUEST: 1240 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 SM_ENTER(EAP, FAILURE); 1247 break; 1248 } 1249 SM_ENTER(EAP, SEND_REQUEST); 1250 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 wpa_printf(MSG_DEBUG, 1257 "EAP: Method did not return a request"); 1258 SM_ENTER(EAP, FAILURE); 1259 break; 1260 } 1261 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 if (sm->methodState == METHOD_END) 1270 SM_ENTER(EAP, SELECT_ACTION); 1271 else if (sm->method_pending == METHOD_PENDING_WAIT) { 1272 wpa_printf(MSG_DEBUG, "EAP: Method has pending " 1273 "processing - wait before proceeding to " 1274 "METHOD_REQUEST state"); 1275 } else if (sm->method_pending == METHOD_PENDING_CONT) { 1276 wpa_printf(MSG_DEBUG, "EAP: Method has completed " 1277 "pending processing - reprocess pending " 1278 "EAP message"); 1279 sm->method_pending = METHOD_PENDING_NONE; 1280 SM_ENTER(EAP, METHOD_RESPONSE); 1281 } else 1282 SM_ENTER(EAP, METHOD_REQUEST); 1283 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 if (sm->method_pending == METHOD_PENDING_WAIT) { 1292 wpa_printf(MSG_DEBUG, "EAP: Method has pending " 1293 "processing - wait before proceeding to " 1294 "METHOD_REQUEST state"); 1295 if (sm->user_eap_method_index > 0) 1296 sm->user_eap_method_index--; 1297 } else if (sm->method_pending == METHOD_PENDING_CONT) { 1298 wpa_printf(MSG_DEBUG, "EAP: Method has completed " 1299 "pending processing - reprocess pending " 1300 "EAP message"); 1301 sm->method_pending = METHOD_PENDING_NONE; 1302 SM_ENTER(EAP, PROPOSE_METHOD); 1303 } else 1304 SM_ENTER(EAP, METHOD_REQUEST); 1305 break; 1306 case EAP_NAK: 1307 SM_ENTER(EAP, SELECT_ACTION); 1308 break; 1309 case EAP_SELECT_ACTION: 1310 if (sm->decision == DECISION_FAILURE) 1311 SM_ENTER(EAP, FAILURE); 1312 else if (sm->decision == DECISION_SUCCESS) 1313 SM_ENTER(EAP, SUCCESS); 1314 else if (sm->decision == DECISION_PASSTHROUGH) 1315 SM_ENTER(EAP, INITIALIZE_PASSTHROUGH); 1316 else if (sm->decision == DECISION_INITIATE_REAUTH_START) 1317 SM_ENTER(EAP, INITIATE_REAUTH_START); 1318#ifdef CONFIG_ERP 1319 else if (sm->eap_server && sm->erp && sm->rxInitiate) 1320 SM_ENTER(EAP, INITIATE_RECEIVED); 1321#endif /* CONFIG_ERP */ 1322 else 1323 SM_ENTER(EAP, PROPOSE_METHOD); 1324 break; 1325 case EAP_INITIATE_REAUTH_START: 1326 SM_ENTER(EAP, SEND_REQUEST); 1327 break; 1328 case EAP_INITIATE_RECEIVED: 1329 if (!sm->eap_server) 1330 SM_ENTER(EAP, SELECT_ACTION); 1331 break; 1332 case EAP_TIMEOUT_FAILURE: 1333 break; 1334 case EAP_FAILURE: 1335 break; 1336 case EAP_SUCCESS: 1337 break; 1338 1339 case EAP_INITIALIZE_PASSTHROUGH: 1340 if (sm->currentId == -1) 1341 SM_ENTER(EAP, AAA_IDLE); 1342 else 1343 SM_ENTER(EAP, AAA_REQUEST); 1344 break; 1345 case EAP_IDLE2: 1346 if (sm->eap_if.eapResp) 1347 SM_ENTER(EAP, RECEIVED2); 1348 else if (sm->eap_if.retransWhile == 0) 1349 SM_ENTER(EAP, RETRANSMIT2); 1350 break; 1351 case EAP_RETRANSMIT2: 1352 if (sm->retransCount > sm->MaxRetrans) 1353 SM_ENTER(EAP, TIMEOUT_FAILURE2); 1354 else 1355 SM_ENTER(EAP, IDLE2); 1356 break; 1357 case EAP_RECEIVED2: 1358 if (sm->rxResp && (sm->respId == sm->currentId)) 1359 SM_ENTER(EAP, AAA_REQUEST); 1360 else 1361 SM_ENTER(EAP, DISCARD2); 1362 break; 1363 case EAP_DISCARD2: 1364 SM_ENTER(EAP, IDLE2); 1365 break; 1366 case EAP_SEND_REQUEST2: 1367 SM_ENTER(EAP, IDLE2); 1368 break; 1369 case EAP_AAA_REQUEST: 1370 SM_ENTER(EAP, AAA_IDLE); 1371 break; 1372 case EAP_AAA_RESPONSE: 1373 SM_ENTER(EAP, SEND_REQUEST2); 1374 break; 1375 case EAP_AAA_IDLE: 1376 if (sm->eap_if.aaaFail) 1377 SM_ENTER(EAP, FAILURE2); 1378 else if (sm->eap_if.aaaSuccess) 1379 SM_ENTER(EAP, SUCCESS2); 1380 else if (sm->eap_if.aaaEapReq) 1381 SM_ENTER(EAP, AAA_RESPONSE); 1382 else if (sm->eap_if.aaaTimeout) 1383 SM_ENTER(EAP, TIMEOUT_FAILURE2); 1384 break; 1385 case EAP_TIMEOUT_FAILURE2: 1386 break; 1387 case EAP_FAILURE2: 1388 break; 1389 case EAP_SUCCESS2: 1390 break; 1391 } 1392} 1393 1394 1395static 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 if (sm->try_initiate_reauth) { 1402 wpa_printf(MSG_DEBUG, 1403 "EAP: retransmit timeout 1 second for EAP-Initiate-Re-auth-Start"); 1404 return 1; 1405 } 1406 1407 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 wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " 1414 "(from EAP method hint)", methodTimeout); 1415 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 rto = 3; 1437 for (i = 0; i < retransCount; i++) { 1438 rto *= 2; 1439 if (rto >= 20) { 1440 rto = 20; 1441 break; 1442 } 1443 } 1444 1445 wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " 1446 "(from dynamic back off; retransCount=%d)", 1447 rto, retransCount); 1448 1449 return rto; 1450} 1451 1452 1453static 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 sm->rxResp = FALSE; 1460 sm->rxInitiate = FALSE; 1461 sm->respId = -1; 1462 sm->respMethod = EAP_TYPE_NONE; 1463 sm->respVendor = EAP_VENDOR_IETF; 1464 sm->respVendorMethod = EAP_TYPE_NONE; 1465 1466 if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) { 1467 wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p " 1468 "len=%lu", resp, 1469 resp ? (unsigned long) wpabuf_len(resp) : 0); 1470 return; 1471 } 1472 1473 hdr = wpabuf_head(resp); 1474 plen = be_to_host16(hdr->length); 1475 if (plen > wpabuf_len(resp)) { 1476 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 return; 1481 } 1482 1483 sm->respId = hdr->identifier; 1484 1485 if (hdr->code == EAP_CODE_RESPONSE) 1486 sm->rxResp = TRUE; 1487 else if (hdr->code == EAP_CODE_INITIATE) 1488 sm->rxInitiate = TRUE; 1489 1490 if (plen > sizeof(*hdr)) { 1491 u8 *pos = (u8 *) (hdr + 1); 1492 sm->respMethod = *pos++; 1493 if (sm->respMethod == EAP_TYPE_EXPANDED) { 1494 if (plen < sizeof(*hdr) + 8) { 1495 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " 1496 "expanded EAP-Packet (plen=%lu)", 1497 (unsigned long) plen); 1498 return; 1499 } 1500 sm->respVendor = WPA_GET_BE24(pos); 1501 pos += 3; 1502 sm->respVendorMethod = WPA_GET_BE32(pos); 1503 } 1504 } 1505 1506 wpa_printf(MSG_DEBUG, 1507 "EAP: parseEapResp: rxResp=%d rxInitiate=%d respId=%d respMethod=%u respVendor=%u respVendorMethod=%u", 1508 sm->rxResp, sm->rxInitiate, sm->respId, sm->respMethod, 1509 sm->respVendor, sm->respVendorMethod); 1510} 1511 1512 1513static int eap_sm_getId(const struct wpabuf *data) 1514{ 1515 const struct eap_hdr *hdr; 1516 1517 if (data == NULL || wpabuf_len(data) < sizeof(*hdr)) 1518 return -1; 1519 1520 hdr = wpabuf_head(data); 1521 wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier); 1522 return hdr->identifier; 1523} 1524 1525 1526static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id) 1527{ 1528 struct wpabuf *msg; 1529 struct eap_hdr *resp; 1530 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); 1531 1532 msg = wpabuf_alloc(sizeof(*resp)); 1533 if (msg == NULL) 1534 return NULL; 1535 resp = wpabuf_put(msg, sizeof(*resp)); 1536 resp->code = EAP_CODE_SUCCESS; 1537 resp->identifier = id; 1538 resp->length = host_to_be16(sizeof(*resp)); 1539 1540 return msg; 1541} 1542 1543 1544static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id) 1545{ 1546 struct wpabuf *msg; 1547 struct eap_hdr *resp; 1548 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); 1549 1550 msg = wpabuf_alloc(sizeof(*resp)); 1551 if (msg == NULL) 1552 return NULL; 1553 resp = wpabuf_put(msg, sizeof(*resp)); 1554 resp->code = EAP_CODE_FAILURE; 1555 resp->identifier = id; 1556 resp->length = host_to_be16(sizeof(*resp)); 1557 1558 return msg; 1559} 1560 1561 1562static int eap_sm_nextId(struct eap_sm *sm, int id) 1563{ 1564 if (id < 0) { 1565 /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a 1566 * random number */ 1567 id = rand() & 0xff; 1568 if (id != sm->lastId) 1569 return id; 1570 } 1571 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 */ 1584void 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 if (sm->user == NULL) 1590 return; 1591 1592 wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " 1593 "index %d)", sm->user_eap_method_index); 1594 1595 wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", 1596 (u8 *) sm->user->methods, 1597 EAP_MAX_METHODS * sizeof(sm->user->methods[0])); 1598 wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer", 1599 nak_list, len); 1600 1601 i = sm->user_eap_method_index; 1602 while (i < EAP_MAX_METHODS && 1603 (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 1604 sm->user->methods[i].method != EAP_TYPE_NONE)) { 1605 if (sm->user->methods[i].vendor != EAP_VENDOR_IETF) 1606 goto not_found; 1607 for (j = 0; j < len; j++) { 1608 if (nak_list[j] == sm->user->methods[i].method) { 1609 break; 1610 } 1611 } 1612 1613 if (j < len) { 1614 /* found */ 1615 i++; 1616 continue; 1617 } 1618 1619 not_found: 1620 /* not found - remove from the list */ 1621 if (i + 1 < EAP_MAX_METHODS) { 1622 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 sm->user->methods[EAP_MAX_METHODS - 1].vendor = 1628 EAP_VENDOR_IETF; 1629 sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE; 1630 } 1631 1632 wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", 1633 (u8 *) sm->user->methods, EAP_MAX_METHODS * 1634 sizeof(sm->user->methods[0])); 1635} 1636 1637 1638static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, 1639 size_t len) 1640{ 1641 if (nak_list == NULL || sm == NULL || sm->user == NULL) 1642 return; 1643 1644 if (sm->user->phase2) { 1645 wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user" 1646 " info was selected - reject"); 1647 sm->decision = DECISION_FAILURE; 1648 return; 1649 } 1650 1651 eap_sm_process_nak(sm, nak_list, len); 1652} 1653 1654 1655static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) 1656{ 1657 EapType next; 1658 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 if (sm->identity == NULL || sm->currentId == -1) { 1668 *vendor = EAP_VENDOR_IETF; 1669 next = EAP_TYPE_IDENTITY; 1670 sm->update_user = TRUE; 1671 } else if (sm->user && idx < EAP_MAX_METHODS && 1672 (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || 1673 sm->user->methods[idx].method != EAP_TYPE_NONE)) { 1674 *vendor = sm->user->methods[idx].vendor; 1675 next = sm->user->methods[idx].method; 1676 sm->user_eap_method_index++; 1677 } else { 1678 *vendor = EAP_VENDOR_IETF; 1679 next = EAP_TYPE_NONE; 1680 } 1681 wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d", 1682 *vendor, next); 1683 return next; 1684} 1685 1686 1687static int eap_sm_Policy_getDecision(struct eap_sm *sm) 1688{ 1689 if (!sm->eap_server && sm->identity && !sm->start_reauth) { 1690 wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH"); 1691 return DECISION_PASSTHROUGH; 1692 } 1693 1694 if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY && 1695 sm->m->isSuccess(sm, sm->eap_method_priv)) { 1696 wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " 1697 "SUCCESS"); 1698 sm->update_user = TRUE; 1699 return DECISION_SUCCESS; 1700 } 1701 1702 if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) && 1703 !sm->m->isSuccess(sm, sm->eap_method_priv)) { 1704 wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " 1705 "FAILURE"); 1706 sm->update_user = TRUE; 1707 return DECISION_FAILURE; 1708 } 1709 1710 if ((sm->user == NULL || sm->update_user) && sm->identity && 1711 !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 int id_req = 0; 1719 if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY && 1720 sm->user->methods[0].vendor == EAP_VENDOR_IETF && 1721 sm->user->methods[0].method == EAP_TYPE_IDENTITY) 1722 id_req = 1; 1723 if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) { 1724 wpa_printf(MSG_DEBUG, "EAP: getDecision: user not " 1725 "found from database -> FAILURE"); 1726 return DECISION_FAILURE; 1727 } 1728 if (id_req && sm->user && 1729 sm->user->methods[0].vendor == EAP_VENDOR_IETF && 1730 sm->user->methods[0].method == EAP_TYPE_IDENTITY) { 1731 wpa_printf(MSG_DEBUG, "EAP: getDecision: stop " 1732 "identity request loop -> FAILURE"); 1733 sm->update_user = TRUE; 1734 return DECISION_FAILURE; 1735 } 1736 sm->update_user = FALSE; 1737 } 1738 sm->start_reauth = FALSE; 1739 1740 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 1741 (sm->user->methods[sm->user_eap_method_index].vendor != 1742 EAP_VENDOR_IETF || 1743 sm->user->methods[sm->user_eap_method_index].method != 1744 EAP_TYPE_NONE)) { 1745 wpa_printf(MSG_DEBUG, "EAP: getDecision: another method " 1746 "available -> CONTINUE"); 1747 return DECISION_CONTINUE; 1748 } 1749 1750 if (!sm->identity && eap_get_erp_send_reauth_start(sm) && 1751 !sm->initiate_reauth_start_sent) { 1752 wpa_printf(MSG_DEBUG, 1753 "EAP: getDecision: send EAP-Initiate/Re-auth-Start"); 1754 return DECISION_INITIATE_REAUTH_START; 1755 } 1756 1757 if (sm->identity == NULL || sm->currentId == -1) { 1758 wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known " 1759 "yet -> CONTINUE"); 1760 return DECISION_CONTINUE; 1761 } 1762 1763 wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> " 1764 "FAILURE"); 1765 return DECISION_FAILURE; 1766} 1767 1768 1769static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method) 1770{ 1771 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 */ 1784int eap_server_sm_step(struct eap_sm *sm) 1785{ 1786 int res = 0; 1787 do { 1788 sm->changed = FALSE; 1789 SM_STEP_RUN(EAP); 1790 if (sm->changed) 1791 res = 1; 1792 } while (sm->changed); 1793 return res; 1794} 1795 1796 1797static void eap_user_free(struct eap_user *user) 1798{ 1799 if (user == NULL) 1800 return; 1801 bin_clear_free(user->password, user->password_len); 1802 user->password = NULL; 1803 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 */ 1816struct 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 sm = os_zalloc(sizeof(*sm)); 1823 if (sm == NULL) 1824 return NULL; 1825 sm->eapol_ctx = eapol_ctx; 1826 sm->eapol_cb = eapol_cb; 1827 sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */ 1828 sm->ssl_ctx = conf->ssl_ctx; 1829 sm->msg_ctx = conf->msg_ctx; 1830 sm->eap_sim_db_priv = conf->eap_sim_db_priv; 1831 sm->backend_auth = conf->backend_auth; 1832 sm->eap_server = conf->eap_server; 1833 if (conf->pac_opaque_encr_key) { 1834 sm->pac_opaque_encr_key = os_malloc(16); 1835 if (sm->pac_opaque_encr_key) { 1836 os_memcpy(sm->pac_opaque_encr_key, 1837 conf->pac_opaque_encr_key, 16); 1838 } 1839 } 1840 if (conf->eap_fast_a_id) { 1841 sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); 1842 if (sm->eap_fast_a_id) { 1843 os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id, 1844 conf->eap_fast_a_id_len); 1845 sm->eap_fast_a_id_len = conf->eap_fast_a_id_len; 1846 } 1847 } 1848 if (conf->eap_fast_a_id_info) 1849 sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); 1850 sm->eap_fast_prov = conf->eap_fast_prov; 1851 sm->pac_key_lifetime = conf->pac_key_lifetime; 1852 sm->pac_key_refresh_time = conf->pac_key_refresh_time; 1853 sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; 1854 sm->tnc = conf->tnc; 1855 sm->wps = conf->wps; 1856 if (conf->assoc_wps_ie) 1857 sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie); 1858 if (conf->assoc_p2p_ie) 1859 sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie); 1860 if (conf->peer_addr) 1861 os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN); 1862 sm->fragment_size = conf->fragment_size; 1863 sm->pwd_group = conf->pwd_group; 1864 sm->pbc_in_m1 = conf->pbc_in_m1; 1865 sm->server_id = conf->server_id; 1866 sm->server_id_len = conf->server_id_len; 1867 sm->erp = conf->erp; 1868 sm->tls_session_lifetime = conf->tls_session_lifetime; 1869 1870#ifdef CONFIG_TESTING_OPTIONS 1871 sm->tls_test_flags = conf->tls_test_flags; 1872#endif /* CONFIG_TESTING_OPTIONS */ 1873 1874 wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); 1875 1876 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 */ 1887void eap_server_sm_deinit(struct eap_sm *sm) 1888{ 1889 if (sm == NULL) 1890 return; 1891 wpa_printf(MSG_DEBUG, "EAP: Server state machine removed"); 1892 if (sm->m && sm->eap_method_priv) 1893 sm->m->reset(sm, sm->eap_method_priv); 1894 wpabuf_free(sm->eap_if.eapReqData); 1895 bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); 1896 os_free(sm->eap_if.eapSessionId); 1897 wpabuf_free(sm->lastReqData); 1898 wpabuf_free(sm->eap_if.eapRespData); 1899 os_free(sm->identity); 1900 os_free(sm->pac_opaque_encr_key); 1901 os_free(sm->eap_fast_a_id); 1902 os_free(sm->eap_fast_a_id_info); 1903 wpabuf_free(sm->eap_if.aaaEapReqData); 1904 wpabuf_free(sm->eap_if.aaaEapRespData); 1905 bin_clear_free(sm->eap_if.aaaEapKeyData, sm->eap_if.aaaEapKeyDataLen); 1906 eap_user_free(sm->user); 1907 wpabuf_free(sm->assoc_wps_ie); 1908 wpabuf_free(sm->assoc_p2p_ie); 1909 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 */ 1920void eap_sm_notify_cached(struct eap_sm *sm) 1921{ 1922 if (sm == NULL) 1923 return; 1924 1925 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 */ 1935void eap_sm_pending_cb(struct eap_sm *sm) 1936{ 1937 if (sm == NULL) 1938 return; 1939 wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received"); 1940 if (sm->method_pending == METHOD_PENDING_WAIT) 1941 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 */ 1950int eap_sm_method_pending(struct eap_sm *sm) 1951{ 1952 if (sm == NULL) 1953 return 0; 1954 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 */ 1964const u8 * eap_get_identity(struct eap_sm *sm, size_t *len) 1965{ 1966 *len = sm->identity_len; 1967 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 */ 1976struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm) 1977{ 1978 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 */ 1990void eap_server_clear_identity(struct eap_sm *sm) 1991{ 1992 os_free(sm->identity); 1993 sm->identity = NULL; 1994} 1995 1996 1997#ifdef CONFIG_TESTING_OPTIONS 1998void 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 if (username) 2006 printf_encode(user, sizeof(user), username, username_len); 2007 else 2008 user[0] = '\0'; 2009 wpa_snprintf_hex_sep(hex_challenge, sizeof(hex_challenge), 2010 challenge, sizeof(challenge), ':'); 2011 wpa_snprintf_hex_sep(hex_response, sizeof(hex_response), response, 24, 2012 ':'); 2013 wpa_printf(MSG_DEBUG, "[%s/user=%s] asleap -C %s -R %s", 2014 source, user, hex_challenge, hex_response); 2015} 2016#endif /* CONFIG_TESTING_OPTIONS */ 2017