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 1443382998 Lines: 698 746 93.6 %
Date: 2015-09-27 Functions: 56 57 98.2 %

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

Generated by: LCOV version 1.10