~ubuntu-branches/ubuntu/hardy/wpasupplicant/hardy

« back to all changes in this revision

Viewing changes to src/eap_peer/eap.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * EAP peer state machines (RFC 4137)
3
 
 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4
 
 *
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.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 *
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).
22
 
 */
23
 
 
24
 
#include "includes.h"
25
 
 
26
 
#include "common.h"
27
 
#include "eap_i.h"
28
 
#include "config_ssid.h"
29
 
#include "tls.h"
30
 
#include "crypto.h"
31
 
#include "pcsc_funcs.h"
32
 
#include "wpa_ctrl.h"
33
 
#include "state_machine.h"
34
 
 
35
 
#define STATE_MACHINE_DATA struct eap_sm
36
 
#define STATE_MACHINE_DEBUG_PREFIX "EAP"
37
 
 
38
 
#define EAP_MAX_AUTH_ROUNDS 50
39
 
 
40
 
 
41
 
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
42
 
                                  EapType method);
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 */
52
 
 
53
 
 
54
 
 
55
 
static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
56
 
{
57
 
        return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
58
 
}
59
 
 
60
 
 
61
 
static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
62
 
                           Boolean value)
63
 
{
64
 
        sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
65
 
}
66
 
 
67
 
 
68
 
static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
69
 
{
70
 
        return sm->eapol_cb->get_int(sm->eapol_ctx, var);
71
 
}
72
 
 
73
 
 
74
 
static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
75
 
                          unsigned int value)
76
 
{
77
 
        sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
78
 
}
79
 
 
80
 
 
81
 
static u8 * eapol_get_eapReqData(struct eap_sm *sm, size_t *len)
82
 
{
83
 
        return sm->eapol_cb->get_eapReqData(sm->eapol_ctx, len);
84
 
}
85
 
 
86
 
 
87
 
static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
88
 
{
89
 
        if (sm->m == NULL || sm->eap_method_priv == NULL)
90
 
                return;
91
 
 
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;
96
 
        sm->m = NULL;
97
 
}
98
 
 
99
 
 
100
 
/*
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).
104
 
 */
105
 
SM_STATE(EAP, INITIALIZE)
106
 
{
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);
113
 
        } else {
114
 
                eap_deinit_prev_method(sm, "INITIALIZE");
115
 
        }
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 */
129
 
        /*
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
135
 
         * something else(?)
136
 
         */
137
 
        eapol_set_bool(sm, EAPOL_eapResp, FALSE);
138
 
        eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
139
 
        sm->num_rounds = 0;
140
 
}
141
 
 
142
 
 
143
 
/*
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.
147
 
 */
148
 
SM_STATE(EAP, DISABLED)
149
 
{
150
 
        SM_ENTRY(EAP, DISABLED);
151
 
        sm->num_rounds = 0;
152
 
}
153
 
 
154
 
 
155
 
/*
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.
159
 
 */
160
 
SM_STATE(EAP, IDLE)
161
 
{
162
 
        SM_ENTRY(EAP, IDLE);
163
 
}
164
 
 
165
 
 
166
 
/*
167
 
 * This state is entered when an EAP packet is received (eapReq == TRUE) to
168
 
 * parse the packet header.
169
 
 */
170
 
SM_STATE(EAP, RECEIVED)
171
 
{
172
 
        const u8 *eapReqData;
173
 
        size_t eapReqDataLen;
174
 
 
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);
179
 
        sm->num_rounds++;
180
 
}
181
 
 
182
 
 
183
 
/*
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.
186
 
 */
187
 
SM_STATE(EAP, GET_METHOD)
188
 
{
189
 
        int reinit;
190
 
        EapType method;
191
 
 
192
 
        SM_ENTRY(EAP, GET_METHOD);
193
 
 
194
 
        if (sm->reqMethod == EAP_TYPE_EXPANDED)
195
 
                method = sm->reqVendorMethod;
196
 
        else
197
 
                method = sm->reqMethod;
198
 
 
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);
202
 
                goto nak;
203
 
        }
204
 
 
205
 
        /*
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
211
 
         * is allocated here.
212
 
         */
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");
220
 
                reinit = 1;
221
 
        } else {
222
 
                eap_deinit_prev_method(sm, "GET_METHOD");
223
 
                reinit = 0;
224
 
        }
225
 
 
226
 
        sm->selectedMethod = sm->reqMethod;
227
 
        if (sm->m == NULL)
228
 
                sm->m = eap_peer_get_eap_method(sm->reqVendor, method);
229
 
        if (!sm->m) {
230
 
                wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
231
 
                           "vendor %d method %d",
232
 
                           sm->reqVendor, method);
233
 
                goto nak;
234
 
        }
235
 
 
236
 
        wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
237
 
                   "vendor %u method %u (%s)",
238
 
                   sm->reqVendor, method, sm->m->name);
239
 
        if (reinit)
240
 
                sm->eap_method_priv = sm->m->init_for_reauth(
241
 
                        sm, sm->eap_method_priv);
242
 
        else
243
 
                sm->eap_method_priv = sm->m->init(sm);
244
 
 
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 "
249
 
                        "method %u (%s)",
250
 
                        sm->reqVendor, method, sm->m->name);
251
 
                sm->m = NULL;
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)) {
257
 
                        /*
258
 
                         * Return without generating Nak in order to allow
259
 
                         * entering of PIN code or passphrase to retry the
260
 
                         * current EAP packet.
261
 
                         */
262
 
                        wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
263
 
                                   "request - skip Nak");
264
 
                        return;
265
 
                }
266
 
 
267
 
                goto nak;
268
 
        }
269
 
 
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);
274
 
        return;
275
 
 
276
 
nak:
277
 
        os_free(sm->eapRespData);
278
 
        sm->eapRespData = NULL;
279
 
        sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen);
280
 
}
281
 
 
282
 
 
283
 
/*
284
 
 * The method processing happens here. The request from the authenticator is
285
 
 * processed, and an appropriate response packet is built.
286
 
 */
287
 
SM_STATE(EAP, METHOD)
288
 
