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