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