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

📄 wpa.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (left >= RSN_SELECTOR_LEN) {		data->group_cipher = rsn_selector_to_bitfield(pos);		pos += RSN_SELECTOR_LEN;		left -= RSN_SELECTOR_LEN;	} else if (left > 0)		  return -3;	if (left >= 2) {		data->pairwise_cipher = 0;		count = pos[0] | (pos[1] << 8);		pos += 2;		left -= 2;		if (count == 0 || left < count * RSN_SELECTOR_LEN)			return -4;		for (i = 0; i < count; i++) {			data->pairwise_cipher |= rsn_selector_to_bitfield(pos);			pos += RSN_SELECTOR_LEN;			left -= RSN_SELECTOR_LEN;		}	} else if (left == 1)		return -5;	if (left >= 2) {		data->key_mgmt = 0;		count = pos[0] | (pos[1] << 8);		pos += 2;		left -= 2;		if (count == 0 || left < count * RSN_SELECTOR_LEN)			return -6;		for (i = 0; i < count; i++) {			data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);			pos += RSN_SELECTOR_LEN;			left -= RSN_SELECTOR_LEN;		}	} else if (left == 1)		return -7;	if (left >= 2) {		data->capabilities = pos[0] | (pos[1] << 8);		pos += 2;		left -= 2;	}	if (left >= 2) {		data->num_pmkid = pos[0] | (pos[1] << 8);		pos += 2;		left -= 2;		if (left < data->num_pmkid * PMKID_LEN) {			wpa_printf(MSG_DEBUG, "RSN: too short RSN IE for "				   "PMKIDs (num=%lu, left=%d)",				   (unsigned long) data->num_pmkid, left);			return -9;		}		data->pmkid = pos;		pos += data->num_pmkid * PMKID_LEN;		left -= data->num_pmkid * PMKID_LEN;	}	if (left > 0) {		return -8;	}	return 0;}int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,			struct wpa_state_machine *sm,			const u8 *wpa_ie, size_t wpa_ie_len){	struct wpa_ie_data data;	int ciphers, key_mgmt, res, i, version;	const u8 *selector;	if (wpa_auth == NULL || sm == NULL)		return WPA_NOT_ENABLED;	if (wpa_ie == NULL || wpa_ie_len < 1)		return WPA_INVALID_IE;	if (wpa_ie[0] == WLAN_EID_RSN)		version = HOSTAPD_WPA_VERSION_WPA2;	else		version = HOSTAPD_WPA_VERSION_WPA;	if (version == HOSTAPD_WPA_VERSION_WPA2) {		res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);		selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;		if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)			selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;		else if (data.key_mgmt & WPA_KEY_MGMT_PSK)			selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;		memcpy(wpa_auth->dot11RSNAAuthenticationSuiteSelected,		       selector, RSN_SELECTOR_LEN);		selector = RSN_CIPHER_SUITE_CCMP;		if (data.pairwise_cipher & WPA_CIPHER_CCMP)			selector = RSN_CIPHER_SUITE_CCMP;		else if (data.pairwise_cipher & WPA_CIPHER_TKIP)			selector = RSN_CIPHER_SUITE_TKIP;		else if (data.pairwise_cipher & WPA_CIPHER_WEP104)			selector = RSN_CIPHER_SUITE_WEP104;		else if (data.pairwise_cipher & WPA_CIPHER_WEP40)			selector = RSN_CIPHER_SUITE_WEP40;		else if (data.pairwise_cipher & WPA_CIPHER_NONE)			selector = RSN_CIPHER_SUITE_NONE;		memcpy(wpa_auth->dot11RSNAPairwiseCipherSelected,		       selector, RSN_SELECTOR_LEN);		selector = RSN_CIPHER_SUITE_CCMP;		if (data.group_cipher & WPA_CIPHER_CCMP)			selector = RSN_CIPHER_SUITE_CCMP;		else if (data.group_cipher & WPA_CIPHER_TKIP)			selector = RSN_CIPHER_SUITE_TKIP;		else if (data.group_cipher & WPA_CIPHER_WEP104)			selector = RSN_CIPHER_SUITE_WEP104;		else if (data.group_cipher & WPA_CIPHER_WEP40)			selector = RSN_CIPHER_SUITE_WEP40;		else if (data.group_cipher & WPA_CIPHER_NONE)			selector = RSN_CIPHER_SUITE_NONE;		memcpy(wpa_auth->dot11RSNAGroupCipherSelected,		       selector, RSN_SELECTOR_LEN);	} else {		res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);		selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;		if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)			selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;		else if (data.key_mgmt & WPA_KEY_MGMT_PSK)			selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;		memcpy(wpa_auth->dot11RSNAAuthenticationSuiteSelected,		       selector, WPA_SELECTOR_LEN);		selector = WPA_CIPHER_SUITE_TKIP;		if (data.pairwise_cipher & WPA_CIPHER_CCMP)			selector = WPA_CIPHER_SUITE_CCMP;		else if (data.pairwise_cipher & WPA_CIPHER_TKIP)			selector = WPA_CIPHER_SUITE_TKIP;		else if (data.pairwise_cipher & WPA_CIPHER_WEP104)			selector = WPA_CIPHER_SUITE_WEP104;		else if (data.pairwise_cipher & WPA_CIPHER_WEP40)			selector = WPA_CIPHER_SUITE_WEP40;		else if (data.pairwise_cipher & WPA_CIPHER_NONE)			selector = WPA_CIPHER_SUITE_NONE;		memcpy(wpa_auth->dot11RSNAPairwiseCipherSelected,		       selector, WPA_SELECTOR_LEN);		selector = WPA_CIPHER_SUITE_TKIP;		if (data.group_cipher & WPA_CIPHER_CCMP)			selector = WPA_CIPHER_SUITE_CCMP;		else if (data.group_cipher & WPA_CIPHER_TKIP)			selector = WPA_CIPHER_SUITE_TKIP;		else if (data.group_cipher & WPA_CIPHER_WEP104)			selector = WPA_CIPHER_SUITE_WEP104;		else if (data.group_cipher & WPA_CIPHER_WEP40)			selector = WPA_CIPHER_SUITE_WEP40;		else if (data.group_cipher & WPA_CIPHER_NONE)			selector = WPA_CIPHER_SUITE_NONE;		memcpy(wpa_auth->dot11RSNAGroupCipherSelected,		       selector, WPA_SELECTOR_LEN);	}	if (res) {		wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "			   MACSTR " (res=%d)", MAC2STR(sm->addr), res);		wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);		return WPA_INVALID_IE;	}	if (data.group_cipher != wpa_auth->conf.wpa_group) {		wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "			   MACSTR, data.group_cipher, MAC2STR(sm->addr));		return WPA_INVALID_GROUP;	}	key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;	if (!key_mgmt) {		wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "			   MACSTR, data.key_mgmt, MAC2STR(sm->addr));		return WPA_INVALID_AKMP;	}	if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)		sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;	else		sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;	ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;	if (!ciphers) {		wpa_printf(MSG_DEBUG, "Invalid WPA pairwise cipher (0x%x) "			   "from " MACSTR,			   data.pairwise_cipher, MAC2STR(sm->addr));		return WPA_INVALID_PAIRWISE;	}	if (ciphers & WPA_CIPHER_CCMP)		sm->pairwise = WPA_CIPHER_CCMP;	else		sm->pairwise = WPA_CIPHER_TKIP;	/* TODO: clear WPA/WPA2 state if STA changes from one to another */	if (wpa_ie[0] == WLAN_EID_RSN)		sm->wpa = WPA_VERSION_WPA2;	else		sm->wpa = WPA_VERSION_WPA;	for (i = 0; i < data.num_pmkid; i++) {		wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",			    &data.pmkid[i * PMKID_LEN], PMKID_LEN);		sm->pmksa = pmksa_cache_get(wpa_auth->pmksa, sm->addr,					    &data.pmkid[i * PMKID_LEN]);		if (sm->pmksa) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,					"PMKID found from PMKSA cache");			memcpy(wpa_auth->dot11RSNAPMKIDUsed,			       sm->pmksa->pmkid, PMKID_LEN);			break;		}	}	if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {		free(sm->wpa_ie);		sm->wpa_ie = malloc(wpa_ie_len);		if (sm->wpa_ie == NULL)			return WPA_ALLOC_FAIL;	}	memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);	sm->wpa_ie_len = wpa_ie_len;	return WPA_IE_OK;}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 *stakey;	size_t stakey_len;	const u8 *mac_addr;	size_t mac_addr_len;};/** * wpa_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_parse_generic(const u8 *pos, const u8 *end,			     struct wpa_eapol_ie_parse *ie){	if (pos[1] == 0)		return 1;	if (pos[1] >= 6 &&	    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 &&	    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 &&	    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 &&	    memcmp(pos + 2, RSN_KEY_DATA_STAKEY, RSN_SELECTOR_LEN) == 0) {		ie->stakey = pos + 2 + RSN_SELECTOR_LEN;		ie->stakey_len = pos[1] - RSN_SELECTOR_LEN;		return 0;	}	if (pos[1] > RSN_SELECTOR_LEN + 2 &&	    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;	}	return 0;}/** * wpa_parse_kde_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_parse_kde_ies(const u8 *buf, size_t len,			     struct wpa_eapol_ie_parse *ie){	const u8 *pos, *end;	int ret = 0;	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[0], pos[1]);			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_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;}struct wpa_state_machine *wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr){	struct wpa_state_machine *sm;	sm = wpa_zalloc(sizeof(struct wpa_state_machine));	if (sm == NULL)		return NULL;	memcpy(sm->addr, addr, ETH_ALEN);	sm->wpa_auth = wpa_auth;	return sm;}void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,			     struct wpa_state_machine *sm){	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)		return;	if (sm->started) {		memset(sm->key_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);		sm->ReAuthenticationRequest = TRUE;		wpa_sm_step(sm);		return;	}	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,			"start authentication");	sm->started = 1;	sm->Init = TRUE;	wpa_sm_step(sm);	sm->Init = FALSE;	sm->AuthenticationRequest = TRUE;	wpa_sm_step(sm);}static void wpa_free_sta_sm(struct wpa_state_machine *sm){	free(sm->last_rx_eapol_key);	free(sm->wpa_ie);	free(sm);}void wpa_auth_sta_deinit(struct wpa_state_machine *sm){	if (sm == NULL)		return;	if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,				"strict rekeying - force GTK rekey since STA "				"is leaving");		eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL);		eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,				       NULL);	}	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);	eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);	if (sm->in_step_loop) {		/* Must not free state machine while wpa_sm_step() is running.		 * Freeing will be completed in the end of wpa_sm_step(). */		wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state "			   "machine deinit for " MACSTR, MAC2STR(sm->addr));		sm->pending_deinit = 1;	} else		wpa_free_sta_sm(sm);}static void wpa_request_new_ptk(struct wpa_state_machine *sm){	if (sm == NULL)		return;	sm->PTKRequest = TRUE;	sm->PTK_valid = 0;}#ifdef CONFIG_STAKEYstatic struct wpa_stakey_negotiation *wpa_stakey_get(struct wpa_authenticator *wpa_auth, const u8 *addr1,	       const u8 *addr2){	struct wpa_stakey_negotiation *neg;	if (wpa_auth == NULL)		return NULL;	neg = wpa_auth->stakey_negotiations;	while (neg) {		if ((memcmp(neg->initiator, addr1, ETH_ALEN) == 0 &&		     memcmp(neg->peer, addr2, ETH_ALEN) == 0) ||		    (memcmp(neg->initiator, addr2, ETH_ALEN) == 0 &&		     memcmp(neg->peer, addr1, ETH_ALEN) == 0))			return neg;		neg = neg->next;	}	return NULL;}struct wpa_stakey_search {	const u8 *addr;	struct wpa_state_machine *sm;};static int wpa_stakey_select_sta(struct wpa_state_machine *sm, void *ctx){	struct wpa_stakey_search *search = ctx;	if (memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {		search->sm = sm;		return 1;	}	return 0;}static void wpa_stakey_step(void *eloop_ctx, void *timeout_ctx){	struct wpa_authenticator *wpa_auth = eloop_ctx;	struct wpa_stakey_negotiation *neg = timeout_ctx;	const u8 *dst, *peer;	struct rsn_stakey_kde kde;	int version;	struct wpa_stakey_search search;	dst = neg->state == PEER ? neg->peer : neg->initiator;	peer = neg->state == PEER ? neg->initiator : neg->peer;	search.addr = dst;	search.sm = NULL;	if (wpa_auth_for_each_sta(wpa_auth, wpa_stakey_select_sta, &search) ==	    0 || search.sm == NULL) {		wpa_printf(MSG_DEBUG, "RSN: STAKey handshake with " MACSTR			   " aborted - STA not associated anymore",			   MAC2STR(dst));		wpa_stakey_remove(wpa_auth, neg);		return;

⌨️ 快捷键说明

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