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

📄 wpa.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	}}static void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,			       int ver, const u8 *dest, u16 proto,			       u8 *msg, size_t msg_len, u8 *key_mic){	if (os_memcmp(dest, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 &&	    os_memcmp(sm->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) {		/*		 * Association event was not yet received; try to fetch		 * BSSID from the driver.		 */		if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {			wpa_printf(MSG_DEBUG, "WPA: Failed to read BSSID for "				   "EAPOL-Key destination address");		} else {			dest = sm->bssid;			wpa_printf(MSG_DEBUG, "WPA: Use BSSID (" MACSTR				   ") as the destination for EAPOL-Key",				   MAC2STR(dest));		}	}	if (key_mic) {		wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic);	}	wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);	wpa_sm_ether_send(sm, dest, proto, msg, msg_len);	eapol_sm_notify_tx_eapol_key(sm->eapol);	os_free(msg);}/** * wpa_sm_key_request - Send EAPOL-Key Request * @sm: Pointer to WPA state machine data from wpa_sm_init() * @error: Indicate whether this is an Michael MIC error report * @pairwise: 1 = error report for pairwise packet, 0 = for group packet * Returns: Pointer to the current network structure or %NULL on failure * * Send an EAPOL-Key Request to the current authenticator. This function is * used to request rekeying and it is usually called when a local Michael MIC * failure is detected. */void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise){	size_t rlen;	struct wpa_eapol_key *reply;	int key_info, ver;	u8 bssid[ETH_ALEN], *rbuf;	if (sm->pairwise_cipher == WPA_CIPHER_CCMP)		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;	else		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	if (wpa_sm_get_bssid(sm, bssid) < 0) {		wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "			   "request");		return;	}	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,				  sizeof(*reply), &rlen, (void *) &reply);	if (rbuf == NULL)		return;	reply->type = sm->proto == WPA_PROTO_RSN ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info = WPA_KEY_INFO_REQUEST | ver;	if (sm->ptk_set)		key_info |= WPA_KEY_INFO_MIC;	if (error)		key_info |= WPA_KEY_INFO_ERROR;	if (pairwise)		key_info |= WPA_KEY_INFO_KEY_TYPE;	WPA_PUT_BE16(reply->key_info, key_info);	WPA_PUT_BE16(reply->key_length, 0);	os_memcpy(reply->replay_counter, sm->request_counter,		  WPA_REPLAY_COUNTER_LEN);	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);	WPA_PUT_BE16(reply->key_data_length, 0);	wpa_printf(MSG_INFO, "WPA: Sending EAPOL-Key Request (error=%d "		   "pairwise=%d ptk_set=%d len=%lu)",		   error, pairwise, sm->ptk_set, (unsigned long) rlen);	wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,			   rbuf, rlen, key_info & WPA_KEY_INFO_MIC ?			   reply->key_mic : NULL);}/** * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) * @sm: Pointer to WPA state machine data from wpa_sm_init() * @peer: MAC address of the peer STA * Returns: 0 on success, or -1 on failure * * Send an EAPOL-Key Request to the current authenticator to start STK * handshake with the peer. */int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer){#ifdef CONFIG_PEERKEY	size_t rlen, kde_len;	struct wpa_eapol_key *req;	int key_info, ver;	u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;	u16 count;	struct wpa_ssid *ssid = sm->cur_ssid;	struct rsn_ie_hdr *hdr;	struct wpa_peerkey *peerkey;	struct wpa_ie_data ie;	if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set ||	    ssid == NULL || !ssid->peerkey)		return -1;	if (sm->ap_rsn_ie &&	    wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&	    !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {		wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");		return -1;	}	if (sm->pairwise_cipher == WPA_CIPHER_CCMP)		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;	else		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	if (wpa_sm_get_bssid(sm, bssid) < 0) {		wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "			   "SMK M1");		return -1;	}	/* TODO: find existing entry and if found, use that instead of adding	 * a new one */	peerkey = os_malloc(sizeof(*peerkey));	if (peerkey == NULL)		return -1;	os_memset(peerkey, 0, sizeof(*peerkey));	peerkey->initiator = 1;	os_memcpy(peerkey->addr, peer, ETH_ALEN);	/* SMK M1:	 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,	 *           MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))	 */	hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;	hdr->elem_id = RSN_INFO_ELEM;	WPA_PUT_LE16(hdr->version, RSN_VERSION);	pos = (u8 *) (hdr + 1);	/* Group Suite can be anything for SMK RSN IE; receiver will just	 * ignore it. */	os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);	pos += RSN_SELECTOR_LEN;	count_pos = pos;	pos += 2;	count = 0;	if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) {		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		count++;	}	if (ssid->pairwise_cipher & WPA_CIPHER_TKIP) {		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		count++;	}	WPA_PUT_LE16(count_pos, count);	hdr->len = (pos - peerkey->rsnie_i) - 2;	peerkey->rsnie_i_len = pos - peerkey->rsnie_i;	wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",		    peerkey->rsnie_i, peerkey->rsnie_i_len);	kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,				  sizeof(*req) + kde_len, &rlen,				  (void *) &req);	if (rbuf == NULL) {		wpa_supplicant_peerkey_free(sm, peerkey);		return -1;	}	req->type = EAPOL_KEY_TYPE_RSN;	key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |		WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;	WPA_PUT_BE16(req->key_info, key_info);	WPA_PUT_BE16(req->key_length, 0);	os_memcpy(req->replay_counter, sm->request_counter,		  WPA_REPLAY_COUNTER_LEN);	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);	if (hostapd_get_rand(peerkey->inonce, WPA_NONCE_LEN)) {		wpa_msg(sm->ctx->ctx, MSG_WARNING,			"WPA: Failed to get random data for INonce");		os_free(rbuf);		wpa_supplicant_peerkey_free(sm, peerkey);		return -1;	}	os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);	wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",		    req->key_nonce, WPA_NONCE_LEN);	WPA_PUT_BE16(req->key_data_length, (u16) kde_len);	pos = (u8 *) (req + 1);	/* Initiator RSN IE */	pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);	/* Peer MAC address KDE */	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);	wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "		   MACSTR ")", MAC2STR(peer));	wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,			   rbuf, rlen, req->key_mic);	peerkey->next = sm->peerkey;	sm->peerkey = peerkey;	return 0;#else /* CONFIG_PEERKEY */	return -1;#endif /* CONFIG_PEERKEY */}struct wpa_eapol_ie_parse {	const u8 *wpa_ie;	size_t wpa_ie_len;	const u8 *rsn_ie;	size_t rsn_ie_len;	const u8 *pmkid;	const u8 *gtk;	size_t gtk_len;	const u8 *mac_addr;	size_t mac_addr_len;#ifdef CONFIG_PEERKEY	const u8 *smk;	size_t smk_len;	const u8 *nonce;	size_t nonce_len;	const u8 *lifetime;	size_t lifetime_len;	const u8 *error;	size_t error_len;#endif /* CONFIG_PEERKEY */#ifdef CONFIG_IEEE80211W	const u8 *dhv;	size_t dhv_len;	const u8 *igtk;	size_t igtk_len;#endif /* CONFIG_IEEE80211W */};/** * wpa_supplicant_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */static int wpa_supplicant_parse_generic(const u8 *pos, const u8 *end,					struct wpa_eapol_ie_parse *ie){	if (pos[1] == 0)		return 1;	if (pos[1] >= 6 &&	    os_memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 &&	    pos[2 + WPA_SELECTOR_LEN] == 1 &&	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {		ie->wpa_ie = pos;		ie->wpa_ie_len = pos[1] + 2;		return 0;	}	if (pos + 1 + RSN_SELECTOR_LEN < end &&	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&	    os_memcmp(pos + 2, RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN) == 0) {		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN) == 0) {		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_MAC_ADDR, RSN_SELECTOR_LEN) == 0) {		ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;		ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}#ifdef CONFIG_PEERKEY	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_SMK, RSN_SELECTOR_LEN) == 0) {		ie->smk = pos + 2 + RSN_SELECTOR_LEN;		ie->smk_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_NONCE, RSN_SELECTOR_LEN) == 0) {		ie->nonce = pos + 2 + RSN_SELECTOR_LEN;		ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_LIFETIME, RSN_SELECTOR_LEN) == 0) {		ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;		ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_ERROR, RSN_SELECTOR_LEN) == 0) {		ie->error = pos + 2 + RSN_SELECTOR_LEN;		ie->error_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}#endif /* CONFIG_PEERKEY */#ifdef CONFIG_IEEE80211W	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_DHV, RSN_SELECTOR_LEN) == 0) {		ie->dhv = pos + 2 + RSN_SELECTOR_LEN;		ie->dhv_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    os_memcmp(pos + 2, RSN_KEY_DATA_IGTK, RSN_SELECTOR_LEN) == 0) {		ie->igtk = pos + 2 + RSN_SELECTOR_LEN;		ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}#endif /* CONFIG_IEEE80211W */	return 0;}/** * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs * @buf: Pointer to the Key Data buffer * @len: Key Data Length * @ie: Pointer to parsed IE data * Returns: 0 on success, -1 on failure */static int wpa_supplicant_parse_ies(const u8 *buf, size_t len,				    struct wpa_eapol_ie_parse *ie){	const u8 *pos, *end;	int ret = 0;	os_memset(ie, 0, sizeof(*ie));	for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {		if (pos[0] == 0xdd &&		    ((pos == buf + len - 1) || pos[1] == 0)) {			/* Ignore padding */			break;		}		if (pos + 2 + pos[1] > end) {			wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "				   "underflow (ie=%d len=%d pos=%d)",				   pos[0], pos[1], (int) (pos - buf));			wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",					buf, len);			ret = -1;			break;		}		if (*pos == RSN_INFO_ELEM) {			ie->rsn_ie = pos;			ie->rsn_ie_len = pos[1] + 2;		} else if (*pos == GENERIC_INFO_ELEM) {			ret = wpa_supplicant_parse_generic(pos, end, ie);			if (ret < 0)				break;			if (ret > 0) {				ret = 0;				break;			}		} else {			wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "				    "Key Data IE", pos, 2 + pos[1]);		}	}	return ret;}static int wpa_supplicant_get_pmk(struct wpa_sm *sm,				  const unsigned char *src_addr,				  const u8 *pmkid){	int abort_cached = 0;	if (pmkid && !sm->cur_pmksa) {		/* When using drivers that generate RSN IE, wpa_supplicant may		 * not have enough time to get the association information		 * event before receiving this 1/4 message, so try to find a		 * matching PMKSA cache entry here. */		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid);		if (sm->cur_pmksa) {			wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from "				   "PMKSA cache");		} else {			wpa_printf(MSG_DEBUG, "RSN: no matching PMKID found");			abort_cached = 1;		}	}	if (pmkid && sm->cur_pmksa &&	    os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);		wpa_sm_set_pmk_from_pmksa(sm);		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",				sm->pmk, sm->pmk_len);		eapol_sm_notify_cached(sm->eapol);	} else if (sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X && sm->eapol) {		int res, pmk_len;		pmk_len = PMK_LEN;		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);		if (res) {			/*			 * EAP-LEAP is an exception from other EAP methods: it			 * uses only 16-byte PMK.			 */			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);			pmk_len = 16;		}		if (res == 0) {			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "					"machines", sm->pmk, pmk_len);			sm->pmk_len = pmk_len;			pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr,					sm->own_addr, sm->cur_ssid);			if (!sm->cur_pmksa && pmkid &&			    pmksa_cache_get(sm->pmksa, src_addr, pmkid)) {				wpa_printf(MSG_DEBUG, "RSN: the new PMK "					   "matches with the PMKID");				abort_cached = 0;			}		} else {			wpa_msg(sm->ctx->ctx, MSG_WARNING,				"WPA: Failed to get master session key from "				"EAPOL state machines");			wpa_msg(sm->ctx->ctx, MSG_WARNING,				"WPA: Key handshake aborted");			if (sm->cur_pmksa) {

⌨️ 快捷键说明

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