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

📄 eap_ttls.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||	    keys.client_random == NULL || keys.server_random == NULL ||	    keys.inner_secret == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "			   "client random, or server random to derive "			   "implicit challenge");		return NULL;	}	rnd = os_malloc(keys.client_random_len + keys.server_random_len);	challenge = os_malloc(len);	if (rnd == NULL || challenge == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "			   "challenge derivation");		os_free(rnd);		os_free(challenge);		return NULL;	}	os_memcpy(rnd, keys.server_random, keys.server_random_len);	os_memcpy(rnd + keys.server_random_len, keys.client_random,		  keys.client_random_len);	if (tls_prf(keys.inner_secret, keys.inner_secret_len,		    "inner application challenge", rnd,		    keys.client_random_len + keys.server_random_len,		    challenge, len)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "			   "challenge");		os_free(rnd);		os_free(challenge);		return NULL;	}	os_free(rnd);	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",			challenge, len);	return challenge;}static int eap_ttls_phase2_nak(struct eap_ttls_data *data, struct eap_hdr *hdr,			       u8 **resp, size_t *resp_len){	struct eap_hdr *resp_hdr;	u8 *pos = (u8 *) (hdr + 1);	size_t i;	/* TODO: add support for expanded Nak */	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 Request: Nak type=%d", *pos);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Allowed Phase2 EAP types",		    (u8 *) data->phase2_eap_types, data->num_phase2_eap_types *		    sizeof(struct eap_method_type));	*resp_len = sizeof(struct eap_hdr) + 1;	*resp = os_malloc(*resp_len + data->num_phase2_eap_types);	if (*resp == NULL)		return -1;	resp_hdr = (struct eap_hdr *) (*resp);	resp_hdr->code = EAP_CODE_RESPONSE;	resp_hdr->identifier = hdr->identifier;	pos = (u8 *) (resp_hdr + 1);	*pos++ = EAP_TYPE_NAK;	for (i = 0; i < data->num_phase2_eap_types; i++) {		if (data->phase2_eap_types[i].vendor == EAP_VENDOR_IETF &&		    data->phase2_eap_types[i].method < 256) {			(*resp_len)++;			*pos++ = data->phase2_eap_types[i].method;		}	}	resp_hdr->length = host_to_be16(*resp_len);	return 0;}static int eap_ttls_phase2_request_eap(struct eap_sm *sm,				       struct eap_ttls_data *data,				       struct eap_method_ret *ret,				       struct eap_hdr *hdr,				       u8 **resp, size_t *resp_len){	size_t len = be_to_host16(hdr->length);	u8 *pos;	struct eap_method_ret iret;	struct wpa_ssid *config = eap_get_config(sm);	if (len <= sizeof(struct eap_hdr)) {		wpa_printf(MSG_INFO, "EAP-TTLS: too short "			   "Phase 2 request (len=%lu)", (unsigned long) len);		return -1;	}	pos = (u8 *) (hdr + 1);	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);	switch (*pos) {	case EAP_TYPE_IDENTITY:		*resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);		break;	default:		if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&		    data->phase2_eap_type.method == EAP_TYPE_NONE) {			size_t i;			for (i = 0; i < data->num_phase2_eap_types; i++) {				if (data->phase2_eap_types[i].vendor !=				    EAP_VENDOR_IETF ||				    data->phase2_eap_types[i].method != *pos)					continue;				data->phase2_eap_type.vendor =					data->phase2_eap_types[i].vendor;				data->phase2_eap_type.method =					data->phase2_eap_types[i].method;				wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "					   "Phase 2 EAP vendor %d method %d",					   data->phase2_eap_type.vendor,					   data->phase2_eap_type.method);				break;			}		}		if (*pos != data->phase2_eap_type.method ||		    *pos == EAP_TYPE_NONE) {			if (eap_ttls_phase2_nak(data, hdr, resp, resp_len))				return -1;			break;		}		if (data->phase2_priv == NULL) {			data->phase2_method = eap_sm_get_eap_methods(				EAP_VENDOR_IETF, *pos);			if (data->phase2_method) {				sm->init_phase2 = 1;				sm->mschapv2_full_key = 1;				data->phase2_priv =					data->phase2_method->init(sm);				sm->init_phase2 = 0;				sm->mschapv2_full_key = 0;			}		}		if (data->phase2_priv == NULL || data->phase2_method == NULL) {			wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "				   "Phase 2 EAP method %d", *pos);			return -1;		}		os_memset(&iret, 0, sizeof(iret));		*resp = data->phase2_method->process(sm, data->phase2_priv,						     &iret, (u8 *) hdr, len,						     resp_len);		if ((iret.methodState == METHOD_DONE ||		     iret.methodState == METHOD_MAY_CONT) &&		    (iret.decision == DECISION_UNCOND_SUCC ||		     iret.decision == DECISION_COND_SUCC ||		     iret.decision == DECISION_FAIL)) {			ret->methodState = iret.methodState;			ret->decision = iret.decision;		}		if (data->ttls_version > 0) {			const struct eap_method *m = data->phase2_method;			void *priv = data->phase2_priv;			/* TTLSv1 requires TLS/IA FinalPhaseFinished */			if (ret->decision == DECISION_UNCOND_SUCC)				ret->decision = DECISION_COND_SUCC;			ret->methodState = METHOD_CONT;			if (ret->decision == DECISION_COND_SUCC &&			    m->isKeyAvailable && m->getKey &&			    m->isKeyAvailable(sm, priv)) {				u8 *key;				size_t key_len;				key = m->getKey(sm, priv, &key_len);				if (key) {					eap_ttls_ia_permute_inner_secret(						sm, data, key, key_len);					os_free(key);				}			}		}		break;	}	if (*resp == NULL &&	    (config->pending_req_identity || config->pending_req_password ||	     config->pending_req_otp)) {		return 0;	}	if (*resp == NULL)		return -1;	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",		    *resp, *resp_len);	return eap_ttls_avp_encapsulate(resp, resp_len,					RADIUS_ATTR_EAP_MESSAGE, 1);}static int eap_ttls_phase2_request_mschapv2(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, *username, *peer_challenge;	size_t username_len, i;	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");	/* MSCHAPv2 does not include optional domain name in the	 * challenge-response calculation, so remove domain prefix	 * (if present). */	username = config->identity;	username_len = config->identity_len;	pos = username;	for (i = 0; i < username_len; i++) {		if (username[i] == '\\') {			username_len -= i + 1;			username += i + 1;			break;		}	}	pos = buf = os_malloc(config->identity_len + 1000);	if (buf == NULL) {		wpa_printf(MSG_ERROR,			   "EAP-TTLS/MSCHAPV2: 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);	/* MS-CHAP-Challenge */	challenge = eap_ttls_implicit_challenge(		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 + 1);	if (challenge == NULL) {		os_free(buf);		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "			   "implicit challenge");		return -1;	}	peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,			       RADIUS_VENDOR_ID_MICROSOFT, 1,			       challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);	/* MS-CHAP2-Response */	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE,			       RADIUS_VENDOR_ID_MICROSOFT, 1,			       EAP_TTLS_MSCHAPV2_RESPONSE_LEN);	data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];	*pos++ = data->ident;	*pos++ = 0; /* Flags */	os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);	pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;	os_memset(pos, 0, 8); /* Reserved, must be zero */	pos += 8;	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: implicit auth_challenge",		    challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: peer_challenge",		    peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 username",			  username, username_len);	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password",			      config->password, config->password_len);	generate_nt_response(challenge, peer_challenge,			     username, username_len,			     config->password, config->password_len,			     pos);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24);	generate_authenticator_response(config->password, config->password_len,					peer_challenge, challenge,					username, username_len,					pos, data->auth_response);	data->auth_response_valid = 1;	if (data->ttls_version > 0) {		u8 pw_hash[16], pw_hash_hash[16], master_key[16];		u8 session_key[2 * MSCHAPV2_KEY_LEN];		nt_password_hash(config->password, config->password_len,				 pw_hash);		hash_nt_password_hash(pw_hash, pw_hash_hash);		get_master_key(pw_hash_hash, pos /* nt_response */,			       master_key);		get_asymetric_start_key(master_key, session_key,					MSCHAPV2_KEY_LEN, 0, 0);		get_asymetric_start_key(master_key,					session_key + MSCHAPV2_KEY_LEN,					MSCHAPV2_KEY_LEN, 1, 0);		eap_ttls_ia_permute_inner_secret(sm, data,						 session_key,						 sizeof(session_key));	}	pos += 24;	os_free(challenge);	AVP_PAD(buf, pos);	*resp = buf;	*resp_len = pos - buf;	if (sm->workaround && data->ttls_version == 0) {		/* At least FreeRADIUS seems to be terminating		 * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success		 * packet. */		wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - "			   "allow success without tunneled response");		ret->methodState = METHOD_MAY_CONT;		ret->decision = DECISION_COND_SUCC;	}	return 0;}static int eap_ttls_phase2_request_mschap(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;	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");	pos = buf = os_malloc(config->identity_len + 1000);	if (buf == NULL) {		wpa_printf(MSG_ERROR,			   "EAP-TTLS/MSCHAP: 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);	/* MS-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/MSCHAP: Failed to derive "			   "implicit challenge");		return -1;	}	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,			       RADIUS_VENDOR_ID_MICROSOFT, 1,			       challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);	/* MS-CHAP-Response */	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE,			       RADIUS_VENDOR_ID_MICROSOFT, 1,			       EAP_TTLS_MSCHAP_RESPONSE_LEN);	data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];	*pos++ = data->ident;	*pos++ = 1; /* Flags: Use NT style passwords */	os_memset(pos, 0, 24); /* LM-Response */	pos += 24;	nt_challenge_response(challenge,			      config->password, config->password_len,			      pos); /* NT-Response */	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",			      config->password, config->password_len);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",		    challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);	pos += 24;	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/MSCHAP 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_pap(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;	size_t pad;	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");	pos = buf = os_malloc(config->identity_len + config->password_len +			      100);	if (buf == NULL) {		wpa_printf(MSG_ERROR,			   "EAP-TTLS/PAP: 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);	/* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts	 * the data, so no separate encryption is used in the AVP itself.	 * However, the password is padded to obfuscate its length. */	pad = (16 - (config->password_len & 15)) & 15;	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,			       config->password_len + pad);	os_memcpy(pos, config->password, config->password_len);	pos += config->password_len;	os_memset(pos, 0, pad);	pos += pad;	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/PAP does not provide tunneled success notification,		 * so assume that Phase2 succeeds. */		ret->methodState = METHOD_DONE;		ret->decision = DECISION_COND_SUCC;	}

⌨️ 快捷键说明

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