~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to src/eap_server/eap_peap.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
 
3
 * Copyright (c) 2004-2008, 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
 
 
15
#include "includes.h"
 
16
 
 
17
#include "common.h"
 
18
#include "eap_i.h"
 
19
#include "eap_tls_common.h"
 
20
#include "eap_common/eap_tlv_common.h"
 
21
#include "tls.h"
 
22
 
 
23
 
 
24
/* Maximum supported PEAP version
 
25
 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
 
26
 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
 
27
 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
 
28
 */
 
29
#define EAP_PEAP_VERSION 1
 
30
 
 
31
 
 
32
static void eap_peap_reset(struct eap_sm *sm, void *priv);
 
33
 
 
34
 
 
35
struct eap_peap_data {
 
36
        struct eap_ssl_data ssl;
 
37
        enum {
 
38
                START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
 
39
                PHASE2_METHOD,
 
40
                PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
 
41
        } state;
 
42
 
 
43
        int peap_version;
 
44
        const struct eap_method *phase2_method;
 
45
        void *phase2_priv;
 
46
        int force_version;
 
47
        struct wpabuf *pending_phase2_resp;
 
48
};
 
49
 
 
50
 
 
51
static const char * eap_peap_state_txt(int state)
 
52
{
 
53
        switch (state) {
 
54
        case START:
 
55
                return "START";
 
56
        case PHASE1:
 
57
                return "PHASE1";
 
58
        case PHASE1_ID2:
 
59
                return "PHASE1_ID2";
 
60
        case PHASE2_START:
 
61
                return "PHASE2_START";
 
62
        case PHASE2_ID:
 
63
                return "PHASE2_ID";
 
64
        case PHASE2_METHOD:
 
65
                return "PHASE2_METHOD";
 
66
        case PHASE2_TLV:
 
67
                return "PHASE2_TLV";
 
68
        case SUCCESS_REQ:
 
69
                return "SUCCESS_REQ";
 
70
        case FAILURE_REQ:
 
71
                return "FAILURE_REQ";
 
72
        case SUCCESS:
 
73
                return "SUCCESS";
 
74
        case FAILURE:
 
75
                return "FAILURE";
 
76
        default:
 
77
                return "Unknown?!";
 
78
        }
 
79
}
 
80
 
 
81
 
 
82
static void eap_peap_state(struct eap_peap_data *data, int state)
 
83
{
 
84
        wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
 
85
                   eap_peap_state_txt(data->state),
 
86
                   eap_peap_state_txt(state));
 
87
        data->state = state;
 
88
}
 
89
 
 
90
 
 
91
static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
 
92
{
 
93
        struct wpabuf *e;
 
94
        struct eap_tlv_hdr *tlv;
 
95
 
 
96
        if (buf == NULL)
 
97
                return NULL;
 
98
 
 
99
        /* Encapsulate EAP packet in EAP-Payload TLV */
 
100
        wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
 
101
        e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
 
102
        if (e == NULL) {
 
103
                wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
 
104
                           "for TLV encapsulation");
 
105
                wpabuf_free(buf);
 
106
                return NULL;
 
107
        }
 
108
        tlv = wpabuf_put(e, sizeof(*tlv));
 
109
        tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
 
110
                                     EAP_TLV_EAP_PAYLOAD_TLV);
 
111
        tlv->length = host_to_be16(wpabuf_len(buf));
 
112
        wpabuf_put_buf(e, buf);
 
113
        wpabuf_free(buf);
 
114
        return e;
 
115
}
 
116
 
 
117
 
 
118
static EapType eap_peap_req_success(struct eap_sm *sm,
 
119
                                    struct eap_peap_data *data)
 
120
{
 
121
        if (data->state == FAILURE || data->state == FAILURE_REQ) {
 
122
                eap_peap_state(data, FAILURE);
 
123
                return EAP_TYPE_NONE;
 
124
        }
 
125
 
 
126
        if (data->peap_version == 0) {
 
127
                sm->tlv_request = TLV_REQ_SUCCESS;
 
128
                eap_peap_state(data, PHASE2_TLV);
 
129
                return EAP_TYPE_TLV;
 
130
        } else {
 
131
                eap_peap_state(data, SUCCESS_REQ);
 
132
                return EAP_TYPE_NONE;
 
133
        }
 
134
}
 