{
289
 
        u8 *eapReqData;
290
 
        size_t eapReqDataLen;
291
 
        struct eap_method_ret ret;
292
 
 
293
 
        SM_ENTRY(EAP, METHOD);
294
 
        if (sm->m == NULL) {
295
 
                wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
296
 
                return;
297
 
        }
298
 
 
299
 
        eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
300
 
 
301
 
        /*
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.
309
 
         *
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)
314
 
         */
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));
330
 
 
331
 
        sm->ignore = ret.ignore;
332
 
        if (sm->ignore)
333
 
                return;
334
 
        sm->methodState = ret.methodState;
335
 
        sm->decision = ret.decision;
336
 
        sm->allowNotifications = ret.allowNotifications;
337
 
 
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,
342
 
                                               &sm->eapKeyDataLen);
343
 
        }
344
 
}
345
 
 
346
 
 
347
 
/*
348
 
 * This state signals the lower layer that a response packet is ready to be
349
 
 * sent.
350
 
 */
351
 
SM_STATE(EAP, SEND_RESPONSE)
352
 
{
353
 
        SM_ENTRY(EAP, SEND_RESPONSE);
354
 
        os_free(sm->lastRespData);
355
 
        if (sm->eapRespData) {
356
 
                if (sm->workaround)
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,
362
 
                                  sm->eapRespDataLen);
363
 
                        sm->lastRespDataLen = sm->eapRespDataLen;
364
 
                }
365
 
                eapol_set_bool(sm, EAPOL_eapResp, TRUE);
366
 
        } else
367
 
                sm->lastRespData = NULL;
368
 
        eapol_set_bool(sm, EAPOL_eapReq, FALSE);
369
 
        eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
370
 
}
371
 
 
372
 
 
373
 
/*
374
 
 * This state signals the lower layer that the request was discarded, and no
375
 
 * response packet will be sent at this time.
376
 
 */
377
 
SM_STATE(EAP, DISCARD)
378
 
{
379
 
        SM_ENTRY(EAP, DISCARD);
380
 
        eapol_set_bool(sm, EAPOL_eapReq, FALSE);
381
 
        eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
382
 
}
383
 
 
384
 
 
385
 
/*
386
 
 * Handles requests for Identity method and builds a response.
387
 
 */
388
 
SM_STATE(EAP, IDENTITY)
389
 
{
390
 
        const u8 *eapReqData;
391
 
        size_t eapReqDataLen;
392
 
 
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);
400
 
}
401
 
 
402
 
 
403
 
/*
404
 
 * Handles requests for Notification method and builds a response.
405
 
 */
406
 
SM_STATE(EAP, NOTIFICATION)
407
 
{
408
 
        const u8 *eapReqData;
409
 
        size_t eapReqDataLen;
410
 
 
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);
417
 
}
418
 
 
419
 
 
420
 
/*
421
 
 * This state retransmits the previous response packet.
422
 
 */
423
 
SM_STATE(EAP, RETRANSMIT)
424
 
{
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;
433
 
                }
434
 
        } else
435
 
                sm->eapRespData = NULL;
436
 
}
437
 
 
438
 
 
439
 
/*
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
442
 
 * restarted.
443
 
 */
444
 
SM_STATE(EAP, SUCCESS)
445
 
{
446
 
        SM_ENTRY(EAP, SUCCESS);
447
 
        if (sm->eapKeyData != NULL)
448
 
                sm->eapKeyAvailable = TRUE;
449
 
        eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
450
 
 
451
 
        /*
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
454
 
         * initialized.
455
 
         */
456
 
        eapol_set_bool(sm, EAPOL_eapReq, FALSE);
457
 
 
458
 
        /*
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.
463
 
         */
464
 
        eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
465
 
 
466
 
        wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
467
 
                "EAP authentication completed successfully");
468
 
}
469
 
 
470
 
 
471
 
/*
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.
474
 
 */
475
 
SM_STATE(EAP, FAILURE)
476
 
{
477
 
        SM_ENTRY(EAP, FAILURE);
478
 
        eapol_set_bool(sm, EAPOL_eapFail, TRUE);
479
 
 
480
 
        /*
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
483
 
         * initialized.
484
 
         */
485
 
        eapol_set_bool(sm, EAPOL_eapReq, FALSE);
486
 
 
487
 
        /*
488
 
         * RFC 4137 does not set eapNoResp here. However, either eapResp or
489
 
         * eapNoResp is required to be set after processing the received EAP
490
 
         * frame.
491
 
         */
492
 
        eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
493
 
 
494
 
        wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
495
 
                "EAP authentication failed");
496
 
}
497
 
 
498
 
 
499
 
static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
500
 
{
501
 
        /*
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.
506
 
         *
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).
510
 
         */
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);
517
 
                return 1;
518
 
        }
519
 
        wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
520
 
                   "lastId=%d", reqId, lastId);
521
 
        return 0;
522
 
}
523
 
 
524
 
 
525
 
/*
526
 
 * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
527
 
 */
528
 
 
529
 
static void eap_peer_sm_step_idle(struct eap_sm *sm)
530
 
{
531
 
        /*
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.
535
 
         */
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);
558
 
}
559
 
 
560
 
 
561
 
static int eap_peer_req_is_duplicate(struct eap_sm *sm)
562
 
{
563
 
        int duplicate;
564
 
 
565
 
        duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
566
 
        if (sm->workaround && duplicate &&
567
 
            os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
568
 
                /*
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.
575
 
                 */
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 "
579
 
                           "duplicate packet");
580
 
                duplicate = 0;
581
 
        }
582
 
 
583
 
        return duplicate;
584
 
}
585
 
 
586
 
 
587
 
static void eap_peer_sm_step_received(struct eap_sm *sm)
588
 
