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

📄 eap_peap.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 2 页
字号:
		ret->methodState = METHOD_DONE;		return 1;	}	buf_len = in_len;	if (data->ssl.tls_in_total > buf_len)		buf_len = data->ssl.tls_in_total;	in_decrypted = malloc(buf_len);	if (in_decrypted == NULL) {		free(data->ssl.tls_in);		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;	}	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,					       msg, msg_len,					       in_decrypted, buf_len);	free(data->ssl.tls_in);	data->ssl.tls_in = NULL;	data->ssl.tls_in_len = 0;	if (len_decrypted < 0) {		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "			   "data");		free(in_decrypted);		return 0;	}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 = malloc(sizeof(struct eap_hdr) +					      len_decrypted);		if (nhdr == NULL) {			free(in_decrypted);			return 0;		}		memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted);		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)) {		free(in_decrypted);		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "			   "EAP frame (len=%d)", len_decrypted);		return 0;	}	len = be_to_host16(hdr->length);	if (len > len_decrypted) {		free(in_decrypted);		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "			   "Phase 2 EAP frame (len=%d hdr->length=%d)",			   len_decrypted, 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 (%d < %d)",			   len, 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 (%d) with real "				   "decrypted len (%d)", len, 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=%d", hdr->code, hdr->identifier, len);	switch (hdr->code) {	case EAP_CODE_REQUEST:		if (eap_peap_phase2_request(sm, data, ret, req, hdr,					    &resp, &resp_len)) {			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. */			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) {				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 = malloc(resp_len);				if (resp) {					memset(resp, 0, resp_len);					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 = malloc(resp_len);		if (resp) {			memset(resp, 0, resp_len);			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;	}	free(in_decrypted);	if (resp) {		u8 *resp_pos;		size_t resp_send_len;		int skip_change = 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_change = 1;		if (data->peap_version == 0 && !skip_change) {			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");		}		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");			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 (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;	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;	free(data->key_data);	data->key_data = NULL;	if (eap_tls_reauth_init(sm, &data->ssl)) {		free(data);		return NULL;	}	data->phase2_success = 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;	len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);	if (data->phase2_method) {		len += snprintf(buf + len, buflen - len,				"EAP-PEAPv%d Phase2 method=%s\n",				data->peap_version, data->phase2_method->name);	}	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 = malloc(EAP_TLS_KEY_LEN);	if (key == NULL)		return NULL;	*len = EAP_TLS_KEY_LEN;	memcpy(key, data->key_data, EAP_TLS_KEY_LEN);	return key;}const struct eap_method eap_method_peap ={	.method = EAP_TYPE_PEAP,	.name = "PEAP",	.init = eap_peap_init,	.deinit = eap_peap_deinit,	.process = eap_peap_process,	.isKeyAvailable = eap_peap_isKeyAvailable,	.getKey = eap_peap_getKey,	.get_status = eap_peap_get_status,	.has_reauth_data = eap_peap_has_reauth_data,	.deinit_for_reauth = eap_peap_deinit_for_reauth,	.init_for_reauth = eap_peap_init_for_reauth,};

⌨️ 快捷键说明

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