135
 
 
136
 
 
137
static EapType eap_peap_req_failure(struct eap_sm *sm,
 
138
                                    struct eap_peap_data *data)
 
139
{
 
140
        if (data->state == FAILURE || data->state == FAILURE_REQ ||
 
141
            data->state == SUCCESS_REQ ||
 
142
            (data->phase2_method &&
 
143
             data->phase2_method->method == EAP_TYPE_TLV)) {
 
144
                eap_peap_state(data, FAILURE);
 
145
                return EAP_TYPE_NONE;
 
146
        }
 
147
 
 
148
        if (data->peap_version == 0) {
 
149
                sm->tlv_request = TLV_REQ_FAILURE;
 
150
                eap_peap_state(data, PHASE2_TLV);
 
151
                return EAP_TYPE_TLV;
 
152
        } else {
 
153
                eap_peap_state(data, FAILURE_REQ);
 
154
                return EAP_TYPE_NONE;
 
155
        }
 
156
}
 
157
 
 
158
 
 
159
static void * eap_peap_init(struct eap_sm *sm)
 
160
{
 
161
        struct eap_peap_data *data;
 
162
 
 
163
        data = os_zalloc(sizeof(*data));
 
164
        if (data == NULL)
 
165
                return NULL;
 
166
        data->peap_version = EAP_PEAP_VERSION;
 
167
        data->force_version = -1;
 
168
        if (sm->user && sm->user->force_version >= 0) {
 
169
                data->force_version = sm->user->force_version;
 
170
                wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
 
171
                           data->force_version);
 
172
                data->peap_version = data->force_version;
 
173
        }
 
174
        data->state = START;
 
175
 
 
176
        if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
 
177
                wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
 
178
                eap_peap_reset(sm, data);
 
179
                return NULL;
 
180
        }
 
181
 
 
182
        return data;
 
183
}
 
184
 
 
185
 
 
186
static void eap_peap_reset(struct eap_sm *sm, void *priv)
 
187
{
 
188
        struct eap_peap_data *data = priv;
 
189
        if (data == NULL)
 
190
                return;
 
191
        if (data->phase2_priv && data->phase2_method)
 
192
                data->phase2_method->reset(sm, data->phase2_priv);
 
193
        eap_server_tls_ssl_deinit(sm, &data->ssl);
 
194
        wpabuf_free(data->pending_phase2_resp);
 
195
        os_free(data);
 
196
}
 
197
 
 
198
 
 
199
static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
 
200
                                            struct eap_peap_data *data, u8 id)
 
201
{
 
202
        struct wpabuf *req;
 
203
 
 
204
        req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
 
205
                            EAP_CODE_REQUEST, id);
 
206
        if (req == NULL) {
 
207
                wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
 
208
                           " request");
 
209
                eap_peap_state(data, FAILURE);
 
210
                return NULL;
 
211
        }
 
212
 
 
213
        wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
 
214
 
 
215
        eap_peap_state(data, PHASE1);
 
216
 
 
217
        return req;
 
218
}
 
219
 
 
220
 
 
221
static struct wpabuf * eap_peap_build_req(struct eap_sm *sm,
 
222
                                          struct eap_peap_data *data, u8 id)
 
223
{
 
224
        int res;
 
225
        struct wpabuf *req;
 
226
 
 
227
        res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_PEAP,
 
228
                                             data->peap_version, id, &req);
 
229
 
 
230
        if (data->peap_version < 2 &&
 
231
            tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
 
232
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, starting "
 
233
                           "Phase2");
 
234
                eap_peap_state(data, PHASE2_START);
 
235
        }
 
236
 
 
237
        if (res == 1)
 
238
                return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
 
239
                                                data->peap_version);
 
240
        return req;
 
241
}
 
