LCOV - code coverage report
Current view: top level - src/eapol_auth - eapol_auth_sm.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 590 690 85.5 %
Date: 2015-02-03 Functions: 50 55 90.9 %

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

Generated by: LCOV version 1.10