1 /* 2 * IEEE 802.1X-2004 Authenticator - EAPOL state machine 3 * Copyright (c) 2002-2015, 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 "eloop.h" 13 #include "state_machine.h" 14 #include "common/eapol_common.h" 15 #include "eap_common/eap_defs.h" 16 #include "eap_common/eap_common.h" 17 #include "eap_server/eap.h" 18 #include "eapol_auth_sm.h" 19 #include "eapol_auth_sm_i.h" 20 21 #define STATE_MACHINE_DATA struct eapol_state_machine 22 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X" 23 #define STATE_MACHINE_ADDR sm->addr 24 25 static const struct eapol_callbacks eapol_cb; 26 27 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */ 28 29 #define setPortAuthorized() \ 30 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1) 31 #define setPortUnauthorized() \ 32 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0) 33 34 /* procedures */ 35 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0) 36 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1) 37 #define txReq() eapol_auth_tx_req(sm) 38 #define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta) 39 #define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta) 40 #define processKey() do { } while (0) 41 42 43 static void eapol_sm_step_run(struct eapol_state_machine *sm); 44 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx); 45 static void eapol_auth_initialize(struct eapol_state_machine *sm); 46 static void eapol_auth_conf_free(struct eapol_auth_config *conf); 47 48 49 static void eapol_auth_logger(struct eapol_authenticator *eapol, 50 const u8 *addr, eapol_logger_level level, 51 const char *txt) 52 { 53 if (eapol->cb.logger == NULL) 54 return; 55 eapol->cb.logger(eapol->conf.ctx, addr, level, txt); 56 } 57 58 59 PRINTF_FORMAT(4, 5) 60 static void eapol_auth_vlogger(struct eapol_authenticator *eapol, 61 const u8 *addr, eapol_logger_level level, 62 const char *fmt, ...) 63 { 64 char *format; 65 int maxlen; 66 va_list ap; 67 68 if (eapol->cb.logger == NULL) 69 return; 70 71 maxlen = os_strlen(fmt) + 100; 72 format = os_malloc(maxlen); 73 if (!format) 74 return; 75 76 va_start(ap, fmt); 77 vsnprintf(format, maxlen, fmt, ap); 78 va_end(ap); 79 80 eapol_auth_logger(eapol, addr, level, format); 81 82 os_free(format); 83 } 84 85 86 static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm, 87 int success) 88 { 89 struct eap_hdr eap; 90 91 os_memset(&eap, 0, sizeof(eap)); 92 93 eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 94 eap.identifier = ++sm->last_eap_id; 95 eap.length = host_to_be16(sizeof(eap)); 96 97 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, 98 "Sending canned EAP packet %s (identifier %d)", 99 success ? "SUCCESS" : "FAILURE", eap.identifier); 100 sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, 101 IEEE802_1X_TYPE_EAP_PACKET, 102 (u8 *) &eap, sizeof(eap)); 103 sm->dot1xAuthEapolFramesTx++; 104 } 105 106 107 static void eapol_auth_tx_req(struct eapol_state_machine *sm) 108 { 109 if (sm->eap_if->eapReqData == NULL || 110 wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) { 111 eapol_auth_logger(sm->eapol, sm->addr, 112 EAPOL_LOGGER_DEBUG, 113 "TxReq called, but there is no EAP request " 114 "from authentication server"); 115 return; 116 } 117 118 if (sm->flags & EAPOL_SM_WAIT_START) { 119 wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR 120 " while waiting for EAPOL-Start", 121 MAC2STR(sm->addr)); 122 return; 123 } 124 125 sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData); 126 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, 127 "Sending EAP Packet (identifier %d)", 128 sm->last_eap_id); 129 sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, 130 IEEE802_1X_TYPE_EAP_PACKET, 131 wpabuf_head(sm->eap_if->eapReqData), 132 wpabuf_len(sm->eap_if->eapReqData)); 133 sm->dot1xAuthEapolFramesTx++; 134 if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY) 135 sm->dot1xAuthEapolReqIdFramesTx++; 136 else 137 sm->dot1xAuthEapolReqFramesTx++; 138 } 139 140 141 /** 142 * eapol_port_timers_tick - Port Timers state machine 143 * @eloop_ctx: struct eapol_state_machine * 144 * @timeout_ctx: Not used 145 * 146 * This statemachine is implemented as a function that will be called 147 * once a second as a registered event loop timeout. 148 */ 149 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) 150 { 151 struct eapol_state_machine *state = timeout_ctx; 152 153 if (state->aWhile > 0) { 154 state->aWhile--; 155 if (state->aWhile == 0) { 156 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 157 " - aWhile --> 0", 158 MAC2STR(state->addr)); 159 } 160 } 161 162 if (state->quietWhile > 0) { 163 state->quietWhile--; 164 if (state->quietWhile == 0) { 165 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 166 " - quietWhile --> 0", 167 MAC2STR(state->addr)); 168 } 169 } 170 171 if (state->reAuthWhen > 0) { 172 state->reAuthWhen--; 173 if (state->reAuthWhen == 0) { 174 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 175 " - reAuthWhen --> 0", 176 MAC2STR(state->addr)); 177 } 178 } 179 180 if (state->eap_if->retransWhile > 0) { 181 state->eap_if->retransWhile--; 182 if (state->eap_if->retransWhile == 0) { 183 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 184 " - (EAP) retransWhile --> 0", 185 MAC2STR(state->addr)); 186 } 187 } 188 189 eapol_sm_step_run(state); 190 191 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state); 192 } 193 194 195 196 /* Authenticator PAE state machine */ 197 198 SM_STATE(AUTH_PAE, INITIALIZE) 199 { 200 SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae); 201 sm->portMode = Auto; 202 203 /* 204 * Clearing keyRun here is not specified in IEEE Std 802.1X-2004, but 205 * it looks like this would be logical thing to do here since the 206 * EAPOL-Key exchange is not possible in this state. It is possible to 207 * get here on disconnection event without advancing to the 208 * AUTHENTICATING state to clear keyRun before the IEEE 802.11 RSN 209 * authenticator state machine runs and that may advance from 210 * AUTHENTICATION2 to INITPMK if keyRun = true has been left from the 211 * last association. This can be avoided by clearing keyRun here. 212 */ 213 sm->keyRun = false; 214 } 215 216 217 SM_STATE(AUTH_PAE, DISCONNECTED) 218 { 219 int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE; 220 bool pre_auth_logoff = sm->auth_pae_state == AUTH_PAE_ABORTING && 221 sm->eapolLogoff && !sm->authenticated; 222 bool logoff = sm->eapolLogoff; 223 224 if (sm->eapolLogoff) { 225 if (sm->auth_pae_state == AUTH_PAE_CONNECTING) 226 sm->authEapLogoffsWhileConnecting++; 227 else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) 228 sm->authAuthEapLogoffWhileAuthenticated++; 229 } 230 231 SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae); 232 233 sm->authPortStatus = Unauthorized; 234 setPortUnauthorized(); 235 sm->reAuthCount = 0; 236 sm->eapolLogoff = false; 237 if (!from_initialize && !pre_auth_logoff) { 238 if (sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, 239 sm->flags & EAPOL_SM_PREAUTH, 240 sm->remediation, logoff)) { 241 wpa_printf(MSG_DEBUG, 242 "EAPOL: Do not restart since lower layers will disconnect the port after EAPOL-Logoff"); 243 sm->stopped = true; 244 } 245 } 246 } 247 248 249 SM_STATE(AUTH_PAE, RESTART) 250 { 251 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) { 252 if (sm->reAuthenticate) 253 sm->authAuthReauthsWhileAuthenticated++; 254 if (sm->eapolStart) 255 sm->authAuthEapStartsWhileAuthenticated++; 256 if (sm->eapolLogoff) 257 sm->authAuthEapLogoffWhileAuthenticated++; 258 } 259 260 SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); 261 262 sm->eap_if->eapRestart = true; 263 } 264 265 266 SM_STATE(AUTH_PAE, CONNECTING) 267 { 268 if (sm->auth_pae_state != AUTH_PAE_CONNECTING) 269 sm->authEntersConnecting++; 270 271 SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); 272 273 sm->reAuthenticate = false; 274 sm->reAuthCount++; 275 } 276 277 278 SM_STATE(AUTH_PAE, HELD) 279 { 280 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail) 281 sm->authAuthFailWhileAuthenticating++; 282 283 SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae); 284 285 sm->authPortStatus = Unauthorized; 286 setPortUnauthorized(); 287 sm->quietWhile = sm->quietPeriod; 288 sm->eapolLogoff = false; 289 290 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, 291 "authentication failed - EAP type: %d (%s)", 292 sm->eap_type_authsrv, 293 eap_server_get_name(0, sm->eap_type_authsrv)); 294 if (sm->eap_type_authsrv != sm->eap_type_supp) { 295 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, 296 "Supplicant used different EAP type: " 297 "%d (%s)", sm->eap_type_supp, 298 eap_server_get_name(0, sm->eap_type_supp)); 299 } 300 sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, 301 sm->flags & EAPOL_SM_PREAUTH, sm->remediation, 302 false); 303 } 304 305 306 SM_STATE(AUTH_PAE, AUTHENTICATED) 307 { 308 char *extra = ""; 309 310 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess) 311 sm->authAuthSuccessesWhileAuthenticating++; 312 313 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae); 314 315 sm->authPortStatus = Authorized; 316 setPortAuthorized(); 317 sm->reAuthCount = 0; 318 if (sm->flags & EAPOL_SM_PREAUTH) 319 extra = " (pre-authentication)"; 320 else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE) 321 extra = " (PMKSA cache)"; 322 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, 323 "authenticated - EAP type: %d (%s)%s", 324 sm->eap_type_authsrv, 325 eap_server_get_name(0, sm->eap_type_authsrv), 326 extra); 327 if (sm->authSuccess) 328 sm->authenticated++; 329 sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1, 330 sm->flags & EAPOL_SM_PREAUTH, sm->remediation, 331 false); 332 } 333 334 335 SM_STATE(AUTH_PAE, AUTHENTICATING) 336 { 337 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); 338 339 sm->eapolStart = false; 340 sm->authSuccess = false; 341 sm->authFail = false; 342 sm->authTimeout = false; 343 sm->authStart = true; 344 sm->keyRun = false; 345 sm->keyDone = false; 346 } 347 348 349 SM_STATE(AUTH_PAE, ABORTING) 350 { 351 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) { 352 if (sm->authTimeout) 353 sm->authAuthTimeoutsWhileAuthenticating++; 354 if (sm->eapolStart) 355 sm->authAuthEapStartsWhileAuthenticating++; 356 if (sm->eapolLogoff) 357 sm->authAuthEapLogoffWhileAuthenticating++; 358 } 359 360 SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); 361 362 sm->authAbort = true; 363 sm->keyRun = false; 364 sm->keyDone = false; 365 } 366 367 368 SM_STATE(AUTH_PAE, FORCE_AUTH) 369 { 370 SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae); 371 372 sm->authPortStatus = Authorized; 373 setPortAuthorized(); 374 sm->portMode = ForceAuthorized; 375 sm->eapolStart = false; 376 txCannedSuccess(); 377 } 378 379 380 SM_STATE(AUTH_PAE, FORCE_UNAUTH) 381 { 382 SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae); 383 384 sm->authPortStatus = Unauthorized; 385 setPortUnauthorized(); 386 sm->portMode = ForceUnauthorized; 387 sm->eapolStart = false; 388 txCannedFail(); 389 } 390 391 392 SM_STEP(AUTH_PAE) 393 { 394 if ((sm->portControl == Auto && sm->portMode != sm->portControl) || 395 sm->initialize || !sm->eap_if->portEnabled) 396 SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE); 397 else if (sm->portControl == ForceAuthorized && 398 sm->portMode != sm->portControl && 399 !(sm->initialize || !sm->eap_if->portEnabled)) 400 SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH); 401 else if (sm->portControl == ForceUnauthorized && 402 sm->portMode != sm->portControl && 403 !(sm->initialize || !sm->eap_if->portEnabled)) 404 SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH); 405 else { 406 switch (sm->auth_pae_state) { 407 case AUTH_PAE_INITIALIZE: 408 SM_ENTER(AUTH_PAE, DISCONNECTED); 409 break; 410 case AUTH_PAE_DISCONNECTED: 411 if (!sm->stopped) 412 SM_ENTER(AUTH_PAE, RESTART); 413 break; 414 case AUTH_PAE_RESTART: 415 if (!sm->eap_if->eapRestart) 416 SM_ENTER(AUTH_PAE, CONNECTING); 417 break; 418 case AUTH_PAE_HELD: 419 if (sm->quietWhile == 0) 420 SM_ENTER(AUTH_PAE, RESTART); 421 break; 422 case AUTH_PAE_CONNECTING: 423 if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax) 424 SM_ENTER(AUTH_PAE, DISCONNECTED); 425 else if ((sm->eap_if->eapReq && 426 sm->reAuthCount <= sm->reAuthMax) || 427 sm->eap_if->eapSuccess || sm->eap_if->eapFail) 428 SM_ENTER(AUTH_PAE, AUTHENTICATING); 429 break; 430 case AUTH_PAE_AUTHENTICATED: 431 if (sm->eapolStart || sm->reAuthenticate) 432 SM_ENTER(AUTH_PAE, RESTART); 433 else if (sm->eapolLogoff || !sm->portValid) 434 SM_ENTER(AUTH_PAE, DISCONNECTED); 435 break; 436 case AUTH_PAE_AUTHENTICATING: 437 if (sm->authSuccess && sm->portValid) 438 SM_ENTER(AUTH_PAE, AUTHENTICATED); 439 else if (sm->authFail || 440 (sm->keyDone && !sm->portValid)) 441 SM_ENTER(AUTH_PAE, HELD); 442 else if (sm->eapolStart || sm->eapolLogoff || 443 sm->authTimeout) 444 SM_ENTER(AUTH_PAE, ABORTING); 445 break; 446 case AUTH_PAE_ABORTING: 447 if (sm->eapolLogoff && !sm->authAbort) 448 SM_ENTER(AUTH_PAE, DISCONNECTED); 449 else if (!sm->eapolLogoff && !sm->authAbort) 450 SM_ENTER(AUTH_PAE, RESTART); 451 break; 452 case AUTH_PAE_FORCE_AUTH: 453 if (sm->eapolStart) 454 SM_ENTER(AUTH_PAE, FORCE_AUTH); 455 break; 456 case AUTH_PAE_FORCE_UNAUTH: 457 if (sm->eapolStart) 458 SM_ENTER(AUTH_PAE, FORCE_UNAUTH); 459 break; 460 } 461 } 462 } 463 464 465 466 /* Backend Authentication state machine */ 467 468 SM_STATE(BE_AUTH, INITIALIZE) 469 { 470 SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); 471 472 abortAuth(); 473 sm->eap_if->eapNoReq = false; 474 sm->authAbort = false; 475 } 476 477 478 SM_STATE(BE_AUTH, REQUEST) 479 { 480 SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); 481 482 txReq(); 483 sm->eap_if->eapReq = false; 484 sm->backendOtherRequestsToSupplicant++; 485 486 /* 487 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but 488 * it looks like this would be logical thing to do there since the old 489 * EAP response would not be valid anymore after the new EAP request 490 * was sent out. 491 * 492 * A race condition has been reported, in which hostapd ended up 493 * sending out EAP-Response/Identity as a response to the first 494 * EAP-Request from the main EAP method. This can be avoided by 495 * clearing eapolEap here. 496 */ 497 sm->eapolEap = false; 498 } 499 500 501 SM_STATE(BE_AUTH, RESPONSE) 502 { 503 SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); 504 505 sm->authTimeout = false; 506 sm->eapolEap = false; 507 sm->eap_if->eapNoReq = false; 508 sm->aWhile = sm->serverTimeout; 509 sm->eap_if->eapResp = true; 510 /* sendRespToServer(); */ 511 sm->backendResponses++; 512 } 513 514 515 SM_STATE(BE_AUTH, SUCCESS) 516 { 517 SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); 518 519 txReq(); 520 sm->authSuccess = true; 521 sm->keyRun = true; 522 } 523 524 525 SM_STATE(BE_AUTH, FAIL) 526 { 527 SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); 528 529 txReq(); 530 sm->authFail = true; 531 } 532 533 534 SM_STATE(BE_AUTH, TIMEOUT) 535 { 536 SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); 537 538 sm->authTimeout = true; 539 } 540 541 542 SM_STATE(BE_AUTH, IDLE) 543 { 544 SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); 545 546 sm->authStart = false; 547 } 548 549 550 SM_STATE(BE_AUTH, IGNORE) 551 { 552 SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); 553 554 sm->eap_if->eapNoReq = false; 555 } 556 557 558 SM_STEP(BE_AUTH) 559 { 560 if (sm->portControl != Auto || sm->initialize || sm->authAbort) { 561 SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE); 562 return; 563 } 564 565 switch (sm->be_auth_state) { 566 case BE_AUTH_INITIALIZE: 567 SM_ENTER(BE_AUTH, IDLE); 568 break; 569 case BE_AUTH_REQUEST: 570 if (sm->eapolEap) 571 SM_ENTER(BE_AUTH, RESPONSE); 572 else if (sm->eap_if->eapReq) 573 SM_ENTER(BE_AUTH, REQUEST); 574 else if (sm->eap_if->eapTimeout) 575 SM_ENTER(BE_AUTH, TIMEOUT); 576 break; 577 case BE_AUTH_RESPONSE: 578 if (sm->eap_if->eapNoReq) 579 SM_ENTER(BE_AUTH, IGNORE); 580 if (sm->eap_if->eapReq) { 581 sm->backendAccessChallenges++; 582 SM_ENTER(BE_AUTH, REQUEST); 583 } else if (sm->aWhile == 0) 584 SM_ENTER(BE_AUTH, TIMEOUT); 585 else if (sm->eap_if->eapFail) { 586 sm->backendAuthFails++; 587 SM_ENTER(BE_AUTH, FAIL); 588 } else if (sm->eap_if->eapSuccess) { 589 sm->backendAuthSuccesses++; 590 SM_ENTER(BE_AUTH, SUCCESS); 591 } 592 break; 593 case BE_AUTH_SUCCESS: 594 SM_ENTER(BE_AUTH, IDLE); 595 break; 596 case BE_AUTH_FAIL: 597 SM_ENTER(BE_AUTH, IDLE); 598 break; 599 case BE_AUTH_TIMEOUT: 600 SM_ENTER(BE_AUTH, IDLE); 601 break; 602 case BE_AUTH_IDLE: 603 if (sm->eap_if->eapFail && sm->authStart) 604 SM_ENTER(BE_AUTH, FAIL); 605 else if (sm->eap_if->eapReq && sm->authStart) 606 SM_ENTER(BE_AUTH, REQUEST); 607 else if (sm->eap_if->eapSuccess && sm->authStart) 608 SM_ENTER(BE_AUTH, SUCCESS); 609 break; 610 case BE_AUTH_IGNORE: 611 if (sm->eapolEap) 612 SM_ENTER(BE_AUTH, RESPONSE); 613 else if (sm->eap_if->eapReq) 614 SM_ENTER(BE_AUTH, REQUEST); 615 else if (sm->eap_if->eapTimeout) 616 SM_ENTER(BE_AUTH, TIMEOUT); 617 break; 618 } 619 } 620 621 622 623 /* Reauthentication Timer state machine */ 624 625 SM_STATE(REAUTH_TIMER, INITIALIZE) 626 { 627 SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer); 628 629 sm->reAuthWhen = sm->reAuthPeriod; 630 } 631 632 633 SM_STATE(REAUTH_TIMER, REAUTHENTICATE) 634 { 635 SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); 636 637 sm->reAuthenticate = true; 638 sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, 639 EAPOL_AUTH_REAUTHENTICATE); 640 } 641 642 643 SM_STEP(REAUTH_TIMER) 644 { 645 if (sm->portControl != Auto || sm->initialize || 646 sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { 647 SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE); 648 return; 649 } 650 651 switch (sm->reauth_timer_state) { 652 case REAUTH_TIMER_INITIALIZE: 653 if (sm->reAuthWhen == 0) 654 SM_ENTER(REAUTH_TIMER, REAUTHENTICATE); 655 break; 656 case REAUTH_TIMER_REAUTHENTICATE: 657 SM_ENTER(REAUTH_TIMER, INITIALIZE); 658 break; 659 } 660 } 661 662 663 664 #ifdef CONFIG_WEP 665 666 /* Authenticator Key Transmit state machine */ 667 668 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) 669 { 670 SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx); 671 } 672 673 674 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) 675 { 676 SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); 677 678 txKey(); 679 sm->eap_if->eapKeyAvailable = false; 680 sm->keyDone = true; 681 } 682 683 684 SM_STEP(AUTH_KEY_TX) 685 { 686 if (sm->initialize || sm->portControl != Auto) { 687 SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT); 688 return; 689 } 690 691 switch (sm->auth_key_tx_state) { 692 case AUTH_KEY_TX_NO_KEY_TRANSMIT: 693 if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable && 694 sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA)) 695 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); 696 break; 697 case AUTH_KEY_TX_KEY_TRANSMIT: 698 if (!sm->keyTxEnabled || !sm->keyRun) 699 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); 700 else if (sm->eap_if->eapKeyAvailable) 701 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); 702 break; 703 } 704 } 705 706 707 708 /* Key Receive state machine */ 709 710 SM_STATE(KEY_RX, NO_KEY_RECEIVE) 711 { 712 SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx); 713 } 714 715 716 SM_STATE(KEY_RX, KEY_RECEIVE) 717 { 718 SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); 719 720 processKey(); 721 sm->rxKey = false; 722 } 723 724 725 SM_STEP(KEY_RX) 726 { 727 if (sm->initialize || !sm->eap_if->portEnabled) { 728 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); 729 return; 730 } 731 732 switch (sm->key_rx_state) { 733 case KEY_RX_NO_KEY_RECEIVE: 734 if (sm->rxKey) 735 SM_ENTER(KEY_RX, KEY_RECEIVE); 736 break; 737 case KEY_RX_KEY_RECEIVE: 738 if (sm->rxKey) 739 SM_ENTER(KEY_RX, KEY_RECEIVE); 740 break; 741 } 742 } 743 744 #endif /* CONFIG_WEP */ 745 746 747 748 /* Controlled Directions state machine */ 749 750 SM_STATE(CTRL_DIR, FORCE_BOTH) 751 { 752 SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir); 753 sm->operControlledDirections = Both; 754 } 755 756 757 SM_STATE(CTRL_DIR, IN_OR_BOTH) 758 { 759 SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir); 760 sm->operControlledDirections = sm->adminControlledDirections; 761 } 762 763 764 SM_STEP(CTRL_DIR) 765 { 766 if (sm->initialize) { 767 SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH); 768 return; 769 } 770 771 switch (sm->ctrl_dir_state) { 772 case CTRL_DIR_FORCE_BOTH: 773 if (sm->eap_if->portEnabled && sm->operEdge) 774 SM_ENTER(CTRL_DIR, IN_OR_BOTH); 775 break; 776 case CTRL_DIR_IN_OR_BOTH: 777 if (sm->operControlledDirections != 778 sm->adminControlledDirections) 779 SM_ENTER(CTRL_DIR, IN_OR_BOTH); 780 if (!sm->eap_if->portEnabled || !sm->operEdge) 781 SM_ENTER(CTRL_DIR, FORCE_BOTH); 782 break; 783 } 784 } 785 786 787 788 struct eapol_state_machine * 789 eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, 790 int flags, const struct wpabuf *assoc_wps_ie, 791 const struct wpabuf *assoc_p2p_ie, void *sta_ctx, 792 const char *identity, const char *radius_cui) 793 { 794 struct eapol_state_machine *sm; 795 struct eap_session_data eap_sess; 796 797 if (eapol == NULL) 798 return NULL; 799 800 sm = os_zalloc(sizeof(*sm)); 801 if (sm == NULL) { 802 wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation " 803 "failed"); 804 return NULL; 805 } 806 sm->radius_identifier = -1; 807 os_memcpy(sm->addr, addr, ETH_ALEN); 808 sm->flags = flags; 809 810 sm->eapol = eapol; 811 sm->sta = sta_ctx; 812 813 /* Set default values for state machine constants */ 814 sm->auth_pae_state = AUTH_PAE_INITIALIZE; 815 sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod; 816 sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax; 817 818 sm->be_auth_state = BE_AUTH_INITIALIZE; 819 sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout; 820 821 sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; 822 sm->reAuthPeriod = eapol->conf.eap_reauth_period; 823 sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0; 824 825 sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; 826 827 sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE; 828 829 sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH; 830 831 sm->portControl = Auto; 832 833 #ifdef CONFIG_WEP 834 if (!eapol->conf.wpa && 835 (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) 836 sm->keyTxEnabled = true; 837 else 838 #endif /* CONFIG_WEP */ 839 sm->keyTxEnabled = false; 840 if (eapol->conf.wpa) 841 sm->portValid = false; 842 else 843 sm->portValid = true; 844 845 os_memset(&eap_sess, 0, sizeof(eap_sess)); 846 eap_sess.assoc_wps_ie = assoc_wps_ie; 847 eap_sess.assoc_p2p_ie = assoc_p2p_ie; 848 eap_sess.peer_addr = addr; 849 sm->eap = eap_server_sm_init(sm, &eapol_cb, eapol->conf.eap_cfg, 850 &eap_sess); 851 if (sm->eap == NULL) { 852 eapol_auth_free(sm); 853 return NULL; 854 } 855 sm->eap_if = eap_get_interface(sm->eap); 856 857 eapol_auth_initialize(sm); 858 859 if (identity) { 860 sm->identity = (u8 *) os_strdup(identity); 861 if (sm->identity) 862 sm->identity_len = os_strlen(identity); 863 } 864 if (radius_cui) 865 sm->radius_cui = wpabuf_alloc_copy(radius_cui, 866 os_strlen(radius_cui)); 867 868 #ifndef CONFIG_NO_RADIUS 869 if (radius_gen_session_id((u8 *) &sm->acct_multi_session_id, 870 sizeof(sm->acct_multi_session_id)) < 0) { 871 eapol_auth_free(sm); 872 return NULL; 873 } 874 #endif /* CONFIG_NO_RADIUS */ 875 876 return sm; 877 } 878 879 880 void eapol_auth_free(struct eapol_state_machine *sm) 881 { 882 if (sm == NULL) 883 return; 884 885 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 886 eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); 887 if (sm->eap) 888 eap_server_sm_deinit(sm->eap); 889 890 wpabuf_free(sm->radius_cui); 891 os_free(sm->identity); 892 os_free(sm); 893 } 894 895 896 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol, 897 const u8 *addr) 898 { 899 return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr); 900 } 901 902 903 static void eapol_sm_step_run(struct eapol_state_machine *sm) 904 { 905 struct eapol_authenticator *eapol = sm->eapol; 906 u8 addr[ETH_ALEN]; 907 unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, 908 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; 909 int max_steps = 100; 910 911 os_memcpy(addr, sm->addr, ETH_ALEN); 912 913 /* 914 * Allow EAPOL state machines to run as long as there are state 915 * changes, but exit and return here through event loop if more than 916 * 100 steps is needed as a precaution against infinite loops inside 917 * eloop callback. 918 */ 919 restart: 920 prev_auth_pae = sm->auth_pae_state; 921 prev_be_auth = sm->be_auth_state; 922 prev_reauth_timer = sm->reauth_timer_state; 923 prev_auth_key_tx = sm->auth_key_tx_state; 924 prev_key_rx = sm->key_rx_state; 925 prev_ctrl_dir = sm->ctrl_dir_state; 926 927 SM_STEP_RUN(AUTH_PAE); 928 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 929 SM_STEP_RUN(BE_AUTH); 930 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 931 SM_STEP_RUN(REAUTH_TIMER); 932 #ifdef CONFIG_WEP 933 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 934 SM_STEP_RUN(AUTH_KEY_TX); 935 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 936 SM_STEP_RUN(KEY_RX); 937 #endif /* CONFIG_WEP */ 938 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 939 SM_STEP_RUN(CTRL_DIR); 940 941 if (prev_auth_pae != sm->auth_pae_state || 942 prev_be_auth != sm->be_auth_state || 943 prev_reauth_timer != sm->reauth_timer_state || 944 prev_auth_key_tx != sm->auth_key_tx_state || 945 prev_key_rx != sm->key_rx_state || 946 prev_ctrl_dir != sm->ctrl_dir_state) { 947 if (--max_steps > 0) 948 goto restart; 949 /* Re-run from eloop timeout */ 950 eapol_auth_step(sm); 951 return; 952 } 953 954 if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) { 955 if (eap_server_sm_step(sm->eap)) { 956 if (--max_steps > 0) 957 goto restart; 958 /* Re-run from eloop timeout */ 959 eapol_auth_step(sm); 960 return; 961 } 962 963 /* TODO: find a better location for this */ 964 if (sm->eap_if->aaaEapResp) { 965 sm->eap_if->aaaEapResp = false; 966 if (sm->eap_if->aaaEapRespData == NULL) { 967 wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " 968 "but no aaaEapRespData available"); 969 return; 970 } 971 sm->eapol->cb.aaa_send( 972 sm->eapol->conf.ctx, sm->sta, 973 wpabuf_head(sm->eap_if->aaaEapRespData), 974 wpabuf_len(sm->eap_if->aaaEapRespData)); 975 } 976 } 977 978 if (eapol_sm_sta_entry_alive(eapol, addr)) 979 sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, 980 EAPOL_AUTH_SM_CHANGE); 981 } 982 983 984 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx) 985 { 986 struct eapol_state_machine *sm = eloop_ctx; 987 eapol_sm_step_run(sm); 988 } 989 990 991 /** 992 * eapol_auth_step - Advance EAPOL state machines 993 * @sm: EAPOL state machine 994 * 995 * This function is called to advance EAPOL state machines after any change 996 * that could affect their state. 997 */ 998 void eapol_auth_step(struct eapol_state_machine *sm) 999 { 1000 /* 1001 * Run eapol_sm_step_run from a registered timeout to make sure that 1002 * other possible timeouts/events are processed and to avoid long 1003 * function call chains. 1004 */ 1005 1006 eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL); 1007 } 1008 1009 1010 static void eapol_auth_initialize(struct eapol_state_machine *sm) 1011 { 1012 sm->initializing = true; 1013 /* Initialize the state machines by asserting initialize and then 1014 * deasserting it after one step */ 1015 sm->initialize = true; 1016 eapol_sm_step_run(sm); 1017 sm->initialize = false; 1018 eapol_sm_step_run(sm); 1019 sm->initializing = false; 1020 1021 /* Start one second tick for port timers state machine */ 1022 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 1023 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); 1024 } 1025 1026 1027 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity, 1028 size_t identity_len, int phase2, 1029 struct eap_user *user) 1030 { 1031 struct eapol_state_machine *sm = ctx; 1032 int ret; 1033 1034 ret = sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity, 1035 identity_len, phase2, user); 1036 if (user->remediation) 1037 sm->remediation = 1; 1038 return ret; 1039 } 1040 1041 1042 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len) 1043 { 1044 struct eapol_state_machine *sm = ctx; 1045 *len = sm->eapol->conf.eap_req_id_text_len; 1046 return sm->eapol->conf.eap_req_id_text; 1047 } 1048 1049 1050 static int eapol_sm_get_erp_send_reauth_start(void *ctx) 1051 { 1052 struct eapol_state_machine *sm = ctx; 1053 return sm->eapol->conf.erp_send_reauth_start; 1054 } 1055 1056 1057 static const char * eapol_sm_get_erp_domain(void *ctx) 1058 { 1059 struct eapol_state_machine *sm = ctx; 1060 return sm->eapol->conf.erp_domain; 1061 } 1062 1063 1064 static struct eap_server_erp_key * eapol_sm_erp_get_key(void *ctx, 1065 const char *keyname) 1066 { 1067 struct eapol_state_machine *sm = ctx; 1068 return sm->eapol->cb.erp_get_key(sm->eapol->conf.ctx, keyname); 1069 } 1070 1071 1072 static int eapol_sm_erp_add_key(void *ctx, struct eap_server_erp_key *erp) 1073 { 1074 struct eapol_state_machine *sm = ctx; 1075 return sm->eapol->cb.erp_add_key(sm->eapol->conf.ctx, erp); 1076 } 1077 1078 1079 static const struct eapol_callbacks eapol_cb = 1080 { 1081 eapol_sm_get_eap_user, 1082 eapol_sm_get_eap_req_id_text, 1083 NULL, 1084 eapol_sm_get_erp_send_reauth_start, 1085 eapol_sm_get_erp_domain, 1086 eapol_sm_erp_get_key, 1087 eapol_sm_erp_add_key, 1088 }; 1089 1090 1091 int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx) 1092 { 1093 if (sm == NULL || ctx == NULL || ctx != sm->eap) 1094 return -1; 1095 1096 eap_sm_pending_cb(sm->eap); 1097 eapol_auth_step(sm); 1098 1099 return 0; 1100 } 1101 1102 1103 void eapol_auth_reauthenticate(struct eapol_state_machine *sm) 1104 { 1105 wpa_printf(MSG_DEBUG, "EAPOL: External reauthentication trigger for " 1106 MACSTR, MAC2STR(sm->addr)); 1107 sm->reAuthenticate = true; 1108 eapol_auth_step(sm); 1109 } 1110 1111 1112 int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param, 1113 const char *value) 1114 { 1115 wpa_printf(MSG_DEBUG, "EAPOL: External configuration operation for " 1116 MACSTR " - param=%s value=%s", 1117 MAC2STR(sm->addr), param, value); 1118 1119 if (os_strcasecmp(param, "AdminControlledDirections") == 0) { 1120 if (os_strcmp(value, "Both") == 0) 1121 sm->adminControlledDirections = Both; 1122 else if (os_strcmp(value, "In") == 0) 1123 sm->adminControlledDirections = In; 1124 else 1125 return -1; 1126 eapol_auth_step(sm); 1127 return 0; 1128 } 1129 1130 if (os_strcasecmp(param, "AdminControlledPortControl") == 0) { 1131 if (os_strcmp(value, "ForceAuthorized") == 0) 1132 sm->portControl = ForceAuthorized; 1133 else if (os_strcmp(value, "ForceUnauthorized") == 0) 1134 sm->portControl = ForceUnauthorized; 1135 else if (os_strcmp(value, "Auto") == 0) 1136 sm->portControl = Auto; 1137 else 1138 return -1; 1139 eapol_auth_step(sm); 1140 return 0; 1141 } 1142 1143 if (os_strcasecmp(param, "quietPeriod") == 0) { 1144 sm->quietPeriod = atoi(value); 1145 return 0; 1146 } 1147 1148 if (os_strcasecmp(param, "serverTimeout") == 0) { 1149 sm->serverTimeout = atoi(value); 1150 return 0; 1151 } 1152 1153 if (os_strcasecmp(param, "reAuthPeriod") == 0) { 1154 sm->reAuthPeriod = atoi(value); 1155 return 0; 1156 } 1157 1158 if (os_strcasecmp(param, "reAuthEnabled") == 0) { 1159 if (os_strcmp(value, "TRUE") == 0) 1160 sm->reAuthEnabled = true; 1161 else if (os_strcmp(value, "FALSE") == 0) 1162 sm->reAuthEnabled = false; 1163 else 1164 return -1; 1165 eapol_auth_step(sm); 1166 return 0; 1167 } 1168 1169 if (os_strcasecmp(param, "KeyTransmissionEnabled") == 0) { 1170 if (os_strcmp(value, "TRUE") == 0) 1171 sm->keyTxEnabled = true; 1172 else if (os_strcmp(value, "FALSE") == 0) 1173 sm->keyTxEnabled = false; 1174 else 1175 return -1; 1176 eapol_auth_step(sm); 1177 return 0; 1178 } 1179 1180 return -1; 1181 } 1182 1183 1184 static int eapol_auth_conf_clone(struct eapol_auth_config *dst, 1185 struct eapol_auth_config *src) 1186 { 1187 dst->eap_cfg = src->eap_cfg; 1188 dst->ctx = src->ctx; 1189 dst->eap_reauth_period = src->eap_reauth_period; 1190 dst->wpa = src->wpa; 1191 #ifdef CONFIG_WEP 1192 dst->individual_wep_key_len = src->individual_wep_key_len; 1193 #endif /* CONFIG_WEP */ 1194 os_free(dst->eap_req_id_text); 1195 if (src->eap_req_id_text) { 1196 dst->eap_req_id_text = os_memdup(src->eap_req_id_text, 1197 src->eap_req_id_text_len); 1198 if (dst->eap_req_id_text == NULL) 1199 return -1; 1200 dst->eap_req_id_text_len = src->eap_req_id_text_len; 1201 } else { 1202 dst->eap_req_id_text = NULL; 1203 dst->eap_req_id_text_len = 0; 1204 } 1205 1206 os_free(dst->erp_domain); 1207 if (src->erp_domain) { 1208 dst->erp_domain = os_strdup(src->erp_domain); 1209 if (dst->erp_domain == NULL) 1210 goto fail; 1211 } else { 1212 dst->erp_domain = NULL; 1213 } 1214 dst->erp_send_reauth_start = src->erp_send_reauth_start; 1215 1216 return 0; 1217 1218 fail: 1219 eapol_auth_conf_free(dst); 1220 return -1; 1221 } 1222 1223 1224 static void eapol_auth_conf_free(struct eapol_auth_config *conf) 1225 { 1226 os_free(conf->eap_req_id_text); 1227 conf->eap_req_id_text = NULL; 1228 os_free(conf->erp_domain); 1229 conf->erp_domain = NULL; 1230 } 1231 1232 1233 struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, 1234 struct eapol_auth_cb *cb) 1235 { 1236 struct eapol_authenticator *eapol; 1237 1238 eapol = os_zalloc(sizeof(*eapol)); 1239 if (eapol == NULL) 1240 return NULL; 1241 1242 if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) { 1243 os_free(eapol); 1244 return NULL; 1245 } 1246 1247 #ifdef CONFIG_WEP 1248 if (conf->individual_wep_key_len > 0) { 1249 /* use key0 in individual key and key1 in broadcast key */ 1250 eapol->default_wep_key_idx = 1; 1251 } 1252 #endif /* CONFIG_WEP */ 1253 1254 eapol->cb.eapol_send = cb->eapol_send; 1255 eapol->cb.aaa_send = cb->aaa_send; 1256 eapol->cb.finished = cb->finished; 1257 eapol->cb.get_eap_user = cb->get_eap_user; 1258 eapol->cb.sta_entry_alive = cb->sta_entry_alive; 1259 eapol->cb.logger = cb->logger; 1260 eapol->cb.set_port_authorized = cb->set_port_authorized; 1261 eapol->cb.abort_auth = cb->abort_auth; 1262 eapol->cb.tx_key = cb->tx_key; 1263 eapol->cb.eapol_event = cb->eapol_event; 1264 eapol->cb.erp_get_key = cb->erp_get_key; 1265 eapol->cb.erp_add_key = cb->erp_add_key; 1266 1267 return eapol; 1268 } 1269 1270 1271 void eapol_auth_deinit(struct eapol_authenticator *eapol) 1272 { 1273 if (eapol == NULL) 1274 return; 1275 1276 eapol_auth_conf_free(&eapol->conf); 1277 #ifdef CONFIG_WEP 1278 os_free(eapol->default_wep_key); 1279 #endif /* CONFIG_WEP */ 1280 os_free(eapol); 1281 } 1282