242
 
 
243
 
 
244
static struct wpabuf * eap_peap_encrypt(struct eap_sm *sm,
 
245
                                        struct eap_peap_data *data,
 
246
                                        u8 id, const u8 *plain,
 
247
                                        size_t plain_len)
 
248
{
 
249
        int res;
 
250
        struct wpabuf *buf;
 
251
 
 
252
        /* TODO: add support for fragmentation, if needed. This will need to
 
253
         * add TLS Message Length field, if the frame is fragmented. */
 
254
        buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP,
 
255
                            1 + data->ssl.tls_out_limit,
 
256
                            EAP_CODE_REQUEST, id);
 
257
        if (buf == NULL)
 
258
                return NULL;
 
259
 
 
260
        wpabuf_put_u8(buf, data->peap_version);
 
261
 
 
262
        res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
 
263
                                     plain, plain_len, wpabuf_put(buf, 0),
 
264
                                     data->ssl.tls_out_limit);
 
265
        if (res < 0) {
 
266
                wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
 
267
                           "data");
 
268
                wpabuf_free(buf);
 
269
                return NULL;
 
270
        }
 
271
 
 
272
        wpabuf_put(buf, res);
 
273
        eap_update_len(buf);
 
274
 
 
275
        return buf;
 
276
}
 
277
 
 
278
 
 
279
static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
 
280
                                                 struct eap_peap_data *data,
 
281
                                                 u8 id)
 
282
{
 
283
        struct wpabuf *buf, *encr_req;
 
284
        const u8 *req;
 
285
        size_t req_len;
 
286
 
 
287
        buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
 
288
        if (data->peap_version >= 2 && buf)
 
289
                buf = eap_peapv2_tlv_eap_payload(buf);
 
290
        if (buf == NULL)
 
291
                return NULL;
 
292
 
 
293
        req = wpabuf_head(buf);
 
294
        req_len = wpabuf_len(buf);
 
295
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
 
296
                        req, req_len);
 
297
 
 
298
        if (data->peap_version == 0 &&
 
299
            data->phase2_method->method != EAP_TYPE_TLV) {
 
300
                req += sizeof(struct eap_hdr);
 
301
                req_len -= sizeof(struct eap_hdr);
 
302
        }
 
303
 
 
304
        encr_req = eap_peap_encrypt(sm, data, id, req, req_len);
 
305
        wpabuf_free(buf);
 
306
 
 
307
        return encr_req;
 
308
}
 
309
 
 
310
 
 
311
static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
 
312
                                                  struct eap_peap_data *data,
 
313
                                                  u8 id, int success)
 
314
{
 
315
        struct wpabuf *encr_req;
 
316
        size_t req_len;
 
317
        struct eap_hdr *hdr;
 
318
 
 
319
        req_len = sizeof(*hdr);
 
320
        hdr = os_zalloc(req_len);
 
321
        if (hdr == NULL)
 
322
                return NULL;
 
323
 
 
324
        hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
 
325
        hdr->identifier = id;
 
326
        hdr->length = host_to_be16(req_len);
 
327
 
 
328
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
 
329
                        (u8 *) hdr, req_len);
 
330
 
 
331
        encr_req = eap_peap_encrypt(sm, data, id, (u8 *) hdr, req_len);
 
332
        os_free(hdr);
 
333
 
 
334
        return encr_req;
 
335
}
 
336
 
 
337
 
 
338
static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
 
339
{
 
340
        struct eap_peap_data *data = priv;
 
341
 
 
342
        switch (data->state) {
 
343
        case START:
 
344
                return eap_peap_build_start(sm, data, id);
 
345
        case PHASE1:
 
346
        case PHASE1_ID2:
 
347
                return eap_peap_build_req(sm, data, id);
 
348
        case PHASE2_ID:
 
349
        case PHASE2_METHOD:
 
350
        case PHASE2_TLV:
 
351
                return eap_peap_build_phase2_req(sm, data, id);
 
352
        case SUCCESS_REQ:
 
353
                return eap_peap_build_phase2_term(sm, data, id, 1);
 
354
        case FAILURE_REQ:
 
355
                return eap_peap_build_phase2_term(sm, data, id, 0);
 
356
        default:
 
357
                wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
 
358
                           __func__, data->state);
 
359
                return NULL;
 
360
        }
 
