1 /*
2 * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt)
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
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19 #include "eap_tls_common.h"
20 #include "config_ssid.h"
21 #include "tls.h"
22 #include "eap_tlv.h"
23
24
25 /* Maximum supported PEAP version
26 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
27 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
28 * 2 = draft-josefsson-ppext-eap-tls-eap-07.txt
29 */
30 #define EAP_PEAP_VERSION 1
31
32
33 static void eap_peap_deinit(struct eap_sm *sm, void *priv);
34
35
36 struct eap_peap_data {
37 struct eap_ssl_data ssl;
38
39 int peap_version, force_peap_version, force_new_label;
40
41 const struct eap_method *phase2_method;
42 void *phase2_priv;
43 int phase2_success;
44 int phase2_eap_success;
45 int phase2_eap_started;
46
47 struct eap_method_type phase2_type;
48 struct eap_method_type *phase2_types;
49 size_t num_phase2_types;
50
51 int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner
52 * EAP-Success
53 * 1 = reply with tunneled EAP-Success to inner
54 * EAP-Success and expect AS to send outer
55 * (unencrypted) EAP-Success after this
56 * 2 = reply with PEAP/TLS ACK to inner
57 * EAP-Success and expect AS to send outer
58 * (unencrypted) EAP-Success after this */
59 int resuming; /* starting a resumed session */
60 u8 *key_data;
61
62 u8 *pending_phase2_req;
63 size_t pending_phase2_req_len;
64 };
65
66
eap_peap_init(struct eap_sm * sm)67 static void * eap_peap_init(struct eap_sm *sm)
68 {
69 struct eap_peap_data *data;
70 struct wpa_ssid *config = eap_get_config(sm);
71
72 data = os_zalloc(sizeof(*data));
73 if (data == NULL)
74 return NULL;
75 sm->peap_done = FALSE;
76 data->peap_version = EAP_PEAP_VERSION;
77 data->force_peap_version = -1;
78 data->peap_outer_success = 2;
79
80 if (config && config->phase1) {
81 char *pos = os_strstr(config->phase1, "peapver=");
82 if (pos) {
83 data->force_peap_version = atoi(pos + 8);
84 data->peap_version = data->force_peap_version;
85 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version "
86 "%d", data->force_peap_version);
87 }
88
89 if (os_strstr(config->phase1, "peaplabel=1")) {
90 data->force_new_label = 1;
91 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for "
92 "key derivation");
93 }
94
95 if (os_strstr(config->phase1, "peap_outer_success=0")) {
96 data->peap_outer_success = 0;
97 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate "
98 "authentication on tunneled EAP-Success");
99 } else if (os_strstr(config->phase1, "peap_outer_success=1")) {
100 data->peap_outer_success = 1;
101 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled "
102 "EAP-Success after receiving tunneled "
103 "EAP-Success");
104 } else if (os_strstr(config->phase1, "peap_outer_success=2")) {
105 data->peap_outer_success = 2;
106 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK "
107 "after receiving tunneled EAP-Success");
108 }
109 }
110
111 if (config && config->phase2) {
112 char *start, *pos, *buf;
113 struct eap_method_type *methods = NULL, *_methods;
114 u8 method;
115 size_t num_methods = 0;
116 start = buf = os_strdup(config->phase2);
117 if (buf == NULL) {
118 eap_peap_deinit(sm, data);
119 return NULL;
120 }
121 while (start && *start != '\0') {
122 int vendor;
123 pos = os_strstr(start, "auth=");
124 if (pos == NULL)
125 break;
126 if (start != pos && *(pos - 1) != ' ') {
127 start = pos + 5;
128 continue;
129 }
130
131 start = pos + 5;
132 pos = os_strchr(start, ' ');
133 if (pos)
134 *pos++ = '\0';
135 method = eap_get_phase2_type(start, &vendor);
136 if (vendor == EAP_VENDOR_IETF &&
137 method == EAP_TYPE_NONE) {
138 wpa_printf(MSG_ERROR, "EAP-PEAP: Unsupported "
139 "Phase2 method '%s'", start);
140 } else {
141 num_methods++;
142 _methods = os_realloc(
143 methods,
144 num_methods * sizeof(*methods));
145 if (_methods == NULL) {
146 os_free(methods);
147 os_free(buf);
148 eap_peap_deinit(sm, data);
149 return NULL;
150 }
151 methods = _methods;
152 methods[num_methods - 1].vendor = vendor;
153 methods[num_methods - 1].method = method;
154 }
155
156 start = pos;
157 }
158 os_free(buf);
159 data->phase2_types = methods;
160 data->num_phase2_types = num_methods;
161 }
162 if (data->phase2_types == NULL) {
163 data->phase2_types =
164 eap_get_phase2_types(config, &data->num_phase2_types);
165 }
166 if (data->phase2_types == NULL) {
167 wpa_printf(MSG_ERROR, "EAP-PEAP: No Phase2 method available");
168 eap_peap_deinit(sm, data);
169 return NULL;
170 }
171 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 EAP types",
172 (u8 *) data->phase2_types,
173 data->num_phase2_types * sizeof(struct eap_method_type));
174 data->phase2_type.vendor = EAP_VENDOR_IETF;
175 data->phase2_type.method = EAP_TYPE_NONE;
176
177 if (eap_tls_ssl_init(sm, &data->ssl, config)) {
178 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
179 eap_peap_deinit(sm, data);
180 return NULL;
181 }
182
183 return data;
184 }
185
186
eap_peap_deinit(struct eap_sm * sm,void * priv)187 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
188 {
189 struct eap_peap_data *data = priv;
190 if (data == NULL)
191 return;
192 if (data->phase2_priv && data->phase2_method)
193 data->phase2_method->deinit(sm, data->phase2_priv);
194 os_free(data->phase2_types);
195 eap_tls_ssl_deinit(sm, &data->ssl);
196 os_free(data->key_data);
197 os_free(data->pending_phase2_req);
198 os_free(data);
199 }
200
201
eap_peap_encrypt(struct eap_sm * sm,struct eap_peap_data * data,int id,const u8 * plain,size_t plain_len,u8 ** out_data,size_t * out_len)202 static int eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data,
203 int id, const u8 *plain, size_t plain_len,
204 u8 **out_data, size_t *out_len)
205 {
206 int res;
207 u8 *pos;
208 struct eap_hdr *resp;
209
210 /* TODO: add support for fragmentation, if needed. This will need to
211 * add TLS Message Length field, if the frame is fragmented.
212 * Note: Microsoft IAS did not seem to like TLS Message Length with
213 * PEAP/MSCHAPv2. */
214 resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
215 if (resp == NULL)
216 return -1;
217
218 resp->code = EAP_CODE_RESPONSE;
219 resp->identifier = id;
220
221 pos = (u8 *) (resp + 1);
222 *pos++ = EAP_TYPE_PEAP;
223 *pos++ = data->peap_version;
224
225 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
226 plain, plain_len,
227 pos, data->ssl.tls_out_limit);
228 if (res < 0) {
229 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
230 "data");
231 os_free(resp);
232 return -1;
233 }
234
235 *out_len = sizeof(struct eap_hdr) + 2 + res;
236 resp->length = host_to_be16(*out_len);
237 *out_data = (u8 *) resp;
238 return 0;
239 }
240
241
eap_peap_phase2_nak(struct eap_peap_data * data,struct eap_hdr * hdr,u8 ** resp,size_t * resp_len)242 static int eap_peap_phase2_nak(struct eap_peap_data *data, struct eap_hdr *hdr,
243 u8 **resp, size_t *resp_len)
244 {
245 struct eap_hdr *resp_hdr;
246 u8 *pos = (u8 *) (hdr + 1);
247 size_t i;
248
249 /* TODO: add support for expanded Nak */
250 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: Nak type=%d", *pos);
251 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Allowed Phase2 EAP types",
252 (u8 *) data->phase2_types,
253 data->num_phase2_types * sizeof(struct eap_method_type));
254 *resp_len = sizeof(struct eap_hdr) + 1;
255 *resp = os_malloc(*resp_len + data->num_phase2_types);
256 if (*resp == NULL)
257 return -1;
258
259 resp_hdr = (struct eap_hdr *) (*resp);
260 resp_hdr->code = EAP_CODE_RESPONSE;
261 resp_hdr->identifier = hdr->identifier;
262 pos = (u8 *) (resp_hdr + 1);
263 *pos++ = EAP_TYPE_NAK;
264 for (i = 0; i < data->num_phase2_types; i++) {
265 if (data->phase2_types[i].vendor == EAP_VENDOR_IETF &&
266 data->phase2_types[i].method < 256) {
267 (*resp_len)++;
268 *pos++ = data->phase2_types[i].method;
269 }
270 }
271 resp_hdr->length = host_to_be16(*resp_len);
272
273 return 0;
274 }
275
276
eap_peap_phase2_request(struct eap_sm * sm,struct eap_peap_data * data,struct eap_method_ret * ret,struct eap_hdr * hdr,u8 ** resp,size_t * resp_len)277 static int eap_peap_phase2_request(struct eap_sm *sm,
278 struct eap_peap_data *data,
279 struct eap_method_ret *ret,
280 struct eap_hdr *hdr,
281 u8 **resp, size_t *resp_len)
282 {
283 size_t len = be_to_host16(hdr->length);
284 u8 *pos;
285 struct eap_method_ret iret;
286 struct wpa_ssid *config = eap_get_config(sm);
287
288 if (len <= sizeof(struct eap_hdr)) {
289 wpa_printf(MSG_INFO, "EAP-PEAP: too short "
290 "Phase 2 request (len=%lu)", (unsigned long) len);
291 return -1;
292 }
293 pos = (u8 *) (hdr + 1);
294 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
295 switch (*pos) {
296 case EAP_TYPE_IDENTITY:
297 *resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);
298 break;
299 case EAP_TYPE_TLV:
300 os_memset(&iret, 0, sizeof(iret));
301 if (eap_tlv_process(sm, &iret, hdr, resp, resp_len,
302 data->phase2_eap_started &&
303 !data->phase2_eap_success)) {
304 ret->methodState = METHOD_DONE;
305 ret->decision = DECISION_FAIL;
306 return -1;
307 }
308 if (iret.methodState == METHOD_DONE ||
309 iret.methodState == METHOD_MAY_CONT) {
310 ret->methodState = iret.methodState;
311 ret->decision = iret.decision;
312 data->phase2_success = 1;
313 }
314 break;
315 default:
316 if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
317 data->phase2_type.method == EAP_TYPE_NONE) {
318 size_t i;
319 for (i = 0; i < data->num_phase2_types; i++) {
320 if (data->phase2_types[i].vendor !=
321 EAP_VENDOR_IETF ||
322 data->phase2_types[i].method != *pos)
323 continue;
324
325 data->phase2_type.vendor =
326 data->phase2_types[i].vendor;
327 data->phase2_type.method =
328 data->phase2_types[i].method;
329 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
330 "Phase 2 EAP vendor %d method %d",
331 data->phase2_type.vendor,
332 data->phase2_type.method);
333 break;
334 }
335 }
336 if (*pos != data->phase2_type.method ||
337 *pos == EAP_TYPE_NONE) {
338 if (eap_peap_phase2_nak(data, hdr, resp, resp_len))
339 return -1;
340 return 0;
341 }
342
343 if (data->phase2_priv == NULL) {
344 data->phase2_method = eap_sm_get_eap_methods(
345 data->phase2_type.vendor,
346 data->phase2_type.method);
347 if (data->phase2_method) {
348 sm->init_phase2 = 1;
349 data->phase2_priv =
350 data->phase2_method->init(sm);
351 sm->init_phase2 = 0;
352 }
353 }
354 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
355 wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize "
356 "Phase 2 EAP method %d", *pos);
357 ret->methodState = METHOD_DONE;
358 ret->decision = DECISION_FAIL;
359 return -1;
360 }
361 data->phase2_eap_started = 1;
362 os_memset(&iret, 0, sizeof(iret));
363 *resp = data->phase2_method->process(sm, data->phase2_priv,
364 &iret, (u8 *) hdr, len,
365 resp_len);
366 if ((iret.methodState == METHOD_DONE ||
367 iret.methodState == METHOD_MAY_CONT) &&
368 (iret.decision == DECISION_UNCOND_SUCC ||
369 iret.decision == DECISION_COND_SUCC)) {
370 data->phase2_eap_success = 1;
371 data->phase2_success = 1;
372 }
373 break;
374 }
375
376 if (*resp == NULL &&
377 (config->pending_req_identity || config->pending_req_password ||
378 config->pending_req_otp || config->pending_req_new_password)) {
379 os_free(data->pending_phase2_req);
380 data->pending_phase2_req = os_malloc(len);
381 if (data->pending_phase2_req) {
382 os_memcpy(data->pending_phase2_req, hdr, len);
383 data->pending_phase2_req_len = len;
384 }
385 }
386
387 return 0;
388 }
389
390
eap_peap_decrypt(struct eap_sm * sm,struct eap_peap_data * data,struct eap_method_ret * ret,const struct eap_hdr * req,const u8 * in_data,size_t in_len,u8 ** out_data,size_t * out_len)391 static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
392 struct eap_method_ret *ret,
393 const struct eap_hdr *req,
394 const u8 *in_data, size_t in_len,
395 u8 **out_data, size_t *out_len)
396 {
397 u8 *in_decrypted;
398 int res, skip_change = 0;
399 struct eap_hdr *hdr, *rhdr;
400 u8 *resp = NULL;
401 size_t resp_len, len_decrypted, len, buf_len;
402 const u8 *msg;
403 size_t msg_len;
404 int need_more_input;
405
406 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
407 " Phase 2", (unsigned long) in_len);
408
409 if (data->pending_phase2_req) {
410 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
411 "skip decryption and use old data");
412 /* Clear TLS reassembly state. */
413 os_free(data->ssl.tls_in);
414 data->ssl.tls_in = NULL;
415 data->ssl.tls_in_len = 0;
416 data->ssl.tls_in_left = 0;
417 data->ssl.tls_in_total = 0;
418 in_decrypted = data->pending_phase2_req;
419 data->pending_phase2_req = NULL;
420 len_decrypted = data->pending_phase2_req_len;
421 skip_change = 1;
422 goto continue_req;
423 }
424
425 msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len,
426 &msg_len, &need_more_input);
427 if (msg == NULL)
428 return need_more_input ? 1 : -1;
429
430 if (in_len == 0 && sm->workaround && data->phase2_success) {
431 /*
432 * Cisco ACS seems to be using TLS ACK to terminate
433 * EAP-PEAPv0/GTC. Try to reply with TLS ACK.
434 */
435 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
436 "expected data - acknowledge with TLS ACK since "
437 "Phase 2 has been completed");
438 ret->decision = DECISION_COND_SUCC;
439 ret->methodState = METHOD_DONE;
440 return 1;
441 }
442
443 buf_len = in_len;
444 if (data->ssl.tls_in_total > buf_len)
445 buf_len = data->ssl.tls_in_total;
446 in_decrypted = os_malloc(buf_len);
447 if (in_decrypted == NULL) {
448 os_free(data->ssl.tls_in);
449 data->ssl.tls_in = NULL;
450 data->ssl.tls_in_len = 0;
451 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
452 "for decryption");
453 return -1;
454 }
455
456 res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
457 msg, msg_len, in_decrypted, buf_len);
458 os_free(data->ssl.tls_in);
459 data->ssl.tls_in = NULL;
460 data->ssl.tls_in_len = 0;
461 if (res < 0) {
462 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
463 "data");
464 os_free(in_decrypted);
465 return 0;
466 }
467 len_decrypted = res;
468
469 continue_req:
470 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted,
471 len_decrypted);
472
473 hdr = (struct eap_hdr *) in_decrypted;
474 if (len_decrypted == 5 && hdr->code == EAP_CODE_REQUEST &&
475 be_to_host16(hdr->length) == 5 &&
476 in_decrypted[4] == EAP_TYPE_IDENTITY) {
477 /* At least FreeRADIUS seems to send full EAP header with
478 * EAP Request Identity */
479 skip_change = 1;
480 }
481 if (len_decrypted >= 5 && hdr->code == EAP_CODE_REQUEST &&
482 in_decrypted[4] == EAP_TYPE_TLV) {
483 skip_change = 1;
484 }
485
486 if (data->peap_version == 0 && !skip_change) {
487 struct eap_hdr *nhdr = os_malloc(sizeof(struct eap_hdr) +
488 len_decrypted);
489 if (nhdr == NULL) {
490 os_free(in_decrypted);
491 return 0;
492 }
493 os_memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted);
494 os_free(in_decrypted);
495 nhdr->code = req->code;
496 nhdr->identifier = req->identifier;
497 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
498 len_decrypted);
499
500 len_decrypted += sizeof(struct eap_hdr);
501 in_decrypted = (u8 *) nhdr;
502 }
503 hdr = (struct eap_hdr *) in_decrypted;
504 if (len_decrypted < sizeof(*hdr)) {
505 os_free(in_decrypted);
506 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
507 "EAP frame (len=%lu)",
508 (unsigned long) len_decrypted);
509 return 0;
510 }
511 len = be_to_host16(hdr->length);
512 if (len > len_decrypted) {
513 os_free(in_decrypted);
514 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
515 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
516 (unsigned long) len_decrypted, (unsigned long) len);
517 return 0;
518 }
519 if (len < len_decrypted) {
520 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
521 "shorter length than full decrypted data "
522 "(%lu < %lu)",
523 (unsigned long) len, (unsigned long) len_decrypted);
524 if (sm->workaround && len == 4 && len_decrypted == 5 &&
525 in_decrypted[4] == EAP_TYPE_IDENTITY) {
526 /* Radiator 3.9 seems to set Phase 2 EAP header to use
527 * incorrect length for the EAP-Request Identity
528 * packet, so fix the inner header to interoperate..
529 * This was fixed in 2004-06-23 patch for Radiator and
530 * this workaround can be removed at some point. */
531 wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace "
532 "Phase 2 EAP header len (%lu) with real "
533 "decrypted len (%lu)",
534 (unsigned long) len,
535 (unsigned long) len_decrypted);
536 len = len_decrypted;
537 hdr->length = host_to_be16(len);
538 }
539 }
540 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
541 "identifier=%d length=%lu", hdr->code, hdr->identifier,
542 (unsigned long) len);
543 switch (hdr->code) {
544 case EAP_CODE_REQUEST:
545 if (eap_peap_phase2_request(sm, data, ret, hdr,
546 &resp, &resp_len)) {
547 os_free(in_decrypted);
548 wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
549 "processing failed");
550 return 0;
551 }
552 break;
553 case EAP_CODE_SUCCESS:
554 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
555 if (data->peap_version == 1) {
556 /* EAP-Success within TLS tunnel is used to indicate
557 * shutdown of the TLS channel. The authentication has
558 * been completed. */
559 if (data->phase2_eap_started &&
560 !data->phase2_eap_success) {
561 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
562 "Success used to indicate success, "
563 "but Phase 2 EAP was not yet "
564 "completed successfully");
565 ret->methodState = METHOD_DONE;
566 ret->decision = DECISION_FAIL;
567 os_free(in_decrypted);
568 return 0;
569 }
570 wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
571 "EAP-Success within TLS tunnel - "
572 "authentication completed");
573 ret->decision = DECISION_UNCOND_SUCC;
574 ret->methodState = METHOD_DONE;
575 data->phase2_success = 1;
576 if (data->peap_outer_success == 2) {
577 os_free(in_decrypted);
578 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
579 "to finish authentication");
580 return 1;
581 } else if (data->peap_outer_success == 1) {
582 /* Reply with EAP-Success within the TLS
583 * channel to complete the authentication. */
584 resp_len = sizeof(struct eap_hdr);
585 resp = os_zalloc(resp_len);
586 if (resp) {
587 rhdr = (struct eap_hdr *) resp;
588 rhdr->code = EAP_CODE_SUCCESS;
589 rhdr->identifier = hdr->identifier;
590 rhdr->length = host_to_be16(resp_len);
591 }
592 } else {
593 /* No EAP-Success expected for Phase 1 (outer,
594 * unencrypted auth), so force EAP state
595 * machine to SUCCESS state. */
596 sm->peap_done = TRUE;
597 }
598 } else {
599 /* FIX: ? */
600 }
601 break;
602 case EAP_CODE_FAILURE:
603 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
604 ret->decision = DECISION_FAIL;
605 ret->methodState = METHOD_MAY_CONT;
606 ret->allowNotifications = FALSE;
607 /* Reply with EAP-Failure within the TLS channel to complete
608 * failure reporting. */
609 resp_len = sizeof(struct eap_hdr);
610 resp = os_zalloc(resp_len);
611 if (resp) {
612 rhdr = (struct eap_hdr *) resp;
613 rhdr->code = EAP_CODE_FAILURE;
614 rhdr->identifier = hdr->identifier;
615 rhdr->length = host_to_be16(resp_len);
616 }
617 break;
618 default:
619 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
620 "Phase 2 EAP header", hdr->code);
621 break;
622 }
623
624 os_free(in_decrypted);
625
626 if (resp) {
627 u8 *resp_pos;
628 size_t resp_send_len;
629 int skip_change2 = 0;
630
631 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
632 resp, resp_len);
633 /* PEAP version changes */
634 if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE &&
635 resp[4] == EAP_TYPE_TLV)
636 skip_change2 = 1;
637 if (data->peap_version == 0 && !skip_change2) {
638 resp_pos = resp + sizeof(struct eap_hdr);
639 resp_send_len = resp_len - sizeof(struct eap_hdr);
640 } else {
641 resp_pos = resp;
642 resp_send_len = resp_len;
643 }
644
645 if (eap_peap_encrypt(sm, data, req->identifier,
646 resp_pos, resp_send_len,
647 out_data, out_len)) {
648 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
649 "a Phase 2 frame");
650 }
651 os_free(resp);
652 }
653
654 return 0;
655 }
656
657
eap_peap_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const u8 * reqData,size_t reqDataLen,size_t * respDataLen)658 static u8 * eap_peap_process(struct eap_sm *sm, void *priv,
659 struct eap_method_ret *ret,
660 const u8 *reqData, size_t reqDataLen,
661 size_t *respDataLen)
662 {
663 const struct eap_hdr *req;
664 size_t left;
665 int res;
666 u8 flags, *resp, id;
667 const u8 *pos;
668 struct eap_peap_data *data = priv;
669
670 pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
671 reqData, reqDataLen, &left, &flags);
672 if (pos == NULL)
673 return NULL;
674 req = (const struct eap_hdr *) reqData;
675 id = req->identifier;
676
677 if (flags & EAP_TLS_FLAGS_START) {
678 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
679 "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
680 data->peap_version);
681 if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)
682 data->peap_version = flags & EAP_PEAP_VERSION_MASK;
683 if (data->force_peap_version >= 0 &&
684 data->force_peap_version != data->peap_version) {
685 wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
686 "forced PEAP version %d",
687 data->force_peap_version);
688 ret->methodState = METHOD_DONE;
689 ret->decision = DECISION_FAIL;
690 ret->allowNotifications = FALSE;
691 return NULL;
692 }
693 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
694 data->peap_version);
695 left = 0; /* make sure that this frame is empty, even though it
696 * should always be, anyway */
697 }
698
699 resp = NULL;
700 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
701 !data->resuming) {
702 res = eap_peap_decrypt(sm, data, ret, req, pos, left,
703 &resp, respDataLen);
704 } else {
705 res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP,
706 data->peap_version, id, pos, left,
707 &resp, respDataLen);
708
709 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
710 char *label;
711 wpa_printf(MSG_DEBUG,
712 "EAP-PEAP: TLS done, proceed to Phase 2");
713 os_free(data->key_data);
714 /* draft-josefsson-ppext-eap-tls-eap-05.txt
715 * specifies that PEAPv1 would use "client PEAP
716 * encryption" as the label. However, most existing
717 * PEAPv1 implementations seem to be using the old
718 * label, "client EAP encryption", instead. Use the old
719 * label by default, but allow it to be configured with
720 * phase1 parameter peaplabel=1. */
721 if (data->peap_version > 1 || data->force_new_label)
722 label = "client PEAP encryption";
723 else
724 label = "client EAP encryption";
725 wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
726 "key derivation", label);
727 data->key_data =
728 eap_tls_derive_key(sm, &data->ssl, label,
729 EAP_TLS_KEY_LEN);
730 if (data->key_data) {
731 wpa_hexdump_key(MSG_DEBUG,
732 "EAP-PEAP: Derived key",
733 data->key_data,
734 EAP_TLS_KEY_LEN);
735 } else {
736 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
737 "derive key");
738 }
739
740 if (sm->workaround && data->resuming) {
741 /*
742 * At least few RADIUS servers (Aegis v1.1.6;
743 * but not v1.1.4; and Cisco ACS) seem to be
744 * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco
745 * ACS) session resumption with outer
746 * EAP-Success. This does not seem to follow
747 * draft-josefsson-pppext-eap-tls-eap-05.txt
748 * section 4.2, so only allow this if EAP
749 * workarounds are enabled.
750 */
751 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
752 "allow outer EAP-Success to "
753 "terminate PEAP resumption");
754 ret->decision = DECISION_COND_SUCC;
755 data->phase2_success = 1;
756 }
757
758 data->resuming = 0;
759 }
760
761 if (res == 2) {
762 /*
763 * Application data included in the handshake message.
764 */
765 os_free(data->pending_phase2_req);
766 data->pending_phase2_req = resp;
767 data->pending_phase2_req_len = *respDataLen;
768 resp = NULL;
769 *respDataLen = 0;
770 res = eap_peap_decrypt(sm, data, ret, req, pos, left,
771 &resp, respDataLen);
772 }
773 }
774
775 if (ret->methodState == METHOD_DONE) {
776 ret->allowNotifications = FALSE;
777 }
778
779 if (res == 1) {
780 return eap_tls_build_ack(&data->ssl, respDataLen, id,
781 EAP_TYPE_PEAP, data->peap_version);
782 }
783
784 return resp;
785 }
786
787
eap_peap_has_reauth_data(struct eap_sm * sm,void * priv)788 static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
789 {
790 struct eap_peap_data *data = priv;
791 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
792 data->phase2_success;
793 }
794
795
eap_peap_deinit_for_reauth(struct eap_sm * sm,void * priv)796 static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
797 {
798 struct eap_peap_data *data = priv;
799 os_free(data->pending_phase2_req);
800 data->pending_phase2_req = NULL;
801 }
802
803
eap_peap_init_for_reauth(struct eap_sm * sm,void * priv)804 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
805 {
806 struct eap_peap_data *data = priv;
807 os_free(data->key_data);
808 data->key_data = NULL;
809 if (eap_tls_reauth_init(sm, &data->ssl)) {
810 os_free(data);
811 return NULL;
812 }
813 if (data->phase2_priv && data->phase2_method &&
814 data->phase2_method->init_for_reauth)
815 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
816 data->phase2_success = 0;
817 data->phase2_eap_success = 0;
818 data->phase2_eap_started = 0;
819 data->resuming = 1;
820 sm->peap_done = FALSE;
821 return priv;
822 }
823
824
eap_peap_get_status(struct eap_sm * sm,void * priv,char * buf,size_t buflen,int verbose)825 static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
826 size_t buflen, int verbose)
827 {
828 struct eap_peap_data *data = priv;
829 int len, ret;
830
831 len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
832 if (data->phase2_method) {
833 ret = os_snprintf(buf + len, buflen - len,
834 "EAP-PEAPv%d Phase2 method=%s\n",
835 data->peap_version,
836 data->phase2_method->name);
837 if (ret < 0 || (size_t) ret >= buflen - len)
838 return len;
839 len += ret;
840 }
841 return len;
842 }
843
844
eap_peap_isKeyAvailable(struct eap_sm * sm,void * priv)845 static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
846 {
847 struct eap_peap_data *data = priv;
848 return data->key_data != NULL && data->phase2_success;
849 }
850
851
eap_peap_getKey(struct eap_sm * sm,void * priv,size_t * len)852 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
853 {
854 struct eap_peap_data *data = priv;
855 u8 *key;
856
857 if (data->key_data == NULL || !data->phase2_success)
858 return NULL;
859
860 key = os_malloc(EAP_TLS_KEY_LEN);
861 if (key == NULL)
862 return NULL;
863
864 *len = EAP_TLS_KEY_LEN;
865 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
866
867 return key;
868 }
869
870
eap_peer_peap_register(void)871 int eap_peer_peap_register(void)
872 {
873 struct eap_method *eap;
874 int ret;
875
876 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
877 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
878 if (eap == NULL)
879 return -1;
880
881 eap->init = eap_peap_init;
882 eap->deinit = eap_peap_deinit;
883 eap->process = eap_peap_process;
884 eap->isKeyAvailable = eap_peap_isKeyAvailable;
885 eap->getKey = eap_peap_getKey;
886 eap->get_status = eap_peap_get_status;
887 eap->has_reauth_data = eap_peap_has_reauth_data;
888 eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
889 eap->init_for_reauth = eap_peap_init_for_reauth;
890
891 ret = eap_peer_method_register(eap);
892 if (ret)
893 eap_peer_method_free(eap);
894 return ret;
895 }
896