{
589
 
        int duplicate = eap_peer_req_is_duplicate(sm);
590
 
 
591
 
        /*
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.
595
 
         */
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 &&
601
 
                 ((sm->rxFailure &&
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);
631
 
        else
632
 
                SM_ENTER(EAP, DISCARD);
633
 
}
634
 
 
635
 
 
636
 
static void eap_peer_sm_step_local(struct eap_sm *sm)
637
 
{
638
 
        switch (sm->EAP_state) {
639
 
        case EAP_INITIALIZE:
640
 
                SM_ENTER(EAP, IDLE);
641
 
                break;
642
 
        case EAP_DISABLED:
643
 
                if (eapol_get_bool(sm, EAPOL_portEnabled) &&
644
 
                    !sm->force_disabled)
645
 
                        SM_ENTER(EAP, INITIALIZE);
646
 
                break;
647
 
        case EAP_IDLE:
648
 
                eap_peer_sm_step_idle(sm);
649
 
                break;
650
 
        case EAP_RECEIVED:
651
 
                eap_peer_sm_step_received(sm);
652
 
                break;
653
 
        case EAP_GET_METHOD:
654
 
                if (sm->selectedMethod == sm->reqMethod)
655
 
                        SM_ENTER(EAP, METHOD);
656
 
                else
657
 
                        SM_ENTER(EAP, SEND_RESPONSE);
658
 
                break;
659
 
        case EAP_METHOD:
660
 
                if (sm->ignore)
661
 
                        SM_ENTER(EAP, DISCARD);
662
 
                else
663
 
                        SM_ENTER(EAP, SEND_RESPONSE);
664
 
                break;
665
 
        case EAP_SEND_RESPONSE:
666
 
                SM_ENTER(EAP, IDLE);
667
 
                break;
668
 
        case EAP_DISCARD:
669
 
                SM_ENTER(EAP, IDLE);
670
 
                break;
671
 
        case EAP_IDENTITY:
672
 
                SM_ENTER(EAP, SEND_RESPONSE);
673
 
                break;
674
 
        case EAP_NOTIFICATION:
675
 
                SM_ENTER(EAP, SEND_RESPONSE);
676
 
                break;
677
 
        case EAP_RETRANSMIT:
678
 
                SM_ENTER(EAP, SEND_RESPONSE);
679
 
                break;
680
 
        case EAP_SUCCESS:
681
 
                break;
682
 
        case EAP_FAILURE:
683
 
                break;
684
 
        }
685
 
}
686
 
 
687
 
 
688
 
SM_STEP(EAP)
689
 
{
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.
704
 
                 */
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);
709
 
                        sm->num_rounds++;
710
 
                        SM_ENTER_GLOBAL(EAP, FAILURE);
711
 
                }
712
 
        } else {
713
 
                /* Local transitions */
714
 
                eap_peer_sm_step_local(sm);
715
 
        }
716
 
}
717
 
 
718
 
 
719
 
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
720
 
                                  EapType method)
721
 
{
722
 
        struct wpa_ssid *config = eap_get_config(sm);
723
 
 
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);
727
 
                return FALSE;
728
 
        }
729
 
        if (eap_peer_get_eap_method(vendor, method))
730
 
                return TRUE;
731
 
        wpa_printf(MSG_DEBUG, "EAP: not included in build: "
732
 
                   "vendor %u method %u", vendor, method);
733
 
        return FALSE;
734
 
}
735
 
 
736
 
 
737
 
static u8 * eap_sm_build_expanded_nak(struct eap_sm *sm, int id, size_t *len,
738
 
                                      const struct eap_method *methods,
739
 
                                      size_t count)
740
 
{
741
 
        struct wpa_ssid *config = eap_get_config(sm);
742
 
        struct eap_hdr *resp;
743
 
        u8 *pos;
744
 
        int found = 0;
745
 
        const struct eap_method *m;
746
 
 
747
 
        wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
748
 
 
749
 
        /* RFC 3748 - 5.3.2: Expanded Nak */
750
 
        *len = sizeof(struct eap_hdr) + 8;
751
 
        resp = os_malloc(*len + 8 * (count + 1));
752
 
        if (resp == NULL)
753
 
                return NULL;
754
 
 
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);
760
 
        pos += 3;
761
 
        WPA_PUT_BE32(pos, EAP_TYPE_NAK);
762
 
        pos += 4;
763
 
 
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,
769
 
                                                  m->method)) {
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);
775
 
                        pos += 3;
776
 
                        WPA_PUT_BE32(pos, m->method);
777
 
                        pos += 4;
778
 
 
779
 
                        (*len) += 8;
780
 
                        found++;
781
 
                }
782
 
        }
783
 
        if (!found) {
784
 
                wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
785
 
                *pos++ = EAP_TYPE_EXPANDED;
786
 
                WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
787
 
                pos += 3;
788
 
                WPA_PUT_BE32(pos, EAP_TYPE_NONE);
789
 
                pos += 4;
790
 
 
791
 
                (*len) += 8;
792
 
        }
793
 
 
794
 
        resp->length = host_to_be16(*len);
795
 
 
796
 
        return (u8 *) resp;
797
 
}
798
 
 
799
 
 
800
 
static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
801
 
{
802
 
        struct wpa_ssid *config = eap_get_config(sm);
803
 
        struct eap_hdr *resp;
804
 
        u8 *pos;
805
 
        int found = 0, expanded_found = 0;
806
 
        size_t count;
807
 
        const struct eap_method *methods, *m;
808
 
 
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);
813
 
        if (methods == NULL)
814
 
                return NULL;
815
 
        if (sm->reqMethod == EAP_TYPE_EXPANDED)
816
 
                return eap_sm_build_expanded_nak(sm, id, len, methods, count);
817
 
 
818
 
        /* RFC 3748 - 5.3.1: Legacy Nak */
819
 
        *len = sizeof(struct eap_hdr) + 1;
820
 
        resp = os_malloc(*len + count + 1);
821
 
        if (resp == NULL)
822
 
                return NULL;
823
 
 
824
 
        resp->code = EAP_CODE_RESPONSE;
825
 
        resp->identifier = id;
826
 
        pos = (u8 *) (resp + 1);
827
 
        *pos++ = EAP_TYPE_NAK;
828
 
 
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,
833
 
                                                  m->method)) {
834
 
                        if (m->vendor != EAP_VENDOR_IETF) {
835
 
                                if (expanded_found)
836
 
                                        continue;
837
 
                                expanded_found = 1;
838
 
                                *pos++ = EAP_TYPE_EXPANDED;
839
 
                        } else
840
 
                                *pos++ = m->method;
841
 
                        (*len)++;
842
 
                        found++;
843
 
                }