361
}
 
362
 
 
363
 
 
364
static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
 
365
                              struct wpabuf *respData)
 
366
{
 
367
        const u8 *pos;
 
368
        size_t len;
 
369
 
 
370
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
 
371
        if (pos == NULL || len < 1) {
 
372
                wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
 
373
                return TRUE;
 
374
        }
 
375
 
 
376
        return FALSE;
 
377
}
 
378
 
 
379
 
 
380
static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
 
381
                                EapType eap_type)
 
382
{
 
383
        if (data->phase2_priv && data->phase2_method) {
 
384
                data->phase2_method->reset(sm, data->phase2_priv);
 
385
                data->phase2_method = NULL;
 
386
                data->phase2_priv = NULL;
 
387
        }
 
388
        data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
 
389
                                                        eap_type);
 
390
        if (!data->phase2_method)
 
391
                return -1;
 
392
 
 
393
        sm->init_phase2 = 1;
 
394
        data->phase2_priv = data->phase2_method->init(sm);
 
395
        sm->init_phase2 = 0;
 
396
        return 0;
 
397
}
 
398
 
 
399
 
 
400
static void eap_peap_process_phase2_response(struct eap_sm *sm,
 
401
                                             struct eap_peap_data *data,
 
402
                                             struct wpabuf *in_data)
 
403
{
 
404
        u8 next_type = EAP_TYPE_NONE;
 
405
        const struct eap_hdr *hdr;
 
406
        const u8 *pos;
 
407
        size_t left;
 
408
 
 
409
        if (data->phase2_priv == NULL) {
 
410
                wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
 
411
                           "initialized?!", __func__);
 
412
                return;
 
413
        }
 
414
 
 
415
        hdr = wpabuf_head(in_data);
 
416
        pos = (const u8 *) (hdr + 1);
 
417
 
 
418
        if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
 
419
                left = wpabuf_len(in_data) - sizeof(*hdr);
 
420
                wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
 
421
                            "allowed types", pos + 1, left - 1);
 
422
                eap_sm_process_nak(sm, pos + 1, left - 1);
 
423
                if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
 
424
                    sm->user->methods[sm->user_eap_method_index].method !=
 
425
                    EAP_TYPE_NONE) {
 
426
                        next_type = sm->user->methods[
 
427
                                sm->user_eap_method_index++].method;
 
428
                        wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
 
429
                                   next_type);
 
430
                } else {
 
431
                        next_type = eap_peap_req_failure(sm, data);
 
432
                }
 
433
                eap_peap_phase2_init(sm, data, next_type);
 
434
                return;
 
435
        }
 
436
 
 
437
        if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
 
438
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
 
439
                           "ignore the packet");
 
440
                return;
 
441
        }
 
442
 
 
443
        data->phase2_method->process(sm, data->phase2_priv, in_data);
 
444
 
 
445
        if (sm->method_pending == METHOD_PENDING_WAIT) {
 
446
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
 
447
                           "pending wait state - save decrypted response");
 
448
                wpabuf_free(data->pending_phase2_resp);
 
449
                data->pending_phase2_resp = wpabuf_dup(in_data);
 
450
        }
 
451
 
 
452
        if (!data->phase2_method->isDone(sm, data->phase2_priv))
 
453
                return;
 
454
 
 
455
        if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
 
456
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
 
457
                next_type = eap_peap_req_failure(sm, data);
 
458
                eap_peap_phase2_init(sm, data, next_type);
 
459
                return;
 
460
        }
 
461
 
 
462
        switch (data->state) {
 
463
        case PHASE1_ID2:
 
464
        case PHASE2_ID:
 
465
                if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
 
466
                        wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
 
467
                                          "Identity not found in the user "
 
468
                                          "database",
 
469
                                          sm->identity, sm->identity_len);
 
