1 /* 2 * hostapd / EAP Full Authenticator state machine (RFC 4137) 3 * Copyright (c) 2004-2007, 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 "eap_i.h" 19 #include "state_machine.h" 20 #include "common/wpa_ctrl.h" 21 22 #define STATE_MACHINE_DATA struct eap_sm 23 #define STATE_MACHINE_DEBUG_PREFIX "EAP" 24 25 #define EAP_MAX_AUTH_ROUNDS 50 26 27 static void eap_user_free(struct eap_user *user); 28 29 30 /* EAP state machines are described in RFC 4137 */ 31 32 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, 33 int eapSRTT, int eapRTTVAR, 34 int methodTimeout); 35 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp); 36 static int eap_sm_getId(const struct wpabuf *data); 37 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id); 38 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id); 39 static int eap_sm_nextId(struct eap_sm *sm, int id); 40 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, 41 size_t len); 42 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor); 43 static int eap_sm_Policy_getDecision(struct eap_sm *sm); 44 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method); 45 46 47 static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src) 48 { 49 if (src == NULL) 50 return -1; 51 52 wpabuf_free(*dst); 53 *dst = wpabuf_dup(src); 54 return *dst ? 0 : -1; 55 } 56 57 58 static int eap_copy_data(u8 **dst, size_t *dst_len, 59 const u8 *src, size_t src_len) 60 { 61 if (src == NULL) 62 return -1; 63 64 os_free(*dst); 65 *dst = os_malloc(src_len); 66 if (*dst) { 67 os_memcpy(*dst, src, src_len); 68 *dst_len = src_len; 69 return 0; 70 } else { 71 *dst_len = 0; 72 return -1; 73 } 74 } 75 76 #define EAP_COPY(dst, src) \ 77 eap_copy_data((dst), (dst ## Len), (src), (src ## Len)) 78 79 80 /** 81 * eap_user_get - Fetch user information from the database 82 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 83 * @identity: Identity (User-Name) of the user 84 * @identity_len: Length of identity in bytes 85 * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user 86 * Returns: 0 on success, or -1 on failure 87 * 88 * This function is used to fetch user information for EAP. The user will be 89 * selected based on the specified identity. sm->user and 90 * sm->user_eap_method_index are updated for the new user when a matching user 91 * is found. sm->user can be used to get user information (e.g., password). 92 */ 93 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, 94 int phase2) 95 { 96 struct eap_user *user; 97 98 if (sm == NULL || sm->eapol_cb == NULL || 99 sm->eapol_cb->get_eap_user == NULL) 100 return -1; 101 102 eap_user_free(sm->user); 103 sm->user = NULL; 104 105 user = os_zalloc(sizeof(*user)); 106 if (user == NULL) 107 return -1; 108 109 if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity, 110 identity_len, phase2, user) != 0) { 111 eap_user_free(user); 112 return -1; 113 } 114 115 sm->user = user; 116 sm->user_eap_method_index = 0; 117 118 return 0; 119 } 120 121 122 SM_STATE(EAP, DISABLED) 123 { 124 SM_ENTRY(EAP, DISABLED); 125 sm->num_rounds = 0; 126 } 127 128 129 SM_STATE(EAP, INITIALIZE) 130 { 131 SM_ENTRY(EAP, INITIALIZE); 132 133 if (sm->eap_if.eapRestart && !sm->eap_server && sm->identity) { 134 /* 135 * Need to allow internal Identity method to be used instead 136 * of passthrough at the beginning of reauthentication. 137 */ 138 eap_server_clear_identity(sm); 139 } 140 141 sm->currentId = -1; 142 sm->eap_if.eapSuccess = FALSE; 143 sm->eap_if.eapFail = FALSE; 144 sm->eap_if.eapTimeout = FALSE; 145 os_free(sm->eap_if.eapKeyData); 146 sm->eap_if.eapKeyData = NULL; 147 sm->eap_if.eapKeyDataLen = 0; 148 sm->eap_if.eapKeyAvailable = FALSE; 149 sm->eap_if.eapRestart = FALSE; 150 151 /* 152 * This is not defined in RFC 4137, but method state needs to be 153 * reseted here so that it does not remain in success state when 154 * re-authentication starts. 155 */ 156 if (sm->m && sm->eap_method_priv) { 157 sm->m->reset(sm, sm->eap_method_priv); 158 sm->eap_method_priv = NULL; 159 } 160 sm->m = NULL; 161 sm->user_eap_method_index = 0; 162 163 if (sm->backend_auth) { 164 sm->currentMethod = EAP_TYPE_NONE; 165 /* parse rxResp, respId, respMethod */ 166 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); 167 if (sm->rxResp) { 168 sm->currentId = sm->respId; 169 } 170 } 171 sm->num_rounds = 0; 172 sm->method_pending = METHOD_PENDING_NONE; 173 174 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED 175 MACSTR, MAC2STR(sm->peer_addr)); 176 } 177 178 179 SM_STATE(EAP, PICK_UP_METHOD) 180 { 181 SM_ENTRY(EAP, PICK_UP_METHOD); 182 183 if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) { 184 sm->currentMethod = sm->respMethod; 185 if (sm->m && sm->eap_method_priv) { 186 sm->m->reset(sm, sm->eap_method_priv); 187 sm->eap_method_priv = NULL; 188 } 189 sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF, 190 sm->currentMethod); 191 if (sm->m && sm->m->initPickUp) { 192 sm->eap_method_priv = sm->m->initPickUp(sm); 193 if (sm->eap_method_priv == NULL) { 194 wpa_printf(MSG_DEBUG, "EAP: Failed to " 195 "initialize EAP method %d", 196 sm->currentMethod); 197 sm->m = NULL; 198 sm->currentMethod = EAP_TYPE_NONE; 199 } 200 } else { 201 sm->m = NULL; 202 sm->currentMethod = EAP_TYPE_NONE; 203 } 204 } 205 206 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD 207 "method=%u", sm->currentMethod); 208 } 209 210 211 SM_STATE(EAP, IDLE) 212 { 213 SM_ENTRY(EAP, IDLE); 214 215 sm->eap_if.retransWhile = eap_sm_calculateTimeout( 216 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, 217 sm->methodTimeout); 218 } 219 220 221 SM_STATE(EAP, RETRANSMIT) 222 { 223 SM_ENTRY(EAP, RETRANSMIT); 224 225 sm->retransCount++; 226 if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { 227 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) 228 sm->eap_if.eapReq = TRUE; 229 } 230 } 231 232 233 SM_STATE(EAP, RECEIVED) 234 { 235 SM_ENTRY(EAP, RECEIVED); 236 237 /* parse rxResp, respId, respMethod */ 238 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); 239 sm->num_rounds++; 240 } 241 242 243 SM_STATE(EAP, DISCARD) 244 { 245 SM_ENTRY(EAP, DISCARD); 246 sm->eap_if.eapResp = FALSE; 247 sm->eap_if.eapNoReq = TRUE; 248 } 249 250 251 SM_STATE(EAP, SEND_REQUEST) 252 { 253 SM_ENTRY(EAP, SEND_REQUEST); 254 255 sm->retransCount = 0; 256 if (sm->eap_if.eapReqData) { 257 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) 258 { 259 sm->eap_if.eapResp = FALSE; 260 sm->eap_if.eapReq = TRUE; 261 } else { 262 sm->eap_if.eapResp = FALSE; 263 sm->eap_if.eapReq = FALSE; 264 } 265 } else { 266 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); 267 sm->eap_if.eapResp = FALSE; 268 sm->eap_if.eapReq = FALSE; 269 sm->eap_if.eapNoReq = TRUE; 270 } 271 } 272 273 274 SM_STATE(EAP, INTEGRITY_CHECK) 275 { 276 SM_ENTRY(EAP, INTEGRITY_CHECK); 277 278 if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) { 279 sm->ignore = TRUE; 280 return; 281 } 282 283 if (sm->m->check) { 284 sm->ignore = sm->m->check(sm, sm->eap_method_priv, 285 sm->eap_if.eapRespData); 286 } 287 } 288 289 290 SM_STATE(EAP, METHOD_REQUEST) 291 { 292 SM_ENTRY(EAP, METHOD_REQUEST); 293 294 if (sm->m == NULL) { 295 wpa_printf(MSG_DEBUG, "EAP: method not initialized"); 296 return; 297 } 298 299 sm->currentId = eap_sm_nextId(sm, sm->currentId); 300 wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d", 301 sm->currentId); 302 sm->lastId = sm->currentId; 303 wpabuf_free(sm->eap_if.eapReqData); 304 sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv, 305 sm->currentId); 306 if (sm->m->getTimeout) 307 sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv); 308 else 309 sm->methodTimeout = 0; 310 } 311 312 313 SM_STATE(EAP, METHOD_RESPONSE) 314 { 315 SM_ENTRY(EAP, METHOD_RESPONSE); 316 317 if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) 318 return; 319 320 sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData); 321 if (sm->m->isDone(sm, sm->eap_method_priv)) { 322 eap_sm_Policy_update(sm, NULL, 0); 323 os_free(sm->eap_if.eapKeyData); 324 if (sm->m->getKey) { 325 sm->eap_if.eapKeyData = sm->m->getKey( 326 sm, sm->eap_method_priv, 327 &sm->eap_if.eapKeyDataLen); 328 } else { 329 sm->eap_if.eapKeyData = NULL; 330 sm->eap_if.eapKeyDataLen = 0; 331 } 332 sm->methodState = METHOD_END; 333 } else { 334 sm->methodState = METHOD_CONTINUE; 335 } 336 } 337 338 339 SM_STATE(EAP, PROPOSE_METHOD) 340 { 341 int vendor; 342 EapType type; 343 344 SM_ENTRY(EAP, PROPOSE_METHOD); 345 346 try_another_method: 347 type = eap_sm_Policy_getNextMethod(sm, &vendor); 348 if (vendor == EAP_VENDOR_IETF) 349 sm->currentMethod = type; 350 else 351 sm->currentMethod = EAP_TYPE_EXPANDED; 352 if (sm->m && sm->eap_method_priv) { 353 sm->m->reset(sm, sm->eap_method_priv); 354 sm->eap_method_priv = NULL; 355 } 356 sm->m = eap_server_get_eap_method(vendor, type); 357 if (sm->m) { 358 sm->eap_method_priv = sm->m->init(sm); 359 if (sm->eap_method_priv == NULL) { 360 wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP " 361 "method %d", sm->currentMethod); 362 sm->m = NULL; 363 sm->currentMethod = EAP_TYPE_NONE; 364 goto try_another_method; 365 } 366 } 367 if (sm->m == NULL) { 368 wpa_printf(MSG_DEBUG, "EAP: Could not find suitable EAP method"); 369 sm->decision = DECISION_FAILURE; 370 return; 371 } 372 if (sm->currentMethod == EAP_TYPE_IDENTITY || 373 sm->currentMethod == EAP_TYPE_NOTIFICATION) 374 sm->methodState = METHOD_CONTINUE; 375 else 376 sm->methodState = METHOD_PROPOSED; 377 378 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD 379 "vendor=%u method=%u", vendor, sm->currentMethod); 380 } 381 382 383 SM_STATE(EAP, NAK) 384 { 385 const struct eap_hdr *nak; 386 size_t len = 0; 387 const u8 *pos; 388 const u8 *nak_list = NULL; 389 390 SM_ENTRY(EAP, NAK); 391 392 if (sm->eap_method_priv) { 393 sm->m->reset(sm, sm->eap_method_priv); 394 sm->eap_method_priv = NULL; 395 } 396 sm->m = NULL; 397 398 if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) 399 return; 400 401 nak = wpabuf_head(sm->eap_if.eapRespData); 402 if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) { 403 len = be_to_host16(nak->length); 404 if (len > wpabuf_len(sm->eap_if.eapRespData)) 405 len = wpabuf_len(sm->eap_if.eapRespData); 406 pos = (const u8 *) (nak + 1); 407 len -= sizeof(*nak); 408 if (*pos == EAP_TYPE_NAK) { 409 pos++; 410 len--; 411 nak_list = pos; 412 } 413 } 414 eap_sm_Policy_update(sm, nak_list, len); 415 } 416 417 418 SM_STATE(EAP, SELECT_ACTION) 419 { 420 SM_ENTRY(EAP, SELECT_ACTION); 421 422 sm->decision = eap_sm_Policy_getDecision(sm); 423 } 424 425 426 SM_STATE(EAP, TIMEOUT_FAILURE) 427 { 428 SM_ENTRY(EAP, TIMEOUT_FAILURE); 429 430 sm->eap_if.eapTimeout = TRUE; 431 } 432 433 434 SM_STATE(EAP, FAILURE) 435 { 436 SM_ENTRY(EAP, FAILURE); 437 438 wpabuf_free(sm->eap_if.eapReqData); 439 sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId); 440 wpabuf_free(sm->lastReqData); 441 sm->lastReqData = NULL; 442 sm->eap_if.eapFail = TRUE; 443 444 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE 445 MACSTR, MAC2STR(sm->peer_addr)); 446 } 447 448 449 SM_STATE(EAP, SUCCESS) 450 { 451 SM_ENTRY(EAP, SUCCESS); 452 453 wpabuf_free(sm->eap_if.eapReqData); 454 sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId); 455 wpabuf_free(sm->lastReqData); 456 sm->lastReqData = NULL; 457 if (sm->eap_if.eapKeyData) 458 sm->eap_if.eapKeyAvailable = TRUE; 459 sm->eap_if.eapSuccess = TRUE; 460 461 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS 462 MACSTR, MAC2STR(sm->peer_addr)); 463 } 464 465 466 SM_STATE(EAP, INITIALIZE_PASSTHROUGH) 467 { 468 SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH); 469 470 wpabuf_free(sm->eap_if.aaaEapRespData); 471 sm->eap_if.aaaEapRespData = NULL; 472 } 473 474 475 SM_STATE(EAP, IDLE2) 476 { 477 SM_ENTRY(EAP, IDLE2); 478 479 sm->eap_if.retransWhile = eap_sm_calculateTimeout( 480 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, 481 sm->methodTimeout); 482 } 483 484 485 SM_STATE(EAP, RETRANSMIT2) 486 { 487 SM_ENTRY(EAP, RETRANSMIT2); 488 489 sm->retransCount++; 490 if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { 491 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) 492 sm->eap_if.eapReq = TRUE; 493 } 494 } 495 496 497 SM_STATE(EAP, RECEIVED2) 498 { 499 SM_ENTRY(EAP, RECEIVED2); 500 501 /* parse rxResp, respId, respMethod */ 502 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); 503 } 504 505 506 SM_STATE(EAP, DISCARD2) 507 { 508 SM_ENTRY(EAP, DISCARD2); 509 sm->eap_if.eapResp = FALSE; 510 sm->eap_if.eapNoReq = TRUE; 511 } 512 513 514 SM_STATE(EAP, SEND_REQUEST2) 515 { 516 SM_ENTRY(EAP, SEND_REQUEST2); 517 518 sm->retransCount = 0; 519 if (sm->eap_if.eapReqData) { 520 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) 521 { 522 sm->eap_if.eapResp = FALSE; 523 sm->eap_if.eapReq = TRUE; 524 } else { 525 sm->eap_if.eapResp = FALSE; 526 sm->eap_if.eapReq = FALSE; 527 } 528 } else { 529 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData"); 530 sm->eap_if.eapResp = FALSE; 531 sm->eap_if.eapReq = FALSE; 532 sm->eap_if.eapNoReq = TRUE; 533 } 534 } 535 536 537 SM_STATE(EAP, AAA_REQUEST) 538 { 539 SM_ENTRY(EAP, AAA_REQUEST); 540 541 if (sm->eap_if.eapRespData == NULL) { 542 wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData"); 543 return; 544 } 545 546 /* 547 * if (respMethod == IDENTITY) 548 * aaaIdentity = eapRespData 549 * This is already taken care of by the EAP-Identity method which 550 * stores the identity into sm->identity. 551 */ 552 553 eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData); 554 } 555 556 557 SM_STATE(EAP, AAA_RESPONSE) 558 { 559 SM_ENTRY(EAP, AAA_RESPONSE); 560 561 eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); 562 sm->currentId = eap_sm_getId(sm->eap_if.eapReqData); 563 sm->methodTimeout = sm->eap_if.aaaMethodTimeout; 564 } 565 566 567 SM_STATE(EAP, AAA_IDLE) 568 { 569 SM_ENTRY(EAP, AAA_IDLE); 570 571 sm->eap_if.aaaFail = FALSE; 572 sm->eap_if.aaaSuccess = FALSE; 573 sm->eap_if.aaaEapReq = FALSE; 574 sm->eap_if.aaaEapNoReq = FALSE; 575 sm->eap_if.aaaEapResp = TRUE; 576 } 577 578 579 SM_STATE(EAP, TIMEOUT_FAILURE2) 580 { 581 SM_ENTRY(EAP, TIMEOUT_FAILURE2); 582 583 sm->eap_if.eapTimeout = TRUE; 584 } 585 586 587 SM_STATE(EAP, FAILURE2) 588 { 589 SM_ENTRY(EAP, FAILURE2); 590 591 eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); 592 sm->eap_if.eapFail = TRUE; 593 } 594 595 596 SM_STATE(EAP, SUCCESS2) 597 { 598 SM_ENTRY(EAP, SUCCESS2); 599 600 eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); 601 602 sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable; 603 if (sm->eap_if.aaaEapKeyAvailable) { 604 EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData); 605 } else { 606 os_free(sm->eap_if.eapKeyData); 607 sm->eap_if.eapKeyData = NULL; 608 sm->eap_if.eapKeyDataLen = 0; 609 } 610 611 sm->eap_if.eapSuccess = TRUE; 612 613 /* 614 * Start reauthentication with identity request even though we know the 615 * previously used identity. This is needed to get reauthentication 616 * started properly. 617 */ 618 sm->start_reauth = TRUE; 619 } 620 621 622 SM_STEP(EAP) 623 { 624 if (sm->eap_if.eapRestart && sm->eap_if.portEnabled) 625 SM_ENTER_GLOBAL(EAP, INITIALIZE); 626 else if (!sm->eap_if.portEnabled) 627 SM_ENTER_GLOBAL(EAP, DISABLED); 628 else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { 629 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { 630 wpa_printf(MSG_DEBUG, "EAP: more than %d " 631 "authentication rounds - abort", 632 EAP_MAX_AUTH_ROUNDS); 633 sm->num_rounds++; 634 SM_ENTER_GLOBAL(EAP, FAILURE); 635 } 636 } else switch (sm->EAP_state) { 637 case EAP_INITIALIZE: 638 if (sm->backend_auth) { 639 if (!sm->rxResp) 640 SM_ENTER(EAP, SELECT_ACTION); 641 else if (sm->rxResp && 642 (sm->respMethod == EAP_TYPE_NAK || 643 (sm->respMethod == EAP_TYPE_EXPANDED && 644 sm->respVendor == EAP_VENDOR_IETF && 645 sm->respVendorMethod == EAP_TYPE_NAK))) 646 SM_ENTER(EAP, NAK); 647 else 648 SM_ENTER(EAP, PICK_UP_METHOD); 649 } else { 650 SM_ENTER(EAP, SELECT_ACTION); 651 } 652 break; 653 case EAP_PICK_UP_METHOD: 654 if (sm->currentMethod == EAP_TYPE_NONE) { 655 SM_ENTER(EAP, SELECT_ACTION); 656 } else { 657 SM_ENTER(EAP, METHOD_RESPONSE); 658 } 659 break; 660 case EAP_DISABLED: 661 if (sm->eap_if.portEnabled) 662 SM_ENTER(EAP, INITIALIZE); 663 break; 664 case EAP_IDLE: 665 if (sm->eap_if.retransWhile == 0) 666 SM_ENTER(EAP, RETRANSMIT); 667 else if (sm->eap_if.eapResp) 668 SM_ENTER(EAP, RECEIVED); 669 break; 670 case EAP_RETRANSMIT: 671 if (sm->retransCount > sm->MaxRetrans) 672 SM_ENTER(EAP, TIMEOUT_FAILURE); 673 else 674 SM_ENTER(EAP, IDLE); 675 break; 676 case EAP_RECEIVED: 677 if (sm->rxResp && (sm->respId == sm->currentId) && 678 (sm->respMethod == EAP_TYPE_NAK || 679 (sm->respMethod == EAP_TYPE_EXPANDED && 680 sm->respVendor == EAP_VENDOR_IETF && 681 sm->respVendorMethod == EAP_TYPE_NAK)) 682 && (sm->methodState == METHOD_PROPOSED)) 683 SM_ENTER(EAP, NAK); 684 else if (sm->rxResp && (sm->respId == sm->currentId) && 685 ((sm->respMethod == sm->currentMethod) || 686 (sm->respMethod == EAP_TYPE_EXPANDED && 687 sm->respVendor == EAP_VENDOR_IETF && 688 sm->respVendorMethod == sm->currentMethod))) 689 SM_ENTER(EAP, INTEGRITY_CHECK); 690 else { 691 wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: " 692 "rxResp=%d respId=%d currentId=%d " 693 "respMethod=%d currentMethod=%d", 694 sm->rxResp, sm->respId, sm->currentId, 695 sm->respMethod, sm->currentMethod); 696 SM_ENTER(EAP, DISCARD); 697 } 698 break; 699 case EAP_DISCARD: 700 SM_ENTER(EAP, IDLE); 701 break; 702 case EAP_SEND_REQUEST: 703 SM_ENTER(EAP, IDLE); 704 break; 705 case EAP_INTEGRITY_CHECK: 706 if (sm->ignore) 707 SM_ENTER(EAP, DISCARD); 708 else 709 SM_ENTER(EAP, METHOD_RESPONSE); 710 break; 711 case EAP_METHOD_REQUEST: 712 if (sm->m == NULL) { 713 /* 714 * This transition is not mentioned in RFC 4137, but it 715 * is needed to handle cleanly a case where EAP method 716 * initialization fails. 717 */ 718 SM_ENTER(EAP, FAILURE); 719 break; 720 } 721 SM_ENTER(EAP, SEND_REQUEST); 722 break; 723 case EAP_METHOD_RESPONSE: 724 /* 725 * Note: Mechanism to allow EAP methods to wait while going 726 * through pending processing is an extension to RFC 4137 727 * which only defines the transits to SELECT_ACTION and 728 * METHOD_REQUEST from this METHOD_RESPONSE state. 729 */ 730 if (sm->methodState == METHOD_END) 731 SM_ENTER(EAP, SELECT_ACTION); 732 else if (sm->method_pending == METHOD_PENDING_WAIT) { 733 wpa_printf(MSG_DEBUG, "EAP: Method has pending " 734 "processing - wait before proceeding to " 735 "METHOD_REQUEST state"); 736 } else if (sm->method_pending == METHOD_PENDING_CONT) { 737 wpa_printf(MSG_DEBUG, "EAP: Method has completed " 738 "pending processing - reprocess pending " 739 "EAP message"); 740 sm->method_pending = METHOD_PENDING_NONE; 741 SM_ENTER(EAP, METHOD_RESPONSE); 742 } else 743 SM_ENTER(EAP, METHOD_REQUEST); 744 break; 745 case EAP_PROPOSE_METHOD: 746 /* 747 * Note: Mechanism to allow EAP methods to wait while going 748 * through pending processing is an extension to RFC 4137 749 * which only defines the transit to METHOD_REQUEST from this 750 * PROPOSE_METHOD state. 751 */ 752 if (sm->method_pending == METHOD_PENDING_WAIT) { 753 wpa_printf(MSG_DEBUG, "EAP: Method has pending " 754 "processing - wait before proceeding to " 755 "METHOD_REQUEST state"); 756 if (sm->user_eap_method_index > 0) 757 sm->user_eap_method_index--; 758 } else if (sm->method_pending == METHOD_PENDING_CONT) { 759 wpa_printf(MSG_DEBUG, "EAP: Method has completed " 760 "pending processing - reprocess pending " 761 "EAP message"); 762 sm->method_pending = METHOD_PENDING_NONE; 763 SM_ENTER(EAP, PROPOSE_METHOD); 764 } else 765 SM_ENTER(EAP, METHOD_REQUEST); 766 break; 767 case EAP_NAK: 768 SM_ENTER(EAP, SELECT_ACTION); 769 break; 770 case EAP_SELECT_ACTION: 771 if (sm->decision == DECISION_FAILURE) 772 SM_ENTER(EAP, FAILURE); 773 else if (sm->decision == DECISION_SUCCESS) 774 SM_ENTER(EAP, SUCCESS); 775 else if (sm->decision == DECISION_PASSTHROUGH) 776 SM_ENTER(EAP, INITIALIZE_PASSTHROUGH); 777 else 778 SM_ENTER(EAP, PROPOSE_METHOD); 779 break; 780 case EAP_TIMEOUT_FAILURE: 781 break; 782 case EAP_FAILURE: 783 break; 784 case EAP_SUCCESS: 785 break; 786 787 case EAP_INITIALIZE_PASSTHROUGH: 788 if (sm->currentId == -1) 789 SM_ENTER(EAP, AAA_IDLE); 790 else 791 SM_ENTER(EAP, AAA_REQUEST); 792 break; 793 case EAP_IDLE2: 794 if (sm->eap_if.eapResp) 795 SM_ENTER(EAP, RECEIVED2); 796 else if (sm->eap_if.retransWhile == 0) 797 SM_ENTER(EAP, RETRANSMIT2); 798 break; 799 case EAP_RETRANSMIT2: 800 if (sm->retransCount > sm->MaxRetrans) 801 SM_ENTER(EAP, TIMEOUT_FAILURE2); 802 else 803 SM_ENTER(EAP, IDLE2); 804 break; 805 case EAP_RECEIVED2: 806 if (sm->rxResp && (sm->respId == sm->currentId)) 807 SM_ENTER(EAP, AAA_REQUEST); 808 else 809 SM_ENTER(EAP, DISCARD2); 810 break; 811 case EAP_DISCARD2: 812 SM_ENTER(EAP, IDLE2); 813 break; 814 case EAP_SEND_REQUEST2: 815 SM_ENTER(EAP, IDLE2); 816 break; 817 case EAP_AAA_REQUEST: 818 SM_ENTER(EAP, AAA_IDLE); 819 break; 820 case EAP_AAA_RESPONSE: 821 SM_ENTER(EAP, SEND_REQUEST2); 822 break; 823 case EAP_AAA_IDLE: 824 if (sm->eap_if.aaaFail) 825 SM_ENTER(EAP, FAILURE2); 826 else if (sm->eap_if.aaaSuccess) 827 SM_ENTER(EAP, SUCCESS2); 828 else if (sm->eap_if.aaaEapReq) 829 SM_ENTER(EAP, AAA_RESPONSE); 830 else if (sm->eap_if.aaaTimeout) 831 SM_ENTER(EAP, TIMEOUT_FAILURE2); 832 break; 833 case EAP_TIMEOUT_FAILURE2: 834 break; 835 case EAP_FAILURE2: 836 break; 837 case EAP_SUCCESS2: 838 break; 839 } 840 } 841 842 843 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, 844 int eapSRTT, int eapRTTVAR, 845 int methodTimeout) 846 { 847 int rto, i; 848 849 if (methodTimeout) { 850 /* 851 * EAP method (either internal or through AAA server, provided 852 * timeout hint. Use that as-is as a timeout for retransmitting 853 * the EAP request if no response is received. 854 */ 855 wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " 856 "(from EAP method hint)", methodTimeout); 857 return methodTimeout; 858 } 859 860 /* 861 * RFC 3748 recommends algorithms described in RFC 2988 for estimation 862 * of the retransmission timeout. This should be implemented once 863 * round-trip time measurements are available. For nowm a simple 864 * backoff mechanism is used instead if there are no EAP method 865 * specific hints. 866 * 867 * SRTT = smoothed round-trip time 868 * RTTVAR = round-trip time variation 869 * RTO = retransmission timeout 870 */ 871 872 /* 873 * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for 874 * initial retransmission and then double the RTO to provide back off 875 * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3 876 * modified RTOmax. 877 */ 878 rto = 3; 879 for (i = 0; i < retransCount; i++) { 880 rto *= 2; 881 if (rto >= 20) { 882 rto = 20; 883 break; 884 } 885 } 886 887 wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " 888 "(from dynamic back off; retransCount=%d)", 889 rto, retransCount); 890 891 return rto; 892 } 893 894 895 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) 896 { 897 const struct eap_hdr *hdr; 898 size_t plen; 899 900 /* parse rxResp, respId, respMethod */ 901 sm->rxResp = FALSE; 902 sm->respId = -1; 903 sm->respMethod = EAP_TYPE_NONE; 904 sm->respVendor = EAP_VENDOR_IETF; 905 sm->respVendorMethod = EAP_TYPE_NONE; 906 907 if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) { 908 wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p " 909 "len=%lu", resp, 910 resp ? (unsigned long) wpabuf_len(resp) : 0); 911 return; 912 } 913 914 hdr = wpabuf_head(resp); 915 plen = be_to_host16(hdr->length); 916 if (plen > wpabuf_len(resp)) { 917 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " 918 "(len=%lu plen=%lu)", 919 (unsigned long) wpabuf_len(resp), 920 (unsigned long) plen); 921 return; 922 } 923 924 sm->respId = hdr->identifier; 925 926 if (hdr->code == EAP_CODE_RESPONSE) 927 sm->rxResp = TRUE; 928 929 if (plen > sizeof(*hdr)) { 930 u8 *pos = (u8 *) (hdr + 1); 931 sm->respMethod = *pos++; 932 if (sm->respMethod == EAP_TYPE_EXPANDED) { 933 if (plen < sizeof(*hdr) + 8) { 934 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " 935 "expanded EAP-Packet (plen=%lu)", 936 (unsigned long) plen); 937 return; 938 } 939 sm->respVendor = WPA_GET_BE24(pos); 940 pos += 3; 941 sm->respVendorMethod = WPA_GET_BE32(pos); 942 } 943 } 944 945 wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d " 946 "respMethod=%u respVendor=%u respVendorMethod=%u", 947 sm->rxResp, sm->respId, sm->respMethod, sm->respVendor, 948 sm->respVendorMethod); 949 } 950 951 952 static int eap_sm_getId(const struct wpabuf *data) 953 { 954 const struct eap_hdr *hdr; 955 956 if (data == NULL || wpabuf_len(data) < sizeof(*hdr)) 957 return -1; 958 959 hdr = wpabuf_head(data); 960 wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier); 961 return hdr->identifier; 962 } 963 964 965 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id) 966 { 967 struct wpabuf *msg; 968 struct eap_hdr *resp; 969 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); 970 971 msg = wpabuf_alloc(sizeof(*resp)); 972 if (msg == NULL) 973 return NULL; 974 resp = wpabuf_put(msg, sizeof(*resp)); 975 resp->code = EAP_CODE_SUCCESS; 976 resp->identifier = id; 977 resp->length = host_to_be16(sizeof(*resp)); 978 979 return msg; 980 } 981 982 983 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id) 984 { 985 struct wpabuf *msg; 986 struct eap_hdr *resp; 987 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); 988 989 msg = wpabuf_alloc(sizeof(*resp)); 990 if (msg == NULL) 991 return NULL; 992 resp = wpabuf_put(msg, sizeof(*resp)); 993 resp->code = EAP_CODE_FAILURE; 994 resp->identifier = id; 995 resp->length = host_to_be16(sizeof(*resp)); 996 997 return msg; 998 } 999 1000 1001 static int eap_sm_nextId(struct eap_sm *sm, int id) 1002 { 1003 if (id < 0) { 1004 /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a 1005 * random number */ 1006 id = rand() & 0xff; 1007 if (id != sm->lastId) 1008 return id; 1009 } 1010 return (id + 1) & 0xff; 1011 } 1012 1013 1014 /** 1015 * eap_sm_process_nak - Process EAP-Response/Nak 1016 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1017 * @nak_list: Nak list (allowed methods) from the supplicant 1018 * @len: Length of nak_list in bytes 1019 * 1020 * This function is called when EAP-Response/Nak is received from the 1021 * supplicant. This can happen for both phase 1 and phase 2 authentications. 1022 */ 1023 void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len) 1024 { 1025 int i; 1026 size_t j; 1027 1028 if (sm->user == NULL) 1029 return; 1030 1031 wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " 1032 "index %d)", sm->user_eap_method_index); 1033 1034 wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", 1035 (u8 *) sm->user->methods, 1036 EAP_MAX_METHODS * sizeof(sm->user->methods[0])); 1037 wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer", 1038 nak_list, len); 1039 1040 i = sm->user_eap_method_index; 1041 while (i < EAP_MAX_METHODS && 1042 (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 1043 sm->user->methods[i].method != EAP_TYPE_NONE)) { 1044 if (sm->user->methods[i].vendor != EAP_VENDOR_IETF) 1045 goto not_found; 1046 for (j = 0; j < len; j++) { 1047 if (nak_list[j] == sm->user->methods[i].method) { 1048 break; 1049 } 1050 } 1051 1052 if (j < len) { 1053 /* found */ 1054 i++; 1055 continue; 1056 } 1057 1058 not_found: 1059 /* not found - remove from the list */ 1060 if (i + 1 < EAP_MAX_METHODS) { 1061 os_memmove(&sm->user->methods[i], 1062 &sm->user->methods[i + 1], 1063 (EAP_MAX_METHODS - i - 1) * 1064 sizeof(sm->user->methods[0])); 1065 } 1066 sm->user->methods[EAP_MAX_METHODS - 1].vendor = 1067 EAP_VENDOR_IETF; 1068 sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE; 1069 } 1070 1071 wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", 1072 (u8 *) sm->user->methods, EAP_MAX_METHODS * 1073 sizeof(sm->user->methods[0])); 1074 } 1075 1076 1077 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, 1078 size_t len) 1079 { 1080 if (nak_list == NULL || sm == NULL || sm->user == NULL) 1081 return; 1082 1083 if (sm->user->phase2) { 1084 wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user" 1085 " info was selected - reject"); 1086 sm->decision = DECISION_FAILURE; 1087 return; 1088 } 1089 1090 eap_sm_process_nak(sm, nak_list, len); 1091 } 1092 1093 1094 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) 1095 { 1096 EapType next; 1097 int idx = sm->user_eap_method_index; 1098 1099 /* In theory, there should be no problems with starting 1100 * re-authentication with something else than EAP-Request/Identity and 1101 * this does indeed work with wpa_supplicant. However, at least Funk 1102 * Supplicant seemed to ignore re-auth if it skipped 1103 * EAP-Request/Identity. 1104 * Re-auth sets currentId == -1, so that can be used here to select 1105 * whether Identity needs to be requested again. */ 1106 if (sm->identity == NULL || sm->currentId == -1) { 1107 *vendor = EAP_VENDOR_IETF; 1108 next = EAP_TYPE_IDENTITY; 1109 sm->update_user = TRUE; 1110 } else if (sm->user && idx < EAP_MAX_METHODS && 1111 (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || 1112 sm->user->methods[idx].method != EAP_TYPE_NONE)) { 1113 *vendor = sm->user->methods[idx].vendor; 1114 next = sm->user->methods[idx].method; 1115 sm->user_eap_method_index++; 1116 } else { 1117 *vendor = EAP_VENDOR_IETF; 1118 next = EAP_TYPE_NONE; 1119 } 1120 wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d", 1121 *vendor, next); 1122 return next; 1123 } 1124 1125 1126 static int eap_sm_Policy_getDecision(struct eap_sm *sm) 1127 { 1128 if (!sm->eap_server && sm->identity && !sm->start_reauth) { 1129 wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH"); 1130 return DECISION_PASSTHROUGH; 1131 } 1132 1133 if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY && 1134 sm->m->isSuccess(sm, sm->eap_method_priv)) { 1135 wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " 1136 "SUCCESS"); 1137 sm->update_user = TRUE; 1138 return DECISION_SUCCESS; 1139 } 1140 1141 if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) && 1142 !sm->m->isSuccess(sm, sm->eap_method_priv)) { 1143 wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " 1144 "FAILURE"); 1145 sm->update_user = TRUE; 1146 return DECISION_FAILURE; 1147 } 1148 1149 if ((sm->user == NULL || sm->update_user) && sm->identity && 1150 !sm->start_reauth) { 1151 /* 1152 * Allow Identity method to be started once to allow identity 1153 * selection hint to be sent from the authentication server, 1154 * but prevent a loop of Identity requests by only allowing 1155 * this to happen once. 1156 */ 1157 int id_req = 0; 1158 if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY && 1159 sm->user->methods[0].vendor == EAP_VENDOR_IETF && 1160 sm->user->methods[0].method == EAP_TYPE_IDENTITY) 1161 id_req = 1; 1162 if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) { 1163 wpa_printf(MSG_DEBUG, "EAP: getDecision: user not " 1164 "found from database -> FAILURE"); 1165 return DECISION_FAILURE; 1166 } 1167 if (id_req && sm->user && 1168 sm->user->methods[0].vendor == EAP_VENDOR_IETF && 1169 sm->user->methods[0].method == EAP_TYPE_IDENTITY) { 1170 wpa_printf(MSG_DEBUG, "EAP: getDecision: stop " 1171 "identity request loop -> FAILURE"); 1172 sm->update_user = TRUE; 1173 return DECISION_FAILURE; 1174 } 1175 sm->update_user = FALSE; 1176 } 1177 sm->start_reauth = FALSE; 1178 1179 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 1180 (sm->user->methods[sm->user_eap_method_index].vendor != 1181 EAP_VENDOR_IETF || 1182 sm->user->methods[sm->user_eap_method_index].method != 1183 EAP_TYPE_NONE)) { 1184 wpa_printf(MSG_DEBUG, "EAP: getDecision: another method " 1185 "available -> CONTINUE"); 1186 return DECISION_CONTINUE; 1187 } 1188 1189 if (sm->identity == NULL || sm->currentId == -1) { 1190 wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known " 1191 "yet -> CONTINUE"); 1192 return DECISION_CONTINUE; 1193 } 1194 1195 wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> " 1196 "FAILURE"); 1197 return DECISION_FAILURE; 1198 } 1199 1200 1201 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method) 1202 { 1203 return method == EAP_TYPE_IDENTITY ? TRUE : FALSE; 1204 } 1205 1206 1207 /** 1208 * eap_server_sm_step - Step EAP server state machine 1209 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1210 * Returns: 1 if EAP state was changed or 0 if not 1211 * 1212 * This function advances EAP state machine to a new state to match with the 1213 * current variables. This should be called whenever variables used by the EAP 1214 * state machine have changed. 1215 */ 1216 int eap_server_sm_step(struct eap_sm *sm) 1217 { 1218 int res = 0; 1219 do { 1220 sm->changed = FALSE; 1221 SM_STEP_RUN(EAP); 1222 if (sm->changed) 1223 res = 1; 1224 } while (sm->changed); 1225 return res; 1226 } 1227 1228 1229 static void eap_user_free(struct eap_user *user) 1230 { 1231 if (user == NULL) 1232 return; 1233 os_free(user->password); 1234 user->password = NULL; 1235 os_free(user); 1236 } 1237 1238 1239 /** 1240 * eap_server_sm_init - Allocate and initialize EAP server state machine 1241 * @eapol_ctx: Context data to be used with eapol_cb calls 1242 * @eapol_cb: Pointer to EAPOL callback functions 1243 * @conf: EAP configuration 1244 * Returns: Pointer to the allocated EAP state machine or %NULL on failure 1245 * 1246 * This function allocates and initializes an EAP state machine. 1247 */ 1248 struct eap_sm * eap_server_sm_init(void *eapol_ctx, 1249 struct eapol_callbacks *eapol_cb, 1250 struct eap_config *conf) 1251 { 1252 struct eap_sm *sm; 1253 1254 sm = os_zalloc(sizeof(*sm)); 1255 if (sm == NULL) 1256 return NULL; 1257 sm->eapol_ctx = eapol_ctx; 1258 sm->eapol_cb = eapol_cb; 1259 sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */ 1260 sm->ssl_ctx = conf->ssl_ctx; 1261 sm->msg_ctx = conf->msg_ctx; 1262 sm->eap_sim_db_priv = conf->eap_sim_db_priv; 1263 sm->backend_auth = conf->backend_auth; 1264 sm->eap_server = conf->eap_server; 1265 if (conf->pac_opaque_encr_key) { 1266 sm->pac_opaque_encr_key = os_malloc(16); 1267 if (sm->pac_opaque_encr_key) { 1268 os_memcpy(sm->pac_opaque_encr_key, 1269 conf->pac_opaque_encr_key, 16); 1270 } 1271 } 1272 if (conf->eap_fast_a_id) { 1273 sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); 1274 if (sm->eap_fast_a_id) { 1275 os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id, 1276 conf->eap_fast_a_id_len); 1277 sm->eap_fast_a_id_len = conf->eap_fast_a_id_len; 1278 } 1279 } 1280 if (conf->eap_fast_a_id_info) 1281 sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); 1282 sm->eap_fast_prov = conf->eap_fast_prov; 1283 sm->pac_key_lifetime = conf->pac_key_lifetime; 1284 sm->pac_key_refresh_time = conf->pac_key_refresh_time; 1285 sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; 1286 sm->tnc = conf->tnc; 1287 sm->wps = conf->wps; 1288 if (conf->assoc_wps_ie) 1289 sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie); 1290 if (conf->assoc_p2p_ie) 1291 sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie); 1292 if (conf->peer_addr) 1293 os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN); 1294 sm->fragment_size = conf->fragment_size; 1295 sm->pwd_group = conf->pwd_group; 1296 sm->pbc_in_m1 = conf->pbc_in_m1; 1297 sm->server_id = conf->server_id; 1298 sm->server_id_len = conf->server_id_len; 1299 1300 wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); 1301 1302 return sm; 1303 } 1304 1305 1306 /** 1307 * eap_server_sm_deinit - Deinitialize and free an EAP server state machine 1308 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1309 * 1310 * This function deinitializes EAP state machine and frees all allocated 1311 * resources. 1312 */ 1313 void eap_server_sm_deinit(struct eap_sm *sm) 1314 { 1315 if (sm == NULL) 1316 return; 1317 wpa_printf(MSG_DEBUG, "EAP: Server state machine removed"); 1318 if (sm->m && sm->eap_method_priv) 1319 sm->m->reset(sm, sm->eap_method_priv); 1320 wpabuf_free(sm->eap_if.eapReqData); 1321 os_free(sm->eap_if.eapKeyData); 1322 wpabuf_free(sm->lastReqData); 1323 wpabuf_free(sm->eap_if.eapRespData); 1324 os_free(sm->identity); 1325 os_free(sm->pac_opaque_encr_key); 1326 os_free(sm->eap_fast_a_id); 1327 os_free(sm->eap_fast_a_id_info); 1328 wpabuf_free(sm->eap_if.aaaEapReqData); 1329 wpabuf_free(sm->eap_if.aaaEapRespData); 1330 os_free(sm->eap_if.aaaEapKeyData); 1331 eap_user_free(sm->user); 1332 wpabuf_free(sm->assoc_wps_ie); 1333 wpabuf_free(sm->assoc_p2p_ie); 1334 os_free(sm); 1335 } 1336 1337 1338 /** 1339 * eap_sm_notify_cached - Notify EAP state machine of cached PMK 1340 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1341 * 1342 * This function is called when PMKSA caching is used to skip EAP 1343 * authentication. 1344 */ 1345 void eap_sm_notify_cached(struct eap_sm *sm) 1346 { 1347 if (sm == NULL) 1348 return; 1349 1350 sm->EAP_state = EAP_SUCCESS; 1351 } 1352 1353 1354 /** 1355 * eap_sm_pending_cb - EAP state machine callback for a pending EAP request 1356 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1357 * 1358 * This function is called when data for a pending EAP-Request is received. 1359 */ 1360 void eap_sm_pending_cb(struct eap_sm *sm) 1361 { 1362 if (sm == NULL) 1363 return; 1364 wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received"); 1365 if (sm->method_pending == METHOD_PENDING_WAIT) 1366 sm->method_pending = METHOD_PENDING_CONT; 1367 } 1368 1369 1370 /** 1371 * eap_sm_method_pending - Query whether EAP method is waiting for pending data 1372 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1373 * Returns: 1 if method is waiting for pending data or 0 if not 1374 */ 1375 int eap_sm_method_pending(struct eap_sm *sm) 1376 { 1377 if (sm == NULL) 1378 return 0; 1379 return sm->method_pending == METHOD_PENDING_WAIT; 1380 } 1381 1382 1383 /** 1384 * eap_get_identity - Get the user identity (from EAP-Response/Identity) 1385 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1386 * @len: Buffer for returning identity length 1387 * Returns: Pointer to the user identity or %NULL if not available 1388 */ 1389 const u8 * eap_get_identity(struct eap_sm *sm, size_t *len) 1390 { 1391 *len = sm->identity_len; 1392 return sm->identity; 1393 } 1394 1395 1396 /** 1397 * eap_get_interface - Get pointer to EAP-EAPOL interface data 1398 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1399 * Returns: Pointer to the EAP-EAPOL interface data 1400 */ 1401 struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm) 1402 { 1403 return &sm->eap_if; 1404 } 1405 1406 1407 /** 1408 * eap_server_clear_identity - Clear EAP identity information 1409 * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() 1410 * 1411 * This function can be used to clear the EAP identity information in the EAP 1412 * server context. This allows the EAP/Identity method to be used again after 1413 * EAPOL-Start or EAPOL-Logoff. 1414 */ 1415 void eap_server_clear_identity(struct eap_sm *sm) 1416 { 1417 os_free(sm->identity); 1418 sm->identity = NULL; 1419 } 1420