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