1 /* 2 * EAPOL supplicant state machines 3 * Copyright (c) 2004-2012, 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 9 #include "includes.h" 10 11 #include "common.h" 12 #include "state_machine.h" 13 #include "wpabuf.h" 14 #include "eloop.h" 15 #include "crypto/crypto.h" 16 #include "crypto/md5.h" 17 #include "common/eapol_common.h" 18 #include "eap_peer/eap.h" 19 #include "eap_peer/eap_config.h" 20 #include "eap_peer/eap_proxy.h" 21 #include "eapol_supp_sm.h" 22 23 #define STATE_MACHINE_DATA struct eapol_sm 24 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL" 25 26 27 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */ 28 29 /** 30 * struct eapol_sm - Internal data for EAPOL state machines 31 */ 32 struct eapol_sm { 33 /* Timers */ 34 unsigned int authWhile; 35 unsigned int heldWhile; 36 unsigned int startWhen; 37 unsigned int idleWhile; /* for EAP state machine */ 38 int timer_tick_enabled; 39 40 /* Global variables */ 41 bool eapFail; 42 bool eapolEap; 43 bool eapSuccess; 44 bool initialize; 45 bool keyDone; 46 bool keyRun; 47 PortControl portControl; 48 bool portEnabled; 49 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ 50 bool portValid; 51 bool suppAbort; 52 bool suppFail; 53 bool suppStart; 54 bool suppSuccess; 55 bool suppTimeout; 56 57 /* Supplicant PAE state machine */ 58 enum { 59 SUPP_PAE_UNKNOWN = 0, 60 SUPP_PAE_DISCONNECTED = 1, 61 SUPP_PAE_LOGOFF = 2, 62 SUPP_PAE_CONNECTING = 3, 63 SUPP_PAE_AUTHENTICATING = 4, 64 SUPP_PAE_AUTHENTICATED = 5, 65 /* unused(6) */ 66 SUPP_PAE_HELD = 7, 67 SUPP_PAE_RESTART = 8, 68 SUPP_PAE_S_FORCE_AUTH = 9, 69 SUPP_PAE_S_FORCE_UNAUTH = 10 70 } SUPP_PAE_state; /* dot1xSuppPaeState */ 71 /* Variables */ 72 bool userLogoff; 73 bool logoffSent; 74 unsigned int startCount; 75 bool eapRestart; 76 PortControl sPortMode; 77 /* Constants */ 78 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ 79 unsigned int startPeriod; /* dot1xSuppStartPeriod */ 80 unsigned int maxStart; /* dot1xSuppMaxStart */ 81 82 /* Key Receive state machine */ 83 enum { 84 KEY_RX_UNKNOWN = 0, 85 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE 86 } KEY_RX_state; 87 /* Variables */ 88 bool rxKey; 89 90 /* Supplicant Backend state machine */ 91 enum { 92 SUPP_BE_UNKNOWN = 0, 93 SUPP_BE_INITIALIZE = 1, 94 SUPP_BE_IDLE = 2, 95 SUPP_BE_REQUEST = 3, 96 SUPP_BE_RECEIVE = 4, 97 SUPP_BE_RESPONSE = 5, 98 SUPP_BE_FAIL = 6, 99 SUPP_BE_TIMEOUT = 7, 100 SUPP_BE_SUCCESS = 8 101 } SUPP_BE_state; /* dot1xSuppBackendPaeState */ 102 /* Variables */ 103 bool eapNoResp; 104 bool eapReq; 105 bool eapResp; 106 /* Constants */ 107 unsigned int authPeriod; /* dot1xSuppAuthPeriod */ 108 109 /* Statistics */ 110 unsigned int dot1xSuppEapolFramesRx; 111 unsigned int dot1xSuppEapolFramesTx; 112 unsigned int dot1xSuppEapolStartFramesTx; 113 unsigned int dot1xSuppEapolLogoffFramesTx; 114 unsigned int dot1xSuppEapolRespFramesTx; 115 unsigned int dot1xSuppEapolReqIdFramesRx; 116 unsigned int dot1xSuppEapolReqFramesRx; 117 unsigned int dot1xSuppInvalidEapolFramesRx; 118 unsigned int dot1xSuppEapLengthErrorFramesRx; 119 unsigned int dot1xSuppLastEapolFrameVersion; 120 unsigned char dot1xSuppLastEapolFrameSource[6]; 121 122 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */ 123 bool changed; 124 struct eap_sm *eap; 125 struct eap_peer_config *config; 126 bool initial_req; 127 u8 *last_rx_key; 128 size_t last_rx_key_len; 129 struct wpabuf *eapReqData; /* for EAP */ 130 bool altAccept; /* for EAP */ 131 bool altReject; /* for EAP */ 132 bool eapTriggerStart; 133 bool replay_counter_valid; 134 u8 last_replay_counter[16]; 135 struct eapol_config conf; 136 struct eapol_ctx *ctx; 137 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } 138 cb_status; 139 bool cached_pmk; 140 141 bool unicast_key_received, broadcast_key_received; 142 143 bool force_authorized_update; 144 145 #ifdef CONFIG_EAP_PROXY 146 bool use_eap_proxy; 147 struct eap_proxy_sm *eap_proxy; 148 #endif /* CONFIG_EAP_PROXY */ 149 }; 150 151 152 static void eapol_sm_txLogoff(struct eapol_sm *sm); 153 static void eapol_sm_txStart(struct eapol_sm *sm); 154 static void eapol_sm_processKey(struct eapol_sm *sm); 155 static void eapol_sm_getSuppRsp(struct eapol_sm *sm); 156 static void eapol_sm_txSuppRsp(struct eapol_sm *sm); 157 static void eapol_sm_abortSupp(struct eapol_sm *sm); 158 static void eapol_sm_abort_cached(struct eapol_sm *sm); 159 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx); 160 static void eapol_sm_set_port_authorized(struct eapol_sm *sm); 161 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm); 162 163 164 /* Port Timers state machine - implemented as a function that will be called 165 * once a second as a registered event loop timeout */ 166 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) 167 { 168 struct eapol_sm *sm = timeout_ctx; 169 170 if (sm->authWhile > 0) { 171 sm->authWhile--; 172 if (sm->authWhile == 0) 173 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0"); 174 } 175 if (sm->heldWhile > 0) { 176 sm->heldWhile--; 177 if (sm->heldWhile == 0) 178 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0"); 179 } 180 if (sm->startWhen > 0) { 181 sm->startWhen--; 182 if (sm->startWhen == 0) 183 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0"); 184 } 185 if (sm->idleWhile > 0) { 186 sm->idleWhile--; 187 if (sm->idleWhile == 0) 188 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0"); 189 } 190 191 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) { 192 if (eloop_register_timeout(1, 0, eapol_port_timers_tick, 193 eloop_ctx, sm) < 0) 194 sm->timer_tick_enabled = 0; 195 } else { 196 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick"); 197 sm->timer_tick_enabled = 0; 198 } 199 eapol_sm_step(sm); 200 } 201 202 203 static int eapol_sm_confirm_auth(struct eapol_sm *sm) 204 { 205 if (!sm->ctx->confirm_auth_cb) 206 return 0; 207 208 return sm->ctx->confirm_auth_cb(sm->ctx->ctx); 209 } 210 211 212 static void eapol_enable_timer_tick(struct eapol_sm *sm) 213 { 214 if (sm->timer_tick_enabled) 215 return; 216 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick"); 217 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 218 if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0) 219 sm->timer_tick_enabled = 1; 220 } 221 222 223 SM_STATE(SUPP_PAE, LOGOFF) 224 { 225 SM_ENTRY(SUPP_PAE, LOGOFF); 226 eapol_sm_txLogoff(sm); 227 sm->logoffSent = true; 228 eapol_sm_set_port_unauthorized(sm); 229 } 230 231 232 SM_STATE(SUPP_PAE, DISCONNECTED) 233 { 234 SM_ENTRY(SUPP_PAE, DISCONNECTED); 235 sm->sPortMode = Auto; 236 sm->startCount = 0; 237 sm->eapTriggerStart = false; 238 sm->logoffSent = false; 239 eapol_sm_set_port_unauthorized(sm); 240 sm->suppAbort = true; 241 242 sm->unicast_key_received = false; 243 sm->broadcast_key_received = false; 244 245 /* 246 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so 247 * allows the timer tick to be stopped more quickly when the port is 248 * not enabled. Since this variable is used only within HELD state, 249 * clearing it on initialization does not change actual state machine 250 * behavior. 251 */ 252 sm->heldWhile = 0; 253 } 254 255 256 SM_STATE(SUPP_PAE, CONNECTING) 257 { 258 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING || 259 sm->SUPP_PAE_state == SUPP_PAE_HELD; 260 SM_ENTRY(SUPP_PAE, CONNECTING); 261 262 if (sm->eapTriggerStart) 263 send_start = 1; 264 if (sm->ctx->preauth) 265 send_start = 1; 266 sm->eapTriggerStart = false; 267 268 if (send_start) { 269 sm->startWhen = sm->startPeriod; 270 sm->startCount++; 271 } else { 272 /* 273 * Do not send EAPOL-Start immediately since in most cases, 274 * Authenticator is going to start authentication immediately 275 * after association and an extra EAPOL-Start is just going to 276 * delay authentication. Use a short timeout to send the first 277 * EAPOL-Start if Authenticator does not start authentication. 278 */ 279 if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) { 280 /* Reduce latency on starting WPS negotiation. */ 281 wpa_printf(MSG_DEBUG, 282 "EAPOL: Using shorter startWhen for WPS"); 283 sm->startWhen = 1; 284 } else { 285 sm->startWhen = 2; 286 } 287 } 288 eapol_enable_timer_tick(sm); 289 sm->eapolEap = false; 290 if (send_start) 291 eapol_sm_txStart(sm); 292 } 293 294 295 SM_STATE(SUPP_PAE, AUTHENTICATING) 296 { 297 SM_ENTRY(SUPP_PAE, AUTHENTICATING); 298 sm->startCount = 0; 299 sm->suppSuccess = false; 300 sm->suppFail = false; 301 sm->suppTimeout = false; 302 sm->keyRun = false; 303 sm->keyDone = false; 304 sm->suppStart = true; 305 } 306 307 308 SM_STATE(SUPP_PAE, HELD) 309 { 310 SM_ENTRY(SUPP_PAE, HELD); 311 sm->heldWhile = sm->heldPeriod; 312 eapol_enable_timer_tick(sm); 313 eapol_sm_set_port_unauthorized(sm); 314 sm->cb_status = EAPOL_CB_FAILURE; 315 } 316 317 318 SM_STATE(SUPP_PAE, AUTHENTICATED) 319 { 320 SM_ENTRY(SUPP_PAE, AUTHENTICATED); 321 eapol_sm_set_port_authorized(sm); 322 sm->cb_status = EAPOL_CB_SUCCESS; 323 } 324 325 326 SM_STATE(SUPP_PAE, RESTART) 327 { 328 if (eapol_sm_confirm_auth(sm)) { 329 /* Don't process restart, we are already reconnecting */ 330 return; 331 } 332 333 SM_ENTRY(SUPP_PAE, RESTART); 334 sm->eapRestart = true; 335 if (sm->altAccept) { 336 /* 337 * Prevent EAP peer state machine from failing due to prior 338 * external EAP success notification (altSuccess=true in the 339 * IDLE state could result in a transition to the FAILURE state. 340 */ 341 wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE"); 342 sm->eapSuccess = false; 343 sm->altAccept = false; 344 } 345 } 346 347 348 SM_STATE(SUPP_PAE, S_FORCE_AUTH) 349 { 350 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH); 351 eapol_sm_set_port_authorized(sm); 352 sm->sPortMode = ForceAuthorized; 353 } 354 355 356 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) 357 { 358 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); 359 eapol_sm_set_port_unauthorized(sm); 360 sm->sPortMode = ForceUnauthorized; 361 eapol_sm_txLogoff(sm); 362 } 363 364 365 SM_STEP(SUPP_PAE) 366 { 367 if ((sm->userLogoff && !sm->logoffSent) && 368 !(sm->initialize || !sm->portEnabled)) 369 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF); 370 else if (((sm->portControl == Auto) && 371 (sm->sPortMode != sm->portControl)) || 372 sm->initialize || !sm->portEnabled) 373 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED); 374 else if ((sm->portControl == ForceAuthorized) && 375 (sm->sPortMode != sm->portControl) && 376 !(sm->initialize || !sm->portEnabled)) 377 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH); 378 else if ((sm->portControl == ForceUnauthorized) && 379 (sm->sPortMode != sm->portControl) && 380 !(sm->initialize || !sm->portEnabled)) 381 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH); 382 else switch (sm->SUPP_PAE_state) { 383 case SUPP_PAE_UNKNOWN: 384 break; 385 case SUPP_PAE_LOGOFF: 386 if (!sm->userLogoff) 387 SM_ENTER(SUPP_PAE, DISCONNECTED); 388 break; 389 case SUPP_PAE_DISCONNECTED: 390 SM_ENTER(SUPP_PAE, CONNECTING); 391 break; 392 case SUPP_PAE_CONNECTING: 393 if (sm->startWhen == 0 && sm->startCount < sm->maxStart) 394 SM_ENTER(SUPP_PAE, CONNECTING); 395 else if (sm->startWhen == 0 && 396 sm->startCount >= sm->maxStart && 397 sm->portValid) 398 SM_ENTER(SUPP_PAE, AUTHENTICATED); 399 else if (sm->eapSuccess || sm->eapFail) 400 SM_ENTER(SUPP_PAE, AUTHENTICATING); 401 else if (sm->eapolEap) 402 SM_ENTER(SUPP_PAE, RESTART); 403 else if (sm->startWhen == 0 && 404 sm->startCount >= sm->maxStart && 405 !sm->portValid) 406 SM_ENTER(SUPP_PAE, HELD); 407 break; 408 case SUPP_PAE_AUTHENTICATING: 409 if (sm->eapSuccess && !sm->portValid && 410 sm->conf.accept_802_1x_keys && 411 sm->conf.required_keys == 0) { 412 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " 413 "plaintext connection; no EAPOL-Key frames " 414 "required"); 415 sm->portValid = true; 416 if (sm->ctx->eapol_done_cb) 417 sm->ctx->eapol_done_cb(sm->ctx->ctx); 418 } 419 if (sm->eapSuccess && sm->portValid) 420 SM_ENTER(SUPP_PAE, AUTHENTICATED); 421 else if (sm->eapFail || (sm->keyDone && !sm->portValid)) 422 SM_ENTER(SUPP_PAE, HELD); 423 else if (sm->suppTimeout) 424 SM_ENTER(SUPP_PAE, CONNECTING); 425 else if (sm->eapTriggerStart) 426 SM_ENTER(SUPP_PAE, CONNECTING); 427 break; 428 case SUPP_PAE_HELD: 429 if (sm->heldWhile == 0) 430 SM_ENTER(SUPP_PAE, CONNECTING); 431 else if (sm->eapolEap) 432 SM_ENTER(SUPP_PAE, RESTART); 433 break; 434 case SUPP_PAE_AUTHENTICATED: 435 if (sm->eapolEap && sm->portValid) 436 SM_ENTER(SUPP_PAE, RESTART); 437 else if (!sm->portValid) 438 SM_ENTER(SUPP_PAE, DISCONNECTED); 439 break; 440 case SUPP_PAE_RESTART: 441 if (!sm->eapRestart) 442 SM_ENTER(SUPP_PAE, AUTHENTICATING); 443 break; 444 case SUPP_PAE_S_FORCE_AUTH: 445 break; 446 case SUPP_PAE_S_FORCE_UNAUTH: 447 break; 448 } 449 } 450 451 452 SM_STATE(KEY_RX, NO_KEY_RECEIVE) 453 { 454 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE); 455 } 456 457 458 SM_STATE(KEY_RX, KEY_RECEIVE) 459 { 460 SM_ENTRY(KEY_RX, KEY_RECEIVE); 461 eapol_sm_processKey(sm); 462 sm->rxKey = false; 463 } 464 465 466 SM_STEP(KEY_RX) 467 { 468 if (sm->initialize || !sm->portEnabled) 469 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); 470 switch (sm->KEY_RX_state) { 471 case KEY_RX_UNKNOWN: 472 break; 473 case KEY_RX_NO_KEY_RECEIVE: 474 if (sm->rxKey) 475 SM_ENTER(KEY_RX, KEY_RECEIVE); 476 break; 477 case KEY_RX_KEY_RECEIVE: 478 if (sm->rxKey) 479 SM_ENTER(KEY_RX, KEY_RECEIVE); 480 break; 481 } 482 } 483 484 485 SM_STATE(SUPP_BE, REQUEST) 486 { 487 SM_ENTRY(SUPP_BE, REQUEST); 488 sm->authWhile = 0; 489 sm->eapReq = true; 490 eapol_sm_getSuppRsp(sm); 491 } 492 493 494 SM_STATE(SUPP_BE, RESPONSE) 495 { 496 SM_ENTRY(SUPP_BE, RESPONSE); 497 eapol_sm_txSuppRsp(sm); 498 sm->eapResp = false; 499 } 500 501 502 SM_STATE(SUPP_BE, SUCCESS) 503 { 504 SM_ENTRY(SUPP_BE, SUCCESS); 505 sm->keyRun = true; 506 sm->suppSuccess = true; 507 508 #ifdef CONFIG_EAP_PROXY 509 if (sm->use_eap_proxy) { 510 if (eap_proxy_key_available(sm->eap_proxy)) { 511 u8 *session_id, *emsk; 512 size_t session_id_len, emsk_len; 513 514 /* New key received - clear IEEE 802.1X EAPOL-Key replay 515 * counter */ 516 sm->replay_counter_valid = false; 517 518 session_id = eap_proxy_get_eap_session_id( 519 sm->eap_proxy, &session_id_len); 520 emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len); 521 if (sm->config->erp && session_id && emsk) { 522 eap_peer_erp_init(sm->eap, session_id, 523 session_id_len, emsk, 524 emsk_len); 525 } else { 526 os_free(session_id); 527 bin_clear_free(emsk, emsk_len); 528 } 529 } 530 return; 531 } 532 #endif /* CONFIG_EAP_PROXY */ 533 534 if (eap_key_available(sm->eap)) { 535 /* New key received - clear IEEE 802.1X EAPOL-Key replay 536 * counter */ 537 sm->replay_counter_valid = false; 538 } 539 } 540 541 542 SM_STATE(SUPP_BE, FAIL) 543 { 544 SM_ENTRY(SUPP_BE, FAIL); 545 sm->suppFail = true; 546 } 547 548 549 SM_STATE(SUPP_BE, TIMEOUT) 550 { 551 SM_ENTRY(SUPP_BE, TIMEOUT); 552 sm->suppTimeout = true; 553 } 554 555 556 SM_STATE(SUPP_BE, IDLE) 557 { 558 SM_ENTRY(SUPP_BE, IDLE); 559 sm->suppStart = false; 560 sm->initial_req = true; 561 } 562 563 564 SM_STATE(SUPP_BE, INITIALIZE) 565 { 566 SM_ENTRY(SUPP_BE, INITIALIZE); 567 eapol_sm_abortSupp(sm); 568 sm->suppAbort = false; 569 570 /* 571 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so 572 * allows the timer tick to be stopped more quickly when the port is 573 * not enabled. Since this variable is used only within RECEIVE state, 574 * clearing it on initialization does not change actual state machine 575 * behavior. 576 */ 577 sm->authWhile = 0; 578 } 579 580 581 SM_STATE(SUPP_BE, RECEIVE) 582 { 583 SM_ENTRY(SUPP_BE, RECEIVE); 584 sm->authWhile = sm->authPeriod; 585 eapol_enable_timer_tick(sm); 586 sm->eapolEap = false; 587 sm->eapNoResp = false; 588 sm->initial_req = false; 589 } 590 591 592 SM_STEP(SUPP_BE) 593 { 594 if (sm->initialize || sm->suppAbort) 595 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE); 596 else switch (sm->SUPP_BE_state) { 597 case SUPP_BE_UNKNOWN: 598 break; 599 case SUPP_BE_REQUEST: 600 /* 601 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL 602 * and SUCCESS based on eapFail and eapSuccess, respectively. 603 * However, IEEE Std 802.1X-2004 is also specifying that 604 * eapNoResp should be set in conjunction with eapSuccess and 605 * eapFail which would mean that more than one of the 606 * transitions here would be activated at the same time. 607 * Skipping RESPONSE and/or RECEIVE states in these cases can 608 * cause problems and the direct transitions to do not seem 609 * correct. Because of this, the conditions for these 610 * transitions are verified only after eapNoResp. They are 611 * unlikely to be used since eapNoResp should always be set if 612 * either of eapSuccess or eapFail is set. 613 */ 614 if (sm->eapResp && sm->eapNoResp) { 615 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both " 616 "eapResp and eapNoResp set?!"); 617 } 618 if (sm->eapResp) 619 SM_ENTER(SUPP_BE, RESPONSE); 620 else if (sm->eapNoResp) 621 SM_ENTER(SUPP_BE, RECEIVE); 622 else if (sm->eapFail) 623 SM_ENTER(SUPP_BE, FAIL); 624 else if (sm->eapSuccess) 625 SM_ENTER(SUPP_BE, SUCCESS); 626 break; 627 case SUPP_BE_RESPONSE: 628 SM_ENTER(SUPP_BE, RECEIVE); 629 break; 630 case SUPP_BE_SUCCESS: 631 SM_ENTER(SUPP_BE, IDLE); 632 break; 633 case SUPP_BE_FAIL: 634 SM_ENTER(SUPP_BE, IDLE); 635 break; 636 case SUPP_BE_TIMEOUT: 637 SM_ENTER(SUPP_BE, IDLE); 638 break; 639 case SUPP_BE_IDLE: 640 if (sm->eapFail && sm->suppStart) 641 SM_ENTER(SUPP_BE, FAIL); 642 else if (sm->eapolEap && sm->suppStart) 643 SM_ENTER(SUPP_BE, REQUEST); 644 else if (sm->eapSuccess && sm->suppStart) 645 SM_ENTER(SUPP_BE, SUCCESS); 646 break; 647 case SUPP_BE_INITIALIZE: 648 SM_ENTER(SUPP_BE, IDLE); 649 break; 650 case SUPP_BE_RECEIVE: 651 if (sm->eapolEap) 652 SM_ENTER(SUPP_BE, REQUEST); 653 else if (sm->eapFail) 654 SM_ENTER(SUPP_BE, FAIL); 655 else if (sm->authWhile == 0) 656 SM_ENTER(SUPP_BE, TIMEOUT); 657 else if (sm->eapSuccess) 658 SM_ENTER(SUPP_BE, SUCCESS); 659 break; 660 } 661 } 662 663 664 static void eapol_sm_txLogoff(struct eapol_sm *sm) 665 { 666 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff"); 667 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, 668 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0); 669 sm->dot1xSuppEapolLogoffFramesTx++; 670 sm->dot1xSuppEapolFramesTx++; 671 } 672 673 674 static void eapol_sm_txStart(struct eapol_sm *sm) 675 { 676 wpa_printf(MSG_DEBUG, "EAPOL: txStart"); 677 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, 678 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0); 679 sm->dot1xSuppEapolStartFramesTx++; 680 sm->dot1xSuppEapolFramesTx++; 681 } 682 683 684 #define IEEE8021X_ENCR_KEY_LEN 32 685 #define IEEE8021X_SIGN_KEY_LEN 32 686 687 struct eap_key_data { 688 u8 encr_key[IEEE8021X_ENCR_KEY_LEN]; 689 u8 sign_key[IEEE8021X_SIGN_KEY_LEN]; 690 }; 691 692 693 static void eapol_sm_processKey(struct eapol_sm *sm) 694 { 695 #ifdef CONFIG_WEP 696 #ifndef CONFIG_FIPS 697 struct ieee802_1x_hdr *hdr; 698 struct ieee802_1x_eapol_key *key; 699 struct eap_key_data keydata; 700 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32]; 701 #ifndef CONFIG_NO_RC4 702 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN]; 703 #endif /* CONFIG_NO_RC4 */ 704 int key_len, res, sign_key_len, encr_key_len; 705 u16 rx_key_length; 706 size_t plen; 707 708 wpa_printf(MSG_DEBUG, "EAPOL: processKey"); 709 if (sm->last_rx_key == NULL) 710 return; 711 712 if (!sm->conf.accept_802_1x_keys) { 713 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key" 714 " even though this was not accepted - " 715 "ignoring this packet"); 716 return; 717 } 718 719 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key)) 720 return; 721 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key; 722 key = (struct ieee802_1x_eapol_key *) (hdr + 1); 723 plen = be_to_host16(hdr->length); 724 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) { 725 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame"); 726 return; 727 } 728 rx_key_length = WPA_GET_BE16(key->key_length); 729 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d " 730 "EAPOL-Key: type=%d key_length=%d key_index=0x%x", 731 hdr->version, hdr->type, be_to_host16(hdr->length), 732 key->type, rx_key_length, key->key_index); 733 734 eapol_sm_notify_lower_layer_success(sm, 1); 735 sign_key_len = IEEE8021X_SIGN_KEY_LEN; 736 encr_key_len = IEEE8021X_ENCR_KEY_LEN; 737 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata)); 738 if (res < 0) { 739 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for " 740 "decrypting EAPOL-Key keys"); 741 return; 742 } 743 if (res == 16) { 744 /* LEAP derives only 16 bytes of keying material. */ 745 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16); 746 if (res) { 747 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP " 748 "master key for decrypting EAPOL-Key keys"); 749 return; 750 } 751 sign_key_len = 16; 752 encr_key_len = 16; 753 os_memcpy(keydata.sign_key, keydata.encr_key, 16); 754 } else if (res) { 755 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key " 756 "data for decrypting EAPOL-Key keys (res=%d)", res); 757 return; 758 } 759 760 /* The key replay_counter must increase when same master key */ 761 if (sm->replay_counter_valid && 762 os_memcmp(sm->last_replay_counter, key->replay_counter, 763 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) { 764 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did " 765 "not increase - ignoring key"); 766 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter", 767 sm->last_replay_counter, 768 IEEE8021X_REPLAY_COUNTER_LEN); 769 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter", 770 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); 771 return; 772 } 773 774 /* Verify key signature (HMAC-MD5) */ 775 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN); 776 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN); 777 hmac_md5(keydata.sign_key, sign_key_len, 778 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length), 779 key->key_signature); 780 if (os_memcmp_const(orig_key_sign, key->key_signature, 781 IEEE8021X_KEY_SIGN_LEN) != 0) { 782 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in " 783 "EAPOL-Key packet"); 784 os_memcpy(key->key_signature, orig_key_sign, 785 IEEE8021X_KEY_SIGN_LEN); 786 return; 787 } 788 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified"); 789 790 key_len = plen - sizeof(*key); 791 if (key_len > 32 || rx_key_length > 32) { 792 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d", 793 key_len ? key_len : rx_key_length); 794 return; 795 } 796 if (key_len == rx_key_length) { 797 #ifdef CONFIG_NO_RC4 798 if (encr_key_len) { 799 /* otherwise unused */ 800 } 801 wpa_printf(MSG_ERROR, "EAPOL: RC4 not supported in the build"); 802 return; 803 #else /* CONFIG_NO_RC4 */ 804 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN); 805 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key, 806 encr_key_len); 807 os_memcpy(datakey, key + 1, key_len); 808 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0, 809 datakey, key_len); 810 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key", 811 datakey, key_len); 812 #endif /* CONFIG_NO_RC4 */ 813 } else if (key_len == 0) { 814 /* 815 * IEEE 802.1X-2004 specifies that least significant Key Length 816 * octets from MS-MPPE-Send-Key are used as the key if the key 817 * data is not present. This seems to be meaning the beginning 818 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in 819 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator. 820 * Anyway, taking the beginning of the keying material from EAP 821 * seems to interoperate with Authenticators. 822 */ 823 key_len = rx_key_length; 824 os_memcpy(datakey, keydata.encr_key, key_len); 825 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying " 826 "material data encryption key", 827 datakey, key_len); 828 } else { 829 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d " 830 "(key_length=%d)", key_len, rx_key_length); 831 return; 832 } 833 834 sm->replay_counter_valid = true; 835 os_memcpy(sm->last_replay_counter, key->replay_counter, 836 IEEE8021X_REPLAY_COUNTER_LEN); 837 838 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d " 839 "len %d", 840 key->key_index & IEEE8021X_KEY_INDEX_FLAG ? 841 "unicast" : "broadcast", 842 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len); 843 844 if (sm->ctx->set_wep_key && 845 sm->ctx->set_wep_key(sm->ctx->ctx, 846 !!(key->key_index & IEEE8021X_KEY_INDEX_FLAG), 847 key->key_index & IEEE8021X_KEY_INDEX_MASK, 848 datakey, key_len) < 0) { 849 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " 850 " driver."); 851 } else { 852 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) 853 sm->unicast_key_received = true; 854 else 855 sm->broadcast_key_received = true; 856 857 if ((sm->unicast_key_received || 858 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && 859 (sm->broadcast_key_received || 860 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST))) 861 { 862 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " 863 "frames received"); 864 sm->portValid = true; 865 if (sm->ctx->eapol_done_cb) 866 sm->ctx->eapol_done_cb(sm->ctx->ctx); 867 } 868 } 869 #endif /* CONFIG_FIPS */ 870 #endif /* CONFIG_WEP */ 871 } 872 873 874 static void eapol_sm_getSuppRsp(struct eapol_sm *sm) 875 { 876 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp"); 877 /* EAP layer processing; no special code is needed, since Supplicant 878 * Backend state machine is waiting for eapNoResp or eapResp to be set 879 * and these are only set in the EAP state machine when the processing 880 * has finished. */ 881 } 882 883 884 static void eapol_sm_txSuppRsp(struct eapol_sm *sm) 885 { 886 struct wpabuf *resp; 887 888 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp"); 889 890 #ifdef CONFIG_EAP_PROXY 891 if (sm->use_eap_proxy) { 892 /* Get EAP Response from EAP Proxy */ 893 resp = eap_proxy_get_eapRespData(sm->eap_proxy); 894 if (resp == NULL) { 895 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy " 896 "response data not available"); 897 return; 898 } 899 } else 900 #endif /* CONFIG_EAP_PROXY */ 901 902 resp = eap_get_eapRespData(sm->eap); 903 if (resp == NULL) { 904 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data " 905 "not available"); 906 return; 907 } 908 909 /* Send EAP-Packet from the EAP layer to the Authenticator */ 910 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, 911 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp), 912 wpabuf_len(resp)); 913 914 /* eapRespData is not used anymore, so free it here */ 915 wpabuf_free(resp); 916 917 if (sm->initial_req) 918 sm->dot1xSuppEapolReqIdFramesRx++; 919 else 920 sm->dot1xSuppEapolReqFramesRx++; 921 sm->dot1xSuppEapolRespFramesTx++; 922 sm->dot1xSuppEapolFramesTx++; 923 } 924 925 926 static void eapol_sm_abortSupp(struct eapol_sm *sm) 927 { 928 /* release system resources that may have been allocated for the 929 * authentication session */ 930 os_free(sm->last_rx_key); 931 sm->last_rx_key = NULL; 932 wpabuf_free(sm->eapReqData); 933 sm->eapReqData = NULL; 934 eap_sm_abort(sm->eap); 935 #ifdef CONFIG_EAP_PROXY 936 eap_proxy_sm_abort(sm->eap_proxy); 937 #endif /* CONFIG_EAP_PROXY */ 938 } 939 940 941 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx) 942 { 943 eapol_sm_step(timeout_ctx); 944 } 945 946 947 static void eapol_sm_set_port_authorized(struct eapol_sm *sm) 948 { 949 int cb; 950 951 cb = sm->suppPortStatus != Authorized || sm->force_authorized_update; 952 sm->force_authorized_update = false; 953 sm->suppPortStatus = Authorized; 954 if (cb && sm->ctx->port_cb) 955 sm->ctx->port_cb(sm->ctx->ctx, 1); 956 } 957 958 959 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm) 960 { 961 int cb; 962 963 cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update; 964 sm->force_authorized_update = false; 965 sm->suppPortStatus = Unauthorized; 966 if (cb && sm->ctx->port_cb) 967 sm->ctx->port_cb(sm->ctx->ctx, 0); 968 } 969 970 971 /** 972 * eapol_sm_step - EAPOL state machine step function 973 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 974 * 975 * This function is called to notify the state machine about changed external 976 * variables. It will step through the EAPOL state machines in loop to process 977 * all triggered state changes. 978 */ 979 void eapol_sm_step(struct eapol_sm *sm) 980 { 981 int i; 982 983 /* In theory, it should be ok to run this in loop until !changed. 984 * However, it is better to use a limit on number of iterations to 985 * allow events (e.g., SIGTERM) to stop the program cleanly if the 986 * state machine were to generate a busy loop. */ 987 for (i = 0; i < 100; i++) { 988 sm->changed = false; 989 SM_STEP_RUN(SUPP_PAE); 990 SM_STEP_RUN(KEY_RX); 991 SM_STEP_RUN(SUPP_BE); 992 #ifdef CONFIG_EAP_PROXY 993 if (sm->use_eap_proxy) { 994 /* Drive the EAP proxy state machine */ 995 if (eap_proxy_sm_step(sm->eap_proxy, sm->eap)) 996 sm->changed = true; 997 } else 998 #endif /* CONFIG_EAP_PROXY */ 999 if (eap_peer_sm_step(sm->eap)) 1000 sm->changed = true; 1001 if (!sm->changed) 1002 break; 1003 } 1004 1005 if (sm->changed) { 1006 /* restart EAPOL state machine step from timeout call in order 1007 * to allow other events to be processed. */ 1008 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); 1009 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm); 1010 } 1011 1012 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) { 1013 enum eapol_supp_result result; 1014 if (sm->cb_status == EAPOL_CB_SUCCESS) 1015 result = EAPOL_SUPP_RESULT_SUCCESS; 1016 else if (eap_peer_was_failure_expected(sm->eap)) 1017 result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE; 1018 else 1019 result = EAPOL_SUPP_RESULT_FAILURE; 1020 sm->cb_status = EAPOL_CB_IN_PROGRESS; 1021 sm->ctx->cb(sm, result, sm->ctx->cb_ctx); 1022 } 1023 } 1024 1025 1026 #ifdef CONFIG_CTRL_IFACE 1027 static const char *eapol_supp_pae_state(int state) 1028 { 1029 switch (state) { 1030 case SUPP_PAE_LOGOFF: 1031 return "LOGOFF"; 1032 case SUPP_PAE_DISCONNECTED: 1033 return "DISCONNECTED"; 1034 case SUPP_PAE_CONNECTING: 1035 return "CONNECTING"; 1036 case SUPP_PAE_AUTHENTICATING: 1037 return "AUTHENTICATING"; 1038 case SUPP_PAE_HELD: 1039 return "HELD"; 1040 case SUPP_PAE_AUTHENTICATED: 1041 return "AUTHENTICATED"; 1042 case SUPP_PAE_RESTART: 1043 return "RESTART"; 1044 default: 1045 return "UNKNOWN"; 1046 } 1047 } 1048 1049 1050 static const char *eapol_supp_be_state(int state) 1051 { 1052 switch (state) { 1053 case SUPP_BE_REQUEST: 1054 return "REQUEST"; 1055 case SUPP_BE_RESPONSE: 1056 return "RESPONSE"; 1057 case SUPP_BE_SUCCESS: 1058 return "SUCCESS"; 1059 case SUPP_BE_FAIL: 1060 return "FAIL"; 1061 case SUPP_BE_TIMEOUT: 1062 return "TIMEOUT"; 1063 case SUPP_BE_IDLE: 1064 return "IDLE"; 1065 case SUPP_BE_INITIALIZE: 1066 return "INITIALIZE"; 1067 case SUPP_BE_RECEIVE: 1068 return "RECEIVE"; 1069 default: 1070 return "UNKNOWN"; 1071 } 1072 } 1073 1074 1075 static const char * eapol_port_status(PortStatus status) 1076 { 1077 if (status == Authorized) 1078 return "Authorized"; 1079 else 1080 return "Unauthorized"; 1081 } 1082 #endif /* CONFIG_CTRL_IFACE */ 1083 1084 1085 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 1086 static const char * eapol_port_control(PortControl ctrl) 1087 { 1088 switch (ctrl) { 1089 case Auto: 1090 return "Auto"; 1091 case ForceUnauthorized: 1092 return "ForceUnauthorized"; 1093 case ForceAuthorized: 1094 return "ForceAuthorized"; 1095 default: 1096 return "Unknown"; 1097 } 1098 } 1099 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 1100 1101 1102 /** 1103 * eapol_sm_configure - Set EAPOL variables 1104 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1105 * @heldPeriod: dot1xSuppHeldPeriod 1106 * @authPeriod: dot1xSuppAuthPeriod 1107 * @startPeriod: dot1xSuppStartPeriod 1108 * @maxStart: dot1xSuppMaxStart 1109 * 1110 * Set configurable EAPOL state machine variables. Each variable can be set to 1111 * the given value or ignored if set to -1 (to set only some of the variables). 1112 */ 1113 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, 1114 int startPeriod, int maxStart) 1115 { 1116 if (sm == NULL) 1117 return; 1118 if (heldPeriod >= 0) 1119 sm->heldPeriod = heldPeriod; 1120 if (authPeriod >= 0) 1121 sm->authPeriod = authPeriod; 1122 if (startPeriod >= 0) 1123 sm->startPeriod = startPeriod; 1124 if (maxStart >= 0) 1125 sm->maxStart = maxStart; 1126 } 1127 1128 1129 /** 1130 * eapol_sm_get_method_name - Get EAPOL method name 1131 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1132 * Returns: Static string containing name of current eap method or NULL 1133 */ 1134 const char * eapol_sm_get_method_name(struct eapol_sm *sm) 1135 { 1136 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED || 1137 sm->suppPortStatus != Authorized) 1138 return NULL; 1139 1140 return eap_sm_get_method_name(sm->eap); 1141 } 1142 1143 1144 #ifdef CONFIG_CTRL_IFACE 1145 /** 1146 * eapol_sm_get_status - Get EAPOL state machine status 1147 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1148 * @buf: Buffer for status information 1149 * @buflen: Maximum buffer length 1150 * @verbose: Whether to include verbose status information 1151 * Returns: Number of bytes written to buf. 1152 * 1153 * Query EAPOL state machine for status information. This function fills in a 1154 * text area with current status information from the EAPOL state machine. If 1155 * the buffer (buf) is not large enough, status information will be truncated 1156 * to fit the buffer. 1157 */ 1158 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, 1159 int verbose) 1160 { 1161 int len, ret; 1162 if (sm == NULL) 1163 return 0; 1164 1165 len = os_snprintf(buf, buflen, 1166 "Supplicant PAE state=%s\n" 1167 "suppPortStatus=%s\n", 1168 eapol_supp_pae_state(sm->SUPP_PAE_state), 1169 eapol_port_status(sm->suppPortStatus)); 1170 if (os_snprintf_error(buflen, len)) 1171 return 0; 1172 1173 if (verbose) { 1174 ret = os_snprintf(buf + len, buflen - len, 1175 "heldPeriod=%u\n" 1176 "authPeriod=%u\n" 1177 "startPeriod=%u\n" 1178 "maxStart=%u\n" 1179 "portControl=%s\n" 1180 "Supplicant Backend state=%s\n", 1181 sm->heldPeriod, 1182 sm->authPeriod, 1183 sm->startPeriod, 1184 sm->maxStart, 1185 eapol_port_control(sm->portControl), 1186 eapol_supp_be_state(sm->SUPP_BE_state)); 1187 if (os_snprintf_error(buflen - len, ret)) 1188 return len; 1189 len += ret; 1190 } 1191 1192 #ifdef CONFIG_EAP_PROXY 1193 if (sm->use_eap_proxy) 1194 len += eap_proxy_sm_get_status(sm->eap_proxy, 1195 buf + len, buflen - len, 1196 verbose); 1197 else 1198 #endif /* CONFIG_EAP_PROXY */ 1199 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose); 1200 1201 return len; 1202 } 1203 1204 1205 /** 1206 * eapol_sm_get_mib - Get EAPOL state machine MIBs 1207 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1208 * @buf: Buffer for MIB information 1209 * @buflen: Maximum buffer length 1210 * Returns: Number of bytes written to buf. 1211 * 1212 * Query EAPOL state machine for MIB information. This function fills in a 1213 * text area with current MIB information from the EAPOL state machine. If 1214 * the buffer (buf) is not large enough, MIB information will be truncated to 1215 * fit the buffer. 1216 */ 1217 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen) 1218 { 1219 size_t len; 1220 int ret; 1221 1222 if (sm == NULL) 1223 return 0; 1224 ret = os_snprintf(buf, buflen, 1225 "dot1xSuppPaeState=%d\n" 1226 "dot1xSuppHeldPeriod=%u\n" 1227 "dot1xSuppAuthPeriod=%u\n" 1228 "dot1xSuppStartPeriod=%u\n" 1229 "dot1xSuppMaxStart=%u\n" 1230 "dot1xSuppSuppControlledPortStatus=%s\n" 1231 "dot1xSuppBackendPaeState=%d\n", 1232 sm->SUPP_PAE_state, 1233 sm->heldPeriod, 1234 sm->authPeriod, 1235 sm->startPeriod, 1236 sm->maxStart, 1237 sm->suppPortStatus == Authorized ? 1238 "Authorized" : "Unauthorized", 1239 sm->SUPP_BE_state); 1240 1241 if (os_snprintf_error(buflen, ret)) 1242 return 0; 1243 len = ret; 1244 1245 ret = os_snprintf(buf + len, buflen - len, 1246 "dot1xSuppEapolFramesRx=%u\n" 1247 "dot1xSuppEapolFramesTx=%u\n" 1248 "dot1xSuppEapolStartFramesTx=%u\n" 1249 "dot1xSuppEapolLogoffFramesTx=%u\n" 1250 "dot1xSuppEapolRespFramesTx=%u\n" 1251 "dot1xSuppEapolReqIdFramesRx=%u\n" 1252 "dot1xSuppEapolReqFramesRx=%u\n" 1253 "dot1xSuppInvalidEapolFramesRx=%u\n" 1254 "dot1xSuppEapLengthErrorFramesRx=%u\n" 1255 "dot1xSuppLastEapolFrameVersion=%u\n" 1256 "dot1xSuppLastEapolFrameSource=" MACSTR "\n", 1257 sm->dot1xSuppEapolFramesRx, 1258 sm->dot1xSuppEapolFramesTx, 1259 sm->dot1xSuppEapolStartFramesTx, 1260 sm->dot1xSuppEapolLogoffFramesTx, 1261 sm->dot1xSuppEapolRespFramesTx, 1262 sm->dot1xSuppEapolReqIdFramesRx, 1263 sm->dot1xSuppEapolReqFramesRx, 1264 sm->dot1xSuppInvalidEapolFramesRx, 1265 sm->dot1xSuppEapLengthErrorFramesRx, 1266 sm->dot1xSuppLastEapolFrameVersion, 1267 MAC2STR(sm->dot1xSuppLastEapolFrameSource)); 1268 1269 if (os_snprintf_error(buflen - len, ret)) 1270 return len; 1271 len += ret; 1272 1273 return len; 1274 } 1275 #endif /* CONFIG_CTRL_IFACE */ 1276 1277 1278 /** 1279 * eapol_sm_rx_eapol - Process received EAPOL frames 1280 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1281 * @src: Source MAC address of the EAPOL packet 1282 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) 1283 * @len: Length of the EAPOL frame 1284 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine, 1285 * -1 failure 1286 */ 1287 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, 1288 size_t len) 1289 { 1290 const struct ieee802_1x_hdr *hdr; 1291 const struct ieee802_1x_eapol_key *key; 1292 int data_len; 1293 int res = 1; 1294 size_t plen; 1295 1296 if (sm == NULL) 1297 return 0; 1298 sm->dot1xSuppEapolFramesRx++; 1299 if (len < sizeof(*hdr)) { 1300 sm->dot1xSuppInvalidEapolFramesRx++; 1301 return 0; 1302 } 1303 hdr = (const struct ieee802_1x_hdr *) buf; 1304 sm->dot1xSuppLastEapolFrameVersion = hdr->version; 1305 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); 1306 if (hdr->version < EAPOL_VERSION) { 1307 /* TODO: backwards compatibility */ 1308 } 1309 plen = be_to_host16(hdr->length); 1310 if (plen > len - sizeof(*hdr)) { 1311 sm->dot1xSuppEapLengthErrorFramesRx++; 1312 return 0; 1313 } 1314 #ifdef CONFIG_WPS 1315 if (sm->conf.wps && sm->conf.workaround && 1316 plen < len - sizeof(*hdr) && 1317 hdr->type == IEEE802_1X_TYPE_EAP_PACKET && 1318 len - sizeof(*hdr) > sizeof(struct eap_hdr)) { 1319 const struct eap_hdr *ehdr = 1320 (const struct eap_hdr *) (hdr + 1); 1321 u16 elen; 1322 1323 elen = be_to_host16(ehdr->length); 1324 if (elen > plen && elen <= len - sizeof(*hdr)) { 1325 /* 1326 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS 1327 * packets with too short EAPOL header length field 1328 * (14 octets). This is fixed in firmware Ver.1.49. 1329 * As a workaround, fix the EAPOL header based on the 1330 * correct length in the EAP packet. 1331 */ 1332 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL " 1333 "payload length based on EAP header: " 1334 "%d -> %d", (int) plen, elen); 1335 plen = elen; 1336 } 1337 } 1338 #endif /* CONFIG_WPS */ 1339 data_len = plen + sizeof(*hdr); 1340 1341 switch (hdr->type) { 1342 case IEEE802_1X_TYPE_EAP_PACKET: 1343 if (sm->conf.workaround) { 1344 /* 1345 * An AP has been reported to send out EAP message with 1346 * undocumented code 10 at some point near the 1347 * completion of EAP authentication. This can result in 1348 * issues with the unexpected EAP message triggering 1349 * restart of EAPOL authentication. Avoid this by 1350 * skipping the message without advancing the state 1351 * machine. 1352 */ 1353 const struct eap_hdr *ehdr = 1354 (const struct eap_hdr *) (hdr + 1); 1355 if (plen >= sizeof(*ehdr) && ehdr->code == 10) { 1356 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10"); 1357 break; 1358 } 1359 } 1360 1361 if (sm->cached_pmk) { 1362 /* Trying to use PMKSA caching, but Authenticator did 1363 * not seem to have a matching entry. Need to restart 1364 * EAPOL state machines. 1365 */ 1366 eapol_sm_abort_cached(sm); 1367 } 1368 wpabuf_free(sm->eapReqData); 1369 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen); 1370 if (sm->eapReqData) { 1371 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " 1372 "frame"); 1373 sm->eapolEap = true; 1374 #ifdef CONFIG_EAP_PROXY 1375 if (sm->use_eap_proxy) { 1376 eap_proxy_packet_update( 1377 sm->eap_proxy, 1378 wpabuf_mhead_u8(sm->eapReqData), 1379 wpabuf_len(sm->eapReqData)); 1380 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy " 1381 "EAP Req updated"); 1382 } 1383 #endif /* CONFIG_EAP_PROXY */ 1384 eapol_sm_step(sm); 1385 } 1386 break; 1387 case IEEE802_1X_TYPE_EAPOL_KEY: 1388 if (plen < sizeof(*key)) { 1389 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " 1390 "frame received"); 1391 break; 1392 } 1393 key = (const struct ieee802_1x_eapol_key *) (hdr + 1); 1394 if (key->type == EAPOL_KEY_TYPE_WPA || 1395 key->type == EAPOL_KEY_TYPE_RSN) { 1396 /* WPA Supplicant takes care of this frame. */ 1397 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " 1398 "frame in EAPOL state machines"); 1399 res = 0; 1400 break; 1401 } 1402 if (key->type != EAPOL_KEY_TYPE_RC4) { 1403 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " 1404 "EAPOL-Key type %d", key->type); 1405 break; 1406 } 1407 os_free(sm->last_rx_key); 1408 sm->last_rx_key = os_malloc(data_len); 1409 if (sm->last_rx_key) { 1410 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " 1411 "frame"); 1412 os_memcpy(sm->last_rx_key, buf, data_len); 1413 sm->last_rx_key_len = data_len; 1414 sm->rxKey = true; 1415 eapol_sm_step(sm); 1416 } 1417 break; 1418 #ifdef CONFIG_MACSEC 1419 case IEEE802_1X_TYPE_EAPOL_MKA: 1420 wpa_printf(MSG_EXCESSIVE, 1421 "EAPOL type %d will be handled by MKA", 1422 hdr->type); 1423 break; 1424 #endif /* CONFIG_MACSEC */ 1425 default: 1426 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", 1427 hdr->type); 1428 sm->dot1xSuppInvalidEapolFramesRx++; 1429 break; 1430 } 1431 1432 return res; 1433 } 1434 1435 1436 /** 1437 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet 1438 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1439 * 1440 * Notify EAPOL state machine about transmitted EAPOL packet from an external 1441 * component, e.g., WPA. This will update the statistics. 1442 */ 1443 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) 1444 { 1445 if (sm) 1446 sm->dot1xSuppEapolFramesTx++; 1447 } 1448 1449 1450 /** 1451 * eapol_sm_notify_portEnabled - Notification about portEnabled change 1452 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1453 * @enabled: New portEnabled value 1454 * 1455 * Notify EAPOL state machine about new portEnabled value. 1456 */ 1457 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, bool enabled) 1458 { 1459 if (sm == NULL) 1460 return; 1461 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1462 "portEnabled=%d", enabled); 1463 if (sm->portEnabled != enabled) 1464 sm->force_authorized_update = true; 1465 sm->portEnabled = enabled; 1466 eapol_sm_step(sm); 1467 } 1468 1469 1470 /** 1471 * eapol_sm_notify_portValid - Notification about portValid change 1472 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1473 * @valid: New portValid value 1474 * 1475 * Notify EAPOL state machine about new portValid value. 1476 */ 1477 void eapol_sm_notify_portValid(struct eapol_sm *sm, bool valid) 1478 { 1479 if (sm == NULL) 1480 return; 1481 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1482 "portValid=%d", valid); 1483 sm->portValid = valid; 1484 eapol_sm_step(sm); 1485 } 1486 1487 1488 /** 1489 * eapol_sm_notify_eap_success - Notification of external EAP success trigger 1490 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1491 * @success: %true = set success, %false = clear success 1492 * 1493 * Notify the EAPOL state machine that external event has forced EAP state to 1494 * success (success = %true). This can be cleared by setting success = %false. 1495 * 1496 * This function is called to update EAP state when WPA-PSK key handshake has 1497 * been completed successfully since WPA-PSK does not use EAP state machine. 1498 */ 1499 void eapol_sm_notify_eap_success(struct eapol_sm *sm, bool success) 1500 { 1501 if (sm == NULL) 1502 return; 1503 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1504 "EAP success=%d", success); 1505 sm->eapSuccess = success; 1506 sm->altAccept = success; 1507 if (success) 1508 eap_notify_success(sm->eap); 1509 eapol_sm_step(sm); 1510 } 1511 1512 1513 /** 1514 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger 1515 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1516 * @fail: %true = set failure, %false = clear failure 1517 * 1518 * Notify EAPOL state machine that external event has forced EAP state to 1519 * failure (fail = %true). This can be cleared by setting fail = %false. 1520 */ 1521 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail) 1522 { 1523 if (sm == NULL) 1524 return; 1525 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1526 "EAP fail=%d", fail); 1527 sm->eapFail = fail; 1528 sm->altReject = fail; 1529 eapol_sm_step(sm); 1530 } 1531 1532 1533 /** 1534 * eapol_sm_notify_config - Notification of EAPOL configuration change 1535 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1536 * @config: Pointer to current network EAP configuration 1537 * @conf: Pointer to EAPOL configuration data 1538 * 1539 * Notify EAPOL state machine that configuration has changed. config will be 1540 * stored as a backpointer to network configuration. This can be %NULL to clear 1541 * the stored pointed. conf will be copied to local EAPOL/EAP configuration 1542 * data. If conf is %NULL, this part of the configuration change will be 1543 * skipped. 1544 */ 1545 void eapol_sm_notify_config(struct eapol_sm *sm, 1546 struct eap_peer_config *config, 1547 const struct eapol_config *conf) 1548 { 1549 if (sm == NULL) 1550 return; 1551 1552 sm->config = config; 1553 #ifdef CONFIG_EAP_PROXY 1554 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0; 1555 #endif /* CONFIG_EAP_PROXY */ 1556 1557 if (conf == NULL) 1558 return; 1559 1560 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; 1561 sm->conf.required_keys = conf->required_keys; 1562 sm->conf.fast_reauth = conf->fast_reauth; 1563 sm->conf.workaround = conf->workaround; 1564 sm->conf.wps = conf->wps; 1565 #ifdef CONFIG_EAP_PROXY 1566 if (sm->use_eap_proxy) { 1567 /* Using EAP Proxy, so skip EAP state machine update */ 1568 return; 1569 } 1570 #endif /* CONFIG_EAP_PROXY */ 1571 if (sm->eap) { 1572 eap_set_fast_reauth(sm->eap, conf->fast_reauth); 1573 eap_set_workaround(sm->eap, conf->workaround); 1574 eap_set_force_disabled(sm->eap, conf->eap_disabled); 1575 eap_set_external_sim(sm->eap, conf->external_sim); 1576 } 1577 } 1578 1579 1580 /** 1581 * eapol_sm_get_key - Get master session key (MSK) from EAP 1582 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1583 * @key: Pointer for key buffer 1584 * @len: Number of bytes to copy to key 1585 * Returns: 0 on success (len of key available), maximum available key len 1586 * (>0) if key is available but it is shorter than len, or -1 on failure. 1587 * 1588 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key 1589 * is available only after a successful authentication. 1590 */ 1591 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) 1592 { 1593 const u8 *eap_key; 1594 size_t eap_len; 1595 1596 #ifdef CONFIG_EAP_PROXY 1597 if (sm && sm->use_eap_proxy) { 1598 /* Get key from EAP proxy */ 1599 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) { 1600 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); 1601 return -1; 1602 } 1603 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len); 1604 if (eap_key == NULL) { 1605 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get " 1606 "eapKeyData"); 1607 return -1; 1608 } 1609 goto key_fetched; 1610 } 1611 #endif /* CONFIG_EAP_PROXY */ 1612 if (sm == NULL || !eap_key_available(sm->eap)) { 1613 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); 1614 return -1; 1615 } 1616 eap_key = eap_get_eapKeyData(sm->eap, &eap_len); 1617 if (eap_key == NULL) { 1618 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData"); 1619 return -1; 1620 } 1621 #ifdef CONFIG_EAP_PROXY 1622 key_fetched: 1623 #endif /* CONFIG_EAP_PROXY */ 1624 if (len > eap_len) { 1625 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not " 1626 "available (len=%lu)", 1627 (unsigned long) len, (unsigned long) eap_len); 1628 return eap_len; 1629 } 1630 os_memcpy(key, eap_key, len); 1631 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)", 1632 (unsigned long) len); 1633 return 0; 1634 } 1635 1636 1637 /** 1638 * eapol_sm_get_session_id - Get EAP Session-Id 1639 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1640 * @len: Pointer to variable that will be set to number of bytes in the session 1641 * Returns: Pointer to the EAP Session-Id or %NULL on failure 1642 * 1643 * The Session-Id is available only after a successful authentication. 1644 */ 1645 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len) 1646 { 1647 if (sm == NULL || !eap_key_available(sm->eap)) { 1648 wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available"); 1649 return NULL; 1650 } 1651 return eap_get_eapSessionId(sm->eap, len); 1652 } 1653 1654 1655 /** 1656 * eapol_sm_notify_logoff - Notification of logon/logoff commands 1657 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1658 * @logoff: Whether command was logoff 1659 * 1660 * Notify EAPOL state machines that user requested logon/logoff. 1661 */ 1662 void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff) 1663 { 1664 if (sm) { 1665 sm->userLogoff = logoff; 1666 if (!logoff) { 1667 /* If there is a delayed txStart queued, start now. */ 1668 sm->startWhen = 0; 1669 } 1670 eapol_sm_step(sm); 1671 } 1672 } 1673 1674 1675 /** 1676 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching 1677 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1678 * 1679 * Notify EAPOL state machines that PMKSA caching was successful. This is used 1680 * to move EAPOL and EAP state machines into authenticated/successful state. 1681 */ 1682 void eapol_sm_notify_cached(struct eapol_sm *sm) 1683 { 1684 if (sm == NULL) 1685 return; 1686 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); 1687 sm->eapSuccess = true; 1688 eap_notify_success(sm->eap); 1689 eapol_sm_step(sm); 1690 } 1691 1692 1693 /** 1694 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching 1695 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1696 * 1697 * Notify EAPOL state machines if PMKSA caching is used. 1698 */ 1699 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm) 1700 { 1701 if (sm == NULL) 1702 return; 1703 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); 1704 sm->cached_pmk = true; 1705 } 1706 1707 1708 static void eapol_sm_abort_cached(struct eapol_sm *sm) 1709 { 1710 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, " 1711 "doing full EAP authentication"); 1712 if (sm == NULL) 1713 return; 1714 sm->cached_pmk = false; 1715 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; 1716 eapol_sm_set_port_unauthorized(sm); 1717 1718 /* Make sure we do not start sending EAPOL-Start frames first, but 1719 * instead move to RESTART state to start EAPOL authentication. */ 1720 sm->startWhen = 3; 1721 eapol_enable_timer_tick(sm); 1722 1723 if (sm->ctx->aborted_cached) 1724 sm->ctx->aborted_cached(sm->ctx->ctx); 1725 } 1726 1727 1728 /** 1729 * eapol_sm_register_scard_ctx - Notification of smart card context 1730 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1731 * @ctx: Context data for smart card operations 1732 * 1733 * Notify EAPOL state machines of context data for smart card operations. This 1734 * context data will be used as a parameter for scard_*() functions. 1735 */ 1736 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx) 1737 { 1738 if (sm) { 1739 sm->ctx->scard_ctx = ctx; 1740 eap_register_scard_ctx(sm->eap, ctx); 1741 } 1742 } 1743 1744 1745 /** 1746 * eapol_sm_notify_portControl - Notification of portControl changes 1747 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1748 * @portControl: New value for portControl variable 1749 * 1750 * Notify EAPOL state machines that portControl variable has changed. 1751 */ 1752 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl) 1753 { 1754 if (sm == NULL) 1755 return; 1756 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1757 "portControl=%s", eapol_port_control(portControl)); 1758 sm->portControl = portControl; 1759 eapol_sm_step(sm); 1760 } 1761 1762 1763 /** 1764 * eapol_sm_notify_ctrl_attached - Notification of attached monitor 1765 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1766 * 1767 * Notify EAPOL state machines that a monitor was attached to the control 1768 * interface to trigger re-sending of pending requests for user input. 1769 */ 1770 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) 1771 { 1772 if (sm == NULL) 1773 return; 1774 eap_sm_notify_ctrl_attached(sm->eap); 1775 } 1776 1777 1778 /** 1779 * eapol_sm_notify_ctrl_response - Notification of received user input 1780 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1781 * 1782 * Notify EAPOL state machines that a control response, i.e., user 1783 * input, was received in order to trigger retrying of a pending EAP request. 1784 */ 1785 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) 1786 { 1787 if (sm == NULL) 1788 return; 1789 if (sm->eapReqData && !sm->eapReq) { 1790 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " 1791 "input) notification - retrying pending EAP " 1792 "Request"); 1793 sm->eapolEap = true; 1794 sm->eapReq = true; 1795 eapol_sm_step(sm); 1796 } 1797 } 1798 1799 1800 /** 1801 * eapol_sm_request_reauth - Request reauthentication 1802 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1803 * 1804 * This function can be used to request EAPOL reauthentication, e.g., when the 1805 * current PMKSA entry is nearing expiration. 1806 */ 1807 void eapol_sm_request_reauth(struct eapol_sm *sm) 1808 { 1809 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED) 1810 return; 1811 eapol_sm_txStart(sm); 1812 } 1813 1814 1815 /** 1816 * eapol_sm_notify_lower_layer_success - Notification of lower layer success 1817 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1818 * @in_eapol_sm: Whether the caller is already running inside EAPOL state 1819 * machine loop (eapol_sm_step()) 1820 * 1821 * Notify EAPOL (and EAP) state machines that a lower layer has detected a 1822 * successful authentication. This is used to recover from dropped EAP-Success 1823 * messages. 1824 */ 1825 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm) 1826 { 1827 if (sm == NULL) 1828 return; 1829 eap_notify_lower_layer_success(sm->eap); 1830 if (!in_eapol_sm) 1831 eapol_sm_step(sm); 1832 } 1833 1834 1835 /** 1836 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid 1837 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1838 */ 1839 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) 1840 { 1841 if (sm) 1842 eap_invalidate_cached_session(sm->eap); 1843 } 1844 1845 1846 static struct eap_peer_config * eapol_sm_get_config(void *ctx) 1847 { 1848 struct eapol_sm *sm = ctx; 1849 return sm ? sm->config : NULL; 1850 } 1851 1852 1853 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) 1854 { 1855 struct eapol_sm *sm = ctx; 1856 if (sm == NULL || sm->eapReqData == NULL) 1857 return NULL; 1858 1859 return sm->eapReqData; 1860 } 1861 1862 1863 static bool eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) 1864 { 1865 struct eapol_sm *sm = ctx; 1866 if (sm == NULL) 1867 return false; 1868 switch (variable) { 1869 case EAPOL_eapSuccess: 1870 return sm->eapSuccess; 1871 case EAPOL_eapRestart: 1872 return sm->eapRestart; 1873 case EAPOL_eapFail: 1874 return sm->eapFail; 1875 case EAPOL_eapResp: 1876 return sm->eapResp; 1877 case EAPOL_eapNoResp: 1878 return sm->eapNoResp; 1879 case EAPOL_eapReq: 1880 return sm->eapReq; 1881 case EAPOL_portEnabled: 1882 return sm->portEnabled; 1883 case EAPOL_altAccept: 1884 return sm->altAccept; 1885 case EAPOL_altReject: 1886 return sm->altReject; 1887 case EAPOL_eapTriggerStart: 1888 return sm->eapTriggerStart; 1889 } 1890 return false; 1891 } 1892 1893 1894 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, 1895 bool value) 1896 { 1897 struct eapol_sm *sm = ctx; 1898 if (sm == NULL) 1899 return; 1900 switch (variable) { 1901 case EAPOL_eapSuccess: 1902 sm->eapSuccess = value; 1903 break; 1904 case EAPOL_eapRestart: 1905 sm->eapRestart = value; 1906 break; 1907 case EAPOL_eapFail: 1908 sm->eapFail = value; 1909 break; 1910 case EAPOL_eapResp: 1911 sm->eapResp = value; 1912 break; 1913 case EAPOL_eapNoResp: 1914 sm->eapNoResp = value; 1915 break; 1916 case EAPOL_eapReq: 1917 sm->eapReq = value; 1918 break; 1919 case EAPOL_portEnabled: 1920 sm->portEnabled = value; 1921 break; 1922 case EAPOL_altAccept: 1923 sm->altAccept = value; 1924 break; 1925 case EAPOL_altReject: 1926 sm->altReject = value; 1927 break; 1928 case EAPOL_eapTriggerStart: 1929 sm->eapTriggerStart = value; 1930 break; 1931 } 1932 } 1933 1934 1935 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable) 1936 { 1937 struct eapol_sm *sm = ctx; 1938 if (sm == NULL) 1939 return 0; 1940 switch (variable) { 1941 case EAPOL_idleWhile: 1942 return sm->idleWhile; 1943 } 1944 return 0; 1945 } 1946 1947 1948 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable, 1949 unsigned int value) 1950 { 1951 struct eapol_sm *sm = ctx; 1952 if (sm == NULL) 1953 return; 1954 switch (variable) { 1955 case EAPOL_idleWhile: 1956 sm->idleWhile = value; 1957 if (sm->idleWhile > 0) 1958 eapol_enable_timer_tick(sm); 1959 break; 1960 } 1961 } 1962 1963 1964 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob) 1965 { 1966 #ifndef CONFIG_NO_CONFIG_BLOBS 1967 struct eapol_sm *sm = ctx; 1968 if (sm && sm->ctx && sm->ctx->set_config_blob) 1969 sm->ctx->set_config_blob(sm->ctx->ctx, blob); 1970 #endif /* CONFIG_NO_CONFIG_BLOBS */ 1971 } 1972 1973 1974 static const struct wpa_config_blob * 1975 eapol_sm_get_config_blob(void *ctx, const char *name) 1976 { 1977 #ifndef CONFIG_NO_CONFIG_BLOBS 1978 struct eapol_sm *sm = ctx; 1979 if (sm && sm->ctx && sm->ctx->get_config_blob) 1980 return sm->ctx->get_config_blob(sm->ctx->ctx, name); 1981 else 1982 return NULL; 1983 #else /* CONFIG_NO_CONFIG_BLOBS */ 1984 return NULL; 1985 #endif /* CONFIG_NO_CONFIG_BLOBS */ 1986 } 1987 1988 1989 static void eapol_sm_notify_pending(void *ctx) 1990 { 1991 struct eapol_sm *sm = ctx; 1992 if (sm == NULL) 1993 return; 1994 if (sm->eapReqData && !sm->eapReq) { 1995 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " 1996 "state machine - retrying pending EAP Request"); 1997 sm->eapolEap = true; 1998 sm->eapReq = true; 1999 eapol_sm_step(sm); 2000 } 2001 } 2002 2003 2004 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 2005 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field, 2006 const char *txt) 2007 { 2008 struct eapol_sm *sm = ctx; 2009 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed"); 2010 if (sm->ctx->eap_param_needed) 2011 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt); 2012 } 2013 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 2014 #define eapol_sm_eap_param_needed NULL 2015 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 2016 2017 static void eapol_sm_notify_cert(void *ctx, struct tls_cert_data *cert, 2018 const char *cert_hash) 2019 { 2020 struct eapol_sm *sm = ctx; 2021 if (sm->ctx->cert_cb) 2022 sm->ctx->cert_cb(sm->ctx->ctx, cert, cert_hash); 2023 } 2024 2025 2026 static void eapol_sm_notify_status(void *ctx, const char *status, 2027 const char *parameter) 2028 { 2029 struct eapol_sm *sm = ctx; 2030 2031 if (sm->ctx->status_cb) 2032 sm->ctx->status_cb(sm->ctx->ctx, status, parameter); 2033 } 2034 2035 2036 static void eapol_sm_notify_eap_error(void *ctx, int error_code) 2037 { 2038 struct eapol_sm *sm = ctx; 2039 2040 if (sm->ctx->eap_error_cb) 2041 sm->ctx->eap_error_cb(sm->ctx->ctx, error_code); 2042 } 2043 2044 2045 #ifdef CONFIG_EAP_PROXY 2046 2047 static void eapol_sm_eap_proxy_cb(void *ctx) 2048 { 2049 struct eapol_sm *sm = ctx; 2050 2051 if (sm->ctx->eap_proxy_cb) 2052 sm->ctx->eap_proxy_cb(sm->ctx->ctx); 2053 } 2054 2055 2056 static void 2057 eapol_sm_eap_proxy_notify_sim_status(void *ctx, 2058 enum eap_proxy_sim_state sim_state) 2059 { 2060 struct eapol_sm *sm = ctx; 2061 2062 if (sm->ctx->eap_proxy_notify_sim_status) 2063 sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state); 2064 } 2065 2066 #endif /* CONFIG_EAP_PROXY */ 2067 2068 2069 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len) 2070 { 2071 struct eapol_sm *sm = ctx; 2072 2073 if (sm->ctx->set_anon_id) 2074 sm->ctx->set_anon_id(sm->ctx->ctx, id, len); 2075 } 2076 2077 2078 static const struct eapol_callbacks eapol_cb = 2079 { 2080 eapol_sm_get_config, 2081 eapol_sm_get_bool, 2082 eapol_sm_set_bool, 2083 eapol_sm_get_int, 2084 eapol_sm_set_int, 2085 eapol_sm_get_eapReqData, 2086 eapol_sm_set_config_blob, 2087 eapol_sm_get_config_blob, 2088 eapol_sm_notify_pending, 2089 eapol_sm_eap_param_needed, 2090 eapol_sm_notify_cert, 2091 eapol_sm_notify_status, 2092 eapol_sm_notify_eap_error, 2093 #ifdef CONFIG_EAP_PROXY 2094 eapol_sm_eap_proxy_cb, 2095 eapol_sm_eap_proxy_notify_sim_status, 2096 eapol_sm_get_eap_proxy_imsi, 2097 #endif /* CONFIG_EAP_PROXY */ 2098 eapol_sm_set_anon_id 2099 }; 2100 2101 2102 /** 2103 * eapol_sm_init - Initialize EAPOL state machine 2104 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer 2105 * and EAPOL state machine will free it in eapol_sm_deinit() 2106 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure 2107 * 2108 * Allocate and initialize an EAPOL state machine. 2109 */ 2110 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) 2111 { 2112 struct eapol_sm *sm; 2113 struct eap_config conf; 2114 sm = os_zalloc(sizeof(*sm)); 2115 if (sm == NULL) 2116 return NULL; 2117 sm->ctx = ctx; 2118 2119 sm->portControl = Auto; 2120 2121 /* Supplicant PAE state machine */ 2122 sm->heldPeriod = 60; 2123 sm->startPeriod = 30; 2124 sm->maxStart = 3; 2125 2126 /* Supplicant Backend state machine */ 2127 sm->authPeriod = 30; 2128 2129 os_memset(&conf, 0, sizeof(conf)); 2130 conf.opensc_engine_path = ctx->opensc_engine_path; 2131 conf.pkcs11_engine_path = ctx->pkcs11_engine_path; 2132 conf.pkcs11_module_path = ctx->pkcs11_module_path; 2133 conf.openssl_ciphers = ctx->openssl_ciphers; 2134 conf.wps = ctx->wps; 2135 conf.cert_in_cb = ctx->cert_in_cb; 2136 2137 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); 2138 if (sm->eap == NULL) { 2139 os_free(sm); 2140 return NULL; 2141 } 2142 2143 #ifdef CONFIG_EAP_PROXY 2144 sm->use_eap_proxy = false; 2145 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx); 2146 if (sm->eap_proxy == NULL) { 2147 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy"); 2148 } 2149 #endif /* CONFIG_EAP_PROXY */ 2150 2151 /* Initialize EAPOL state machines */ 2152 sm->force_authorized_update = true; 2153 sm->initialize = true; 2154 eapol_sm_step(sm); 2155 sm->initialize = false; 2156 eapol_sm_step(sm); 2157 2158 if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0) 2159 sm->timer_tick_enabled = 1; 2160 2161 return sm; 2162 } 2163 2164 2165 /** 2166 * eapol_sm_deinit - Deinitialize EAPOL state machine 2167 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 2168 * 2169 * Deinitialize and free EAPOL state machine. 2170 */ 2171 void eapol_sm_deinit(struct eapol_sm *sm) 2172 { 2173 if (sm == NULL) 2174 return; 2175 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); 2176 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 2177 eap_peer_sm_deinit(sm->eap); 2178 #ifdef CONFIG_EAP_PROXY 2179 eap_proxy_deinit(sm->eap_proxy); 2180 #endif /* CONFIG_EAP_PROXY */ 2181 os_free(sm->last_rx_key); 2182 wpabuf_free(sm->eapReqData); 2183 os_free(sm->ctx); 2184 os_free(sm); 2185 } 2186 2187 2188 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, 2189 struct ext_password_data *ext) 2190 { 2191 if (sm && sm->eap) 2192 eap_sm_set_ext_pw_ctx(sm->eap, ext); 2193 } 2194 2195 2196 int eapol_sm_failed(struct eapol_sm *sm) 2197 { 2198 if (sm == NULL) 2199 return 0; 2200 return !sm->eapSuccess && sm->eapFail; 2201 } 2202 2203 2204 #ifdef CONFIG_EAP_PROXY 2205 int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len) 2206 { 2207 struct eapol_sm *sm = ctx; 2208 2209 if (sm->eap_proxy == NULL) 2210 return -1; 2211 return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len); 2212 } 2213 #endif /* CONFIG_EAP_PROXY */ 2214 2215 2216 void eapol_sm_erp_flush(struct eapol_sm *sm) 2217 { 2218 if (sm) 2219 eap_peer_erp_free_keys(sm->eap); 2220 } 2221 2222 2223 struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm) 2224 { 2225 #ifdef CONFIG_ERP 2226 if (!sm) 2227 return NULL; 2228 return eap_peer_build_erp_reauth_start(sm->eap, 0); 2229 #else /* CONFIG_ERP */ 2230 return NULL; 2231 #endif /* CONFIG_ERP */ 2232 } 2233 2234 2235 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf, 2236 size_t len) 2237 { 2238 #ifdef CONFIG_ERP 2239 if (!sm) 2240 return; 2241 eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len); 2242 #endif /* CONFIG_ERP */ 2243 } 2244 2245 2246 int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num) 2247 { 2248 #ifdef CONFIG_ERP 2249 if (!sm) 2250 return -1; 2251 return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num); 2252 #else /* CONFIG_ERP */ 2253 return -1; 2254 #endif /* CONFIG_ERP */ 2255 } 2256 2257 2258 int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config, 2259 const u8 **username, size_t *username_len, 2260 const u8 **realm, size_t *realm_len, 2261 u16 *erp_next_seq_num, const u8 **rrk, 2262 size_t *rrk_len) 2263 { 2264 #ifdef CONFIG_ERP 2265 if (!sm) 2266 return -1; 2267 return eap_peer_get_erp_info(sm->eap, config, username, username_len, 2268 realm, realm_len, erp_next_seq_num, rrk, 2269 rrk_len); 2270 #else /* CONFIG_ERP */ 2271 return -1; 2272 #endif /* CONFIG_ERP */ 2273 } 2274