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