470
                        next_type = eap_peap_req_failure(sm, data);
 
471
                        break;
 
472
                }
 
473
 
 
474
                eap_peap_state(data, PHASE2_METHOD);
 
475
                next_type = sm->user->methods[0].method;
 
476
                sm->user_eap_method_index = 1;
 
477
                wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
 
478
                break;
 
479
        case PHASE2_METHOD:
 
480
                next_type = eap_peap_req_success(sm, data);
 
481
                break;
 
482
        case PHASE2_TLV:
 
483
                if (sm->tlv_request == TLV_REQ_SUCCESS ||
 
484
                    data->state == SUCCESS_REQ) {
 
485
                        eap_peap_state(data, SUCCESS);
 
486
                } else {
 
487
                        eap_peap_state(data, FAILURE);
 
488
                }
 
489
                break;
 
490
        case FAILURE:
 
491
                break;
 
492
        default:
 
493
                wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
 
494
                           __func__, data->state);
 
495
                break;
 
496
        }
 
497
 
 
498
        eap_peap_phase2_init(sm, data, next_type);
 
499
}
 
500
 
 
501
 
 
502
static void eap_peap_process_phase2(struct eap_sm *sm,
 
503
                                    struct eap_peap_data *data,
 
504
                                    const struct wpabuf *respData,
 
505
                                    const u8 *in_data, size_t in_len)
 
506
{
 
507
        struct wpabuf *in_decrypted;
 
508
        int len_decrypted, res;
 
509
        const struct eap_hdr *hdr;
 
510
        size_t buf_len, len;
 
511
 
 
512
        wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
 
513
                   " Phase 2", (unsigned long) in_len);
 
514
 
 
515
        if (data->pending_phase2_resp) {
 
516
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
 
517
                           "skip decryption and use old data");
 
518
                eap_peap_process_phase2_response(sm, data,
 
519
                                                 data->pending_phase2_resp);
 
520
                wpabuf_free(data->pending_phase2_resp);
 
521
                data->pending_phase2_resp = NULL;
 
522
                return;
 
523
        }
 
524
 
 
525
        /* FIX: get rid of const -> non-const typecast */
 
526
        res = eap_server_tls_data_reassemble(sm, &data->ssl, (u8 **) &in_data,
 
527
                                             &in_len);
 
528
        if (res < 0 || res == 1)
 
529
                return;
 
530
 
 
531
        buf_len = in_len;
 
532
        if (data->ssl.tls_in_total > buf_len)
 
533
                buf_len = data->ssl.tls_in_total;
 
534
        in_decrypted = wpabuf_alloc(buf_len);
 
535
        if (in_decrypted == NULL) {
 
536
                os_free(data->ssl.tls_in);
 
537
                data->ssl.tls_in = NULL;
 
538
                data->ssl.tls_in_len = 0;
 
539
                wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
 
540
                           "for decryption");
 
541
                return;
 
542
        }
 
543
 
 
544
        len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
 
545
                                               in_data, in_len,
 
546
                                               wpabuf_mhead(in_decrypted),
 
547
                                               buf_len);
 
548
        os_free(data->ssl.tls_in);
 
549
        data->ssl.tls_in = NULL;
 
550
        data->ssl.tls_in_len = 0;
 
551
        if (len_decrypted < 0) {
 
552
                wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
 
553
                           "data");
 
554
                wpabuf_free(in_decrypted);
 
555
                eap_peap_state(data, FAILURE);
 
556
                return;
 
557
        }
 
558
        wpabuf_put(in_decrypted, len_decrypted);
 
559
 
 
560
        wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
 
561
                            in_decrypted);
 
562
 
 
563
        hdr = wpabuf_head(in_decrypted);
 
