2 * hostapd / EAP Standalone Authenticator state machine
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
20 #include <netinet/in.h>
22 #include <sys/socket.h>
29 #define EAP_MAX_AUTH_ROUNDS 50
31 extern const struct eap_method eap_method_identity;
33 extern const struct eap_method eap_method_md5;
36 extern const struct eap_method eap_method_tls;
39 extern const struct eap_method eap_method_mschapv2;
40 #endif /* EAP_MSCHAPv2 */
42 extern const struct eap_method eap_method_peap;
45 extern const struct eap_method eap_method_tlv;
48 extern const struct eap_method eap_method_gtc;
51 extern const struct eap_method eap_method_ttls;
54 extern const struct eap_method eap_method_sim;
57 extern const struct eap_method eap_method_pax;
60 extern const struct eap_method eap_method_psk;
63 static const struct eap_method *eap_methods[] =
74 #endif /* EAP_MSCHAPv2 */
97 #define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0]))
100 const struct eap_method * eap_sm_get_eap_methods(int method)
103 for (i = 0; i < NUM_EAP_METHODS; i++) {
104 if (eap_methods[i]->method == method)
105 return eap_methods[i];
110 static void eap_user_free(struct eap_user *user);
113 /* EAP state machines are described in draft-ietf-eap-statemachine-05.txt */
115 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
116 int eapSRTT, int eapRTTVAR,
118 static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len);
119 static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len);
120 static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len);
121 static int eap_sm_nextId(struct eap_sm *sm, int id);
122 static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len);
123 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm);
124 static int eap_sm_Policy_getDecision(struct eap_sm *sm);
125 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);
128 /* Definitions for clarifying state machine implementation */
129 #define SM_STATE(machine, state) \
130 static void sm_ ## machine ## _ ## state ## _Enter(struct eap_sm *sm, \
133 #define SM_ENTRY(machine, state) \
134 if (!global || sm->machine ## _state != machine ## _ ## state) { \
135 sm->changed = TRUE; \
136 wpa_printf(MSG_DEBUG, "EAP: " #machine " entering state " #state); \
138 sm->machine ## _state = machine ## _ ## state;
140 #define SM_ENTER(machine, state) \
141 sm_ ## machine ## _ ## state ## _Enter(sm, 0)
142 #define SM_ENTER_GLOBAL(machine, state) \
143 sm_ ## machine ## _ ## state ## _Enter(sm, 1)
145 #define SM_STEP(machine) \
146 static void sm_ ## machine ## _Step(struct eap_sm *sm)
148 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
151 static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
153 return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
157 static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
160 sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
164 static void eapol_set_eapReqData(struct eap_sm *sm,
165 const u8 *eapReqData, size_t eapReqDataLen)
167 wpa_hexdump(MSG_MSGDUMP, "EAP: eapReqData -> EAPOL",
168 sm->eapReqData, sm->eapReqDataLen);
169 sm->eapol_cb->set_eapReqData(sm->eapol_ctx, eapReqData, eapReqDataLen);
173 static void eapol_set_eapKeyData(struct eap_sm *sm,
174 const u8 *eapKeyData, size_t eapKeyDataLen)
176 wpa_hexdump(MSG_MSGDUMP, "EAP: eapKeyData -> EAPOL",
177 sm->eapKeyData, sm->eapKeyDataLen);
178 sm->eapol_cb->set_eapKeyData(sm->eapol_ctx, eapKeyData, eapKeyDataLen);
182 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
185 struct eap_user *user;
187 if (sm == NULL || sm->eapol_cb == NULL ||
188 sm->eapol_cb->get_eap_user == NULL)
191 eap_user_free(sm->user);
194 user = malloc(sizeof(*user));
197 memset(user, 0, sizeof(*user));
199 if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
200 identity_len, phase2, user) != 0) {
206 sm->user_eap_method_index = 0;
212 SM_STATE(EAP, DISABLED)
214 SM_ENTRY(EAP, DISABLED);
219 SM_STATE(EAP, INITIALIZE)
221 SM_ENTRY(EAP, INITIALIZE);
224 eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
225 eapol_set_bool(sm, EAPOL_eapFail, FALSE);
226 eapol_set_bool(sm, EAPOL_eapTimeout, FALSE);
227 free(sm->eapKeyData);
228 sm->eapKeyData = NULL;
229 sm->eapKeyDataLen = 0;
230 /* eapKeyAvailable = FALSE */
231 eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
233 /* This is not defined in draft-ietf-eap-statemachine-05.txt, but
234 * method state needs to be reseted here so that it does not remain in
235 * success state when re-authentication starts. */
236 if (sm->m && sm->eap_method_priv) {
237 sm->m->reset(sm, sm->eap_method_priv);
238 sm->eap_method_priv = NULL;
241 sm->user_eap_method_index = 0;
243 if (sm->backend_auth) {
244 sm->currentMethod = EAP_TYPE_NONE;
245 /* parse rxResp, respId, respMethod */
246 eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);
248 sm->currentId = sm->respId;
255 SM_STATE(EAP, PICK_UP_METHOD)
257 SM_ENTRY(EAP, PICK_UP_METHOD);
259 if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {
260 sm->currentMethod = sm->respMethod;
261 if (sm->m && sm->eap_method_priv) {
262 sm->m->reset(sm, sm->eap_method_priv);
263 sm->eap_method_priv = NULL;
265 sm->m = eap_sm_get_eap_methods(sm->currentMethod);
266 if (sm->m && sm->m->initPickUp) {
267 sm->eap_method_priv = sm->m->initPickUp(sm);
268 if (sm->eap_method_priv == NULL) {
269 wpa_printf(MSG_DEBUG, "EAP: Failed to "
270 "initialize EAP method %d",
273 sm->currentMethod = EAP_TYPE_NONE;
277 sm->currentMethod = EAP_TYPE_NONE;
287 sm->retransWhile = eap_sm_calculateTimeout(sm, sm->retransCount,
288 sm->eapSRTT, sm->eapRTTVAR,
293 SM_STATE(EAP, RETRANSMIT)
295 SM_ENTRY(EAP, RETRANSMIT);
297 /* TODO: Is this needed since EAPOL state machines take care of
302 SM_STATE(EAP, RECEIVED)
304 SM_ENTRY(EAP, RECEIVED);
306 /* parse rxResp, respId, respMethod */
307 eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);
312 SM_STATE(EAP, DISCARD)
314 SM_ENTRY(EAP, DISCARD);
315 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
316 eapol_set_bool(sm, EAPOL_eapNoReq, TRUE);
320 SM_STATE(EAP, SEND_REQUEST)
322 SM_ENTRY(EAP, SEND_REQUEST);
324 sm->retransCount = 0;
325 if (sm->eapReqData) {
326 eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);
327 free(sm->lastReqData);
328 sm->lastReqData = sm->eapReqData;
329 sm->lastReqDataLen = sm->eapReqDataLen;
330 sm->eapReqData = NULL;
331 sm->eapReqDataLen = 0;
332 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
333 eapol_set_bool(sm, EAPOL_eapReq, TRUE);
335 wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");
336 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
337 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
338 eapol_set_bool(sm, EAPOL_eapNoReq, TRUE);
343 SM_STATE(EAP, INTEGRITY_CHECK)
345 SM_ENTRY(EAP, INTEGRITY_CHECK);
348 sm->ignore = sm->m->check(sm, sm->eap_method_priv,
349 sm->eapRespData, sm->eapRespDataLen);
354 SM_STATE(EAP, METHOD_REQUEST)
356 SM_ENTRY(EAP, METHOD_REQUEST);
359 wpa_printf(MSG_DEBUG, "EAP: method not initialized");
363 sm->currentId = eap_sm_nextId(sm, sm->currentId);
364 wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",
366 sm->lastId = sm->currentId;
367 free(sm->eapReqData);
368 sm->eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,
369 sm->currentId, &sm->eapReqDataLen);
370 if (sm->m->getTimeout)
371 sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);
373 sm->methodTimeout = 0;
377 SM_STATE(EAP, METHOD_RESPONSE)
379 SM_ENTRY(EAP, METHOD_RESPONSE);
381 sm->m->process(sm, sm->eap_method_priv, sm->eapRespData,
383 if (sm->m->isDone(sm, sm->eap_method_priv)) {
384 eap_sm_Policy_update(sm, NULL, 0);
385 free(sm->eapKeyData);
387 sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
390 sm->eapKeyData = NULL;
391 sm->eapKeyDataLen = 0;
393 sm->methodState = METHOD_END;
395 sm->methodState = METHOD_CONTINUE;
400 SM_STATE(EAP, PROPOSE_METHOD)
402 SM_ENTRY(EAP, PROPOSE_METHOD);
404 sm->currentMethod = eap_sm_Policy_getNextMethod(sm);
405 if (sm->m && sm->eap_method_priv) {
406 sm->m->reset(sm, sm->eap_method_priv);
407 sm->eap_method_priv = NULL;
409 sm->m = eap_sm_get_eap_methods(sm->currentMethod);
411 sm->eap_method_priv = sm->m->init(sm);
412 if (sm->eap_method_priv == NULL) {
413 wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "
414 "method %d", sm->currentMethod);
416 sm->currentMethod = EAP_TYPE_NONE;
419 if (sm->currentMethod == EAP_TYPE_IDENTITY ||
420 sm->currentMethod == EAP_TYPE_NOTIFICATION)
421 sm->methodState = METHOD_CONTINUE;
423 sm->methodState = METHOD_PROPOSED;
431 u8 *pos, *nak_list = NULL;
435 if (sm->eap_method_priv) {
436 sm->m->reset(sm, sm->eap_method_priv);
437 sm->eap_method_priv = NULL;
441 nak = (struct eap_hdr *) sm->eapRespData;
442 if (nak && sm->eapRespDataLen > sizeof(*nak)) {
443 len = ntohs(nak->length);
444 if (len > sm->eapRespDataLen)
445 len = sm->eapRespDataLen;
446 pos = (u8 *) (nak + 1);
448 if (*pos == EAP_TYPE_NAK) {
454 eap_sm_Policy_update(sm, nak_list, len);
458 SM_STATE(EAP, SELECT_ACTION)
460 SM_ENTRY(EAP, SELECT_ACTION);
462 sm->decision = eap_sm_Policy_getDecision(sm);
466 SM_STATE(EAP, TIMEOUT_FAILURE)
468 SM_ENTRY(EAP, TIMEOUT_FAILURE);
470 eapol_set_bool(sm, EAPOL_eapTimeout, TRUE);
474 SM_STATE(EAP, FAILURE)
476 SM_ENTRY(EAP, FAILURE);
478 free(sm->eapReqData);
479 sm->eapReqData = eap_sm_buildFailure(sm, sm->currentId,
481 if (sm->eapReqData) {
482 eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);
483 free(sm->eapReqData);
484 sm->eapReqData = NULL;
485 sm->eapReqDataLen = 0;
487 free(sm->lastReqData);
488 sm->lastReqData = NULL;
489 sm->lastReqDataLen = 0;
490 eapol_set_bool(sm, EAPOL_eapFail, TRUE);
494 SM_STATE(EAP, SUCCESS)
496 SM_ENTRY(EAP, SUCCESS);
498 free(sm->eapReqData);
499 sm->eapReqData = eap_sm_buildSuccess(sm, sm->currentId,
501 if (sm->eapReqData) {
502 eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);
503 free(sm->eapReqData);
504 sm->eapReqData = NULL;
505 sm->eapReqDataLen = 0;
507 free(sm->lastReqData);
508 sm->lastReqData = NULL;
509 sm->lastReqDataLen = 0;
510 if (sm->eapKeyData) {
511 eapol_set_eapKeyData(sm, sm->eapKeyData, sm->eapKeyDataLen);
513 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
519 if (eapol_get_bool(sm, EAPOL_eapRestart) &&
520 eapol_get_bool(sm, EAPOL_portEnabled))
521 SM_ENTER_GLOBAL(EAP, INITIALIZE);
522 else if (!eapol_get_bool(sm, EAPOL_portEnabled))
523 SM_ENTER_GLOBAL(EAP, DISABLED);
524 else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
525 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
526 wpa_printf(MSG_DEBUG, "EAP: more than %d "
527 "authentication rounds - abort",
528 EAP_MAX_AUTH_ROUNDS);
530 SM_ENTER_GLOBAL(EAP, FAILURE);
532 } else switch (sm->EAP_state) {
534 if (sm->backend_auth) {
536 SM_ENTER(EAP, SELECT_ACTION);
537 else if (sm->rxResp &&
538 (sm->respMethod == EAP_TYPE_NAK ||
539 sm->respMethod == EAP_TYPE_EXPANDED_NAK))
542 SM_ENTER(EAP, PICK_UP_METHOD);
544 SM_ENTER(EAP, SELECT_ACTION);
547 case EAP_PICK_UP_METHOD:
548 if (sm->currentMethod == EAP_TYPE_NONE) {
549 SM_ENTER(EAP, SELECT_ACTION);
551 SM_ENTER(EAP, METHOD_RESPONSE);
555 if (eapol_get_bool(sm, EAPOL_portEnabled))
556 SM_ENTER(EAP, INITIALIZE);
559 if (sm->retransWhile == 0)
560 SM_ENTER(EAP, RETRANSMIT);
561 else if (eapol_get_bool(sm, EAPOL_eapResp))
562 SM_ENTER(EAP, RECEIVED);
565 if (sm->retransCount > sm->MaxRetrans)
566 SM_ENTER(EAP, TIMEOUT_FAILURE);
571 if (sm->rxResp && (sm->respId == sm->currentId) &&
572 (sm->respMethod == EAP_TYPE_NAK ||
573 sm->respMethod == EAP_TYPE_EXPANDED_NAK)
574 && (sm->methodState == METHOD_PROPOSED))
576 else if (sm->rxResp && (sm->respId == sm->currentId) &&
577 (sm->respMethod == sm->currentMethod))
578 SM_ENTER(EAP, INTEGRITY_CHECK);
580 SM_ENTER(EAP, DISCARD);
585 case EAP_SEND_REQUEST:
588 case EAP_INTEGRITY_CHECK:
590 SM_ENTER(EAP, DISCARD);
592 SM_ENTER(EAP, METHOD_RESPONSE);
594 case EAP_METHOD_REQUEST:
595 SM_ENTER(EAP, SEND_REQUEST);
597 case EAP_METHOD_RESPONSE:
598 if (sm->methodState == METHOD_END)
599 SM_ENTER(EAP, SELECT_ACTION);
601 SM_ENTER(EAP, METHOD_REQUEST);
603 case EAP_PROPOSE_METHOD:
604 SM_ENTER(EAP, METHOD_REQUEST);
607 SM_ENTER(EAP, SELECT_ACTION);
609 case EAP_SELECT_ACTION:
610 if (sm->decision == DECISION_FAILURE)
611 SM_ENTER(EAP, FAILURE);
612 else if (sm->decision == DECISION_SUCCESS)
613 SM_ENTER(EAP, SUCCESS);
615 SM_ENTER(EAP, PROPOSE_METHOD);
617 case EAP_TIMEOUT_FAILURE:
627 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
628 int eapSRTT, int eapRTTVAR,
631 /* For now, retransmission is done in EAPOL state machines, so make
632 * sure EAP state machine does not end up trying to retransmit packets.
638 static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len)
643 /* parse rxResp, respId, respMethod */
646 sm->respMethod = EAP_TYPE_NONE;
648 if (resp == NULL || len < sizeof(*hdr))
651 hdr = (struct eap_hdr *) resp;
652 plen = ntohs(hdr->length);
654 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
655 "(len=%lu plen=%lu)", (unsigned long) len,
656 (unsigned long) plen);
660 sm->respId = hdr->identifier;
662 if (hdr->code == EAP_CODE_RESPONSE)
665 if (len > sizeof(*hdr))
666 sm->respMethod = *((u8 *) (hdr + 1));
668 wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d "
669 "respMethod=%d", sm->rxResp, sm->respId, sm->respMethod);
673 static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len)
675 struct eap_hdr *resp;
676 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id);
678 *len = sizeof(*resp);
682 resp->code = EAP_CODE_SUCCESS;
683 resp->identifier = id;
684 resp->length = htons(*len);
690 static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len)
692 struct eap_hdr *resp;
693 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id);
695 *len = sizeof(*resp);
699 resp->code = EAP_CODE_FAILURE;
700 resp->identifier = id;
701 resp->length = htons(*len);
707 static int eap_sm_nextId(struct eap_sm *sm, int id)
710 /* RFC 3748 Ch 4.1: recommended to initalize Identifier with a
713 if (id != sm->lastId)
716 return (id + 1) & 0xff;
720 void eap_sm_process_nak(struct eap_sm *sm, u8 *nak_list, size_t len)
724 wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method "
725 "index %d)", sm->user_eap_method_index);
727 wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods",
728 sm->user->methods, EAP_MAX_METHODS);
729 wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer",
732 i = sm->user_eap_method_index;
733 while (i < EAP_MAX_METHODS && sm->user->methods[i] != EAP_TYPE_NONE) {
734 for (j = 0; j < len; j++) {
735 if (nak_list[j] == sm->user->methods[i]) {
746 /* not found - remove from the list */
747 memmove(&sm->user->methods[i], &sm->user->methods[i + 1],
748 EAP_MAX_METHODS - i - 1);
749 sm->user->methods[EAP_MAX_METHODS - 1] = EAP_TYPE_NONE;
752 wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods",
753 sm->user->methods, EAP_MAX_METHODS);
757 static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len)
759 if (nak_list == NULL || sm == NULL || sm->user == NULL)
762 if (sm->user->phase2) {
763 wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user"
764 " info was selected - reject");
765 sm->decision = DECISION_FAILURE;
769 eap_sm_process_nak(sm, nak_list, len);
773 static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm)
777 /* In theory, there should be no problems with starting
778 * re-authentication with something else than EAP-Request/Identity and
779 * this does indeed work with wpa_supplicant. However, at least Funk
780 * Supplicant seemed to ignore re-auth if it skipped
781 * EAP-Request/Identity.
782 * Re-auth sets currentId == -1, so that can be used here to select
783 * whether Identity needs to be requested again. */
784 if (sm->identity == NULL || sm->currentId == -1) {
785 next = EAP_TYPE_IDENTITY;
786 sm->update_user = TRUE;
787 } else if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
788 sm->user->methods[sm->user_eap_method_index] !=
790 next = sm->user->methods[sm->user_eap_method_index++];
792 next = EAP_TYPE_NONE;
794 wpa_printf(MSG_DEBUG, "EAP: getNextMethod: type %d", next);
799 static int eap_sm_Policy_getDecision(struct eap_sm *sm)
801 if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY &&
802 sm->m->isSuccess(sm, sm->eap_method_priv)) {
803 wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> "
805 sm->update_user = TRUE;
806 return DECISION_SUCCESS;
809 if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) &&
810 !sm->m->isSuccess(sm, sm->eap_method_priv)) {
811 wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> "
813 sm->update_user = TRUE;
814 return DECISION_FAILURE;
817 if ((sm->user == NULL || sm->update_user) && sm->identity) {
818 if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
819 wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
820 "found from database -> FAILURE");
821 return DECISION_FAILURE;
823 sm->update_user = FALSE;
826 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
827 sm->user->methods[sm->user_eap_method_index] != EAP_TYPE_NONE) {
828 wpa_printf(MSG_DEBUG, "EAP: getDecision: another method "
829 "available -> CONTINUE");
830 return DECISION_CONTINUE;
833 if (sm->identity == NULL || sm->currentId == -1) {
834 wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known "
836 return DECISION_CONTINUE;
839 wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> "
841 return DECISION_FAILURE;
845 static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
847 return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
851 int eap_sm_step(struct eap_sm *sm)
859 } while (sm->changed);
864 u8 eap_get_type(const char *name)
867 for (i = 0; i < NUM_EAP_METHODS; i++) {
868 if (strcmp(eap_methods[i]->name, name) == 0)
869 return eap_methods[i]->method;
871 return EAP_TYPE_NONE;
875 void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData,
876 size_t eapRespDataLen)
880 free(sm->eapRespData);
881 sm->eapRespData = malloc(eapRespDataLen);
882 if (sm->eapRespData == NULL)
884 memcpy(sm->eapRespData, eapRespData, eapRespDataLen);
885 sm->eapRespDataLen = eapRespDataLen;
886 wpa_hexdump(MSG_MSGDUMP, "EAP: EAP-Response received",
887 eapRespData, eapRespDataLen);
891 static void eap_user_free(struct eap_user *user)
895 free(user->password);
896 user->password = NULL;
901 struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
902 struct eap_config *eap_conf)
906 sm = malloc(sizeof(*sm));
909 memset(sm, 0, sizeof(*sm));
910 sm->eapol_ctx = eapol_ctx;
911 sm->eapol_cb = eapol_cb;
913 sm->ssl_ctx = eap_conf->ssl_ctx;
914 sm->eap_sim_db_priv = eap_conf->eap_sim_db_priv;
915 sm->backend_auth = eap_conf->backend_auth;
917 wpa_printf(MSG_DEBUG, "EAP: State machine created");
923 void eap_sm_deinit(struct eap_sm *sm)
927 wpa_printf(MSG_DEBUG, "EAP: State machine removed");
928 if (sm->m && sm->eap_method_priv)
929 sm->m->reset(sm, sm->eap_method_priv);
930 free(sm->eapReqData);
931 free(sm->eapKeyData);
932 free(sm->lastReqData);
933 free(sm->eapRespData);
935 eap_user_free(sm->user);
940 void eap_sm_notify_cached(struct eap_sm *sm)
945 sm->EAP_state = EAP_SUCCESS;