844
 
        }
845
 
        if (!found) {
846
 
                *pos = EAP_TYPE_NONE;
847
 
                (*len)++;
848
 
        }
849
 
        wpa_hexdump(MSG_DEBUG, "EAP: allowed methods",
850
 
                    ((u8 *) (resp + 1)) + 1, found);
851
 
 
852
 
        resp->length = host_to_be16(*len);
853
 
 
854
 
        return (u8 *) resp;
855
 
}
856
 
 
857
 
 
858
 
static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req)
859
 
{
860
 
        const struct eap_hdr *hdr = (const struct eap_hdr *) req;
861
 
        const u8 *pos = (const u8 *) (hdr + 1);
862
 
        pos++;
863
 
 
864
 
        wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
865
 
                "EAP authentication started");
866
 
 
867
 
        /*
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.
873
 
         */
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);
878
 
}
879
 
 
880
 
 
881
 
#ifdef PCSC_FUNCS
882
 
static int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
883
 
{
884
 
        int aka = 0;
885
 
        char imsi[100];
886
 
        size_t imsi_len;
887
 
        struct eap_method_type *m = ssid->eap_methods;
888
 
        int i;
889
 
 
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");
893
 
                return -1;
894
 
        }
895
 
 
896
 
        wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
897
 
 
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) {
902
 
                        aka = 1;
903
 
                        break;
904
 
                }
905
 
        }
906
 
 
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");
912
 
                return -1;
913
 
        }
914
 
 
915
 
        ssid->identity[0] = aka ? '0' : '1';
916
 
        os_memcpy(ssid->identity + 1, imsi, imsi_len);
917
 
        ssid->identity_len = 1 + imsi_len;
918
 
 
919
 
        return 0;
920
 
}
921
 
#endif /* PCSC_FUNCS */
922
 
 
923
 
 
924
 
static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
925
 
{
926
 
#ifdef PCSC_FUNCS
927
 
        if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
928
 
                /*
929
 
                 * Make sure the same PIN is not tried again in order to avoid
930
 
                 * blocking SIM.
931
 
                 */
932
 
                os_free(ssid->pin);
933
 
                ssid->pin = NULL;
934
 
 
935
 
                wpa_printf(MSG_WARNING, "PIN validation failed");
936
 
                eap_sm_request_pin(sm);
937
 
                return -1;
938
 
        }
939
 
 
940
 
        return eap_sm_imsi_identity(sm, ssid);
941
 
#else /* PCSC_FUNCS */
942
 
        return -1;
943
 
#endif /* PCSC_FUNCS */
944
 
}
945
 
 
946
 
 
947
 
/**
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
954
 
 * failure
955
 
 *
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.
958
 
 */
959
 
u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
960
 
                          int encrypted)
961
 
{
962
 
        struct wpa_ssid *config = eap_get_config(sm);
963
 
        struct eap_hdr *resp;
964
 
        u8 *pos;
965
 
        const u8 *identity;
966
 
        size_t identity_len;
967
 
 
968
 
        if (config == NULL) {
969
 
                wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
970
 
                           "was not available");
971
 
                return NULL;
972
 
        }
973
 
 
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);
984
 
        } else {
985
 
                identity = config->identity;
986
 
                identity_len = config->identity_len;
987
 
                wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
988
 
                                  identity, identity_len);
989
 
        }
990
 
 
991
 
        if (identity == NULL) {
992
 
                wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
993
 
                           "configuration was not available");
994
 
                if (config->pcsc) {
995
 
                        if (eap_sm_get_scard_identity(sm, config) < 0)
996
 
                                return NULL;
997
 
                        identity = config->identity;
998
 
                        identity_len = config->identity_len;
999
 
                        wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
1000
 
                                          "IMSI", identity, identity_len);
1001
 
                } else {
1002
 
                        eap_sm_request_identity(sm);
1003
 
                        return NULL;
1004
 
                }
1005
 
        }
1006
 
 
1007
 
        *len = sizeof(struct eap_hdr) + 1 + identity_len;
1008
 
        resp = os_malloc(*len);
1009
 
        if (resp == NULL)
1010
 
                return NULL;
1011
 
 
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);
1018
 
 
1019
 
        return (u8 *) resp;
1020
 
}
1021
 
 
1022
 
 
1023
 
static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req)
1024
 
{
1025
 
        const struct eap_hdr *hdr = (const struct eap_hdr *) req;
1026
 
        const u8 *pos;
1027
 
        char *msg;
1028
 
        size_t i, msg_len;
1029
 
 
1030
 
        pos = (const u8 *) (hdr + 1);
1031
 
        pos++;
1032
 
 
1033
 
        msg_len = be_to_host16(hdr->length);
1034
 
        if (msg_len < 5)
1035
 
                return;
1036
 
        msg_len -= 5;
1037
 
        wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
1038
 
                          pos, msg_len);
1039
 
 
1040
 
        msg = os_malloc(msg_len + 1);
1041
 
        if (msg == NULL)
1042
 
                return;
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);
1048
 
        os_free(msg);
1049
 
}
1050
 
 
1051
 
 
1052
 
static u8 * eap_sm_buildNotify(int id, size_t *len)
1053
 
{
1054
 
        struct eap_hdr *resp;
1055
 
        u8 *pos;
1056
 
 
1057
 
        wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
1058
 
        *len = sizeof(struct eap_hdr) + 1;
1059
 
        resp = os_malloc(*len);
1060
 
        if (resp == NULL)
1061
 
                return NULL;
1062
 
 
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;
1068
 
 
1069
 
        return (u8 *) resp;
1070
 
}
1071
 
 
1072
 
 
1073
 
static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len)
1074
 