564
 
 
565
        if (data->peap_version == 0 && data->state != PHASE2_TLV) {
 
566
                const struct eap_hdr *resp;
 
567
                struct eap_hdr *nhdr;
 
568
                struct wpabuf *nbuf =
 
569
                        wpabuf_alloc(sizeof(struct eap_hdr) +
 
570
                                     wpabuf_len(in_decrypted));
 
571
                if (nbuf == NULL) {
 
572
                        wpabuf_free(in_decrypted);
 
573
                        return;
 
574
                }
 
575
 
 
576
                resp = wpabuf_head(respData);
 
577
                nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
 
578
                nhdr->code = resp->code;
 
579
                nhdr->identifier = resp->identifier;
 
580
                nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
 
581
                                            wpabuf_len(in_decrypted));
 
582
                wpabuf_put_buf(nbuf, in_decrypted);
 
583
                wpabuf_free(in_decrypted);
 
584
 
 
585
                in_decrypted = nbuf;
 
586
        } else if (data->peap_version >= 2) {
 
587
                struct eap_tlv_hdr *tlv;
 
588
                struct wpabuf *nmsg;
 
589
 
 
590
                if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
 
591
                        wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
 
592
                                   "EAP TLV");
 
593
                        wpabuf_free(in_decrypted);
 
594
                        return;
 
595
                }
 
596
                tlv = wpabuf_mhead(in_decrypted);
 
597
                if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
 
598
                    EAP_TLV_EAP_PAYLOAD_TLV) {
 
599
                        wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
 
600
                        wpabuf_free(in_decrypted);
 
601
                        return;
 
602
                }
 
603
                if (sizeof(*tlv) + be_to_host16(tlv->length) >
 
604
                    wpabuf_len(in_decrypted)) {
 
605
                        wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
 
606
                                   "length");
 
607
                        wpabuf_free(in_decrypted);
 
608
                        return;
 
609
                }
 
610
                hdr = (struct eap_hdr *) (tlv + 1);
 
611
                if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
 
612
                        wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
 
613
                                   "EAP packet in EAP TLV");
 
614
                        wpabuf_free(in_decrypted);
 
615
                        return;
 
616
                }
 
617
 
 
618
                nmsg = wpabuf_alloc(be_to_host16(hdr->length));
 
619
                if (nmsg == NULL) {
 
620
                        wpabuf_free(in_decrypted);
 
621
                        return;
 
622
                }
 
623
 
 
624
                wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
 
625
                wpabuf_free(in_decrypted);
 
626
                in_decrypted = nmsg;
 
627
        }
 
628
 
 
629
        hdr = wpabuf_head(in_decrypted);
 
630
        if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
 
631
                wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
 
632
                           "EAP frame (len=%lu)",
 
633
                           (unsigned long) wpabuf_len(in_decrypted));
 
634
                wpabuf_free(in_decrypted);
 
635
                eap_peap_req_failure(sm, data);
 
636
                return;
 
637
        }
 
638
        len = be_to_host16(hdr->length);
 
639
        if (len > wpabuf_len(in_decrypted)) {
 
640
                wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
 
641
                           "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
 
642
                           (unsigned long) wpabuf_len(in_decrypted),
 
643
                           (unsigned long) len);
 
644
                wpabuf_free(in_decrypted);
 
645
                eap_peap_req_failure(sm, data);
 
646
                return;
 
647
        }
 
648
        wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
 
649
                   "identifier=%d length=%lu", hdr->code, hdr->identifier,
 
650
                   (unsigned long) len);
 
651
        switch (hdr->code) {
 
652
        case EAP_CODE_RESPONSE:
 
653
                eap_peap_process_phase2_response(sm, data, in_decrypted);
 
654
                break;
 
655
        case EAP_CODE_SUCCESS:
 
656
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
 
657
                if (data->state == SUCCESS_REQ) {
 
658
                        eap_peap_state(data, SUCCESS);
 
659
                }
 
660
                break;
 
661
        case EAP_CODE_FAILURE:
 
662
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
 
663
                eap_peap_state(data, FAILURE);
 
664
                break;
 
665
        default:
 
666
                wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
 
667
                           "Phase 2 EAP header", hdr->code);
 
668
                break;
 
669
        }
 
670
 
 
671
        os_free(in_decrypted);
 
672
}
 
