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