📄 wpa.c
字号:
/* WPA Capabilities; use defaults, so no need to include it */ hdr->len = (pos - buf) - 2; return pos - buf;}static int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len){ struct rsn_ie_hdr *hdr; int num_suites; u8 *pos, *count; hdr = (struct rsn_ie_hdr *) buf; hdr->elem_id = WLAN_EID_RSN; pos = (u8 *) &hdr->version; *pos++ = RSN_VERSION & 0xff; *pos++ = RSN_VERSION >> 8; pos = (u8 *) (hdr + 1); if (conf->wpa_group == WPA_CIPHER_CCMP) { memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); } else if (conf->wpa_group == WPA_CIPHER_TKIP) { memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); } else if (conf->wpa_group == WPA_CIPHER_WEP104) { memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN); } else if (conf->wpa_group == WPA_CIPHER_WEP40) { memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN); } else { wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", conf->wpa_group); return -1; } pos += RSN_SELECTOR_LEN; num_suites = 0; count = pos; pos += 2; if (conf->wpa_pairwise & WPA_CIPHER_CCMP) { memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->wpa_pairwise & WPA_CIPHER_NONE) { memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN); pos += RSN_SELECTOR_LEN; num_suites++; } if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", conf->wpa_pairwise); return -1; } *count++ = num_suites & 0xff; *count = (num_suites >> 8) & 0xff; num_suites = 0; count = pos; pos += 2; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN); pos += RSN_SELECTOR_LEN; num_suites++; } if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", conf->wpa_key_mgmt); return -1; } *count++ = num_suites & 0xff; *count = (num_suites >> 8) & 0xff; /* RSN Capabilities */ *pos++ = conf->rsn_preauth ? BIT(0) : 0; *pos++ = 0; hdr->len = (pos - buf) - 2; return pos - buf;}static int wpa_gen_wpa_ie(struct wpa_authenticator *wpa_auth){ u8 *pos, buf[100]; int res; pos = buf; if (wpa_auth->conf.wpa & HOSTAPD_WPA_VERSION_WPA2) { res = wpa_write_rsn_ie(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); if (res < 0) return res; pos += res; } if (wpa_auth->conf.wpa & HOSTAPD_WPA_VERSION_WPA) { res = wpa_write_wpa_ie(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); if (res < 0) return res; pos += res; } free(wpa_auth->wpa_ie); wpa_auth->wpa_ie = malloc(pos - buf); if (wpa_auth->wpa_ie == NULL) return -1; memcpy(wpa_auth->wpa_ie, buf, pos - buf); wpa_auth->wpa_ie_len = pos - buf; return 0;}static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, const u8 *addr){ if (wpa_auth->cb.disconnect == NULL) return; wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);}static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx){ struct wpa_authenticator *wpa_auth = eloop_ctx; if (hostapd_get_rand(wpa_auth->GMK, WPA_GMK_LEN)) { wpa_printf(MSG_ERROR, "Failed to get random data for WPA " "initialization."); } else { wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); } if (wpa_auth->conf.wpa_gmk_rekey) { eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, wpa_rekey_gmk, wpa_auth, NULL); }}static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx){ struct wpa_authenticator *wpa_auth = eloop_ctx; wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); wpa_auth->GTKReKey = TRUE; do { wpa_auth->changed = FALSE; wpa_group_sm_step(wpa_auth); } while (wpa_auth->changed); if (wpa_auth->conf.wpa_group_rekey) { eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, wpa_rekey_gtk, wpa_auth, NULL); }}static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx){ if (sm->pmksa == ctx) sm->pmksa = NULL; return 0;}static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, void *ctx){ struct wpa_authenticator *wpa_auth = ctx; wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);}/** * wpa_init - Initialize WPA authenticator * @addr: Authenticator address * @conf: Configuration for WPA authenticator * Returns: Pointer to WPA authenticator data or %NULL on failure */struct wpa_authenticator * wpa_init(const u8 *addr, struct wpa_auth_config *conf, struct wpa_auth_callbacks *cb){ struct wpa_authenticator *wpa_auth; u8 rkey[32]; u8 buf[ETH_ALEN + 8]; wpa_auth = wpa_zalloc(sizeof(struct wpa_authenticator)); if (wpa_auth == NULL) return NULL; memcpy(wpa_auth->addr, addr, ETH_ALEN); memcpy(&wpa_auth->conf, conf, sizeof(*conf)); memcpy(&wpa_auth->cb, cb, sizeof(*cb)); if (wpa_gen_wpa_ie(wpa_auth)) { wpa_printf(MSG_ERROR, "Could not generate WPA IE."); free(wpa_auth); return NULL; } wpa_auth->GTKAuthenticator = TRUE; switch (wpa_auth->conf.wpa_group) { case WPA_CIPHER_CCMP: wpa_auth->GTK_len = 16; break; case WPA_CIPHER_TKIP: wpa_auth->GTK_len = 32; break; case WPA_CIPHER_WEP104: wpa_auth->GTK_len = 13; break; case WPA_CIPHER_WEP40: wpa_auth->GTK_len = 5; break; } wpa_auth->pmksa = pmksa_cache_init(wpa_auth_pmksa_free_cb, wpa_auth); if (wpa_auth->pmksa == NULL) { wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); free(wpa_auth->wpa_ie); free(wpa_auth); return NULL; } /* Counter = PRF-256(Random number, "Init Counter", * Local MAC Address || Time) */ memcpy(buf, wpa_auth->addr, ETH_ALEN); wpa_get_ntp_timestamp(buf + ETH_ALEN); if (hostapd_get_rand(rkey, sizeof(rkey)) || hostapd_get_rand(wpa_auth->GMK, WPA_GMK_LEN)) { wpa_printf(MSG_ERROR, "Failed to get random data for WPA " "initialization."); pmksa_cache_deinit(wpa_auth->pmksa); free(wpa_auth->wpa_ie); free(wpa_auth); return NULL; } sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), wpa_auth->Counter, WPA_NONCE_LEN); if (wpa_auth->conf.wpa_gmk_rekey) { eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, wpa_rekey_gmk, wpa_auth, NULL); } if (wpa_auth->conf.wpa_group_rekey) { eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, wpa_rekey_gtk, wpa_auth, NULL); } wpa_auth->GInit = TRUE; wpa_group_sm_step(wpa_auth); wpa_auth->GInit = FALSE; wpa_group_sm_step(wpa_auth); return wpa_auth;}/** * wpa_deinit - Deinitialize WPA authenticator * @wpa_auth: Pointer to WPA authenticator data from wpa_init() */void wpa_deinit(struct wpa_authenticator *wpa_auth){ eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); while (wpa_auth->stakey_negotiations) wpa_stakey_remove(wpa_auth, wpa_auth->stakey_negotiations); pmksa_cache_deinit(wpa_auth->pmksa); free(wpa_auth->wpa_ie); free(wpa_auth);}/** * wpa_reconfig - Update WPA authenticator configuration * @wpa_auth: Pointer to WPA authenticator data from wpa_init() * @conf: Configuration for WPA authenticator */int wpa_reconfig(struct wpa_authenticator *wpa_auth, struct wpa_auth_config *conf){ if (wpa_auth == NULL) return 0; memcpy(&wpa_auth->conf, conf, sizeof(*conf)); /* * TODO: * Disassociate stations if configuration changed * Update WPA/RSN IE */ return 0;}static int wpa_selector_to_bitfield(u8 *s){ if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0) return WPA_CIPHER_NONE; if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0) return WPA_CIPHER_WEP40; if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0) return WPA_CIPHER_TKIP; if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0) return WPA_CIPHER_CCMP; if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0) return WPA_CIPHER_WEP104; return 0;}static int wpa_key_mgmt_to_bitfield(u8 *s){ if (memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) == 0) return WPA_KEY_MGMT_IEEE8021X; if (memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN) == 0) return WPA_KEY_MGMT_PSK; return 0;}static int rsn_selector_to_bitfield(u8 *s){ if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0) return WPA_CIPHER_NONE; if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0) return WPA_CIPHER_WEP40; if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0) return WPA_CIPHER_TKIP; if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0) return WPA_CIPHER_CCMP; if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0) return WPA_CIPHER_WEP104; return 0;}static int rsn_key_mgmt_to_bitfield(u8 *s){ if (memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) == 0) return WPA_KEY_MGMT_IEEE8021X; if (memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN) == 0) return WPA_KEY_MGMT_PSK; return 0;}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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -