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

📄 eap_peap.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			return 0;		}		hdr = (struct eap_hdr *) (tlv + 1);		if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {			wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "				   "EAP packet in EAP TLV");			wpabuf_free(in_decrypted);			return 0;		}		nmsg = wpabuf_alloc(be_to_host16(hdr->length));		if (nmsg == NULL) {			wpabuf_free(in_decrypted);			return 0;		}		wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));		wpabuf_free(in_decrypted);		in_decrypted = nmsg;	}	hdr = wpabuf_mhead(in_decrypted);	if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "			   "EAP frame (len=%lu)",			   (unsigned long) wpabuf_len(in_decrypted));		wpabuf_free(in_decrypted);		return 0;	}	len = be_to_host16(hdr->length);	if (len > wpabuf_len(in_decrypted)) {		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",			   (unsigned long) wpabuf_len(in_decrypted),			   (unsigned long) len);		wpabuf_free(in_decrypted);		return 0;	}	if (len < wpabuf_len(in_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) wpabuf_len(in_decrypted));	}	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, in_decrypted,					    &resp)) {			wpabuf_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;				wpabuf_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) {				wpabuf_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 = wpabuf_alloc(sizeof(struct eap_hdr));				if (resp) {					rhdr = wpabuf_put(resp, sizeof(*rhdr));					rhdr->code = EAP_CODE_SUCCESS;					rhdr->identifier = hdr->identifier;					rhdr->length =						host_to_be16(sizeof(*rhdr));				}			} 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 = wpabuf_alloc(sizeof(struct eap_hdr));		if (resp) {			rhdr = wpabuf_put(resp, sizeof(*rhdr));			rhdr->code = EAP_CODE_FAILURE;			rhdr->identifier = hdr->identifier;			rhdr->length = host_to_be16(sizeof(*rhdr));		}		break;	default:		wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "			   "Phase 2 EAP header", hdr->code);		break;	}	wpabuf_free(in_decrypted);	if (resp) {		int skip_change2 = 0;		struct wpabuf *rmsg, buf;		wpa_hexdump_buf_key(MSG_DEBUG,				    "EAP-PEAP: Encrypting Phase 2 data", resp);		/* PEAP version changes */		if (data->peap_version >= 2) {			resp = eap_peapv2_tlv_eap_payload(resp);			if (resp == NULL)				return -1;		}		if (wpabuf_len(resp) >= 5 &&		    wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&		    eap_get_type(resp) == EAP_TYPE_TLV)			skip_change2 = 1;		rmsg = resp;		if (data->peap_version == 0 && !skip_change2) {			wpabuf_set(&buf, wpabuf_head_u8(resp) +				   sizeof(struct eap_hdr),				   wpabuf_len(resp) - sizeof(struct eap_hdr));			rmsg = &buf;		}		if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,					 data->peap_version, req->identifier,					 rmsg, out_data)) {			wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "				   "a Phase 2 frame");		}		wpabuf_free(resp);	}	return 0;}static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,					struct eap_method_ret *ret,					const struct wpabuf *reqData){	const struct eap_hdr *req;	size_t left;	int res;	u8 flags, id;	struct wpabuf *resp;	const u8 *pos;	struct eap_peap_data *data = priv;	pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,					reqData, &left, &flags);	if (pos == NULL)		return NULL;	req = wpabuf_head(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) {		struct wpabuf msg;		wpabuf_set(&msg, pos, left);		res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);	} else {		res = eap_peer_tls_process_helper(sm, &data->ssl,						  EAP_TYPE_PEAP,						  data->peap_version, id, pos,						  left, &resp);		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_peer_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) {			struct wpabuf msg;			/*			 * Application data included in the handshake message.			 */			wpabuf_free(data->pending_phase2_req);			data->pending_phase2_req = resp;			resp = NULL;			wpabuf_set(&msg, pos, left);			res = eap_peap_decrypt(sm, data, ret, req, &msg,					       &resp);		}	}	if (ret->methodState == METHOD_DONE) {		ret->allowNotifications = FALSE;	}	if (res == 1) {		wpabuf_free(resp);		return eap_peer_tls_build_ack(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;	wpabuf_free(data->pending_phase2_req);	data->pending_phase2_req = NULL;	data->crypto_binding_used = 0;}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_peer_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_peer_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;	if (data->crypto_binding_used) {		u8 csk[128];		/*		 * Note: It looks like Microsoft implementation requires null		 * termination for this label while the one used for deriving		 * IPMK|CMK did not use null termination.		 */		peap_prfplus(data->peap_version, data->ipmk, 40,			     "Session Key Generating Function",			     (u8 *) "\00", 1, csk, sizeof(csk));		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));		os_memcpy(key, csk, EAP_TLS_KEY_LEN);		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",			    key, EAP_TLS_KEY_LEN);	} else		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 + -