2
* EAP peer state machines (RFC 4137)
3
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.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).
28
#include "config_ssid.h"
31
#include "pcsc_funcs.h"
33
#include "state_machine.h"
35
#define STATE_MACHINE_DATA struct eap_sm
36
#define STATE_MACHINE_DEBUG_PREFIX "EAP"
38
#define EAP_MAX_AUTH_ROUNDS 50
41
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
43
static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len);
44
static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req);
45
static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req);
46
static u8 * eap_sm_buildNotify(int id, size_t *len);
47
static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len);
48
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
49
static const char * eap_sm_method_state_txt(EapMethodState state);
50
static const char * eap_sm_decision_txt(EapDecision decision);
51
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
55
static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
57
return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
61
static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
64
sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
68
static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
70
return sm->eapol_cb->get_int(sm->eapol_ctx, var);
74
static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
77
sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
81
static u8 * eapol_get_eapReqData(struct eap_sm *sm, size_t *len)
83
return sm->eapol_cb->get_eapReqData(sm->eapol_ctx, len);
87
static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
89
if (sm->m == NULL || sm->eap_method_priv == NULL)
92
wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
93
"(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
94
sm->m->deinit(sm, sm->eap_method_priv);
95
sm->eap_method_priv = NULL;
101
* This state initializes state machine variables when the machine is
102
* activated (portEnabled = TRUE). This is also used when re-starting
103
* authentication (eapRestart == TRUE).
105
SM_STATE(EAP, INITIALIZE)
107
SM_ENTRY(EAP, INITIALIZE);
108
if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
109
sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
110
wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
111
"fast reauthentication");
112
sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
114
eap_deinit_prev_method(sm, "INITIALIZE");
116
sm->selectedMethod = EAP_TYPE_NONE;
117
sm->methodState = METHOD_NONE;
118
sm->allowNotifications = TRUE;
119
sm->decision = DECISION_FAIL;
120
eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
121
eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
122
eapol_set_bool(sm, EAPOL_eapFail, FALSE);
123
os_free(sm->eapKeyData);
124
sm->eapKeyData = NULL;
125
sm->eapKeyAvailable = FALSE;
126
eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
127
sm->lastId = -1; /* new session - make sure this does not match with
128
* the first EAP-Packet */
130
* RFC 4137 does not reset eapResp and eapNoResp here. However, this
131
* seemed to be able to trigger cases where both were set and if EAPOL
132
* state machine uses eapNoResp first, it may end up not sending a real
133
* reply correctly. This occurred when the workaround in FAIL state set
134
* eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
137
eapol_set_bool(sm, EAPOL_eapResp, FALSE);
138
eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
144
* This state is reached whenever service from the lower layer is interrupted
145
* or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
146
* occurs when the port becomes enabled.
148
SM_STATE(EAP, DISABLED)
150
SM_ENTRY(EAP, DISABLED);
156
* The state machine spends most of its time here, waiting for something to
157
* happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
158
* SEND_RESPONSE states.
167
* This state is entered when an EAP packet is received (eapReq == TRUE) to
168
* parse the packet header.
170
SM_STATE(EAP, RECEIVED)
172
const u8 *eapReqData;
173
size_t eapReqDataLen;
175
SM_ENTRY(EAP, RECEIVED);
176
eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
177
/* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
178
eap_sm_parseEapReq(sm, eapReqData, eapReqDataLen);
184
* This state is entered when a request for a new type comes in. Either the
185
* correct method is started, or a Nak response is built.
187
SM_STATE(EAP, GET_METHOD)
192
SM_ENTRY(EAP, GET_METHOD);
194
if (sm->reqMethod == EAP_TYPE_EXPANDED)
195
method = sm->reqVendorMethod;
197
method = sm->reqMethod;
199
if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
200
wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
201
sm->reqVendor, method);
206
* RFC 4137 does not define specific operation for fast
207
* re-authentication (session resumption). The design here is to allow
208
* the previously used method data to be maintained for
209
* re-authentication if the method support session resumption.
210
* Otherwise, the previously used method data is freed and a new method
213
if (sm->fast_reauth &&
214
sm->m && sm->m->vendor == sm->reqVendor &&
215
sm->m->method == method &&
216
sm->m->has_reauth_data &&
217
sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
218
wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
219
" for fast re-authentication");
222
eap_deinit_prev_method(sm, "GET_METHOD");
226
sm->selectedMethod = sm->reqMethod;
228
sm->m = eap_peer_get_eap_method(sm->reqVendor, method);
230
wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
231
"vendor %d method %d",
232
sm->reqVendor, method);
236
wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
237
"vendor %u method %u (%s)",
238
sm->reqVendor, method, sm->m->name);
240
sm->eap_method_priv = sm->m->init_for_reauth(
241
sm, sm->eap_method_priv);
243
sm->eap_method_priv = sm->m->init(sm);
245
if (sm->eap_method_priv == NULL) {
246
struct wpa_ssid *config = eap_get_config(sm);
247
wpa_msg(sm->msg_ctx, MSG_INFO,
248
"EAP: Failed to initialize EAP method: vendor %u "
250
sm->reqVendor, method, sm->m->name);
252
sm->methodState = METHOD_NONE;
253
sm->selectedMethod = EAP_TYPE_NONE;
254
if (sm->reqMethod == EAP_TYPE_TLS && config &&
255
(config->pending_req_pin ||
256
config->pending_req_passphrase)) {
258
* Return without generating Nak in order to allow
259
* entering of PIN code or passphrase to retry the
260
* current EAP packet.
262
wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
263
"request - skip Nak");
270
sm->methodState = METHOD_INIT;
271
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
272
"EAP vendor %u method %u (%s) selected",
273
sm->reqVendor, method, sm->m->name);
277
os_free(sm->eapRespData);
278
sm->eapRespData = NULL;
279
sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen);
284
* The method processing happens here. The request from the authenticator is
285
* processed, and an appropriate response packet is built.
287
SM_STATE(EAP, METHOD)
290
size_t eapReqDataLen;
291
struct eap_method_ret ret;
293
SM_ENTRY(EAP, METHOD);
295
wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
299
eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
302
* Get ignore, methodState, decision, allowNotifications, and
303
* eapRespData. RFC 4137 uses three separate method procedure (check,
304
* process, and buildResp) in this state. These have been combined into
305
* a single function call to m->process() in order to optimize EAP
306
* method implementation interface a bit. These procedures are only
307
* used from within this METHOD state, so there is no need to keep
308
* these as separate C functions.
310
* The RFC 4137 procedures return values as follows:
311
* ignore = m.check(eapReqData)
312
* (methodState, decision, allowNotifications) = m.process(eapReqData)
313
* eapRespData = m.buildResp(reqId)
315
os_memset(&ret, 0, sizeof(ret));
316
ret.ignore = sm->ignore;
317
ret.methodState = sm->methodState;
318
ret.decision = sm->decision;
319
ret.allowNotifications = sm->allowNotifications;
320
os_free(sm->eapRespData);
321
sm->eapRespData = NULL;
322
sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
323
eapReqData, eapReqDataLen,
324
&sm->eapRespDataLen);
325
wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
326
"methodState=%s decision=%s",
327
ret.ignore ? "TRUE" : "FALSE",
328
eap_sm_method_state_txt(ret.methodState),
329
eap_sm_decision_txt(ret.decision));
331
sm->ignore = ret.ignore;
334
sm->methodState = ret.methodState;
335
sm->decision = ret.decision;
336
sm->allowNotifications = ret.allowNotifications;
338
if (sm->m->isKeyAvailable && sm->m->getKey &&
339
sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
340
os_free(sm->eapKeyData);
341
sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
348
* This state signals the lower layer that a response packet is ready to be
351
SM_STATE(EAP, SEND_RESPONSE)
353
SM_ENTRY(EAP, SEND_RESPONSE);
354
os_free(sm->lastRespData);
355
if (sm->eapRespData) {
357
os_memcpy(sm->last_md5, sm->req_md5, 16);
358
sm->lastId = sm->reqId;
359
sm->lastRespData = os_malloc(sm->eapRespDataLen);
360
if (sm->lastRespData) {
361
os_memcpy(sm->lastRespData, sm->eapRespData,
363
sm->lastRespDataLen = sm->eapRespDataLen;
365
eapol_set_bool(sm, EAPOL_eapResp, TRUE);
367
sm->lastRespData = NULL;
368
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
369
eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
374
* This state signals the lower layer that the request was discarded, and no
375
* response packet will be sent at this time.
377
SM_STATE(EAP, DISCARD)
379
SM_ENTRY(EAP, DISCARD);
380
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
381
eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
386
* Handles requests for Identity method and builds a response.
388
SM_STATE(EAP, IDENTITY)
390
const u8 *eapReqData;
391
size_t eapReqDataLen;
393
SM_ENTRY(EAP, IDENTITY);
394
eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
395
eap_sm_processIdentity(sm, eapReqData);
396
os_free(sm->eapRespData);
397
sm->eapRespData = NULL;
398
sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId,
399
&sm->eapRespDataLen, 0);
404
* Handles requests for Notification method and builds a response.
406
SM_STATE(EAP, NOTIFICATION)
408
const u8 *eapReqData;
409
size_t eapReqDataLen;
411
SM_ENTRY(EAP, NOTIFICATION);
412
eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
413
eap_sm_processNotify(sm, eapReqData);
414
os_free(sm->eapRespData);
415
sm->eapRespData = NULL;
416
sm->eapRespData = eap_sm_buildNotify(sm->reqId, &sm->eapRespDataLen);
421
* This state retransmits the previous response packet.
423
SM_STATE(EAP, RETRANSMIT)
425
SM_ENTRY(EAP, RETRANSMIT);
426
os_free(sm->eapRespData);
427
if (sm->lastRespData) {
428
sm->eapRespData = os_malloc(sm->lastRespDataLen);
429
if (sm->eapRespData) {
430
os_memcpy(sm->eapRespData, sm->lastRespData,
431
sm->lastRespDataLen);
432
sm->eapRespDataLen = sm->lastRespDataLen;
435
sm->eapRespData = NULL;
440
* This state is entered in case of a successful completion of authentication
441
* and state machine waits here until port is disabled or EAP authentication is
444
SM_STATE(EAP, SUCCESS)
446
SM_ENTRY(EAP, SUCCESS);
447
if (sm->eapKeyData != NULL)
448
sm->eapKeyAvailable = TRUE;
449
eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
452
* RFC 4137 does not clear eapReq here, but this seems to be required
453
* to avoid processing the same request twice when state machine is
456
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
459
* RFC 4137 does not set eapNoResp here, but this seems to be required
460
* to get EAPOL Supplicant backend state machine into SUCCESS state. In
461
* addition, either eapResp or eapNoResp is required to be set after
462
* processing the received EAP frame.
464
eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
466
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
467
"EAP authentication completed successfully");
472
* This state is entered in case of a failure and state machine waits here
473
* until port is disabled or EAP authentication is restarted.
475
SM_STATE(EAP, FAILURE)
477
SM_ENTRY(EAP, FAILURE);
478
eapol_set_bool(sm, EAPOL_eapFail, TRUE);
481
* RFC 4137 does not clear eapReq here, but this seems to be required
482
* to avoid processing the same request twice when state machine is
485
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
488
* RFC 4137 does not set eapNoResp here. However, either eapResp or
489
* eapNoResp is required to be set after processing the received EAP
492
eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
494
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
495
"EAP authentication failed");
499
static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
502
* At least Microsoft IAS and Meetinghouse Aegis seem to be sending
503
* EAP-Success/Failure with lastId + 1 even though RFC 3748 and
504
* RFC 4137 require that reqId == lastId. In addition, it looks like
505
* Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
507
* Accept this kind of Id if EAP workarounds are enabled. These are
508
* unauthenticated plaintext messages, so this should have minimal
509
* security implications (bit easier to fake EAP-Success/Failure).
511
if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
512
reqId == ((lastId + 2) & 0xff))) {
513
wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
514
"identifier field in EAP Success: "
515
"reqId=%d lastId=%d (these are supposed to be "
516
"same)", reqId, lastId);
519
wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
520
"lastId=%d", reqId, lastId);
526
* RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
529
static void eap_peer_sm_step_idle(struct eap_sm *sm)
532
* The first three transitions are from RFC 4137. The last two are
533
* local additions to handle special cases with LEAP and PEAP server
534
* not sending EAP-Success in some cases.
536
if (eapol_get_bool(sm, EAPOL_eapReq))
537
SM_ENTER(EAP, RECEIVED);
538
else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
539
sm->decision != DECISION_FAIL) ||
540
(eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
541
sm->decision == DECISION_UNCOND_SUCC))
542
SM_ENTER(EAP, SUCCESS);
543
else if (eapol_get_bool(sm, EAPOL_altReject) ||
544
(eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
545
sm->decision != DECISION_UNCOND_SUCC) ||
546
(eapol_get_bool(sm, EAPOL_altAccept) &&
547
sm->methodState != METHOD_CONT &&
548
sm->decision == DECISION_FAIL))
549
SM_ENTER(EAP, FAILURE);
550
else if (sm->selectedMethod == EAP_TYPE_LEAP &&
551
sm->leap_done && sm->decision != DECISION_FAIL &&
552
sm->methodState == METHOD_DONE)
553
SM_ENTER(EAP, SUCCESS);
554
else if (sm->selectedMethod == EAP_TYPE_PEAP &&
555
sm->peap_done && sm->decision != DECISION_FAIL &&
556
sm->methodState == METHOD_DONE)
557
SM_ENTER(EAP, SUCCESS);
561
static int eap_peer_req_is_duplicate(struct eap_sm *sm)
565
duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
566
if (sm->workaround && duplicate &&
567
os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
569
* RFC 4137 uses (reqId == lastId) as the only verification for
570
* duplicate EAP requests. However, this misses cases where the
571
* AS is incorrectly using the same id again; and
572
* unfortunately, such implementations exist. Use MD5 hash as
573
* an extra verification for the packets being duplicate to
574
* workaround these issues.
576
wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but "
577
"EAP packets were not identical");
578
wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a "
587
static void eap_peer_sm_step_received(struct eap_sm *sm)
589
int duplicate = eap_peer_req_is_duplicate(sm);
592
* Two special cases below for LEAP are local additions to work around
593
* odd LEAP behavior (EAP-Success in the middle of authentication and
594
* then swapped roles). Other transitions are based on RFC 4137.
596
if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
597
(sm->reqId == sm->lastId ||
598
eap_success_workaround(sm, sm->reqId, sm->lastId)))
599
SM_ENTER(EAP, SUCCESS);
600
else if (sm->methodState != METHOD_CONT &&
602
sm->decision != DECISION_UNCOND_SUCC) ||
603
(sm->rxSuccess && sm->decision == DECISION_FAIL &&
604
(sm->selectedMethod != EAP_TYPE_LEAP ||
605
sm->methodState != METHOD_MAY_CONT))) &&
606
(sm->reqId == sm->lastId ||
607
eap_success_workaround(sm, sm->reqId, sm->lastId)))
608
SM_ENTER(EAP, FAILURE);
609
else if (sm->rxReq && duplicate)
610
SM_ENTER(EAP, RETRANSMIT);
611
else if (sm->rxReq && !duplicate &&
612
sm->reqMethod == EAP_TYPE_NOTIFICATION &&
613
sm->allowNotifications)
614
SM_ENTER(EAP, NOTIFICATION);
615
else if (sm->rxReq && !duplicate &&
616
sm->selectedMethod == EAP_TYPE_NONE &&
617
sm->reqMethod == EAP_TYPE_IDENTITY)
618
SM_ENTER(EAP, IDENTITY);
619
else if (sm->rxReq && !duplicate &&
620
sm->selectedMethod == EAP_TYPE_NONE &&
621
sm->reqMethod != EAP_TYPE_IDENTITY &&
622
sm->reqMethod != EAP_TYPE_NOTIFICATION)
623
SM_ENTER(EAP, GET_METHOD);
624
else if (sm->rxReq && !duplicate &&
625
sm->reqMethod == sm->selectedMethod &&
626
sm->methodState != METHOD_DONE)
627
SM_ENTER(EAP, METHOD);
628
else if (sm->selectedMethod == EAP_TYPE_LEAP &&
629
(sm->rxSuccess || sm->rxResp))
630
SM_ENTER(EAP, METHOD);
632
SM_ENTER(EAP, DISCARD);
636
static void eap_peer_sm_step_local(struct eap_sm *sm)
638
switch (sm->EAP_state) {
643
if (eapol_get_bool(sm, EAPOL_portEnabled) &&
645
SM_ENTER(EAP, INITIALIZE);
648
eap_peer_sm_step_idle(sm);
651
eap_peer_sm_step_received(sm);
654
if (sm->selectedMethod == sm->reqMethod)
655
SM_ENTER(EAP, METHOD);
657
SM_ENTER(EAP, SEND_RESPONSE);
661
SM_ENTER(EAP, DISCARD);
663
SM_ENTER(EAP, SEND_RESPONSE);
665
case EAP_SEND_RESPONSE:
672
SM_ENTER(EAP, SEND_RESPONSE);
674
case EAP_NOTIFICATION:
675
SM_ENTER(EAP, SEND_RESPONSE);
678
SM_ENTER(EAP, SEND_RESPONSE);
690
/* Global transitions */
691
if (eapol_get_bool(sm, EAPOL_eapRestart) &&
692
eapol_get_bool(sm, EAPOL_portEnabled))
693
SM_ENTER_GLOBAL(EAP, INITIALIZE);
694
else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
695
SM_ENTER_GLOBAL(EAP, DISABLED);
696
else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
697
/* RFC 4137 does not place any limit on number of EAP messages
698
* in an authentication session. However, some error cases have
699
* ended up in a state were EAP messages were sent between the
700
* peer and server in a loop (e.g., TLS ACK frame in both
701
* direction). Since this is quite undesired outcome, limit the
702
* total number of EAP round-trips and abort authentication if
703
* this limit is exceeded.
705
if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
706
wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
707
"authentication rounds - abort",
708
EAP_MAX_AUTH_ROUNDS);
710
SM_ENTER_GLOBAL(EAP, FAILURE);
713
/* Local transitions */
714
eap_peer_sm_step_local(sm);
719
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
722
struct wpa_ssid *config = eap_get_config(sm);
724
if (!wpa_config_allowed_eap_method(config, vendor, method)) {
725
wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
726
"vendor %u method %u", vendor, method);
729
if (eap_peer_get_eap_method(vendor, method))
731
wpa_printf(MSG_DEBUG, "EAP: not included in build: "
732
"vendor %u method %u", vendor, method);
737
static u8 * eap_sm_build_expanded_nak(struct eap_sm *sm, int id, size_t *len,
738
const struct eap_method *methods,
741
struct wpa_ssid *config = eap_get_config(sm);
742
struct eap_hdr *resp;
745
const struct eap_method *m;
747
wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
749
/* RFC 3748 - 5.3.2: Expanded Nak */
750
*len = sizeof(struct eap_hdr) + 8;
751
resp = os_malloc(*len + 8 * (count + 1));
755
resp->code = EAP_CODE_RESPONSE;
756
resp->identifier = id;
757
pos = (u8 *) (resp + 1);
758
*pos++ = EAP_TYPE_EXPANDED;
759
WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
761
WPA_PUT_BE32(pos, EAP_TYPE_NAK);
764
for (m = methods; m; m = m->next) {
765
if (sm->reqVendor == m->vendor &&
766
sm->reqVendorMethod == m->method)
767
continue; /* do not allow the current method again */
768
if (wpa_config_allowed_eap_method(config, m->vendor,
770
wpa_printf(MSG_DEBUG, "EAP: allowed type: "
771
"vendor=%u method=%u",
772
m->vendor, m->method);
773
*pos++ = EAP_TYPE_EXPANDED;
774
WPA_PUT_BE24(pos, m->vendor);
776
WPA_PUT_BE32(pos, m->method);
784
wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
785
*pos++ = EAP_TYPE_EXPANDED;
786
WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
788
WPA_PUT_BE32(pos, EAP_TYPE_NONE);
794
resp->length = host_to_be16(*len);
800
static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
802
struct wpa_ssid *config = eap_get_config(sm);
803
struct eap_hdr *resp;
805
int found = 0, expanded_found = 0;
807
const struct eap_method *methods, *m;
809
wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
810
"vendor=%u method=%u not allowed)", sm->reqMethod,
811
sm->reqVendor, sm->reqVendorMethod);
812
methods = eap_peer_get_methods(&count);
815
if (sm->reqMethod == EAP_TYPE_EXPANDED)
816
return eap_sm_build_expanded_nak(sm, id, len, methods, count);
818
/* RFC 3748 - 5.3.1: Legacy Nak */
819
*len = sizeof(struct eap_hdr) + 1;
820
resp = os_malloc(*len + count + 1);
824
resp->code = EAP_CODE_RESPONSE;
825
resp->identifier = id;
826
pos = (u8 *) (resp + 1);
827
*pos++ = EAP_TYPE_NAK;
829
for (m = methods; m; m = m->next) {
830
if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
831
continue; /* do not allow the current method again */
832
if (wpa_config_allowed_eap_method(config, m->vendor,
834
if (m->vendor != EAP_VENDOR_IETF) {
838
*pos++ = EAP_TYPE_EXPANDED;
846
*pos = EAP_TYPE_NONE;
849
wpa_hexdump(MSG_DEBUG, "EAP: allowed methods",
850
((u8 *) (resp + 1)) + 1, found);
852
resp->length = host_to_be16(*len);
858
static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req)
860
const struct eap_hdr *hdr = (const struct eap_hdr *) req;
861
const u8 *pos = (const u8 *) (hdr + 1);
864
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
865
"EAP authentication started");
868
* RFC 3748 - 5.1: Identity
869
* Data field may contain a displayable message in UTF-8. If this
870
* includes NUL-character, only the data before that should be
871
* displayed. Some EAP implementasitons may piggy-back additional
872
* options after the NUL.
874
/* TODO: could save displayable message so that it can be shown to the
875
* user in case of interaction is required */
876
wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
877
pos, be_to_host16(hdr->length) - 5);
882
static int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
887
struct eap_method_type *m = ssid->eap_methods;
890
imsi_len = sizeof(imsi);
891
if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
892
wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
896
wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
898
for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
899
m[i].method != EAP_TYPE_NONE); i++) {
900
if (m[i].vendor == EAP_VENDOR_IETF &&
901
m[i].method == EAP_TYPE_AKA) {
907
os_free(ssid->identity);
908
ssid->identity = os_malloc(1 + imsi_len);
909
if (ssid->identity == NULL) {
910
wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
911
"IMSI-based identity");
915
ssid->identity[0] = aka ? '0' : '1';
916
os_memcpy(ssid->identity + 1, imsi, imsi_len);
917
ssid->identity_len = 1 + imsi_len;
921
#endif /* PCSC_FUNCS */
924
static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
927
if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
929
* Make sure the same PIN is not tried again in order to avoid
935
wpa_printf(MSG_WARNING, "PIN validation failed");
936
eap_sm_request_pin(sm);
940
return eap_sm_imsi_identity(sm, ssid);
941
#else /* PCSC_FUNCS */
943
#endif /* PCSC_FUNCS */
948
* eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
949
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
950
* @id: EAP identifier for the packet
951
* @len: Pointer to a variable that will be set to the length of the response
952
* @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
953
* Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
956
* This function allocates and builds an EAP-Identity/Response packet for the
957
* current network. The caller is responsible for freeing the returned data.
959
u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
962
struct wpa_ssid *config = eap_get_config(sm);
963
struct eap_hdr *resp;
968
if (config == NULL) {
969
wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
970
"was not available");
974
if (sm->m && sm->m->get_identity &&
975
(identity = sm->m->get_identity(sm, sm->eap_method_priv,
976
&identity_len)) != NULL) {
977
wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
978
"identity", identity, identity_len);
979
} else if (!encrypted && config->anonymous_identity) {
980
identity = config->anonymous_identity;
981
identity_len = config->anonymous_identity_len;
982
wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
983
identity, identity_len);
985
identity = config->identity;
986
identity_len = config->identity_len;
987
wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
988
identity, identity_len);
991
if (identity == NULL) {
992
wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
993
"configuration was not available");
995
if (eap_sm_get_scard_identity(sm, config) < 0)
997
identity = config->identity;
998
identity_len = config->identity_len;
999
wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
1000
"IMSI", identity, identity_len);
1002
eap_sm_request_identity(sm);
1007
*len = sizeof(struct eap_hdr) + 1 + identity_len;
1008
resp = os_malloc(*len);
1012
resp->code = EAP_CODE_RESPONSE;
1013
resp->identifier = id;
1014
resp->length = host_to_be16(*len);
1015
pos = (u8 *) (resp + 1);
1016
*pos++ = EAP_TYPE_IDENTITY;
1017
os_memcpy(pos, identity, identity_len);
1023
static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req)
1025
const struct eap_hdr *hdr = (const struct eap_hdr *) req;
1030
pos = (const u8 *) (hdr + 1);
1033
msg_len = be_to_host16(hdr->length);
1037
wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
1040
msg = os_malloc(msg_len + 1);
1043
for (i = 0; i < msg_len; i++)
1044
msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
1045
msg[msg_len] = '\0';
1046
wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
1047
WPA_EVENT_EAP_NOTIFICATION, msg);
1052
static u8 * eap_sm_buildNotify(int id, size_t *len)
1054
struct eap_hdr *resp;
1057
wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
1058
*len = sizeof(struct eap_hdr) + 1;
1059
resp = os_malloc(*len);
1063
resp->code = EAP_CODE_RESPONSE;
1064
resp->identifier = id;
1065
resp->length = host_to_be16(*len);
1066
pos = (u8 *) (resp + 1);
1067
*pos = EAP_TYPE_NOTIFICATION;
1073
static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len)
1075
const struct eap_hdr *hdr;
1079
sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
1081
sm->reqMethod = EAP_TYPE_NONE;
1082
sm->reqVendor = EAP_VENDOR_IETF;
1083
sm->reqVendorMethod = EAP_TYPE_NONE;
1085
if (req == NULL || len < sizeof(*hdr))
1088
hdr = (const struct eap_hdr *) req;
1089
plen = be_to_host16(hdr->length);
1091
wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
1092
"(len=%lu plen=%lu)",
1093
(unsigned long) len, (unsigned long) plen);
1097
sm->reqId = hdr->identifier;
1099
if (sm->workaround) {
1100
md5_vector(1, (const u8 **) &req, &plen, sm->req_md5);
1103
switch (hdr->code) {
1104
case EAP_CODE_REQUEST:
1105
if (plen < sizeof(*hdr) + 1) {
1106
wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
1111
pos = (const u8 *) (hdr + 1);
1112
sm->reqMethod = *pos++;
1113
if (sm->reqMethod == EAP_TYPE_EXPANDED) {
1114
if (plen < sizeof(*hdr) + 8) {
1115
wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
1116
"expanded EAP-Packet (plen=%lu)",
1117
(unsigned long) plen);
1120
sm->reqVendor = WPA_GET_BE24(pos);
1122
sm->reqVendorMethod = WPA_GET_BE32(pos);
1124
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
1125
"method=%u vendor=%u vendorMethod=%u",
1126
sm->reqId, sm->reqMethod, sm->reqVendor,
1127
sm->reqVendorMethod);
1129
case EAP_CODE_RESPONSE:
1130
if (sm->selectedMethod == EAP_TYPE_LEAP) {
1132
* LEAP differs from RFC 4137 by using reversed roles
1133
* for mutual authentication and because of this, we
1134
* need to accept EAP-Response frames if LEAP is used.
1136
if (plen < sizeof(*hdr) + 1) {
1137
wpa_printf(MSG_DEBUG, "EAP: Too short "
1138
"EAP-Response - no Type field");
1142
pos = (const u8 *) (hdr + 1);
1143
sm->reqMethod = *pos;
1144
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
1145
"LEAP method=%d id=%d",
1146
sm->reqMethod, sm->reqId);
1149
wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
1151
case EAP_CODE_SUCCESS:
1152
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
1153
sm->rxSuccess = TRUE;
1155
case EAP_CODE_FAILURE:
1156
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
1157
sm->rxFailure = TRUE;
1160
wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
1161
"code %d", hdr->code);
1168
* eap_peer_sm_init - Allocate and initialize EAP peer state machine
1169
* @eapol_ctx: Context data to be used with eapol_cb calls
1170
* @eapol_cb: Pointer to EAPOL callback functions
1171
* @msg_ctx: Context data for wpa_msg() calls
1172
* @conf: EAP configuration
1173
* Returns: Pointer to the allocated EAP state machine or %NULL on failure
1175
* This function allocates and initializes an EAP state machine. In addition,
1176
* this initializes TLS library for the new EAP state machine. eapol_cb pointer
1177
* will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP
1178
* state machine. Consequently, the caller must make sure that this data
1179
* structure remains alive while the EAP state machine is active.
1181
struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
1182
struct eapol_callbacks *eapol_cb,
1183
void *msg_ctx, struct eap_config *conf)
1186
struct tls_config tlsconf;
1188
sm = os_zalloc(sizeof(*sm));
1191
sm->eapol_ctx = eapol_ctx;
1192
sm->eapol_cb = eapol_cb;
1193
sm->msg_ctx = msg_ctx;
1194
sm->ClientTimeout = 60;
1196
os_memset(&tlsconf, 0, sizeof(tlsconf));
1197
tlsconf.opensc_engine_path = conf->opensc_engine_path;
1198
tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
1199
tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
1200
sm->ssl_ctx = tls_init(&tlsconf);
1201
if (sm->ssl_ctx == NULL) {
1202
wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
1213
* eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine
1214
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1216
* This function deinitializes EAP state machine and frees all allocated
1219
void eap_peer_sm_deinit(struct eap_sm *sm)
1223
eap_deinit_prev_method(sm, "EAP deinit");
1225
tls_deinit(sm->ssl_ctx);
1231
* eap_peer_sm_step - Step EAP peer state machine
1232
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1233
* Returns: 1 if EAP state was changed or 0 if not
1235
* This function advances EAP state machine to a new state to match with the
1236
* current variables. This should be called whenever variables used by the EAP
1237
* state machine have changed.
1239
int eap_peer_sm_step(struct eap_sm *sm)
1243
sm->changed = FALSE;
1247
} while (sm->changed);
1253
* eap_sm_abort - Abort EAP authentication
1254
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1256
* Release system resources that have been allocated for the authentication
1257
* session without fully deinitializing the EAP state machine.
1259
void eap_sm_abort(struct eap_sm *sm)
1261
os_free(sm->lastRespData);
1262
sm->lastRespData = NULL;
1263
os_free(sm->eapRespData);
1264
sm->eapRespData = NULL;
1265
os_free(sm->eapKeyData);
1266
sm->eapKeyData = NULL;
1268
/* This is not clearly specified in the EAP statemachines draft, but
1269
* it seems necessary to make sure that some of the EAPOL variables get
1270
* cleared for the next authentication. */
1271
eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
1275
#ifdef CONFIG_CTRL_IFACE
1276
static const char * eap_sm_state_txt(int state)
1279
case EAP_INITIALIZE:
1280
return "INITIALIZE";
1287
case EAP_GET_METHOD:
1288
return "GET_METHOD";
1291
case EAP_SEND_RESPONSE:
1292
return "SEND_RESPONSE";
1297
case EAP_NOTIFICATION:
1298
return "NOTIFICATION";
1299
case EAP_RETRANSMIT:
1300
return "RETRANSMIT";
1309
#endif /* CONFIG_CTRL_IFACE */
1312
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1313
static const char * eap_sm_method_state_txt(EapMethodState state)
1322
case METHOD_MAY_CONT:
1332
static const char * eap_sm_decision_txt(EapDecision decision)
1337
case DECISION_COND_SUCC:
1339
case DECISION_UNCOND_SUCC:
1340
return "UNCOND_SUCC";
1345
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1348
#ifdef CONFIG_CTRL_IFACE
1351
* eap_sm_get_status - Get EAP state machine status
1352
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1353
* @buf: Buffer for status information
1354
* @buflen: Maximum buffer length
1355
* @verbose: Whether to include verbose status information
1356
* Returns: Number of bytes written to buf.
1358
* Query EAP state machine for status information. This function fills in a
1359
* text area with current status information from the EAPOL state machine. If
1360
* the buffer (buf) is not large enough, status information will be truncated
1361
* to fit the buffer.
1363
int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
1370
len = os_snprintf(buf, buflen,
1372
eap_sm_state_txt(sm->EAP_state));
1373
if (len < 0 || (size_t) len >= buflen)
1376
if (sm->selectedMethod != EAP_TYPE_NONE) {
1381
const struct eap_method *m =
1382
eap_peer_get_eap_method(EAP_VENDOR_IETF,
1383
sm->selectedMethod);
1389
ret = os_snprintf(buf + len, buflen - len,
1390
"selectedMethod=%d (EAP-%s)\n",
1391
sm->selectedMethod, name);
1392
if (ret < 0 || (size_t) ret >= buflen - len)
1396
if (sm->m && sm->m->get_status) {
1397
len += sm->m->get_status(sm, sm->eap_method_priv,
1398
buf + len, buflen - len,
1404
ret = os_snprintf(buf + len, buflen - len,
1408
"ClientTimeout=%d\n",
1410
eap_sm_method_state_txt(sm->methodState),
1411
eap_sm_decision_txt(sm->decision),
1413
if (ret < 0 || (size_t) ret >= buflen - len)
1420
#endif /* CONFIG_CTRL_IFACE */
1423
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1425
TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
1427
} eap_ctrl_req_type;
1429
static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
1430
const char *msg, size_t msglen)
1432
struct wpa_ssid *config;
1441
config = eap_get_config(sm);
1449
config->pending_req_identity++;
1454
config->pending_req_password++;
1456
case TYPE_NEW_PASSWORD:
1457
field = "NEW_PASSWORD";
1458
txt = "New Password";
1459
config->pending_req_new_password++;
1464
config->pending_req_pin++;
1469
tmp = os_malloc(msglen + 3);
1473
os_memcpy(tmp + 1, msg, msglen);
1474
tmp[msglen + 1] = ']';
1475
tmp[msglen + 2] = '\0';
1477
os_free(config->pending_req_otp);
1478
config->pending_req_otp = tmp;
1479
config->pending_req_otp_len = msglen + 3;
1481
if (config->pending_req_otp == NULL)
1483
txt = config->pending_req_otp;
1486
case TYPE_PASSPHRASE:
1487
field = "PASSPHRASE";
1488
txt = "Private key passphrase";
1489
config->pending_req_passphrase++;
1495
buflen = 100 + os_strlen(txt) + config->ssid_len;
1496
buf = os_malloc(buflen);
1499
len = os_snprintf(buf, buflen,
1500
WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
1501
field, config->id, txt);
1502
if (len < 0 || (size_t) len >= buflen) {
1506
if (config->ssid && buflen > len + config->ssid_len) {
1507
os_memcpy(buf + len, config->ssid, config->ssid_len);
1508
len += config->ssid_len;
1511
buf[buflen - 1] = '\0';
1512
wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf);
1515
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1516
#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
1517
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1521
* eap_sm_request_identity - Request identity from user (ctrl_iface)
1522
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1524
* EAP methods can call this function to request identity information for the
1525
* current network. This is normally called when the identity is not included
1526
* in the network configuration. The request will be sent to monitor programs
1527
* through the control interface.
1529
void eap_sm_request_identity(struct eap_sm *sm)
1531
eap_sm_request(sm, TYPE_IDENTITY, NULL, 0);
1536
* eap_sm_request_password - Request password from user (ctrl_iface)
1537
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1539
* EAP methods can call this function to request password information for the
1540
* current network. This is normally called when the password is not included
1541
* in the network configuration. The request will be sent to monitor programs
1542
* through the control interface.
1544
void eap_sm_request_password(struct eap_sm *sm)
1546
eap_sm_request(sm, TYPE_PASSWORD, NULL, 0);
1551
* eap_sm_request_new_password - Request new password from user (ctrl_iface)
1552
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1554
* EAP methods can call this function to request new password information for
1555
* the current network. This is normally called when the EAP method indicates
1556
* that the current password has expired and password change is required. The
1557
* request will be sent to monitor programs through the control interface.
1559
void eap_sm_request_new_password(struct eap_sm *sm)
1561
eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0);
1566
* eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
1567
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1569
* EAP methods can call this function to request SIM or smart card PIN
1570
* information for the current network. This is normally called when the PIN is
1571
* not included in the network configuration. The request will be sent to
1572
* monitor programs through the control interface.
1574
void eap_sm_request_pin(struct eap_sm *sm)
1576
eap_sm_request(sm, TYPE_PIN, NULL, 0);
1581
* eap_sm_request_otp - Request one time password from user (ctrl_iface)
1582
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1583
* @msg: Message to be displayed to the user when asking for OTP
1584
* @msg_len: Length of the user displayable message
1586
* EAP methods can call this function to request open time password (OTP) for
1587
* the current network. The request will be sent to monitor programs through
1588
* the control interface.
1590
void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
1592
eap_sm_request(sm, TYPE_OTP, msg, msg_len);
1597
* eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
1598
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1600
* EAP methods can call this function to request passphrase for a private key
1601
* for the current network. This is normally called when the passphrase is not
1602
* included in the network configuration. The request will be sent to monitor
1603
* programs through the control interface.
1605
void eap_sm_request_passphrase(struct eap_sm *sm)
1607
eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0);
1612
* eap_sm_notify_ctrl_attached - Notification of attached monitor
1613
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1615
* Notify EAP state machines that a monitor was attached to the control
1616
* interface to trigger re-sending of pending requests for user input.
1618
void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
1620
struct wpa_ssid *config = eap_get_config(sm);
1625
/* Re-send any pending requests for user data since a new control
1626
* interface was added. This handles cases where the EAP authentication
1627
* starts immediately after system startup when the user interface is
1628
* not yet running. */
1629
if (config->pending_req_identity)
1630
eap_sm_request_identity(sm);
1631
if (config->pending_req_password)
1632
eap_sm_request_password(sm);
1633
if (config->pending_req_new_password)
1634
eap_sm_request_new_password(sm);
1635
if (config->pending_req_otp)
1636
eap_sm_request_otp(sm, NULL, 0);
1637
if (config->pending_req_pin)
1638
eap_sm_request_pin(sm);
1639
if (config->pending_req_passphrase)
1640
eap_sm_request_passphrase(sm);
1644
static int eap_allowed_phase2_type(int vendor, int type)
1646
if (vendor != EAP_VENDOR_IETF)
1648
return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
1649
type != EAP_TYPE_FAST;
1654
* eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
1655
* @name: EAP method name, e.g., MD5
1656
* @vendor: Buffer for returning EAP Vendor-Id
1657
* Returns: EAP method type or %EAP_TYPE_NONE if not found
1659
* This function maps EAP type names into EAP type numbers that are allowed for
1660
* Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
1661
* EAP-PEAP, EAP-TTLS, and EAP-FAST.
1663
u32 eap_get_phase2_type(const char *name, int *vendor)
1666
u8 type = eap_peer_get_type(name, &v);
1667
if (eap_allowed_phase2_type(v, type)) {
1671
*vendor = EAP_VENDOR_IETF;
1672
return EAP_TYPE_NONE;
1677
* eap_get_phase2_types - Get list of allowed EAP phase 2 types
1678
* @config: Pointer to a network configuration
1679
* @count: Pointer to a variable to be filled with number of returned EAP types
1680
* Returns: Pointer to allocated type list or %NULL on failure
1682
* This function generates an array of allowed EAP phase 2 (tunneled) types for
1683
* the given network configuration.
1685
struct eap_method_type * eap_get_phase2_types(struct wpa_ssid *config,
1688
struct eap_method_type *buf;
1692
const struct eap_method *methods, *m;
1694
methods = eap_peer_get_methods(&mcount);
1695
if (methods == NULL)
1698
buf = os_malloc(mcount * sizeof(struct eap_method_type));
1702
for (m = methods; m; m = m->next) {
1705
if (eap_allowed_phase2_type(vendor, method)) {
1706
if (vendor == EAP_VENDOR_IETF &&
1707
method == EAP_TYPE_TLS && config &&
1708
config->private_key2 == NULL)
1710
buf[*count].vendor = vendor;
1711
buf[*count].method = method;
1721
* eap_set_fast_reauth - Update fast_reauth setting
1722
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1723
* @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
1725
void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
1727
sm->fast_reauth = enabled;
1732
* eap_set_workaround - Update EAP workarounds setting
1733
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1734
* @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
1736
void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
1738
sm->workaround = workaround;
1743
* eap_get_config - Get current network configuration
1744
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1745
* Returns: Pointer to the current network configuration or %NULL if not found
1747
* EAP peer methods should avoid using this function if they can use other
1748
* access functions, like eap_get_config_identity() and
1749
* eap_get_config_password(), that do not require direct access to
1752
struct wpa_ssid * eap_get_config(struct eap_sm *sm)
1754
return sm->eapol_cb->get_config(sm->eapol_ctx);
1759
* eap_get_config_password - Get identity from the network configuration
1760
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1761
* @len: Buffer for the length of the identity
1762
* Returns: Pointer to the identity or %NULL if not found
1764
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
1766
struct wpa_ssid *config = eap_get_config(sm);
1769
*len = config->identity_len;
1770
return config->identity;
1775
* eap_get_config_password - Get password from the network configuration
1776
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1777
* @len: Buffer for the length of the password
1778
* Returns: Pointer to the password or %NULL if not found
1780
const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
1782
struct wpa_ssid *config = eap_get_config(sm);
1785
*len = config->password_len;
1786
return config->password;
1791
* eap_get_config_new_password - Get new password from network configuration
1792
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1793
* @len: Buffer for the length of the new password
1794
* Returns: Pointer to the new password or %NULL if not found
1796
const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
1798
struct wpa_ssid *config = eap_get_config(sm);
1801
*len = config->new_password_len;
1802
return config->new_password;
1807
* eap_get_config_otp - Get one-time password from the network configuration
1808
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1809
* @len: Buffer for the length of the one-time password
1810
* Returns: Pointer to the one-time password or %NULL if not found
1812
const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
1814
struct wpa_ssid *config = eap_get_config(sm);
1817
*len = config->otp_len;
1823
* eap_clear_config_otp - Clear used one-time password
1824
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1826
* This function clears a used one-time password (OTP) from the current network
1827
* configuration. This should be called when the OTP has been used and is not
1830
void eap_clear_config_otp(struct eap_sm *sm)
1832
struct wpa_ssid *config = eap_get_config(sm);
1835
os_memset(config->otp, 0, config->otp_len);
1836
os_free(config->otp);
1838
config->otp_len = 0;
1843
* eap_key_available - Get key availability (eapKeyAvailable variable)
1844
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1845
* Returns: 1 if EAP keying material is available, 0 if not
1847
int eap_key_available(struct eap_sm *sm)
1849
return sm ? sm->eapKeyAvailable : 0;
1854
* eap_notify_success - Notify EAP state machine about external success trigger
1855
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1857
* This function is called when external event, e.g., successful completion of
1858
* WPA-PSK key handshake, is indicating that EAP state machine should move to
1859
* success state. This is mainly used with security modes that do not use EAP
1860
* state machine (e.g., WPA-PSK).
1862
void eap_notify_success(struct eap_sm *sm)
1865
sm->decision = DECISION_COND_SUCC;
1866
sm->EAP_state = EAP_SUCCESS;
1872
* eap_notify_lower_layer_success - Notification of lower layer success
1873
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1875
* Notify EAP state machines that a lower layer has detected a successful
1876
* authentication. This is used to recover from dropped EAP-Success messages.
1878
void eap_notify_lower_layer_success(struct eap_sm *sm)
1883
if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
1884
sm->decision == DECISION_FAIL ||
1885
(sm->methodState != METHOD_MAY_CONT &&
1886
sm->methodState != METHOD_DONE))
1889
if (sm->eapKeyData != NULL)
1890
sm->eapKeyAvailable = TRUE;
1891
eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
1892
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
1893
"EAP authentication completed successfully (based on lower "
1899
* eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
1900
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1901
* @len: Pointer to variable that will be set to number of bytes in the key
1902
* Returns: Pointer to the EAP keying data or %NULL on failure
1904
* Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
1905
* key is available only after a successful authentication. EAP state machine
1906
* continues to manage the key data and the caller must not change or free the
1909
const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
1911
if (sm == NULL || sm->eapKeyData == NULL) {
1916
*len = sm->eapKeyDataLen;
1917
return sm->eapKeyData;
1922
* eap_get_eapKeyData - Get EAP response data
1923
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1924
* @len: Pointer to variable that will be set to the length of the response
1925
* Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
1927
* Fetch EAP response (eapRespData) from the EAP state machine. This data is
1928
* available when EAP state machine has processed an incoming EAP request. The
1929
* EAP state machine does not maintain a reference to the response after this
1930
* function is called and the caller is responsible for freeing the data.
1932
u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len)
1936
if (sm == NULL || sm->eapRespData == NULL) {
1941
resp = sm->eapRespData;
1942
*len = sm->eapRespDataLen;
1943
sm->eapRespData = NULL;
1944
sm->eapRespDataLen = 0;
1951
* eap_sm_register_scard_ctx - Notification of smart card context
1952
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1953
* @ctx: Context data for smart card operations
1955
* Notify EAP state machines of context data for smart card operations. This
1956
* context data will be used as a parameter for scard_*() functions.
1958
void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
1961
sm->scard_ctx = ctx;
1966
* eap_set_config_blob - Set or add a named configuration blob
1967
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1968
* @blob: New value for the blob
1970
* Adds a new configuration blob or replaces the current value of an existing
1973
void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
1975
sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
1980
* eap_get_config_blob - Get a named configuration blob
1981
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1982
* @name: Name of the blob
1983
* Returns: Pointer to blob data or %NULL if not found
1985
const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
1988
return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
1993
* eap_set_force_disabled - Set force_disabled flag
1994
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1995
* @disabled: 1 = EAP disabled, 0 = EAP enabled
1997
* This function is used to force EAP state machine to be disabled when it is
1998
* not in use (e.g., with WPA-PSK or plaintext connections).
2000
void eap_set_force_disabled(struct eap_sm *sm, int disabled)
2002
sm->force_disabled = disabled;
2007
* eap_notify_pending - Notify that EAP method is ready to re-process a request
2008
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2010
* An EAP method can perform a pending operation (e.g., to get a response from
2011
* an external process). Once the response is available, this function can be
2012
* used to request EAPOL state machine to retry delivering the previously
2013
* received (and still unanswered) EAP request to EAP state machine.
2015
void eap_notify_pending(struct eap_sm *sm)
2017
sm->eapol_cb->notify_pending(sm->eapol_ctx);
2022
* eap_invalidate_cached_session - Mark cached session data invalid
2023
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2025
void eap_invalidate_cached_session(struct eap_sm *sm)
2028
eap_deinit_prev_method(sm, "invalidate");