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
;