{
1075
 
        const struct eap_hdr *hdr;
1076
 
        size_t plen;
1077
 
        const u8 *pos;
1078
 
 
1079
 
        sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
1080
 
        sm->reqId = 0;
1081
 
        sm->reqMethod = EAP_TYPE_NONE;
1082
 
        sm->reqVendor = EAP_VENDOR_IETF;
1083
 
        sm->reqVendorMethod = EAP_TYPE_NONE;
1084
 
 
1085
 
        if (req == NULL || len < sizeof(*hdr))
1086
 
                return;
1087
 
 
1088
 
        hdr = (const struct eap_hdr *) req;
1089
 
        plen = be_to_host16(hdr->length);
1090
 
        if (plen > len) {
1091
 
                wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
1092
 
                           "(len=%lu plen=%lu)",
1093
 
                           (unsigned long) len, (unsigned long) plen);
1094
 
                return;
1095
 
        }
1096
 
 
1097
 
        sm->reqId = hdr->identifier;
1098
 
 
1099
 
        if (sm->workaround) {
1100
 
                md5_vector(1, (const u8 **) &req, &plen, sm->req_md5);
1101
 
        }
1102
 
 
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 - "
1107
 
                                   "no Type field");
1108
 
                        return;
1109
 
                }
1110
 
                sm->rxReq = TRUE;
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);
1118
 
                                return;
1119
 
                        }
1120
 
                        sm->reqVendor = WPA_GET_BE24(pos);
1121
 
                        pos += 3;
1122
 
                        sm->reqVendorMethod = WPA_GET_BE32(pos);
1123
 
                }
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);
1128
 
                break;
1129
 
        case EAP_CODE_RESPONSE:
1130
 
                if (sm->selectedMethod == EAP_TYPE_LEAP) {
1131
 
                        /*
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.
1135
 
                         */
1136
 
                        if (plen < sizeof(*hdr) + 1) {
1137
 
                                wpa_printf(MSG_DEBUG, "EAP: Too short "
1138
 
                                           "EAP-Response - no Type field");
1139
 
                                return;
1140
 
                        }
1141
 
                        sm->rxResp = TRUE;
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);
1147
 
                        break;
1148
 
                }
1149
 
                wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
1150
 
                break;
1151
 
        case EAP_CODE_SUCCESS:
1152
 
                wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
1153
 
                sm->rxSuccess = TRUE;
1154
 
                break;
1155
 
        case EAP_CODE_FAILURE:
1156
 
                wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
1157
 
                sm->rxFailure = TRUE;
1158
 
                break;
1159
 
        default:
1160
 
                wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
1161
 
                           "code %d", hdr->code);
1162
 
                break;
1163
 
        }
1164
 
}
1165
 
 
1166
 
 
1167
 
/**
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
1174
 
 *
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.
1180
 
 */
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)
1184
 
{
1185
 
        struct eap_sm *sm;
1186
 
        struct tls_config tlsconf;
1187
 
 
1188
 
        sm = os_zalloc(sizeof(*sm));
1189
 
        if (sm == NULL)
1190
 
                return NULL;
1191
 
        sm->eapol_ctx = eapol_ctx;
1192
 
        sm->eapol_cb = eapol_cb;
1193
 
        sm->msg_ctx = msg_ctx;
1194
 
        sm->ClientTimeout = 60;
1195
 
 
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 "
1203
 
                           "context.");
1204
 
                os_free(sm);
1205
 
                return NULL;
1206
 
        }
1207
 
 
1208
 
        return sm;
1209
 
}
1210
 
 
1211
 
 
1212
 
/**
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()
1215
 
 *
1216
 
 * This function deinitializes EAP state machine and frees all allocated
1217
 
 * resources.
1218
 
 */
1219
 
void eap_peer_sm_deinit(struct eap_sm *sm)
1220
 
{
1221
 
        if (sm == NULL)
1222
 
                return;
1223
 
        eap_deinit_prev_method(sm, "EAP deinit");
1224
 
        eap_sm_abort(sm);
1225
 
        tls_deinit(sm->ssl_ctx);
1226
 
        os_free(sm);
1227
 
}
1228
 
 
1229
 
 
1230
 
/**
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
1234
 
 *
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.
1238
 
 */
1239
 
int eap_peer_sm_step(struct eap_sm *sm)
1240
 
{
1241
 
        int res = 0;
1242
 
        do {
1243
 
                sm->changed = FALSE;
1244
 
                SM_STEP_RUN(EAP);
1245
 
                if (sm->changed)
1246
 
                        res = 1;
1247
 
        } while (sm->changed);
1248
 
        return res;
1249
 
}
1250
 
 
1251
 
 
1252
 
/**
1253
 
 * eap_sm_abort - Abort EAP authentication
1254
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1255
 
 *
1256
 
 * Release system resources that have been allocated for the authentication
1257
 
 * session without fully deinitializing the EAP state machine.
1258
 
 */
1259
 
void eap_sm_abort(struct eap_sm *sm)
1260
 
{
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;
1267
 
 
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);
1272
 
}
1273
 
 
1274
 
 
1275
 
#ifdef CONFIG_CTRL_IFACE
1276
 
static const char * eap_sm_state_txt(int state)
1277
 
{
1278
 
        switch (state) {
1279
 
        case EAP_INITIALIZE:
1280
 
                return "INITIALIZE";
1281
 
        case EAP_DISABLED:
1282
 
                return "DISABLED";
1283
 
        case EAP_IDLE:
1284
 
                return "IDLE";
1285
 
        case EAP_RECEIVED:
1286
 
                return "RECEIVED";
1287
 
        case EAP_GET_METHOD:
1288
 
                return "GET_METHOD";
1289
 
        case EAP_METHOD:
1290
 
                return "METHOD";
1291
 
        case EAP_SEND_RESPONSE:
1292
 
                return "SEND_RESPONSE";
1293
 
        case EAP_DISCARD:
1294
 
                return "DISCARD";
1295
 
        case EAP_IDENTITY:
1296
 
                return "IDENTITY";
1297
 
        case EAP_NOTIFICATION:
1298
 
                return "NOTIFICATION";
1299
 
        case EAP_RETRANSMIT:
1300
 
                return "RETRANSMIT";
1301
 
        case EAP_SUCCESS:
1302
 
                return "SUCCESS";
1303
 
        case EAP_FAILURE:
1304
 
                return "FAILURE";
1305
 
        default:
1306
 
                return "UNKNOWN";
1307
 
        }
1308
 
}
1309
 
#endif /* CONFIG_CTRL_IFACE */
1310
 
 
1311
 
 
1312
 
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1313
 
