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

📄 wpa.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
				   const char *reason, const u8 *src_addr,				   const u8 *wpa_ie, size_t wpa_ie_len,				   const u8 *rsn_ie, size_t rsn_ie_len){	wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",		reason, MAC2STR(src_addr));	if (sm->ap_wpa_ie) {		wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",			    sm->ap_wpa_ie, sm->ap_wpa_ie_len);	}	if (wpa_ie) {		if (!sm->ap_wpa_ie) {			wpa_printf(MSG_INFO, "WPA: No WPA IE in "				   "Beacon/ProbeResp");		}		wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",			    wpa_ie, wpa_ie_len);	}	if (sm->ap_rsn_ie) {		wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",			    sm->ap_rsn_ie, sm->ap_rsn_ie_len);	}	if (rsn_ie) {		if (!sm->ap_rsn_ie) {			wpa_printf(MSG_INFO, "WPA: No RSN IE in "				   "Beacon/ProbeResp");		}		wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",			    rsn_ie, rsn_ie_len);	}	wpa_sm_disassociate(sm, REASON_IE_IN_4WAY_DIFFERS);	wpa_sm_req_scan(sm, 0, 0);}static int wpa_supplicant_validate_ie(struct wpa_sm *sm,				      const unsigned char *src_addr,				      struct wpa_eapol_ie_parse *ie){	struct wpa_ssid *ssid = sm->cur_ssid;	if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {		wpa_printf(MSG_DEBUG, "WPA: No WPA/RSN IE for this AP known. "			   "Trying to get from scan results");		if (wpa_sm_get_beacon_ie(sm) < 0) {			wpa_printf(MSG_WARNING, "WPA: Could not find AP from "				   "the scan results");		} else {			wpa_printf(MSG_DEBUG, "WPA: Found the current AP from "				   "updated scan results");		}	}	if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&	    (sm->ap_wpa_ie || sm->ap_rsn_ie)) {		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "				       "with IE in Beacon/ProbeResp (no IE?)",				       src_addr, ie->wpa_ie, ie->wpa_ie_len,				       ie->rsn_ie, ie->rsn_ie_len);		return -1;	}	if ((ie->wpa_ie && sm->ap_wpa_ie &&	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||	      os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||	    (ie->rsn_ie && sm->ap_rsn_ie &&	     (ie->rsn_ie_len != sm->ap_rsn_ie_len ||	      os_memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) {		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "				       "with IE in Beacon/ProbeResp",				       src_addr, ie->wpa_ie, ie->wpa_ie_len,				       ie->rsn_ie, ie->rsn_ie_len);		return -1;	}	if (sm->proto == WPA_PROTO_WPA &&	    ie->rsn_ie && sm->ap_rsn_ie == NULL &&	    ssid && (ssid->proto & WPA_PROTO_RSN)) {		wpa_report_ie_mismatch(sm, "Possible downgrade attack "				       "detected - RSN was enabled and RSN IE "				       "was in msg 3/4, but not in "				       "Beacon/ProbeResp",				       src_addr, ie->wpa_ie, ie->wpa_ie_len,				       ie->rsn_ie, ie->rsn_ie_len);		return -1;	}	return 0;}static int wpa_supplicant_send_4_of_4(struct wpa_sm *sm,				      const unsigned char *dst,				      const struct wpa_eapol_key *key,				      u16 ver, u16 key_info,				      const u8 *kde, size_t kde_len,				      struct wpa_ptk *ptk){	size_t rlen;	struct wpa_eapol_key *reply;	u8 *rbuf;	if (kde)		wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len);	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,				  sizeof(*reply) + kde_len,				  &rlen, (void *) &reply);	if (rbuf == NULL)		return -1;	reply->type = sm->proto == WPA_PROTO_RSN ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info &= WPA_KEY_INFO_SECURE;	key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;	WPA_PUT_BE16(reply->key_info, key_info);	if (sm->proto == WPA_PROTO_RSN)		WPA_PUT_BE16(reply->key_length, 0);	else		os_memcpy(reply->key_length, key->key_length, 2);	os_memcpy(reply->replay_counter, key->replay_counter,		  WPA_REPLAY_COUNTER_LEN);	WPA_PUT_BE16(reply->key_data_length, kde_len);	if (kde)		os_memcpy(reply + 1, kde, kde_len);	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,			   rbuf, rlen, reply->key_mic);	return 0;}static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,					  const struct wpa_eapol_key *key,					  u16 ver){	u16 key_info, keylen, len;	const u8 *pos;	struct wpa_eapol_ie_parse ie;	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);	wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from "		   MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);	key_info = WPA_GET_BE16(key->key_info);	pos = (const u8 *) (key + 1);	len = WPA_GET_BE16(key->key_data_length);	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len);	wpa_supplicant_parse_ies(pos, len, &ie);	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {		wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data");		return;	}#ifdef CONFIG_IEEE80211W	if ((ie.dhv || ie.igtk) && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {		wpa_printf(MSG_WARNING, "WPA: DHV/IGTK KDE in unencrypted key "			   "data");		return;	}	if (ie.dhv && ie.dhv_len != sizeof(struct wpa_dhv_kde)) {		wpa_printf(MSG_WARNING, "WPA: Invalid DHV KDE length %lu",			   (unsigned long) ie.dhv_len);		return;	}	if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) {		wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KDE length %lu",			   (unsigned long) ie.igtk_len);		return;	}#endif /* CONFIG_IEEE80211W */	if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)		return;	if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {		wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way "			   "Handshake differs from 3 of 4-Way Handshake - drop"			   " packet (src=" MACSTR ")", MAC2STR(sm->bssid));		return;	}	keylen = WPA_GET_BE16(key->key_length);	switch (sm->pairwise_cipher) {	case WPA_CIPHER_CCMP:		if (keylen != 16) {			wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length "				   "%d (src=" MACSTR ")",				   keylen, MAC2STR(sm->bssid));			return;		}		break;	case WPA_CIPHER_TKIP:		if (keylen != 32) {			wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length "				   "%d (src=" MACSTR ")",				   keylen, MAC2STR(sm->bssid));			return;		}		break;	}	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,				       NULL, 0, &sm->ptk))		return;	/* SNonce was successfully used in msg 3/4, so mark it to be renewed	 * for the next 4-Way Handshake. If msg 3 is received again, the old	 * SNonce will still be used to avoid changing PTK. */	sm->renew_snonce = 1;	if (key_info & WPA_KEY_INFO_INSTALL) {		wpa_supplicant_install_ptk(sm, key);	}	if (key_info & WPA_KEY_INFO_SECURE) {		wpa_sm_mlme_setprotection(			sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);		eapol_sm_notify_portValid(sm->eapol, TRUE);	}	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);	if (ie.gtk &&	    wpa_supplicant_pairwise_gtk(sm, key,					ie.gtk, ie.gtk_len, key_info) < 0) {		wpa_printf(MSG_INFO, "RSN: Failed to configure GTK");	}	if (ieee80211w_set_keys(sm, &ie) < 0)		wpa_printf(MSG_INFO, "RSN: Failed to configure DHV/IGTK");}#ifdef CONFIG_PEERKEYstatic void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx){#if 0	struct wpa_sm *sm = eloop_ctx;	struct wpa_peerkey *peerkey = timeout_ctx;#endif	/* TODO: time out SMK and any STK that was generated using this SMK */}static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,					struct wpa_peerkey *peerkey){	eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);	os_free(peerkey);}static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,					 const u8 *peer,					 u16 mui, u16 error_type, int ver){#ifndef CONFIG_NO_WPA2	size_t rlen;	struct wpa_eapol_key *err;	struct rsn_error_kde error;	u8 *rbuf, *pos;	size_t kde_len;	u16 key_info;	kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);	if (peer)		kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,				  NULL, sizeof(*err) + kde_len, &rlen,				  (void *) &err);	if (rbuf == NULL)		return -1;	err->type = EAPOL_KEY_TYPE_RSN;	key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |		WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |		WPA_KEY_INFO_REQUEST;	WPA_PUT_BE16(err->key_info, key_info);	WPA_PUT_BE16(err->key_length, 0);	os_memcpy(err->replay_counter, sm->request_counter,		  WPA_REPLAY_COUNTER_LEN);	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);	WPA_PUT_BE16(err->key_data_length, (u16) kde_len);	pos = (u8 *) (err + 1);	if (peer) {		/* Peer MAC Address KDE */		pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);	}	/* Error KDE */	error.mui = host_to_be16(mui);	error.error_type = host_to_be16(error_type);	pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,			  (u8 *) &error, sizeof(error));	if (peer) {		wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "			   MACSTR " mui %d error_type %d)",			   MAC2STR(peer), mui, error_type);	} else {		wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "			   "(mui %d error_type %d)", mui, error_type);	}	wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,			   rbuf, rlen, err->key_mic);	return 0;#else /* CONFIG_NO_WPA2 */	return -1;#endif /* CONFIG_NO_WPA2 */}static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,				      const unsigned char *src_addr,				      const struct wpa_eapol_key *key,				      int ver, struct wpa_peerkey *peerkey){	size_t rlen;	struct wpa_eapol_key *reply;	u8 *rbuf, *pos;	size_t kde_len;	u16 key_info;	/* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */	kde_len = peerkey->rsnie_p_len +		2 + RSN_SELECTOR_LEN + ETH_ALEN +		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,				  NULL, sizeof(*reply) + kde_len, &rlen,				  (void *) &reply);	if (rbuf == NULL)		return -1;	reply->type = EAPOL_KEY_TYPE_RSN;	key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |		WPA_KEY_INFO_SECURE;	WPA_PUT_BE16(reply->key_info, key_info);	WPA_PUT_BE16(reply->key_length, 0);	os_memcpy(reply->replay_counter, key->replay_counter,		  WPA_REPLAY_COUNTER_LEN);	os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);	WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);	pos = (u8 *) (reply + 1);	/* Peer RSN IE */	pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);	/* Initiator MAC Address KDE */	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);	/* Initiator Nonce */	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE,			  peerkey->inonce, WPA_NONCE_LEN);	wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");	wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,			   rbuf, rlen, reply->key_mic);	return 0;}static int wpa_supplicant_process_smk_m2(	struct wpa_sm *sm, const unsigned char *src_addr,	const struct wpa_eapol_key *key, size_t extra_len, int ver){	struct wpa_ssid *ssid = sm->cur_ssid;	struct wpa_peerkey *peerkey;	struct wpa_eapol_ie_parse kde;	struct wpa_ie_data ie;	int cipher;	struct rsn_ie_hdr *hdr;	u8 *pos;	wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");	if (ssid == NULL || !ssid->peerkey || sm->proto != WPA_PROTO_RSN) {		wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "			   "the current network");		return -1;	}	if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <	    0) {		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");		return -1;	}	if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||	    kde.mac_addr_len < ETH_ALEN) {		wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "			   "SMK M2");		return -1;	}	wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,		   MAC2STR(kde.mac_addr));	if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {		wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "			   "M2");		return -1;	}	if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {		wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");		return -1;	}	cipher = ie.pairwise_cipher & ssid->pairwise_cipher;	if (cipher & WPA_CIPHER_CCMP) {		wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");		cipher = WPA_CIPHER_CCMP;	} else if (cipher & WPA_CIPHER_TKIP) {		wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");		cipher = WPA_CIPHER_TKIP;	} else {		wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");		wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,					      STK_MUI_SMK, STK_ERR_CPHR_NS,					      ver);		return -1;	}	/* TODO: find existing entry and if found, use that instead of adding	 * a new one; how to handle the case where both ends initiate at the	 * same time? */	peerkey = os_malloc(sizeof(*peerkey));	if (peerkey == NULL)		return -1;	os_memset(peerkey, 0, sizeof(*peerkey));	os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);	os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);	os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);	peerkey->rsnie_i_len = kde.rsn_ie_len;	peerkey->cipher = cipher;	if (hostapd_get_rand(peerkey->pnonce, WPA_NONCE_LEN)) {		wpa_msg(sm->ctx->ctx, MSG_WARNING,			"WPA: Failed to get random data for PNonce");		wpa_supplicant_peerkey_free(sm, peerkey);		return -1;	}	hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;	hdr->elem_id = RSN_INFO_ELEM;	WPA_PUT_LE16(hdr->version, RSN_VERSION);	pos = (u8 *) (hdr + 1);	/* Group

⌨️ 快捷键说明

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