• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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