static const char * eap_sm_method_state_txt(EapMethodState state)
1314
 
{
1315
 
        switch (state) {
1316
 
        case METHOD_NONE:
1317
 
                return "NONE";
1318
 
        case METHOD_INIT:
1319
 
                return "INIT";
1320
 
        case METHOD_CONT:
1321
 
                return "CONT";
1322
 
        case METHOD_MAY_CONT:
1323
 
                return "MAY_CONT";
1324
 
        case METHOD_DONE:
1325
 
                return "DONE";
1326
 
        default:
1327
 
                return "UNKNOWN";
1328
 
        }
1329
 
}
1330
 
 
1331
 
 
1332
 
static const char * eap_sm_decision_txt(EapDecision decision)
1333
 
{
1334
 
        switch (decision) {
1335
 
        case DECISION_FAIL:
1336
 
                return "FAIL";
1337
 
        case DECISION_COND_SUCC:
1338
 
                return "COND_SUCC";
1339
 
        case DECISION_UNCOND_SUCC:
1340
 
                return "UNCOND_SUCC";
1341
 
        default:
1342
 
                return "UNKNOWN";
1343
 
        }
1344
 
}
1345
 
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1346
 
 
1347
 
 
1348
 
#ifdef CONFIG_CTRL_IFACE
1349
 
 
1350
 
/**
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.
1357
 
 *
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.
1362
 
 */
1363
 
int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
1364
 
{
1365
 
        int len, ret;
1366
 
 
1367
 
        if (sm == NULL)
1368
 
                return 0;
1369
 
 
1370
 
        len = os_snprintf(buf, buflen,
1371
 
                          "EAP state=%s\n",
1372
 
                          eap_sm_state_txt(sm->EAP_state));
1373
 
        if (len < 0 || (size_t) len >= buflen)
1374
 
                return 0;
1375
 
 
1376
 
        if (sm->selectedMethod != EAP_TYPE_NONE) {
1377
 
                const char *name;
1378
 
                if (sm->m) {
1379
 
                        name = sm->m->name;
1380
 
                } else {
1381
 
                        const struct eap_method *m =
1382
 
                                eap_peer_get_eap_method(EAP_VENDOR_IETF,
1383
 
                                                        sm->selectedMethod);
1384
 
                        if (m)
1385
 
                                name = m->name;
1386
 
                        else
1387
 
                                name = "?";
1388
 
                }
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)
1393
 
                        return len;
1394
 
                len += ret;
1395
 
 
1396
 
                if (sm->m && sm->m->get_status) {
1397
 
                        len += sm->m->get_status(sm, sm->eap_method_priv,
1398
 
                                                 buf + len, buflen - len,
1399
 
                                                 verbose);
1400
 
                }
1401
 
        }
1402
 
 
1403
 
        if (verbose) {
1404
 
                ret = os_snprintf(buf + len, buflen - len,
1405
 
                                  "reqMethod=%d\n"
1406
 
                                  "methodState=%s\n"
1407
 
                                  "decision=%s\n"
1408
 
                                  "ClientTimeout=%d\n",
1409
 
                                  sm->reqMethod,
1410
 
                                  eap_sm_method_state_txt(sm->methodState),
1411
 
                                  eap_sm_decision_txt(sm->decision),
1412
 
                                  sm->ClientTimeout);
1413
 
                if (ret < 0 || (size_t) ret >= buflen - len)
1414
 
                        return len;
1415
 
                len += ret;
1416
 
        }
1417
 
 
1418
 
        return len;
1419
 
}
1420
 
#endif /* CONFIG_CTRL_IFACE */
1421
 
 
1422
 
 
1423
 
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1424
 
typedef enum {
1425
 
        TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
1426
 
        TYPE_PASSPHRASE
1427
 
} eap_ctrl_req_type;
1428
 
 
1429
 
static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
1430
 
                           const char *msg, size_t msglen)
1431
 
{
1432
 
        struct wpa_ssid *config;
1433
 
        char *buf;
1434
 
        size_t buflen;
1435
 
        int len;
1436
 
        char *field;
1437
 
        char *txt, *tmp;
1438
 
 
1439
 
        if (sm == NULL)
1440
 
                return;
1441
 
        config = eap_get_config(sm);
1442
 
        if (config == NULL)
1443
 
                return;
1444
 
 
1445
 
        switch (type) {
1446
 
        case TYPE_IDENTITY:
1447
 
                field = "IDENTITY";
1448
 
                txt = "Identity";
1449
 
                config->pending_req_identity++;
1450
 
                break;
1451
 
        case TYPE_PASSWORD:
1452
 
                field = "PASSWORD";
1453
 
                txt = "Password";
1454
 
                config->pending_req_password++;
1455
 
                break;
1456
 
        case TYPE_NEW_PASSWORD:
1457
 
                field = "NEW_PASSWORD";
1458
 
                txt = "New Password";
1459
 
                config->pending_req_new_password++;
1460
 
                break;
1461
 
        case TYPE_PIN:
1462
 
                field = "PIN";
1463
 
                txt = "PIN";
1464
 
                config->pending_req_pin++;
1465
 
                break;
1466
 
        case TYPE_OTP:
1467
 
                field = "OTP";
1468
 
                if (msg) {
1469
 
                        tmp = os_malloc(msglen + 3);
1470
 
                        if (tmp == NULL)
1471
 
                                return;
1472
 
                        tmp[0] = '[';
1473
 
                        os_memcpy(tmp + 1, msg, msglen);
1474
 
                        tmp[msglen + 1] = ']';
1475
 
                        tmp[msglen + 2] = '\0';
1476
 
                        txt = tmp;
1477
 
                        os_free(config->pending_req_otp);
1478
 
                        config->pending_req_otp = tmp;
1479
 
                        config->pending_req_otp_len = msglen + 3;
1480
 
                } else {
1481
 
                        if (config->pending_req_otp == NULL)
1482
 
                                return;
1483
 
                        txt = config->pending_req_otp;
1484
 
                }
1485
 
                break;
1486
 
        case TYPE_PASSPHRASE:
1487
 
                field = "PASSPHRASE";
1488
 
                txt = "Private key passphrase";
1489
 
                config->pending_req_passphrase++;
1490
 
                break;
1491
 
        default:
1492
 
                return;
1493
 
        }
1494
 
 
1495
 
        buflen = 100 + os_strlen(txt) + config->ssid_len;
1496
 
        buf = os_malloc(buflen);
1497
 
        if (buf == NULL)
1498
 
                return;
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) {
1503
 
                os_free(buf);
1504
 
                return;
1505
 
        }
