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