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

📄 eap_fast.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->fast_version);	/* RFC 4851, 4.1.1. Authority ID Data */	eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);	eap_fast_state(data, PHASE1);	return req;}static int eap_fast_phase1_done(struct eap_sm *sm, struct eap_fast_data *data){	char cipher[64];	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase1 done, starting Phase2");	if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher))	    < 0) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to get cipher "			   "information");		eap_fast_state(data, FAILURE);		return -1;	}	data->anon_provisioning = os_strstr(cipher, "ADH") != NULL;		    	if (data->anon_provisioning) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Anonymous provisioning");		eap_fast_derive_key_provisioning(sm, data);	} else		eap_fast_derive_key_auth(sm, data);	eap_fast_state(data, PHASE2_START);	return 0;}static struct wpabuf * eap_fast_build_phase2_req(struct eap_sm *sm,						 struct eap_fast_data *data,						 u8 id){	struct wpabuf *req;	if (data->phase2_priv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not "			   "initialized");		return NULL;	}	req = data->phase2_method->buildReq(sm, data->phase2_priv, id);	if (req == NULL)		return NULL;	wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-FAST: Phase 2 EAP-Request", req);	return eap_fast_tlv_eap_payload(req);}static struct wpabuf * eap_fast_build_crypto_binding(	struct eap_sm *sm, struct eap_fast_data *data){	struct wpabuf *buf;	struct eap_tlv_result_tlv *result;	struct eap_tlv_crypto_binding_tlv *binding;	buf = wpabuf_alloc(2 * sizeof(*result) + sizeof(*binding));	if (buf == NULL)		return NULL;	if (data->send_new_pac || data->anon_provisioning ||	    data->phase2_method)		data->final_result = 0;	else		data->final_result = 1;	if (!data->final_result || data->eap_seq > 1) {		/* Intermediate-Result */		wpa_printf(MSG_DEBUG, "EAP-FAST: Add Intermediate-Result TLV "			   "(status=SUCCESS)");		result = wpabuf_put(buf, sizeof(*result));		result->tlv_type = host_to_be16(			EAP_TLV_TYPE_MANDATORY |			EAP_TLV_INTERMEDIATE_RESULT_TLV);		result->length = host_to_be16(2);		result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);	}	if (data->final_result) {		/* Result TLV */		wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV "			   "(status=SUCCESS)");		result = wpabuf_put(buf, sizeof(*result));		result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |						EAP_TLV_RESULT_TLV);		result->length = host_to_be16(2);		result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);	}	/* Crypto-Binding TLV */	binding = wpabuf_put(buf, sizeof(*binding));	binding->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |					 EAP_TLV_CRYPTO_BINDING_TLV);	binding->length = host_to_be16(sizeof(*binding) -				       sizeof(struct eap_tlv_hdr));	binding->version = EAP_FAST_VERSION;	binding->received_version = data->peer_version;	binding->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST;	if (os_get_random(binding->nonce, sizeof(binding->nonce)) < 0) {		wpabuf_free(buf);		return NULL;	}	/*	 * RFC 4851, Section 4.2.8:	 * The nonce in a request MUST have its least significant bit set to 0.	 */	binding->nonce[sizeof(binding->nonce) - 1] &= ~0x01;	os_memcpy(data->crypto_binding_nonce, binding->nonce,		  sizeof(binding->nonce));	/*	 * RFC 4851, Section 5.3:	 * CMK = CMK[j]	 * Compound-MAC = HMAC-SHA1( CMK, Crypto-Binding TLV )	 */	hmac_sha1(data->cmk, EAP_FAST_CMK_LEN,		  (u8 *) binding, sizeof(*binding),		  binding->compound_mac);	wpa_printf(MSG_DEBUG, "EAP-FAST: Add Crypto-Binding TLV: Version %d "		   "Received Version %d SubType %d",		   binding->version, binding->received_version,		   binding->subtype);	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE",		    binding->nonce, sizeof(binding->nonce));	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC",		    binding->compound_mac, sizeof(binding->compound_mac));	return buf;}static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,					  struct eap_fast_data *data){	u8 pac_key[EAP_FAST_PAC_KEY_LEN];	u8 *pac_buf, *pac_opaque;	struct wpabuf *buf;	u8 *pos;	size_t buf_len, srv_id_info_len, pac_len;	struct eap_tlv_hdr *pac_tlv;	struct pac_tlv_hdr *pac_info;	struct eap_tlv_result_tlv *result;	struct os_time now;	if (os_get_random(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 ||	    os_get_time(&now) < 0)		return NULL;	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key",			pac_key, EAP_FAST_PAC_KEY_LEN);	pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) +		(2 + sm->identity_len) + 8;	pac_buf = os_malloc(pac_len);	if (pac_buf == NULL)		return NULL;	srv_id_info_len = os_strlen(data->srv_id_info);	pos = pac_buf;	*pos++ = PAC_OPAQUE_TYPE_KEY;	*pos++ = EAP_FAST_PAC_KEY_LEN;	os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN);	pos += EAP_FAST_PAC_KEY_LEN;	*pos++ = PAC_OPAQUE_TYPE_LIFETIME;	*pos++ = 4;	WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime);	pos += 4;	if (sm->identity) {		*pos++ = PAC_OPAQUE_TYPE_IDENTITY;		*pos++ = sm->identity_len;		os_memcpy(pos, sm->identity, sm->identity_len);		pos += sm->identity_len;	}	pac_len = pos - pac_buf;	while (pac_len % 8) {		*pos++ = PAC_OPAQUE_TYPE_PAD;		pac_len++;	}	pac_opaque = os_malloc(pac_len + 8);	if (pac_opaque == NULL) {		os_free(pac_buf);		return NULL;	}	if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf,		     pac_opaque) < 0) {		os_free(pac_buf);		os_free(pac_opaque);		return NULL;	}	os_free(pac_buf);	pac_len += 8;	wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque",		    pac_opaque, pac_len);	buf_len = sizeof(*pac_tlv) +		sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN +		sizeof(struct pac_tlv_hdr) + pac_len +		data->srv_id_len + srv_id_info_len + 100 + sizeof(*result);	buf = wpabuf_alloc(buf_len);	if (buf == NULL) {		os_free(pac_opaque);		return NULL;	}	/* Result TLV */	wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)");	result = wpabuf_put(buf, sizeof(*result));	WPA_PUT_BE16((u8 *) &result->tlv_type,		     EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV);	WPA_PUT_BE16((u8 *) &result->length, 2);	WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS);	/* PAC TLV */	wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV");	pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv));	pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |					 EAP_TLV_PAC_TLV);	/* PAC-Key */	eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN);	/* PAC-Opaque */	eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len);	os_free(pac_opaque);	/* PAC-Info */	pac_info = wpabuf_put(buf, sizeof(*pac_info));	pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO);	/* PAC-Lifetime (inside PAC-Info) */	eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4);	wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime);	/* A-ID (inside PAC-Info) */	eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);		/* Note: headers may be misaligned after A-ID */	/* A-ID-Info (inside PAC-Info) */	eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info,			 srv_id_info_len);	/* PAC-Type (inside PAC-Info) */	eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2);	wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC);	/* Update PAC-Info and PAC TLV Length fields */	pos = wpabuf_put(buf, 0);	pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1));	pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1));	return buf;}static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id){	struct eap_fast_data *data = priv;	struct wpabuf *req = NULL;	struct wpabuf *encr;	if (data->ssl.state == FRAG_ACK) {		return eap_server_tls_build_ack(id, EAP_TYPE_FAST,						data->fast_version);	}	if (data->ssl.state == WAIT_FRAG_ACK) {		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST,						data->fast_version, id);	}	switch (data->state) {	case START:		return eap_fast_build_start(sm, data, id);	case PHASE1:		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {			if (eap_fast_phase1_done(sm, data) < 0)				return NULL;		}		break;	case PHASE2_ID:	case PHASE2_METHOD:		req = eap_fast_build_phase2_req(sm, data, id);		break;	case CRYPTO_BINDING:		req = eap_fast_build_crypto_binding(sm, data);		if (data->phase2_method) {			/*			 * Include the start of the next EAP method in the			 * sequence in the same message with Crypto-Binding to			 * save a round-trip.			 */			struct wpabuf *eap;			eap = eap_fast_build_phase2_req(sm, data, id);			req = wpabuf_concat(req, eap);			eap_fast_state(data, PHASE2_METHOD);		}		break;	case REQUEST_PAC:		req = eap_fast_build_pac(sm, data);		break;	default:		wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d",			   __func__, data->state);		return NULL;	}	if (req) {		wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 "				    "TLVs", req);		encr = eap_server_tls_encrypt(sm, &data->ssl,					      wpabuf_mhead(req),					      wpabuf_len(req));		wpabuf_free(req);		wpabuf_free(data->ssl.out_buf);		data->ssl.out_used = 0;		data->ssl.out_buf = encr;	}	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST,					data->fast_version, id);}static Boolean eap_fast_check(struct eap_sm *sm, void *priv,			      struct wpabuf *respData){	const u8 *pos;	size_t len;	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData, &len);	if (pos == NULL || len < 1) {		wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame");		return TRUE;	}	return FALSE;}static int eap_fast_phase2_init(struct eap_sm *sm, struct eap_fast_data *data,				EapType eap_type){	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_server_get_eap_method(EAP_VENDOR_IETF,							eap_type);	if (!data->phase2_method)		return -1;	if (data->key_block_p) {		sm->auth_challenge = data->key_block_p->server_challenge;		sm->peer_challenge = data->key_block_p->client_challenge;	}	sm->init_phase2 = 1;	data->phase2_priv = data->phase2_method->init(sm);	sm->init_phase2 = 0;	sm->auth_challenge = NULL;	sm->peer_challenge = NULL;	return data->phase2_priv == NULL ? -1 : 0;}static void eap_fast_process_phase2_response(struct eap_sm *sm,					     struct eap_fast_data *data,					     u8 *in_data, size_t in_len){	u8 next_type = EAP_TYPE_NONE;	struct eap_hdr *hdr;	u8 *pos;	size_t left;	struct wpabuf buf;	const struct eap_method *m = data->phase2_method;	void *priv = data->phase2_priv;	if (priv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: %s - Phase2 not "			   "initialized?!", __func__);		return;	}	hdr = (struct eap_hdr *) in_data;	pos = (u8 *) (hdr + 1);	if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {		left = in_len - sizeof(*hdr);		wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; "			    "allowed types", pos + 1, left - 1);#ifdef EAP_TNC		if (m && m->vendor == EAP_VENDOR_IETF &&		    m->method == EAP_TYPE_TNC) {			wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required "				   "TNC negotiation");			next_type = eap_fast_req_failure(sm, data);			eap_fast_phase2_init(sm, data, next_type);			return;		}#endif /* EAP_TNC */		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-FAST: try EAP type %d",				   next_type);		} else {			next_type = eap_fast_req_failure(sm, data);		}		eap_fast_phase2_init(sm, data, next_type);		return;	}	wpabuf_set(&buf, in_data, in_len);	if (m->check(sm, priv, &buf)) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 check() asked to "			   "ignore the packet");		next_type = eap_fast_req_failure(sm, data);		return;	}	m->process(sm, priv, &buf);	if (!m->isDone(sm, priv))		return;	if (!m->isSuccess(sm, priv)) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method failed");		next_type = eap_fast_req_failure(sm, data);		eap_fast_phase2_init(sm, data, next_type);		return;	}	switch (data->state) {	case PHASE2_ID:		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {			wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Phase2 "					  "Identity not found in the user "					  "database",					  sm->identity, sm->identity_len);			next_type = eap_fast_req_failure(sm, data);			break;		}		eap_fast_state(data, PHASE2_METHOD);		if (data->anon_provisioning) {			/*			 * Only EAP-MSCHAPv2 is allowed for anonymous			 * provisioning.			 */			next_type = EAP_TYPE_MSCHAPV2;			sm->user_eap_method_index = 0;		} else {			next_type = sm->user->methods[0].method;			sm->user_eap_method_index = 1;		}		wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", next_type);		break;	case PHASE2_METHOD:	case CRYPTO_BINDING:		eap_fast_update_icmk(sm, data);		eap_fast_state(data, CRYPTO_BINDING);		data->eap_seq++;		next_type = EAP_TYPE_NONE;#ifdef EAP_TNC		if (sm->tnc && !data->tnc_started) {			wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC");			next_type = EAP_TYPE_TNC;			data->tnc_started = 1;		}#endif /* EAP_TNC */		break;	case FAILURE:		break;	default:		wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d",			   __func__, data->state);		break;	}	eap_fast_phase2_init(sm, data, next_type);}static void eap_fast_process_phase2_eap(struct eap_sm *sm,					struct eap_fast_data *data,					u8 *in_data, size_t in_len){	struct eap_hdr *hdr;	size_t len;	hdr = (struct eap_hdr *) in_data;	if (in_len < (int) sizeof(*hdr)) {		wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 "			   "EAP frame (len=%lu)", (unsigned long) in_len);		eap_fast_req_failure(sm, data);		return;	}	len = be_to_host16(hdr->length);	if (len > in_len) {		wpa_printf(MSG_INFO, "EAP-FAST: Length mismatch in "			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",			   (unsigned long) in_len, (unsigned long) len);		eap_fast_req_failure(sm, data);		return;	}	wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: code=%d "		   "identifier=%d length=%lu", hdr->code, hdr->identifier,		   (unsigned long) len);

⌨️ 快捷键说明

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