673
 
 
674
 
 
675
static int eap_peapv2_start_phase2(struct eap_sm *sm,
 
676
                                   struct eap_peap_data *data)
 
677
{
 
678
        struct wpabuf *buf, *buf2;
 
679
        int res;
 
680
        u8 *tls_out;
 
681
 
 
682
        wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
 
683
                   "payload in the same message");
 
684
        eap_peap_state(data, PHASE1_ID2);
 
685
        if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
 
686
                return -1;
 
687
 
 
688
        /* TODO: which Id to use here? */
 
689
        buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
 
690
        if (buf == NULL)
 
691
                return -1;
 
692
 
 
693
        buf2 = eap_peapv2_tlv_eap_payload(buf);
 
694
        if (buf2 == NULL)
 
695
                return -1;
 
696
 
 
697
        wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
 
698
 
 
699
        buf = wpabuf_alloc(data->ssl.tls_out_limit);
 
700
        if (buf == NULL) {
 
701
                wpabuf_free(buf2);
 
702
                return -1;
 
703
        }
 
704
 
 
705
        res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
 
706
                                     wpabuf_head(buf2), wpabuf_len(buf2),
 
707
                                     wpabuf_put(buf, 0),
 
708
                                     data->ssl.tls_out_limit);
 
709
        wpabuf_free(buf2);
 
710
 
 
711
        if (res < 0) {
 
712
                wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
 
713
                           "data");
 
714
                wpabuf_free(buf);
 
715
                return -1;
 
716
        }
 
717
 
 
718
        wpabuf_put(buf, res);
 
719
        wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
 
720
                        buf);
 
721
 
 
722
        /* Append TLS data into the pending buffer after the Server Finished */
 
723
        tls_out = os_realloc(data->ssl.tls_out,
 
724
                             data->ssl.tls_out_len + wpabuf_len(buf));
 
725
        if (tls_out == NULL) {
 
726
                wpabuf_free(buf);
 
727
                return -1;
 
728
        }
 
729
 
 
730
        os_memcpy(tls_out + data->ssl.tls_out_len, wpabuf_head(buf),
 
731
                  wpabuf_len(buf));
 
732
        data->ssl.tls_out = tls_out;
 
733
        data->ssl.tls_out_len += wpabuf_len(buf);
 
734
 
 
735
        wpabuf_free(buf);
 
736
 
 
737
        return 0;
 
738
}
 
739
 
 
740
 
 
741
static void eap_peap_process(struct eap_sm *sm, void *priv,
 
742
                             struct wpabuf *respData)
 
743
{
 
744
        struct eap_peap_data *data = priv;
 
745
        const u8 *pos;
 
746
        u8 flags;
 
747
        size_t left;
 
748
        unsigned int tls_msg_len;
 
749
        int peer_version;
 
750
 
 
751
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
 
752
                               &left);
 
753
        if (pos == NULL || left < 1)
 
754
                return;
 
755
        flags = *pos++;
 
756
        left--;
 
757
        wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
 
758
                   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
 
759
                   flags);
 
760
        peer_version = flags & EAP_PEAP_VERSION_MASK;
 
761
        if (data->force_version >= 0 && peer_version != data->force_version) {
 
762
                wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
 
763
                           " version (forced=%d peer=%d) - reject",
 
764
                           data->force_version, peer_version);
 
765
                eap_peap_state(data, FAILURE);
 
766
                return;
 
767
        }
 
768
        if (peer_version < data->peap_version) {
 
769
                wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
 
770
                           "use version %d",
 
771
                           peer_version, data->peap_version, peer_version);
 
772
                data->peap_version = peer_version;
 
773
        }
 
774
        if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
 
775
                if (left < 4) {
 
776
                        wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS "
 
777
                                   "length");
 
778
                        eap_peap_state(data, FAILURE);
 
779
                        return;
 
780
                }
 
781
                tls_msg_len = WPA_GET_BE32(pos);
 
782
                wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d",
 
783
                           tls_msg_len);
 
