00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
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
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
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
00467
00468
00469
00470
00471
00472
00473
00474
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
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
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
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
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
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
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
00878
00879
00880
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
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
00920 eapol_auth_step(sm);
00921 return;
00922 }
00923
00924
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
00963
00964
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
00975
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
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
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 }