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