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