eapol_supp_sm.c revision 4ce9c87407c036fc83eb5a6044ddf976c86f53fc
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->conf.workaround) { 1261 /* 1262 * An AP has been reported to send out EAP message with 1263 * undocumented code 10 at some point near the 1264 * completion of EAP authentication. This can result in 1265 * issues with the unexpected EAP message triggering 1266 * restart of EAPOL authentication. Avoid this by 1267 * skipping the message without advancing the state 1268 * machine. 1269 */ 1270 const struct eap_hdr *ehdr = 1271 (const struct eap_hdr *) (hdr + 1); 1272 if (plen >= sizeof(*ehdr) && ehdr->code == 10) { 1273 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10"); 1274 break; 1275 } 1276 } 1277 1278 if (sm->cached_pmk) { 1279 /* Trying to use PMKSA caching, but Authenticator did 1280 * not seem to have a matching entry. Need to restart 1281 * EAPOL state machines. 1282 */ 1283 eapol_sm_abort_cached(sm); 1284 } 1285 wpabuf_free(sm->eapReqData); 1286 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen); 1287 if (sm->eapReqData) { 1288 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " 1289 "frame"); 1290 sm->eapolEap = TRUE; 1291#ifdef CONFIG_EAP_PROXY 1292 if (sm->use_eap_proxy) { 1293 eap_proxy_packet_update( 1294 sm->eap_proxy, 1295 wpabuf_mhead_u8(sm->eapReqData), 1296 wpabuf_len(sm->eapReqData)); 1297 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy " 1298 "EAP Req updated"); 1299 } 1300#endif /* CONFIG_EAP_PROXY */ 1301 eapol_sm_step(sm); 1302 } 1303 break; 1304 case IEEE802_1X_TYPE_EAPOL_KEY: 1305 if (plen < sizeof(*key)) { 1306 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " 1307 "frame received"); 1308 break; 1309 } 1310 key = (const struct ieee802_1x_eapol_key *) (hdr + 1); 1311 if (key->type == EAPOL_KEY_TYPE_WPA || 1312 key->type == EAPOL_KEY_TYPE_RSN) { 1313 /* WPA Supplicant takes care of this frame. */ 1314 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " 1315 "frame in EAPOL state machines"); 1316 res = 0; 1317 break; 1318 } 1319 if (key->type != EAPOL_KEY_TYPE_RC4) { 1320 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " 1321 "EAPOL-Key type %d", key->type); 1322 break; 1323 } 1324 os_free(sm->last_rx_key); 1325 sm->last_rx_key = os_malloc(data_len); 1326 if (sm->last_rx_key) { 1327 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " 1328 "frame"); 1329 os_memcpy(sm->last_rx_key, buf, data_len); 1330 sm->last_rx_key_len = data_len; 1331 sm->rxKey = TRUE; 1332 eapol_sm_step(sm); 1333 } 1334 break; 1335 default: 1336 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", 1337 hdr->type); 1338 sm->dot1xSuppInvalidEapolFramesRx++; 1339 break; 1340 } 1341 1342 return res; 1343} 1344 1345 1346/** 1347 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet 1348 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1349 * 1350 * Notify EAPOL state machine about transmitted EAPOL packet from an external 1351 * component, e.g., WPA. This will update the statistics. 1352 */ 1353void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) 1354{ 1355 if (sm) 1356 sm->dot1xSuppEapolFramesTx++; 1357} 1358 1359 1360/** 1361 * eapol_sm_notify_portEnabled - Notification about portEnabled change 1362 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1363 * @enabled: New portEnabled value 1364 * 1365 * Notify EAPOL state machine about new portEnabled value. 1366 */ 1367void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) 1368{ 1369 if (sm == NULL) 1370 return; 1371 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1372 "portEnabled=%d", enabled); 1373 sm->portEnabled = enabled; 1374 eapol_sm_step(sm); 1375} 1376 1377 1378/** 1379 * eapol_sm_notify_portValid - Notification about portValid change 1380 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1381 * @valid: New portValid value 1382 * 1383 * Notify EAPOL state machine about new portValid value. 1384 */ 1385void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) 1386{ 1387 if (sm == NULL) 1388 return; 1389 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1390 "portValid=%d", valid); 1391 sm->portValid = valid; 1392 eapol_sm_step(sm); 1393} 1394 1395 1396/** 1397 * eapol_sm_notify_eap_success - Notification of external EAP success trigger 1398 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1399 * @success: %TRUE = set success, %FALSE = clear success 1400 * 1401 * Notify the EAPOL state machine that external event has forced EAP state to 1402 * success (success = %TRUE). This can be cleared by setting success = %FALSE. 1403 * 1404 * This function is called to update EAP state when WPA-PSK key handshake has 1405 * been completed successfully since WPA-PSK does not use EAP state machine. 1406 */ 1407void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) 1408{ 1409 if (sm == NULL) 1410 return; 1411 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1412 "EAP success=%d", success); 1413 sm->eapSuccess = success; 1414 sm->altAccept = success; 1415 if (success) 1416 eap_notify_success(sm->eap); 1417 eapol_sm_step(sm); 1418} 1419 1420 1421/** 1422 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger 1423 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1424 * @fail: %TRUE = set failure, %FALSE = clear failure 1425 * 1426 * Notify EAPOL state machine that external event has forced EAP state to 1427 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. 1428 */ 1429void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) 1430{ 1431 if (sm == NULL) 1432 return; 1433 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1434 "EAP fail=%d", fail); 1435 sm->eapFail = fail; 1436 sm->altReject = fail; 1437 eapol_sm_step(sm); 1438} 1439 1440 1441/** 1442 * eapol_sm_notify_config - Notification of EAPOL configuration change 1443 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1444 * @config: Pointer to current network EAP configuration 1445 * @conf: Pointer to EAPOL configuration data 1446 * 1447 * Notify EAPOL state machine that configuration has changed. config will be 1448 * stored as a backpointer to network configuration. This can be %NULL to clear 1449 * the stored pointed. conf will be copied to local EAPOL/EAP configuration 1450 * data. If conf is %NULL, this part of the configuration change will be 1451 * skipped. 1452 */ 1453void eapol_sm_notify_config(struct eapol_sm *sm, 1454 struct eap_peer_config *config, 1455 const struct eapol_config *conf) 1456{ 1457 if (sm == NULL) 1458 return; 1459 1460 sm->config = config; 1461#ifdef CONFIG_EAP_PROXY 1462 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0; 1463#endif /* CONFIG_EAP_PROXY */ 1464 1465 if (conf == NULL) 1466 return; 1467 1468 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; 1469 sm->conf.required_keys = conf->required_keys; 1470 sm->conf.fast_reauth = conf->fast_reauth; 1471 sm->conf.workaround = conf->workaround; 1472#ifdef CONFIG_EAP_PROXY 1473 if (sm->use_eap_proxy) { 1474 /* Using EAP Proxy, so skip EAP state machine update */ 1475 return; 1476 } 1477#endif /* CONFIG_EAP_PROXY */ 1478 if (sm->eap) { 1479 eap_set_fast_reauth(sm->eap, conf->fast_reauth); 1480 eap_set_workaround(sm->eap, conf->workaround); 1481 eap_set_force_disabled(sm->eap, conf->eap_disabled); 1482 eap_set_external_sim(sm->eap, conf->external_sim); 1483 } 1484} 1485 1486 1487/** 1488 * eapol_sm_get_key - Get master session key (MSK) from EAP 1489 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1490 * @key: Pointer for key buffer 1491 * @len: Number of bytes to copy to key 1492 * Returns: 0 on success (len of key available), maximum available key len 1493 * (>0) if key is available but it is shorter than len, or -1 on failure. 1494 * 1495 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key 1496 * is available only after a successful authentication. 1497 */ 1498int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) 1499{ 1500 const u8 *eap_key; 1501 size_t eap_len; 1502 1503#ifdef CONFIG_EAP_PROXY 1504 if (sm->use_eap_proxy) { 1505 /* Get key from EAP proxy */ 1506 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) { 1507 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); 1508 return -1; 1509 } 1510 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len); 1511 if (eap_key == NULL) { 1512 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get " 1513 "eapKeyData"); 1514 return -1; 1515 } 1516 goto key_fetched; 1517 } 1518#endif /* CONFIG_EAP_PROXY */ 1519 if (sm == NULL || !eap_key_available(sm->eap)) { 1520 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); 1521 return -1; 1522 } 1523 eap_key = eap_get_eapKeyData(sm->eap, &eap_len); 1524 if (eap_key == NULL) { 1525 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData"); 1526 return -1; 1527 } 1528#ifdef CONFIG_EAP_PROXY 1529key_fetched: 1530#endif /* CONFIG_EAP_PROXY */ 1531 if (len > eap_len) { 1532 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not " 1533 "available (len=%lu)", 1534 (unsigned long) len, (unsigned long) eap_len); 1535 return eap_len; 1536 } 1537 os_memcpy(key, eap_key, len); 1538 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)", 1539 (unsigned long) len); 1540 return 0; 1541} 1542 1543 1544/** 1545 * eapol_sm_notify_logoff - Notification of logon/logoff commands 1546 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1547 * @logoff: Whether command was logoff 1548 * 1549 * Notify EAPOL state machines that user requested logon/logoff. 1550 */ 1551void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) 1552{ 1553 if (sm) { 1554 sm->userLogoff = logoff; 1555 if (!logoff) { 1556 /* If there is a delayed txStart queued, start now. */ 1557 sm->startWhen = 0; 1558 } 1559 eapol_sm_step(sm); 1560 } 1561} 1562 1563 1564/** 1565 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching 1566 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1567 * 1568 * Notify EAPOL state machines that PMKSA caching was successful. This is used 1569 * to move EAPOL and EAP state machines into authenticated/successful state. 1570 */ 1571void eapol_sm_notify_cached(struct eapol_sm *sm) 1572{ 1573 if (sm == NULL) 1574 return; 1575 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); 1576 sm->eapSuccess = TRUE; 1577 eap_notify_success(sm->eap); 1578 eapol_sm_step(sm); 1579} 1580 1581 1582/** 1583 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching 1584 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1585 * @attempt: Whether PMKSA caching is tried 1586 * 1587 * Notify EAPOL state machines whether PMKSA caching is used. 1588 */ 1589void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt) 1590{ 1591 if (sm == NULL) 1592 return; 1593 if (attempt) { 1594 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); 1595 sm->cached_pmk = TRUE; 1596 } else { 1597 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA"); 1598 sm->cached_pmk = FALSE; 1599 } 1600} 1601 1602 1603static void eapol_sm_abort_cached(struct eapol_sm *sm) 1604{ 1605 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, " 1606 "doing full EAP authentication"); 1607 if (sm == NULL) 1608 return; 1609 sm->cached_pmk = FALSE; 1610 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; 1611 sm->suppPortStatus = Unauthorized; 1612 eapol_sm_set_port_unauthorized(sm); 1613 1614 /* Make sure we do not start sending EAPOL-Start frames first, but 1615 * instead move to RESTART state to start EAPOL authentication. */ 1616 sm->startWhen = 3; 1617 eapol_enable_timer_tick(sm); 1618 1619 if (sm->ctx->aborted_cached) 1620 sm->ctx->aborted_cached(sm->ctx->ctx); 1621} 1622 1623 1624/** 1625 * eapol_sm_register_scard_ctx - Notification of smart card context 1626 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1627 * @ctx: Context data for smart card operations 1628 * 1629 * Notify EAPOL state machines of context data for smart card operations. This 1630 * context data will be used as a parameter for scard_*() functions. 1631 */ 1632void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx) 1633{ 1634 if (sm) { 1635 sm->ctx->scard_ctx = ctx; 1636 eap_register_scard_ctx(sm->eap, ctx); 1637 } 1638} 1639 1640 1641/** 1642 * eapol_sm_notify_portControl - Notification of portControl changes 1643 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1644 * @portControl: New value for portControl variable 1645 * 1646 * Notify EAPOL state machines that portControl variable has changed. 1647 */ 1648void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl) 1649{ 1650 if (sm == NULL) 1651 return; 1652 wpa_printf(MSG_DEBUG, "EAPOL: External notification - " 1653 "portControl=%s", eapol_port_control(portControl)); 1654 sm->portControl = portControl; 1655 eapol_sm_step(sm); 1656} 1657 1658 1659/** 1660 * eapol_sm_notify_ctrl_attached - Notification of attached monitor 1661 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1662 * 1663 * Notify EAPOL state machines that a monitor was attached to the control 1664 * interface to trigger re-sending of pending requests for user input. 1665 */ 1666void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) 1667{ 1668 if (sm == NULL) 1669 return; 1670 eap_sm_notify_ctrl_attached(sm->eap); 1671} 1672 1673 1674/** 1675 * eapol_sm_notify_ctrl_response - Notification of received user input 1676 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1677 * 1678 * Notify EAPOL state machines that a control response, i.e., user 1679 * input, was received in order to trigger retrying of a pending EAP request. 1680 */ 1681void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) 1682{ 1683 if (sm == NULL) 1684 return; 1685 if (sm->eapReqData && !sm->eapReq) { 1686 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " 1687 "input) notification - retrying pending EAP " 1688 "Request"); 1689 sm->eapolEap = TRUE; 1690 sm->eapReq = TRUE; 1691 eapol_sm_step(sm); 1692 } 1693} 1694 1695 1696/** 1697 * eapol_sm_request_reauth - Request reauthentication 1698 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1699 * 1700 * This function can be used to request EAPOL reauthentication, e.g., when the 1701 * current PMKSA entry is nearing expiration. 1702 */ 1703void eapol_sm_request_reauth(struct eapol_sm *sm) 1704{ 1705 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED) 1706 return; 1707 eapol_sm_txStart(sm); 1708} 1709 1710 1711/** 1712 * eapol_sm_notify_lower_layer_success - Notification of lower layer success 1713 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1714 * @in_eapol_sm: Whether the caller is already running inside EAPOL state 1715 * machine loop (eapol_sm_step()) 1716 * 1717 * Notify EAPOL (and EAP) state machines that a lower layer has detected a 1718 * successful authentication. This is used to recover from dropped EAP-Success 1719 * messages. 1720 */ 1721void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm) 1722{ 1723 if (sm == NULL) 1724 return; 1725 eap_notify_lower_layer_success(sm->eap); 1726 if (!in_eapol_sm) 1727 eapol_sm_step(sm); 1728} 1729 1730 1731/** 1732 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid 1733 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 1734 */ 1735void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) 1736{ 1737 if (sm) 1738 eap_invalidate_cached_session(sm->eap); 1739} 1740 1741 1742static struct eap_peer_config * eapol_sm_get_config(void *ctx) 1743{ 1744 struct eapol_sm *sm = ctx; 1745 return sm ? sm->config : NULL; 1746} 1747 1748 1749static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) 1750{ 1751 struct eapol_sm *sm = ctx; 1752 if (sm == NULL || sm->eapReqData == NULL) 1753 return NULL; 1754 1755 return sm->eapReqData; 1756} 1757 1758 1759static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) 1760{ 1761 struct eapol_sm *sm = ctx; 1762 if (sm == NULL) 1763 return FALSE; 1764 switch (variable) { 1765 case EAPOL_eapSuccess: 1766 return sm->eapSuccess; 1767 case EAPOL_eapRestart: 1768 return sm->eapRestart; 1769 case EAPOL_eapFail: 1770 return sm->eapFail; 1771 case EAPOL_eapResp: 1772 return sm->eapResp; 1773 case EAPOL_eapNoResp: 1774 return sm->eapNoResp; 1775 case EAPOL_eapReq: 1776 return sm->eapReq; 1777 case EAPOL_portEnabled: 1778 return sm->portEnabled; 1779 case EAPOL_altAccept: 1780 return sm->altAccept; 1781 case EAPOL_altReject: 1782 return sm->altReject; 1783 } 1784 return FALSE; 1785} 1786 1787 1788static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, 1789 Boolean value) 1790{ 1791 struct eapol_sm *sm = ctx; 1792 if (sm == NULL) 1793 return; 1794 switch (variable) { 1795 case EAPOL_eapSuccess: 1796 sm->eapSuccess = value; 1797 break; 1798 case EAPOL_eapRestart: 1799 sm->eapRestart = value; 1800 break; 1801 case EAPOL_eapFail: 1802 sm->eapFail = value; 1803 break; 1804 case EAPOL_eapResp: 1805 sm->eapResp = value; 1806 break; 1807 case EAPOL_eapNoResp: 1808 sm->eapNoResp = value; 1809 break; 1810 case EAPOL_eapReq: 1811 sm->eapReq = value; 1812 break; 1813 case EAPOL_portEnabled: 1814 sm->portEnabled = value; 1815 break; 1816 case EAPOL_altAccept: 1817 sm->altAccept = value; 1818 break; 1819 case EAPOL_altReject: 1820 sm->altReject = value; 1821 break; 1822 } 1823} 1824 1825 1826static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable) 1827{ 1828 struct eapol_sm *sm = ctx; 1829 if (sm == NULL) 1830 return 0; 1831 switch (variable) { 1832 case EAPOL_idleWhile: 1833 return sm->idleWhile; 1834 } 1835 return 0; 1836} 1837 1838 1839static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable, 1840 unsigned int value) 1841{ 1842 struct eapol_sm *sm = ctx; 1843 if (sm == NULL) 1844 return; 1845 switch (variable) { 1846 case EAPOL_idleWhile: 1847 sm->idleWhile = value; 1848 if (sm->idleWhile > 0) 1849 eapol_enable_timer_tick(sm); 1850 break; 1851 } 1852} 1853 1854 1855static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob) 1856{ 1857#ifndef CONFIG_NO_CONFIG_BLOBS 1858 struct eapol_sm *sm = ctx; 1859 if (sm && sm->ctx && sm->ctx->set_config_blob) 1860 sm->ctx->set_config_blob(sm->ctx->ctx, blob); 1861#endif /* CONFIG_NO_CONFIG_BLOBS */ 1862} 1863 1864 1865static const struct wpa_config_blob * 1866eapol_sm_get_config_blob(void *ctx, const char *name) 1867{ 1868#ifndef CONFIG_NO_CONFIG_BLOBS 1869 struct eapol_sm *sm = ctx; 1870 if (sm && sm->ctx && sm->ctx->get_config_blob) 1871 return sm->ctx->get_config_blob(sm->ctx->ctx, name); 1872 else 1873 return NULL; 1874#else /* CONFIG_NO_CONFIG_BLOBS */ 1875 return NULL; 1876#endif /* CONFIG_NO_CONFIG_BLOBS */ 1877} 1878 1879 1880static void eapol_sm_notify_pending(void *ctx) 1881{ 1882 struct eapol_sm *sm = ctx; 1883 if (sm == NULL) 1884 return; 1885 if (sm->eapReqData && !sm->eapReq) { 1886 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " 1887 "state machine - retrying pending EAP Request"); 1888 sm->eapolEap = TRUE; 1889 sm->eapReq = TRUE; 1890 eapol_sm_step(sm); 1891 } 1892} 1893 1894 1895#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 1896static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field, 1897 const char *txt) 1898{ 1899 struct eapol_sm *sm = ctx; 1900 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed"); 1901 if (sm->ctx->eap_param_needed) 1902 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt); 1903} 1904#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 1905#define eapol_sm_eap_param_needed NULL 1906#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 1907 1908static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject, 1909 const char *cert_hash, 1910 const struct wpabuf *cert) 1911{ 1912 struct eapol_sm *sm = ctx; 1913 if (sm->ctx->cert_cb) 1914 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject, 1915 cert_hash, cert); 1916} 1917 1918 1919static void eapol_sm_notify_status(void *ctx, const char *status, 1920 const char *parameter) 1921{ 1922 struct eapol_sm *sm = ctx; 1923 1924 if (sm->ctx->status_cb) 1925 sm->ctx->status_cb(sm->ctx->ctx, status, parameter); 1926} 1927 1928 1929static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len) 1930{ 1931 struct eapol_sm *sm = ctx; 1932 1933 if (sm->ctx->set_anon_id) 1934 sm->ctx->set_anon_id(sm->ctx->ctx, id, len); 1935} 1936 1937 1938static struct eapol_callbacks eapol_cb = 1939{ 1940 eapol_sm_get_config, 1941 eapol_sm_get_bool, 1942 eapol_sm_set_bool, 1943 eapol_sm_get_int, 1944 eapol_sm_set_int, 1945 eapol_sm_get_eapReqData, 1946 eapol_sm_set_config_blob, 1947 eapol_sm_get_config_blob, 1948 eapol_sm_notify_pending, 1949 eapol_sm_eap_param_needed, 1950 eapol_sm_notify_cert, 1951 eapol_sm_notify_status, 1952 eapol_sm_set_anon_id 1953}; 1954 1955 1956/** 1957 * eapol_sm_init - Initialize EAPOL state machine 1958 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer 1959 * and EAPOL state machine will free it in eapol_sm_deinit() 1960 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure 1961 * 1962 * Allocate and initialize an EAPOL state machine. 1963 */ 1964struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) 1965{ 1966 struct eapol_sm *sm; 1967 struct eap_config conf; 1968 sm = os_zalloc(sizeof(*sm)); 1969 if (sm == NULL) 1970 return NULL; 1971 sm->ctx = ctx; 1972 1973 sm->portControl = Auto; 1974 1975 /* Supplicant PAE state machine */ 1976 sm->heldPeriod = 60; 1977 sm->startPeriod = 30; 1978 sm->maxStart = 3; 1979 1980 /* Supplicant Backend state machine */ 1981 sm->authPeriod = 30; 1982 1983 os_memset(&conf, 0, sizeof(conf)); 1984 conf.opensc_engine_path = ctx->opensc_engine_path; 1985 conf.pkcs11_engine_path = ctx->pkcs11_engine_path; 1986 conf.pkcs11_module_path = ctx->pkcs11_module_path; 1987 conf.wps = ctx->wps; 1988 conf.cert_in_cb = ctx->cert_in_cb; 1989 1990 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); 1991 if (sm->eap == NULL) { 1992 os_free(sm); 1993 return NULL; 1994 } 1995 1996#ifdef CONFIG_EAP_PROXY 1997 sm->use_eap_proxy = FALSE; 1998 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx); 1999 if (sm->eap_proxy == NULL) { 2000 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy"); 2001 } 2002#endif /* CONFIG_EAP_PROXY */ 2003 2004 /* Initialize EAPOL state machines */ 2005 sm->initialize = TRUE; 2006 eapol_sm_step(sm); 2007 sm->initialize = FALSE; 2008 eapol_sm_step(sm); 2009 2010 sm->timer_tick_enabled = 1; 2011 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); 2012 2013 return sm; 2014} 2015 2016 2017/** 2018 * eapol_sm_deinit - Deinitialize EAPOL state machine 2019 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() 2020 * 2021 * Deinitialize and free EAPOL state machine. 2022 */ 2023void eapol_sm_deinit(struct eapol_sm *sm) 2024{ 2025 if (sm == NULL) 2026 return; 2027 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); 2028 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 2029 eap_peer_sm_deinit(sm->eap); 2030#ifdef CONFIG_EAP_PROXY 2031 eap_proxy_deinit(sm->eap_proxy); 2032#endif /* CONFIG_EAP_PROXY */ 2033 os_free(sm->last_rx_key); 2034 wpabuf_free(sm->eapReqData); 2035 os_free(sm->ctx); 2036 os_free(sm); 2037} 2038 2039 2040void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, 2041 struct ext_password_data *ext) 2042{ 2043 if (sm && sm->eap) 2044 eap_sm_set_ext_pw_ctx(sm->eap, ext); 2045} 2046 2047 2048int eapol_sm_failed(struct eapol_sm *sm) 2049{ 2050 if (sm == NULL) 2051 return 0; 2052 return !sm->eapSuccess && sm->eapFail; 2053} 2054 2055 2056int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len) 2057{ 2058#ifdef CONFIG_EAP_PROXY 2059 if (sm->eap_proxy == NULL) 2060 return -1; 2061 return eap_proxy_get_imsi(sm->eap_proxy, imsi, len); 2062#else /* CONFIG_EAP_PROXY */ 2063 return -1; 2064#endif /* CONFIG_EAP_PROXY */ 2065} 2066