⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap_peap.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		data->ssl.tls_in = NULL;		data->ssl.tls_in_len = 0;		wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "			   "for decryption");		return -1;	}	res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,				     msg, msg_len, in_decrypted, buf_len);	os_free(data->ssl.tls_in);	data->ssl.tls_in = NULL;	data->ssl.tls_in_len = 0;	if (res < 0) {		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "			   "data");		os_free(in_decrypted);		return 0;	}	len_decrypted = res;continue_req:	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted,		    len_decrypted);	hdr = (struct eap_hdr *) in_decrypted;	if (len_decrypted == 5 && hdr->code == EAP_CODE_REQUEST &&	    be_to_host16(hdr->length) == 5 &&	    in_decrypted[4] == EAP_TYPE_IDENTITY) {		/* At least FreeRADIUS seems to send full EAP header with		 * EAP Request Identity */		skip_change = 1;	}	if (len_decrypted >= 5 && hdr->code == EAP_CODE_REQUEST &&	    in_decrypted[4] == EAP_TYPE_TLV) {		skip_change = 1;	}	if (data->peap_version == 0 && !skip_change) {		struct eap_hdr *nhdr = os_malloc(sizeof(struct eap_hdr) +						 len_decrypted);		if (nhdr == NULL) {			os_free(in_decrypted);			return 0;		}		os_memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted);		os_free(in_decrypted);		nhdr->code = req->code;		nhdr->identifier = req->identifier;		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +					    len_decrypted);		len_decrypted += sizeof(struct eap_hdr);		in_decrypted = (u8 *) nhdr;	}	hdr = (struct eap_hdr *) in_decrypted;	if (len_decrypted < sizeof(*hdr)) {		os_free(in_decrypted);		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "			   "EAP frame (len=%lu)",			   (unsigned long) len_decrypted);		return 0;	}	len = be_to_host16(hdr->length);	if (len > len_decrypted) {		os_free(in_decrypted);		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",			   (unsigned long) len_decrypted, (unsigned long) len);		return 0;	}	if (len < len_decrypted) {		wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "			   "shorter length than full decrypted data "			   "(%lu < %lu)",			   (unsigned long) len, (unsigned long) len_decrypted);		if (sm->workaround && len == 4 && len_decrypted == 5 &&		    in_decrypted[4] == EAP_TYPE_IDENTITY) {			/* Radiator 3.9 seems to set Phase 2 EAP header to use			 * incorrect length for the EAP-Request Identity			 * packet, so fix the inner header to interoperate..			 * This was fixed in 2004-06-23 patch for Radiator and			 * this workaround can be removed at some point. */			wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace "				   "Phase 2 EAP header len (%lu) with real "				   "decrypted len (%lu)",				   (unsigned long) len,				   (unsigned long) len_decrypted);			len = len_decrypted;			hdr->length = host_to_be16(len);		}	}	wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "		   "identifier=%d length=%lu", hdr->code, hdr->identifier,		   (unsigned long) len);	switch (hdr->code) {	case EAP_CODE_REQUEST:		if (eap_peap_phase2_request(sm, data, ret, hdr,					    &resp, &resp_len)) {			os_free(in_decrypted);			wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "				   "processing failed");			return 0;		}		break;	case EAP_CODE_SUCCESS:		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");		if (data->peap_version == 1) {			/* EAP-Success within TLS tunnel is used to indicate			 * shutdown of the TLS channel. The authentication has			 * been completed. */			if (data->phase2_eap_started &&			    !data->phase2_eap_success) {				wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "					   "Success used to indicate success, "					   "but Phase 2 EAP was not yet "					   "completed successfully");				ret->methodState = METHOD_DONE;				ret->decision = DECISION_FAIL;				os_free(in_decrypted);				return 0;			}			wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "				   "EAP-Success within TLS tunnel - "				   "authentication completed");			ret->decision = DECISION_UNCOND_SUCC;			ret->methodState = METHOD_DONE;			data->phase2_success = 1;			if (data->peap_outer_success == 2) {				os_free(in_decrypted);				wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "					   "to finish authentication");				return 1;			} else if (data->peap_outer_success == 1) {				/* Reply with EAP-Success within the TLS				 * channel to complete the authentication. */				resp_len = sizeof(struct eap_hdr);				resp = os_zalloc(resp_len);				if (resp) {					rhdr = (struct eap_hdr *) resp;					rhdr->code = EAP_CODE_SUCCESS;					rhdr->identifier = hdr->identifier;					rhdr->length = host_to_be16(resp_len);				}			} else {				/* No EAP-Success expected for Phase 1 (outer,				 * unencrypted auth), so force EAP state				 * machine to SUCCESS state. */				sm->peap_done = TRUE;			}		} else {			/* FIX: ? */		}		break;	case EAP_CODE_FAILURE:		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");		ret->decision = DECISION_FAIL;		ret->methodState = METHOD_MAY_CONT;		ret->allowNotifications = FALSE;		/* Reply with EAP-Failure within the TLS channel to complete		 * failure reporting. */		resp_len = sizeof(struct eap_hdr);		resp = os_zalloc(resp_len);		if (resp) {			rhdr = (struct eap_hdr *) resp;			rhdr->code = EAP_CODE_FAILURE;			rhdr->identifier = hdr->identifier;			rhdr->length = host_to_be16(resp_len);		}		break;	default:		wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "			   "Phase 2 EAP header", hdr->code);		break;	}	os_free(in_decrypted);	if (resp) {		u8 *resp_pos;		size_t resp_send_len;		int skip_change2 = 0;		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",				resp, resp_len);		/* PEAP version changes */		if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE &&		    resp[4] == EAP_TYPE_TLV)			skip_change2 = 1;		if (data->peap_version == 0 && !skip_change2) {			resp_pos = resp + sizeof(struct eap_hdr);			resp_send_len = resp_len - sizeof(struct eap_hdr);		} else {			resp_pos = resp;			resp_send_len = resp_len;		}		if (eap_peap_encrypt(sm, data, req->identifier,				     resp_pos, resp_send_len,				     out_data, out_len)) {			wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "				   "a Phase 2 frame");		}		os_free(resp);	}	return 0;}static u8 * eap_peap_process(struct eap_sm *sm, void *priv,			     struct eap_method_ret *ret,			     const u8 *reqData, size_t reqDataLen,			     size_t *respDataLen){	const struct eap_hdr *req;	size_t left;	int res;	u8 flags, *resp, id;	const u8 *pos;	struct eap_peap_data *data = priv;	pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,				   reqData, reqDataLen, &left, &flags);	if (pos == NULL)		return NULL;	req = (const struct eap_hdr *) reqData;	id = req->identifier;	if (flags & EAP_TLS_FLAGS_START) {		wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "			   "ver=%d)", flags & EAP_PEAP_VERSION_MASK,			data->peap_version);		if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)			data->peap_version = flags & EAP_PEAP_VERSION_MASK;		if (data->force_peap_version >= 0 &&		    data->force_peap_version != data->peap_version) {			wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "				   "forced PEAP version %d",				   data->force_peap_version);			ret->methodState = METHOD_DONE;			ret->decision = DECISION_FAIL;			ret->allowNotifications = FALSE;			return NULL;		}		wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",			   data->peap_version);		left = 0; /* make sure that this frame is empty, even though it			   * should always be, anyway */	}	resp = NULL;	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&	    !data->resuming) {		res = eap_peap_decrypt(sm, data, ret, req, pos, left,				       &resp, respDataLen);	} else {		res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP,					     data->peap_version, id, pos, left,					     &resp, respDataLen);		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {			char *label;			wpa_printf(MSG_DEBUG,				   "EAP-PEAP: TLS done, proceed to Phase 2");			os_free(data->key_data);			/* draft-josefsson-ppext-eap-tls-eap-05.txt			 * specifies that PEAPv1 would use "client PEAP			 * encryption" as the label. However, most existing			 * PEAPv1 implementations seem to be using the old			 * label, "client EAP encryption", instead. Use the old			 * label by default, but allow it to be configured with			 * phase1 parameter peaplabel=1. */			if (data->peap_version > 1 || data->force_new_label)				label = "client PEAP encryption";			else				label = "client EAP encryption";			wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "				   "key derivation", label);			data->key_data =				eap_tls_derive_key(sm, &data->ssl, label,						   EAP_TLS_KEY_LEN);			if (data->key_data) {				wpa_hexdump_key(MSG_DEBUG, 						"EAP-PEAP: Derived key",						data->key_data,						EAP_TLS_KEY_LEN);			} else {				wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "					   "derive key");			}			if (sm->workaround && data->resuming) {				/*				 * At least few RADIUS servers (Aegis v1.1.6;				 * but not v1.1.4; and Cisco ACS) seem to be				 * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco				 * ACS) session resumption with outer				 * EAP-Success. This does not seem to follow				 * draft-josefsson-pppext-eap-tls-eap-05.txt				 * section 4.2, so only allow this if EAP				 * workarounds are enabled.				 */				wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "					   "allow outer EAP-Success to "					   "terminate PEAP resumption");				ret->decision = DECISION_COND_SUCC;				data->phase2_success = 1;			}			data->resuming = 0;		}		if (res == 2) {			/*			 * Application data included in the handshake message.			 */			os_free(data->pending_phase2_req);			data->pending_phase2_req = resp;			data->pending_phase2_req_len = *respDataLen;			resp = NULL;			*respDataLen = 0;			res = eap_peap_decrypt(sm, data, ret, req, pos, left,					       &resp, respDataLen);		}	}	if (ret->methodState == METHOD_DONE) {		ret->allowNotifications = FALSE;	}	if (res == 1) {		return eap_tls_build_ack(&data->ssl, respDataLen, id,					 EAP_TYPE_PEAP, data->peap_version);	}	return resp;}static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv){	struct eap_peap_data *data = priv;	return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&		data->phase2_success;}static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv){	struct eap_peap_data *data = priv;	os_free(data->pending_phase2_req);	data->pending_phase2_req = NULL;}static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv){	struct eap_peap_data *data = priv;	os_free(data->key_data);	data->key_data = NULL;	if (eap_tls_reauth_init(sm, &data->ssl)) {		os_free(data);		return NULL;	}	if (data->phase2_priv && data->phase2_method &&	    data->phase2_method->init_for_reauth)		data->phase2_method->init_for_reauth(sm, data->phase2_priv);	data->phase2_success = 0;	data->phase2_eap_success = 0;	data->phase2_eap_started = 0;	data->resuming = 1;	sm->peap_done = FALSE;	return priv;}static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,			       size_t buflen, int verbose){	struct eap_peap_data *data = priv;	int len, ret;	len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);	if (data->phase2_method) {		ret = os_snprintf(buf + len, buflen - len,				  "EAP-PEAPv%d Phase2 method=%s\n",				  data->peap_version,				  data->phase2_method->name);		if (ret < 0 || (size_t) ret >= buflen - len)			return len;		len += ret;	}	return len;}static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv){	struct eap_peap_data *data = priv;	return data->key_data != NULL && data->phase2_success;}static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len){	struct eap_peap_data *data = priv;	u8 *key;	if (data->key_data == NULL || !data->phase2_success)		return NULL;	key = os_malloc(EAP_TLS_KEY_LEN);	if (key == NULL)		return NULL;	*len = EAP_TLS_KEY_LEN;	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);	return key;}int eap_peer_peap_register(void){	struct eap_method *eap;	int ret;	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,				    EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");	if (eap == NULL)		return -1;	eap->init = eap_peap_init;	eap->deinit = eap_peap_deinit;	eap->process = eap_peap_process;	eap->isKeyAvailable = eap_peap_isKeyAvailable;	eap->getKey = eap_peap_getKey;	eap->get_status = eap_peap_get_status;	eap->has_reauth_data = eap_peap_has_reauth_data;	eap->deinit_for_reauth = eap_peap_deinit_for_reauth;	eap->init_for_reauth = eap_peap_init_for_reauth;	ret = eap_peer_method_register(eap);	if (ret)		eap_peer_method_free(eap);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -