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 1475438200 Lines: 698 745 93.7 %
Date: 2016-10-02 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       17358 : static void eapol_auth_logger(struct eapol_authenticator *eapol,
      50             :                               const u8 *addr, eapol_logger_level level,
      51             :                               const char *txt)
      52             : {
      53       17358 :         if (eapol->cb.logger == NULL)
      54       17358 :                 return;
      55       17358 :         eapol->cb.logger(eapol->conf.ctx, addr, level, txt);
      56             : }
      57             : 
      58             : 
      59       17362 : 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       17362 :         if (eapol->cb.logger == NULL)
      68           6 :                 return;
      69             : 
      70       17362 :         maxlen = os_strlen(fmt) + 100;
      71       17362 :         format = os_malloc(maxlen);
      72       17362 :         if (!format)
      73           6 :                 return;
      74             : 
      75       17356 :         va_start(ap, fmt);
      76       17356 :         vsnprintf(format, maxlen, fmt, ap);
      77       17356 :         va_end(ap);
      78             : 
      79       17356 :         eapol_auth_logger(eapol, addr, level, format);
      80             : 
      81       17356 :         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       14783 : static void eapol_auth_tx_req(struct eapol_state_machine *sm)
     107             : {
     108       29564 :         if (sm->eap_if->eapReqData == NULL ||
     109       14781 :             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       14781 :         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       14778 :         sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData);
     125       14778 :         eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
     126             :                            "Sending EAP Packet (identifier %d)",
     127       14778 :                            sm->last_eap_id);
     128       44334 :         sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
     129             :                                  IEEE802_1X_TYPE_EAP_PACKET,
     130       14778 :                                  wpabuf_head(sm->eap_if->eapReqData),
     131       14778 :                                  wpabuf_len(sm->eap_if->eapReqData));
     132       14778 :         sm->dot1xAuthEapolFramesTx++;
     133       14778 :         if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY)
     134        3014 :                 sm->dot1xAuthEapolReqIdFramesTx++;
     135             :         else
     136       11764 :                 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         484 : static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
     149             : {
     150         484 :         struct eapol_state_machine *state = timeout_ctx;
     151             : 
     152         484 :         if (state->aWhile > 0) {
     153         451 :                 state->aWhile--;
     154         451 :                 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         484 :         if (state->quietWhile > 0) {
     162          42 :                 state->quietWhile--;
     163          42 :                 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         484 :         if (state->reAuthWhen > 0) {
     171         484 :                 state->reAuthWhen--;
     172         484 :                 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         484 :         if (state->eap_if->retransWhile > 0) {
     180         369 :                 state->eap_if->retransWhile--;
     181         369 :                 if (state->eap_if->retransWhile == 0) {
     182         408 :                         wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
     183             :                                    " - (EAP) retransWhile --> 0",
     184         408 :                                    MAC2STR(state->addr));
     185             :                 }
     186             :         }
     187             : 
     188         484 :         eapol_sm_step_run(state);
     189             : 
     190         484 :         eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
     191         484 : }
     192             : 
     193             : 
     194             : 
     195             : /* Authenticator PAE state machine */
     196             : 
     197       11957 : SM_STATE(AUTH_PAE, INITIALIZE)
     198             : {
     199       11957 :         SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
     200       11957 :         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       11957 :         sm->keyRun = FALSE;
     213       11957 : }
     214             : 
     215             : 
     216        2831 : SM_STATE(AUTH_PAE, DISCONNECTED)
     217             : {
     218        2831 :         int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
     219             : 
     220        2831 :         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        2831 :         SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
     228             : 
     229        2831 :         sm->authPortStatus = Unauthorized;
     230        2831 :         setPortUnauthorized();
     231        2831 :         sm->reAuthCount = 0;
     232        2831 :         sm->eapolLogoff = FALSE;
     233        2831 :         if (!from_initialize) {
     234          12 :                 sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
     235           6 :                                        sm->flags & EAPOL_SM_PREAUTH,
     236             :                                        sm->remediation);
     237             :         }
     238        2831 : }
     239             : 
     240             : 
     241        3007 : SM_STATE(AUTH_PAE, RESTART)
     242             : {
     243        3007 :         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
     244         111 :                 if (sm->reAuthenticate)
     245          13 :                         sm->authAuthReauthsWhileAuthenticated++;
     246         111 :                 if (sm->eapolStart)
     247          98 :                         sm->authAuthEapStartsWhileAuthenticated++;
     248         111 :                 if (sm->eapolLogoff)
     249           0 :                         sm->authAuthEapLogoffWhileAuthenticated++;
     250             :         }
     251             : 
     252        3007 :         SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
     253             : 
     254        3007 :         sm->eap_if->eapRestart = TRUE;
     255        3007 : }
     256             : 
     257             : 
     258        3007 : SM_STATE(AUTH_PAE, CONNECTING)
     259             : {
     260        3007 :         if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
     261        3007 :                 sm->authEntersConnecting++;
     262             : 
     263        3007 :         SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
     264             : 
     265        3007 :         sm->reAuthenticate = FALSE;
     266        3007 :         sm->reAuthCount++;
     267        3007 : }
     268             : 
     269             : 
     270         753 : SM_STATE(AUTH_PAE, HELD)
     271             : {
     272         753 :         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
     273         753 :                 sm->authAuthFailWhileAuthenticating++;
     274             : 
     275         753 :         SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
     276             : 
     277         753 :         sm->authPortStatus = Unauthorized;
     278         753 :         setPortUnauthorized();
     279         753 :         sm->quietWhile = sm->quietPeriod;
     280         753 :         sm->eapolLogoff = FALSE;
     281             : 
     282        1506 :         eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING,
     283             :                            "authentication failed - EAP type: %d (%s)",
     284         753 :                            sm->eap_type_authsrv,
     285         753 :                            eap_server_get_name(0, sm->eap_type_authsrv));
     286         753 :         if (sm->eap_type_authsrv != sm->eap_type_supp) {
     287        1150 :                 eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
     288             :                                    "Supplicant used different EAP type: "
     289         575 :                                    "%d (%s)", sm->eap_type_supp,
     290         575 :                                    eap_server_get_name(0, sm->eap_type_supp));
     291             :         }
     292        1506 :         sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
     293         753 :                                sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
     294         753 : }
     295             : 
     296             : 
     297        1254 : SM_STATE(AUTH_PAE, AUTHENTICATED)
     298             : {
     299        1254 :         char *extra = "";
     300             : 
     301        1254 :         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
     302        1254 :                 sm->authAuthSuccessesWhileAuthenticating++;
     303             :                                                         
     304        1254 :         SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
     305             : 
     306        1254 :         sm->authPortStatus = Authorized;
     307        1254 :         setPortAuthorized();
     308        1254 :         sm->reAuthCount = 0;
     309        1254 :         if (sm->flags & EAPOL_SM_PREAUTH)
     310           7 :                 extra = " (pre-authentication)";
     311        1247 :         else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE)
     312          39 :                 extra = " (PMKSA cache)";
     313        2508 :         eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
     314             :                            "authenticated - EAP type: %d (%s)%s",
     315        1254 :                            sm->eap_type_authsrv,
     316        1254 :                            eap_server_get_name(0, sm->eap_type_authsrv),
     317             :                            extra);
     318        2508 :         sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
     319        1254 :                                sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
     320        1254 : }
     321             : 
     322             : 
     323        3003 : SM_STATE(AUTH_PAE, AUTHENTICATING)
     324             : {
     325        3003 :         SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
     326             : 
     327        3003 :         sm->eapolStart = FALSE;
     328        3003 :         sm->authSuccess = FALSE;
     329        3003 :         sm->authFail = FALSE;
     330        3003 :         sm->authTimeout = FALSE;
     331        3003 :         sm->authStart = TRUE;
     332        3003 :         sm->keyRun = FALSE;
     333        3003 :         sm->keyDone = FALSE;
     334        3003 : }
     335             : 
     336             : 
     337          71 : SM_STATE(AUTH_PAE, ABORTING)
     338             : {
     339          71 :         if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
     340          71 :                 if (sm->authTimeout)
     341           1 :                         sm->authAuthTimeoutsWhileAuthenticating++;
     342          71 :                 if (sm->eapolStart)
     343          70 :                         sm->authAuthEapStartsWhileAuthenticating++;
     344          71 :                 if (sm->eapolLogoff)
     345           0 :                         sm->authAuthEapLogoffWhileAuthenticating++;
     346             :         }
     347             : 
     348          71 :         SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
     349             : 
     350          71 :         sm->authAbort = TRUE;
     351          71 :         sm->keyRun = FALSE;
     352          71 :         sm->keyDone = FALSE;
     353          71 : }
     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      105148 : SM_STEP(AUTH_PAE)
     381             : {
     382      207597 :         if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
     383      204898 :             sm->initialize || !sm->eap_if->portEnabled)
     384       11957 :                 SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE);
     385       93193 :         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       93192 :         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       93189 :                 switch (sm->auth_pae_state) {
     395             :                 case AUTH_PAE_INITIALIZE:
     396        2825 :                         SM_ENTER(AUTH_PAE, DISCONNECTED);
     397        2825 :                         break;
     398             :                 case AUTH_PAE_DISCONNECTED:
     399        2825 :                         SM_ENTER(AUTH_PAE, RESTART);
     400        2825 :                         break;
     401             :                 case AUTH_PAE_RESTART:
     402        6014 :                         if (!sm->eap_if->eapRestart)
     403        3007 :                                 SM_ENTER(AUTH_PAE, CONNECTING);
     404        6014 :                         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        3007 :                         if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
     411           4 :                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
     412        6003 :                         else if ((sm->eap_if->eapReq &&
     413        3003 :                                   sm->reAuthCount <= sm->reAuthMax) ||
     414           6 :                                  sm->eap_if->eapSuccess || sm->eap_if->eapFail)
     415        3003 :                                 SM_ENTER(AUTH_PAE, AUTHENTICATING);
     416        3007 :                         break;
     417             :                 case AUTH_PAE_AUTHENTICATED:
     418        1691 :                         if (sm->eapolStart || sm->reAuthenticate)
     419         111 :                                 SM_ENTER(AUTH_PAE, RESTART);
     420        1580 :                         else if (sm->eapolLogoff || !sm->portValid)
     421           2 :                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
     422        1691 :                         break;
     423             :                 case AUTH_PAE_AUTHENTICATING:
     424       76754 :                         if (sm->authSuccess && sm->portValid)
     425        1254 :                                 SM_ENTER(AUTH_PAE, AUTHENTICATED);
     426      150247 :                         else if (sm->authFail ||
     427       74747 :                                  (sm->keyDone && !sm->portValid))
     428         753 :                                 SM_ENTER(AUTH_PAE, HELD);
     429      149424 :                         else if (sm->eapolStart || sm->eapolLogoff ||
     430       74677 :                                  sm->authTimeout)
     431          71 :                                 SM_ENTER(AUTH_PAE, ABORTING);
     432       76754 :                         break;
     433             :                 case AUTH_PAE_ABORTING:
     434          71 :                         if (sm->eapolLogoff && !sm->authAbort)
     435           0 :                                 SM_ENTER(AUTH_PAE, DISCONNECTED);
     436          71 :                         else if (!sm->eapolLogoff && !sm->authAbort)
     437          71 :                                 SM_ENTER(AUTH_PAE, RESTART);
     438          71 :                         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      105148 : }
     450             : 
     451             : 
     452             : 
     453             : /* Backend Authentication state machine */
     454             : 
     455        2773 : SM_STATE(BE_AUTH, INITIALIZE)
     456             : {
     457        2773 :         SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
     458             : 
     459        2773 :         abortAuth();
     460        2773 :         sm->eap_if->eapNoReq = FALSE;
     461        2773 :         sm->authAbort = FALSE;
     462        2773 : }
     463             : 
     464             : 
     465       12754 : SM_STATE(BE_AUTH, REQUEST)
     466             : {
     467       12754 :         SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
     468             : 
     469       12754 :         txReq();
     470       12754 :         sm->eap_if->eapReq = FALSE;
     471       12754 :         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       12754 :         sm->eapolEap = FALSE;
     485       12754 : }
     486             : 
     487             : 
     488       11925 : SM_STATE(BE_AUTH, RESPONSE)
     489             : {
     490       11925 :         SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
     491             : 
     492       11925 :         sm->authTimeout = FALSE;
     493       11925 :         sm->eapolEap = FALSE;
     494       11925 :         sm->eap_if->eapNoReq = FALSE;
     495       11925 :         sm->aWhile = sm->serverTimeout;
     496       11925 :         sm->eap_if->eapResp = TRUE;
     497             :         /* sendRespToServer(); */
     498       11925 :         sm->backendResponses++;
     499       11925 : }
     500             : 
     501             : 
     502        1277 : SM_STATE(BE_AUTH, SUCCESS)
     503             : {
     504        1277 :         SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
     505             : 
     506        1277 :         txReq();
     507        1277 :         sm->authSuccess = TRUE;
     508        1277 :         sm->keyRun = TRUE;
     509        1277 : }
     510             : 
     511             : 
     512         752 : SM_STATE(BE_AUTH, FAIL)
     513             : {
     514         752 :         SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
     515             : 
     516         752 :         txReq();
     517         752 :         sm->authFail = TRUE;
     518         752 : }
     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        4840 : SM_STATE(BE_AUTH, IDLE)
     530             : {
     531        4840 :         SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
     532             : 
     533        4840 :         sm->authStart = FALSE;
     534        4840 : }
     535             : 
     536             : 
     537          25 : SM_STATE(BE_AUTH, IGNORE)
     538             : {
     539          25 :         SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
     540             : 
     541          25 :         sm->eap_if->eapNoReq = FALSE;
     542          25 : }
     543             : 
     544             : 
     545      105148 : SM_STEP(BE_AUTH)
     546             : {
     547      105148 :         if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
     548        2773 :                 SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE);
     549      107921 :                 return;
     550             :         }
     551             : 
     552      102375 :         switch (sm->be_auth_state) {
     553             :         case BE_AUTH_INITIALIZE:
     554        2770 :                 SM_ENTER(BE_AUTH, IDLE);
     555        2770 :                 break;
     556             :         case BE_AUTH_REQUEST:
     557       33605 :                 if (sm->eapolEap)
     558       11923 :                         SM_ENTER(BE_AUTH, RESPONSE);
     559       21682 :                 else if (sm->eap_if->eapReq)
     560           8 :                         SM_ENTER(BE_AUTH, REQUEST);
     561       21674 :                 else if (sm->eap_if->eapTimeout)
     562           0 :                         SM_ENTER(BE_AUTH, TIMEOUT);
     563       33605 :                 break;
     564             :         case BE_AUTH_RESPONSE:
     565       38594 :                 if (sm->eap_if->eapNoReq)
     566          25 :                         SM_ENTER(BE_AUTH, IGNORE);
     567       38594 :                 if (sm->eap_if->eapReq) {
     568        9744 :                         sm->backendAccessChallenges++;
     569        9744 :                         SM_ENTER(BE_AUTH, REQUEST);
     570       28850 :                 } else if (sm->aWhile == 0)
     571           1 :                         SM_ENTER(BE_AUTH, TIMEOUT);
     572       28849 :                 else if (sm->eap_if->eapFail) {
     573         749 :                         sm->backendAuthFails++;
     574         749 :                         SM_ENTER(BE_AUTH, FAIL);
     575       28100 :                 } else if (sm->eap_if->eapSuccess) {
     576        1277 :                         sm->backendAuthSuccesses++;
     577        1277 :                         SM_ENTER(BE_AUTH, SUCCESS);
     578             :                 }
     579       38594 :                 break;
     580             :         case BE_AUTH_SUCCESS:
     581        1318 :                 SM_ENTER(BE_AUTH, IDLE);
     582        1318 :                 break;
     583             :         case BE_AUTH_FAIL:
     584         752 :                 SM_ENTER(BE_AUTH, IDLE);
     585         752 :                 break;
     586             :         case BE_AUTH_TIMEOUT:
     587           0 :                 SM_ENTER(BE_AUTH, IDLE);
     588           0 :                 break;
     589             :         case BE_AUTH_IDLE:
     590       25317 :                 if (sm->eap_if->eapFail && sm->authStart)
     591           3 :                         SM_ENTER(BE_AUTH, FAIL);
     592       25314 :                 else if (sm->eap_if->eapReq && sm->authStart)
     593        3000 :                         SM_ENTER(BE_AUTH, REQUEST);
     594       22314 :                 else if (sm->eap_if->eapSuccess && sm->authStart)
     595           0 :                         SM_ENTER(BE_AUTH, SUCCESS);
     596       25317 :                 break;
     597             :         case BE_AUTH_IGNORE:
     598          19 :                 if (sm->eapolEap)
     599           2 :                         SM_ENTER(BE_AUTH, RESPONSE);
     600          17 :                 else if (sm->eap_if->eapReq)
     601           2 :                         SM_ENTER(BE_AUTH, REQUEST);
     602          15 :                 else if (sm->eap_if->eapTimeout)
     603           0 :                         SM_ENTER(BE_AUTH, TIMEOUT);
     604          19 :                 break;
     605             :         }
     606             : }
     607             : 
     608             : 
     609             : 
     610             : /* Reauthentication Timer state machine */
     611             : 
     612       93836 : SM_STATE(REAUTH_TIMER, INITIALIZE)
     613             : {
     614       93836 :         SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
     615             : 
     616       93836 :         sm->reAuthWhen = sm->reAuthPeriod;
     617       93836 : }
     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      105148 : SM_STEP(REAUTH_TIMER)
     631             : {
     632      207594 :         if (sm->portControl != Auto || sm->initialize ||
     633      113760 :             sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
     634       93835 :                 SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE);
     635      198983 :                 return;
     636             :         }
     637             : 
     638       11313 :         switch (sm->reauth_timer_state) {
     639             :         case REAUTH_TIMER_INITIALIZE:
     640       11312 :                 if (sm->reAuthWhen == 0)
     641           1 :                         SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
     642       11312 :                 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        2704 : SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
     654             : {
     655        2704 :         SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
     656        2704 : }
     657             : 
     658             : 
     659           8 : SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
     660             : {
     661           8 :         SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
     662             : 
     663           8 :         txKey();
     664           8 :         sm->eap_if->eapKeyAvailable = FALSE;
     665           8 :         sm->keyDone = TRUE;
     666           8 : }
     667             : 
     668             : 
     669      105148 : SM_STEP(AUTH_KEY_TX)
     670             : {
     671      105148 :         if (sm->initialize || sm->portControl != Auto) {
     672        2702 :                 SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT);
     673      107850 :                 return;
     674             :         }
     675             : 
     676      102446 :         switch (sm->auth_key_tx_state) {
     677             :         case AUTH_KEY_TX_NO_KEY_TRANSMIT:
     678      102432 :                 if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
     679          16 :                     sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA))
     680           8 :                         SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
     681      102424 :                 break;
     682             :         case AUTH_KEY_TX_KEY_TRANSMIT:
     683          22 :                 if (!sm->keyTxEnabled || !sm->keyRun)
     684           2 :                         SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
     685          20 :                 else if (sm->eap_if->eapKeyAvailable)
     686           0 :                         SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
     687          22 :                 break;
     688             :         }
     689             : }
     690             : 
     691             : 
     692             : 
     693             : /* Key Receive state machine */
     694             : 
     695       12715 : SM_STATE(KEY_RX, NO_KEY_RECEIVE)
     696             : {
     697       12715 :         SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
     698       12715 : }
     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      105148 : SM_STEP(KEY_RX)
     711             : {
     712      105148 :         if (sm->initialize || !sm->eap_if->portEnabled) {
     713       12715 :                 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
     714      117863 :                 return;
     715             :         }
     716             : 
     717       92433 :         switch (sm->key_rx_state) {
     718             :         case KEY_RX_NO_KEY_RECEIVE:
     719       92433 :                 if (sm->rxKey)
     720           0 :                         SM_ENTER(KEY_RX, KEY_RECEIVE);
     721       92433 :                 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        2698 : SM_STATE(CTRL_DIR, FORCE_BOTH)
     734             : {
     735        2698 :         SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
     736        2698 :         sm->operControlledDirections = Both;
     737        2698 : }
     738             : 
     739             : 
     740        2698 : SM_STATE(CTRL_DIR, IN_OR_BOTH)
     741             : {
     742        2698 :         SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
     743        2698 :         sm->operControlledDirections = sm->adminControlledDirections;
     744        2698 : }
     745             : 
     746             : 
     747      105148 : SM_STEP(CTRL_DIR)
     748             : {
     749      105148 :         if (sm->initialize) {
     750        2698 :                 SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH);
     751      107846 :                 return;
     752             :         }
     753             : 
     754      102450 :         switch (sm->ctrl_dir_state) {
     755             :         case CTRL_DIR_FORCE_BOTH:
     756       99752 :                 if (sm->eap_if->portEnabled && sm->operEdge)
     757           0 :                         SM_ENTER(CTRL_DIR, IN_OR_BOTH);
     758       99752 :                 break;
     759             :         case CTRL_DIR_IN_OR_BOTH:
     760        5396 :                 if (sm->operControlledDirections !=
     761        2698 :                     sm->adminControlledDirections)
     762           0 :                         SM_ENTER(CTRL_DIR, IN_OR_BOTH);
     763        2698 :                 if (!sm->eap_if->portEnabled || !sm->operEdge)
     764        2698 :                         SM_ENTER(CTRL_DIR, FORCE_BOTH);
     765        2698 :                 break;
     766             :         }
     767             : }
     768             : 
     769             : 
     770             : 
     771             : struct eapol_state_machine *
     772        2699 : 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        2699 :         if (eapol == NULL)
     781           0 :                 return NULL;
     782             : 
     783        2699 :         sm = os_zalloc(sizeof(*sm));
     784        2699 :         if (sm == NULL) {
     785           1 :                 wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation "
     786             :                            "failed");
     787           1 :                 return NULL;
     788             :         }
     789        2698 :         sm->radius_identifier = -1;
     790        2698 :         os_memcpy(sm->addr, addr, ETH_ALEN);
     791        2698 :         sm->flags = flags;
     792             : 
     793        2698 :         sm->eapol = eapol;
     794        2698 :         sm->sta = sta_ctx;
     795             : 
     796             :         /* Set default values for state machine constants */
     797        2698 :         sm->auth_pae_state = AUTH_PAE_INITIALIZE;
     798        2698 :         sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
     799        2698 :         sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
     800             : 
     801        2698 :         sm->be_auth_state = BE_AUTH_INITIALIZE;
     802        2698 :         sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
     803             : 
     804        2698 :         sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
     805        2698 :         sm->reAuthPeriod = eapol->conf.eap_reauth_period;
     806        2698 :         sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE;
     807             : 
     808        2698 :         sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
     809             : 
     810        2698 :         sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
     811             : 
     812        2698 :         sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
     813             : 
     814        2698 :         sm->portControl = Auto;
     815             : 
     816        2746 :         if (!eapol->conf.wpa &&
     817          90 :             (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
     818           6 :                 sm->keyTxEnabled = TRUE;
     819             :         else
     820        2692 :                 sm->keyTxEnabled = FALSE;
     821        2698 :         if (eapol->conf.wpa)
     822        2650 :                 sm->portValid = FALSE;
     823             :         else
     824          48 :                 sm->portValid = TRUE;
     825             : 
     826        2698 :         os_memset(&eap_conf, 0, sizeof(eap_conf));
     827        2698 :         eap_conf.eap_server = eapol->conf.eap_server;
     828        2698 :         eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
     829        2698 :         eap_conf.msg_ctx = eapol->conf.msg_ctx;
     830        2698 :         eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
     831        2698 :         eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
     832        2698 :         eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
     833        2698 :         eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
     834        2698 :         eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
     835        2698 :         eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
     836        2698 :         eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
     837        2698 :         eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
     838        2698 :         eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
     839        2698 :         eap_conf.tnc = eapol->conf.tnc;
     840        2698 :         eap_conf.wps = eapol->conf.wps;
     841        2698 :         eap_conf.assoc_wps_ie = assoc_wps_ie;
     842        2698 :         eap_conf.assoc_p2p_ie = assoc_p2p_ie;
     843        2698 :         eap_conf.peer_addr = addr;
     844        2698 :         eap_conf.fragment_size = eapol->conf.fragment_size;
     845        2698 :         eap_conf.pwd_group = eapol->conf.pwd_group;
     846        2698 :         eap_conf.pbc_in_m1 = eapol->conf.pbc_in_m1;
     847        2698 :         eap_conf.server_id = eapol->conf.server_id;
     848        2698 :         eap_conf.server_id_len = eapol->conf.server_id_len;
     849        2698 :         eap_conf.erp = eapol->conf.erp;
     850        2698 :         eap_conf.tls_session_lifetime = eapol->conf.tls_session_lifetime;
     851        2698 :         sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
     852        2698 :         if (sm->eap == NULL) {
     853           0 :                 eapol_auth_free(sm);
     854           0 :                 return NULL;
     855             :         }
     856        2698 :         sm->eap_if = eap_get_interface(sm->eap);
     857             : 
     858        2698 :         eapol_auth_initialize(sm);
     859             : 
     860        2698 :         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        2698 :         if (radius_cui)
     866           1 :                 sm->radius_cui = wpabuf_alloc_copy(radius_cui,
     867             :                                                    os_strlen(radius_cui));
     868             : 
     869             : #ifndef CONFIG_NO_RADIUS
     870        2440 :         if (radius_gen_session_id((u8 *) &sm->acct_multi_session_id,
     871             :                                   sizeof(sm->acct_multi_session_id)) < 0) {
     872           0 :                 eapol_auth_free(sm);
     873           0 :                 return NULL;
     874             :         }
     875             : #endif /* CONFIG_NO_RADIUS */
     876             : 
     877        2698 :         return sm;
     878             : }
     879             : 
     880             : 
     881        2698 : void eapol_auth_free(struct eapol_state_machine *sm)
     882             : {
     883        2698 :         if (sm == NULL)
     884        2698 :                 return;
     885             : 
     886        2698 :         eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
     887        2698 :         eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
     888        2698 :         if (sm->eap)
     889        2698 :                 eap_server_sm_deinit(sm->eap);
     890             : 
     891        2698 :         wpabuf_free(sm->radius_cui);
     892        2698 :         os_free(sm->identity);
     893        2698 :         os_free(sm);
     894             : }
     895             : 
     896             : 
     897      588030 : static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
     898             :                                     const u8 *addr)
     899             : {
     900      588030 :         return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr);
     901             : }
     902             : 
     903             : 
     904       39925 : static void eapol_sm_step_run(struct eapol_state_machine *sm)
     905             : {
     906       39925 :         struct eapol_authenticator *eapol = sm->eapol;
     907             :         u8 addr[ETH_ALEN];
     908             :         unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
     909             :                 prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
     910       39925 :         int max_steps = 100;
     911             : 
     912       39925 :         os_memcpy(addr, sm->addr, ETH_ALEN);
     913             : 
     914             :         /*
     915             :          * Allow EAPOL state machines to run as long as there are state
     916             :          * changes, but exit and return here through event loop if more than
     917             :          * 100 steps is needed as a precaution against infinite loops inside
     918             :          * eloop callback.
     919             :          */
     920             : restart:
     921      105148 :         prev_auth_pae = sm->auth_pae_state;
     922      105148 :         prev_be_auth = sm->be_auth_state;
     923      105148 :         prev_reauth_timer = sm->reauth_timer_state;
     924      105148 :         prev_auth_key_tx = sm->auth_key_tx_state;
     925      105148 :         prev_key_rx = sm->key_rx_state;
     926      105148 :         prev_ctrl_dir = sm->ctrl_dir_state;
     927             : 
     928      105148 :         SM_STEP_RUN(AUTH_PAE);
     929      105148 :         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
     930      105148 :                 SM_STEP_RUN(BE_AUTH);
     931      105148 :         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
     932      105148 :                 SM_STEP_RUN(REAUTH_TIMER);
     933      105148 :         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
     934      105148 :                 SM_STEP_RUN(AUTH_KEY_TX);
     935      105148 :         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
     936      105148 :                 SM_STEP_RUN(KEY_RX);
     937      105148 :         if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
     938      105148 :                 SM_STEP_RUN(CTRL_DIR);
     939             : 
     940      195588 :         if (prev_auth_pae != sm->auth_pae_state ||
     941      153281 :             prev_be_auth != sm->be_auth_state ||
     942      125681 :             prev_reauth_timer != sm->reauth_timer_state ||
     943      125678 :             prev_auth_key_tx != sm->auth_key_tx_state ||
     944      125676 :             prev_key_rx != sm->key_rx_state ||
     945       62838 :             prev_ctrl_dir != sm->ctrl_dir_state) {
     946       42310 :                 if (--max_steps > 0)
     947       42310 :                         goto restart;
     948             :                 /* Re-run from eloop timeout */
     949           0 :                 eapol_auth_step(sm);
     950           0 :                 return;
     951             :         }
     952             : 
     953       62838 :         if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
     954       57442 :                 if (eap_server_sm_step(sm->eap)) {
     955       22913 :                         if (--max_steps > 0)
     956       22913 :                                 goto restart;
     957             :                         /* Re-run from eloop timeout */
     958           0 :                         eapol_auth_step(sm);
     959           0 :                         return;
     960             :                 }
     961             : 
     962             :                 /* TODO: find a better location for this */
     963       34529 :                 if (sm->eap_if->aaaEapResp) {
     964        7278 :                         sm->eap_if->aaaEapResp = FALSE;
     965        7278 :                         if (sm->eap_if->aaaEapRespData == NULL) {
     966           3 :                                 wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
     967             :                                            "but no aaaEapRespData available");
     968           3 :                                 return;
     969             :                         }
     970       29100 :                         sm->eapol->cb.aaa_send(
     971        7275 :                                 sm->eapol->conf.ctx, sm->sta,
     972        7275 :                                 wpabuf_head(sm->eap_if->aaaEapRespData),
     973        7275 :                                 wpabuf_len(sm->eap_if->aaaEapRespData));
     974             :                 }
     975             :         }
     976             : 
     977       39922 :         if (eapol_sm_sta_entry_alive(eapol, addr))
     978       34526 :                 sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
     979             :                                           EAPOL_AUTH_SM_CHANGE);
     980             : }
     981             : 
     982             : 
     983       34045 : static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
     984             : {
     985       34045 :         struct eapol_state_machine *sm = eloop_ctx;
     986       34045 :         eapol_sm_step_run(sm);
     987       34045 : }
     988             : 
     989             : 
     990             : /**
     991             :  * eapol_auth_step - Advance EAPOL state machines
     992             :  * @sm: EAPOL state machine
     993             :  *
     994             :  * This function is called to advance EAPOL state machines after any change
     995             :  * that could affect their state.
     996             :  */
     997       40806 : void eapol_auth_step(struct eapol_state_machine *sm)
     998             : {
     999             :         /*
    1000             :          * Run eapol_sm_step_run from a registered timeout to make sure that
    1001             :          * other possible timeouts/events are processed and to avoid long
    1002             :          * function call chains.
    1003             :          */
    1004             : 
    1005       40806 :         eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
    1006       40806 : }
    1007             : 
    1008             : 
    1009        2698 : static void eapol_auth_initialize(struct eapol_state_machine *sm)
    1010             : {
    1011        2698 :         sm->initializing = TRUE;
    1012             :         /* Initialize the state machines by asserting initialize and then
    1013             :          * deasserting it after one step */
    1014        2698 :         sm->initialize = TRUE;
    1015        2698 :         eapol_sm_step_run(sm);
    1016        2698 :         sm->initialize = FALSE;
    1017        2698 :         eapol_sm_step_run(sm);
    1018        2698 :         sm->initializing = FALSE;
    1019             : 
    1020             :         /* Start one second tick for port timers state machine */
    1021        2698 :         eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
    1022        2698 :         eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
    1023        2698 : }
    1024             : 
    1025             : 
    1026        1074 : static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
    1027             :                                  size_t identity_len, int phase2,
    1028             :                                  struct eap_user *user)
    1029             : {
    1030        1074 :         struct eapol_state_machine *sm = ctx;
    1031             :         int ret;
    1032             : 
    1033        1074 :         ret = sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity,
    1034             :                                          identity_len, phase2, user);
    1035        1074 :         if (user->remediation)
    1036           0 :                 sm->remediation = 1;
    1037        1074 :         return ret;
    1038             : }
    1039             : 
    1040             : 
    1041        2964 : static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
    1042             : {
    1043        2964 :         struct eapol_state_machine *sm = ctx;
    1044        2964 :         *len = sm->eapol->conf.eap_req_id_text_len;
    1045        2964 :         return sm->eapol->conf.eap_req_id_text;
    1046             : }
    1047             : 
    1048             : 
    1049        2912 : static int eapol_sm_get_erp_send_reauth_start(void *ctx)
    1050             : {
    1051        2912 :         struct eapol_state_machine *sm = ctx;
    1052        2912 :         return sm->eapol->conf.erp_send_reauth_start;
    1053             : }
    1054             : 
    1055             : 
    1056          92 : static const char * eapol_sm_get_erp_domain(void *ctx)
    1057             : {
    1058          92 :         struct eapol_state_machine *sm = ctx;
    1059          92 :         return sm->eapol->conf.erp_domain;
    1060             : }
    1061             : 
    1062             : 
    1063          11 : static struct eap_server_erp_key * eapol_sm_erp_get_key(void *ctx,
    1064             :                                                         const char *keyname)
    1065             : {
    1066          11 :         struct eapol_state_machine *sm = ctx;
    1067          11 :         return sm->eapol->cb.erp_get_key(sm->eapol->conf.ctx, keyname);
    1068             : }
    1069             : 
    1070             : 
    1071          24 : static int eapol_sm_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
    1072             : {
    1073          24 :         struct eapol_state_machine *sm = ctx;
    1074          24 :         return sm->eapol->cb.erp_add_key(sm->eapol->conf.ctx, erp);
    1075             : }
    1076             : 
    1077             : 
    1078             : static const struct eapol_callbacks eapol_cb =
    1079             : {
    1080             :         eapol_sm_get_eap_user,
    1081             :         eapol_sm_get_eap_req_id_text,
    1082             :         NULL,
    1083             :         eapol_sm_get_erp_send_reauth_start,
    1084             :         eapol_sm_get_erp_domain,
    1085             :         eapol_sm_erp_get_key,
    1086             :         eapol_sm_erp_add_key,
    1087             : };
    1088             : 
    1089             : 
    1090          58 : int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
    1091             : {
    1092          58 :         if (sm == NULL || ctx == NULL || ctx != sm->eap)
    1093           0 :                 return -1;
    1094             : 
    1095          58 :         eap_sm_pending_cb(sm->eap);
    1096          58 :         eapol_auth_step(sm);
    1097             : 
    1098          58 :         return 0;
    1099             : }
    1100             : 
    1101             : 
    1102          11 : void eapol_auth_reauthenticate(struct eapol_state_machine *sm)
    1103             : {
    1104          66 :         wpa_printf(MSG_DEBUG, "EAPOL: External reauthentication trigger for "
    1105          66 :                    MACSTR, MAC2STR(sm->addr));
    1106          11 :         sm->reAuthenticate = TRUE;
    1107          11 :         eapol_auth_step(sm);
    1108          11 : }
    1109             : 
    1110             : 
    1111          18 : int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param,
    1112             :                         const char *value)
    1113             : {
    1114         108 :         wpa_printf(MSG_DEBUG, "EAPOL: External configuration operation for "
    1115             :                    MACSTR " - param=%s value=%s",
    1116         108 :                    MAC2STR(sm->addr), param, value);
    1117             : 
    1118          18 :         if (os_strcasecmp(param, "AdminControlledDirections") == 0) {
    1119           3 :                 if (os_strcmp(value, "Both") == 0)
    1120           1 :                         sm->adminControlledDirections = Both;
    1121           2 :                 else if (os_strcmp(value, "In") == 0)
    1122           1 :                         sm->adminControlledDirections = In;
    1123             :                 else
    1124           1 :                         return -1;
    1125           2 :                 eapol_auth_step(sm);
    1126           2 :                 return 0;
    1127             :         }
    1128             : 
    1129          15 :         if (os_strcasecmp(param, "AdminControlledPortControl") == 0) {
    1130           4 :                 if (os_strcmp(value, "ForceAuthorized") == 0)
    1131           1 :                         sm->portControl = ForceAuthorized;
    1132           3 :                 else if (os_strcmp(value, "ForceUnauthorized") == 0)
    1133           1 :                         sm->portControl = ForceUnauthorized;
    1134           2 :                 else if (os_strcmp(value, "Auto") == 0)
    1135           1 :                         sm->portControl = Auto;
    1136             :                 else
    1137           1 :                         return -1;
    1138           3 :                 eapol_auth_step(sm);
    1139           3 :                 return 0;
    1140             :         }
    1141             : 
    1142          11 :         if (os_strcasecmp(param, "quietPeriod") == 0) {
    1143           1 :                 sm->quietPeriod = atoi(value);
    1144           1 :                 return 0;
    1145             :         }
    1146             : 
    1147          10 :         if (os_strcasecmp(param, "serverTimeout") == 0) {
    1148           2 :                 sm->serverTimeout = atoi(value);
    1149           2 :                 return 0;
    1150             :         }
    1151             : 
    1152           8 :         if (os_strcasecmp(param, "reAuthPeriod") == 0) {
    1153           1 :                 sm->reAuthPeriod = atoi(value);
    1154           1 :                 return 0;
    1155             :         }
    1156             : 
    1157           7 :         if (os_strcasecmp(param, "reAuthEnabled") == 0) {
    1158           3 :                 if (os_strcmp(value, "TRUE") == 0)
    1159           1 :                         sm->reAuthEnabled = TRUE;
    1160           2 :                 else if (os_strcmp(value, "FALSE") == 0)
    1161           1 :                         sm->reAuthEnabled = FALSE;
    1162             :                 else
    1163           1 :                         return -1;
    1164           2 :                 eapol_auth_step(sm);
    1165           2 :                 return 0;
    1166             :         }
    1167             : 
    1168           4 :         if (os_strcasecmp(param, "KeyTransmissionEnabled") == 0) {
    1169           3 :                 if (os_strcmp(value, "TRUE") == 0)
    1170           1 :                         sm->keyTxEnabled = TRUE;
    1171           2 :                 else if (os_strcmp(value, "FALSE") == 0)
    1172           1 :                         sm->keyTxEnabled = FALSE;
    1173             :                 else
    1174           1 :                         return -1;
    1175           2 :                 eapol_auth_step(sm);
    1176           2 :                 return 0;
    1177             :         }
    1178             : 
    1179           1 :         return -1;
    1180             : }
    1181             : 
    1182             : 
    1183        2651 : static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
    1184             :                                  struct eapol_auth_config *src)
    1185             : {
    1186        2651 :         dst->ctx = src->ctx;
    1187        2651 :         dst->eap_reauth_period = src->eap_reauth_period;
    1188        2651 :         dst->wpa = src->wpa;
    1189        2651 :         dst->individual_wep_key_len = src->individual_wep_key_len;
    1190        2651 :         dst->eap_server = src->eap_server;
    1191        2651 :         dst->ssl_ctx = src->ssl_ctx;
    1192        2651 :         dst->msg_ctx = src->msg_ctx;
    1193        2651 :         dst->eap_sim_db_priv = src->eap_sim_db_priv;
    1194        2651 :         os_free(dst->eap_req_id_text);
    1195        2651 :         dst->pwd_group = src->pwd_group;
    1196        2651 :         dst->pbc_in_m1 = src->pbc_in_m1;
    1197        2651 :         dst->server_id = src->server_id;
    1198        2651 :         dst->server_id_len = src->server_id_len;
    1199        2651 :         if (src->eap_req_id_text) {
    1200           1 :                 dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
    1201           1 :                 if (dst->eap_req_id_text == NULL)
    1202           0 :                         return -1;
    1203           1 :                 os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
    1204             :                           src->eap_req_id_text_len);
    1205           1 :                 dst->eap_req_id_text_len = src->eap_req_id_text_len;
    1206             :         } else {
    1207        2650 :                 dst->eap_req_id_text = NULL;
    1208        2650 :                 dst->eap_req_id_text_len = 0;
    1209             :         }
    1210        2651 :         if (src->pac_opaque_encr_key) {
    1211          29 :                 dst->pac_opaque_encr_key = os_malloc(16);
    1212          29 :                 if (dst->pac_opaque_encr_key == NULL)
    1213           0 :                         goto fail;
    1214          29 :                 os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
    1215             :                           16);
    1216             :         } else
    1217        2622 :                 dst->pac_opaque_encr_key = NULL;
    1218        2651 :         if (src->eap_fast_a_id) {
    1219          29 :                 dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
    1220          29 :                 if (dst->eap_fast_a_id == NULL)
    1221           0 :                         goto fail;
    1222          29 :                 os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
    1223             :                           src->eap_fast_a_id_len);
    1224          29 :                 dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
    1225             :         } else
    1226        2622 :                 dst->eap_fast_a_id = NULL;
    1227        2651 :         if (src->eap_fast_a_id_info) {
    1228          29 :                 dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
    1229          29 :                 if (dst->eap_fast_a_id_info == NULL)
    1230           0 :                         goto fail;
    1231             :         } else
    1232        2622 :                 dst->eap_fast_a_id_info = NULL;
    1233        2651 :         dst->eap_fast_prov = src->eap_fast_prov;
    1234        2651 :         dst->pac_key_lifetime = src->pac_key_lifetime;
    1235        2651 :         dst->pac_key_refresh_time = src->pac_key_refresh_time;
    1236        2651 :         dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
    1237        2651 :         dst->tnc = src->tnc;
    1238        2651 :         dst->wps = src->wps;
    1239        2651 :         dst->fragment_size = src->fragment_size;
    1240             : 
    1241        2651 :         os_free(dst->erp_domain);
    1242        2651 :         if (src->erp_domain) {
    1243          12 :                 dst->erp_domain = os_strdup(src->erp_domain);
    1244          12 :                 if (dst->erp_domain == NULL)
    1245           0 :                         goto fail;
    1246             :         } else {
    1247        2639 :                 dst->erp_domain = NULL;
    1248             :         }
    1249        2651 :         dst->erp_send_reauth_start = src->erp_send_reauth_start;
    1250        2651 :         dst->erp = src->erp;
    1251        2651 :         dst->tls_session_lifetime = src->tls_session_lifetime;
    1252             : 
    1253        2651 :         return 0;
    1254             : 
    1255             : fail:
    1256           0 :         eapol_auth_conf_free(dst);
    1257           0 :         return -1;
    1258             : }
    1259             : 
    1260             : 
    1261        2651 : static void eapol_auth_conf_free(struct eapol_auth_config *conf)
    1262             : {
    1263        2651 :         os_free(conf->eap_req_id_text);
    1264        2651 :         conf->eap_req_id_text = NULL;
    1265        2651 :         os_free(conf->pac_opaque_encr_key);
    1266        2651 :         conf->pac_opaque_encr_key = NULL;
    1267        2651 :         os_free(conf->eap_fast_a_id);
    1268        2651 :         conf->eap_fast_a_id = NULL;
    1269        2651 :         os_free(conf->eap_fast_a_id_info);
    1270        2651 :         conf->eap_fast_a_id_info = NULL;
    1271        2651 :         os_free(conf->erp_domain);
    1272        2651 :         conf->erp_domain = NULL;
    1273        2651 : }
    1274             : 
    1275             : 
    1276        2652 : struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
    1277             :                                              struct eapol_auth_cb *cb)
    1278             : {
    1279             :         struct eapol_authenticator *eapol;
    1280             : 
    1281        2652 :         eapol = os_zalloc(sizeof(*eapol));
    1282        2652 :         if (eapol == NULL)
    1283           1 :                 return NULL;
    1284             : 
    1285        2651 :         if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
    1286           0 :                 os_free(eapol);
    1287           0 :                 return NULL;
    1288             :         }
    1289             : 
    1290        2651 :         if (conf->individual_wep_key_len > 0) {
    1291             :                 /* use key0 in individual key and key1 in broadcast key */
    1292           6 :                 eapol->default_wep_key_idx = 1;
    1293             :         }
    1294             : 
    1295        2651 :         eapol->cb.eapol_send = cb->eapol_send;
    1296        2651 :         eapol->cb.aaa_send = cb->aaa_send;
    1297        2651 :         eapol->cb.finished = cb->finished;
    1298        2651 :         eapol->cb.get_eap_user = cb->get_eap_user;
    1299        2651 :         eapol->cb.sta_entry_alive = cb->sta_entry_alive;
    1300        2651 :         eapol->cb.logger = cb->logger;
    1301        2651 :         eapol->cb.set_port_authorized = cb->set_port_authorized;
    1302        2651 :         eapol->cb.abort_auth = cb->abort_auth;
    1303        2651 :         eapol->cb.tx_key = cb->tx_key;
    1304        2651 :         eapol->cb.eapol_event = cb->eapol_event;
    1305        2651 :         eapol->cb.erp_get_key = cb->erp_get_key;
    1306        2651 :         eapol->cb.erp_add_key = cb->erp_add_key;
    1307             : 
    1308        2651 :         return eapol;
    1309             : }
    1310             : 
    1311             : 
    1312        2659 : void eapol_auth_deinit(struct eapol_authenticator *eapol)
    1313             : {
    1314        2659 :         if (eapol == NULL)
    1315        2667 :                 return;
    1316             : 
    1317        2651 :         eapol_auth_conf_free(&eapol->conf);
    1318        2651 :         os_free(eapol->default_wep_key);
    1319        2651 :         os_free(eapol);
    1320             : }

Generated by: LCOV version 1.10