1506
 
        if (config->ssid && buflen > len + config->ssid_len) {
1507
 
                os_memcpy(buf + len, config->ssid, config->ssid_len);
1508
 
                len += config->ssid_len;
1509
 
                buf[len] = '\0';
1510
 
        }
1511
 
        buf[buflen - 1] = '\0';
1512
 
        wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf);
1513
 
        os_free(buf);
1514
 
}
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 */
1518
 
 
1519
 
 
1520
 
/**
1521
 
 * eap_sm_request_identity - Request identity from user (ctrl_iface)
1522
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1523
 
 *
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.
1528
 
 */
1529
 
void eap_sm_request_identity(struct eap_sm *sm)
1530
 
{
1531
 
        eap_sm_request(sm, TYPE_IDENTITY, NULL, 0);
1532
 
}
1533
 
 
1534
 
 
1535
 
/**
1536
 
 * eap_sm_request_password - Request password from user (ctrl_iface)
1537
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1538
 
 *
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.
1543
 
 */
1544
 
void eap_sm_request_password(struct eap_sm *sm)
1545
 
{
1546
 
        eap_sm_request(sm, TYPE_PASSWORD, NULL, 0);
1547
 
}
1548
 
 
1549
 
 
1550
 
/**
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()
1553
 
 *
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.
1558
 
 */
1559
 
void eap_sm_request_new_password(struct eap_sm *sm)
1560
 
{
1561
 
        eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0);
1562
 
}
1563
 
 
1564
 
 
1565
 
/**
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()
1568
 
 *
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.
1573
 
 */
1574
 
void eap_sm_request_pin(struct eap_sm *sm)
1575
 
{
1576
 
        eap_sm_request(sm, TYPE_PIN, NULL, 0);
1577
 
}
1578
 
 
1579
 
 
1580
 
/**
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
1585
 
 *
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.
1589
 
 */
1590
 
void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
1591
 
{
1592
 
        eap_sm_request(sm, TYPE_OTP, msg, msg_len);
1593
 
}
1594
 
 
1595
 
 
1596
 
/**
1597
 
 * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
1598
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1599
 
 *
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.
1604
 
 */
1605
 
void eap_sm_request_passphrase(struct eap_sm *sm)
1606
 
{
1607
 
        eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0);
1608
 
}
1609
 
 
1610
 
 
1611
 
/**
1612
 
 * eap_sm_notify_ctrl_attached - Notification of attached monitor
1613
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1614
 
 *
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.
1617
 
 */
1618
 
void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
1619
 
{
1620
 
        struct wpa_ssid *config = eap_get_config(sm);
1621
 
 
1622
 
        if (config == NULL)
1623
 
                return;
1624
 
 
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);
1641
 
}
1642
 
 
1643
 
 
1644
 
static int eap_allowed_phase2_type(int vendor, int type)
1645
 
{
1646
 
        if (vendor != EAP_VENDOR_IETF)
1647
 
                return 0;
1648
 
        return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
1649
 
                type != EAP_TYPE_FAST;
1650
 
}
1651
 
 
1652
 
 
1653
 
/**
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
1658
 
 *
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.
1662
 
 */
1663
 
u32 eap_get_phase2_type(const char *name, int *vendor)
1664
 
{
1665
 
        int v;
1666
 
        u8 type = eap_peer_get_type(name, &v);
1667
 
        if (eap_allowed_phase2_type(v, type)) {
1668
 
                *vendor = v;
1669
 
                return type;
1670
 
        }
1671
 
        *vendor = EAP_VENDOR_IETF;
1672
 
        return EAP_TYPE_NONE;
1673
 
}
1674
 
 
1675
 
 
1676
 
/**
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
1681
 
 *
1682
 
 * This function generates an array of allowed EAP phase 2 (tunneled) types for
1683
 
 * the given network configuration.
1684
 
 */
1685
 
struct eap_method_type * eap_get_phase2_types(struct wpa_ssid *config,
1686
 
                                              size_t *count)
1687
 
{
1688
 
        struct eap_method_type *buf;
1689
 
        u32 method;
1690
 
        int vendor;
1691
 
        size_t mcount;
1692
 
        const struct eap_method *methods, *m;
1693
 
 
1694
 
        methods = eap_peer_get_methods(&mcount);
1695
 
        if (methods == NULL)
1696
 
                return NULL;
1697
 
        *count = 0;
1698
 
        buf = os_malloc(mcount * sizeof(struct eap_method_type));
1699
 
        if (buf == NULL)
1700
 
                return NULL;
1701
 
 
1702
 
        for (m = methods; m; m = m->next) {
1703
 
                vendor = m->vendor;
1704
 
                method = m->method;
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)
1709
 
                                continue;
1710
 
                        buf[*count].vendor = vendor;
1711
 
                        buf[*count].method = method;
1712
 
                        (*count)++;
1713
 
                }
1714
 
        }
1715
 
 
1716
 
        return buf;
1717
 
}
1718
 
 
1719
 
 
1720
 
/**
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
1724
 
 */
1725
 
void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
1726
 
{
1727
 
        sm->fast_reauth = enabled;
1728
 
}
1729
 
 
1730
 
 
1731
 
/**
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
1735
 
 */
1736
 
void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
1737
 
{
1738
 
        sm->workaround = workaround;
1739
 
}
1740
 
 
1741
 
 
1742
 
/**
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
1746
 
 *
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
1750
 
 * struct wpa_ssid.
1751
 
 */
1752
 
struct wpa_ssid * eap_get_config(struct eap_sm *sm)
1753
 
{
1754
 
        return sm->eapol_cb->get_config(sm->eapol_ctx);
1755
 
}
1756
 
 
1757
 
 
1758
 
