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

📄 eap_ttls.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
{	if (data->phase2_priv && data->phase2_method) {		data->phase2_method->reset(sm, data->phase2_priv);		data->phase2_method = NULL;		data->phase2_priv = NULL;	}	data->phase2_method = eap_sm_get_eap_methods(EAP_VENDOR_IETF,						     eap_type);	if (!data->phase2_method)		return -1;	sm->init_phase2 = 1;	data->phase2_priv = data->phase2_method->init(sm);	sm->init_phase2 = 0;	return 0;}static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm,						 struct eap_ttls_data *data,						 u8 *in_data, size_t in_len){	u8 next_type = EAP_TYPE_NONE;	struct eap_hdr *hdr;	u8 *pos;	size_t left;	const struct eap_method *m = data->phase2_method;	void *priv = data->phase2_priv;	if (data->phase2_priv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not "			   "initialized?!", __func__);		return;	}	hdr = (struct eap_hdr *) in_data;	pos = (u8 *) (hdr + 1);	left = in_len - sizeof(*hdr);	if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {		wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; "			    "allowed types", pos + 1, left - 1);		eap_sm_process_nak(sm, pos + 1, left - 1);		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&		    sm->user->methods[sm->user_eap_method_index].method !=		    EAP_TYPE_NONE) {			next_type = sm->user->methods[				sm->user_eap_method_index++].method;			wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d",				   next_type);			eap_ttls_phase2_eap_init(sm, data, next_type);		} else {			eap_ttls_state(data, FAILURE);		}		return;	}	if (m->check(sm, priv, in_data, in_len)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to "			   "ignore the packet");		return;	}	m->process(sm, priv, in_data, in_len);	if (!m->isDone(sm, priv))		return;	if (!m->isSuccess(sm, priv)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed");		eap_ttls_state(data, FAILURE);		return;	}	switch (data->state) {	case PHASE2_START:		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {			wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 "					  "Identity not found in the user "					  "database",					  sm->identity, sm->identity_len);			eap_ttls_state(data, FAILURE);			break;		}		eap_ttls_state(data, PHASE2_METHOD);		next_type = sm->user->methods[0].method;		sm->user_eap_method_index = 1;		wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type);		break;	case PHASE2_METHOD:		if (data->ttls_version > 0) {			if (m->getKey) {				u8 *key;				size_t key_len;				key = m->getKey(sm, priv, &key_len);				eap_ttls_ia_permute_inner_secret(sm, data,								 key, key_len);			}			eap_ttls_state(data, PHASE_FINISHED);		} else			eap_ttls_state(data, SUCCESS);		break;	case FAILURE:		break;	default:		wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",			   __func__, data->state);		break;	}	eap_ttls_phase2_eap_init(sm, data, next_type);}static void eap_ttls_process_phase2_eap(struct eap_sm *sm,					struct eap_ttls_data *data,					const u8 *eap, size_t eap_len){	struct eap_hdr *hdr;	size_t len;	if (data->state == PHASE2_START) {		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2");		if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0)		{			wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to "				   "initialize EAP-Identity");			return;		}	}	if (eap_len < sizeof(*hdr)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP "			   "packet (len=%lu)", (unsigned long) eap_len);		return;	}	hdr = (struct eap_hdr *) eap;	len = be_to_host16(hdr->length);	wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d "		   "identifier=%d length=%lu", hdr->code, hdr->identifier,		   (unsigned long) len);	if (len > eap_len) {		wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2"			   " EAP frame (hdr len=%lu, data len in AVP=%lu)",			   (unsigned long) len, (unsigned long) eap_len);		return;	}	switch (hdr->code) {	case EAP_CODE_RESPONSE:		eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr,						     len);		break;	default:		wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in "			   "Phase 2 EAP header", hdr->code);		break;	}}static void eap_ttls_process_phase2(struct eap_sm *sm,				    struct eap_ttls_data *data,				    struct eap_hdr *resp,				    u8 *in_data, size_t in_len){	u8 *in_decrypted;	int buf_len, len_decrypted, res;	struct eap_ttls_avp parse;	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"		   " Phase 2", (unsigned long) in_len);	res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len);	if (res < 0 || res == 1)		return;	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-TTLS: failed to allocate memory "			   "for decryption");		return;	}	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,					       in_data, in_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-TTLS: Failed to decrypt Phase 2 "			   "data");		free(in_decrypted);		eap_ttls_state(data, FAILURE);		return;	}	if (data->state == PHASE_FINISHED) {		if (len_decrypted == 0 &&		    tls_connection_ia_final_phase_finished(sm->ssl_ctx,							   data->ssl.conn)) {			wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "				   "received");			eap_ttls_state(data, SUCCESS);		} else {			wpa_printf(MSG_INFO, "EAP-TTLS: Did not receive valid "				   "FinalPhaseFinished");			eap_ttls_state(data, FAILURE);		}		free(in_decrypted);		return;	}	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",			in_decrypted, len_decrypted);	if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");		free(in_decrypted);		eap_ttls_state(data, FAILURE);		return;	}	if (parse.user_name) {		free(sm->identity);		sm->identity = malloc(parse.user_name_len);		if (sm->identity) {			memcpy(sm->identity, parse.user_name,			       parse.user_name_len);			sm->identity_len = parse.user_name_len;		}		if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1)		    != 0) {			wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not "				   "found in the user database");			eap_ttls_state(data, FAILURE);			goto done;		}	}	if (parse.eap) {		eap_ttls_process_phase2_eap(sm, data, parse.eap,					    parse.eap_len);	} else if (parse.user_password) {		eap_ttls_process_phase2_pap(sm, data, parse.user_password,					    parse.user_password_len);	} else if (parse.chap_password) {		eap_ttls_process_phase2_chap(sm, data,					     parse.chap_challenge,					     parse.chap_challenge_len,					     parse.chap_password,					     parse.chap_password_len);	} else if (parse.mschap_response) {		eap_ttls_process_phase2_mschap(sm, data,					       parse.mschap_challenge,					       parse.mschap_challenge_len,					       parse.mschap_response,					       parse.mschap_response_len);	} else if (parse.mschap2_response) {		eap_ttls_process_phase2_mschapv2(sm, data,						 parse.mschap_challenge,						 parse.mschap_challenge_len,						 parse.mschap2_response,						 parse.mschap2_response_len);	}done:	free(in_decrypted);	free(parse.eap); }static void eap_ttls_process(struct eap_sm *sm, void *priv,			     u8 *respData, size_t respDataLen){	struct eap_ttls_data *data = priv;	struct eap_hdr *resp;	u8 *pos, flags;	int left;	unsigned int tls_msg_len;	int peer_version;	resp = (struct eap_hdr *) respData;	pos = (u8 *) (resp + 1);	pos++;	flags = *pos++;	left = htons(resp->length) - sizeof(struct eap_hdr) - 2;	wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - "		   "Flags 0x%02x", (unsigned long) respDataLen, flags);	peer_version = flags & EAP_PEAP_VERSION_MASK;	if (peer_version < data->ttls_version) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "			   "use version %d",			   peer_version, data->ttls_version, peer_version);		data->ttls_version = peer_version;	}	if (data->ttls_version > 0 && !data->tls_ia_configured) {		if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {			wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "				   "TLS/IA");			eap_ttls_state(data, FAILURE);			return;		}		data->tls_ia_configured = 1;	}	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {		if (left < 4) {			wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS "				   "length");			eap_ttls_state(data, FAILURE);			return;		}		tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) |			pos[3];		wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d",			   tls_msg_len);		if (data->ssl.tls_in_left == 0) {			data->ssl.tls_in_total = tls_msg_len;			data->ssl.tls_in_left = tls_msg_len;			free(data->ssl.tls_in);			data->ssl.tls_in = NULL;			data->ssl.tls_in_len = 0;		}		pos += 4;		left -= 4;	}	switch (data->state) {	case PHASE1:		if (eap_tls_process_helper(sm, &data->ssl, pos, left) < 0) {			wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing "				   "failed");			eap_ttls_state(data, FAILURE);		}		break;	case PHASE2_START:	case PHASE2_METHOD:	case PHASE_FINISHED:		eap_ttls_process_phase2(sm, data, resp, pos, left);		break;	case PHASE2_MSCHAPV2_RESP:		if (data->mschapv2_resp_ok && left == 0) {			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "				   "acknowledged response");			eap_ttls_state(data, data->ttls_version > 0 ?				       PHASE_FINISHED : SUCCESS);		} else if (!data->mschapv2_resp_ok) {			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "				   "acknowledged error");			eap_ttls_state(data, FAILURE);		} else {			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "				   "frame from peer (payload len %d, expected "				   "empty frame)", left);			eap_ttls_state(data, FAILURE);		}		break;	default:		wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s",			   data->state, __func__);		break;	}	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {		wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error "			   "in TLS processing");		eap_ttls_state(data, FAILURE);	}}static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv){	struct eap_ttls_data *data = priv;	return data->state == SUCCESS || data->state == FAILURE;}static u8 * eap_ttls_v1_derive_key(struct eap_sm *sm,				   struct eap_ttls_data *data){	struct tls_keys keys;	u8 *rnd, *key;	memset(&keys, 0, sizeof(keys));	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 keying "			   "material");		return NULL;	}	rnd = malloc(keys.client_random_len + keys.server_random_len);	key = malloc(EAP_TLS_KEY_LEN);	if (rnd == NULL || key == NULL) {		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");		free(rnd);		free(key);		return NULL;	}	memcpy(rnd, keys.client_random, keys.client_random_len);	memcpy(rnd + keys.client_random_len, keys.server_random,	       keys.server_random_len);	if (tls_prf(keys.inner_secret, keys.inner_secret_len,		    "ttls v1 keying material", rnd, keys.client_random_len +		    keys.server_random_len, key, EAP_TLS_KEY_LEN)) {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");		free(rnd);		free(key);		return NULL;	}	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",		    rnd, keys.client_random_len + keys.server_random_len);	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",			keys.inner_secret, keys.inner_secret_len);	free(rnd);	return key;}static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len){	struct eap_ttls_data *data = priv;	u8 *eapKeyData;	if (data->state != SUCCESS)		return NULL;	if (data->ttls_version == 0) {		eapKeyData = eap_tls_derive_key(sm, &data->ssl,						"ttls keying material",						EAP_TLS_KEY_LEN);	} else {		eapKeyData = eap_ttls_v1_derive_key(sm, data);	}	if (eapKeyData) {		*len = EAP_TLS_KEY_LEN;		wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",				eapKeyData, EAP_TLS_KEY_LEN);	} else {		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");	}	return eapKeyData;}static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv){	struct eap_ttls_data *data = priv;	return data->state == SUCCESS;}int eap_server_ttls_register(void){	struct eap_method *eap;	int ret;	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,				      EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");	if (eap == NULL)		return -1;	eap->init = eap_ttls_init;	eap->reset = eap_ttls_reset;	eap->buildReq = eap_ttls_buildReq;	eap->check = eap_ttls_check;	eap->process = eap_ttls_process;	eap->isDone = eap_ttls_isDone;	eap->getKey = eap_ttls_getKey;	eap->isSuccess = eap_ttls_isSuccess;	ret = eap_server_method_register(eap);	if (ret)		eap_server_method_free(eap);	return ret;}

⌨️ 快捷键说明

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