784
                if (data->ssl.tls_in_left == 0) {
 
785
                        data->ssl.tls_in_total = tls_msg_len;
 
786
                        data->ssl.tls_in_left = tls_msg_len;
 
787
                        os_free(data->ssl.tls_in);
 
788
                        data->ssl.tls_in = NULL;
 
789
                        data->ssl.tls_in_len = 0;
 
790
                }
 
791
                pos += 4;
 
792
                left -= 4;
 
793
        }
 
794
 
 
795
        switch (data->state) {
 
796
        case PHASE1:
 
797
                if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
 
798
                    0) {
 
799
                        wpa_printf(MSG_INFO, "EAP-PEAP: TLS processing "
 
800
                                   "failed");
 
801
                        eap_peap_state(data, FAILURE);
 
802
                        break;
 
803
                }
 
804
 
 
805
                if (data->peap_version >= 2 &&
 
806
                    tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
 
807
                        if (eap_peapv2_start_phase2(sm, data)) {
 
808
                                eap_peap_state(data, FAILURE);
 
809
                                break;
 
810
                        }
 
811
                }
 
812
                break;
 
813
        case PHASE2_START:
 
814
                eap_peap_state(data, PHASE2_ID);
 
815
                eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
 
816
                break;
 
817
        case PHASE1_ID2:
 
818
        case PHASE2_ID:
 
819
        case PHASE2_METHOD:
 
820
        case PHASE2_TLV:
 
821
                eap_peap_process_phase2(sm, data, respData, pos, left);
 
822
                break;
 
823
        case SUCCESS_REQ:
 
824
                eap_peap_state(data, SUCCESS);
 
825
                break;
 
826
        case FAILURE_REQ:
 
827
                eap_peap_state(data, FAILURE);
 
828
                break;
 
829
        default:
 
830
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
 
831
                           data->state, __func__);
 
832
                break;
 
833
        }
 
834
 
 
835
        if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
 
836
                wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
 
837
                           "in TLS processing");
 
838
                eap_peap_state(data, FAILURE);
 
839
        }
 
840
}
 
841
 
 
842
 
 
843
static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
 
844
{
 
845
        struct eap_peap_data *data = priv;
 
846
        return data->state == SUCCESS || data->state == FAILURE;
 
847
}
 
848
 
 
849
 
 
850
static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
 
851
{
 
852
        struct eap_peap_data *data = priv;
 
853
        u8 *eapKeyData;
 
854
 
 
855
        if (data->state != SUCCESS)
 
856
                return NULL;
 
857
 
 
858
        /* TODO: PEAPv1 - different label in some cases */
 
859
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
 
860
                                               "client EAP encryption",
 
861
                                               EAP_TLS_KEY_LEN);
 
862
        if (eapKeyData) {
 
863
                *len = EAP_TLS_KEY_LEN;
 
864
                wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
 
865
                            eapKeyData, EAP_TLS_KEY_LEN);
 
866
        } else {
 
867
                wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
 
868
        }
 
869
 
 
870
        return eapKeyData;
 
871
}
 
872
 
 
873
 
 
874
static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
 
875
{
 
876
        struct eap_peap_data *data = priv;
 
877
        return data->state == SUCCESS;
 
878
}
 
879
 
 
880
 
 
881
int eap_server_peap_register(void)
 
882
{
 
883
        struct eap_method *eap;
 
884
        int ret;
 
885
 
 
886
        eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
 
887
                                      EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
 
888
        if (eap == NULL)
 
889
                return -1;
 
890
 
 
891
        eap->init = eap_peap_init;
 
892
        eap->reset = eap_peap_reset;
 
893
        eap->buildReq = eap_peap_buildReq;
 
894
        eap->check = eap_peap_check;
 
895
        eap->process = eap_peap_process;
 
896
        eap->isDone = eap_peap_isDone;
 
897
        eap->getKey = eap_peap_getKey;
 
898
        eap->isSuccess = eap_peap_isSuccess;
 
899
 
 
900
        ret = eap_server_method_register(eap);
 
901
        if (ret)
 
902
                eap_server_method_free(eap);
 
903
        return ret;
 
904
}