LCOV - code coverage report
Current view: top level - src/eap_peer - eap.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 730 960 76.0 %
Date: 2014-05-28 Functions: 76 90 84.4 %

          Line data    Source code
       1             : /*
       2             :  * EAP peer state machines (RFC 4137)
       3             :  * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  *
       8             :  * This file implements the Peer State Machine as defined in RFC 4137. The used
       9             :  * states and state transitions match mostly with the RFC. However, there are
      10             :  * couple of additional transitions for working around small issues noticed
      11             :  * during testing. These exceptions are explained in comments within the
      12             :  * functions in this file. The method functions, m.func(), are similar to the
      13             :  * ones used in RFC 4137, but some small changes have used here to optimize
      14             :  * operations and to add functionality needed for fast re-authentication
      15             :  * (session resumption).
      16             :  */
      17             : 
      18             : #include "includes.h"
      19             : 
      20             : #include "common.h"
      21             : #include "pcsc_funcs.h"
      22             : #include "state_machine.h"
      23             : #include "ext_password.h"
      24             : #include "crypto/crypto.h"
      25             : #include "crypto/tls.h"
      26             : #include "common/wpa_ctrl.h"
      27             : #include "eap_common/eap_wsc_common.h"
      28             : #include "eap_i.h"
      29             : #include "eap_config.h"
      30             : 
      31             : #define STATE_MACHINE_DATA struct eap_sm
      32             : #define STATE_MACHINE_DEBUG_PREFIX "EAP"
      33             : 
      34             : #define EAP_MAX_AUTH_ROUNDS 50
      35             : #define EAP_CLIENT_TIMEOUT_DEFAULT 60
      36             : 
      37             : 
      38             : static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
      39             :                                   EapType method);
      40             : static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id);
      41             : static void eap_sm_processIdentity(struct eap_sm *sm,
      42             :                                    const struct wpabuf *req);
      43             : static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req);
      44             : static struct wpabuf * eap_sm_buildNotify(int id);
      45             : static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
      46             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
      47             : static const char * eap_sm_method_state_txt(EapMethodState state);
      48             : static const char * eap_sm_decision_txt(EapDecision decision);
      49             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
      50             : 
      51             : 
      52             : 
      53      163202 : static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
      54             : {
      55      163202 :         return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
      56             : }
      57             : 
      58             : 
      59       26825 : static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
      60             :                            Boolean value)
      61             : {
      62       26825 :         sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
      63       26825 : }
      64             : 
      65             : 
      66       26924 : static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
      67             : {
      68       26924 :         return sm->eapol_cb->get_int(sm->eapol_ctx, var);
      69             : }
      70             : 
      71             : 
      72       22831 : static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
      73             :                           unsigned int value)
      74             : {
      75       22831 :         sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
      76       22831 : }
      77             : 
      78             : 
      79        6386 : static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
      80             : {
      81        6386 :         return sm->eapol_cb->get_eapReqData(sm->eapol_ctx);
      82             : }
      83             : 
      84             : 
      85        2096 : static void eap_notify_status(struct eap_sm *sm, const char *status,
      86             :                                       const char *parameter)
      87             : {
      88        2096 :         wpa_printf(MSG_DEBUG, "EAP: Status notification: %s (param=%s)",
      89             :                    status, parameter);
      90        2096 :         if (sm->eapol_cb->notify_status)
      91        2096 :                 sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
      92        2096 : }
      93             : 
      94             : 
      95        6587 : static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
      96             : {
      97        6587 :         ext_password_free(sm->ext_pw_buf);
      98        6587 :         sm->ext_pw_buf = NULL;
      99             : 
     100        6587 :         if (sm->m == NULL || sm->eap_method_priv == NULL)
     101       12684 :                 return;
     102             : 
     103         980 :         wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
     104         980 :                    "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
     105         490 :         sm->m->deinit(sm, sm->eap_method_priv);
     106         490 :         sm->eap_method_priv = NULL;
     107         490 :         sm->m = NULL;
     108             : }
     109             : 
     110             : 
     111             : /**
     112             :  * eap_allowed_method - Check whether EAP method is allowed
     113             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     114             :  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
     115             :  * @method: EAP type
     116             :  * Returns: 1 = allowed EAP method, 0 = not allowed
     117             :  */
     118        2214 : int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
     119             : {
     120        2214 :         struct eap_peer_config *config = eap_get_config(sm);
     121             :         int i;
     122             :         struct eap_method_type *m;
     123             : 
     124        2214 :         if (config == NULL || config->eap_methods == NULL)
     125           0 :                 return 1;
     126             : 
     127        2214 :         m = config->eap_methods;
     128        9656 :         for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
     129        5228 :                      m[i].method != EAP_TYPE_NONE; i++) {
     130        2214 :                 if (m[i].vendor == vendor && m[i].method == method)
     131         604 :                         return 1;
     132             :         }
     133        1610 :         return 0;
     134             : }
     135             : 
     136             : 
     137             : /*
     138             :  * This state initializes state machine variables when the machine is
     139             :  * activated (portEnabled = TRUE). This is also used when re-starting
     140             :  * authentication (eapRestart == TRUE).
     141             :  */
     142        1048 : SM_STATE(EAP, INITIALIZE)
     143             : {
     144        1048 :         SM_ENTRY(EAP, INITIALIZE);
     145        1098 :         if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
     146          99 :             sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
     147          49 :             !sm->prev_failure) {
     148          49 :                 wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
     149             :                            "fast reauthentication");
     150          49 :                 sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
     151             :         } else {
     152         999 :                 eap_deinit_prev_method(sm, "INITIALIZE");
     153             :         }
     154        1048 :         sm->selectedMethod = EAP_TYPE_NONE;
     155        1048 :         sm->methodState = METHOD_NONE;
     156        1048 :         sm->allowNotifications = TRUE;
     157        1048 :         sm->decision = DECISION_FAIL;
     158        1048 :         sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
     159        1048 :         eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
     160        1048 :         eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
     161        1048 :         eapol_set_bool(sm, EAPOL_eapFail, FALSE);
     162        1048 :         os_free(sm->eapKeyData);
     163        1048 :         sm->eapKeyData = NULL;
     164        1048 :         os_free(sm->eapSessionId);
     165        1048 :         sm->eapSessionId = NULL;
     166        1048 :         sm->eapKeyAvailable = FALSE;
     167        1048 :         eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
     168        1048 :         sm->lastId = -1; /* new session - make sure this does not match with
     169             :                           * the first EAP-Packet */
     170             :         /*
     171             :          * RFC 4137 does not reset eapResp and eapNoResp here. However, this
     172             :          * seemed to be able to trigger cases where both were set and if EAPOL
     173             :          * state machine uses eapNoResp first, it may end up not sending a real
     174             :          * reply correctly. This occurred when the workaround in FAIL state set
     175             :          * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
     176             :          * something else(?)
     177             :          */
     178        1048 :         eapol_set_bool(sm, EAPOL_eapResp, FALSE);
     179        1048 :         eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
     180        1048 :         sm->num_rounds = 0;
     181        1048 :         sm->prev_failure = 0;
     182        1048 :         sm->expected_failure = 0;
     183        1048 : }
     184             : 
     185             : 
     186             : /*
     187             :  * This state is reached whenever service from the lower layer is interrupted
     188             :  * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
     189             :  * occurs when the port becomes enabled.
     190             :  */
     191       18821 : SM_STATE(EAP, DISABLED)
     192             : {
     193       18821 :         SM_ENTRY(EAP, DISABLED);
     194       18821 :         sm->num_rounds = 0;
     195             :         /*
     196             :          * RFC 4137 does not describe clearing of idleWhile here, but doing so
     197             :          * allows the timer tick to be stopped more quickly when EAP is not in
     198             :          * use.
     199             :          */
     200       18821 :         eapol_set_int(sm, EAPOL_idleWhile, 0);
     201       18821 : }
     202             : 
     203             : 
     204             : /*
     205             :  * The state machine spends most of its time here, waiting for something to
     206             :  * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
     207             :  * SEND_RESPONSE states.
     208             :  */
     209        4010 : SM_STATE(EAP, IDLE)
     210             : {
     211        4010 :         SM_ENTRY(EAP, IDLE);
     212        4010 : }
     213             : 
     214             : 
     215             : /*
     216             :  * This state is entered when an EAP packet is received (eapReq == TRUE) to
     217             :  * parse the packet header.
     218             :  */
     219        3493 : SM_STATE(EAP, RECEIVED)
     220             : {
     221             :         const struct wpabuf *eapReqData;
     222             : 
     223        3493 :         SM_ENTRY(EAP, RECEIVED);
     224        3493 :         eapReqData = eapol_get_eapReqData(sm);
     225             :         /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
     226        3493 :         eap_sm_parseEapReq(sm, eapReqData);
     227        3493 :         sm->num_rounds++;
     228        3493 : }
     229             : 
     230             : 
     231             : /*
     232             :  * This state is entered when a request for a new type comes in. Either the
     233             :  * correct method is started, or a Nak response is built.
     234             :  */
     235         604 : SM_STATE(EAP, GET_METHOD)
     236             : {
     237             :         int reinit;
     238             :         EapType method;
     239             :         const struct eap_method *eap_method;
     240             : 
     241         604 :         SM_ENTRY(EAP, GET_METHOD);
     242             : 
     243         604 :         if (sm->reqMethod == EAP_TYPE_EXPANDED)
     244         207 :                 method = sm->reqVendorMethod;
     245             :         else
     246         397 :                 method = sm->reqMethod;
     247             : 
     248         604 :         eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
     249             : 
     250         604 :         if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
     251          63 :                 wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
     252             :                            sm->reqVendor, method);
     253          63 :                 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
     254             :                         "vendor=%u method=%u -> NAK",
     255             :                         sm->reqVendor, method);
     256          63 :                 eap_notify_status(sm, "refuse proposed method",
     257             :                                   eap_method ?  eap_method->name : "unknown");
     258          63 :                 goto nak;
     259             :         }
     260             : 
     261         541 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
     262             :                 "vendor=%u method=%u", sm->reqVendor, method);
     263             : 
     264         541 :         eap_notify_status(sm, "accept proposed method",
     265             :                           eap_method ?  eap_method->name : "unknown");
     266             :         /*
     267             :          * RFC 4137 does not define specific operation for fast
     268             :          * re-authentication (session resumption). The design here is to allow
     269             :          * the previously used method data to be maintained for
     270             :          * re-authentication if the method support session resumption.
     271             :          * Otherwise, the previously used method data is freed and a new method
     272             :          * is allocated here.
     273             :          */
     274        1082 :         if (sm->fast_reauth &&
     275         629 :             sm->m && sm->m->vendor == sm->reqVendor &&
     276          87 :             sm->m->method == method &&
     277          86 :             sm->m->has_reauth_data &&
     278          43 :             sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
     279          43 :                 wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
     280             :                            " for fast re-authentication");
     281          43 :                 reinit = 1;
     282             :         } else {
     283         498 :                 eap_deinit_prev_method(sm, "GET_METHOD");
     284         498 :                 reinit = 0;
     285             :         }
     286             : 
     287         541 :         sm->selectedMethod = sm->reqMethod;
     288         541 :         if (sm->m == NULL)
     289         498 :                 sm->m = eap_method;
     290         541 :         if (!sm->m) {
     291           0 :                 wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
     292             :                            "vendor %d method %d",
     293             :                            sm->reqVendor, method);
     294           0 :                 goto nak;
     295             :         }
     296             : 
     297         541 :         sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
     298             : 
     299         541 :         wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
     300             :                    "vendor %u method %u (%s)",
     301         541 :                    sm->reqVendor, method, sm->m->name);
     302         541 :         if (reinit)
     303          43 :                 sm->eap_method_priv = sm->m->init_for_reauth(
     304             :                         sm, sm->eap_method_priv);
     305             :         else
     306         498 :                 sm->eap_method_priv = sm->m->init(sm);
     307             : 
     308         541 :         if (sm->eap_method_priv == NULL) {
     309           8 :                 struct eap_peer_config *config = eap_get_config(sm);
     310           8 :                 wpa_msg(sm->msg_ctx, MSG_INFO,
     311             :                         "EAP: Failed to initialize EAP method: vendor %u "
     312             :                         "method %u (%s)",
     313           8 :                         sm->reqVendor, method, sm->m->name);
     314           8 :                 sm->m = NULL;
     315           8 :                 sm->methodState = METHOD_NONE;
     316           8 :                 sm->selectedMethod = EAP_TYPE_NONE;
     317           9 :                 if (sm->reqMethod == EAP_TYPE_TLS && config &&
     318           2 :                     (config->pending_req_pin ||
     319           1 :                      config->pending_req_passphrase)) {
     320             :                         /*
     321             :                          * Return without generating Nak in order to allow
     322             :                          * entering of PIN code or passphrase to retry the
     323             :                          * current EAP packet.
     324             :                          */
     325           1 :                         wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
     326             :                                    "request - skip Nak");
     327           1 :                         return;
     328             :                 }
     329             : 
     330           7 :                 goto nak;
     331             :         }
     332             : 
     333         533 :         sm->methodState = METHOD_INIT;
     334         533 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
     335             :                 "EAP vendor %u method %u (%s) selected",
     336         533 :                 sm->reqVendor, method, sm->m->name);
     337         533 :         return;
     338             : 
     339             : nak:
     340          70 :         wpabuf_free(sm->eapRespData);
     341          70 :         sm->eapRespData = NULL;
     342          70 :         sm->eapRespData = eap_sm_buildNak(sm, sm->reqId);
     343             : }
     344             : 
     345             : 
     346             : /*
     347             :  * The method processing happens here. The request from the authenticator is
     348             :  * processed, and an appropriate response packet is built.
     349             :  */
     350        2348 : SM_STATE(EAP, METHOD)
     351             : {
     352             :         struct wpabuf *eapReqData;
     353             :         struct eap_method_ret ret;
     354        2348 :         int min_len = 1;
     355             : 
     356        2348 :         SM_ENTRY(EAP, METHOD);
     357        2348 :         if (sm->m == NULL) {
     358           0 :                 wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
     359           0 :                 return;
     360             :         }
     361             : 
     362        2348 :         eapReqData = eapol_get_eapReqData(sm);
     363        2348 :         if (sm->m->vendor == EAP_VENDOR_IETF && sm->m->method == EAP_TYPE_LEAP)
     364           0 :                 min_len = 0; /* LEAP uses EAP-Success without payload */
     365        2348 :         if (!eap_hdr_len_valid(eapReqData, min_len))
     366           0 :                 return;
     367             : 
     368             :         /*
     369             :          * Get ignore, methodState, decision, allowNotifications, and
     370             :          * eapRespData. RFC 4137 uses three separate method procedure (check,
     371             :          * process, and buildResp) in this state. These have been combined into
     372             :          * a single function call to m->process() in order to optimize EAP
     373             :          * method implementation interface a bit. These procedures are only
     374             :          * used from within this METHOD state, so there is no need to keep
     375             :          * these as separate C functions.
     376             :          *
     377             :          * The RFC 4137 procedures return values as follows:
     378             :          * ignore = m.check(eapReqData)
     379             :          * (methodState, decision, allowNotifications) = m.process(eapReqData)
     380             :          * eapRespData = m.buildResp(reqId)
     381             :          */
     382        2348 :         os_memset(&ret, 0, sizeof(ret));
     383        2348 :         ret.ignore = sm->ignore;
     384        2348 :         ret.methodState = sm->methodState;
     385        2348 :         ret.decision = sm->decision;
     386        2348 :         ret.allowNotifications = sm->allowNotifications;
     387        2348 :         wpabuf_free(sm->eapRespData);
     388        2348 :         sm->eapRespData = NULL;
     389        2348 :         sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
     390             :                                          eapReqData);
     391        4696 :         wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
     392             :                    "methodState=%s decision=%s eapRespData=%p",
     393        2348 :                    ret.ignore ? "TRUE" : "FALSE",
     394             :                    eap_sm_method_state_txt(ret.methodState),
     395             :                    eap_sm_decision_txt(ret.decision),
     396             :                    sm->eapRespData);
     397             : 
     398        2348 :         sm->ignore = ret.ignore;
     399        2348 :         if (sm->ignore)
     400           0 :                 return;
     401        2348 :         sm->methodState = ret.methodState;
     402        2348 :         sm->decision = ret.decision;
     403        2348 :         sm->allowNotifications = ret.allowNotifications;
     404             : 
     405        3742 :         if (sm->m->isKeyAvailable && sm->m->getKey &&
     406        1394 :             sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
     407         427 :                 os_free(sm->eapKeyData);
     408         427 :                 sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
     409             :                                                &sm->eapKeyDataLen);
     410         427 :                 os_free(sm->eapSessionId);
     411         427 :                 sm->eapSessionId = NULL;
     412         427 :                 if (sm->m->getSessionId) {
     413         400 :                         sm->eapSessionId = sm->m->getSessionId(
     414             :                                 sm, sm->eap_method_priv,
     415             :                                 &sm->eapSessionIdLen);
     416         800 :                         wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
     417         400 :                                     sm->eapSessionId, sm->eapSessionIdLen);
     418             :                 }
     419             :         }
     420             : }
     421             : 
     422             : 
     423             : /*
     424             :  * This state signals the lower layer that a response packet is ready to be
     425             :  * sent.
     426             :  */
     427        2962 : SM_STATE(EAP, SEND_RESPONSE)
     428             : {
     429        2962 :         SM_ENTRY(EAP, SEND_RESPONSE);
     430        2962 :         wpabuf_free(sm->lastRespData);
     431        2962 :         if (sm->eapRespData) {
     432        2948 :                 if (sm->workaround)
     433        2948 :                         os_memcpy(sm->last_md5, sm->req_md5, 16);
     434        2948 :                 sm->lastId = sm->reqId;
     435        2948 :                 sm->lastRespData = wpabuf_dup(sm->eapRespData);
     436        2948 :                 eapol_set_bool(sm, EAPOL_eapResp, TRUE);
     437             :         } else {
     438          14 :                 wpa_printf(MSG_DEBUG, "EAP: No eapRespData available");
     439          14 :                 sm->lastRespData = NULL;
     440             :         }
     441        2962 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     442        2962 :         eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
     443        2962 : }
     444             : 
     445             : 
     446             : /*
     447             :  * This state signals the lower layer that the request was discarded, and no
     448             :  * response packet will be sent at this time.
     449             :  */
     450           0 : SM_STATE(EAP, DISCARD)
     451             : {
     452           0 :         SM_ENTRY(EAP, DISCARD);
     453           0 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     454           0 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
     455           0 : }
     456             : 
     457             : 
     458             : /*
     459             :  * Handles requests for Identity method and builds a response.
     460             :  */
     461         545 : SM_STATE(EAP, IDENTITY)
     462             : {
     463             :         const struct wpabuf *eapReqData;
     464             : 
     465         545 :         SM_ENTRY(EAP, IDENTITY);
     466         545 :         eapReqData = eapol_get_eapReqData(sm);
     467         545 :         if (!eap_hdr_len_valid(eapReqData, 1))
     468         545 :                 return;
     469         545 :         eap_sm_processIdentity(sm, eapReqData);
     470         545 :         wpabuf_free(sm->eapRespData);
     471         545 :         sm->eapRespData = NULL;
     472         545 :         sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0);
     473             : }
     474             : 
     475             : 
     476             : /*
     477             :  * Handles requests for Notification method and builds a response.
     478             :  */
     479           0 : SM_STATE(EAP, NOTIFICATION)
     480             : {
     481             :         const struct wpabuf *eapReqData;
     482             : 
     483           0 :         SM_ENTRY(EAP, NOTIFICATION);
     484           0 :         eapReqData = eapol_get_eapReqData(sm);
     485           0 :         if (!eap_hdr_len_valid(eapReqData, 1))
     486           0 :                 return;
     487           0 :         eap_sm_processNotify(sm, eapReqData);
     488           0 :         wpabuf_free(sm->eapRespData);
     489           0 :         sm->eapRespData = NULL;
     490           0 :         sm->eapRespData = eap_sm_buildNotify(sm->reqId);
     491             : }
     492             : 
     493             : 
     494             : /*
     495             :  * This state retransmits the previous response packet.
     496             :  */
     497           1 : SM_STATE(EAP, RETRANSMIT)
     498             : {
     499           1 :         SM_ENTRY(EAP, RETRANSMIT);
     500           1 :         wpabuf_free(sm->eapRespData);
     501           1 :         if (sm->lastRespData)
     502           1 :                 sm->eapRespData = wpabuf_dup(sm->lastRespData);
     503             :         else
     504           0 :                 sm->eapRespData = NULL;
     505           1 : }
     506             : 
     507             : 
     508             : /*
     509             :  * This state is entered in case of a successful completion of authentication
     510             :  * and state machine waits here until port is disabled or EAP authentication is
     511             :  * restarted.
     512             :  */
     513         283 : SM_STATE(EAP, SUCCESS)
     514             : {
     515         283 :         SM_ENTRY(EAP, SUCCESS);
     516         283 :         if (sm->eapKeyData != NULL)
     517         283 :                 sm->eapKeyAvailable = TRUE;
     518         283 :         eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
     519             : 
     520             :         /*
     521             :          * RFC 4137 does not clear eapReq here, but this seems to be required
     522             :          * to avoid processing the same request twice when state machine is
     523             :          * initialized.
     524             :          */
     525         283 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     526             : 
     527             :         /*
     528             :          * RFC 4137 does not set eapNoResp here, but this seems to be required
     529             :          * to get EAPOL Supplicant backend state machine into SUCCESS state. In
     530             :          * addition, either eapResp or eapNoResp is required to be set after
     531             :          * processing the received EAP frame.
     532             :          */
     533         283 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
     534             : 
     535         283 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
     536             :                 "EAP authentication completed successfully");
     537         283 : }
     538             : 
     539             : 
     540             : /*
     541             :  * This state is entered in case of a failure and state machine waits here
     542             :  * until port is disabled or EAP authentication is restarted.
     543             :  */
     544         248 : SM_STATE(EAP, FAILURE)
     545             : {
     546         248 :         SM_ENTRY(EAP, FAILURE);
     547         248 :         eapol_set_bool(sm, EAPOL_eapFail, TRUE);
     548             : 
     549             :         /*
     550             :          * RFC 4137 does not clear eapReq here, but this seems to be required
     551             :          * to avoid processing the same request twice when state machine is
     552             :          * initialized.
     553             :          */
     554         248 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     555             : 
     556             :         /*
     557             :          * RFC 4137 does not set eapNoResp here. However, either eapResp or
     558             :          * eapNoResp is required to be set after processing the received EAP
     559             :          * frame.
     560             :          */
     561         248 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
     562             : 
     563         248 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
     564             :                 "EAP authentication failed");
     565             : 
     566         248 :         sm->prev_failure = 1;
     567         248 : }
     568             : 
     569             : 
     570           0 : static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
     571             : {
     572             :         /*
     573             :          * At least Microsoft IAS and Meetinghouse Aegis seem to be sending
     574             :          * EAP-Success/Failure with lastId + 1 even though RFC 3748 and
     575             :          * RFC 4137 require that reqId == lastId. In addition, it looks like
     576             :          * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
     577             :          *
     578             :          * Accept this kind of Id if EAP workarounds are enabled. These are
     579             :          * unauthenticated plaintext messages, so this should have minimal
     580             :          * security implications (bit easier to fake EAP-Success/Failure).
     581             :          */
     582           0 :         if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
     583           0 :                                reqId == ((lastId + 2) & 0xff))) {
     584           0 :                 wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
     585             :                            "identifier field in EAP Success: "
     586             :                            "reqId=%d lastId=%d (these are supposed to be "
     587             :                            "same)", reqId, lastId);
     588           0 :                 return 1;
     589             :         }
     590           0 :         wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
     591             :                    "lastId=%d", reqId, lastId);
     592           0 :         return 0;
     593             : }
     594             : 
     595             : 
     596             : /*
     597             :  * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
     598             :  */
     599             : 
     600       16955 : static void eap_peer_sm_step_idle(struct eap_sm *sm)
     601             : {
     602             :         /*
     603             :          * The first three transitions are from RFC 4137. The last two are
     604             :          * local additions to handle special cases with LEAP and PEAP server
     605             :          * not sending EAP-Success in some cases.
     606             :          */
     607       16955 :         if (eapol_get_bool(sm, EAPOL_eapReq))
     608        3493 :                 SM_ENTER(EAP, RECEIVED);
     609       13462 :         else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
     610       13462 :                   sm->decision != DECISION_FAIL) ||
     611       13462 :                  (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
     612           0 :                   sm->decision == DECISION_UNCOND_SUCC))
     613           0 :                 SM_ENTER(EAP, SUCCESS);
     614       26924 :         else if (eapol_get_bool(sm, EAPOL_altReject) ||
     615       13462 :                  (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
     616       13462 :                   sm->decision != DECISION_UNCOND_SUCC) ||
     617       13462 :                  (eapol_get_bool(sm, EAPOL_altAccept) &&
     618           0 :                   sm->methodState != METHOD_CONT &&
     619           0 :                   sm->decision == DECISION_FAIL))
     620           0 :                 SM_ENTER(EAP, FAILURE);
     621       13462 :         else if (sm->selectedMethod == EAP_TYPE_LEAP &&
     622           0 :                  sm->leap_done && sm->decision != DECISION_FAIL &&
     623           0 :                  sm->methodState == METHOD_DONE)
     624           0 :                 SM_ENTER(EAP, SUCCESS);
     625       14487 :         else if (sm->selectedMethod == EAP_TYPE_PEAP &&
     626        1025 :                  sm->peap_done && sm->decision != DECISION_FAIL &&
     627           0 :                  sm->methodState == METHOD_DONE)
     628           0 :                 SM_ENTER(EAP, SUCCESS);
     629       16955 : }
     630             : 
     631             : 
     632        3492 : static int eap_peer_req_is_duplicate(struct eap_sm *sm)
     633             : {
     634             :         int duplicate;
     635             : 
     636        3492 :         duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
     637        3493 :         if (sm->workaround && duplicate &&
     638           1 :             os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
     639             :                 /*
     640             :                  * RFC 4137 uses (reqId == lastId) as the only verification for
     641             :                  * duplicate EAP requests. However, this misses cases where the
     642             :                  * AS is incorrectly using the same id again; and
     643             :                  * unfortunately, such implementations exist. Use MD5 hash as
     644             :                  * an extra verification for the packets being duplicate to
     645             :                  * workaround these issues.
     646             :                  */
     647           0 :                 wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but "
     648             :                            "EAP packets were not identical");
     649           0 :                 wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a "
     650             :                            "duplicate packet");
     651           0 :                 duplicate = 0;
     652             :         }
     653             : 
     654        3492 :         return duplicate;
     655             : }
     656             : 
     657             : 
     658        3492 : static void eap_peer_sm_step_received(struct eap_sm *sm)
     659             : {
     660        3492 :         int duplicate = eap_peer_req_is_duplicate(sm);
     661             : 
     662             :         /*
     663             :          * Two special cases below for LEAP are local additions to work around
     664             :          * odd LEAP behavior (EAP-Success in the middle of authentication and
     665             :          * then swapped roles). Other transitions are based on RFC 4137.
     666             :          */
     667        3775 :         if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
     668         283 :             (sm->reqId == sm->lastId ||
     669           0 :              eap_success_workaround(sm, sm->reqId, sm->lastId)))
     670         283 :                 SM_ENTER(EAP, SUCCESS);
     671        6410 :         else if (sm->methodState != METHOD_CONT &&
     672        3445 :                  ((sm->rxFailure &&
     673        3201 :                    sm->decision != DECISION_UNCOND_SUCC) ||
     674        2957 :                   (sm->rxSuccess && sm->decision == DECISION_FAIL &&
     675           0 :                    (sm->selectedMethod != EAP_TYPE_LEAP ||
     676         244 :                     sm->methodState != METHOD_MAY_CONT))) &&
     677         244 :                  (sm->reqId == sm->lastId ||
     678           0 :                   eap_success_workaround(sm, sm->reqId, sm->lastId)))
     679         244 :                 SM_ENTER(EAP, FAILURE);
     680        2965 :         else if (sm->rxReq && duplicate)
     681           1 :                 SM_ENTER(EAP, RETRANSMIT);
     682        5928 :         else if (sm->rxReq && !duplicate &&
     683        2964 :                  sm->reqMethod == EAP_TYPE_NOTIFICATION &&
     684           0 :                  sm->allowNotifications)
     685           0 :                 SM_ENTER(EAP, NOTIFICATION);
     686        5928 :         else if (sm->rxReq && !duplicate &&
     687        4113 :                  sm->selectedMethod == EAP_TYPE_NONE &&
     688        1149 :                  sm->reqMethod == EAP_TYPE_IDENTITY)
     689         545 :                 SM_ENTER(EAP, IDENTITY);
     690        4838 :         else if (sm->rxReq && !duplicate &&
     691        3023 :                  sm->selectedMethod == EAP_TYPE_NONE &&
     692        1208 :                  sm->reqMethod != EAP_TYPE_IDENTITY &&
     693         604 :                  sm->reqMethod != EAP_TYPE_NOTIFICATION)
     694         604 :                 SM_ENTER(EAP, GET_METHOD);
     695        3630 :         else if (sm->rxReq && !duplicate &&
     696        3630 :                  sm->reqMethod == sm->selectedMethod &&
     697        1815 :                  sm->methodState != METHOD_DONE)
     698        1815 :                 SM_ENTER(EAP, METHOD);
     699           0 :         else if (sm->selectedMethod == EAP_TYPE_LEAP &&
     700           0 :                  (sm->rxSuccess || sm->rxResp))
     701           0 :                 SM_ENTER(EAP, METHOD);
     702             :         else
     703           0 :                 SM_ENTER(EAP, DISCARD);
     704        3492 : }
     705             : 
     706             : 
     707       32664 : static void eap_peer_sm_step_local(struct eap_sm *sm)
     708             : {
     709       32664 :         switch (sm->EAP_state) {
     710             :         case EAP_INITIALIZE:
     711        1048 :                 SM_ENTER(EAP, IDLE);
     712        1048 :                 break;
     713             :         case EAP_DISABLED:
     714        1010 :                 if (eapol_get_bool(sm, EAPOL_portEnabled) &&
     715         505 :                     !sm->force_disabled)
     716         505 :                         SM_ENTER(EAP, INITIALIZE);
     717         505 :                 break;
     718             :         case EAP_IDLE:
     719       16955 :                 eap_peer_sm_step_idle(sm);
     720       16955 :                 break;
     721             :         case EAP_RECEIVED:
     722        3492 :                 eap_peer_sm_step_received(sm);
     723        3492 :                 break;
     724             :         case EAP_GET_METHOD:
     725         604 :                 if (sm->selectedMethod == sm->reqMethod)
     726         533 :                         SM_ENTER(EAP, METHOD);
     727             :                 else
     728          71 :                         SM_ENTER(EAP, SEND_RESPONSE);
     729         604 :                 break;
     730             :         case EAP_METHOD:
     731             :                 /*
     732             :                  * Note: RFC 4137 uses methodState == DONE && decision == FAIL
     733             :                  * as the condition. eapRespData == NULL here is used to allow
     734             :                  * final EAP method response to be sent without having to change
     735             :                  * all methods to either use methodState MAY_CONT or leaving
     736             :                  * decision to something else than FAIL in cases where the only
     737             :                  * expected response is EAP-Failure.
     738             :                  */
     739        2348 :                 if (sm->ignore)
     740           0 :                         SM_ENTER(EAP, DISCARD);
     741        2685 :                 else if (sm->methodState == METHOD_DONE &&
     742         543 :                          sm->decision == DECISION_FAIL && !sm->eapRespData)
     743           3 :                         SM_ENTER(EAP, FAILURE);
     744             :                 else
     745        2345 :                         SM_ENTER(EAP, SEND_RESPONSE);
     746        2348 :                 break;
     747             :         case EAP_SEND_RESPONSE:
     748        2962 :                 SM_ENTER(EAP, IDLE);
     749        2962 :                 break;
     750             :         case EAP_DISCARD:
     751           0 :                 SM_ENTER(EAP, IDLE);
     752           0 :                 break;
     753             :         case EAP_IDENTITY:
     754         545 :                 SM_ENTER(EAP, SEND_RESPONSE);
     755         545 :                 break;
     756             :         case EAP_NOTIFICATION:
     757           0 :                 SM_ENTER(EAP, SEND_RESPONSE);
     758           0 :                 break;
     759             :         case EAP_RETRANSMIT:
     760           1 :                 SM_ENTER(EAP, SEND_RESPONSE);
     761           1 :                 break;
     762             :         case EAP_SUCCESS:
     763        2966 :                 break;
     764             :         case EAP_FAILURE:
     765        1238 :                 break;
     766             :         }
     767       32664 : }
     768             : 
     769             : 
     770       52034 : SM_STEP(EAP)
     771             : {
     772             :         /* Global transitions */
     773       52577 :         if (eapol_get_bool(sm, EAPOL_eapRestart) &&
     774         543 :             eapol_get_bool(sm, EAPOL_portEnabled))
     775         543 :                 SM_ENTER_GLOBAL(EAP, INITIALIZE);
     776       51491 :         else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
     777       18821 :                 SM_ENTER_GLOBAL(EAP, DISABLED);
     778       32670 :         else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
     779             :                 /* RFC 4137 does not place any limit on number of EAP messages
     780             :                  * in an authentication session. However, some error cases have
     781             :                  * ended up in a state were EAP messages were sent between the
     782             :                  * peer and server in a loop (e.g., TLS ACK frame in both
     783             :                  * direction). Since this is quite undesired outcome, limit the
     784             :                  * total number of EAP round-trips and abort authentication if
     785             :                  * this limit is exceeded.
     786             :                  */
     787           6 :                 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
     788           1 :                         wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
     789             :                                 "authentication rounds - abort",
     790             :                                 EAP_MAX_AUTH_ROUNDS);
     791           1 :                         sm->num_rounds++;
     792           1 :                         SM_ENTER_GLOBAL(EAP, FAILURE);
     793             :                 }
     794             :         } else {
     795             :                 /* Local transitions */
     796       32664 :                 eap_peer_sm_step_local(sm);
     797             :         }
     798       52034 : }
     799             : 
     800             : 
     801         604 : static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
     802             :                                   EapType method)
     803             : {
     804         604 :         if (!eap_allowed_method(sm, vendor, method)) {
     805          63 :                 wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
     806             :                            "vendor %u method %u", vendor, method);
     807          63 :                 return FALSE;
     808             :         }
     809         541 :         if (eap_peer_get_eap_method(vendor, method))
     810         541 :                 return TRUE;
     811           0 :         wpa_printf(MSG_DEBUG, "EAP: not included in build: "
     812             :                    "vendor %u method %u", vendor, method);
     813           0 :         return FALSE;
     814             : }
     815             : 
     816             : 
     817           1 : static struct wpabuf * eap_sm_build_expanded_nak(
     818             :         struct eap_sm *sm, int id, const struct eap_method *methods,
     819             :         size_t count)
     820             : {
     821             :         struct wpabuf *resp;
     822           1 :         int found = 0;
     823             :         const struct eap_method *m;
     824             : 
     825           1 :         wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
     826             : 
     827             :         /* RFC 3748 - 5.3.2: Expanded Nak */
     828           1 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
     829             :                              8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
     830           1 :         if (resp == NULL)
     831           0 :                 return NULL;
     832             : 
     833           1 :         wpabuf_put_be24(resp, EAP_VENDOR_IETF);
     834           1 :         wpabuf_put_be32(resp, EAP_TYPE_NAK);
     835             : 
     836          25 :         for (m = methods; m; m = m->next) {
     837          26 :                 if (sm->reqVendor == m->vendor &&
     838           2 :                     sm->reqVendorMethod == m->method)
     839           1 :                         continue; /* do not allow the current method again */
     840          23 :                 if (eap_allowed_method(sm, m->vendor, m->method)) {
     841           1 :                         wpa_printf(MSG_DEBUG, "EAP: allowed type: "
     842             :                                    "vendor=%u method=%u",
     843           1 :                                    m->vendor, m->method);
     844           1 :                         wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
     845           1 :                         wpabuf_put_be24(resp, m->vendor);
     846           1 :                         wpabuf_put_be32(resp, m->method);
     847             : 
     848           1 :                         found++;
     849             :                 }
     850             :         }
     851           1 :         if (!found) {
     852           0 :                 wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
     853           0 :                 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
     854           0 :                 wpabuf_put_be24(resp, EAP_VENDOR_IETF);
     855           0 :                 wpabuf_put_be32(resp, EAP_TYPE_NONE);
     856             :         }
     857             : 
     858           1 :         eap_update_len(resp);
     859             : 
     860           1 :         return resp;
     861             : }
     862             : 
     863             : 
     864          70 : static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id)
     865             : {
     866             :         struct wpabuf *resp;
     867             :         u8 *start;
     868          70 :         int found = 0, expanded_found = 0;
     869             :         size_t count;
     870             :         const struct eap_method *methods, *m;
     871             : 
     872         140 :         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
     873          70 :                    "vendor=%u method=%u not allowed)", sm->reqMethod,
     874             :                    sm->reqVendor, sm->reqVendorMethod);
     875          70 :         methods = eap_peer_get_methods(&count);
     876          70 :         if (methods == NULL)
     877           0 :                 return NULL;
     878          70 :         if (sm->reqMethod == EAP_TYPE_EXPANDED)
     879           1 :                 return eap_sm_build_expanded_nak(sm, id, methods, count);
     880             : 
     881             :         /* RFC 3748 - 5.3.1: Legacy Nak */
     882          69 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
     883             :                              sizeof(struct eap_hdr) + 1 + count + 1,
     884             :                              EAP_CODE_RESPONSE, id);
     885          69 :         if (resp == NULL)
     886           0 :                 return NULL;
     887             : 
     888          69 :         start = wpabuf_put(resp, 0);
     889        1725 :         for (m = methods; m; m = m->next) {
     890        1656 :                 if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
     891          69 :                         continue; /* do not allow the current method again */
     892        1587 :                 if (eap_allowed_method(sm, m->vendor, m->method)) {
     893          62 :                         if (m->vendor != EAP_VENDOR_IETF) {
     894           0 :                                 if (expanded_found)
     895           0 :                                         continue;
     896           0 :                                 expanded_found = 1;
     897           0 :                                 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
     898             :                         } else
     899          62 :                                 wpabuf_put_u8(resp, m->method);
     900          62 :                         found++;
     901             :                 }
     902             :         }
     903          69 :         if (!found)
     904           7 :                 wpabuf_put_u8(resp, EAP_TYPE_NONE);
     905          69 :         wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found);
     906             : 
     907          69 :         eap_update_len(resp);
     908             : 
     909          69 :         return resp;
     910             : }
     911             : 
     912             : 
     913         545 : static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
     914             : {
     915             :         const u8 *pos;
     916             :         size_t msg_len;
     917             : 
     918         545 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
     919             :                 "EAP authentication started");
     920         545 :         eap_notify_status(sm, "started", "");
     921             : 
     922         545 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req,
     923             :                                &msg_len);
     924         545 :         if (pos == NULL)
     925         545 :                 return;
     926             : 
     927             :         /*
     928             :          * RFC 3748 - 5.1: Identity
     929             :          * Data field may contain a displayable message in UTF-8. If this
     930             :          * includes NUL-character, only the data before that should be
     931             :          * displayed. Some EAP implementasitons may piggy-back additional
     932             :          * options after the NUL.
     933             :          */
     934             :         /* TODO: could save displayable message so that it can be shown to the
     935             :          * user in case of interaction is required */
     936         545 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
     937             :                           pos, msg_len);
     938             : }
     939             : 
     940             : 
     941             : #ifdef PCSC_FUNCS
     942             : 
     943             : /*
     944             :  * Rules for figuring out MNC length based on IMSI for SIM cards that do not
     945             :  * include MNC length field.
     946             :  */
     947             : static int mnc_len_from_imsi(const char *imsi)
     948             : {
     949             :         char mcc_str[4];
     950             :         unsigned int mcc;
     951             : 
     952             :         os_memcpy(mcc_str, imsi, 3);
     953             :         mcc_str[3] = '\0';
     954             :         mcc = atoi(mcc_str);
     955             : 
     956             :         if (mcc == 228)
     957             :                 return 2; /* Networks in Switzerland use 2-digit MNC */
     958             :         if (mcc == 244)
     959             :                 return 2; /* Networks in Finland use 2-digit MNC */
     960             : 
     961             :         return -1;
     962             : }
     963             : 
     964             : 
     965             : static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
     966             :                                     size_t max_len, size_t *imsi_len)
     967             : {
     968             :         int mnc_len;
     969             :         char *pos, mnc[4];
     970             : 
     971             :         if (*imsi_len + 36 > max_len) {
     972             :                 wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
     973             :                 return -1;
     974             :         }
     975             : 
     976             :         /* MNC (2 or 3 digits) */
     977             :         mnc_len = scard_get_mnc_len(sm->scard_ctx);
     978             :         if (mnc_len < 0)
     979             :                 mnc_len = mnc_len_from_imsi(imsi);
     980             :         if (mnc_len < 0) {
     981             :                 wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
     982             :                            "assuming 3");
     983             :                 mnc_len = 3;
     984             :         }
     985             : 
     986             :         if (mnc_len == 2) {
     987             :                 mnc[0] = '0';
     988             :                 mnc[1] = imsi[3];
     989             :                 mnc[2] = imsi[4];
     990             :         } else if (mnc_len == 3) {
     991             :                 mnc[0] = imsi[3];
     992             :                 mnc[1] = imsi[4];
     993             :                 mnc[2] = imsi[5];
     994             :         }
     995             :         mnc[3] = '\0';
     996             : 
     997             :         pos = imsi + *imsi_len;
     998             :         pos += os_snprintf(pos, imsi + max_len - pos,
     999             :                            "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
    1000             :                            mnc, imsi[0], imsi[1], imsi[2]);
    1001             :         *imsi_len = pos - imsi;
    1002             : 
    1003             :         return 0;
    1004             : }
    1005             : 
    1006             : 
    1007             : static int eap_sm_imsi_identity(struct eap_sm *sm,
    1008             :                                 struct eap_peer_config *conf)
    1009             : {
    1010             :         enum { EAP_SM_SIM, EAP_SM_AKA, EAP_SM_AKA_PRIME } method = EAP_SM_SIM;
    1011             :         char imsi[100];
    1012             :         size_t imsi_len;
    1013             :         struct eap_method_type *m = conf->eap_methods;
    1014             :         int i;
    1015             : 
    1016             :         imsi_len = sizeof(imsi);
    1017             :         if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
    1018             :                 wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
    1019             :                 return -1;
    1020             :         }
    1021             : 
    1022             :         wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
    1023             : 
    1024             :         if (imsi_len < 7) {
    1025             :                 wpa_printf(MSG_WARNING, "Too short IMSI for SIM identity");
    1026             :                 return -1;
    1027             :         }
    1028             : 
    1029             :         if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
    1030             :                 wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
    1031             :                 return -1;
    1032             :         }
    1033             :         wpa_hexdump_ascii(MSG_DEBUG, "IMSI + realm", (u8 *) imsi, imsi_len);
    1034             : 
    1035             :         for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
    1036             :                           m[i].method != EAP_TYPE_NONE); i++) {
    1037             :                 if (m[i].vendor == EAP_VENDOR_IETF &&
    1038             :                     m[i].method == EAP_TYPE_AKA_PRIME) {
    1039             :                         method = EAP_SM_AKA_PRIME;
    1040             :                         break;
    1041             :                 }
    1042             : 
    1043             :                 if (m[i].vendor == EAP_VENDOR_IETF &&
    1044             :                     m[i].method == EAP_TYPE_AKA) {
    1045             :                         method = EAP_SM_AKA;
    1046             :                         break;
    1047             :                 }
    1048             :         }
    1049             : 
    1050             :         os_free(conf->identity);
    1051             :         conf->identity = os_malloc(1 + imsi_len);
    1052             :         if (conf->identity == NULL) {
    1053             :                 wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
    1054             :                            "IMSI-based identity");
    1055             :                 return -1;
    1056             :         }
    1057             : 
    1058             :         switch (method) {
    1059             :         case EAP_SM_SIM:
    1060             :                 conf->identity[0] = '1';
    1061             :                 break;
    1062             :         case EAP_SM_AKA:
    1063             :                 conf->identity[0] = '0';
    1064             :                 break;
    1065             :         case EAP_SM_AKA_PRIME:
    1066             :                 conf->identity[0] = '6';
    1067             :                 break;
    1068             :         }
    1069             :         os_memcpy(conf->identity + 1, imsi, imsi_len);
    1070             :         conf->identity_len = 1 + imsi_len;
    1071             : 
    1072             :         return 0;
    1073             : }
    1074             : 
    1075             : #endif /* PCSC_FUNCS */
    1076             : 
    1077             : 
    1078           0 : static int eap_sm_set_scard_pin(struct eap_sm *sm,
    1079             :                                 struct eap_peer_config *conf)
    1080             : {
    1081             : #ifdef PCSC_FUNCS
    1082             :         if (scard_set_pin(sm->scard_ctx, conf->pin)) {
    1083             :                 /*
    1084             :                  * Make sure the same PIN is not tried again in order to avoid
    1085             :                  * blocking SIM.
    1086             :                  */
    1087             :                 os_free(conf->pin);
    1088             :                 conf->pin = NULL;
    1089             : 
    1090             :                 wpa_printf(MSG_WARNING, "PIN validation failed");
    1091             :                 eap_sm_request_pin(sm);
    1092             :                 return -1;
    1093             :         }
    1094             :         return 0;
    1095             : #else /* PCSC_FUNCS */
    1096           0 :         return -1;
    1097             : #endif /* PCSC_FUNCS */
    1098             : }
    1099             : 
    1100           0 : static int eap_sm_get_scard_identity(struct eap_sm *sm,
    1101             :                                      struct eap_peer_config *conf)
    1102             : {
    1103             : #ifdef PCSC_FUNCS
    1104             :         if (eap_sm_set_scard_pin(sm, conf))
    1105             :                 return -1;
    1106             : 
    1107             :         return eap_sm_imsi_identity(sm, conf);
    1108             : #else /* PCSC_FUNCS */
    1109           0 :         return -1;
    1110             : #endif /* PCSC_FUNCS */
    1111             : }
    1112             : 
    1113             : 
    1114             : /**
    1115             :  * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
    1116             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1117             :  * @id: EAP identifier for the packet
    1118             :  * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
    1119             :  * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
    1120             :  * failure
    1121             :  *
    1122             :  * This function allocates and builds an EAP-Identity/Response packet for the
    1123             :  * current network. The caller is responsible for freeing the returned data.
    1124             :  */
    1125         598 : struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
    1126             : {
    1127         598 :         struct eap_peer_config *config = eap_get_config(sm);
    1128             :         struct wpabuf *resp;
    1129             :         const u8 *identity;
    1130             :         size_t identity_len;
    1131             : 
    1132         598 :         if (config == NULL) {
    1133           0 :                 wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
    1134             :                            "was not available");
    1135           0 :                 return NULL;
    1136             :         }
    1137             : 
    1138         625 :         if (sm->m && sm->m->get_identity &&
    1139          27 :             (identity = sm->m->get_identity(sm, sm->eap_method_priv,
    1140             :                                             &identity_len)) != NULL) {
    1141          27 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
    1142             :                                   "identity", identity, identity_len);
    1143         571 :         } else if (!encrypted && config->anonymous_identity) {
    1144         141 :                 identity = config->anonymous_identity;
    1145         141 :                 identity_len = config->anonymous_identity_len;
    1146         141 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
    1147             :                                   identity, identity_len);
    1148             :         } else {
    1149         430 :                 identity = config->identity;
    1150         430 :                 identity_len = config->identity_len;
    1151         430 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
    1152             :                                   identity, identity_len);
    1153             :         }
    1154             : 
    1155         598 :         if (identity == NULL) {
    1156           0 :                 wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
    1157             :                            "configuration was not available");
    1158           0 :                 if (config->pcsc) {
    1159           0 :                         if (eap_sm_get_scard_identity(sm, config) < 0)
    1160           0 :                                 return NULL;
    1161           0 :                         identity = config->identity;
    1162           0 :                         identity_len = config->identity_len;
    1163           0 :                         wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
    1164             :                                           "IMSI", identity, identity_len);
    1165             :                 } else {
    1166           0 :                         eap_sm_request_identity(sm);
    1167           0 :                         return NULL;
    1168             :                 }
    1169         598 :         } else if (config->pcsc) {
    1170           0 :                 if (eap_sm_set_scard_pin(sm, config) < 0)
    1171           0 :                         return NULL;
    1172             :         }
    1173             : 
    1174         598 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
    1175             :                              EAP_CODE_RESPONSE, id);
    1176         598 :         if (resp == NULL)
    1177           0 :                 return NULL;
    1178             : 
    1179         598 :         wpabuf_put_data(resp, identity, identity_len);
    1180             : 
    1181         598 :         return resp;
    1182             : }
    1183             : 
    1184             : 
    1185           0 : static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
    1186             : {
    1187             :         const u8 *pos;
    1188             :         char *msg;
    1189             :         size_t i, msg_len;
    1190             : 
    1191           0 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req,
    1192             :                                &msg_len);
    1193           0 :         if (pos == NULL)
    1194           0 :                 return;
    1195           0 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
    1196             :                           pos, msg_len);
    1197             : 
    1198           0 :         msg = os_malloc(msg_len + 1);
    1199           0 :         if (msg == NULL)
    1200           0 :                 return;
    1201           0 :         for (i = 0; i < msg_len; i++)
    1202           0 :                 msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
    1203           0 :         msg[msg_len] = '\0';
    1204           0 :         wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
    1205             :                 WPA_EVENT_EAP_NOTIFICATION, msg);
    1206           0 :         os_free(msg);
    1207             : }
    1208             : 
    1209             : 
    1210           0 : static struct wpabuf * eap_sm_buildNotify(int id)
    1211             : {
    1212             :         struct wpabuf *resp;
    1213             : 
    1214           0 :         wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
    1215           0 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
    1216             :                              EAP_CODE_RESPONSE, id);
    1217           0 :         if (resp == NULL)
    1218           0 :                 return NULL;
    1219             : 
    1220           0 :         return resp;
    1221             : }
    1222             : 
    1223             : 
    1224        3493 : static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
    1225             : {
    1226             :         const struct eap_hdr *hdr;
    1227             :         size_t plen;
    1228             :         const u8 *pos;
    1229             : 
    1230        3493 :         sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
    1231        3493 :         sm->reqId = 0;
    1232        3493 :         sm->reqMethod = EAP_TYPE_NONE;
    1233        3493 :         sm->reqVendor = EAP_VENDOR_IETF;
    1234        3493 :         sm->reqVendorMethod = EAP_TYPE_NONE;
    1235             : 
    1236        3493 :         if (req == NULL || wpabuf_len(req) < sizeof(*hdr))
    1237           0 :                 return;
    1238             : 
    1239        3493 :         hdr = wpabuf_head(req);
    1240        3493 :         plen = be_to_host16(hdr->length);
    1241        3493 :         if (plen > wpabuf_len(req)) {
    1242           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
    1243             :                            "(len=%lu plen=%lu)",
    1244             :                            (unsigned long) wpabuf_len(req),
    1245             :                            (unsigned long) plen);
    1246           0 :                 return;
    1247             :         }
    1248             : 
    1249        3493 :         sm->reqId = hdr->identifier;
    1250             : 
    1251        3493 :         if (sm->workaround) {
    1252             :                 const u8 *addr[1];
    1253        3493 :                 addr[0] = wpabuf_head(req);
    1254        3493 :                 md5_vector(1, addr, &plen, sm->req_md5);
    1255             :         }
    1256             : 
    1257        3493 :         switch (hdr->code) {
    1258             :         case EAP_CODE_REQUEST:
    1259        2966 :                 if (plen < sizeof(*hdr) + 1) {
    1260           0 :                         wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
    1261             :                                    "no Type field");
    1262           0 :                         return;
    1263             :                 }
    1264        2966 :                 sm->rxReq = TRUE;
    1265        2966 :                 pos = (const u8 *) (hdr + 1);
    1266        2966 :                 sm->reqMethod = *pos++;
    1267        2966 :                 if (sm->reqMethod == EAP_TYPE_EXPANDED) {
    1268         975 :                         if (plen < sizeof(*hdr) + 8) {
    1269           0 :                                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
    1270             :                                            "expanded EAP-Packet (plen=%lu)",
    1271             :                                            (unsigned long) plen);
    1272           0 :                                 return;
    1273             :                         }
    1274         975 :                         sm->reqVendor = WPA_GET_BE24(pos);
    1275         975 :                         pos += 3;
    1276         975 :                         sm->reqVendorMethod = WPA_GET_BE32(pos);
    1277             :                 }
    1278        5932 :                 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
    1279             :                            "method=%u vendor=%u vendorMethod=%u",
    1280        2966 :                            sm->reqId, sm->reqMethod, sm->reqVendor,
    1281             :                            sm->reqVendorMethod);
    1282        2966 :                 break;
    1283             :         case EAP_CODE_RESPONSE:
    1284           0 :                 if (sm->selectedMethod == EAP_TYPE_LEAP) {
    1285             :                         /*
    1286             :                          * LEAP differs from RFC 4137 by using reversed roles
    1287             :                          * for mutual authentication and because of this, we
    1288             :                          * need to accept EAP-Response frames if LEAP is used.
    1289             :                          */
    1290           0 :                         if (plen < sizeof(*hdr) + 1) {
    1291           0 :                                 wpa_printf(MSG_DEBUG, "EAP: Too short "
    1292             :                                            "EAP-Response - no Type field");
    1293           0 :                                 return;
    1294             :                         }
    1295           0 :                         sm->rxResp = TRUE;
    1296           0 :                         pos = (const u8 *) (hdr + 1);
    1297           0 :                         sm->reqMethod = *pos;
    1298           0 :                         wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
    1299             :                                    "LEAP method=%d id=%d",
    1300           0 :                                    sm->reqMethod, sm->reqId);
    1301           0 :                         break;
    1302             :                 }
    1303           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
    1304           0 :                 break;
    1305             :         case EAP_CODE_SUCCESS:
    1306         283 :                 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
    1307         283 :                 eap_notify_status(sm, "completion", "success");
    1308         283 :                 sm->rxSuccess = TRUE;
    1309         283 :                 break;
    1310             :         case EAP_CODE_FAILURE:
    1311         244 :                 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
    1312         244 :                 eap_notify_status(sm, "completion", "failure");
    1313         244 :                 sm->rxFailure = TRUE;
    1314         244 :                 break;
    1315             :         default:
    1316           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
    1317           0 :                            "code %d", hdr->code);
    1318           0 :                 break;
    1319             :         }
    1320             : }
    1321             : 
    1322             : 
    1323         816 : static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
    1324             :                                   union tls_event_data *data)
    1325             : {
    1326         816 :         struct eap_sm *sm = ctx;
    1327         816 :         char *hash_hex = NULL;
    1328             : 
    1329         816 :         switch (ev) {
    1330             :         case TLS_CERT_CHAIN_SUCCESS:
    1331         395 :                 eap_notify_status(sm, "remote certificate verification",
    1332             :                                   "success");
    1333         395 :                 break;
    1334             :         case TLS_CERT_CHAIN_FAILURE:
    1335          24 :                 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
    1336             :                         "reason=%d depth=%d subject='%s' err='%s'",
    1337          12 :                         data->cert_fail.reason,
    1338             :                         data->cert_fail.depth,
    1339             :                         data->cert_fail.subject,
    1340             :                         data->cert_fail.reason_txt);
    1341          12 :                 eap_notify_status(sm, "remote certificate verification",
    1342             :                                   data->cert_fail.reason_txt);
    1343          12 :                 break;
    1344             :         case TLS_PEER_CERTIFICATE:
    1345         396 :                 if (!sm->eapol_cb->notify_cert)
    1346           0 :                         break;
    1347             : 
    1348         396 :                 if (data->peer_cert.hash) {
    1349           3 :                         size_t len = data->peer_cert.hash_len * 2 + 1;
    1350           3 :                         hash_hex = os_malloc(len);
    1351           3 :                         if (hash_hex) {
    1352           3 :                                 wpa_snprintf_hex(hash_hex, len,
    1353             :                                                  data->peer_cert.hash,
    1354             :                                                  data->peer_cert.hash_len);
    1355             :                         }
    1356             :                 }
    1357             : 
    1358         396 :                 sm->eapol_cb->notify_cert(sm->eapol_ctx,
    1359             :                                           data->peer_cert.depth,
    1360             :                                           data->peer_cert.subject,
    1361             :                                           hash_hex, data->peer_cert.cert);
    1362         396 :                 break;
    1363             :         case TLS_ALERT:
    1364          13 :                 if (data->alert.is_local)
    1365          13 :                         eap_notify_status(sm, "local TLS alert",
    1366             :                                           data->alert.description);
    1367             :                 else
    1368           0 :                         eap_notify_status(sm, "remote TLS alert",
    1369             :                                           data->alert.description);
    1370          13 :                 break;
    1371             :         }
    1372             : 
    1373         816 :         os_free(hash_hex);
    1374         816 : }
    1375             : 
    1376             : 
    1377             : /**
    1378             :  * eap_peer_sm_init - Allocate and initialize EAP peer state machine
    1379             :  * @eapol_ctx: Context data to be used with eapol_cb calls
    1380             :  * @eapol_cb: Pointer to EAPOL callback functions
    1381             :  * @msg_ctx: Context data for wpa_msg() calls
    1382             :  * @conf: EAP configuration
    1383             :  * Returns: Pointer to the allocated EAP state machine or %NULL on failure
    1384             :  *
    1385             :  * This function allocates and initializes an EAP state machine. In addition,
    1386             :  * this initializes TLS library for the new EAP state machine. eapol_cb pointer
    1387             :  * will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP
    1388             :  * state machine. Consequently, the caller must make sure that this data
    1389             :  * structure remains alive while the EAP state machine is active.
    1390             :  */
    1391          71 : struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
    1392             :                                  struct eapol_callbacks *eapol_cb,
    1393             :                                  void *msg_ctx, struct eap_config *conf)
    1394             : {
    1395             :         struct eap_sm *sm;
    1396             :         struct tls_config tlsconf;
    1397             : 
    1398          71 :         sm = os_zalloc(sizeof(*sm));
    1399          71 :         if (sm == NULL)
    1400           0 :                 return NULL;
    1401          71 :         sm->eapol_ctx = eapol_ctx;
    1402          71 :         sm->eapol_cb = eapol_cb;
    1403          71 :         sm->msg_ctx = msg_ctx;
    1404          71 :         sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
    1405          71 :         sm->wps = conf->wps;
    1406             : 
    1407          71 :         os_memset(&tlsconf, 0, sizeof(tlsconf));
    1408          71 :         tlsconf.opensc_engine_path = conf->opensc_engine_path;
    1409          71 :         tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
    1410          71 :         tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
    1411             : #ifdef CONFIG_FIPS
    1412             :         tlsconf.fips_mode = 1;
    1413             : #endif /* CONFIG_FIPS */
    1414          71 :         tlsconf.event_cb = eap_peer_sm_tls_event;
    1415          71 :         tlsconf.cb_ctx = sm;
    1416          71 :         tlsconf.cert_in_cb = conf->cert_in_cb;
    1417          71 :         sm->ssl_ctx = tls_init(&tlsconf);
    1418          71 :         if (sm->ssl_ctx == NULL) {
    1419           0 :                 wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
    1420             :                            "context.");
    1421           0 :                 os_free(sm);
    1422           0 :                 return NULL;
    1423             :         }
    1424             : 
    1425          71 :         sm->ssl_ctx2 = tls_init(&tlsconf);
    1426          71 :         if (sm->ssl_ctx2 == NULL) {
    1427           0 :                 wpa_printf(MSG_INFO, "SSL: Failed to initialize TLS "
    1428             :                            "context (2).");
    1429             :                 /* Run without separate TLS context within TLS tunnel */
    1430             :         }
    1431             : 
    1432          71 :         return sm;
    1433             : }
    1434             : 
    1435             : 
    1436             : /**
    1437             :  * eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine
    1438             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1439             :  *
    1440             :  * This function deinitializes EAP state machine and frees all allocated
    1441             :  * resources.
    1442             :  */
    1443          71 : void eap_peer_sm_deinit(struct eap_sm *sm)
    1444             : {
    1445          71 :         if (sm == NULL)
    1446          71 :                 return;
    1447          71 :         eap_deinit_prev_method(sm, "EAP deinit");
    1448          71 :         eap_sm_abort(sm);
    1449          71 :         if (sm->ssl_ctx2)
    1450          71 :                 tls_deinit(sm->ssl_ctx2);
    1451          71 :         tls_deinit(sm->ssl_ctx);
    1452          71 :         os_free(sm);
    1453             : }
    1454             : 
    1455             : 
    1456             : /**
    1457             :  * eap_peer_sm_step - Step EAP peer state machine
    1458             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1459             :  * Returns: 1 if EAP state was changed or 0 if not
    1460             :  *
    1461             :  * This function advances EAP state machine to a new state to match with the
    1462             :  * current variables. This should be called whenever variables used by the EAP
    1463             :  * state machine have changed.
    1464             :  */
    1465       35550 : int eap_peer_sm_step(struct eap_sm *sm)
    1466             : {
    1467       35550 :         int res = 0;
    1468             :         do {
    1469       52034 :                 sm->changed = FALSE;
    1470       52034 :                 SM_STEP_RUN(EAP);
    1471       52034 :                 if (sm->changed)
    1472       16484 :                         res = 1;
    1473       52034 :         } while (sm->changed);
    1474       35550 :         return res;
    1475             : }
    1476             : 
    1477             : 
    1478             : /**
    1479             :  * eap_sm_abort - Abort EAP authentication
    1480             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1481             :  *
    1482             :  * Release system resources that have been allocated for the authentication
    1483             :  * session without fully deinitializing the EAP state machine.
    1484             :  */
    1485       13936 : void eap_sm_abort(struct eap_sm *sm)
    1486             : {
    1487       13936 :         wpabuf_free(sm->lastRespData);
    1488       13936 :         sm->lastRespData = NULL;
    1489       13936 :         wpabuf_free(sm->eapRespData);
    1490       13936 :         sm->eapRespData = NULL;
    1491       13936 :         os_free(sm->eapKeyData);
    1492       13936 :         sm->eapKeyData = NULL;
    1493       13936 :         os_free(sm->eapSessionId);
    1494       13936 :         sm->eapSessionId = NULL;
    1495             : 
    1496             :         /* This is not clearly specified in the EAP statemachines draft, but
    1497             :          * it seems necessary to make sure that some of the EAPOL variables get
    1498             :          * cleared for the next authentication. */
    1499       13936 :         eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
    1500       13936 : }
    1501             : 
    1502             : 
    1503             : #ifdef CONFIG_CTRL_IFACE
    1504         194 : static const char * eap_sm_state_txt(int state)
    1505             : {
    1506         194 :         switch (state) {
    1507             :         case EAP_INITIALIZE:
    1508           0 :                 return "INITIALIZE";
    1509             :         case EAP_DISABLED:
    1510           0 :                 return "DISABLED";
    1511             :         case EAP_IDLE:
    1512           1 :                 return "IDLE";
    1513             :         case EAP_RECEIVED:
    1514           0 :                 return "RECEIVED";
    1515             :         case EAP_GET_METHOD:
    1516           0 :                 return "GET_METHOD";
    1517             :         case EAP_METHOD:
    1518           0 :                 return "METHOD";
    1519             :         case EAP_SEND_RESPONSE:
    1520           0 :                 return "SEND_RESPONSE";
    1521             :         case EAP_DISCARD:
    1522           0 :                 return "DISCARD";
    1523             :         case EAP_IDENTITY:
    1524           0 :                 return "IDENTITY";
    1525             :         case EAP_NOTIFICATION:
    1526           0 :                 return "NOTIFICATION";
    1527             :         case EAP_RETRANSMIT:
    1528           0 :                 return "RETRANSMIT";
    1529             :         case EAP_SUCCESS:
    1530         193 :                 return "SUCCESS";
    1531             :         case EAP_FAILURE:
    1532           0 :                 return "FAILURE";
    1533             :         default:
    1534           0 :                 return "UNKNOWN";
    1535             :         }
    1536             : }
    1537             : #endif /* CONFIG_CTRL_IFACE */
    1538             : 
    1539             : 
    1540             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
    1541        2348 : static const char * eap_sm_method_state_txt(EapMethodState state)
    1542             : {
    1543        2348 :         switch (state) {
    1544             :         case METHOD_NONE:
    1545           0 :                 return "NONE";
    1546             :         case METHOD_INIT:
    1547          15 :                 return "INIT";
    1548             :         case METHOD_CONT:
    1549           8 :                 return "CONT";
    1550             :         case METHOD_MAY_CONT:
    1551        1988 :                 return "MAY_CONT";
    1552             :         case METHOD_DONE:
    1553         337 :                 return "DONE";
    1554             :         default:
    1555           0 :                 return "UNKNOWN";
    1556             :         }
    1557             : }
    1558             : 
    1559             : 
    1560        2348 : static const char * eap_sm_decision_txt(EapDecision decision)
    1561             : {
    1562        2348 :         switch (decision) {
    1563             :         case DECISION_FAIL:
    1564        1976 :                 return "FAIL";
    1565             :         case DECISION_COND_SUCC:
    1566         174 :                 return "COND_SUCC";
    1567             :         case DECISION_UNCOND_SUCC:
    1568         198 :                 return "UNCOND_SUCC";
    1569             :         default:
    1570           0 :                 return "UNKNOWN";
    1571             :         }
    1572             : }
    1573             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
    1574             : 
    1575             : 
    1576             : #ifdef CONFIG_CTRL_IFACE
    1577             : 
    1578             : /**
    1579             :  * eap_sm_get_status - Get EAP state machine status
    1580             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1581             :  * @buf: Buffer for status information
    1582             :  * @buflen: Maximum buffer length
    1583             :  * @verbose: Whether to include verbose status information
    1584             :  * Returns: Number of bytes written to buf.
    1585             :  *
    1586             :  * Query EAP state machine for status information. This function fills in a
    1587             :  * text area with current status information from the EAPOL state machine. If
    1588             :  * the buffer (buf) is not large enough, status information will be truncated
    1589             :  * to fit the buffer.
    1590             :  */
    1591         194 : int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
    1592             : {
    1593             :         int len, ret;
    1594             : 
    1595         194 :         if (sm == NULL)
    1596           0 :                 return 0;
    1597             : 
    1598         194 :         len = os_snprintf(buf, buflen,
    1599             :                           "EAP state=%s\n",
    1600         194 :                           eap_sm_state_txt(sm->EAP_state));
    1601         194 :         if (len < 0 || (size_t) len >= buflen)
    1602           0 :                 return 0;
    1603             : 
    1604         194 :         if (sm->selectedMethod != EAP_TYPE_NONE) {
    1605             :                 const char *name;
    1606         193 :                 if (sm->m) {
    1607         193 :                         name = sm->m->name;
    1608             :                 } else {
    1609           0 :                         const struct eap_method *m =
    1610           0 :                                 eap_peer_get_eap_method(EAP_VENDOR_IETF,
    1611             :                                                         sm->selectedMethod);
    1612           0 :                         if (m)
    1613           0 :                                 name = m->name;
    1614             :                         else
    1615           0 :                                 name = "?";
    1616             :                 }
    1617         193 :                 ret = os_snprintf(buf + len, buflen - len,
    1618             :                                   "selectedMethod=%d (EAP-%s)\n",
    1619         193 :                                   sm->selectedMethod, name);
    1620         193 :                 if (ret < 0 || (size_t) ret >= buflen - len)
    1621           0 :                         return len;
    1622         193 :                 len += ret;
    1623             : 
    1624         193 :                 if (sm->m && sm->m->get_status) {
    1625          97 :                         len += sm->m->get_status(sm, sm->eap_method_priv,
    1626             :                                                  buf + len, buflen - len,
    1627             :                                                  verbose);
    1628             :                 }
    1629             :         }
    1630             : 
    1631         194 :         if (verbose) {
    1632           0 :                 ret = os_snprintf(buf + len, buflen - len,
    1633             :                                   "reqMethod=%d\n"
    1634             :                                   "methodState=%s\n"
    1635             :                                   "decision=%s\n"
    1636             :                                   "ClientTimeout=%d\n",
    1637           0 :                                   sm->reqMethod,
    1638             :                                   eap_sm_method_state_txt(sm->methodState),
    1639             :                                   eap_sm_decision_txt(sm->decision),
    1640             :                                   sm->ClientTimeout);
    1641           0 :                 if (ret < 0 || (size_t) ret >= buflen - len)
    1642           0 :                         return len;
    1643           0 :                 len += ret;
    1644             :         }
    1645             : 
    1646         194 :         return len;
    1647             : }
    1648             : #endif /* CONFIG_CTRL_IFACE */
    1649             : 
    1650             : 
    1651             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
    1652          15 : static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
    1653             :                            const char *msg, size_t msglen)
    1654             : {
    1655             :         struct eap_peer_config *config;
    1656          15 :         const char *txt = NULL;
    1657             :         char *tmp;
    1658             : 
    1659          15 :         if (sm == NULL)
    1660           0 :                 return;
    1661          15 :         config = eap_get_config(sm);
    1662          15 :         if (config == NULL)
    1663           0 :                 return;
    1664             : 
    1665          15 :         switch (field) {
    1666             :         case WPA_CTRL_REQ_EAP_IDENTITY:
    1667           1 :                 config->pending_req_identity++;
    1668           1 :                 break;
    1669             :         case WPA_CTRL_REQ_EAP_PASSWORD:
    1670           6 :                 config->pending_req_password++;
    1671           6 :                 break;
    1672             :         case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
    1673           0 :                 config->pending_req_new_password++;
    1674           0 :                 break;
    1675             :         case WPA_CTRL_REQ_EAP_PIN:
    1676           0 :                 config->pending_req_pin++;
    1677           0 :                 break;
    1678             :         case WPA_CTRL_REQ_EAP_OTP:
    1679           1 :                 if (msg) {
    1680           1 :                         tmp = os_malloc(msglen + 3);
    1681           1 :                         if (tmp == NULL)
    1682           0 :                                 return;
    1683           1 :                         tmp[0] = '[';
    1684           1 :                         os_memcpy(tmp + 1, msg, msglen);
    1685           1 :                         tmp[msglen + 1] = ']';
    1686           1 :                         tmp[msglen + 2] = '\0';
    1687           1 :                         txt = tmp;
    1688           1 :                         os_free(config->pending_req_otp);
    1689           1 :                         config->pending_req_otp = tmp;
    1690           1 :                         config->pending_req_otp_len = msglen + 3;
    1691             :                 } else {
    1692           0 :                         if (config->pending_req_otp == NULL)
    1693           0 :                                 return;
    1694           0 :                         txt = config->pending_req_otp;
    1695             :                 }
    1696           1 :                 break;
    1697             :         case WPA_CTRL_REQ_EAP_PASSPHRASE:
    1698           1 :                 config->pending_req_passphrase++;
    1699           1 :                 break;
    1700             :         case WPA_CTRL_REQ_SIM:
    1701           6 :                 txt = msg;
    1702           6 :                 break;
    1703             :         default:
    1704           0 :                 return;
    1705             :         }
    1706             : 
    1707          15 :         if (sm->eapol_cb->eap_param_needed)
    1708          15 :                 sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
    1709             : }
    1710             : #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
    1711             : #define eap_sm_request(sm, type, msg, msglen) do { } while (0)
    1712             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
    1713             : 
    1714           0 : const char * eap_sm_get_method_name(struct eap_sm *sm)
    1715             : {
    1716           0 :         if (sm->m == NULL)
    1717           0 :                 return "UNKNOWN";
    1718           0 :         return sm->m->name;
    1719             : }
    1720             : 
    1721             : 
    1722             : /**
    1723             :  * eap_sm_request_identity - Request identity from user (ctrl_iface)
    1724             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1725             :  *
    1726             :  * EAP methods can call this function to request identity information for the
    1727             :  * current network. This is normally called when the identity is not included
    1728             :  * in the network configuration. The request will be sent to monitor programs
    1729             :  * through the control interface.
    1730             :  */
    1731           1 : void eap_sm_request_identity(struct eap_sm *sm)
    1732             : {
    1733           1 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
    1734           1 : }
    1735             : 
    1736             : 
    1737             : /**
    1738             :  * eap_sm_request_password - Request password from user (ctrl_iface)
    1739             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1740             :  *
    1741             :  * EAP methods can call this function to request password information for the
    1742             :  * current network. This is normally called when the password is not included
    1743             :  * in the network configuration. The request will be sent to monitor programs
    1744             :  * through the control interface.
    1745             :  */
    1746           6 : void eap_sm_request_password(struct eap_sm *sm)
    1747             : {
    1748           6 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
    1749           6 : }
    1750             : 
    1751             : 
    1752             : /**
    1753             :  * eap_sm_request_new_password - Request new password from user (ctrl_iface)
    1754             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1755             :  *
    1756             :  * EAP methods can call this function to request new password information for
    1757             :  * the current network. This is normally called when the EAP method indicates
    1758             :  * that the current password has expired and password change is required. The
    1759             :  * request will be sent to monitor programs through the control interface.
    1760             :  */
    1761           0 : void eap_sm_request_new_password(struct eap_sm *sm)
    1762             : {
    1763           0 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
    1764           0 : }
    1765             : 
    1766             : 
    1767             : /**
    1768             :  * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
    1769             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1770             :  *
    1771             :  * EAP methods can call this function to request SIM or smart card PIN
    1772             :  * information for the current network. This is normally called when the PIN is
    1773             :  * not included in the network configuration. The request will be sent to
    1774             :  * monitor programs through the control interface.
    1775             :  */
    1776           0 : void eap_sm_request_pin(struct eap_sm *sm)
    1777             : {
    1778           0 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_PIN, NULL, 0);
    1779           0 : }
    1780             : 
    1781             : 
    1782             : /**
    1783             :  * eap_sm_request_otp - Request one time password from user (ctrl_iface)
    1784             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1785             :  * @msg: Message to be displayed to the user when asking for OTP
    1786             :  * @msg_len: Length of the user displayable message
    1787             :  *
    1788             :  * EAP methods can call this function to request open time password (OTP) for
    1789             :  * the current network. The request will be sent to monitor programs through
    1790             :  * the control interface.
    1791             :  */
    1792           1 : void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
    1793             : {
    1794           1 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_OTP, msg, msg_len);
    1795           1 : }
    1796             : 
    1797             : 
    1798             : /**
    1799             :  * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
    1800             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1801             :  *
    1802             :  * EAP methods can call this function to request passphrase for a private key
    1803             :  * for the current network. This is normally called when the passphrase is not
    1804             :  * included in the network configuration. The request will be sent to monitor
    1805             :  * programs through the control interface.
    1806             :  */
    1807           1 : void eap_sm_request_passphrase(struct eap_sm *sm)
    1808             : {
    1809           1 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSPHRASE, NULL, 0);
    1810           1 : }
    1811             : 
    1812             : 
    1813             : /**
    1814             :  * eap_sm_request_sim - Request external SIM processing
    1815             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1816             :  * @req: EAP method specific request
    1817             :  */
    1818           6 : void eap_sm_request_sim(struct eap_sm *sm, const char *req)
    1819             : {
    1820           6 :         eap_sm_request(sm, WPA_CTRL_REQ_SIM, req, os_strlen(req));
    1821           6 : }
    1822             : 
    1823             : 
    1824             : /**
    1825             :  * eap_sm_notify_ctrl_attached - Notification of attached monitor
    1826             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1827             :  *
    1828             :  * Notify EAP state machines that a monitor was attached to the control
    1829             :  * interface to trigger re-sending of pending requests for user input.
    1830             :  */
    1831          63 : void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
    1832             : {
    1833          63 :         struct eap_peer_config *config = eap_get_config(sm);
    1834             : 
    1835          63 :         if (config == NULL)
    1836         119 :                 return;
    1837             : 
    1838             :         /* Re-send any pending requests for user data since a new control
    1839             :          * interface was added. This handles cases where the EAP authentication
    1840             :          * starts immediately after system startup when the user interface is
    1841             :          * not yet running. */
    1842           7 :         if (config->pending_req_identity)
    1843           0 :                 eap_sm_request_identity(sm);
    1844           7 :         if (config->pending_req_password)
    1845           0 :                 eap_sm_request_password(sm);
    1846           7 :         if (config->pending_req_new_password)
    1847           0 :                 eap_sm_request_new_password(sm);
    1848           7 :         if (config->pending_req_otp)
    1849           0 :                 eap_sm_request_otp(sm, NULL, 0);
    1850           7 :         if (config->pending_req_pin)
    1851           0 :                 eap_sm_request_pin(sm);
    1852           7 :         if (config->pending_req_passphrase)
    1853           0 :                 eap_sm_request_passphrase(sm);
    1854             : }
    1855             : 
    1856             : 
    1857         173 : static int eap_allowed_phase2_type(int vendor, int type)
    1858             : {
    1859         173 :         if (vendor != EAP_VENDOR_IETF)
    1860          20 :                 return 0;
    1861         153 :         return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
    1862             :                 type != EAP_TYPE_FAST;
    1863             : }
    1864             : 
    1865             : 
    1866             : /**
    1867             :  * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
    1868             :  * @name: EAP method name, e.g., MD5
    1869             :  * @vendor: Buffer for returning EAP Vendor-Id
    1870             :  * Returns: EAP method type or %EAP_TYPE_NONE if not found
    1871             :  *
    1872             :  * This function maps EAP type names into EAP type numbers that are allowed for
    1873             :  * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
    1874             :  * EAP-PEAP, EAP-TTLS, and EAP-FAST.
    1875             :  */
    1876          53 : u32 eap_get_phase2_type(const char *name, int *vendor)
    1877             : {
    1878             :         int v;
    1879          53 :         u8 type = eap_peer_get_type(name, &v);
    1880          53 :         if (eap_allowed_phase2_type(v, type)) {
    1881          53 :                 *vendor = v;
    1882          53 :                 return type;
    1883             :         }
    1884           0 :         *vendor = EAP_VENDOR_IETF;
    1885           0 :         return EAP_TYPE_NONE;
    1886             : }
    1887             : 
    1888             : 
    1889             : /**
    1890             :  * eap_get_phase2_types - Get list of allowed EAP phase 2 types
    1891             :  * @config: Pointer to a network configuration
    1892             :  * @count: Pointer to a variable to be filled with number of returned EAP types
    1893             :  * Returns: Pointer to allocated type list or %NULL on failure
    1894             :  *
    1895             :  * This function generates an array of allowed EAP phase 2 (tunneled) types for
    1896             :  * the given network configuration.
    1897             :  */
    1898           5 : struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
    1899             :                                               size_t *count)
    1900             : {
    1901             :         struct eap_method_type *buf;
    1902             :         u32 method;
    1903             :         int vendor;
    1904             :         size_t mcount;
    1905             :         const struct eap_method *methods, *m;
    1906             : 
    1907           5 :         methods = eap_peer_get_methods(&mcount);
    1908           5 :         if (methods == NULL)
    1909           0 :                 return NULL;
    1910           5 :         *count = 0;
    1911           5 :         buf = os_malloc(mcount * sizeof(struct eap_method_type));
    1912           5 :         if (buf == NULL)
    1913           0 :                 return NULL;
    1914             : 
    1915         125 :         for (m = methods; m; m = m->next) {
    1916         120 :                 vendor = m->vendor;
    1917         120 :                 method = m->method;
    1918         120 :                 if (eap_allowed_phase2_type(vendor, method)) {
    1919          85 :                         if (vendor == EAP_VENDOR_IETF &&
    1920          10 :                             method == EAP_TYPE_TLS && config &&
    1921           5 :                             config->private_key2 == NULL)
    1922           5 :                                 continue;
    1923          80 :                         buf[*count].vendor = vendor;
    1924          80 :                         buf[*count].method = method;
    1925          80 :                         (*count)++;
    1926             :                 }
    1927             :         }
    1928             : 
    1929           5 :         return buf;
    1930             : }
    1931             : 
    1932             : 
    1933             : /**
    1934             :  * eap_set_fast_reauth - Update fast_reauth setting
    1935             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1936             :  * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
    1937             :  */
    1938        1088 : void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
    1939             : {
    1940        1088 :         sm->fast_reauth = enabled;
    1941        1088 : }
    1942             : 
    1943             : 
    1944             : /**
    1945             :  * eap_set_workaround - Update EAP workarounds setting
    1946             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1947             :  * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
    1948             :  */
    1949        1088 : void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
    1950             : {
    1951        1088 :         sm->workaround = workaround;
    1952        1088 : }
    1953             : 
    1954             : 
    1955             : /**
    1956             :  * eap_get_config - Get current network configuration
    1957             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1958             :  * Returns: Pointer to the current network configuration or %NULL if not found
    1959             :  *
    1960             :  * EAP peer methods should avoid using this function if they can use other
    1961             :  * access functions, like eap_get_config_identity() and
    1962             :  * eap_get_config_password(), that do not require direct access to
    1963             :  * struct eap_peer_config.
    1964             :  */
    1965        5589 : struct eap_peer_config * eap_get_config(struct eap_sm *sm)
    1966             : {
    1967        5589 :         return sm->eapol_cb->get_config(sm->eapol_ctx);
    1968             : }
    1969             : 
    1970             : 
    1971             : /**
    1972             :  * eap_get_config_identity - Get identity from the network configuration
    1973             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1974             :  * @len: Buffer for the length of the identity
    1975             :  * Returns: Pointer to the identity or %NULL if not found
    1976             :  */
    1977         939 : const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
    1978             : {
    1979         939 :         struct eap_peer_config *config = eap_get_config(sm);
    1980         939 :         if (config == NULL)
    1981           0 :                 return NULL;
    1982         939 :         *len = config->identity_len;
    1983         939 :         return config->identity;
    1984             : }
    1985             : 
    1986             : 
    1987           6 : static int eap_get_ext_password(struct eap_sm *sm,
    1988             :                                 struct eap_peer_config *config)
    1989             : {
    1990             :         char *name;
    1991             : 
    1992           6 :         if (config->password == NULL)
    1993           0 :                 return -1;
    1994             : 
    1995           6 :         name = os_zalloc(config->password_len + 1);
    1996           6 :         if (name == NULL)
    1997           0 :                 return -1;
    1998           6 :         os_memcpy(name, config->password, config->password_len);
    1999             : 
    2000           6 :         ext_password_free(sm->ext_pw_buf);
    2001           6 :         sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
    2002           6 :         os_free(name);
    2003             : 
    2004           6 :         return sm->ext_pw_buf == NULL ? -1 : 0;
    2005             : }
    2006             : 
    2007             : 
    2008             : /**
    2009             :  * eap_get_config_password - Get password from the network configuration
    2010             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2011             :  * @len: Buffer for the length of the password
    2012             :  * Returns: Pointer to the password or %NULL if not found
    2013             :  */
    2014         355 : const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
    2015             : {
    2016         355 :         struct eap_peer_config *config = eap_get_config(sm);
    2017         355 :         if (config == NULL)
    2018           0 :                 return NULL;
    2019             : 
    2020         355 :         if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
    2021           4 :                 if (eap_get_ext_password(sm, config) < 0)
    2022           0 :                         return NULL;
    2023           4 :                 *len = wpabuf_len(sm->ext_pw_buf);
    2024           4 :                 return wpabuf_head(sm->ext_pw_buf);
    2025             :         }
    2026             : 
    2027         351 :         *len = config->password_len;
    2028         351 :         return config->password;
    2029             : }
    2030             : 
    2031             : 
    2032             : /**
    2033             :  * eap_get_config_password2 - Get password from the network configuration
    2034             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2035             :  * @len: Buffer for the length of the password
    2036             :  * @hash: Buffer for returning whether the password is stored as a
    2037             :  * NtPasswordHash instead of plaintext password; can be %NULL if this
    2038             :  * information is not needed
    2039             :  * Returns: Pointer to the password or %NULL if not found
    2040             :  */
    2041         125 : const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
    2042             : {
    2043         125 :         struct eap_peer_config *config = eap_get_config(sm);
    2044         125 :         if (config == NULL)
    2045           0 :                 return NULL;
    2046             : 
    2047         125 :         if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
    2048           2 :                 if (eap_get_ext_password(sm, config) < 0)
    2049           0 :                         return NULL;
    2050           2 :                 if (hash)
    2051           2 :                         *hash = 0;
    2052           2 :                 *len = wpabuf_len(sm->ext_pw_buf);
    2053           2 :                 return wpabuf_head(sm->ext_pw_buf);
    2054             :         }
    2055             : 
    2056         123 :         *len = config->password_len;
    2057         123 :         if (hash)
    2058         123 :                 *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
    2059         123 :         return config->password;
    2060             : }
    2061             : 
    2062             : 
    2063             : /**
    2064             :  * eap_get_config_new_password - Get new password from network configuration
    2065             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2066             :  * @len: Buffer for the length of the new password
    2067             :  * Returns: Pointer to the new password or %NULL if not found
    2068             :  */
    2069           0 : const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
    2070             : {
    2071           0 :         struct eap_peer_config *config = eap_get_config(sm);
    2072           0 :         if (config == NULL)
    2073           0 :                 return NULL;
    2074           0 :         *len = config->new_password_len;
    2075           0 :         return config->new_password;
    2076             : }
    2077             : 
    2078             : 
    2079             : /**
    2080             :  * eap_get_config_otp - Get one-time password from the network configuration
    2081             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2082             :  * @len: Buffer for the length of the one-time password
    2083             :  * Returns: Pointer to the one-time password or %NULL if not found
    2084             :  */
    2085           9 : const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
    2086             : {
    2087           9 :         struct eap_peer_config *config = eap_get_config(sm);
    2088           9 :         if (config == NULL)
    2089           0 :                 return NULL;
    2090           9 :         *len = config->otp_len;
    2091           9 :         return config->otp;
    2092             : }
    2093             : 
    2094             : 
    2095             : /**
    2096             :  * eap_clear_config_otp - Clear used one-time password
    2097             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2098             :  *
    2099             :  * This function clears a used one-time password (OTP) from the current network
    2100             :  * configuration. This should be called when the OTP has been used and is not
    2101             :  * needed anymore.
    2102             :  */
    2103           1 : void eap_clear_config_otp(struct eap_sm *sm)
    2104             : {
    2105           1 :         struct eap_peer_config *config = eap_get_config(sm);
    2106           1 :         if (config == NULL)
    2107           1 :                 return;
    2108           1 :         os_memset(config->otp, 0, config->otp_len);
    2109           1 :         os_free(config->otp);
    2110           1 :         config->otp = NULL;
    2111           1 :         config->otp_len = 0;
    2112             : }
    2113             : 
    2114             : 
    2115             : /**
    2116             :  * eap_get_config_phase1 - Get phase1 data from the network configuration
    2117             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2118             :  * Returns: Pointer to the phase1 data or %NULL if not found
    2119             :  */
    2120         254 : const char * eap_get_config_phase1(struct eap_sm *sm)
    2121             : {
    2122         254 :         struct eap_peer_config *config = eap_get_config(sm);
    2123         254 :         if (config == NULL)
    2124           0 :                 return NULL;
    2125         254 :         return config->phase1;
    2126             : }
    2127             : 
    2128             : 
    2129             : /**
    2130             :  * eap_get_config_phase2 - Get phase2 data from the network configuration
    2131             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2132             :  * Returns: Pointer to the phase1 data or %NULL if not found
    2133             :  */
    2134           0 : const char * eap_get_config_phase2(struct eap_sm *sm)
    2135             : {
    2136           0 :         struct eap_peer_config *config = eap_get_config(sm);
    2137           0 :         if (config == NULL)
    2138           0 :                 return NULL;
    2139           0 :         return config->phase2;
    2140             : }
    2141             : 
    2142             : 
    2143         218 : int eap_get_config_fragment_size(struct eap_sm *sm)
    2144             : {
    2145         218 :         struct eap_peer_config *config = eap_get_config(sm);
    2146         218 :         if (config == NULL)
    2147           0 :                 return -1;
    2148         218 :         return config->fragment_size;
    2149             : }
    2150             : 
    2151             : 
    2152             : /**
    2153             :  * eap_key_available - Get key availability (eapKeyAvailable variable)
    2154             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2155             :  * Returns: 1 if EAP keying material is available, 0 if not
    2156             :  */
    2157        1205 : int eap_key_available(struct eap_sm *sm)
    2158             : {
    2159        1205 :         return sm ? sm->eapKeyAvailable : 0;
    2160             : }
    2161             : 
    2162             : 
    2163             : /**
    2164             :  * eap_notify_success - Notify EAP state machine about external success trigger
    2165             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2166             :  *
    2167             :  * This function is called when external event, e.g., successful completion of
    2168             :  * WPA-PSK key handshake, is indicating that EAP state machine should move to
    2169             :  * success state. This is mainly used with security modes that do not use EAP
    2170             :  * state machine (e.g., WPA-PSK).
    2171             :  */
    2172         383 : void eap_notify_success(struct eap_sm *sm)
    2173             : {
    2174         383 :         if (sm) {
    2175         383 :                 sm->decision = DECISION_COND_SUCC;
    2176         383 :                 sm->EAP_state = EAP_SUCCESS;
    2177             :         }
    2178         383 : }
    2179             : 
    2180             : 
    2181             : /**
    2182             :  * eap_notify_lower_layer_success - Notification of lower layer success
    2183             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2184             :  *
    2185             :  * Notify EAP state machines that a lower layer has detected a successful
    2186             :  * authentication. This is used to recover from dropped EAP-Success messages.
    2187             :  */
    2188        1288 : void eap_notify_lower_layer_success(struct eap_sm *sm)
    2189             : {
    2190        1288 :         if (sm == NULL)
    2191           0 :                 return;
    2192             : 
    2193        1820 :         if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
    2194         718 :             sm->decision == DECISION_FAIL ||
    2195         335 :             (sm->methodState != METHOD_MAY_CONT &&
    2196         149 :              sm->methodState != METHOD_DONE))
    2197        1142 :                 return;
    2198             : 
    2199         146 :         if (sm->eapKeyData != NULL)
    2200           0 :                 sm->eapKeyAvailable = TRUE;
    2201         146 :         eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
    2202         146 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
    2203             :                 "EAP authentication completed successfully (based on lower "
    2204             :                 "layer success)");
    2205             : }
    2206             : 
    2207             : 
    2208             : /**
    2209             :  * eap_get_eapSessionId - Get Session-Id from EAP state machine
    2210             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2211             :  * @len: Pointer to variable that will be set to number of bytes in the session
    2212             :  * Returns: Pointer to the EAP Session-Id or %NULL on failure
    2213             :  *
    2214             :  * Fetch EAP Session-Id from the EAP state machine. The Session-Id is available
    2215             :  * only after a successful authentication. EAP state machine continues to manage
    2216             :  * the Session-Id and the caller must not change or free the returned data.
    2217             :  */
    2218           0 : const u8 * eap_get_eapSessionId(struct eap_sm *sm, size_t *len)
    2219             : {
    2220           0 :         if (sm == NULL || sm->eapSessionId == NULL) {
    2221           0 :                 *len = 0;
    2222           0 :                 return NULL;
    2223             :         }
    2224             : 
    2225           0 :         *len = sm->eapSessionIdLen;
    2226           0 :         return sm->eapSessionId;
    2227             : }
    2228             : 
    2229             : 
    2230             : /**
    2231             :  * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
    2232             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2233             :  * @len: Pointer to variable that will be set to number of bytes in the key
    2234             :  * Returns: Pointer to the EAP keying data or %NULL on failure
    2235             :  *
    2236             :  * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
    2237             :  * key is available only after a successful authentication. EAP state machine
    2238             :  * continues to manage the key data and the caller must not change or free the
    2239             :  * returned data.
    2240             :  */
    2241         559 : const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
    2242             : {
    2243         559 :         if (sm == NULL || sm->eapKeyData == NULL) {
    2244           0 :                 *len = 0;
    2245           0 :                 return NULL;
    2246             :         }
    2247             : 
    2248         559 :         *len = sm->eapKeyDataLen;
    2249         559 :         return sm->eapKeyData;
    2250             : }
    2251             : 
    2252             : 
    2253             : /**
    2254             :  * eap_get_eapKeyData - Get EAP response data
    2255             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2256             :  * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
    2257             :  *
    2258             :  * Fetch EAP response (eapRespData) from the EAP state machine. This data is
    2259             :  * available when EAP state machine has processed an incoming EAP request. The
    2260             :  * EAP state machine does not maintain a reference to the response after this
    2261             :  * function is called and the caller is responsible for freeing the data.
    2262             :  */
    2263        2947 : struct wpabuf * eap_get_eapRespData(struct eap_sm *sm)
    2264             : {
    2265             :         struct wpabuf *resp;
    2266             : 
    2267        2947 :         if (sm == NULL || sm->eapRespData == NULL)
    2268           0 :                 return NULL;
    2269             : 
    2270        2947 :         resp = sm->eapRespData;
    2271        2947 :         sm->eapRespData = NULL;
    2272             : 
    2273        2947 :         return resp;
    2274             : }
    2275             : 
    2276             : 
    2277             : /**
    2278             :  * eap_sm_register_scard_ctx - Notification of smart card context
    2279             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2280             :  * @ctx: Context data for smart card operations
    2281             :  *
    2282             :  * Notify EAP state machines of context data for smart card operations. This
    2283             :  * context data will be used as a parameter for scard_*() functions.
    2284             :  */
    2285          69 : void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
    2286             : {
    2287          69 :         if (sm)
    2288          69 :                 sm->scard_ctx = ctx;
    2289          69 : }
    2290             : 
    2291             : 
    2292             : /**
    2293             :  * eap_set_config_blob - Set or add a named configuration blob
    2294             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2295             :  * @blob: New value for the blob
    2296             :  *
    2297             :  * Adds a new configuration blob or replaces the current value of an existing
    2298             :  * blob.
    2299             :  */
    2300           7 : void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
    2301             : {
    2302             : #ifndef CONFIG_NO_CONFIG_BLOBS
    2303           7 :         sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
    2304             : #endif /* CONFIG_NO_CONFIG_BLOBS */
    2305           7 : }
    2306             : 
    2307             : 
    2308             : /**
    2309             :  * eap_get_config_blob - Get a named configuration blob
    2310             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2311             :  * @name: Name of the blob
    2312             :  * Returns: Pointer to blob data or %NULL if not found
    2313             :  */
    2314          20 : const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
    2315             :                                                    const char *name)
    2316             : {
    2317             : #ifndef CONFIG_NO_CONFIG_BLOBS
    2318          20 :         return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
    2319             : #else /* CONFIG_NO_CONFIG_BLOBS */
    2320             :         return NULL;
    2321             : #endif /* CONFIG_NO_CONFIG_BLOBS */
    2322             : }
    2323             : 
    2324             : 
    2325             : /**
    2326             :  * eap_set_force_disabled - Set force_disabled flag
    2327             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2328             :  * @disabled: 1 = EAP disabled, 0 = EAP enabled
    2329             :  *
    2330             :  * This function is used to force EAP state machine to be disabled when it is
    2331             :  * not in use (e.g., with WPA-PSK or plaintext connections).
    2332             :  */
    2333        1088 : void eap_set_force_disabled(struct eap_sm *sm, int disabled)
    2334             : {
    2335        1088 :         sm->force_disabled = disabled;
    2336        1088 : }
    2337             : 
    2338             : 
    2339             : /**
    2340             :  * eap_set_external_sim - Set external_sim flag
    2341             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2342             :  * @external_sim: Whether external SIM/USIM processing is used
    2343             :  */
    2344        1088 : void eap_set_external_sim(struct eap_sm *sm, int external_sim)
    2345             : {
    2346        1088 :         sm->external_sim = external_sim;
    2347        1088 : }
    2348             : 
    2349             : 
    2350             :  /**
    2351             :  * eap_notify_pending - Notify that EAP method is ready to re-process a request
    2352             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2353             :  *
    2354             :  * An EAP method can perform a pending operation (e.g., to get a response from
    2355             :  * an external process). Once the response is available, this function can be
    2356             :  * used to request EAPOL state machine to retry delivering the previously
    2357             :  * received (and still unanswered) EAP request to EAP state machine.
    2358             :  */
    2359           0 : void eap_notify_pending(struct eap_sm *sm)
    2360             : {
    2361           0 :         sm->eapol_cb->notify_pending(sm->eapol_ctx);
    2362           0 : }
    2363             : 
    2364             : 
    2365             : /**
    2366             :  * eap_invalidate_cached_session - Mark cached session data invalid
    2367             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2368             :  */
    2369        5019 : void eap_invalidate_cached_session(struct eap_sm *sm)
    2370             : {
    2371        5019 :         if (sm)
    2372        5019 :                 eap_deinit_prev_method(sm, "invalidate");
    2373        5019 : }
    2374             : 
    2375             : 
    2376        1913 : int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf)
    2377             : {
    2378        2789 :         if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
    2379         876 :             os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
    2380        1037 :                 return 0; /* Not a WPS Enrollee */
    2381             : 
    2382         876 :         if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL)
    2383         620 :                 return 0; /* Not using PBC */
    2384             : 
    2385         256 :         return 1;
    2386             : }
    2387             : 
    2388             : 
    2389         823 : int eap_is_wps_pin_enrollee(struct eap_peer_config *conf)
    2390             : {
    2391        1324 :         if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
    2392         501 :             os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
    2393         322 :                 return 0; /* Not a WPS Enrollee */
    2394             : 
    2395         501 :         if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL)
    2396          58 :                 return 0; /* Not using PIN */
    2397             : 
    2398         443 :         return 1;
    2399             : }
    2400             : 
    2401             : 
    2402          83 : void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext)
    2403             : {
    2404          83 :         ext_password_free(sm->ext_pw_buf);
    2405          83 :         sm->ext_pw_buf = NULL;
    2406          83 :         sm->ext_pw = ext;
    2407          83 : }
    2408             : 
    2409             : 
    2410             : /**
    2411             :  * eap_set_anon_id - Set or add anonymous identity
    2412             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2413             :  * @id: Anonymous identity (e.g., EAP-SIM pseudonym) or %NULL to clear
    2414             :  * @len: Length of anonymous identity in octets
    2415             :  */
    2416          49 : void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len)
    2417             : {
    2418          49 :         if (sm->eapol_cb->set_anon_id)
    2419          49 :                 sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
    2420          49 : }
    2421             : 
    2422             : 
    2423         248 : int eap_peer_was_failure_expected(struct eap_sm *sm)
    2424             : {
    2425         248 :         return sm->expected_failure;
    2426             : }

Generated by: LCOV version 1.10