eap.c

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

Generated on Sat Nov 21 23:16:51 2009 for hostapd by  doxygen 1.6.1