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