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

📄 eap_ttls.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	return 0;}static int eap_ttls_phase2_request_chap(struct eap_sm *sm,					struct eap_ttls_data *data,					struct eap_method_ret *ret,					u8 **resp, size_t *resp_len){	struct wpa_ssid *config = eap_get_config(sm);	u8 *buf, *pos, *challenge;	const u8 *addr[3];	size_t len[3];	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");	pos = buf = os_malloc(config->identity_len + 1000);	if (buf == NULL) {		wpa_printf(MSG_ERROR,			   "EAP-TTLS/CHAP: Failed to allocate memory");		return -1;	}	/* User-Name */	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,			       config->identity, config->identity_len);	/* CHAP-Challenge */	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);	if (challenge == NULL) {		os_free(buf);		wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "			   "implicit challenge");		return -1;	}	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,			       challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);	/* CHAP-Password */	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,			       1 + EAP_TTLS_CHAP_PASSWORD_LEN);	data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];	*pos++ = data->ident;	/* MD5(Ident + Password + Challenge) */	addr[0] = &data->ident;	len[0] = 1;	addr[1] = config->password;	len[1] = config->password_len;	addr[2] = challenge;	len[2] = EAP_TTLS_CHAP_CHALLENGE_LEN;	md5_vector(3, addr, len, pos);	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",			  config->identity, config->identity_len);	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",			      config->password, config->password_len);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",		    challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",		    pos, EAP_TTLS_CHAP_PASSWORD_LEN);	pos += EAP_TTLS_CHAP_PASSWORD_LEN;	os_free(challenge);	AVP_PAD(buf, pos);	*resp = buf;	*resp_len = pos - buf;	if (data->ttls_version > 0) {		/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,		 * so do not allow connection to be terminated yet. */		ret->methodState = METHOD_CONT;		ret->decision = DECISION_COND_SUCC;	} else {		/* EAP-TTLS/CHAP does not provide tunneled success		 * notification, so assume that Phase2 succeeds. */		ret->methodState = METHOD_DONE;		ret->decision = DECISION_COND_SUCC;	}	return 0;}static int eap_ttls_phase2_request(struct eap_sm *sm,				   struct eap_ttls_data *data,				   struct eap_method_ret *ret,				   const struct eap_hdr *req,				   struct eap_hdr *hdr,				   u8 **resp, size_t *resp_len){	int res = 0;	size_t len;	if (data->phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||	    data->phase2_type == EAP_TTLS_PHASE2_MSCHAP ||	    data->phase2_type == EAP_TTLS_PHASE2_PAP ||	    data->phase2_type == EAP_TTLS_PHASE2_CHAP) {		if (eap_get_config_identity(sm, &len) == NULL) {			wpa_printf(MSG_INFO,				   "EAP-TTLS: Identity not configured");			eap_sm_request_identity(sm);			if (eap_get_config_password(sm, &len) == NULL)				eap_sm_request_password(sm);			return 0;		}		if (eap_get_config_password(sm, &len) == NULL) {			wpa_printf(MSG_INFO,				   "EAP-TTLS: Password not configured");			eap_sm_request_password(sm);			return 0;		}	}	switch (data->phase2_type) {	case EAP_TTLS_PHASE2_EAP:		res = eap_ttls_phase2_request_eap(sm, data, ret, hdr,						  resp, resp_len);		break;	case EAP_TTLS_PHASE2_MSCHAPV2:		res = eap_ttls_phase2_request_mschapv2(sm, data, ret,						       resp, resp_len);		break;	case EAP_TTLS_PHASE2_MSCHAP:		res = eap_ttls_phase2_request_mschap(sm, data, ret,						     resp, resp_len);		break;	case EAP_TTLS_PHASE2_PAP:		res = eap_ttls_phase2_request_pap(sm, data, ret,						  resp, resp_len);		break;	case EAP_TTLS_PHASE2_CHAP:		res = eap_ttls_phase2_request_chap(sm, data, ret,						   resp, resp_len);		break;	default:		wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");		res = -1;		break;	}	if (res < 0) {		ret->methodState = METHOD_DONE;		ret->decision = DECISION_FAIL;	}	return res;}static u8 * eap_ttls_build_phase_finished(struct eap_sm *sm,					  struct eap_ttls_data *data,					  int id, int final,					  size_t *reqDataLen){	int len;	struct eap_hdr *req;	u8 *pos;	const int max_len = 300;	len = sizeof(struct eap_hdr) + 2 + max_len;	req = os_malloc(len);	if (req == NULL)		return NULL;	req->code = EAP_CODE_RESPONSE;	req->identifier = id;	pos = (u8 *) (req + 1);	*pos++ = EAP_TYPE_TTLS;	*pos++ = data->ttls_version;	len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,						    data->ssl.conn,						    final, pos, max_len);	if (len < 0) {		os_free(req);		return NULL;	}	*reqDataLen = sizeof(struct eap_hdr) + 2 + len;	req->length = host_to_be16(*reqDataLen);	return (u8 *) req;}static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_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){	u8 *in_decrypted = NULL, *pos;	int res, retval = 0;	struct eap_hdr *hdr = NULL;	u8 *resp = NULL, *mschapv2 = NULL, *eapdata = NULL;	size_t resp_len, eap_len = 0, len_decrypted = 0, len, buf_len, left;	struct ttls_avp *avp;	u8 recv_response[20];	int mschapv2_error = 0;	struct wpa_ssid *config = eap_get_config(sm);	const u8 *msg;	size_t msg_len;	int need_more_input;	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"		   " Phase 2", (unsigned long) in_len);	if (data->pending_phase2_req) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "			   "skip decryption and use old data");		/* Clear TLS reassembly state. */		os_free(data->ssl.tls_in);		data->ssl.tls_in = NULL;		data->ssl.tls_in_len = 0;		data->ssl.tls_in_left = 0;		data->ssl.tls_in_total = 0;		in_decrypted = data->pending_phase2_req;		data->pending_phase2_req = NULL;		len_decrypted = data->pending_phase2_req_len;		if (data->pending_phase2_req_len == 0) {			os_free(in_decrypted);			in_decrypted = NULL;			goto fake_req_identity;		}		goto continue_req;	}	if (in_len == 0 && data->phase2_start) {		data->phase2_start = 0;		/* EAP-TTLS does not use Phase2 on fast re-auth; this must be		 * done only if TLS part was indeed resuming a previous		 * session. Most Authentication Servers terminate EAP-TTLS		 * before reaching this point, but some do not. Make		 * wpa_supplicant stop phase 2 here, if needed. */		if (data->reauth &&		    tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {			wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - "				   "skip phase 2");			*out_data = eap_tls_build_ack(&data->ssl, out_len,						      req->identifier,						      EAP_TYPE_TTLS, 0);			ret->methodState = METHOD_DONE;			ret->decision = DECISION_UNCOND_SUCC;			data->phase2_success = 1;			return 0;		}	fake_req_identity:		wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "			   "Phase 2 - use fake EAP-Request Identity");		buf_len = sizeof(*hdr) + 1;		in_decrypted = os_malloc(buf_len);		if (in_decrypted == NULL) {			wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "				   "memory for fake EAP-Identity Request");			retval = -1;			goto done;		}		hdr = (struct eap_hdr *) in_decrypted;		hdr->code = EAP_CODE_REQUEST;		hdr->identifier = 0;		hdr->length = host_to_be16(sizeof(*hdr) + 1);		in_decrypted[sizeof(*hdr)] = EAP_TYPE_IDENTITY;		goto process_eap;	}	msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len,				      &msg_len, &need_more_input);	if (msg == NULL)		return need_more_input ? 1 : -1;	buf_len = in_len;	if (data->ssl.tls_in_total > buf_len)		buf_len = data->ssl.tls_in_total;	in_decrypted = os_malloc(buf_len);	if (in_decrypted == NULL) {		os_free(data->ssl.tls_in);		data->ssl.tls_in = NULL;		data->ssl.tls_in_len = 0;		wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "			   "for decryption");		retval = -1;		goto done;	}	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-TTLS: Failed to decrypt Phase 2 "			   "data");		retval = -1;		goto done;	}	len_decrypted = res;	if (data->ttls_version > 0 && len_decrypted == 0 &&	    tls_connection_ia_final_phase_finished(sm->ssl_ctx,						   data->ssl.conn)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received");		wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication "			   "succeeded");		ret->methodState = METHOD_DONE;		ret->decision = DECISION_UNCOND_SUCC;		data->phase2_success = 1;		*out_data = eap_ttls_build_phase_finished(sm, data,							  req->identifier, 1,							  out_len);		eap_ttls_v1_derive_key(sm, data);		goto done;	}continue_req:	data->phase2_start = 0;	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs",		    in_decrypted, len_decrypted);	if (len_decrypted < sizeof(struct ttls_avp)) {		wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"			   " len=%lu expected %lu or more - dropped",			   (unsigned long) len_decrypted,			   (unsigned long) sizeof(struct ttls_avp));		retval = -1;		goto done;	}	/* Parse AVPs */	pos = in_decrypted;	left = len_decrypted;	mschapv2 = NULL;	while (left > 0) {		u32 avp_code, avp_length, vendor_id = 0;		u8 avp_flags, *dpos;		size_t pad, dlen;		avp = (struct ttls_avp *) pos;		avp_code = be_to_host32(avp->avp_code);		avp_length = be_to_host32(avp->avp_length);		avp_flags = (avp_length >> 24) & 0xff;		avp_length &= 0xffffff;		wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "			   "length=%d", (int) avp_code, avp_flags,			   (int) avp_length);		if (avp_length > left) {			wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "				   "(len=%d, left=%lu) - dropped",				   (int) avp_length, (unsigned long) left);			retval = -1;			goto done;		}		if (avp_length < sizeof(*avp)) {			wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length "				   "%d", avp_length);			retval = -1;			goto done;		}		dpos = (u8 *) (avp + 1);		dlen = avp_length - sizeof(*avp);		if (avp_flags & AVP_FLAGS_VENDOR) {			if (dlen < 4) {				wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP "					   "underflow");				retval = -1;				goto done;			}			vendor_id = be_to_host32(* (u32 *) dpos);			wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",				   (int) vendor_id);			dpos += 4;			dlen -= 4;		}		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);		if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {			wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");			if (eapdata == NULL) {				eapdata = os_malloc(dlen);				if (eapdata == NULL) {					retval = -1;					wpa_printf(MSG_WARNING, "EAP-TTLS: "						   "failed to allocate memory "						   "for Phase 2 EAP data");					goto done;				}				os_memcpy(eapdata, dpos, dlen);				eap_len = dlen;			} else {				u8 *neweap = os_realloc(eapdata,							eap_len + dlen);				if (neweap == NULL) {					retval = -1;					wpa_printf(MSG_WARNING, "EAP-TTLS: "						   "failed to allocate memory "						   "for Phase 2 EAP data");					goto done;				}				os_memcpy(neweap + eap_len, dpos, dlen);				eapdata = neweap;				eap_len += dlen;			}		} else if (vendor_id == 0 &&			   avp_code == RADIUS_ATTR_REPLY_MESSAGE) {			/* This is an optional message that can be displayed to			 * the user. */			wpa_hexdump_ascii(MSG_DEBUG,					  "EAP-TTLS: AVP - Reply-Message",					  dpos, dlen);		} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&			   avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) {			wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: "					  "MS-CHAP2-Success", dpos, dlen);			if (dlen != 43) {				wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected "					   "MS-CHAP2-Success length "					   "(len=%lu, expected 43)",					   (unsigned long) dlen);				retval = -1;				break;			}			mschapv2 = dpos;		} else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&			   avp_code == RADIUS_ATTR_MS_CHAP_ERROR) {			wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: "					  "MS-CHAP-Error", dpos, dlen);			mschapv2_error = 1;		} else if (avp_flags & AVP_FLAGS_MANDATORY) {			wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported "				   "mandatory AVP code %d vendor_id %d - "				   "dropped", (int) avp_code, (int) vendor_id);			retval = -1;			goto done;		} else {

⌨️ 快捷键说明

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