📄 wpa.c
字号:
if (pmkid) entry = hapd->pmkid[PMKID_HASH(pmkid)]; else entry = hapd->pmksa; while (entry) { if ((spa == NULL || memcmp(entry->spa, spa, ETH_ALEN) == 0) && (pmkid == NULL || memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) return entry; entry = pmkid ? entry->hnext : entry->next; } return NULL;}struct wpa_ie_data { int pairwise_cipher; int group_cipher; int key_mgmt; int capabilities; size_t num_pmkid; u8 *pmkid;};static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data){ struct wpa_ie_hdr *hdr; u8 *pos; int left; int i, count; memset(data, 0, sizeof(*data)); data->pairwise_cipher = WPA_CIPHER_TKIP; data->group_cipher = WPA_CIPHER_TKIP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) return -1; hdr = (struct wpa_ie_hdr *) wpa_ie; if (hdr->elem_id != WLAN_EID_GENERIC || hdr->len != wpa_ie_len - 2 || memcmp(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 || le_to_host16(hdr->version) != WPA_VERSION) { return -2; } pos = (u8 *) (hdr + 1); left = wpa_ie_len - sizeof(*hdr); if (left >= WPA_SELECTOR_LEN) { data->group_cipher = wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_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 * WPA_SELECTOR_LEN) return -4; for (i = 0; i < count; i++) { data->pairwise_cipher |= wpa_selector_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_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 * WPA_SELECTOR_LEN) return -6; for (i = 0; i < count; i++) { data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); pos += WPA_SELECTOR_LEN; left -= WPA_SELECTOR_LEN; } } else if (left == 1) return -7; if (left >= 2) { data->capabilities = pos[0] | (pos[1] << 8); pos += 2; left -= 2; } if (left > 0) { return -8; } return 0;}static int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data){ struct rsn_ie_hdr *hdr; u8 *pos; int left; int i, count; memset(data, 0, sizeof(*data)); data->pairwise_cipher = WPA_CIPHER_CCMP; data->group_cipher = WPA_CIPHER_CCMP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) return -1; hdr = (struct rsn_ie_hdr *) rsn_ie; if (hdr->elem_id != WLAN_EID_RSN || hdr->len != rsn_ie_len - 2 || le_to_host16(hdr->version) != RSN_VERSION) { return -2; } pos = (u8 *) (hdr + 1); left = rsn_ie_len - sizeof(*hdr); 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) { printf("RSN: too short RSN IE for PMKIDs " "(num=%lu, left=%d)\n", (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 hostapd_data *hapd, struct sta_info *sta, const u8 *wpa_ie, size_t wpa_ie_len, int version){ struct wpa_ie_data data; int ciphers, key_mgmt, res, i; const u8 *selector; 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(hapd->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(hapd->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(hapd->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(hapd->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(hapd->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(hapd->wpa_auth->dot11RSNAGroupCipherSelected, selector, WPA_SELECTOR_LEN); } if (res) { printf("Failed to parse WPA/RSN IE from " MACSTR " (res=%d)\n", MAC2STR(sta->addr), res); hostapd_hexdump("WPA/RSN IE", wpa_ie, wpa_ie_len); return WPA_INVALID_IE; } if (data.group_cipher != hapd->conf->wpa_group) { printf("Invalid WPA group cipher (0x%x) from " MACSTR "\n", data.group_cipher, MAC2STR(sta->addr)); return WPA_INVALID_GROUP; } key_mgmt = data.key_mgmt & hapd->conf->wpa_key_mgmt; if (!key_mgmt) { printf("Invalid WPA key mgmt (0x%x) from " MACSTR "\n", data.key_mgmt, MAC2STR(sta->addr)); return WPA_INVALID_AKMP; } if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) sta->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; else sta->wpa_key_mgmt = WPA_KEY_MGMT_PSK; ciphers = data.pairwise_cipher & hapd->conf->wpa_pairwise; if (!ciphers) { printf("Invalid WPA pairwise cipher (0x%x) from " MACSTR "\n", data.pairwise_cipher, MAC2STR(sta->addr)); return WPA_INVALID_PAIRWISE; } if (ciphers & WPA_CIPHER_CCMP) sta->pairwise = WPA_CIPHER_CCMP; else sta->pairwise = WPA_CIPHER_TKIP; /* TODO: clear WPA/WPA2 state if STA changes from one to another */ if (wpa_ie[0] == WLAN_EID_RSN) sta->wpa = WPA_VERSION_WPA2; else sta->wpa = WPA_VERSION_WPA; for (i = 0; i < data.num_pmkid; i++) { if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("RSN IE: STA PMKID", &data.pmkid[i * PMKID_LEN], PMKID_LEN); } sta->pmksa = pmksa_cache_get(hapd, sta->addr, &data.pmkid[i * PMKID_LEN]); if (sta->pmksa) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "PMKID found from PMKSA cache"); if (hapd->wpa_auth) { memcpy(hapd->wpa_auth->dot11RSNAPMKIDUsed, sta->pmksa->pmkid, PMKID_LEN); } break; } } return WPA_IE_OK;}void wpa_new_station(struct hostapd_data *hapd, struct sta_info *sta){ struct wpa_state_machine *sm; if (!hapd->conf->wpa) return; if (sta->wpa_sm) { sm = sta->wpa_sm; memset(sm->key_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); sm->ReAuthenticationRequest = TRUE; wpa_sm_step(sm); return; } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "start authentication"); sm = malloc(sizeof(struct wpa_state_machine)); if (sm == NULL) return; memset(sm, 0, sizeof(struct wpa_state_machine)); sm->hapd = hapd; sm->sta = sta; sta->wpa_sm = sm; sm->Init = TRUE; wpa_sm_step(sm); sm->Init = FALSE; sm->AuthenticationRequest = TRUE; wpa_sm_step(sm);}void wpa_free_station(struct sta_info *sta){ struct wpa_state_machine *sm = sta->wpa_sm; if (sm == NULL) return; if (sm->hapd->conf->wpa_strict_rekey && sm->has_GTK) { hostapd_logger(sm->hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "strict rekeying - force " "GTK rekey since STA is leaving"); eloop_cancel_timeout(wpa_rekey_gtk, sm->hapd, NULL); eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->hapd, NULL); } eloop_cancel_timeout(wpa_send_eapol_timeout, sm->hapd, sta); eloop_cancel_timeout(wpa_sm_call_step, sm->hapd, sta->wpa_sm); free(sm->last_rx_eapol_key); free(sm); sta->wpa_sm = NULL;}static void wpa_request_new_ptk(struct hostapd_data *hapd, struct sta_info *sta){ struct wpa_state_machine *sm = sta->wpa_sm; if (sm == NULL) return; sm->PTKRequest = TRUE; sm->PTK_valid = 0;}void wpa_receive(struct hostapd_data *hapd, struct sta_info *sta, u8 *data, size_t data_len){ struct wpa_state_machine *sm = sta->wpa_sm; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u16 key_info, key_data_length; enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg; char *msgtxt; if (!hapd->conf->wpa) return; if (sm == NULL) return; if (data_len < sizeof(*hdr) + sizeof(*key)) return; hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); key_info = ntohs(key->key_info); key_data_length = ntohs(key->key_data_length); if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " "key_data overflow (%d > %lu)", key_data_length, (unsigned long) (data_len - sizeof(*hdr) - sizeof(*key))); return; } /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys * are set */ if (key_info & WPA_KEY_INFO_REQUEST) { msg = REQUEST; msgtxt = "Request"; } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { msg = GROUP_2; msgtxt = "2/2 Group"; } else if (key_data_length == 0) { msg = PAIRWISE_4; msgtxt = "4/4 Pairwise"; } else { msg = PAIRWISE_2; msgtxt = "2/4 Pairwise"; } if (key_info & WPA_KEY_INFO_REQUEST) { if (sta->req_replay_counter_used && memcmp(key->replay_counter, sta->req_replay_counter, WPA_REPLAY_COUNTER_LEN) <= 0) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_WARNING, "received EAPOL-Key request with " "replayed counter"); return; } } if (!(key_info & WPA_KEY_INFO_REQUEST) && (!sm->key_replay_counter_valid || memcmp(key->replay_counter, sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN) != 0)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key %s with unexpected replay " "counter", msgtxt); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("expected replay counter",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -