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

📄 eap_peap.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");		eap_peap_req_failure(sm, data);		next_type = EAP_TYPE_NONE;		eap_peap_phase2_init(sm, data, next_type);		return;	}	os_free(data->phase2_key);	if (data->phase2_method->getKey) {		data->phase2_key = data->phase2_method->getKey(			sm, data->phase2_priv, &data->phase2_key_len);		if (data->phase2_key == NULL) {			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "				   "failed");			eap_peap_req_failure(sm, data);			eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);			return;		}		if (data->phase2_key_len == 32 &&		    data->phase2_method->vendor == EAP_VENDOR_IETF &&		    data->phase2_method->method == EAP_TYPE_MSCHAPV2) {			/*			 * Microsoft uses reverse order for MS-MPPE keys in			 * EAP-PEAP when compared to EAP-FAST derivation of			 * ISK. Swap the keys here to get the correct ISK for			 * EAP-PEAPv0 cryptobinding.			 */			u8 tmp[16];			os_memcpy(tmp, data->phase2_key, 16);			os_memcpy(data->phase2_key, data->phase2_key + 16, 16);			os_memcpy(data->phase2_key + 16, tmp, 16);		}	}	switch (data->state) {	case PHASE1_ID2:	case PHASE2_ID:	case PHASE2_SOH:		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {			wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "					  "Identity not found in the user "					  "database",					  sm->identity, sm->identity_len);			eap_peap_req_failure(sm, data);			next_type = EAP_TYPE_NONE;			break;		}#ifdef EAP_TNC		if (data->state != PHASE2_SOH && sm->tnc &&		    data->peap_version == 0) {			eap_peap_state(data, PHASE2_SOH);			wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "				   "TNC (NAP SOH)");			next_type = EAP_TYPE_NONE;			break;		}#endif /* EAP_TNC */		eap_peap_state(data, PHASE2_METHOD);		next_type = sm->user->methods[0].method;		sm->user_eap_method_index = 1;		wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);		break;	case PHASE2_METHOD:		eap_peap_req_success(sm, data);		next_type = EAP_TYPE_NONE;		break;	case FAILURE:		break;	default:		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",			   __func__, data->state);		break;	}	eap_peap_phase2_init(sm, data, next_type);}static void eap_peap_process_phase2(struct eap_sm *sm,				    struct eap_peap_data *data,				    const struct wpabuf *respData,				    struct wpabuf *in_buf){	struct wpabuf *in_decrypted;	int len_decrypted;	const struct eap_hdr *hdr;	size_t buf_len, len;	u8 *in_data;	size_t in_len;	in_data = wpabuf_mhead(in_buf);	in_len = wpabuf_len(in_buf);	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"		   " Phase 2", (unsigned long) in_len);	if (data->pending_phase2_resp) {		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "			   "skip decryption and use old data");		eap_peap_process_phase2_response(sm, data,						 data->pending_phase2_resp);		wpabuf_free(data->pending_phase2_resp);		data->pending_phase2_resp = NULL;		return;	}	buf_len = in_len;	/*	 * Even though we try to disable TLS compression, it is possible that	 * this cannot be done with all TLS libraries. Add extra buffer space	 * to handle the possibility of the decrypted data being longer than	 * input data.	 */	buf_len += 500;	buf_len *= 3;	in_decrypted = wpabuf_alloc(buf_len);	if (in_decrypted == NULL) {		wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "			   "for decryption");		return;	}	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,					       in_data, in_len,					       wpabuf_mhead(in_decrypted),					       buf_len);	if (len_decrypted < 0) {		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "			   "data");		wpabuf_free(in_decrypted);		eap_peap_state(data, FAILURE);		return;	}	wpabuf_put(in_decrypted, len_decrypted);	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",			    in_decrypted);	hdr = wpabuf_head(in_decrypted);	if (data->peap_version == 0 && data->state != PHASE2_TLV) {		const struct eap_hdr *resp;		struct eap_hdr *nhdr;		struct wpabuf *nbuf =			wpabuf_alloc(sizeof(struct eap_hdr) +				     wpabuf_len(in_decrypted));		if (nbuf == NULL) {			wpabuf_free(in_decrypted);			return;		}		resp = wpabuf_head(respData);		nhdr = wpabuf_put(nbuf, sizeof(*nhdr));		nhdr->code = resp->code;		nhdr->identifier = resp->identifier;		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +					    wpabuf_len(in_decrypted));		wpabuf_put_buf(nbuf, in_decrypted);		wpabuf_free(in_decrypted);		in_decrypted = nbuf;	} else if (data->peap_version >= 2) {		struct eap_tlv_hdr *tlv;		struct wpabuf *nmsg;		if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {			wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "				   "EAP TLV");			wpabuf_free(in_decrypted);			return;		}		tlv = wpabuf_mhead(in_decrypted);		if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=		    EAP_TLV_EAP_PAYLOAD_TLV) {			wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");			wpabuf_free(in_decrypted);			return;		}		if (sizeof(*tlv) + be_to_host16(tlv->length) >		    wpabuf_len(in_decrypted)) {			wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "				   "length");			wpabuf_free(in_decrypted);			return;		}		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;		}		nmsg = wpabuf_alloc(be_to_host16(hdr->length));		if (nmsg == NULL) {			wpabuf_free(in_decrypted);			return;		}		wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));		wpabuf_free(in_decrypted);		in_decrypted = nmsg;	}	hdr = wpabuf_head(in_decrypted);	if (wpabuf_len(in_decrypted) < (int) 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);		eap_peap_req_failure(sm, data);		return;	}	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);		eap_peap_req_failure(sm, data);		return;	}	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_RESPONSE:		eap_peap_process_phase2_response(sm, data, in_decrypted);		break;	case EAP_CODE_SUCCESS:		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");		if (data->state == SUCCESS_REQ) {			eap_peap_state(data, SUCCESS);		}		break;	case EAP_CODE_FAILURE:		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");		eap_peap_state(data, FAILURE);		break;	default:		wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "			   "Phase 2 EAP header", hdr->code);		break;	}	os_free(in_decrypted);}static int eap_peapv2_start_phase2(struct eap_sm *sm,				   struct eap_peap_data *data){	struct wpabuf *buf, *buf2;	int res;	wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "		   "payload in the same message");	eap_peap_state(data, PHASE1_ID2);	if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))		return -1;	/* TODO: which Id to use here? */	buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);	if (buf == NULL)		return -1;	buf2 = eap_peapv2_tlv_eap_payload(buf);	if (buf2 == NULL)		return -1;	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);	buf = wpabuf_alloc(data->ssl.tls_out_limit);	if (buf == NULL) {		wpabuf_free(buf2);		return -1;	}	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,				     wpabuf_head(buf2), wpabuf_len(buf2),				     wpabuf_put(buf, 0),				     data->ssl.tls_out_limit);	wpabuf_free(buf2);	if (res < 0) {		wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "			   "data");		wpabuf_free(buf);		return -1;	}	wpabuf_put(buf, res);	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",			buf);	/* Append TLS data into the pending buffer after the Server Finished */	if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {		wpabuf_free(buf);		return -1;	}	wpabuf_put_buf(data->ssl.out_buf, buf);	wpabuf_free(buf);	return 0;}static int eap_peap_process_version(struct eap_sm *sm, void *priv,				    int peer_version){	struct eap_peap_data *data = priv;	data->recv_version = peer_version;	if (data->force_version >= 0 && peer_version != data->force_version) {		wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"			   " version (forced=%d peer=%d) - reject",			   data->force_version, peer_version);		return -1;	}	if (peer_version < data->peap_version) {		wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "			   "use version %d",			   peer_version, data->peap_version, peer_version);		data->peap_version = peer_version;	}	return 0;}static void eap_peap_process_msg(struct eap_sm *sm, void *priv,				 const struct wpabuf *respData){	struct eap_peap_data *data = priv;	switch (data->state) {	case PHASE1:		if (eap_server_tls_phase1(sm, &data->ssl) < 0) {			eap_peap_state(data, FAILURE);			break;		}		if (data->peap_version >= 2 &&		    tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {			if (eap_peapv2_start_phase2(sm, data)) {				eap_peap_state(data, FAILURE);				break;			}		}		break;	case PHASE2_START:		eap_peap_state(data, PHASE2_ID);		eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);		break;	case PHASE1_ID2:	case PHASE2_ID:	case PHASE2_METHOD:	case PHASE2_SOH:	case PHASE2_TLV:		eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf);		break;	case SUCCESS_REQ:		eap_peap_state(data, SUCCESS);		break;	case FAILURE_REQ:		eap_peap_state(data, FAILURE);		break;	default:		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",			   data->state, __func__);		break;	}}static void eap_peap_process(struct eap_sm *sm, void *priv,			     struct wpabuf *respData){	struct eap_peap_data *data = priv;	if (eap_server_tls_process(sm, &data->ssl, respData, data,				   EAP_TYPE_PEAP, eap_peap_process_version,				   eap_peap_process_msg) < 0)		eap_peap_state(data, FAILURE);}static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv){	struct eap_peap_data *data = priv;	return data->state == SUCCESS || data->state == FAILURE;}static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len){	struct eap_peap_data *data = priv;	u8 *eapKeyData;	if (data->state != SUCCESS)		return NULL;	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));		eapKeyData = os_malloc(EAP_TLS_KEY_LEN);		if (eapKeyData) {			os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);			*len = EAP_TLS_KEY_LEN;			wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",				    eapKeyData, EAP_TLS_KEY_LEN);		} else {			wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "				   "key");		}		return eapKeyData;	}	/* TODO: PEAPv1 - different label in some cases */	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,					       "client EAP encryption",					       EAP_TLS_KEY_LEN);	if (eapKeyData) {		*len = EAP_TLS_KEY_LEN;		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",			    eapKeyData, EAP_TLS_KEY_LEN);	} else {		wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");	}	return eapKeyData;}static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv){	struct eap_peap_data *data = priv;	return data->state == SUCCESS;}int eap_server_peap_register(void){	struct eap_method *eap;	int ret;	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,				      EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");	if (eap == NULL)		return -1;	eap->init = eap_peap_init;	eap->reset = eap_peap_reset;	eap->buildReq = eap_peap_buildReq;	eap->check = eap_peap_check;	eap->process = eap_peap_process;	eap->isDone = eap_peap_isDone;	eap->getKey = eap_peap_getKey;	eap->isSuccess = eap_peap_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 + -