Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt)
      3  * Copyright (c) 2004-2006, Jouni Malinen <j (at) 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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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