📄 wpa.c
字号:
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 + -