eap_server.c
Go to the documentation of this file.
00001 /*
00002  * hostapd / EAP Full Authenticator state machine (RFC 4137)
00003  * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  *
00014  * This state machine is based on the full authenticator state machine defined
00015  * in RFC 4137. However, to support backend authentication in RADIUS
00016  * authentication server functionality, parts of backend authenticator (also
00017  * from RFC 4137) are mixed in. This functionality is enabled by setting
00018  * backend_auth configuration variable to TRUE.
00019  */
00020 
00021 #include "includes.h"
00022 
00023 #include "common.h"
00024 #include "eap_i.h"
00025 #include "state_machine.h"
00026 #include "common/wpa_ctrl.h"
00027 
00028 #define STATE_MACHINE_DATA struct eap_sm
00029 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
00030 
00031 #define EAP_MAX_AUTH_ROUNDS 50
00032 
00033 static void eap_user_free(struct eap_user *user);
00034 
00035 
00036 /* EAP state machines are described in RFC 4137 */
00037 
00038 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
00039                                    int eapSRTT, int eapRTTVAR,
00040                                    int methodTimeout);
00041 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp);
00042 static int eap_sm_getId(const struct wpabuf *data);
00043 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id);
00044 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id);
00045 static int eap_sm_nextId(struct eap_sm *sm, int id);
00046 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
00047                                  size_t len);
00048 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor);
00049 static int eap_sm_Policy_getDecision(struct eap_sm *sm);
00050 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
00051 
00052 
00053 static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src)
00054 {
00055         if (src == NULL)
00056                 return -1;
00057 
00058         wpabuf_free(*dst);
00059         *dst = wpabuf_dup(src);
00060         return *dst ? 0 : -1;
00061 }
00062 
00063 
00064 static int eap_copy_data(u8 **dst, size_t *dst_len,
00065                          const u8 *src, size_t src_len)
00066 {
00067         if (src == NULL)
00068                 return -1;
00069 
00070         os_free(*dst);
00071         *dst = os_malloc(src_len);
00072         if (*dst) {
00073                 os_memcpy(*dst, src, src_len);
00074                 *dst_len = src_len;
00075                 return 0;
00076         } else {
00077                 *dst_len = 0;
00078                 return -1;
00079         }
00080 }
00081 
00082 #define EAP_COPY(dst, src) \
00083         eap_copy_data((dst), (dst ## Len), (src), (src ## Len))
00084 
00085 
00099 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
00100                  int phase2)
00101 {
00102         struct eap_user *user;
00103 
00104         if (sm == NULL || sm->eapol_cb == NULL ||
00105             sm->eapol_cb->get_eap_user == NULL)
00106                 return -1;
00107 
00108         eap_user_free(sm->user);
00109         sm->user = NULL;
00110 
00111         user = os_zalloc(sizeof(*user));
00112         if (user == NULL)
00113             return -1;
00114 
00115         if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
00116                                        identity_len, phase2, user) != 0) {
00117                 eap_user_free(user);
00118                 return -1;
00119         }
00120 
00121         sm->user = user;
00122         sm->user_eap_method_index = 0;
00123 
00124         return 0;
00125 }
00126 
00127 
00128 SM_STATE(EAP, DISABLED)
00129 {
00130         SM_ENTRY(EAP, DISABLED);
00131         sm->num_rounds = 0;
00132 }
00133 
00134 
00135 SM_STATE(EAP, INITIALIZE)
00136 {
00137         SM_ENTRY(EAP, INITIALIZE);
00138 
00139         sm->currentId = -1;
00140         sm->eap_if.eapSuccess = FALSE;
00141         sm->eap_if.eapFail = FALSE;
00142         sm->eap_if.eapTimeout = FALSE;
00143         os_free(sm->eap_if.eapKeyData);
00144         sm->eap_if.eapKeyData = NULL;
00145         sm->eap_if.eapKeyDataLen = 0;
00146         sm->eap_if.eapKeyAvailable = FALSE;
00147         sm->eap_if.eapRestart = FALSE;
00148 
00149         /*
00150          * This is not defined in RFC 4137, but method state needs to be
00151          * reseted here so that it does not remain in success state when
00152          * re-authentication starts.
00153          */
00154         if (sm->m && sm->eap_method_priv) {
00155                 sm->m->reset(sm, sm->eap_method_priv);
00156                 sm->eap_method_priv = NULL;
00157         }
00158         sm->m = NULL;
00159         sm->user_eap_method_index = 0;
00160 
00161         if (sm->backend_auth) {
00162                 sm->currentMethod = EAP_TYPE_NONE;
00163                 /* parse rxResp, respId, respMethod */
00164                 eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
00165                 if (sm->rxResp) {
00166                         sm->currentId = sm->respId;
00167                 }
00168         }
00169         sm->num_rounds = 0;
00170         sm->method_pending = METHOD_PENDING_NONE;
00171 
00172         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
00173                 MACSTR, MAC2STR(sm->peer_addr));
00174 }
00175 
00176 
00177 SM_STATE(EAP, PICK_UP_METHOD)
00178 {
00179         SM_ENTRY(EAP, PICK_UP_METHOD);
00180 
00181         if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
00182                 sm->currentMethod = sm->respMethod;
00183                 if (sm->m && sm->eap_method_priv) {
00184                         sm->m->reset(sm, sm->eap_method_priv);
00185                         sm->eap_method_priv = NULL;
00186                 }
00187                 sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF,
00188                                                   sm->currentMethod);
00189                 if (sm->m && sm->m->initPickUp) {
00190                         sm->eap_method_priv = sm->m->initPickUp(sm);
00191                         if (sm->eap_method_priv == NULL) {
00192                                 wpa_printf(MSG_DEBUG, "EAP: Failed to "
00193                                            "initialize EAP method %d",
00194                                            sm->currentMethod);
00195                                 sm->m = NULL;
00196                                 sm->currentMethod = EAP_TYPE_NONE;
00197                         }
00198                 } else {
00199                         sm->m = NULL;
00200                         sm->currentMethod = EAP_TYPE_NONE;
00201                 }
00202         }
00203 
00204         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
00205                 "method=%u", sm->currentMethod);
00206 }
00207 
00208 
00209 SM_STATE(EAP, IDLE)
00210 {
00211         SM_ENTRY(EAP, IDLE);
00212 
00213         sm->eap_if.retransWhile = eap_sm_calculateTimeout(
00214                 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
00215                 sm->methodTimeout);
00216 }
00217 
00218 
00219 SM_STATE(EAP, RETRANSMIT)
00220 {
00221         SM_ENTRY(EAP, RETRANSMIT);
00222 
00223         sm->retransCount++;
00224         if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
00225                 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
00226                         sm->eap_if.eapReq = TRUE;
00227         }
00228 }
00229 
00230 
00231 SM_STATE(EAP, RECEIVED)
00232 {
00233         SM_ENTRY(EAP, RECEIVED);
00234 
00235         /* parse rxResp, respId, respMethod */
00236         eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
00237         sm->num_rounds++;
00238 }
00239 
00240 
00241 SM_STATE(EAP, DISCARD)
00242 {
00243         SM_ENTRY(EAP, DISCARD);
00244         sm->eap_if.eapResp = FALSE;
00245         sm->eap_if.eapNoReq = TRUE;
00246 }
00247 
00248 
00249 SM_STATE(EAP, SEND_REQUEST)
00250 {
00251         SM_ENTRY(EAP, SEND_REQUEST);
00252 
00253         sm->retransCount = 0;
00254         if (sm->eap_if.eapReqData) {
00255                 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
00256                 {
00257                         sm->eap_if.eapResp = FALSE;
00258                         sm->eap_if.eapReq = TRUE;
00259                 } else {
00260                         sm->eap_if.eapResp = FALSE;
00261                         sm->eap_if.eapReq = FALSE;
00262                 }
00263         } else {
00264                 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
00265                 sm->eap_if.eapResp = FALSE;
00266                 sm->eap_if.eapReq = FALSE;
00267                 sm->eap_if.eapNoReq = TRUE;
00268         }
00269 }
00270 
00271 
00272 SM_STATE(EAP, INTEGRITY_CHECK)
00273 {
00274         SM_ENTRY(EAP, INTEGRITY_CHECK);
00275 
00276         if (sm->m->check) {
00277                 sm->ignore = sm->m->check(sm, sm->eap_method_priv,
00278                                           sm->eap_if.eapRespData);
00279         }
00280 }
00281 
00282 
00283 SM_STATE(EAP, METHOD_REQUEST)
00284 {
00285         SM_ENTRY(EAP, METHOD_REQUEST);
00286 
00287         if (sm->m == NULL) {
00288                 wpa_printf(MSG_DEBUG, "EAP: method not initialized");
00289                 return;
00290         }
00291 
00292         sm->currentId = eap_sm_nextId(sm, sm->currentId);
00293         wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
00294                    sm->currentId);
00295         sm->lastId = sm->currentId;
00296         wpabuf_free(sm->eap_if.eapReqData);
00297         sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
00298                                                 sm->currentId);
00299         if (sm->m->getTimeout)
00300                 sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
00301         else
00302                 sm->methodTimeout = 0;
00303 }
00304 
00305 
00306 SM_STATE(EAP, METHOD_RESPONSE)
00307 {
00308         SM_ENTRY(EAP, METHOD_RESPONSE);
00309 
00310         sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData);
00311         if (sm->m->isDone(sm, sm->eap_method_priv)) {
00312                 eap_sm_Policy_update(sm, NULL, 0);
00313                 os_free(sm->eap_if.eapKeyData);
00314                 if (sm->m->getKey) {
00315                         sm->eap_if.eapKeyData = sm->m->getKey(
00316                                 sm, sm->eap_method_priv,
00317                                 &sm->eap_if.eapKeyDataLen);
00318                 } else {
00319                         sm->eap_if.eapKeyData = NULL;
00320                         sm->eap_if.eapKeyDataLen = 0;
00321                 }
00322                 sm->methodState = METHOD_END;
00323         } else {
00324                 sm->methodState = METHOD_CONTINUE;
00325         }
00326 }
00327 
00328 
00329 SM_STATE(EAP, PROPOSE_METHOD)
00330 {
00331         int vendor;
00332         EapType type;
00333 
00334         SM_ENTRY(EAP, PROPOSE_METHOD);
00335 
00336         type = eap_sm_Policy_getNextMethod(sm, &vendor);
00337         if (vendor == EAP_VENDOR_IETF)
00338                 sm->currentMethod = type;
00339         else
00340                 sm->currentMethod = EAP_TYPE_EXPANDED;
00341         if (sm->m && sm->eap_method_priv) {
00342                 sm->m->reset(sm, sm->eap_method_priv);
00343                 sm->eap_method_priv = NULL;
00344         }
00345         sm->m = eap_server_get_eap_method(vendor, type);
00346         if (sm->m) {
00347                 sm->eap_method_priv = sm->m->init(sm);
00348                 if (sm->eap_method_priv == NULL) {
00349                         wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
00350                                    "method %d", sm->currentMethod);
00351                         sm->m = NULL;
00352                         sm->currentMethod = EAP_TYPE_NONE;
00353                 }
00354         }
00355         if (sm->currentMethod == EAP_TYPE_IDENTITY ||
00356             sm->currentMethod == EAP_TYPE_NOTIFICATION)
00357                 sm->methodState = METHOD_CONTINUE;
00358         else
00359                 sm->methodState = METHOD_PROPOSED;
00360 
00361         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
00362                 "vendor=%u method=%u", vendor, sm->currentMethod);
00363 }
00364 
00365 
00366 SM_STATE(EAP, NAK)
00367 {
00368         const struct eap_hdr *nak;
00369         size_t len = 0;
00370         const u8 *pos;
00371         const u8 *nak_list = NULL;
00372 
00373         SM_ENTRY(EAP, NAK);
00374 
00375         if (sm->eap_method_priv) {
00376                 sm->m->reset(sm, sm->eap_method_priv);
00377                 sm->eap_method_priv = NULL;
00378         }
00379         sm->m = NULL;
00380 
00381         nak = wpabuf_head(sm->eap_if.eapRespData);
00382         if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) {
00383                 len = be_to_host16(nak->length);
00384                 if (len > wpabuf_len(sm->eap_if.eapRespData))
00385                         len = wpabuf_len(sm->eap_if.eapRespData);
00386                 pos = (const u8 *) (nak + 1);
00387                 len -= sizeof(*nak);
00388                 if (*pos == EAP_TYPE_NAK) {
00389                         pos++;
00390                         len--;
00391                         nak_list = pos;
00392                 }
00393         }
00394         eap_sm_Policy_update(sm, nak_list, len);
00395 }
00396 
00397 
00398 SM_STATE(EAP, SELECT_ACTION)
00399 {
00400         SM_ENTRY(EAP, SELECT_ACTION);
00401 
00402         sm->decision = eap_sm_Policy_getDecision(sm);
00403 }
00404 
00405 
00406 SM_STATE(EAP, TIMEOUT_FAILURE)
00407 {
00408         SM_ENTRY(EAP, TIMEOUT_FAILURE);
00409 
00410         sm->eap_if.eapTimeout = TRUE;
00411 }
00412 
00413 
00414 SM_STATE(EAP, FAILURE)
00415 {
00416         SM_ENTRY(EAP, FAILURE);
00417 
00418         wpabuf_free(sm->eap_if.eapReqData);
00419         sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId);
00420         wpabuf_free(sm->lastReqData);
00421         sm->lastReqData = NULL;
00422         sm->eap_if.eapFail = TRUE;
00423 
00424         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
00425                 MACSTR, MAC2STR(sm->peer_addr));
00426 }
00427 
00428 
00429 SM_STATE(EAP, SUCCESS)
00430 {
00431         SM_ENTRY(EAP, SUCCESS);
00432 
00433         wpabuf_free(sm->eap_if.eapReqData);
00434         sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId);
00435         wpabuf_free(sm->lastReqData);
00436         sm->lastReqData = NULL;
00437         if (sm->eap_if.eapKeyData)
00438                 sm->eap_if.eapKeyAvailable = TRUE;
00439         sm->eap_if.eapSuccess = TRUE;
00440 
00441         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
00442                 MACSTR, MAC2STR(sm->peer_addr));
00443 }
00444 
00445 
00446 SM_STATE(EAP, INITIALIZE_PASSTHROUGH)
00447 {
00448         SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH);
00449 
00450         wpabuf_free(sm->eap_if.aaaEapRespData);
00451         sm->eap_if.aaaEapRespData = NULL;
00452 }
00453 
00454 
00455 SM_STATE(EAP, IDLE2)
00456 {
00457         SM_ENTRY(EAP, IDLE2);
00458 
00459         sm->eap_if.retransWhile = eap_sm_calculateTimeout(
00460                 sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR,
00461                 sm->methodTimeout);
00462 }
00463 
00464 
00465 SM_STATE(EAP, RETRANSMIT2)
00466 {
00467         SM_ENTRY(EAP, RETRANSMIT2);
00468 
00469         sm->retransCount++;
00470         if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) {
00471                 if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0)
00472                         sm->eap_if.eapReq = TRUE;
00473         }
00474 }
00475 
00476 
00477 SM_STATE(EAP, RECEIVED2)
00478 {
00479         SM_ENTRY(EAP, RECEIVED2);
00480 
00481         /* parse rxResp, respId, respMethod */
00482         eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
00483 }
00484 
00485 
00486 SM_STATE(EAP, DISCARD2)
00487 {
00488         SM_ENTRY(EAP, DISCARD2);
00489         sm->eap_if.eapResp = FALSE;
00490         sm->eap_if.eapNoReq = TRUE;
00491 }
00492 
00493 
00494 SM_STATE(EAP, SEND_REQUEST2)
00495 {
00496         SM_ENTRY(EAP, SEND_REQUEST2);
00497 
00498         sm->retransCount = 0;
00499         if (sm->eap_if.eapReqData) {
00500                 if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
00501                 {
00502                         sm->eap_if.eapResp = FALSE;
00503                         sm->eap_if.eapReq = TRUE;
00504                 } else {
00505                         sm->eap_if.eapResp = FALSE;
00506                         sm->eap_if.eapReq = FALSE;
00507                 }
00508         } else {
00509                 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData");
00510                 sm->eap_if.eapResp = FALSE;
00511                 sm->eap_if.eapReq = FALSE;
00512                 sm->eap_if.eapNoReq = TRUE;
00513         }
00514 }
00515 
00516 
00517 SM_STATE(EAP, AAA_REQUEST)
00518 {
00519         SM_ENTRY(EAP, AAA_REQUEST);
00520 
00521         if (sm->eap_if.eapRespData == NULL) {
00522                 wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData");
00523                 return;
00524         }
00525 
00526         /*
00527          * if (respMethod == IDENTITY)
00528          *      aaaIdentity = eapRespData
00529          * This is already taken care of by the EAP-Identity method which
00530          * stores the identity into sm->identity.
00531          */
00532 
00533         eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData);
00534 }
00535 
00536 
00537 SM_STATE(EAP, AAA_RESPONSE)
00538 {
00539         SM_ENTRY(EAP, AAA_RESPONSE);
00540 
00541         eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
00542         sm->currentId = eap_sm_getId(sm->eap_if.eapReqData);
00543         sm->methodTimeout = sm->eap_if.aaaMethodTimeout;
00544 }
00545 
00546 
00547 SM_STATE(EAP, AAA_IDLE)
00548 {
00549         SM_ENTRY(EAP, AAA_IDLE);
00550 
00551         sm->eap_if.aaaFail = FALSE;
00552         sm->eap_if.aaaSuccess = FALSE;
00553         sm->eap_if.aaaEapReq = FALSE;
00554         sm->eap_if.aaaEapNoReq = FALSE;
00555         sm->eap_if.aaaEapResp = TRUE;
00556 }
00557 
00558 
00559 SM_STATE(EAP, TIMEOUT_FAILURE2)
00560 {
00561         SM_ENTRY(EAP, TIMEOUT_FAILURE2);
00562 
00563         sm->eap_if.eapTimeout = TRUE;
00564 }
00565 
00566 
00567 SM_STATE(EAP, FAILURE2)
00568 {
00569         SM_ENTRY(EAP, FAILURE2);
00570 
00571         eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
00572         sm->eap_if.eapFail = TRUE;
00573 }
00574 
00575 
00576 SM_STATE(EAP, SUCCESS2)
00577 {
00578         SM_ENTRY(EAP, SUCCESS2);
00579 
00580         eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
00581 
00582         sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable;
00583         if (sm->eap_if.aaaEapKeyAvailable) {
00584                 EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData);
00585         } else {
00586                 os_free(sm->eap_if.eapKeyData);
00587                 sm->eap_if.eapKeyData = NULL;
00588                 sm->eap_if.eapKeyDataLen = 0;
00589         }
00590 
00591         sm->eap_if.eapSuccess = TRUE;
00592 
00593         /*
00594          * Start reauthentication with identity request even though we know the
00595          * previously used identity. This is needed to get reauthentication
00596          * started properly.
00597          */
00598         sm->start_reauth = TRUE;
00599 }
00600 
00601 
00602 SM_STEP(EAP)
00603 {
00604         if (sm->eap_if.eapRestart && sm->eap_if.portEnabled)
00605                 SM_ENTER_GLOBAL(EAP, INITIALIZE);
00606         else if (!sm->eap_if.portEnabled)
00607                 SM_ENTER_GLOBAL(EAP, DISABLED);
00608         else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
00609                 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
00610                         wpa_printf(MSG_DEBUG, "EAP: more than %d "
00611                                    "authentication rounds - abort",
00612                                    EAP_MAX_AUTH_ROUNDS);
00613                         sm->num_rounds++;
00614                         SM_ENTER_GLOBAL(EAP, FAILURE);
00615                 }
00616         } else switch (sm->EAP_state) {
00617         case EAP_INITIALIZE:
00618                 if (sm->backend_auth) {
00619                         if (!sm->rxResp)
00620                                 SM_ENTER(EAP, SELECT_ACTION);
00621                         else if (sm->rxResp &&
00622                                  (sm->respMethod == EAP_TYPE_NAK ||
00623                                   (sm->respMethod == EAP_TYPE_EXPANDED &&
00624                                    sm->respVendor == EAP_VENDOR_IETF &&
00625                                    sm->respVendorMethod == EAP_TYPE_NAK)))
00626                                 SM_ENTER(EAP, NAK);
00627                         else
00628                                 SM_ENTER(EAP, PICK_UP_METHOD);
00629                 } else {
00630                         SM_ENTER(EAP, SELECT_ACTION);
00631                 }
00632                 break;
00633         case EAP_PICK_UP_METHOD:
00634                 if (sm->currentMethod == EAP_TYPE_NONE) {
00635                         SM_ENTER(EAP, SELECT_ACTION);
00636                 } else {
00637                         SM_ENTER(EAP, METHOD_RESPONSE);
00638                 }
00639                 break;
00640         case EAP_DISABLED:
00641                 if (sm->eap_if.portEnabled)
00642                         SM_ENTER(EAP, INITIALIZE);
00643                 break;
00644         case EAP_IDLE:
00645                 if (sm->eap_if.retransWhile == 0)
00646                         SM_ENTER(EAP, RETRANSMIT);
00647                 else if (sm->eap_if.eapResp)
00648                         SM_ENTER(EAP, RECEIVED);
00649                 break;
00650         case EAP_RETRANSMIT:
00651                 if (sm->retransCount > sm->MaxRetrans)
00652                         SM_ENTER(EAP, TIMEOUT_FAILURE);
00653                 else
00654                         SM_ENTER(EAP, IDLE);
00655                 break;
00656         case EAP_RECEIVED:
00657                 if (sm->rxResp && (sm->respId == sm->currentId) &&
00658                     (sm->respMethod == EAP_TYPE_NAK ||
00659                      (sm->respMethod == EAP_TYPE_EXPANDED &&
00660                       sm->respVendor == EAP_VENDOR_IETF &&
00661                       sm->respVendorMethod == EAP_TYPE_NAK))
00662                     && (sm->methodState == METHOD_PROPOSED))
00663                         SM_ENTER(EAP, NAK);
00664                 else if (sm->rxResp && (sm->respId == sm->currentId) &&
00665                          ((sm->respMethod == sm->currentMethod) ||
00666                           (sm->respMethod == EAP_TYPE_EXPANDED &&
00667                            sm->respVendor == EAP_VENDOR_IETF &&
00668                            sm->respVendorMethod == sm->currentMethod)))
00669                         SM_ENTER(EAP, INTEGRITY_CHECK);
00670                 else {
00671                         wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: "
00672                                    "rxResp=%d respId=%d currentId=%d "
00673                                    "respMethod=%d currentMethod=%d",
00674                                    sm->rxResp, sm->respId, sm->currentId,
00675                                    sm->respMethod, sm->currentMethod);
00676                         SM_ENTER(EAP, DISCARD);
00677                 }
00678                 break;
00679         case EAP_DISCARD:
00680                 SM_ENTER(EAP, IDLE);
00681                 break;
00682         case EAP_SEND_REQUEST:
00683                 SM_ENTER(EAP, IDLE);
00684                 break;
00685         case EAP_INTEGRITY_CHECK:
00686                 if (sm->ignore)
00687                         SM_ENTER(EAP, DISCARD);
00688                 else
00689                         SM_ENTER(EAP, METHOD_RESPONSE);
00690                 break;
00691         case EAP_METHOD_REQUEST:
00692                 SM_ENTER(EAP, SEND_REQUEST);
00693                 break;
00694         case EAP_METHOD_RESPONSE:
00695                 /*
00696                  * Note: Mechanism to allow EAP methods to wait while going
00697                  * through pending processing is an extension to RFC 4137
00698                  * which only defines the transits to SELECT_ACTION and
00699                  * METHOD_REQUEST from this METHOD_RESPONSE state.
00700                  */
00701                 if (sm->methodState == METHOD_END)
00702                         SM_ENTER(EAP, SELECT_ACTION);
00703                 else if (sm->method_pending == METHOD_PENDING_WAIT) {
00704                         wpa_printf(MSG_DEBUG, "EAP: Method has pending "
00705                                    "processing - wait before proceeding to "
00706                                    "METHOD_REQUEST state");
00707                 } else if (sm->method_pending == METHOD_PENDING_CONT) {
00708                         wpa_printf(MSG_DEBUG, "EAP: Method has completed "
00709                                    "pending processing - reprocess pending "
00710                                    "EAP message");
00711                         sm->method_pending = METHOD_PENDING_NONE;
00712                         SM_ENTER(EAP, METHOD_RESPONSE);
00713                 } else
00714                         SM_ENTER(EAP, METHOD_REQUEST);
00715                 break;
00716         case EAP_PROPOSE_METHOD:
00717                 /*
00718                  * Note: Mechanism to allow EAP methods to wait while going
00719                  * through pending processing is an extension to RFC 4137
00720                  * which only defines the transit to METHOD_REQUEST from this
00721                  * PROPOSE_METHOD state.
00722                  */
00723                 if (sm->method_pending == METHOD_PENDING_WAIT) {
00724                         wpa_printf(MSG_DEBUG, "EAP: Method has pending "
00725                                    "processing - wait before proceeding to "
00726                                    "METHOD_REQUEST state");
00727                         if (sm->user_eap_method_index > 0)
00728                                 sm->user_eap_method_index--;
00729                 } else if (sm->method_pending == METHOD_PENDING_CONT) {
00730                         wpa_printf(MSG_DEBUG, "EAP: Method has completed "
00731                                    "pending processing - reprocess pending "
00732                                    "EAP message");
00733                         sm->method_pending = METHOD_PENDING_NONE;
00734                         SM_ENTER(EAP, PROPOSE_METHOD);
00735                 } else
00736                         SM_ENTER(EAP, METHOD_REQUEST);
00737                 break;
00738         case EAP_NAK:
00739                 SM_ENTER(EAP, SELECT_ACTION);
00740                 break;
00741         case EAP_SELECT_ACTION:
00742                 if (sm->decision == DECISION_FAILURE)
00743                         SM_ENTER(EAP, FAILURE);
00744                 else if (sm->decision == DECISION_SUCCESS)
00745                         SM_ENTER(EAP, SUCCESS);
00746                 else if (sm->decision == DECISION_PASSTHROUGH)
00747                         SM_ENTER(EAP, INITIALIZE_PASSTHROUGH);
00748                 else
00749                         SM_ENTER(EAP, PROPOSE_METHOD);
00750                 break;
00751         case EAP_TIMEOUT_FAILURE:
00752                 break;
00753         case EAP_FAILURE:
00754                 break;
00755         case EAP_SUCCESS:
00756                 break;
00757 
00758         case EAP_INITIALIZE_PASSTHROUGH:
00759                 if (sm->currentId == -1)
00760                         SM_ENTER(EAP, AAA_IDLE);
00761                 else
00762                         SM_ENTER(EAP, AAA_REQUEST);
00763                 break;
00764         case EAP_IDLE2:
00765                 if (sm->eap_if.eapResp)
00766                         SM_ENTER(EAP, RECEIVED2);
00767                 else if (sm->eap_if.retransWhile == 0)
00768                         SM_ENTER(EAP, RETRANSMIT2);
00769                 break;
00770         case EAP_RETRANSMIT2:
00771                 if (sm->retransCount > sm->MaxRetrans)
00772                         SM_ENTER(EAP, TIMEOUT_FAILURE2);
00773                 else
00774                         SM_ENTER(EAP, IDLE2);
00775                 break;
00776         case EAP_RECEIVED2:
00777                 if (sm->rxResp && (sm->respId == sm->currentId))
00778                         SM_ENTER(EAP, AAA_REQUEST);
00779                 else
00780                         SM_ENTER(EAP, DISCARD2);
00781                 break;
00782         case EAP_DISCARD2:
00783                 SM_ENTER(EAP, IDLE2);
00784                 break;
00785         case EAP_SEND_REQUEST2:
00786                 SM_ENTER(EAP, IDLE2);
00787                 break;
00788         case EAP_AAA_REQUEST:
00789                 SM_ENTER(EAP, AAA_IDLE);
00790                 break;
00791         case EAP_AAA_RESPONSE:
00792                 SM_ENTER(EAP, SEND_REQUEST2);
00793                 break;
00794         case EAP_AAA_IDLE:
00795                 if (sm->eap_if.aaaFail)
00796                         SM_ENTER(EAP, FAILURE2);
00797                 else if (sm->eap_if.aaaSuccess)
00798                         SM_ENTER(EAP, SUCCESS2);
00799                 else if (sm->eap_if.aaaEapReq)
00800                         SM_ENTER(EAP, AAA_RESPONSE);
00801                 else if (sm->eap_if.aaaTimeout)
00802                         SM_ENTER(EAP, TIMEOUT_FAILURE2);
00803                 break;
00804         case EAP_TIMEOUT_FAILURE2:
00805                 break;
00806         case EAP_FAILURE2:
00807                 break;
00808         case EAP_SUCCESS2:
00809                 break;
00810         }
00811 }
00812 
00813 
00814 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
00815                                    int eapSRTT, int eapRTTVAR,
00816                                    int methodTimeout)
00817 {
00818         int rto, i;
00819 
00820         if (methodTimeout) {
00821                 /*
00822                  * EAP method (either internal or through AAA server, provided
00823                  * timeout hint. Use that as-is as a timeout for retransmitting
00824                  * the EAP request if no response is received.
00825                  */
00826                 wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
00827                            "(from EAP method hint)", methodTimeout);
00828                 return methodTimeout;
00829         }
00830 
00831         /*
00832          * RFC 3748 recommends algorithms described in RFC 2988 for estimation
00833          * of the retransmission timeout. This should be implemented once
00834          * round-trip time measurements are available. For nowm a simple
00835          * backoff mechanism is used instead if there are no EAP method
00836          * specific hints.
00837          *
00838          * SRTT = smoothed round-trip time
00839          * RTTVAR = round-trip time variation
00840          * RTO = retransmission timeout
00841          */
00842 
00843         /*
00844          * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for
00845          * initial retransmission and then double the RTO to provide back off
00846          * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3
00847          * modified RTOmax.
00848          */
00849         rto = 3;
00850         for (i = 0; i < retransCount; i++) {
00851                 rto *= 2;
00852                 if (rto >= 20) {
00853                         rto = 20;
00854                         break;
00855                 }
00856         }
00857 
00858         wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds "
00859                    "(from dynamic back off; retransCount=%d)",
00860                    rto, retransCount);
00861 
00862         return rto;
00863 }
00864 
00865 
00866 static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp)
00867 {
00868         const struct eap_hdr *hdr;
00869         size_t plen;
00870 
00871         /* parse rxResp, respId, respMethod */
00872         sm->rxResp = FALSE;
00873         sm->respId = -1;
00874         sm->respMethod = EAP_TYPE_NONE;
00875         sm->respVendor = EAP_VENDOR_IETF;
00876         sm->respVendorMethod = EAP_TYPE_NONE;
00877 
00878         if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) {
00879                 wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p "
00880                            "len=%lu", resp,
00881                            resp ? (unsigned long) wpabuf_len(resp) : 0);
00882                 return;
00883         }
00884 
00885         hdr = wpabuf_head(resp);
00886         plen = be_to_host16(hdr->length);
00887         if (plen > wpabuf_len(resp)) {
00888                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
00889                            "(len=%lu plen=%lu)",
00890                            (unsigned long) wpabuf_len(resp),
00891                            (unsigned long) plen);
00892                 return;
00893         }
00894 
00895         sm->respId = hdr->identifier;
00896 
00897         if (hdr->code == EAP_CODE_RESPONSE)
00898                 sm->rxResp = TRUE;
00899 
00900         if (plen > sizeof(*hdr)) {
00901                 u8 *pos = (u8 *) (hdr + 1);
00902                 sm->respMethod = *pos++;
00903                 if (sm->respMethod == EAP_TYPE_EXPANDED) {
00904                         if (plen < sizeof(*hdr) + 8) {
00905                                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
00906                                            "expanded EAP-Packet (plen=%lu)",
00907                                            (unsigned long) plen);
00908                                 return;
00909                         }
00910                         sm->respVendor = WPA_GET_BE24(pos);
00911                         pos += 3;
00912                         sm->respVendorMethod = WPA_GET_BE32(pos);
00913                 }
00914         }
00915 
00916         wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "
00917                    "respMethod=%u respVendor=%u respVendorMethod=%u",
00918                    sm->rxResp, sm->respId, sm->respMethod, sm->respVendor,
00919                    sm->respVendorMethod);
00920 }
00921 
00922 
00923 static int eap_sm_getId(const struct wpabuf *data)
00924 {
00925         const struct eap_hdr *hdr;
00926 
00927         if (data == NULL || wpabuf_len(data) < sizeof(*hdr))
00928                 return -1;
00929 
00930         hdr = wpabuf_head(data);
00931         wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier);
00932         return hdr->identifier;
00933 }
00934 
00935 
00936 static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id)
00937 {
00938         struct wpabuf *msg;
00939         struct eap_hdr *resp;
00940         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
00941 
00942         msg = wpabuf_alloc(sizeof(*resp));
00943         if (msg == NULL)
00944                 return NULL;
00945         resp = wpabuf_put(msg, sizeof(*resp));
00946         resp->code = EAP_CODE_SUCCESS;
00947         resp->identifier = id;
00948         resp->length = host_to_be16(sizeof(*resp));
00949 
00950         return msg;
00951 }
00952 
00953 
00954 static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id)
00955 {
00956         struct wpabuf *msg;
00957         struct eap_hdr *resp;
00958         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
00959 
00960         msg = wpabuf_alloc(sizeof(*resp));
00961         if (msg == NULL)
00962                 return NULL;
00963         resp = wpabuf_put(msg, sizeof(*resp));
00964         resp->code = EAP_CODE_FAILURE;
00965         resp->identifier = id;
00966         resp->length = host_to_be16(sizeof(*resp));
00967 
00968         return msg;
00969 }
00970 
00971 
00972 static int eap_sm_nextId(struct eap_sm *sm, int id)
00973 {
00974         if (id < 0) {
00975                 /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a
00976                  * random number */
00977                 id = rand() & 0xff;
00978                 if (id != sm->lastId)
00979                         return id;
00980         }
00981         return (id + 1) & 0xff;
00982 }
00983 
00984 
00994 void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len)
00995 {
00996         int i;
00997         size_t j;
00998 
00999         if (sm->user == NULL)
01000                 return;
01001 
01002         wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
01003                    "index %d)", sm->user_eap_method_index);
01004 
01005         wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
01006                     (u8 *) sm->user->methods,
01007                     EAP_MAX_METHODS * sizeof(sm->user->methods[0]));
01008         wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
01009                     nak_list, len);
01010 
01011         i = sm->user_eap_method_index;
01012         while (i < EAP_MAX_METHODS &&
01013                (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
01014                 sm->user->methods[i].method != EAP_TYPE_NONE)) {
01015                 if (sm->user->methods[i].vendor != EAP_VENDOR_IETF)
01016                         goto not_found;
01017                 for (j = 0; j < len; j++) {
01018                         if (nak_list[j] == sm->user->methods[i].method) {
01019                                 break;
01020                         }
01021                 }
01022 
01023                 if (j < len) {
01024                         /* found */
01025                         i++;
01026                         continue;
01027                 }
01028 
01029         not_found:
01030                 /* not found - remove from the list */
01031                 os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1],
01032                            (EAP_MAX_METHODS - i - 1) *
01033                            sizeof(sm->user->methods[0]));
01034                 sm->user->methods[EAP_MAX_METHODS - 1].vendor =
01035                         EAP_VENDOR_IETF;
01036                 sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE;
01037         }
01038 
01039         wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
01040                     (u8 *) sm->user->methods, EAP_MAX_METHODS *
01041                     sizeof(sm->user->methods[0]));
01042 }
01043 
01044 
01045 static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list,
01046                                  size_t len)
01047 {
01048         if (nak_list == NULL || sm == NULL || sm->user == NULL)
01049                 return;
01050 
01051         if (sm->user->phase2) {
01052                 wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
01053                            " info was selected - reject");
01054                 sm->decision = DECISION_FAILURE;
01055                 return;
01056         }
01057 
01058         eap_sm_process_nak(sm, nak_list, len);
01059 }
01060 
01061 
01062 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
01063 {
01064         EapType next;
01065         int idx = sm->user_eap_method_index;
01066 
01067         /* In theory, there should be no problems with starting
01068          * re-authentication with something else than EAP-Request/Identity and
01069          * this does indeed work with wpa_supplicant. However, at least Funk
01070          * Supplicant seemed to ignore re-auth if it skipped
01071          * EAP-Request/Identity.
01072          * Re-auth sets currentId == -1, so that can be used here to select
01073          * whether Identity needs to be requested again. */
01074         if (sm->identity == NULL || sm->currentId == -1) {
01075                 *vendor = EAP_VENDOR_IETF;
01076                 next = EAP_TYPE_IDENTITY;
01077                 sm->update_user = TRUE;
01078         } else if (sm->user && idx < EAP_MAX_METHODS &&
01079                    (sm->user->methods[idx].vendor != EAP_VENDOR_IETF ||
01080                     sm->user->methods[idx].method != EAP_TYPE_NONE)) {
01081                 *vendor = sm->user->methods[idx].vendor;
01082                 next = sm->user->methods[idx].method;
01083                 sm->user_eap_method_index++;
01084         } else {
01085                 *vendor = EAP_VENDOR_IETF;
01086                 next = EAP_TYPE_NONE;
01087         }
01088         wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d",
01089                    *vendor, next);
01090         return next;
01091 }
01092 
01093 
01094 static int eap_sm_Policy_getDecision(struct eap_sm *sm)
01095 {
01096         if (!sm->eap_server && sm->identity && !sm->start_reauth) {
01097                 wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
01098                 return DECISION_PASSTHROUGH;
01099         }
01100 
01101         if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
01102             sm->m->isSuccess(sm, sm->eap_method_priv)) {
01103                 wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
01104                            "SUCCESS");
01105                 sm->update_user = TRUE;
01106                 return DECISION_SUCCESS;
01107         }
01108 
01109         if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
01110             !sm->m->isSuccess(sm, sm->eap_method_priv)) {
01111                 wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
01112                            "FAILURE");
01113                 sm->update_user = TRUE;
01114                 return DECISION_FAILURE;
01115         }
01116 
01117         if ((sm->user == NULL || sm->update_user) && sm->identity &&
01118             !sm->start_reauth) {
01119                 /*
01120                  * Allow Identity method to be started once to allow identity
01121                  * selection hint to be sent from the authentication server,
01122                  * but prevent a loop of Identity requests by only allowing
01123                  * this to happen once.
01124                  */
01125                 int id_req = 0;
01126                 if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
01127                     sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
01128                     sm->user->methods[0].method == EAP_TYPE_IDENTITY)
01129                         id_req = 1;
01130                 if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
01131                         wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
01132                                    "found from database -> FAILURE");
01133                         return DECISION_FAILURE;
01134                 }
01135                 if (id_req && sm->user &&
01136                     sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
01137                     sm->user->methods[0].method == EAP_TYPE_IDENTITY) {
01138                         wpa_printf(MSG_DEBUG, "EAP: getDecision: stop "
01139                                    "identity request loop -> FAILURE");
01140                         sm->update_user = TRUE;
01141                         return DECISION_FAILURE;
01142                 }
01143                 sm->update_user = FALSE;
01144         }
01145         sm->start_reauth = FALSE;
01146 
01147         if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
01148             (sm->user->methods[sm->user_eap_method_index].vendor !=
01149              EAP_VENDOR_IETF ||
01150              sm->user->methods[sm->user_eap_method_index].method !=
01151              EAP_TYPE_NONE)) {
01152                 wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
01153                            "available -> CONTINUE");
01154                 return DECISION_CONTINUE;
01155         }
01156 
01157         if (sm->identity == NULL || sm->currentId == -1) {
01158                 wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
01159                            "yet -> CONTINUE");
01160                 return DECISION_CONTINUE;
01161         }
01162 
01163         wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
01164                    "FAILURE");
01165         return DECISION_FAILURE;
01166 }
01167 
01168 
01169 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
01170 {
01171         return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
01172 }
01173 
01174 
01184 int eap_server_sm_step(struct eap_sm *sm)
01185 {
01186         int res = 0;
01187         do {
01188                 sm->changed = FALSE;
01189                 SM_STEP_RUN(EAP);
01190                 if (sm->changed)
01191                         res = 1;
01192         } while (sm->changed);
01193         return res;
01194 }
01195 
01196 
01197 static void eap_user_free(struct eap_user *user)
01198 {
01199         if (user == NULL)
01200                 return;
01201         os_free(user->password);
01202         user->password = NULL;
01203         os_free(user);
01204 }
01205 
01206 
01216 struct eap_sm * eap_server_sm_init(void *eapol_ctx,
01217                                    struct eapol_callbacks *eapol_cb,
01218                                    struct eap_config *conf)
01219 {
01220         struct eap_sm *sm;
01221 
01222         sm = os_zalloc(sizeof(*sm));
01223         if (sm == NULL)
01224                 return NULL;
01225         sm->eapol_ctx = eapol_ctx;
01226         sm->eapol_cb = eapol_cb;
01227         sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
01228         sm->ssl_ctx = conf->ssl_ctx;
01229         sm->msg_ctx = conf->msg_ctx;
01230         sm->eap_sim_db_priv = conf->eap_sim_db_priv;
01231         sm->backend_auth = conf->backend_auth;
01232         sm->eap_server = conf->eap_server;
01233         if (conf->pac_opaque_encr_key) {
01234                 sm->pac_opaque_encr_key = os_malloc(16);
01235                 if (sm->pac_opaque_encr_key) {
01236                         os_memcpy(sm->pac_opaque_encr_key,
01237                                   conf->pac_opaque_encr_key, 16);
01238                 }
01239         }
01240         if (conf->eap_fast_a_id) {
01241                 sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
01242                 if (sm->eap_fast_a_id) {
01243                         os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
01244                                   conf->eap_fast_a_id_len);
01245                         sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
01246                 }
01247         }
01248         if (conf->eap_fast_a_id_info)
01249                 sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
01250         sm->eap_fast_prov = conf->eap_fast_prov;
01251         sm->pac_key_lifetime = conf->pac_key_lifetime;
01252         sm->pac_key_refresh_time = conf->pac_key_refresh_time;
01253         sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
01254         sm->tnc = conf->tnc;
01255         sm->wps = conf->wps;
01256         if (conf->assoc_wps_ie)
01257                 sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
01258         if (conf->peer_addr)
01259                 os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
01260 
01261         wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
01262 
01263         return sm;
01264 }
01265 
01266 
01274 void eap_server_sm_deinit(struct eap_sm *sm)
01275 {
01276         if (sm == NULL)
01277                 return;
01278         wpa_printf(MSG_DEBUG, "EAP: Server state machine removed");
01279         if (sm->m && sm->eap_method_priv)
01280                 sm->m->reset(sm, sm->eap_method_priv);
01281         wpabuf_free(sm->eap_if.eapReqData);
01282         os_free(sm->eap_if.eapKeyData);
01283         wpabuf_free(sm->lastReqData);
01284         wpabuf_free(sm->eap_if.eapRespData);
01285         os_free(sm->identity);
01286         os_free(sm->pac_opaque_encr_key);
01287         os_free(sm->eap_fast_a_id);
01288         os_free(sm->eap_fast_a_id_info);
01289         wpabuf_free(sm->eap_if.aaaEapReqData);
01290         wpabuf_free(sm->eap_if.aaaEapRespData);
01291         os_free(sm->eap_if.aaaEapKeyData);
01292         eap_user_free(sm->user);
01293         wpabuf_free(sm->assoc_wps_ie);
01294         os_free(sm);
01295 }
01296 
01297 
01305 void eap_sm_notify_cached(struct eap_sm *sm)
01306 {
01307         if (sm == NULL)
01308                 return;
01309 
01310         sm->EAP_state = EAP_SUCCESS;
01311 }
01312 
01313 
01320 void eap_sm_pending_cb(struct eap_sm *sm)
01321 {
01322         if (sm == NULL)
01323                 return;
01324         wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received");
01325         if (sm->method_pending == METHOD_PENDING_WAIT)
01326                 sm->method_pending = METHOD_PENDING_CONT;
01327 }
01328 
01329 
01335 int eap_sm_method_pending(struct eap_sm *sm)
01336 {
01337         if (sm == NULL)
01338                 return 0;
01339         return sm->method_pending == METHOD_PENDING_WAIT;
01340 }
01341 
01342 
01349 const u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
01350 {
01351         *len = sm->identity_len;
01352         return sm->identity;
01353 }
01354 
01355 
01361 struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm)
01362 {
01363         return &sm->eap_if;
01364 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:37