2 * WPA Supplicant / EAP state machines (RFC 4137)
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.
14 * This file implements the Peer State Machine as defined in RFC 4137. The used
15 * states and state transitions match mostly with the RFC. However, there are
16 * couple of additional transitions for working around small issues noticed
17 * during testing. These exceptions are explained in comments within the
18 * functions in this file. The method functions, m.func(), are similar to the
19 * ones used in RFC 4137, but some small changes have used here to optimize
20 * operations and to add functionality needed for fast re-authentication
21 * (session resumption).
31 #include "wpa_supplicant.h"
32 #include "config_ssid.h"
35 #include "pcsc_funcs.h"
39 #define EAP_MAX_AUTH_ROUNDS 50
43 extern const struct eap_method eap_method_md5;
46 extern const struct eap_method eap_method_tls;
49 extern const struct eap_method eap_method_mschapv2;
52 extern const struct eap_method eap_method_peap;
55 extern const struct eap_method eap_method_ttls;
58 extern const struct eap_method eap_method_gtc;
61 extern const struct eap_method eap_method_otp;
64 extern const struct eap_method eap_method_sim;
67 extern const struct eap_method eap_method_leap;
70 extern const struct eap_method eap_method_psk;
73 extern const struct eap_method eap_method_aka;
76 extern const struct eap_method eap_method_fast;
79 extern const struct eap_method eap_method_pax;
82 static const struct eap_method *eap_methods[] =
124 #define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0]))
128 * eap_sm_get_eap_methods - Get EAP method based on type number
129 * @method: EAP type number
130 * Returns: Pointer to EAP method of %NULL if not found
132 const struct eap_method * eap_sm_get_eap_methods(int method)
135 for (i = 0; i < NUM_EAP_METHODS; i++) {
136 if (eap_methods[i]->method == method)
137 return eap_methods[i];
143 static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method);
144 static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len);
145 static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req,
147 static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len);
148 static u8 * eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len);
149 static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len);
150 static const char * eap_sm_method_state_txt(EapMethodState state);
151 static const char * eap_sm_decision_txt(EapDecision decision);
154 /* Definitions for clarifying state machine implementation */
155 #define SM_STATE(machine, state) \
156 static void sm_ ## machine ## _ ## state ## _Enter(struct eap_sm *sm, \
159 #define SM_ENTRY(machine, state) \
160 if (!global || sm->machine ## _state != machine ## _ ## state) { \
161 sm->changed = TRUE; \
162 wpa_printf(MSG_DEBUG, "EAP: " #machine " entering state " #state); \
164 sm->machine ## _state = machine ## _ ## state;
166 #define SM_ENTER(machine, state) \
167 sm_ ## machine ## _ ## state ## _Enter(sm, 0)
168 #define SM_ENTER_GLOBAL(machine, state) \
169 sm_ ## machine ## _ ## state ## _Enter(sm, 1)
171 #define SM_STEP(machine) \
172 static void sm_ ## machine ## _Step(struct eap_sm *sm)
174 #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
177 static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
179 return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
183 static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
186 sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
190 static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
192 return sm->eapol_cb->get_int(sm->eapol_ctx, var);
196 static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
199 sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
203 static u8 * eapol_get_eapReqData(struct eap_sm *sm, size_t *len)
205 return sm->eapol_cb->get_eapReqData(sm->eapol_ctx, len);
209 static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
211 if (sm->m == NULL || sm->eap_method_priv == NULL)
214 wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
215 "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
216 sm->m->deinit(sm, sm->eap_method_priv);
217 sm->eap_method_priv = NULL;
223 * This state initializes state machine variables when the machine is
224 * activated (portEnabled = TRUE). This is also used when re-starting
225 * authentication (eapRestart == TRUE).
227 SM_STATE(EAP, INITIALIZE)
229 SM_ENTRY(EAP, INITIALIZE);
230 if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
231 sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
232 wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
233 "fast reauthentication");
234 sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
236 eap_deinit_prev_method(sm, "INITIALIZE");
238 sm->selectedMethod = EAP_TYPE_NONE;
239 sm->methodState = METHOD_NONE;
240 sm->allowNotifications = TRUE;
241 sm->decision = DECISION_FAIL;
242 eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
243 eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
244 eapol_set_bool(sm, EAPOL_eapFail, FALSE);
245 free(sm->eapKeyData);
246 sm->eapKeyData = NULL;
247 sm->eapKeyAvailable = FALSE;
248 eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
249 sm->lastId = -1; /* new session - make sure this does not match with
250 * the first EAP-Packet */
252 * RFC 4137 does not reset eapResp and eapNoResp here. However, this
253 * seemed to be able to trigger cases where both were set and if EAPOL
254 * state machine uses eapNoResp first, it may end up not sending a real
255 * reply correctly. This occurred when the workaround in FAIL state set
256 * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
259 eapol_set_bool(sm, EAPOL_eapResp, FALSE);
260 eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
266 * This state is reached whenever service from the lower layer is interrupted
267 * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
268 * occurs when the port becomes enabled.
270 SM_STATE(EAP, DISABLED)
272 SM_ENTRY(EAP, DISABLED);
278 * The state machine spends most of its time here, waiting for something to
279 * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
280 * SEND_RESPONSE states.
289 * This state is entered when an EAP packet is received (eapReq == TRUE) to
290 * parse the packet header.
292 SM_STATE(EAP, RECEIVED)
294 const u8 *eapReqData;
295 size_t eapReqDataLen;
297 SM_ENTRY(EAP, RECEIVED);
298 eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
299 /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
300 eap_sm_parseEapReq(sm, eapReqData, eapReqDataLen);
306 * This state is entered when a request for a new type comes in. Either the
307 * correct method is started, or a Nak response is built.
309 SM_STATE(EAP, GET_METHOD)
311 SM_ENTRY(EAP, GET_METHOD);
312 if (eap_sm_allowMethod(sm, sm->reqMethod)) {
315 * RFC 4137 does not define specific operation for fast
316 * re-authentication (session resumption). The design here is
317 * to allow the previously used method data to be maintained
318 * for re-authentication if the method support session
319 * resumption. Otherwise, the previously used method data is
320 * freed and a new method is allocated here.
322 if (sm->fast_reauth &&
323 sm->m && sm->m->method == sm->reqMethod &&
324 sm->m->has_reauth_data &&
325 sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
326 wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
327 " for fast re-authentication");
330 eap_deinit_prev_method(sm, "GET_METHOD");
331 sm->selectedMethod = sm->reqMethod;
333 sm->m = eap_sm_get_eap_methods(sm->selectedMethod);
335 wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP "
337 sm->selectedMethod, sm->m->name);
339 sm->eap_method_priv = sm->m->init_for_reauth(
340 sm, sm->eap_method_priv);
342 sm->eap_method_priv = sm->m->init(sm);
343 if (sm->eap_method_priv == NULL) {
344 struct wpa_ssid *config = eap_get_config(sm);
345 wpa_msg(sm->msg_ctx, MSG_INFO,
346 "EAP: Failed to initialize EAP method "
348 sm->selectedMethod, sm->m->name);
350 sm->methodState = METHOD_NONE;
351 sm->selectedMethod = EAP_TYPE_NONE;
352 if (sm->reqMethod == EAP_TYPE_TLS &&
354 (config->pending_req_pin ||
355 config->pending_req_passphrase)) {
357 * Return without generating Nak in
358 * order to allow entering of PIN code
359 * or passphrase to retry the current
362 wpa_printf(MSG_DEBUG, "EAP: Pending "
363 "PIN/passphrase request - "
368 sm->methodState = METHOD_INIT;
369 wpa_msg(sm->msg_ctx, MSG_INFO,
371 "EAP method %d (%s) selected",
372 sm->selectedMethod, sm->m->name);
378 free(sm->eapRespData);
379 sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen);
384 * The method processing happens here. The request from the authenticator is
385 * processed, and an appropriate response packet is built.
387 SM_STATE(EAP, METHOD)
390 size_t eapReqDataLen;
391 struct eap_method_ret ret;
393 SM_ENTRY(EAP, METHOD);
395 wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
399 eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
402 * Get ignore, methodState, decision, allowNotifications, and
403 * eapRespData. RFC 4137 uses three separate method procedure (check,
404 * process, and buildResp) in this state. These have been combined into
405 * a single function call to m->process() in order to optimize EAP
406 * method implementation interface a bit. These procedures are only
407 * used from within this METHOD state, so there is no need to keep
408 * these as separate C functions.
410 * The RFC 4137 procedures return values as follows:
411 * ignore = m.check(eapReqData)
412 * (methodState, decision, allowNotifications) = m.process(eapReqData)
413 * eapRespData = m.buildResp(reqId)
415 memset(&ret, 0, sizeof(ret));
416 ret.ignore = sm->ignore;
417 ret.methodState = sm->methodState;
418 ret.decision = sm->decision;
419 ret.allowNotifications = sm->allowNotifications;
420 free(sm->eapRespData);
421 sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
422 eapReqData, eapReqDataLen,
423 &sm->eapRespDataLen);
424 wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
425 "methodState=%s decision=%s",
426 ret.ignore ? "TRUE" : "FALSE",
427 eap_sm_method_state_txt(ret.methodState),
428 eap_sm_decision_txt(ret.decision));
430 sm->ignore = ret.ignore;
433 sm->methodState = ret.methodState;
434 sm->decision = ret.decision;
435 sm->allowNotifications = ret.allowNotifications;
437 if (sm->m->isKeyAvailable && sm->m->getKey &&
438 sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
439 free(sm->eapKeyData);
440 sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
447 * This state signals the lower layer that a response packet is ready to be
450 SM_STATE(EAP, SEND_RESPONSE)
452 SM_ENTRY(EAP, SEND_RESPONSE);
453 free(sm->lastRespData);
454 if (sm->eapRespData) {
456 memcpy(sm->last_md5, sm->req_md5, 16);
457 sm->lastId = sm->reqId;
458 sm->lastRespData = malloc(sm->eapRespDataLen);
459 if (sm->lastRespData) {
460 memcpy(sm->lastRespData, sm->eapRespData,
462 sm->lastRespDataLen = sm->eapRespDataLen;
464 eapol_set_bool(sm, EAPOL_eapResp, TRUE);
466 sm->lastRespData = NULL;
467 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
468 eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
473 * This state signals the lower layer that the request was discarded, and no
474 * response packet will be sent at this time.
476 SM_STATE(EAP, DISCARD)
478 SM_ENTRY(EAP, DISCARD);
479 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
480 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
485 * Handles requests for Identity method and builds a response.
487 SM_STATE(EAP, IDENTITY)
489 const u8 *eapReqData;
490 size_t eapReqDataLen;
492 SM_ENTRY(EAP, IDENTITY);
493 eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
494 eap_sm_processIdentity(sm, eapReqData, eapReqDataLen);
495 free(sm->eapRespData);
496 sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId,
497 &sm->eapRespDataLen, 0);
502 * Handles requests for Notification method and builds a response.
504 SM_STATE(EAP, NOTIFICATION)
506 const u8 *eapReqData;
507 size_t eapReqDataLen;
509 SM_ENTRY(EAP, NOTIFICATION);
510 eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
511 eap_sm_processNotify(sm, eapReqData, eapReqDataLen);
512 free(sm->eapRespData);
513 sm->eapRespData = eap_sm_buildNotify(sm, sm->reqId,
514 &sm->eapRespDataLen);
519 * This state retransmits the previous response packet.
521 SM_STATE(EAP, RETRANSMIT)
523 SM_ENTRY(EAP, RETRANSMIT);
524 free(sm->eapRespData);
525 if (sm->lastRespData) {
526 sm->eapRespData = malloc(sm->lastRespDataLen);
527 if (sm->eapRespData) {
528 memcpy(sm->eapRespData, sm->lastRespData,
529 sm->lastRespDataLen);
530 sm->eapRespDataLen = sm->lastRespDataLen;
533 sm->eapRespData = NULL;
538 * This state is entered in case of a successful completion of authentication
539 * and state machine waits here until port is disabled or EAP authentication is
542 SM_STATE(EAP, SUCCESS)
544 SM_ENTRY(EAP, SUCCESS);
545 if (sm->eapKeyData != NULL)
546 sm->eapKeyAvailable = TRUE;
547 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
550 * RFC 4137 does not clear eapReq here, but this seems to be required
551 * to avoid processing the same request twice when state machine is
554 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
557 * RFC 4137 does not set eapNoResp here, but this seems to be required
558 * to get EAPOL Supplicant backend state machine into SUCCESS state. In
559 * addition, either eapResp or eapNoResp is required to be set after
560 * processing the received EAP frame.
562 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
564 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
565 "EAP authentication completed successfully");
570 * This state is entered in case of a failure and state machine waits here
571 * until port is disabled or EAP authentication is restarted.
573 SM_STATE(EAP, FAILURE)
575 SM_ENTRY(EAP, FAILURE);
576 eapol_set_bool(sm, EAPOL_eapFail, TRUE);
579 * RFC 4137 does not clear eapReq here, but this seems to be required
580 * to avoid processing the same request twice when state machine is
583 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
586 * RFC 4137 does not set eapNoResp here. However, either eapResp or
587 * eapNoResp is required to be set after processing the received EAP
590 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
592 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
593 "EAP authentication failed");
597 static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
600 * At least Microsoft IAS and Meetinghouse Aegis seem to be sending
601 * EAP-Success/Failure with lastId + 1 even though RFC 3748 and
602 * RFC 4137 require that reqId == lastId. In addition, it looks like
603 * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
605 * Accept this kind of Id if EAP workarounds are enabled. These are
606 * unauthenticated plaintext messages, so this should have minimal
607 * security implications (bit easier to fake EAP-Success/Failure).
609 if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
610 reqId == ((lastId + 2) & 0xff))) {
611 wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
612 "identifier field in EAP Success: "
613 "reqId=%d lastId=%d (these are supposed to be "
614 "same)", reqId, lastId);
617 wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
618 "lastId=%d", reqId, lastId);
624 * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
630 if (eapol_get_bool(sm, EAPOL_eapRestart) &&
631 eapol_get_bool(sm, EAPOL_portEnabled))
632 SM_ENTER_GLOBAL(EAP, INITIALIZE);
633 else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
634 SM_ENTER_GLOBAL(EAP, DISABLED);
635 else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
636 /* RFC 4137 does not place any limit on number of EAP messages
637 * in an authentication session. However, some error cases have
638 * ended up in a state were EAP messages were sent between the
639 * peer and server in a loop (e.g., TLS ACK frame in both
640 * direction). Since this is quite undesired outcome, limit the
641 * total number of EAP round-trips and abort authentication if
642 * this limit is exceeded.
644 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
645 wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
646 "authentication rounds - abort",
647 EAP_MAX_AUTH_ROUNDS);
649 SM_ENTER_GLOBAL(EAP, FAILURE);
651 } else switch (sm->EAP_state) {
656 if (eapol_get_bool(sm, EAPOL_portEnabled) &&
658 SM_ENTER(EAP, INITIALIZE);
662 * The first three transitions are from RFC 4137. The last two
663 * are local additions to handle special cases with LEAP and
664 * PEAP server not sending EAP-Success in some cases.
666 if (eapol_get_bool(sm, EAPOL_eapReq))
667 SM_ENTER(EAP, RECEIVED);
668 else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
669 sm->decision != DECISION_FAIL) ||
670 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
671 sm->decision == DECISION_UNCOND_SUCC))
672 SM_ENTER(EAP, SUCCESS);
673 else if (eapol_get_bool(sm, EAPOL_altReject) ||
674 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
675 sm->decision != DECISION_UNCOND_SUCC) ||
676 (eapol_get_bool(sm, EAPOL_altAccept) &&
677 sm->methodState != METHOD_CONT &&
678 sm->decision == DECISION_FAIL))
679 SM_ENTER(EAP, FAILURE);
680 else if (sm->selectedMethod == EAP_TYPE_LEAP &&
681 sm->leap_done && sm->decision != DECISION_FAIL &&
682 sm->methodState == METHOD_DONE)
683 SM_ENTER(EAP, SUCCESS);
684 else if (sm->selectedMethod == EAP_TYPE_PEAP &&
685 sm->peap_done && sm->decision != DECISION_FAIL &&
686 sm->methodState == METHOD_DONE)
687 SM_ENTER(EAP, SUCCESS);
690 duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
691 if (sm->workaround && duplicate &&
692 memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
694 * RFC 4137 uses (reqId == lastId) as the only
695 * verification for duplicate EAP requests. However,
696 * this misses cases where the AS is incorrectly using
697 * the same id again; and unfortunately, such
698 * implementations exist. Use MD5 hash as an extra
699 * verification for the packets being duplicate to
700 * workaround these issues.
702 wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again,"
703 " but EAP packets were not identical");
704 wpa_printf(MSG_DEBUG, "EAP: workaround - assume this "
705 "is not a duplicate packet");
710 * Two special cases below for LEAP are local additions to work
711 * around odd LEAP behavior (EAP-Success in the middle of
712 * authentication and then swapped roles). Other transitions
713 * are based on RFC 4137.
715 if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
716 (sm->reqId == sm->lastId ||
717 eap_success_workaround(sm, sm->reqId, sm->lastId)))
718 SM_ENTER(EAP, SUCCESS);
719 else if (sm->methodState != METHOD_CONT &&
721 sm->decision != DECISION_UNCOND_SUCC) ||
722 (sm->rxSuccess && sm->decision == DECISION_FAIL &&
723 (sm->selectedMethod != EAP_TYPE_LEAP ||
724 sm->methodState != METHOD_MAY_CONT))) &&
725 (sm->reqId == sm->lastId ||
726 eap_success_workaround(sm, sm->reqId, sm->lastId)))
727 SM_ENTER(EAP, FAILURE);
728 else if (sm->rxReq && duplicate)
729 SM_ENTER(EAP, RETRANSMIT);
730 else if (sm->rxReq && !duplicate &&
731 sm->reqMethod == EAP_TYPE_NOTIFICATION &&
732 sm->allowNotifications)
733 SM_ENTER(EAP, NOTIFICATION);
734 else if (sm->rxReq && !duplicate &&
735 sm->selectedMethod == EAP_TYPE_NONE &&
736 sm->reqMethod == EAP_TYPE_IDENTITY)
737 SM_ENTER(EAP, IDENTITY);
738 else if (sm->rxReq && !duplicate &&
739 sm->selectedMethod == EAP_TYPE_NONE &&
740 sm->reqMethod != EAP_TYPE_IDENTITY &&
741 sm->reqMethod != EAP_TYPE_NOTIFICATION)
742 SM_ENTER(EAP, GET_METHOD);
743 else if (sm->rxReq && !duplicate &&
744 sm->reqMethod == sm->selectedMethod &&
745 sm->methodState != METHOD_DONE)
746 SM_ENTER(EAP, METHOD);
747 else if (sm->selectedMethod == EAP_TYPE_LEAP &&
748 (sm->rxSuccess || sm->rxResp))
749 SM_ENTER(EAP, METHOD);
751 SM_ENTER(EAP, DISCARD);
754 if (sm->selectedMethod == sm->reqMethod)
755 SM_ENTER(EAP, METHOD);
757 SM_ENTER(EAP, SEND_RESPONSE);
761 SM_ENTER(EAP, DISCARD);
763 SM_ENTER(EAP, SEND_RESPONSE);
765 case EAP_SEND_RESPONSE:
772 SM_ENTER(EAP, SEND_RESPONSE);
774 case EAP_NOTIFICATION:
775 SM_ENTER(EAP, SEND_RESPONSE);
778 SM_ENTER(EAP, SEND_RESPONSE);
788 static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method)
790 struct wpa_ssid *config = eap_get_config(sm);
793 if (!wpa_config_allowed_eap_method(config, method))
795 for (i = 0; i < NUM_EAP_METHODS; i++) {
796 if (eap_methods[i]->method == method)
803 static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
805 struct wpa_ssid *config = eap_get_config(sm);
806 struct eap_hdr *resp;
810 wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %d not "
811 "allowed)", sm->reqMethod);
812 *len = sizeof(struct eap_hdr) + 1;
813 resp = malloc(*len + NUM_EAP_METHODS);
817 resp->code = EAP_CODE_RESPONSE;
818 resp->identifier = id;
819 pos = (u8 *) (resp + 1);
820 *pos++ = EAP_TYPE_NAK;
822 for (i = 0; i < NUM_EAP_METHODS; i++) {
823 if (eap_methods[i]->method != sm->reqMethod &&
824 wpa_config_allowed_eap_method(config,
825 eap_methods[i]->method)) {
826 *pos++ = eap_methods[i]->method;
832 *pos = EAP_TYPE_NONE;
835 wpa_hexdump(MSG_DEBUG, "EAP: allowed methods",
836 ((u8 *) (resp + 1)) + 1, found);
838 resp->length = host_to_be16(*len);
844 static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req,
847 const struct eap_hdr *hdr = (const struct eap_hdr *) req;
848 const u8 *pos = (const u8 *) (hdr + 1);
851 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
852 "EAP authentication started");
855 * RFC 3748 - 5.1: Identity
856 * Data field may contain a displayable message in UTF-8. If this
857 * includes NUL-character, only the data before that should be
858 * displayed. Some EAP implementasitons may piggy-back additional
859 * options after the NUL.
861 /* TODO: could save displayable message so that it can be shown to the
862 * user in case of interaction is required */
863 wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
864 pos, be_to_host16(hdr->length) - 5);
868 static int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
873 u8 *pos = ssid->eap_methods;
875 imsi_len = sizeof(imsi);
876 if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
877 wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
881 wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
883 while (pos && *pos != EAP_TYPE_NONE) {
884 if (*pos == EAP_TYPE_AKA) {
891 free(ssid->identity);
892 ssid->identity = malloc(1 + imsi_len);
893 if (ssid->identity == NULL) {
894 wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
895 "IMSI-based identity");
899 ssid->identity[0] = aka ? '0' : '1';
900 memcpy(ssid->identity + 1, imsi, imsi_len);
901 ssid->identity_len = 1 + imsi_len;
906 static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
908 if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
910 * Make sure the same PIN is not tried again in order to avoid
916 wpa_printf(MSG_WARNING, "PIN validation failed");
917 eap_sm_request_pin(sm, ssid);
921 return eap_sm_imsi_identity(sm, ssid);
926 * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
927 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
928 * @id: EAP identifier for the packet
929 * @len: Pointer to a variable that will be set to the length of the response
930 * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
931 * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
934 * This function allocates and builds an EAP-Identity/Response packet for the
935 * current network. The caller is responsible for freeing the returned data.
937 u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
940 struct wpa_ssid *config = eap_get_config(sm);
941 struct eap_hdr *resp;
946 if (config == NULL) {
947 wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
948 "was not available");
952 if (sm->m && sm->m->get_identity &&
953 (identity = sm->m->get_identity(sm, sm->eap_method_priv,
954 &identity_len)) != NULL) {
955 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
956 "identity", identity, identity_len);
957 } else if (!encrypted && config->anonymous_identity) {
958 identity = config->anonymous_identity;
959 identity_len = config->anonymous_identity_len;
960 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
961 identity, identity_len);
963 identity = config->identity;
964 identity_len = config->identity_len;
965 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
966 identity, identity_len);
969 if (identity == NULL) {
970 wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
971 "configuration was not available");
973 if (eap_sm_get_scard_identity(sm, config) < 0)
975 identity = config->identity;
976 identity_len = config->identity_len;
977 wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
978 "IMSI", identity, identity_len);
980 eap_sm_request_identity(sm, config);
985 *len = sizeof(struct eap_hdr) + 1 + identity_len;
990 resp->code = EAP_CODE_RESPONSE;
991 resp->identifier = id;
992 resp->length = host_to_be16(*len);
993 pos = (u8 *) (resp + 1);
994 *pos++ = EAP_TYPE_IDENTITY;
995 memcpy(pos, identity, identity_len);
1001 static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len)
1003 const struct eap_hdr *hdr = (const struct eap_hdr *) req;
1009 pos = (const u8 *) (hdr + 1);
1012 msg_len = be_to_host16(hdr->length);
1016 wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
1019 msg = malloc(msg_len + 1);
1022 for (i = 0; i < msg_len; i++)
1023 msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
1024 msg[msg_len] = '\0';
1025 wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
1026 WPA_EVENT_EAP_NOTIFICATION, msg);
1031 static u8 * eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len)
1033 struct eap_hdr *resp;
1036 wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
1037 *len = sizeof(struct eap_hdr) + 1;
1038 resp = malloc(*len);
1042 resp->code = EAP_CODE_RESPONSE;
1043 resp->identifier = id;
1044 resp->length = host_to_be16(*len);
1045 pos = (u8 *) (resp + 1);
1046 *pos = EAP_TYPE_NOTIFICATION;
1052 static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len)
1054 const struct eap_hdr *hdr;
1057 sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
1059 sm->reqMethod = EAP_TYPE_NONE;
1061 if (req == NULL || len < sizeof(*hdr))
1064 hdr = (const struct eap_hdr *) req;
1065 plen = be_to_host16(hdr->length);
1067 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
1068 "(len=%lu plen=%lu)",
1069 (unsigned long) len, (unsigned long) plen);
1073 sm->reqId = hdr->identifier;
1075 if (sm->workaround) {
1076 md5_vector(1, (const u8 **) &req, &len, sm->req_md5);
1079 switch (hdr->code) {
1080 case EAP_CODE_REQUEST:
1082 if (plen > sizeof(*hdr))
1083 sm->reqMethod = *((u8 *) (hdr + 1));
1084 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request method=%d "
1085 "id=%d", sm->reqMethod, sm->reqId);
1087 case EAP_CODE_RESPONSE:
1088 if (sm->selectedMethod == EAP_TYPE_LEAP) {
1090 * LEAP differs from RFC 4137 by using reversed roles
1091 * for mutual authentication and because of this, we
1092 * need to accept EAP-Response frames if LEAP is used.
1095 if (plen > sizeof(*hdr))
1096 sm->reqMethod = *((u8 *) (hdr + 1));
1097 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
1098 "LEAP method=%d id=%d",
1099 sm->reqMethod, sm->reqId);
1102 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
1104 case EAP_CODE_SUCCESS:
1105 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
1106 sm->rxSuccess = TRUE;
1108 case EAP_CODE_FAILURE:
1109 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
1110 sm->rxFailure = TRUE;
1113 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
1114 "code %d", hdr->code);
1121 * eap_sm_init - Allocate and initialize EAP state machine
1122 * @eapol_ctx: Context data to be used with eapol_cb calls
1123 * @eapol_cb: Pointer to EAPOL callback functions
1124 * @msg_ctx: Context data for wpa_msg() calls
1125 * @conf: EAP configuration
1126 * Returns: Pointer to the allocated EAP state machine or %NULL on failure
1128 * This function allocates and initializes an EAP state machine. In addition,
1129 * this initializes TLS library for the new EAP state machine. eapol_cb pointer
1130 * will be in use until eap_sm_deinit() is used to deinitialize this EAP state
1131 * machine. Consequently, the caller must make sure that this data structure
1132 * remains alive while the EAP state machine is active.
1134 struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
1135 void *msg_ctx, struct eap_config *conf)
1138 struct tls_config tlsconf;
1140 sm = malloc(sizeof(*sm));
1143 memset(sm, 0, sizeof(*sm));
1144 sm->eapol_ctx = eapol_ctx;
1145 sm->eapol_cb = eapol_cb;
1146 sm->msg_ctx = msg_ctx;
1147 sm->ClientTimeout = 60;
1149 memset(&tlsconf, 0, sizeof(tlsconf));
1150 tlsconf.opensc_engine_path = conf->opensc_engine_path;
1151 tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
1152 tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
1153 sm->ssl_ctx = tls_init(&tlsconf);
1154 if (sm->ssl_ctx == NULL) {
1155 wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
1166 * eap_sm_deinit - Deinitialize and free an EAP state machine
1167 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1169 * This function deinitializes EAP state machine and frees all allocated
1172 void eap_sm_deinit(struct eap_sm *sm)
1176 eap_deinit_prev_method(sm, "EAP deinit");
1178 tls_deinit(sm->ssl_ctx);
1184 * eap_sm_step - Step EAP state machine
1185 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1186 * Returns: 1 if EAP state was changed or 0 if not
1188 * This function advances EAP state machine to a new state to match with the
1189 * current variables. This should be called whenever variables used by the EAP
1190 * state machine have changed.
1192 int eap_sm_step(struct eap_sm *sm)
1196 sm->changed = FALSE;
1200 } while (sm->changed);
1206 * eap_sm_abort - Abort EAP authentication
1207 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1209 * Release system resources that have been allocated for the authentication
1210 * session without fully deinitializing the EAP state machine.
1212 void eap_sm_abort(struct eap_sm *sm)
1214 free(sm->lastRespData);
1215 sm->lastRespData = NULL;
1216 free(sm->eapRespData);
1217 sm->eapRespData = NULL;
1218 free(sm->eapKeyData);
1219 sm->eapKeyData = NULL;
1223 static const char * eap_sm_state_txt(int state)
1226 case EAP_INITIALIZE:
1227 return "INITIALIZE";
1234 case EAP_GET_METHOD:
1235 return "GET_METHOD";
1238 case EAP_SEND_RESPONSE:
1239 return "SEND_RESPONSE";
1244 case EAP_NOTIFICATION:
1245 return "NOTIFICATION";
1246 case EAP_RETRANSMIT:
1247 return "RETRANSMIT";
1258 static const char * eap_sm_method_state_txt(EapMethodState state)
1267 case METHOD_MAY_CONT:
1277 static const char * eap_sm_decision_txt(EapDecision decision)
1282 case DECISION_COND_SUCC:
1284 case DECISION_UNCOND_SUCC:
1285 return "UNCOND_SUCC";
1293 * eap_sm_get_status - Get EAP state machine status
1294 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1295 * @buf: Buffer for status information
1296 * @buflen: Maximum buffer length
1297 * @verbose: Whether to include verbose status information
1298 * Returns: Number of bytes written to buf.
1300 * Query EAP state machine for status information. This function fills in a
1301 * text area with current status information from the EAPOL state machine. If
1302 * the buffer (buf) is not large enough, status information will be truncated
1303 * to fit the buffer.
1305 int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
1312 len = snprintf(buf, buflen,
1314 eap_sm_state_txt(sm->EAP_state));
1316 if (sm->selectedMethod != EAP_TYPE_NONE) {
1321 const struct eap_method *m =
1322 eap_sm_get_eap_methods(sm->selectedMethod);
1328 len += snprintf(buf + len, buflen - len,
1329 "selectedMethod=%d (EAP-%s)\n",
1330 sm->selectedMethod, name);
1332 if (sm->m && sm->m->get_status) {
1333 len += sm->m->get_status(sm, sm->eap_method_priv,
1334 buf + len, buflen - len,
1340 len += snprintf(buf + len, buflen - len,
1344 "ClientTimeout=%d\n",
1346 eap_sm_method_state_txt(sm->methodState),
1347 eap_sm_decision_txt(sm->decision),
1356 TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
1358 } eap_ctrl_req_type;
1360 static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config,
1361 eap_ctrl_req_type type, const char *msg,
1370 if (config == NULL || sm == NULL)
1377 config->pending_req_identity++;
1382 config->pending_req_password++;
1384 case TYPE_NEW_PASSWORD:
1385 field = "NEW_PASSWORD";
1386 txt = "New Password";
1387 config->pending_req_new_password++;
1392 config->pending_req_pin++;
1397 tmp = malloc(msglen + 3);
1401 memcpy(tmp + 1, msg, msglen);
1402 tmp[msglen + 1] = ']';
1403 tmp[msglen + 2] = '\0';
1405 free(config->pending_req_otp);
1406 config->pending_req_otp = tmp;
1407 config->pending_req_otp_len = msglen + 3;
1409 if (config->pending_req_otp == NULL)
1411 txt = config->pending_req_otp;
1414 case TYPE_PASSPHRASE:
1415 field = "PASSPHRASE";
1416 txt = "Private key passphrase";
1417 config->pending_req_passphrase++;
1423 buflen = 100 + strlen(txt) + config->ssid_len;
1424 buf = malloc(buflen);
1427 len = snprintf(buf, buflen, WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
1428 field, config->id, txt);
1429 if (config->ssid && buflen > len + config->ssid_len) {
1430 memcpy(buf + len, config->ssid, config->ssid_len);
1431 len += config->ssid_len;
1434 wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf);
1440 * eap_sm_request_identity - Request identity from user (ctrl_iface)
1441 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1442 * @config: Pointer to the current network configuration
1444 * EAP methods can call this function to request identity information for the
1445 * current network. This is normally called when the identity is not included
1446 * in the network configuration. The request will be sent to monitor programs
1447 * through the control interface.
1449 void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config)
1451 eap_sm_request(sm, config, TYPE_IDENTITY, NULL, 0);
1456 * eap_sm_request_password - Request password from user (ctrl_iface)
1457 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1458 * @config: Pointer to the current network configuration
1460 * EAP methods can call this function to request password information for the
1461 * current network. This is normally called when the password is not included
1462 * in the network configuration. The request will be sent to monitor programs
1463 * through the control interface.
1465 void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config)
1467 eap_sm_request(sm, config, TYPE_PASSWORD, NULL, 0);
1472 * eap_sm_request_new_password - Request new password from user (ctrl_iface)
1473 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1474 * @config: Pointer to the current network configuration
1476 * EAP methods can call this function to request new password information for
1477 * the current network. This is normally called when the EAP method indicates
1478 * that the current password has expired and password change is required. The
1479 * request will be sent to monitor programs through the control interface.
1481 void eap_sm_request_new_password(struct eap_sm *sm, struct wpa_ssid *config)
1483 eap_sm_request(sm, config, TYPE_NEW_PASSWORD, NULL, 0);
1488 * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
1489 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1490 * @config: Pointer to the current network configuration
1492 * EAP methods can call this function to request SIM or smart card PIN
1493 * information for the current network. This is normally called when the PIN is
1494 * not included in the network configuration. The request will be sent to
1495 * monitor programs through the control interface.
1497 void eap_sm_request_pin(struct eap_sm *sm, struct wpa_ssid *config)
1499 eap_sm_request(sm, config, TYPE_PIN, NULL, 0);
1504 * eap_sm_request_otp - Request one time password from user (ctrl_iface)
1505 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1506 * @config: Pointer to the current network configuration
1507 * @msg: Message to be displayed to the user when asking for OTP
1508 * @msg_len: Length of the user displayable message
1510 * EAP methods can call this function to request open time password (OTP) for
1511 * the current network. The request will be sent to monitor programs through
1512 * the control interface.
1514 void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config,
1515 const char *msg, size_t msg_len)
1517 eap_sm_request(sm, config, TYPE_OTP, msg, msg_len);
1522 * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
1523 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1524 * @config: Pointer to the current network configuration
1526 * EAP methods can call this function to request passphrase for a private key
1527 * for the current network. This is normally called when the passphrase is not
1528 * included in the network configuration. The request will be sent to monitor
1529 * programs through the control interface.
1531 void eap_sm_request_passphrase(struct eap_sm *sm, struct wpa_ssid *config)
1533 eap_sm_request(sm, config, TYPE_PASSPHRASE, NULL, 0);
1538 * eap_sm_notify_ctrl_attached - Notification of attached monitor
1539 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1541 * Notify EAP state machines that a monitor was attached to the control
1542 * interface to trigger re-sending of pending requests for user input.
1544 void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
1546 struct wpa_ssid *config = eap_get_config(sm);
1551 /* Re-send any pending requests for user data since a new control
1552 * interface was added. This handles cases where the EAP authentication
1553 * starts immediately after system startup when the user interface is
1554 * not yet running. */
1555 if (config->pending_req_identity)
1556 eap_sm_request_identity(sm, config);
1557 if (config->pending_req_password)
1558 eap_sm_request_password(sm, config);
1559 if (config->pending_req_new_password)
1560 eap_sm_request_new_password(sm, config);
1561 if (config->pending_req_otp)
1562 eap_sm_request_otp(sm, config, NULL, 0);
1563 if (config->pending_req_pin)
1564 eap_sm_request_pin(sm, config);
1565 if (config->pending_req_passphrase)
1566 eap_sm_request_passphrase(sm, config);
1571 * eap_get_type - Get EAP type for the given EAP method name
1572 * @name: EAP method name, e.g., TLS
1573 * Returns: EAP method type or %EAP_TYPE_NONE if not found
1575 * This function maps EAP type names into EAP type numbers based on the list of
1576 * EAP methods included in the build.
1578 u8 eap_get_type(const char *name)
1581 for (i = 0; i < NUM_EAP_METHODS; i++) {
1582 if (strcmp(eap_methods[i]->name, name) == 0)
1583 return eap_methods[i]->method;
1585 return EAP_TYPE_NONE;
1590 * eap_get_name - Get EAP method name for the given EAP type
1591 * @type: EAP method type
1592 * Returns: EAP method name, e.g., TLS, or %NULL if not found
1594 * This function maps EAP type numbers into EAP type names based on the list of
1595 * EAP methods included in the build.
1597 const char * eap_get_name(EapType type)
1600 for (i = 0; i < NUM_EAP_METHODS; i++) {
1601 if (eap_methods[i]->method == type)
1602 return eap_methods[i]->name;
1609 * eap_get_names - Get space separated list of names for supported EAP methods
1610 * @buf: Buffer for names
1611 * @buflen: Buffer length
1612 * Returns: Number of characters written into buf (not including nul
1615 size_t eap_get_names(char *buf, size_t buflen)
1623 for (i = 0; i < NUM_EAP_METHODS; i++) {
1624 pos += snprintf(pos, end - pos, "%s%s",
1625 i == 0 ? "" : " ", eap_methods[i]->name);
1632 static int eap_allowed_phase2_type(int type)
1634 return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
1635 type != EAP_TYPE_FAST;
1640 * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
1641 * @name: EAP method name, e.g., MD5
1642 * Returns: EAP method type or %EAP_TYPE_NONE if not found
1644 * This function maps EAP type names into EAP type numbers that are allowed for
1645 * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
1646 * EAP-PEAP, EAP-TTLS, and EAP-FAST.
1648 u8 eap_get_phase2_type(const char *name)
1650 u8 type = eap_get_type(name);
1651 if (eap_allowed_phase2_type(type))
1653 return EAP_TYPE_NONE;
1658 * eap_get_phase2_types - Get list of allowed EAP phase 2 types
1659 * @config: Pointer to a network configuration
1660 * @count: Pointer to a variable to be filled with number of returned EAP types
1661 * Returns: Pointer to allocated type list or %NULL on failure
1663 * This function generates an array of allowed EAP phase 2 (tunneled) types for
1664 * the given network configuration.
1666 u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count)
1672 buf = malloc(NUM_EAP_METHODS);
1676 for (i = 0; i < NUM_EAP_METHODS; i++) {
1677 method = eap_methods[i]->method;
1678 if (eap_allowed_phase2_type(method)) {
1679 if (method == EAP_TYPE_TLS && config &&
1680 config->private_key2 == NULL)
1682 buf[*count] = method;
1692 * eap_set_fast_reauth - Update fast_reauth setting
1693 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1694 * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
1696 void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
1698 sm->fast_reauth = enabled;
1703 * eap_set_workaround - Update EAP workarounds setting
1704 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1705 * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
1707 void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
1709 sm->workaround = workaround;
1714 * eap_get_config - Get current network configuration
1715 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1716 * Returns: Pointer to the current network configuration or %NULL if not found
1718 struct wpa_ssid * eap_get_config(struct eap_sm *sm)
1720 return sm->eapol_cb->get_config(sm->eapol_ctx);
1725 * eap_key_available - Get key availability (eapKeyAvailable variable)
1726 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1727 * Returns: 1 if EAP keying material is available, 0 if not
1729 int eap_key_available(struct eap_sm *sm)
1731 return sm ? sm->eapKeyAvailable : 0;
1736 * eap_notify_success - Notify EAP state machine about external success trigger
1737 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1739 * This function is called when external event, e.g., successful completion of
1740 * WPA-PSK key handshake, is indicating that EAP state machine should move to
1741 * success state. This is mainly used with security modes that do not use EAP
1742 * state machine (e.g., WPA-PSK).
1744 void eap_notify_success(struct eap_sm *sm)
1747 sm->decision = DECISION_COND_SUCC;
1748 sm->EAP_state = EAP_SUCCESS;
1754 * eap_notify_lower_layer_success - Notification of lower layer success
1755 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1757 * Notify EAP state machines that a lower layer has detected a successful
1758 * authentication. This is used to recover from dropped EAP-Success messages.
1760 void eap_notify_lower_layer_success(struct eap_sm *sm)
1765 if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
1766 sm->decision == DECISION_FAIL ||
1767 (sm->methodState != METHOD_MAY_CONT &&
1768 sm->methodState != METHOD_DONE))
1771 if (sm->eapKeyData != NULL)
1772 sm->eapKeyAvailable = TRUE;
1773 eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
1774 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
1775 "EAP authentication completed successfully (based on lower "
1781 * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
1782 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1783 * @len: Pointer to variable that will be set to number of bytes in the key
1784 * Returns: Pointer to the EAP keying data or %NULL on failure
1786 * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
1787 * key is available only after a successful authentication. EAP state machine
1788 * continues to manage the key data and the caller must not change or free the
1791 const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
1793 if (sm == NULL || sm->eapKeyData == NULL) {
1798 *len = sm->eapKeyDataLen;
1799 return sm->eapKeyData;
1804 * eap_get_eapKeyData - Get EAP response data
1805 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1806 * @len: Pointer to variable that will be set to the length of the response
1807 * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
1809 * Fetch EAP response (eapRespData) from the EAP state machine. This data is
1810 * available when EAP state machine has processed an incoming EAP request. The
1811 * EAP state machine does not maintain a reference to the response after this
1812 * function is called and the caller is responsible for freeing the data.
1814 u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len)
1818 if (sm == NULL || sm->eapRespData == NULL) {
1823 resp = sm->eapRespData;
1824 *len = sm->eapRespDataLen;
1825 sm->eapRespData = NULL;
1826 sm->eapRespDataLen = 0;
1833 * eap_sm_register_scard_ctx - Notification of smart card context
1834 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1835 * @ctx: Context data for smart card operations
1837 * Notify EAP state machines of context data for smart card operations. This
1838 * context data will be used as a parameter for scard_*() functions.
1840 void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
1843 sm->scard_ctx = ctx;
1848 * eap_hdr_validate - Validate EAP header
1849 * @eap_type: Expected EAP type number
1850 * @msg: EAP frame (starting with EAP header)
1851 * @msglen: Length of msg
1852 * @plen: Pointer to variable to contain the returned payload length
1853 * Returns: Pointer to EAP payload (after type field), or %NULL on failure
1855 * This is a helper function for EAP method implementations. This is usually
1856 * called in the beginning of struct eap_method::process() function to verify
1857 * that the received EAP request packet has a valid header.
1859 const u8 * eap_hdr_validate(EapType eap_type, const u8 *msg, size_t msglen,
1862 const struct eap_hdr *hdr;
1866 hdr = (const struct eap_hdr *) msg;
1867 pos = (const u8 *) (hdr + 1);
1868 if (msglen < sizeof(*hdr) + 1 || *pos != eap_type) {
1869 wpa_printf(MSG_INFO, "EAP: Invalid frame type");
1872 len = be_to_host16(hdr->length);
1873 if (len < sizeof(*hdr) + 1 || len > msglen) {
1874 wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
1877 *plen = len - sizeof(*hdr) - 1;
1883 * eap_set_config_blob - Set or add a named configuration blob
1884 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1885 * @blob: New value for the blob
1887 * Adds a new configuration blob or replaces the current value of an existing
1890 void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
1892 sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
1897 * eap_get_config_blob - Get a named configuration blob
1898 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1899 * @name: Name of the blob
1900 * Returns: Pointer to blob data or %NULL if not found
1902 const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
1905 return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
1910 * eap_set_force_disabled - Set force_disabled flag
1911 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
1912 * @disabled: 1 = EAP disabled, 0 = EAP enabled
1914 * This function is used to force EAP state machine to be disabled when it is
1915 * not in use (e.g., with WPA-PSK or plaintext connections).
1917 void eap_set_force_disabled(struct eap_sm *sm, int disabled)
1919 sm->force_disabled = disabled;