$search
00001 /* 00002 * IEEE 802.1X-2004 Authenticator - EAPOL state machine 00003 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eloop.h" 00019 #include "state_machine.h" 00020 #include "common/eapol_common.h" 00021 #include "eap_common/eap_defs.h" 00022 #include "eap_common/eap_common.h" 00023 #include "eap_server/eap.h" 00024 #include "eapol_auth_sm.h" 00025 #include "eapol_auth_sm_i.h" 00026 00027 #define STATE_MACHINE_DATA struct eapol_state_machine 00028 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X" 00029 #define STATE_MACHINE_ADDR sm->addr 00030 00031 static struct eapol_callbacks eapol_cb; 00032 00033 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */ 00034 00035 #define setPortAuthorized() \ 00036 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1) 00037 #define setPortUnauthorized() \ 00038 sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0) 00039 00040 /* procedures */ 00041 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0) 00042 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1) 00043 #define txReq() eapol_auth_tx_req(sm) 00044 #define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta) 00045 #define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta) 00046 #define processKey() do { } while (0) 00047 00048 00049 static void eapol_sm_step_run(struct eapol_state_machine *sm); 00050 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx); 00051 static void eapol_auth_initialize(struct eapol_state_machine *sm); 00052 00053 00054 static void eapol_auth_logger(struct eapol_authenticator *eapol, 00055 const u8 *addr, eapol_logger_level level, 00056 const char *txt) 00057 { 00058 if (eapol->cb.logger == NULL) 00059 return; 00060 eapol->cb.logger(eapol->conf.ctx, addr, level, txt); 00061 } 00062 00063 00064 static void eapol_auth_vlogger(struct eapol_authenticator *eapol, 00065 const u8 *addr, eapol_logger_level level, 00066 const char *fmt, ...) 00067 { 00068 char *format; 00069 int maxlen; 00070 va_list ap; 00071 00072 if (eapol->cb.logger == NULL) 00073 return; 00074 00075 maxlen = os_strlen(fmt) + 100; 00076 format = os_malloc(maxlen); 00077 if (!format) 00078 return; 00079 00080 va_start(ap, fmt); 00081 vsnprintf(format, maxlen, fmt, ap); 00082 va_end(ap); 00083 00084 eapol_auth_logger(eapol, addr, level, format); 00085 00086 os_free(format); 00087 } 00088 00089 00090 static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm, 00091 int success) 00092 { 00093 struct eap_hdr eap; 00094 00095 os_memset(&eap, 0, sizeof(eap)); 00096 00097 eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; 00098 eap.identifier = ++sm->last_eap_id; 00099 eap.length = host_to_be16(sizeof(eap)); 00100 00101 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, 00102 "Sending canned EAP packet %s (identifier %d)", 00103 success ? "SUCCESS" : "FAILURE", eap.identifier); 00104 sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, 00105 IEEE802_1X_TYPE_EAP_PACKET, 00106 (u8 *) &eap, sizeof(eap)); 00107 sm->dot1xAuthEapolFramesTx++; 00108 } 00109 00110 00111 static void eapol_auth_tx_req(struct eapol_state_machine *sm) 00112 { 00113 if (sm->eap_if->eapReqData == NULL || 00114 wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) { 00115 eapol_auth_logger(sm->eapol, sm->addr, 00116 EAPOL_LOGGER_DEBUG, 00117 "TxReq called, but there is no EAP request " 00118 "from authentication server"); 00119 return; 00120 } 00121 00122 if (sm->flags & EAPOL_SM_WAIT_START) { 00123 wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR 00124 " while waiting for EAPOL-Start", 00125 MAC2STR(sm->addr)); 00126 return; 00127 } 00128 00129 sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData); 00130 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, 00131 "Sending EAP Packet (identifier %d)", 00132 sm->last_eap_id); 00133 sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, 00134 IEEE802_1X_TYPE_EAP_PACKET, 00135 wpabuf_head(sm->eap_if->eapReqData), 00136 wpabuf_len(sm->eap_if->eapReqData)); 00137 sm->dot1xAuthEapolFramesTx++; 00138 if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY) 00139 sm->dot1xAuthEapolReqIdFramesTx++; 00140 else 00141 sm->dot1xAuthEapolReqFramesTx++; 00142 } 00143 00144 00153 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) 00154 { 00155 struct eapol_state_machine *state = timeout_ctx; 00156 00157 if (state->aWhile > 0) { 00158 state->aWhile--; 00159 if (state->aWhile == 0) { 00160 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 00161 " - aWhile --> 0", 00162 MAC2STR(state->addr)); 00163 } 00164 } 00165 00166 if (state->quietWhile > 0) { 00167 state->quietWhile--; 00168 if (state->quietWhile == 0) { 00169 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 00170 " - quietWhile --> 0", 00171 MAC2STR(state->addr)); 00172 } 00173 } 00174 00175 if (state->reAuthWhen > 0) { 00176 state->reAuthWhen--; 00177 if (state->reAuthWhen == 0) { 00178 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 00179 " - reAuthWhen --> 0", 00180 MAC2STR(state->addr)); 00181 } 00182 } 00183 00184 if (state->eap_if->retransWhile > 0) { 00185 state->eap_if->retransWhile--; 00186 if (state->eap_if->retransWhile == 0) { 00187 wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR 00188 " - (EAP) retransWhile --> 0", 00189 MAC2STR(state->addr)); 00190 } 00191 } 00192 00193 eapol_sm_step_run(state); 00194 00195 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state); 00196 } 00197 00198 00199 00200 /* Authenticator PAE state machine */ 00201 00202 SM_STATE(AUTH_PAE, INITIALIZE) 00203 { 00204 SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae); 00205 sm->portMode = Auto; 00206 } 00207 00208 00209 SM_STATE(AUTH_PAE, DISCONNECTED) 00210 { 00211 int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE; 00212 00213 if (sm->eapolLogoff) { 00214 if (sm->auth_pae_state == AUTH_PAE_CONNECTING) 00215 sm->authEapLogoffsWhileConnecting++; 00216 else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) 00217 sm->authAuthEapLogoffWhileAuthenticated++; 00218 } 00219 00220 SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae); 00221 00222 sm->authPortStatus = Unauthorized; 00223 setPortUnauthorized(); 00224 sm->reAuthCount = 0; 00225 sm->eapolLogoff = FALSE; 00226 if (!from_initialize) { 00227 sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, 00228 sm->flags & EAPOL_SM_PREAUTH); 00229 } 00230 } 00231 00232 00233 SM_STATE(AUTH_PAE, RESTART) 00234 { 00235 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) { 00236 if (sm->reAuthenticate) 00237 sm->authAuthReauthsWhileAuthenticated++; 00238 if (sm->eapolStart) 00239 sm->authAuthEapStartsWhileAuthenticated++; 00240 if (sm->eapolLogoff) 00241 sm->authAuthEapLogoffWhileAuthenticated++; 00242 } 00243 00244 SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); 00245 00246 sm->eap_if->eapRestart = TRUE; 00247 } 00248 00249 00250 SM_STATE(AUTH_PAE, CONNECTING) 00251 { 00252 if (sm->auth_pae_state != AUTH_PAE_CONNECTING) 00253 sm->authEntersConnecting++; 00254 00255 SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); 00256 00257 sm->reAuthenticate = FALSE; 00258 sm->reAuthCount++; 00259 } 00260 00261 00262 SM_STATE(AUTH_PAE, HELD) 00263 { 00264 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail) 00265 sm->authAuthFailWhileAuthenticating++; 00266 00267 SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae); 00268 00269 sm->authPortStatus = Unauthorized; 00270 setPortUnauthorized(); 00271 sm->quietWhile = sm->quietPeriod; 00272 sm->eapolLogoff = FALSE; 00273 00274 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, 00275 "authentication failed - EAP type: %d (%s)", 00276 sm->eap_type_authsrv, 00277 eap_server_get_name(0, sm->eap_type_authsrv)); 00278 if (sm->eap_type_authsrv != sm->eap_type_supp) { 00279 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, 00280 "Supplicant used different EAP type: " 00281 "%d (%s)", sm->eap_type_supp, 00282 eap_server_get_name(0, sm->eap_type_supp)); 00283 } 00284 sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, 00285 sm->flags & EAPOL_SM_PREAUTH); 00286 } 00287 00288 00289 SM_STATE(AUTH_PAE, AUTHENTICATED) 00290 { 00291 char *extra = ""; 00292 00293 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess) 00294 sm->authAuthSuccessesWhileAuthenticating++; 00295 00296 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae); 00297 00298 sm->authPortStatus = Authorized; 00299 setPortAuthorized(); 00300 sm->reAuthCount = 0; 00301 if (sm->flags & EAPOL_SM_PREAUTH) 00302 extra = " (pre-authentication)"; 00303 else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE) 00304 extra = " (PMKSA cache)"; 00305 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, 00306 "authenticated - EAP type: %d (%s)%s", 00307 sm->eap_type_authsrv, 00308 eap_server_get_name(0, sm->eap_type_authsrv), 00309 extra); 00310 sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1, 00311 sm->flags & EAPOL_SM_PREAUTH); 00312 } 00313 00314 00315 SM_STATE(AUTH_PAE, AUTHENTICATING) 00316 { 00317 SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); 00318 00319 sm->eapolStart = FALSE; 00320 sm->authSuccess = FALSE; 00321 sm->authFail = FALSE; 00322 sm->authTimeout = FALSE; 00323 sm->authStart = TRUE; 00324 sm->keyRun = FALSE; 00325 sm->keyDone = FALSE; 00326 } 00327 00328 00329 SM_STATE(AUTH_PAE, ABORTING) 00330 { 00331 if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) { 00332 if (sm->authTimeout) 00333 sm->authAuthTimeoutsWhileAuthenticating++; 00334 if (sm->eapolStart) 00335 sm->authAuthEapStartsWhileAuthenticating++; 00336 if (sm->eapolLogoff) 00337 sm->authAuthEapLogoffWhileAuthenticating++; 00338 } 00339 00340 SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); 00341 00342 sm->authAbort = TRUE; 00343 sm->keyRun = FALSE; 00344 sm->keyDone = FALSE; 00345 } 00346 00347 00348 SM_STATE(AUTH_PAE, FORCE_AUTH) 00349 { 00350 SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae); 00351 00352 sm->authPortStatus = Authorized; 00353 setPortAuthorized(); 00354 sm->portMode = ForceAuthorized; 00355 sm->eapolStart = FALSE; 00356 txCannedSuccess(); 00357 } 00358 00359 00360 SM_STATE(AUTH_PAE, FORCE_UNAUTH) 00361 { 00362 SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae); 00363 00364 sm->authPortStatus = Unauthorized; 00365 setPortUnauthorized(); 00366 sm->portMode = ForceUnauthorized; 00367 sm->eapolStart = FALSE; 00368 txCannedFail(); 00369 } 00370 00371 00372 SM_STEP(AUTH_PAE) 00373 { 00374 if ((sm->portControl == Auto && sm->portMode != sm->portControl) || 00375 sm->initialize || !sm->eap_if->portEnabled) 00376 SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE); 00377 else if (sm->portControl == ForceAuthorized && 00378 sm->portMode != sm->portControl && 00379 !(sm->initialize || !sm->eap_if->portEnabled)) 00380 SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH); 00381 else if (sm->portControl == ForceUnauthorized && 00382 sm->portMode != sm->portControl && 00383 !(sm->initialize || !sm->eap_if->portEnabled)) 00384 SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH); 00385 else { 00386 switch (sm->auth_pae_state) { 00387 case AUTH_PAE_INITIALIZE: 00388 SM_ENTER(AUTH_PAE, DISCONNECTED); 00389 break; 00390 case AUTH_PAE_DISCONNECTED: 00391 SM_ENTER(AUTH_PAE, RESTART); 00392 break; 00393 case AUTH_PAE_RESTART: 00394 if (!sm->eap_if->eapRestart) 00395 SM_ENTER(AUTH_PAE, CONNECTING); 00396 break; 00397 case AUTH_PAE_HELD: 00398 if (sm->quietWhile == 0) 00399 SM_ENTER(AUTH_PAE, RESTART); 00400 break; 00401 case AUTH_PAE_CONNECTING: 00402 if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax) 00403 SM_ENTER(AUTH_PAE, DISCONNECTED); 00404 else if ((sm->eap_if->eapReq && 00405 sm->reAuthCount <= sm->reAuthMax) || 00406 sm->eap_if->eapSuccess || sm->eap_if->eapFail) 00407 SM_ENTER(AUTH_PAE, AUTHENTICATING); 00408 break; 00409 case AUTH_PAE_AUTHENTICATED: 00410 if (sm->eapolStart || sm->reAuthenticate) 00411 SM_ENTER(AUTH_PAE, RESTART); 00412 else if (sm->eapolLogoff || !sm->portValid) 00413 SM_ENTER(AUTH_PAE, DISCONNECTED); 00414 break; 00415 case AUTH_PAE_AUTHENTICATING: 00416 if (sm->authSuccess && sm->portValid) 00417 SM_ENTER(AUTH_PAE, AUTHENTICATED); 00418 else if (sm->authFail || 00419 (sm->keyDone && !sm->portValid)) 00420 SM_ENTER(AUTH_PAE, HELD); 00421 else if (sm->eapolStart || sm->eapolLogoff || 00422 sm->authTimeout) 00423 SM_ENTER(AUTH_PAE, ABORTING); 00424 break; 00425 case AUTH_PAE_ABORTING: 00426 if (sm->eapolLogoff && !sm->authAbort) 00427 SM_ENTER(AUTH_PAE, DISCONNECTED); 00428 else if (!sm->eapolLogoff && !sm->authAbort) 00429 SM_ENTER(AUTH_PAE, RESTART); 00430 break; 00431 case AUTH_PAE_FORCE_AUTH: 00432 if (sm->eapolStart) 00433 SM_ENTER(AUTH_PAE, FORCE_AUTH); 00434 break; 00435 case AUTH_PAE_FORCE_UNAUTH: 00436 if (sm->eapolStart) 00437 SM_ENTER(AUTH_PAE, FORCE_UNAUTH); 00438 break; 00439 } 00440 } 00441 } 00442 00443 00444 00445 /* Backend Authentication state machine */ 00446 00447 SM_STATE(BE_AUTH, INITIALIZE) 00448 { 00449 SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); 00450 00451 abortAuth(); 00452 sm->eap_if->eapNoReq = FALSE; 00453 sm->authAbort = FALSE; 00454 } 00455 00456 00457 SM_STATE(BE_AUTH, REQUEST) 00458 { 00459 SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); 00460 00461 txReq(); 00462 sm->eap_if->eapReq = FALSE; 00463 sm->backendOtherRequestsToSupplicant++; 00464 00465 /* 00466 * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but 00467 * it looks like this would be logical thing to do there since the old 00468 * EAP response would not be valid anymore after the new EAP request 00469 * was sent out. 00470 * 00471 * A race condition has been reported, in which hostapd ended up 00472 * sending out EAP-Response/Identity as a response to the first 00473 * EAP-Request from the main EAP method. This can be avoided by 00474 * clearing eapolEap here. 00475 */ 00476 sm->eapolEap = FALSE; 00477 } 00478 00479 00480 SM_STATE(BE_AUTH, RESPONSE) 00481 { 00482 SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); 00483 00484 sm->authTimeout = FALSE; 00485 sm->eapolEap = FALSE; 00486 sm->eap_if->eapNoReq = FALSE; 00487 sm->aWhile = sm->serverTimeout; 00488 sm->eap_if->eapResp = TRUE; 00489 /* sendRespToServer(); */ 00490 sm->backendResponses++; 00491 } 00492 00493 00494 SM_STATE(BE_AUTH, SUCCESS) 00495 { 00496 SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); 00497 00498 txReq(); 00499 sm->authSuccess = TRUE; 00500 sm->keyRun = TRUE; 00501 } 00502 00503 00504 SM_STATE(BE_AUTH, FAIL) 00505 { 00506 SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); 00507 00508 txReq(); 00509 sm->authFail = TRUE; 00510 } 00511 00512 00513 SM_STATE(BE_AUTH, TIMEOUT) 00514 { 00515 SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); 00516 00517 sm->authTimeout = TRUE; 00518 } 00519 00520 00521 SM_STATE(BE_AUTH, IDLE) 00522 { 00523 SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); 00524 00525 sm->authStart = FALSE; 00526 } 00527 00528 00529 SM_STATE(BE_AUTH, IGNORE) 00530 { 00531 SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); 00532 00533 sm->eap_if->eapNoReq = FALSE; 00534 } 00535 00536 00537 SM_STEP(BE_AUTH) 00538 { 00539 if (sm->portControl != Auto || sm->initialize || sm->authAbort) { 00540 SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE); 00541 return; 00542 } 00543 00544 switch (sm->be_auth_state) { 00545 case BE_AUTH_INITIALIZE: 00546 SM_ENTER(BE_AUTH, IDLE); 00547 break; 00548 case BE_AUTH_REQUEST: 00549 if (sm->eapolEap) 00550 SM_ENTER(BE_AUTH, RESPONSE); 00551 else if (sm->eap_if->eapReq) 00552 SM_ENTER(BE_AUTH, REQUEST); 00553 else if (sm->eap_if->eapTimeout) 00554 SM_ENTER(BE_AUTH, TIMEOUT); 00555 break; 00556 case BE_AUTH_RESPONSE: 00557 if (sm->eap_if->eapNoReq) 00558 SM_ENTER(BE_AUTH, IGNORE); 00559 if (sm->eap_if->eapReq) { 00560 sm->backendAccessChallenges++; 00561 SM_ENTER(BE_AUTH, REQUEST); 00562 } else if (sm->aWhile == 0) 00563 SM_ENTER(BE_AUTH, TIMEOUT); 00564 else if (sm->eap_if->eapFail) { 00565 sm->backendAuthFails++; 00566 SM_ENTER(BE_AUTH, FAIL); 00567 } else if (sm->eap_if->eapSuccess) { 00568 sm->backendAuthSuccesses++; 00569 SM_ENTER(BE_AUTH, SUCCESS); 00570 } 00571 break; 00572 case BE_AUTH_SUCCESS: 00573 SM_ENTER(BE_AUTH, IDLE); 00574 break; 00575 case BE_AUTH_FAIL: 00576 SM_ENTER(BE_AUTH, IDLE); 00577 break; 00578 case BE_AUTH_TIMEOUT: 00579 SM_ENTER(BE_AUTH, IDLE); 00580 break; 00581 case BE_AUTH_IDLE: 00582 if (sm->eap_if->eapFail && sm->authStart) 00583 SM_ENTER(BE_AUTH, FAIL); 00584 else if (sm->eap_if->eapReq && sm->authStart) 00585 SM_ENTER(BE_AUTH, REQUEST); 00586 else if (sm->eap_if->eapSuccess && sm->authStart) 00587 SM_ENTER(BE_AUTH, SUCCESS); 00588 break; 00589 case BE_AUTH_IGNORE: 00590 if (sm->eapolEap) 00591 SM_ENTER(BE_AUTH, RESPONSE); 00592 else if (sm->eap_if->eapReq) 00593 SM_ENTER(BE_AUTH, REQUEST); 00594 else if (sm->eap_if->eapTimeout) 00595 SM_ENTER(BE_AUTH, TIMEOUT); 00596 break; 00597 } 00598 } 00599 00600 00601 00602 /* Reauthentication Timer state machine */ 00603 00604 SM_STATE(REAUTH_TIMER, INITIALIZE) 00605 { 00606 SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer); 00607 00608 sm->reAuthWhen = sm->reAuthPeriod; 00609 } 00610 00611 00612 SM_STATE(REAUTH_TIMER, REAUTHENTICATE) 00613 { 00614 SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); 00615 00616 sm->reAuthenticate = TRUE; 00617 sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, 00618 EAPOL_AUTH_REAUTHENTICATE); 00619 } 00620 00621 00622 SM_STEP(REAUTH_TIMER) 00623 { 00624 if (sm->portControl != Auto || sm->initialize || 00625 sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { 00626 SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE); 00627 return; 00628 } 00629 00630 switch (sm->reauth_timer_state) { 00631 case REAUTH_TIMER_INITIALIZE: 00632 if (sm->reAuthWhen == 0) 00633 SM_ENTER(REAUTH_TIMER, REAUTHENTICATE); 00634 break; 00635 case REAUTH_TIMER_REAUTHENTICATE: 00636 SM_ENTER(REAUTH_TIMER, INITIALIZE); 00637 break; 00638 } 00639 } 00640 00641 00642 00643 /* Authenticator Key Transmit state machine */ 00644 00645 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) 00646 { 00647 SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx); 00648 } 00649 00650 00651 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) 00652 { 00653 SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); 00654 00655 txKey(); 00656 sm->eap_if->eapKeyAvailable = FALSE; 00657 sm->keyDone = TRUE; 00658 } 00659 00660 00661 SM_STEP(AUTH_KEY_TX) 00662 { 00663 if (sm->initialize || sm->portControl != Auto) { 00664 SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT); 00665 return; 00666 } 00667 00668 switch (sm->auth_key_tx_state) { 00669 case AUTH_KEY_TX_NO_KEY_TRANSMIT: 00670 if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable && 00671 sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA)) 00672 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); 00673 break; 00674 case AUTH_KEY_TX_KEY_TRANSMIT: 00675 if (!sm->keyTxEnabled || !sm->keyRun) 00676 SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); 00677 else if (sm->eap_if->eapKeyAvailable) 00678 SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); 00679 break; 00680 } 00681 } 00682 00683 00684 00685 /* Key Receive state machine */ 00686 00687 SM_STATE(KEY_RX, NO_KEY_RECEIVE) 00688 { 00689 SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx); 00690 } 00691 00692 00693 SM_STATE(KEY_RX, KEY_RECEIVE) 00694 { 00695 SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); 00696 00697 processKey(); 00698 sm->rxKey = FALSE; 00699 } 00700 00701 00702 SM_STEP(KEY_RX) 00703 { 00704 if (sm->initialize || !sm->eap_if->portEnabled) { 00705 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); 00706 return; 00707 } 00708 00709 switch (sm->key_rx_state) { 00710 case KEY_RX_NO_KEY_RECEIVE: 00711 if (sm->rxKey) 00712 SM_ENTER(KEY_RX, KEY_RECEIVE); 00713 break; 00714 case KEY_RX_KEY_RECEIVE: 00715 if (sm->rxKey) 00716 SM_ENTER(KEY_RX, KEY_RECEIVE); 00717 break; 00718 } 00719 } 00720 00721 00722 00723 /* Controlled Directions state machine */ 00724 00725 SM_STATE(CTRL_DIR, FORCE_BOTH) 00726 { 00727 SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir); 00728 sm->operControlledDirections = Both; 00729 } 00730 00731 00732 SM_STATE(CTRL_DIR, IN_OR_BOTH) 00733 { 00734 SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir); 00735 sm->operControlledDirections = sm->adminControlledDirections; 00736 } 00737 00738 00739 SM_STEP(CTRL_DIR) 00740 { 00741 if (sm->initialize) { 00742 SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH); 00743 return; 00744 } 00745 00746 switch (sm->ctrl_dir_state) { 00747 case CTRL_DIR_FORCE_BOTH: 00748 if (sm->eap_if->portEnabled && sm->operEdge) 00749 SM_ENTER(CTRL_DIR, IN_OR_BOTH); 00750 break; 00751 case CTRL_DIR_IN_OR_BOTH: 00752 if (sm->operControlledDirections != 00753 sm->adminControlledDirections) 00754 SM_ENTER(CTRL_DIR, IN_OR_BOTH); 00755 if (!sm->eap_if->portEnabled || !sm->operEdge) 00756 SM_ENTER(CTRL_DIR, FORCE_BOTH); 00757 break; 00758 } 00759 } 00760 00761 00762 00763 struct eapol_state_machine * 00764 eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, 00765 int flags, const struct wpabuf *assoc_wps_ie, void *sta_ctx) 00766 { 00767 struct eapol_state_machine *sm; 00768 struct eap_config eap_conf; 00769 00770 if (eapol == NULL) 00771 return NULL; 00772 00773 sm = os_zalloc(sizeof(*sm)); 00774 if (sm == NULL) { 00775 wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation " 00776 "failed"); 00777 return NULL; 00778 } 00779 sm->radius_identifier = -1; 00780 os_memcpy(sm->addr, addr, ETH_ALEN); 00781 sm->flags = flags; 00782 00783 sm->eapol = eapol; 00784 sm->sta = sta_ctx; 00785 00786 /* Set default values for state machine constants */ 00787 sm->auth_pae_state = AUTH_PAE_INITIALIZE; 00788 sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod; 00789 sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax; 00790 00791 sm->be_auth_state = BE_AUTH_INITIALIZE; 00792 sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout; 00793 00794 sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; 00795 sm->reAuthPeriod = eapol->conf.eap_reauth_period; 00796 sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; 00797 00798 sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; 00799 00800 sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE; 00801 00802 sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH; 00803 00804 sm->portControl = Auto; 00805 00806 if (!eapol->conf.wpa && 00807 (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) 00808 sm->keyTxEnabled = TRUE; 00809 else 00810 sm->keyTxEnabled = FALSE; 00811 if (eapol->conf.wpa) 00812 sm->portValid = FALSE; 00813 else 00814 sm->portValid = TRUE; 00815 00816 os_memset(&eap_conf, 0, sizeof(eap_conf)); 00817 eap_conf.eap_server = eapol->conf.eap_server; 00818 eap_conf.ssl_ctx = eapol->conf.ssl_ctx; 00819 eap_conf.msg_ctx = eapol->conf.msg_ctx; 00820 eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv; 00821 eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key; 00822 eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id; 00823 eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len; 00824 eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info; 00825 eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov; 00826 eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime; 00827 eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time; 00828 eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind; 00829 eap_conf.tnc = eapol->conf.tnc; 00830 eap_conf.wps = eapol->conf.wps; 00831 eap_conf.assoc_wps_ie = assoc_wps_ie; 00832 eap_conf.peer_addr = addr; 00833 sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf); 00834 if (sm->eap == NULL) { 00835 eapol_auth_free(sm); 00836 return NULL; 00837 } 00838 sm->eap_if = eap_get_interface(sm->eap); 00839 00840 eapol_auth_initialize(sm); 00841 00842 return sm; 00843 } 00844 00845 00846 void eapol_auth_free(struct eapol_state_machine *sm) 00847 { 00848 if (sm == NULL) 00849 return; 00850 00851 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 00852 eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); 00853 if (sm->eap) 00854 eap_server_sm_deinit(sm->eap); 00855 os_free(sm); 00856 } 00857 00858 00859 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol, 00860 const u8 *addr) 00861 { 00862 return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr); 00863 } 00864 00865 00866 static void eapol_sm_step_run(struct eapol_state_machine *sm) 00867 { 00868 struct eapol_authenticator *eapol = sm->eapol; 00869 u8 addr[ETH_ALEN]; 00870 unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, 00871 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; 00872 int max_steps = 100; 00873 00874 os_memcpy(addr, sm->addr, ETH_ALEN); 00875 00876 /* 00877 * Allow EAPOL state machines to run as long as there are state 00878 * changes, but exit and return here through event loop if more than 00879 * 100 steps is needed as a precaution against infinite loops inside 00880 * eloop callback. 00881 */ 00882 restart: 00883 prev_auth_pae = sm->auth_pae_state; 00884 prev_be_auth = sm->be_auth_state; 00885 prev_reauth_timer = sm->reauth_timer_state; 00886 prev_auth_key_tx = sm->auth_key_tx_state; 00887 prev_key_rx = sm->key_rx_state; 00888 prev_ctrl_dir = sm->ctrl_dir_state; 00889 00890 SM_STEP_RUN(AUTH_PAE); 00891 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 00892 SM_STEP_RUN(BE_AUTH); 00893 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 00894 SM_STEP_RUN(REAUTH_TIMER); 00895 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 00896 SM_STEP_RUN(AUTH_KEY_TX); 00897 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 00898 SM_STEP_RUN(KEY_RX); 00899 if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) 00900 SM_STEP_RUN(CTRL_DIR); 00901 00902 if (prev_auth_pae != sm->auth_pae_state || 00903 prev_be_auth != sm->be_auth_state || 00904 prev_reauth_timer != sm->reauth_timer_state || 00905 prev_auth_key_tx != sm->auth_key_tx_state || 00906 prev_key_rx != sm->key_rx_state || 00907 prev_ctrl_dir != sm->ctrl_dir_state) { 00908 if (--max_steps > 0) 00909 goto restart; 00910 /* Re-run from eloop timeout */ 00911 eapol_auth_step(sm); 00912 return; 00913 } 00914 00915 if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) { 00916 if (eap_server_sm_step(sm->eap)) { 00917 if (--max_steps > 0) 00918 goto restart; 00919 /* Re-run from eloop timeout */ 00920 eapol_auth_step(sm); 00921 return; 00922 } 00923 00924 /* TODO: find a better location for this */ 00925 if (sm->eap_if->aaaEapResp) { 00926 sm->eap_if->aaaEapResp = FALSE; 00927 if (sm->eap_if->aaaEapRespData == NULL) { 00928 wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " 00929 "but no aaaEapRespData available"); 00930 return; 00931 } 00932 sm->eapol->cb.aaa_send( 00933 sm->eapol->conf.ctx, sm->sta, 00934 wpabuf_head(sm->eap_if->aaaEapRespData), 00935 wpabuf_len(sm->eap_if->aaaEapRespData)); 00936 } 00937 } 00938 00939 if (eapol_sm_sta_entry_alive(eapol, addr)) 00940 sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, 00941 EAPOL_AUTH_SM_CHANGE); 00942 } 00943 00944 00945 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx) 00946 { 00947 struct eapol_state_machine *sm = eloop_ctx; 00948 eapol_sm_step_run(sm); 00949 } 00950 00951 00959 void eapol_auth_step(struct eapol_state_machine *sm) 00960 { 00961 /* 00962 * Run eapol_sm_step_run from a registered timeout to make sure that 00963 * other possible timeouts/events are processed and to avoid long 00964 * function call chains. 00965 */ 00966 00967 eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL); 00968 } 00969 00970 00971 static void eapol_auth_initialize(struct eapol_state_machine *sm) 00972 { 00973 sm->initializing = TRUE; 00974 /* Initialize the state machines by asserting initialize and then 00975 * deasserting it after one step */ 00976 sm->initialize = TRUE; 00977 eapol_sm_step_run(sm); 00978 sm->initialize = FALSE; 00979 eapol_sm_step_run(sm); 00980 sm->initializing = FALSE; 00981 00982 /* Start one second tick for port timers state machine */ 00983 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); 00984 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); 00985 } 00986 00987 00988 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity, 00989 size_t identity_len, int phase2, 00990 struct eap_user *user) 00991 { 00992 struct eapol_state_machine *sm = ctx; 00993 return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity, 00994 identity_len, phase2, user); 00995 } 00996 00997 00998 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len) 00999 { 01000 struct eapol_state_machine *sm = ctx; 01001 *len = sm->eapol->conf.eap_req_id_text_len; 01002 return sm->eapol->conf.eap_req_id_text; 01003 } 01004 01005 01006 static struct eapol_callbacks eapol_cb = 01007 { 01008 eapol_sm_get_eap_user, 01009 eapol_sm_get_eap_req_id_text 01010 }; 01011 01012 01013 int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx) 01014 { 01015 if (sm == NULL || ctx != sm->eap) 01016 return -1; 01017 01018 eap_sm_pending_cb(sm->eap); 01019 eapol_auth_step(sm); 01020 01021 return 0; 01022 } 01023 01024 01025 static int eapol_auth_conf_clone(struct eapol_auth_config *dst, 01026 struct eapol_auth_config *src) 01027 { 01028 dst->ctx = src->ctx; 01029 dst->eap_reauth_period = src->eap_reauth_period; 01030 dst->wpa = src->wpa; 01031 dst->individual_wep_key_len = src->individual_wep_key_len; 01032 dst->eap_server = src->eap_server; 01033 dst->ssl_ctx = src->ssl_ctx; 01034 dst->msg_ctx = src->msg_ctx; 01035 dst->eap_sim_db_priv = src->eap_sim_db_priv; 01036 os_free(dst->eap_req_id_text); 01037 if (src->eap_req_id_text) { 01038 dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len); 01039 if (dst->eap_req_id_text == NULL) 01040 return -1; 01041 os_memcpy(dst->eap_req_id_text, src->eap_req_id_text, 01042 src->eap_req_id_text_len); 01043 dst->eap_req_id_text_len = src->eap_req_id_text_len; 01044 } else { 01045 dst->eap_req_id_text = NULL; 01046 dst->eap_req_id_text_len = 0; 01047 } 01048 if (src->pac_opaque_encr_key) { 01049 dst->pac_opaque_encr_key = os_malloc(16); 01050 os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key, 01051 16); 01052 } else 01053 dst->pac_opaque_encr_key = NULL; 01054 if (src->eap_fast_a_id) { 01055 dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len); 01056 if (dst->eap_fast_a_id == NULL) { 01057 os_free(dst->eap_req_id_text); 01058 return -1; 01059 } 01060 os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id, 01061 src->eap_fast_a_id_len); 01062 dst->eap_fast_a_id_len = src->eap_fast_a_id_len; 01063 } else 01064 dst->eap_fast_a_id = NULL; 01065 if (src->eap_fast_a_id_info) { 01066 dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info); 01067 if (dst->eap_fast_a_id_info == NULL) { 01068 os_free(dst->eap_req_id_text); 01069 os_free(dst->eap_fast_a_id); 01070 return -1; 01071 } 01072 } else 01073 dst->eap_fast_a_id_info = NULL; 01074 dst->eap_fast_prov = src->eap_fast_prov; 01075 dst->pac_key_lifetime = src->pac_key_lifetime; 01076 dst->pac_key_refresh_time = src->pac_key_refresh_time; 01077 dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind; 01078 dst->tnc = src->tnc; 01079 dst->wps = src->wps; 01080 return 0; 01081 } 01082 01083 01084 static void eapol_auth_conf_free(struct eapol_auth_config *conf) 01085 { 01086 os_free(conf->eap_req_id_text); 01087 conf->eap_req_id_text = NULL; 01088 os_free(conf->pac_opaque_encr_key); 01089 conf->pac_opaque_encr_key = NULL; 01090 os_free(conf->eap_fast_a_id); 01091 conf->eap_fast_a_id = NULL; 01092 os_free(conf->eap_fast_a_id_info); 01093 conf->eap_fast_a_id_info = NULL; 01094 } 01095 01096 01097 struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, 01098 struct eapol_auth_cb *cb) 01099 { 01100 struct eapol_authenticator *eapol; 01101 01102 eapol = os_zalloc(sizeof(*eapol)); 01103 if (eapol == NULL) 01104 return NULL; 01105 01106 if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) { 01107 os_free(eapol); 01108 return NULL; 01109 } 01110 01111 if (conf->individual_wep_key_len > 0) { 01112 /* use key0 in individual key and key1 in broadcast key */ 01113 eapol->default_wep_key_idx = 1; 01114 } 01115 01116 eapol->cb.eapol_send = cb->eapol_send; 01117 eapol->cb.aaa_send = cb->aaa_send; 01118 eapol->cb.finished = cb->finished; 01119 eapol->cb.get_eap_user = cb->get_eap_user; 01120 eapol->cb.sta_entry_alive = cb->sta_entry_alive; 01121 eapol->cb.logger = cb->logger; 01122 eapol->cb.set_port_authorized = cb->set_port_authorized; 01123 eapol->cb.abort_auth = cb->abort_auth; 01124 eapol->cb.tx_key = cb->tx_key; 01125 eapol->cb.eapol_event = cb->eapol_event; 01126 01127 return eapol; 01128 } 01129 01130 01131 void eapol_auth_deinit(struct eapol_authenticator *eapol) 01132 { 01133 if (eapol == NULL) 01134 return; 01135 01136 eapol_auth_conf_free(&eapol->conf); 01137 os_free(eapol->default_wep_key); 01138 os_free(eapol); 01139 }