eapol_sm.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "ieee802_1x.h"
00020 #include "eapol_sm.h"
00021 #include "eloop.h"
00022 #include "wpa.h"
00023 #include "preauth.h"
00024 #include "sta_info.h"
00025 #include "eap_server/eap.h"
00026 #include "state_machine.h"
00027 #include "eap_common/eap_common.h"
00028 
00029 #define STATE_MACHINE_DATA struct eapol_state_machine
00030 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
00031 #define STATE_MACHINE_ADDR sm->addr
00032 
00033 static struct eapol_callbacks eapol_cb;
00034 
00035 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
00036 
00037 #define setPortAuthorized() \
00038 sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 1)
00039 #define setPortUnauthorized() \
00040 sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 0)
00041 
00042 /* procedures */
00043 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
00044 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
00045 #define txReq() eapol_auth_tx_req(sm)
00046 #define abortAuth() sm->eapol->cb.abort_auth(sm->hapd, sm->sta)
00047 #define txKey() sm->eapol->cb.tx_key(sm->hapd, sm->sta)
00048 #define processKey() do { } while (0)
00049 
00050 
00051 static void eapol_sm_step_run(struct eapol_state_machine *sm);
00052 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
00053 
00054 
00055 static void eapol_auth_logger(struct eapol_authenticator *eapol,
00056                               const u8 *addr, logger_level level,
00057                               const char *txt)
00058 {
00059         if (eapol->cb.logger == NULL)
00060                 return;
00061         eapol->cb.logger(eapol->conf.hapd, addr, level, txt);
00062 }
00063 
00064 
00065 static void eapol_auth_vlogger(struct eapol_authenticator *eapol,
00066                                const u8 *addr, logger_level level,
00067                                const char *fmt, ...)
00068 {
00069         char *format;
00070         int maxlen;
00071         va_list ap;
00072 
00073         if (eapol->cb.logger == NULL)
00074                 return;
00075 
00076         maxlen = os_strlen(fmt) + 100;
00077         format = os_malloc(maxlen);
00078         if (!format)
00079                 return;
00080 
00081         va_start(ap, fmt);
00082         vsnprintf(format, maxlen, fmt, ap);
00083         va_end(ap);
00084 
00085         eapol_auth_logger(eapol, addr, level, format);
00086 
00087         os_free(format);
00088 }
00089 
00090 
00091 static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
00092                                      int success)
00093 {
00094         struct eap_hdr eap;
00095 
00096         os_memset(&eap, 0, sizeof(eap));
00097 
00098         eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
00099         eap.identifier = ++sm->last_eap_id;
00100         eap.length = host_to_be16(sizeof(eap));
00101 
00102         eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
00103                            "Sending canned EAP packet %s (identifier %d)",
00104                            success ? "SUCCESS" : "FAILURE", eap.identifier);
00105         sm->eapol->cb.eapol_send(sm->hapd, sm->sta, 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->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET,
00134                                  wpabuf_head(sm->eap_if->eapReqData),
00135                                  wpabuf_len(sm->eap_if->eapReqData));
00136         sm->dot1xAuthEapolFramesTx++;
00137         if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY)
00138                 sm->dot1xAuthEapolReqIdFramesTx++;
00139         else
00140                 sm->dot1xAuthEapolReqFramesTx++;
00141 }
00142 
00143 
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->hapd, 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_type_text(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_type_text(sm->eap_type_supp));
00283         }
00284         sm->eapol->cb.finished(sm->hapd, 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 (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm))
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_type_text(sm->eap_type_authsrv), extra);
00309         sm->eapol->cb.finished(sm->hapd, sm->sta, 1,
00310                                sm->flags & EAPOL_SM_PREAUTH);
00311 }
00312 
00313 
00314 SM_STATE(AUTH_PAE, AUTHENTICATING)
00315 {
00316         SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
00317 
00318         sm->eapolStart = FALSE;
00319         sm->authSuccess = FALSE;
00320         sm->authFail = FALSE;
00321         sm->authTimeout = FALSE;
00322         sm->authStart = TRUE;
00323         sm->keyRun = FALSE;
00324         sm->keyDone = FALSE;
00325 }
00326 
00327 
00328 SM_STATE(AUTH_PAE, ABORTING)
00329 {
00330         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
00331                 if (sm->authTimeout)
00332                         sm->authAuthTimeoutsWhileAuthenticating++;
00333                 if (sm->eapolStart)
00334                         sm->authAuthEapStartsWhileAuthenticating++;
00335                 if (sm->eapolLogoff)
00336                         sm->authAuthEapLogoffWhileAuthenticating++;
00337         }
00338 
00339         SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
00340 
00341         sm->authAbort = TRUE;
00342         sm->keyRun = FALSE;
00343         sm->keyDone = FALSE;
00344 }
00345 
00346 
00347 SM_STATE(AUTH_PAE, FORCE_AUTH)
00348 {
00349         SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
00350 
00351         sm->authPortStatus = Authorized;
00352         setPortAuthorized();
00353         sm->portMode = ForceAuthorized;
00354         sm->eapolStart = FALSE;
00355         txCannedSuccess();
00356 }
00357 
00358 
00359 SM_STATE(AUTH_PAE, FORCE_UNAUTH)
00360 {
00361         SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
00362 
00363         sm->authPortStatus = Unauthorized;
00364         setPortUnauthorized();
00365         sm->portMode = ForceUnauthorized;
00366         sm->eapolStart = FALSE;
00367         txCannedFail();
00368 }
00369 
00370 
00371 SM_STEP(AUTH_PAE)
00372 {
00373         if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
00374             sm->initialize || !sm->eap_if->portEnabled)
00375                 SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE);
00376         else if (sm->portControl == ForceAuthorized &&
00377                  sm->portMode != sm->portControl &&
00378                  !(sm->initialize || !sm->eap_if->portEnabled))
00379                 SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH);
00380         else if (sm->portControl == ForceUnauthorized &&
00381                  sm->portMode != sm->portControl &&
00382                  !(sm->initialize || !sm->eap_if->portEnabled))
00383                 SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH);
00384         else {
00385                 switch (sm->auth_pae_state) {
00386                 case AUTH_PAE_INITIALIZE:
00387                         SM_ENTER(AUTH_PAE, DISCONNECTED);
00388                         break;
00389                 case AUTH_PAE_DISCONNECTED:
00390                         SM_ENTER(AUTH_PAE, RESTART);
00391                         break;
00392                 case AUTH_PAE_RESTART:
00393                         if (!sm->eap_if->eapRestart)
00394                                 SM_ENTER(AUTH_PAE, CONNECTING);
00395                         break;
00396                 case AUTH_PAE_HELD:
00397                         if (sm->quietWhile == 0)
00398                                 SM_ENTER(AUTH_PAE, RESTART);
00399                         break;
00400                 case AUTH_PAE_CONNECTING:
00401                         if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
00402                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
00403                         else if ((sm->eap_if->eapReq &&
00404                                   sm->reAuthCount <= sm->reAuthMax) ||
00405                                  sm->eap_if->eapSuccess || sm->eap_if->eapFail)
00406                                 SM_ENTER(AUTH_PAE, AUTHENTICATING);
00407                         break;
00408                 case AUTH_PAE_AUTHENTICATED:
00409                         if (sm->eapolStart || sm->reAuthenticate)
00410                                 SM_ENTER(AUTH_PAE, RESTART);
00411                         else if (sm->eapolLogoff || !sm->portValid)
00412                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
00413                         break;
00414                 case AUTH_PAE_AUTHENTICATING:
00415                         if (sm->authSuccess && sm->portValid)
00416                                 SM_ENTER(AUTH_PAE, AUTHENTICATED);
00417                         else if (sm->authFail ||
00418                                  (sm->keyDone && !sm->portValid))
00419                                 SM_ENTER(AUTH_PAE, HELD);
00420                         else if (sm->eapolStart || sm->eapolLogoff ||
00421                                  sm->authTimeout)
00422                                 SM_ENTER(AUTH_PAE, ABORTING);
00423                         break;
00424                 case AUTH_PAE_ABORTING:
00425                         if (sm->eapolLogoff && !sm->authAbort)
00426                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
00427                         else if (!sm->eapolLogoff && !sm->authAbort)
00428                                 SM_ENTER(AUTH_PAE, RESTART);
00429                         break;
00430                 case AUTH_PAE_FORCE_AUTH:
00431                         if (sm->eapolStart)
00432                                 SM_ENTER(AUTH_PAE, FORCE_AUTH);
00433                         break;
00434                 case AUTH_PAE_FORCE_UNAUTH:
00435                         if (sm->eapolStart)
00436                                 SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
00437                         break;
00438                 }
00439         }
00440 }
00441 
00442 
00443 
00444 /* Backend Authentication state machine */
00445 
00446 SM_STATE(BE_AUTH, INITIALIZE)
00447 {
00448         SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
00449 
00450         abortAuth();
00451         sm->eap_if->eapNoReq = FALSE;
00452         sm->authAbort = FALSE;
00453 }
00454 
00455 
00456 SM_STATE(BE_AUTH, REQUEST)
00457 {
00458         SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
00459 
00460         txReq();
00461         sm->eap_if->eapReq = FALSE;
00462         sm->backendOtherRequestsToSupplicant++;
00463 
00464         /*
00465          * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
00466          * it looks like this would be logical thing to do there since the old
00467          * EAP response would not be valid anymore after the new EAP request
00468          * was sent out.
00469          *
00470          * A race condition has been reported, in which hostapd ended up
00471          * sending out EAP-Response/Identity as a response to the first
00472          * EAP-Request from the main EAP method. This can be avoided by
00473          * clearing eapolEap here.
00474          */
00475         sm->eapolEap = FALSE;
00476 }
00477 
00478 
00479 SM_STATE(BE_AUTH, RESPONSE)
00480 {
00481         SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
00482 
00483         sm->authTimeout = FALSE;
00484         sm->eapolEap = FALSE;
00485         sm->eap_if->eapNoReq = FALSE;
00486         sm->aWhile = sm->serverTimeout;
00487         sm->eap_if->eapResp = TRUE;
00488         /* sendRespToServer(); */
00489         sm->backendResponses++;
00490 }
00491 
00492 
00493 SM_STATE(BE_AUTH, SUCCESS)
00494 {
00495         SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
00496 
00497         txReq();
00498         sm->authSuccess = TRUE;
00499         sm->keyRun = TRUE;
00500 }
00501 
00502 
00503 SM_STATE(BE_AUTH, FAIL)
00504 {
00505         SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
00506 
00507         txReq();
00508         sm->authFail = TRUE;
00509 }
00510 
00511 
00512 SM_STATE(BE_AUTH, TIMEOUT)
00513 {
00514         SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
00515 
00516         sm->authTimeout = TRUE;
00517 }
00518 
00519 
00520 SM_STATE(BE_AUTH, IDLE)
00521 {
00522         SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
00523 
00524         sm->authStart = FALSE;
00525 }
00526 
00527 
00528 SM_STATE(BE_AUTH, IGNORE)
00529 {
00530         SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
00531 
00532         sm->eap_if->eapNoReq = FALSE;
00533 }
00534 
00535 
00536 SM_STEP(BE_AUTH)
00537 {
00538         if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
00539                 SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE);
00540                 return;
00541         }
00542 
00543         switch (sm->be_auth_state) {
00544         case BE_AUTH_INITIALIZE:
00545                 SM_ENTER(BE_AUTH, IDLE);
00546                 break;
00547         case BE_AUTH_REQUEST:
00548                 if (sm->eapolEap)
00549                         SM_ENTER(BE_AUTH, RESPONSE);
00550                 else if (sm->eap_if->eapReq)
00551                         SM_ENTER(BE_AUTH, REQUEST);
00552                 else if (sm->eap_if->eapTimeout)
00553                         SM_ENTER(BE_AUTH, TIMEOUT);
00554                 break;
00555         case BE_AUTH_RESPONSE:
00556                 if (sm->eap_if->eapNoReq)
00557                         SM_ENTER(BE_AUTH, IGNORE);
00558                 if (sm->eap_if->eapReq) {
00559                         sm->backendAccessChallenges++;
00560                         SM_ENTER(BE_AUTH, REQUEST);
00561                 } else if (sm->aWhile == 0)
00562                         SM_ENTER(BE_AUTH, TIMEOUT);
00563                 else if (sm->eap_if->eapFail) {
00564                         sm->backendAuthFails++;
00565                         SM_ENTER(BE_AUTH, FAIL);
00566                 } else if (sm->eap_if->eapSuccess) {
00567                         sm->backendAuthSuccesses++;
00568                         SM_ENTER(BE_AUTH, SUCCESS);
00569                 }
00570                 break;
00571         case BE_AUTH_SUCCESS:
00572                 SM_ENTER(BE_AUTH, IDLE);
00573                 break;
00574         case BE_AUTH_FAIL:
00575                 SM_ENTER(BE_AUTH, IDLE);
00576                 break;
00577         case BE_AUTH_TIMEOUT:
00578                 SM_ENTER(BE_AUTH, IDLE);
00579                 break;
00580         case BE_AUTH_IDLE:
00581                 if (sm->eap_if->eapFail && sm->authStart)
00582                         SM_ENTER(BE_AUTH, FAIL);
00583                 else if (sm->eap_if->eapReq && sm->authStart)
00584                         SM_ENTER(BE_AUTH, REQUEST);
00585                 else if (sm->eap_if->eapSuccess && sm->authStart)
00586                         SM_ENTER(BE_AUTH, SUCCESS);
00587                 break;
00588         case BE_AUTH_IGNORE:
00589                 if (sm->eapolEap)
00590                         SM_ENTER(BE_AUTH, RESPONSE);
00591                 else if (sm->eap_if->eapReq)
00592                         SM_ENTER(BE_AUTH, REQUEST);
00593                 else if (sm->eap_if->eapTimeout)
00594                         SM_ENTER(BE_AUTH, TIMEOUT);
00595                 break;
00596         }
00597 }
00598 
00599 
00600 
00601 /* Reauthentication Timer state machine */
00602 
00603 SM_STATE(REAUTH_TIMER, INITIALIZE)
00604 {
00605         SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
00606 
00607         sm->reAuthWhen = sm->reAuthPeriod;
00608 }
00609 
00610 
00611 SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
00612 {
00613         SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
00614 
00615         sm->reAuthenticate = TRUE;
00616         wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL);
00617 }
00618 
00619 
00620 SM_STEP(REAUTH_TIMER)
00621 {
00622         if (sm->portControl != Auto || sm->initialize ||
00623             sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
00624                 SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE);
00625                 return;
00626         }
00627 
00628         switch (sm->reauth_timer_state) {
00629         case REAUTH_TIMER_INITIALIZE:
00630                 if (sm->reAuthWhen == 0)
00631                         SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
00632                 break;
00633         case REAUTH_TIMER_REAUTHENTICATE:
00634                 SM_ENTER(REAUTH_TIMER, INITIALIZE);
00635                 break;
00636         }
00637 }
00638 
00639 
00640 
00641 /* Authenticator Key Transmit state machine */
00642 
00643 SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
00644 {
00645         SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
00646 }
00647 
00648 
00649 SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
00650 {
00651         SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
00652 
00653         txKey();
00654         sm->eap_if->eapKeyAvailable = FALSE;
00655         sm->keyDone = TRUE;
00656 }
00657 
00658 
00659 SM_STEP(AUTH_KEY_TX)
00660 {
00661         if (sm->initialize || sm->portControl != Auto) {
00662                 SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT);
00663                 return;
00664         }
00665 
00666         switch (sm->auth_key_tx_state) {
00667         case AUTH_KEY_TX_NO_KEY_TRANSMIT:
00668                 if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
00669                     sm->keyRun && !wpa_auth_sta_wpa_version(sm->sta->wpa_sm))
00670                         SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
00671                 break;
00672         case AUTH_KEY_TX_KEY_TRANSMIT:
00673                 if (!sm->keyTxEnabled || !sm->keyRun)
00674                         SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
00675                 else if (sm->eap_if->eapKeyAvailable)
00676                         SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
00677                 break;
00678         }
00679 }
00680 
00681 
00682 
00683 /* Key Receive state machine */
00684 
00685 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
00686 {
00687         SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
00688 }
00689 
00690 
00691 SM_STATE(KEY_RX, KEY_RECEIVE)
00692 {
00693         SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
00694 
00695         processKey();
00696         sm->rxKey = FALSE;
00697 }
00698 
00699 
00700 SM_STEP(KEY_RX)
00701 {
00702         if (sm->initialize || !sm->eap_if->portEnabled) {
00703                 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
00704                 return;
00705         }
00706 
00707         switch (sm->key_rx_state) {
00708         case KEY_RX_NO_KEY_RECEIVE:
00709                 if (sm->rxKey)
00710                         SM_ENTER(KEY_RX, KEY_RECEIVE);
00711                 break;
00712         case KEY_RX_KEY_RECEIVE:
00713                 if (sm->rxKey)
00714                         SM_ENTER(KEY_RX, KEY_RECEIVE);
00715                 break;
00716         }
00717 }
00718 
00719 
00720 
00721 /* Controlled Directions state machine */
00722 
00723 SM_STATE(CTRL_DIR, FORCE_BOTH)
00724 {
00725         SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
00726         sm->operControlledDirections = Both;
00727 }
00728 
00729 
00730 SM_STATE(CTRL_DIR, IN_OR_BOTH)
00731 {
00732         SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
00733         sm->operControlledDirections = sm->adminControlledDirections;
00734 }
00735 
00736 
00737 SM_STEP(CTRL_DIR)
00738 {
00739         if (sm->initialize) {
00740                 SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH);
00741                 return;
00742         }
00743 
00744         switch (sm->ctrl_dir_state) {
00745         case CTRL_DIR_FORCE_BOTH:
00746                 if (sm->eap_if->portEnabled && sm->operEdge)
00747                         SM_ENTER(CTRL_DIR, IN_OR_BOTH);
00748                 break;
00749         case CTRL_DIR_IN_OR_BOTH:
00750                 if (sm->operControlledDirections !=
00751                     sm->adminControlledDirections)
00752                         SM_ENTER(CTRL_DIR, IN_OR_BOTH);
00753                 if (!sm->eap_if->portEnabled || !sm->operEdge)
00754                         SM_ENTER(CTRL_DIR, FORCE_BOTH);
00755                 break;
00756         }
00757 }
00758 
00759 
00760 
00761 struct eapol_state_machine *
00762 eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
00763                  int preauth, struct sta_info *sta)
00764 {
00765         struct eapol_state_machine *sm;
00766         struct hostapd_data *hapd; /* TODO: to be removed */
00767         struct eap_config eap_conf;
00768 
00769         if (eapol == NULL)
00770                 return NULL;
00771         hapd = eapol->conf.hapd;
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         if (preauth)
00782                 sm->flags |= EAPOL_SM_PREAUTH;
00783 
00784         sm->hapd = hapd;
00785         sm->eapol = eapol;
00786         sm->sta = sta;
00787 
00788         /* Set default values for state machine constants */
00789         sm->auth_pae_state = AUTH_PAE_INITIALIZE;
00790         sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
00791         sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
00792 
00793         sm->be_auth_state = BE_AUTH_INITIALIZE;
00794         sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
00795 
00796         sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
00797         sm->reAuthPeriod = eapol->conf.eap_reauth_period;
00798         sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE;
00799 
00800         sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
00801 
00802         sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
00803 
00804         sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
00805 
00806         sm->portControl = Auto;
00807 
00808         if (!eapol->conf.wpa &&
00809             (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
00810                 sm->keyTxEnabled = TRUE;
00811         else
00812                 sm->keyTxEnabled = FALSE;
00813         if (eapol->conf.wpa)
00814                 sm->portValid = FALSE;
00815         else
00816                 sm->portValid = TRUE;
00817 
00818         os_memset(&eap_conf, 0, sizeof(eap_conf));
00819         eap_conf.eap_server = eapol->conf.eap_server;
00820         eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
00821         eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
00822         eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
00823         eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
00824         eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
00825         eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
00826         eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
00827         eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
00828         eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
00829         eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
00830         eap_conf.tnc = eapol->conf.tnc;
00831         eap_conf.wps = eapol->conf.wps;
00832         eap_conf.assoc_wps_ie = sta->wps_ie;
00833         eap_conf.peer_addr = addr;
00834         sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
00835         if (sm->eap == NULL) {
00836                 eapol_auth_free(sm);
00837                 return NULL;
00838         }
00839         sm->eap_if = eap_get_interface(sm->eap);
00840 
00841         eapol_auth_initialize(sm);
00842 
00843         return sm;
00844 }
00845 
00846 
00847 void eapol_auth_free(struct eapol_state_machine *sm)
00848 {
00849         if (sm == NULL)
00850                 return;
00851 
00852         eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
00853         eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
00854         if (sm->eap)
00855                 eap_server_sm_deinit(sm->eap);
00856         os_free(sm);
00857 }
00858 
00859 
00860 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
00861                                     const u8 *addr)
00862 {
00863         return eapol->cb.sta_entry_alive(eapol->conf.hapd, addr);
00864 }
00865 
00866 
00867 static void eapol_sm_step_run(struct eapol_state_machine *sm)
00868 {
00869         struct eapol_authenticator *eapol = sm->eapol;
00870         u8 addr[ETH_ALEN];
00871         unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
00872                 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
00873         int max_steps = 100;
00874 
00875         os_memcpy(addr, sm->addr, ETH_ALEN);
00876 
00877         /*
00878          * Allow EAPOL state machines to run as long as there are state
00879          * changes, but exit and return here through event loop if more than
00880          * 100 steps is needed as a precaution against infinite loops inside
00881          * eloop callback.
00882          */
00883 restart:
00884         prev_auth_pae = sm->auth_pae_state;
00885         prev_be_auth = sm->be_auth_state;
00886         prev_reauth_timer = sm->reauth_timer_state;
00887         prev_auth_key_tx = sm->auth_key_tx_state;
00888         prev_key_rx = sm->key_rx_state;
00889         prev_ctrl_dir = sm->ctrl_dir_state;
00890 
00891         SM_STEP_RUN(AUTH_PAE);
00892         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
00893                 SM_STEP_RUN(BE_AUTH);
00894         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
00895                 SM_STEP_RUN(REAUTH_TIMER);
00896         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
00897                 SM_STEP_RUN(AUTH_KEY_TX);
00898         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
00899                 SM_STEP_RUN(KEY_RX);
00900         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
00901                 SM_STEP_RUN(CTRL_DIR);
00902 
00903         if (prev_auth_pae != sm->auth_pae_state ||
00904             prev_be_auth != sm->be_auth_state ||
00905             prev_reauth_timer != sm->reauth_timer_state ||
00906             prev_auth_key_tx != sm->auth_key_tx_state ||
00907             prev_key_rx != sm->key_rx_state ||
00908             prev_ctrl_dir != sm->ctrl_dir_state) {
00909                 if (--max_steps > 0)
00910                         goto restart;
00911                 /* Re-run from eloop timeout */
00912                 eapol_auth_step(sm);
00913                 return;
00914         }
00915 
00916         if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
00917                 if (eap_server_sm_step(sm->eap)) {
00918                         if (--max_steps > 0)
00919                                 goto restart;
00920                         /* Re-run from eloop timeout */
00921                         eapol_auth_step(sm);
00922                         return;
00923                 }
00924 
00925                 /* TODO: find a better location for this */
00926                 if (sm->eap_if->aaaEapResp) {
00927                         sm->eap_if->aaaEapResp = FALSE;
00928                         if (sm->eap_if->aaaEapRespData == NULL) {
00929                                 wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
00930                                            "but no aaaEapRespData available");
00931                                 return;
00932                         }
00933                         sm->eapol->cb.aaa_send(
00934                                 sm->hapd, sm->sta,
00935                                 wpabuf_head(sm->eap_if->aaaEapRespData),
00936                                 wpabuf_len(sm->eap_if->aaaEapRespData));
00937                 }
00938         }
00939 
00940         if (eapol_sm_sta_entry_alive(eapol, addr))
00941                 wpa_auth_sm_notify(sm->sta->wpa_sm);
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 
00960 void eapol_auth_step(struct eapol_state_machine *sm)
00961 {
00962         /*
00963          * Run eapol_sm_step_run from a registered timeout to make sure that
00964          * other possible timeouts/events are processed and to avoid long
00965          * function call chains.
00966          */
00967 
00968         eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
00969 }
00970 
00971 
00972 void eapol_auth_initialize(struct eapol_state_machine *sm)
00973 {
00974         sm->initializing = TRUE;
00975         /* Initialize the state machines by asserting initialize and then
00976          * deasserting it after one step */
00977         sm->initialize = TRUE;
00978         eapol_sm_step_run(sm);
00979         sm->initialize = FALSE;
00980         eapol_sm_step_run(sm);
00981         sm->initializing = FALSE;
00982 
00983         /* Start one second tick for port timers state machine */
00984         eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
00985         eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
00986 }
00987 
00988 
00989 #ifdef HOSTAPD_DUMP_STATE
00990 static inline const char * port_type_txt(PortTypes pt)
00991 {
00992         switch (pt) {
00993         case ForceUnauthorized: return "ForceUnauthorized";
00994         case ForceAuthorized: return "ForceAuthorized";
00995         case Auto: return "Auto";
00996         default: return "Unknown";
00997         }
00998 }
00999 
01000 
01001 static inline const char * port_state_txt(PortState ps)
01002 {
01003         switch (ps) {
01004         case Unauthorized: return "Unauthorized";
01005         case Authorized: return "Authorized";
01006         default: return "Unknown";
01007         }
01008 }
01009 
01010 
01011 static inline const char * ctrl_dir_txt(ControlledDirection dir)
01012 {
01013         switch (dir) {
01014         case Both: return "Both";
01015         case In: return "In";
01016         default: return "Unknown";
01017         }
01018 }
01019 
01020 
01021 static inline const char * auth_pae_state_txt(int s)
01022 {
01023         switch (s) {
01024         case AUTH_PAE_INITIALIZE: return "INITIALIZE";
01025         case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
01026         case AUTH_PAE_CONNECTING: return "CONNECTING";
01027         case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
01028         case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
01029         case AUTH_PAE_ABORTING: return "ABORTING";
01030         case AUTH_PAE_HELD: return "HELD";
01031         case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
01032         case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
01033         case AUTH_PAE_RESTART: return "RESTART";
01034         default: return "Unknown";
01035         }
01036 }
01037 
01038 
01039 static inline const char * be_auth_state_txt(int s)
01040 {
01041         switch (s) {
01042         case BE_AUTH_REQUEST: return "REQUEST";
01043         case BE_AUTH_RESPONSE: return "RESPONSE";
01044         case BE_AUTH_SUCCESS: return "SUCCESS";
01045         case BE_AUTH_FAIL: return "FAIL";
01046         case BE_AUTH_TIMEOUT: return "TIMEOUT";
01047         case BE_AUTH_IDLE: return "IDLE";
01048         case BE_AUTH_INITIALIZE: return "INITIALIZE";
01049         case BE_AUTH_IGNORE: return "IGNORE";
01050         default: return "Unknown";
01051         }
01052 }
01053 
01054 
01055 static inline const char * reauth_timer_state_txt(int s)
01056 {
01057         switch (s) {
01058         case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
01059         case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
01060         default: return "Unknown";
01061         }
01062 }
01063 
01064 
01065 static inline const char * auth_key_tx_state_txt(int s)
01066 {
01067         switch (s) {
01068         case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
01069         case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
01070         default: return "Unknown";
01071         }
01072 }
01073 
01074 
01075 static inline const char * key_rx_state_txt(int s)
01076 {
01077         switch (s) {
01078         case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
01079         case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
01080         default: return "Unknown";
01081         }
01082 }
01083 
01084 
01085 static inline const char * ctrl_dir_state_txt(int s)
01086 {
01087         switch (s) {
01088         case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
01089         case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
01090         default: return "Unknown";
01091         }
01092 }
01093 
01094 
01095 void eapol_auth_dump_state(FILE *f, const char *prefix,
01096                            struct eapol_state_machine *sm)
01097 {
01098         fprintf(f, "%sEAPOL state machine:\n", prefix);
01099         fprintf(f, "%s  aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
01100                 sm->aWhile, sm->quietWhile, sm->reAuthWhen);
01101 #define _SB(b) ((b) ? "TRUE" : "FALSE")
01102         fprintf(f,
01103                 "%s  authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
01104                 "%s  authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
01105                 "%s  eapSuccess=%s eapTimeout=%s initialize=%s "
01106                 "keyAvailable=%s\n"
01107                 "%s  keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
01108                 "%s  portEnabled=%s portValid=%s reAuthenticate=%s\n",
01109                 prefix, _SB(sm->authAbort), _SB(sm->authFail),
01110                 port_state_txt(sm->authPortStatus), _SB(sm->authStart),
01111                 prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
01112                 _SB(sm->eap_if->eapFail), _SB(sm->eapolEap),
01113                 prefix, _SB(sm->eap_if->eapSuccess),
01114                 _SB(sm->eap_if->eapTimeout),
01115                 _SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable),
01116                 prefix, _SB(sm->keyDone), _SB(sm->keyRun),
01117                 _SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
01118                 prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid),
01119                 _SB(sm->reAuthenticate));
01120 
01121         fprintf(f, "%s  Authenticator PAE:\n"
01122                 "%s    state=%s\n"
01123                 "%s    eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
01124                 "%s    portMode=%s reAuthCount=%d\n"
01125                 "%s    quietPeriod=%d reAuthMax=%d\n"
01126                 "%s    authEntersConnecting=%d\n"
01127                 "%s    authEapLogoffsWhileConnecting=%d\n"
01128                 "%s    authEntersAuthenticating=%d\n"
01129                 "%s    authAuthSuccessesWhileAuthenticating=%d\n"
01130                 "%s    authAuthTimeoutsWhileAuthenticating=%d\n"
01131                 "%s    authAuthFailWhileAuthenticating=%d\n"
01132                 "%s    authAuthEapStartsWhileAuthenticating=%d\n"
01133                 "%s    authAuthEapLogoffWhileAuthenticating=%d\n"
01134                 "%s    authAuthReauthsWhileAuthenticated=%d\n"
01135                 "%s    authAuthEapStartsWhileAuthenticated=%d\n"
01136                 "%s    authAuthEapLogoffWhileAuthenticated=%d\n",
01137                 prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
01138                 _SB(sm->eapolLogoff), _SB(sm->eapolStart),
01139                 _SB(sm->eap_if->eapRestart),
01140                 prefix, port_type_txt(sm->portMode), sm->reAuthCount,
01141                 prefix, sm->quietPeriod, sm->reAuthMax,
01142                 prefix, sm->authEntersConnecting,
01143                 prefix, sm->authEapLogoffsWhileConnecting,
01144                 prefix, sm->authEntersAuthenticating,
01145                 prefix, sm->authAuthSuccessesWhileAuthenticating,
01146                 prefix, sm->authAuthTimeoutsWhileAuthenticating,
01147                 prefix, sm->authAuthFailWhileAuthenticating,
01148                 prefix, sm->authAuthEapStartsWhileAuthenticating,
01149                 prefix, sm->authAuthEapLogoffWhileAuthenticating,
01150                 prefix, sm->authAuthReauthsWhileAuthenticated,
01151                 prefix, sm->authAuthEapStartsWhileAuthenticated,
01152                 prefix, sm->authAuthEapLogoffWhileAuthenticated);
01153 
01154         fprintf(f, "%s  Backend Authentication:\n"
01155                 "%s    state=%s\n"
01156                 "%s    eapNoReq=%s eapReq=%s eapResp=%s\n"
01157                 "%s    serverTimeout=%d\n"
01158                 "%s    backendResponses=%d\n"
01159                 "%s    backendAccessChallenges=%d\n"
01160                 "%s    backendOtherRequestsToSupplicant=%d\n"
01161                 "%s    backendAuthSuccesses=%d\n"
01162                 "%s    backendAuthFails=%d\n",
01163                 prefix, prefix,
01164                 be_auth_state_txt(sm->be_auth_state),
01165                 prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq),
01166                 _SB(sm->eap_if->eapResp),
01167                 prefix, sm->serverTimeout,
01168                 prefix, sm->backendResponses,
01169                 prefix, sm->backendAccessChallenges,
01170                 prefix, sm->backendOtherRequestsToSupplicant,
01171                 prefix, sm->backendAuthSuccesses,
01172                 prefix, sm->backendAuthFails);
01173 
01174         fprintf(f, "%s  Reauthentication Timer:\n"
01175                 "%s    state=%s\n"
01176                 "%s    reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
01177                 reauth_timer_state_txt(sm->reauth_timer_state), prefix,
01178                 sm->reAuthPeriod, _SB(sm->reAuthEnabled));
01179 
01180         fprintf(f, "%s  Authenticator Key Transmit:\n"
01181                 "%s    state=%s\n", prefix, prefix,
01182                 auth_key_tx_state_txt(sm->auth_key_tx_state));
01183 
01184         fprintf(f, "%s  Key Receive:\n"
01185                 "%s    state=%s\n"
01186                 "%s    rxKey=%s\n", prefix, prefix,
01187                 key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
01188 
01189         fprintf(f, "%s  Controlled Directions:\n"
01190                 "%s    state=%s\n"
01191                 "%s    adminControlledDirections=%s "
01192                 "operControlledDirections=%s\n"
01193                 "%s    operEdge=%s\n", prefix, prefix,
01194                 ctrl_dir_state_txt(sm->ctrl_dir_state),
01195                 prefix, ctrl_dir_txt(sm->adminControlledDirections),
01196                 ctrl_dir_txt(sm->operControlledDirections),
01197                 prefix, _SB(sm->operEdge));
01198 #undef _SB
01199 }
01200 #endif /* HOSTAPD_DUMP_STATE */
01201 
01202 
01203 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
01204                                  size_t identity_len, int phase2,
01205                                  struct eap_user *user)
01206 {
01207         struct eapol_state_machine *sm = ctx;
01208         return sm->eapol->cb.get_eap_user(sm->hapd, identity, identity_len,
01209                                           phase2, user);
01210 }
01211 
01212 
01213 static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
01214 {
01215         struct eapol_state_machine *sm = ctx;
01216         *len = sm->eapol->conf.eap_req_id_text_len;
01217         return sm->eapol->conf.eap_req_id_text;
01218 }
01219 
01220 
01221 static struct eapol_callbacks eapol_cb =
01222 {
01223         .get_eap_user = eapol_sm_get_eap_user,
01224         .get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
01225 };
01226 
01227 
01228 int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
01229 {
01230         if (sm == NULL || ctx != sm->eap)
01231                 return -1;
01232 
01233         eap_sm_pending_cb(sm->eap);
01234         eapol_auth_step(sm);
01235 
01236         return 0;
01237 }
01238 
01239 
01240 static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
01241                                  struct eapol_auth_config *src)
01242 {
01243         dst->hapd = src->hapd;
01244         dst->eap_reauth_period = src->eap_reauth_period;
01245         dst->wpa = src->wpa;
01246         dst->individual_wep_key_len = src->individual_wep_key_len;
01247         dst->eap_server = src->eap_server;
01248         dst->ssl_ctx = src->ssl_ctx;
01249         dst->eap_sim_db_priv = src->eap_sim_db_priv;
01250         os_free(dst->eap_req_id_text);
01251         if (src->eap_req_id_text) {
01252                 dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
01253                 if (dst->eap_req_id_text == NULL)
01254                         return -1;
01255                 os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
01256                           src->eap_req_id_text_len);
01257                 dst->eap_req_id_text_len = src->eap_req_id_text_len;
01258         } else {
01259                 dst->eap_req_id_text = NULL;
01260                 dst->eap_req_id_text_len = 0;
01261         }
01262         if (src->pac_opaque_encr_key) {
01263                 dst->pac_opaque_encr_key = os_malloc(16);
01264                 os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
01265                           16);
01266         } else
01267                 dst->pac_opaque_encr_key = NULL;
01268         if (src->eap_fast_a_id) {
01269                 dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
01270                 if (dst->eap_fast_a_id == NULL) {
01271                         os_free(dst->eap_req_id_text);
01272                         return -1;
01273                 }
01274                 os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
01275                           src->eap_fast_a_id_len);
01276                 dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
01277         } else
01278                 dst->eap_fast_a_id = NULL;
01279         if (src->eap_fast_a_id_info) {
01280                 dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
01281                 if (dst->eap_fast_a_id_info == NULL) {
01282                         os_free(dst->eap_req_id_text);
01283                         os_free(dst->eap_fast_a_id);
01284                         return -1;
01285                 }
01286         } else
01287                 dst->eap_fast_a_id_info = NULL;
01288         dst->eap_fast_prov = src->eap_fast_prov;
01289         dst->pac_key_lifetime = src->pac_key_lifetime;
01290         dst->pac_key_refresh_time = src->pac_key_refresh_time;
01291         dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
01292         dst->tnc = src->tnc;
01293         dst->wps = src->wps;
01294         return 0;
01295 }
01296 
01297 
01298 static void eapol_auth_conf_free(struct eapol_auth_config *conf)
01299 {
01300         os_free(conf->eap_req_id_text);
01301         conf->eap_req_id_text = NULL;
01302         os_free(conf->pac_opaque_encr_key);
01303         conf->pac_opaque_encr_key = NULL;
01304         os_free(conf->eap_fast_a_id);
01305         conf->eap_fast_a_id = NULL;
01306         os_free(conf->eap_fast_a_id_info);
01307         conf->eap_fast_a_id_info = NULL;
01308 }
01309 
01310 
01311 struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
01312                                              struct eapol_auth_cb *cb)
01313 {
01314         struct eapol_authenticator *eapol;
01315 
01316         eapol = os_zalloc(sizeof(*eapol));
01317         if (eapol == NULL)
01318                 return NULL;
01319 
01320         if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
01321                 os_free(eapol);
01322                 return NULL;
01323         }
01324 
01325         if (conf->individual_wep_key_len > 0) {
01326                 /* use key0 in individual key and key1 in broadcast key */
01327                 eapol->default_wep_key_idx = 1;
01328         }
01329 
01330         eapol->cb.eapol_send = cb->eapol_send;
01331         eapol->cb.aaa_send = cb->aaa_send;
01332         eapol->cb.finished = cb->finished;
01333         eapol->cb.get_eap_user = cb->get_eap_user;
01334         eapol->cb.sta_entry_alive = cb->sta_entry_alive;
01335         eapol->cb.logger = cb->logger;
01336         eapol->cb.set_port_authorized = cb->set_port_authorized;
01337         eapol->cb.abort_auth = cb->abort_auth;
01338         eapol->cb.tx_key = cb->tx_key;
01339 
01340         return eapol;
01341 }
01342 
01343 
01344 void eapol_auth_deinit(struct eapol_authenticator *eapol)
01345 {
01346         if (eapol == NULL)
01347                 return;
01348 
01349         eapol_auth_conf_free(&eapol->conf);
01350         os_free(eapol->default_wep_key);
01351         os_free(eapol);
01352 }
01353 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:47 2009 for hostapd by  doxygen 1.6.1