/**
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
1763
 
 */
1764
 
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
1765
 
{
1766
 
        struct wpa_ssid *config = eap_get_config(sm);
1767
 
        if (config == NULL)
1768
 
                return NULL;
1769
 
        *len = config->identity_len;
1770
 
        return config->identity;
1771
 
}
1772
 
 
1773
 
 
1774
 
/**
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
1779
 
 */
1780
 
const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
1781
 
{
1782
 
        struct wpa_ssid *config = eap_get_config(sm);
1783
 
        if (config == NULL)
1784
 
                return NULL;
1785
 
        *len = config->password_len;
1786
 
        return config->password;
1787
 
}
1788
 
 
1789
 
 
1790
 
/**
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
1795
 
 */
1796
 
const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
1797
 
{
1798
 
        struct wpa_ssid *config = eap_get_config(sm);
1799
 
        if (config == NULL)
1800
 
                return NULL;
1801
 
        *len = config->new_password_len;
1802
 
        return config->new_password;
1803
 
}
1804
 
 
1805
 
 
1806
 
/**
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
1811
 
 */
1812
 
const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
1813
 
{
1814
 
        struct wpa_ssid *config = eap_get_config(sm);
1815
 
        if (config == NULL)
1816
 
                return NULL;
1817
 
        *len = config->otp_len;
1818
 
        return config->otp;
1819
 
}
1820
 
 
1821
 
 
1822
 
/**
1823
 
 * eap_clear_config_otp - Clear used one-time password
1824
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1825
 
 *
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
1828
 
 * needed anymore.
1829
 
 */
1830
 
void eap_clear_config_otp(struct eap_sm *sm)
1831
 
{
1832
 
        struct wpa_ssid *config = eap_get_config(sm);
1833
 
        if (config == NULL)
1834
 
                return;
1835
 
        os_memset(config->otp, 0, config->otp_len);
1836
 
        os_free(config->otp);
1837
 
        config->otp = NULL;
1838
 
        config->otp_len = 0;
1839
 
}
1840
 
 
1841
 
 
1842
 
/**
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
1846
 
 */
1847
 
int eap_key_available(struct eap_sm *sm)
1848
 
{
1849
 
        return sm ? sm->eapKeyAvailable : 0;
1850
 
}
1851
 
 
1852
 
 
1853
 
/**
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()
1856
 
 *
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).
1861
 
 */
1862
 
void eap_notify_success(struct eap_sm *sm)
1863
 
{
1864
 
        if (sm) {
1865
 
                sm->decision = DECISION_COND_SUCC;
1866
 
                sm->EAP_state = EAP_SUCCESS;
1867
 
        }
1868
 
}
1869
 
 
1870
 
 
1871
 
/**
1872
 
 * eap_notify_lower_layer_success - Notification of lower layer success
1873
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
1874
 
 *
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.
1877
 
 */
1878
 
void eap_notify_lower_layer_success(struct eap_sm *sm)
1879
 
{
1880
 
        if (sm == NULL)
1881
 
                return;
1882
 
 
1883
 
        if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
1884
 
            sm->decision == DECISION_FAIL ||
1885
 
            (sm->methodState != METHOD_MAY_CONT &&
1886
 
             sm->methodState != METHOD_DONE))
1887
 
                return;
1888
 
 
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 "
1894
 
                "layer success)");
1895
 
}
1896
 
 
1897
 
 
1898
 
/**
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
1903
 
 *
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
1907
 
 * returned data.
1908
 
 */
1909
 
const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
1910
 
{
1911
 
        if (sm == NULL || sm->eapKeyData == NULL) {
1912
 
                *len = 0;
1913
 
                return NULL;
1914
 
        }
1915
 
 
1916
 
        *len = sm->eapKeyDataLen;
1917
 
        return sm->eapKeyData;
1918
 
}
1919
 
 
1920
 
 
1921
 
/**
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
1926
 
 *
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.
1931
 
 */
1932
 
u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len)
1933
 
{
1934
 
        u8 *resp;
1935
 
 
1936
 
        if (sm == NULL || sm->eapRespData == NULL) {
1937
 
                *len = 0;
1938
 
                return NULL;
1939
 
        }
1940
 
 
1941
 
        resp = sm->eapRespData;
1942
 
        *len = sm->eapRespDataLen;
1943
 
        sm->eapRespData = NULL;
1944
 
        sm->eapRespDataLen = 0;
1945
 
 
1946
 
        return resp;
1947
 
}
1948
 
 
1949
 
 
1950
 
/**
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
1954
 
 *
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.
1957
 
 */
1958
 
void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
1959
 
{
1960
 
        if (sm)
1961
 
                sm->scard_ctx = ctx;
1962
 
}
1963
 
 
1964
 
 
1965
 
/**
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
1969
 
 *
1970
 
 * Adds a new configuration blob or replaces the current value of an existing
1971
 
 * blob.
1972
 
 */
1973
 
void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
1974
 
{
1975
 
        sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
1976
 
}
1977
 
 
1978
 
 
1979
 
/**
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
1984
 
 */
1985
 
const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
1986
 
                                                   const char *name)
1987
 
{
1988
 
        return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
1989
 
}
1990
 
 
1991
 
 
1992
 
/**
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
1996
 
 *
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).
1999
 
 */
2000
 
void eap_set_force_disabled(struct eap_sm *sm, int disabled)
2001
 
{
2002
 
        sm->force_disabled = disabled;
2003
 
}
2004
 
 
2005
 
 
2006
 
 /**
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()
2009
 
 *
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.
2014
 
 */
2015
 
void eap_notify_pending(struct eap_sm *sm)
2016
 
{
2017
 
        sm->eapol_cb->notify_pending(sm->eapol_ctx);
2018
 
}
2019
 
 
2020
 
 
2021
 
/**
2022
 
 * eap_invalidate_cached_session - Mark cached session data invalid
2023
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
2024
 
 */
2025
 
void eap_invalidate_cached_session(struct eap_sm *sm)
2026
 
{
2027
 
        if (sm)
2028
 
                eap_deinit_prev_method(sm, "invalidate");
2029
 
}