📄 wpa_auth_ie.c
字号:
/* * hostapd - WPA/RSN IE and KDE definitions * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "config.h"#include "ieee802_11.h"#include "eapol_sm.h"#include "wpa.h"#include "pmksa_cache.h"#include "wpa_auth_ie.h"#include "wpa_auth_i.h"static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len){ struct wpa_ie_hdr *hdr; int num_suites; u8 *pos, *count; hdr = (struct wpa_ie_hdr *) buf; hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); WPA_PUT_LE16(hdr->version, WPA_VERSION); pos = (u8 *) (hdr + 1); if (conf->wpa_group == WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); } else if (conf->wpa_group == WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); } else if (conf->wpa_group == WPA_CIPHER_WEP104) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); } else if (conf->wpa_group == WPA_CIPHER_WEP40) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); } else { wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", conf->wpa_group); return -1; } pos += WPA_SELECTOR_LEN; num_suites = 0; count = pos; pos += 2; if (conf->wpa_pairwise & WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); pos += WPA_SELECTOR_LEN; num_suites++; } if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); pos += WPA_SELECTOR_LEN; num_suites++; } if (conf->wpa_pairwise & WPA_CIPHER_NONE) { RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); pos += WPA_SELECTOR_LEN; num_suites++; } if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", conf->wpa_pairwise); return -1; } WPA_PUT_LE16(count, num_suites); num_suites = 0; count = pos; pos += 2; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); pos += WPA_SELECTOR_LEN; num_suites++; } if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); pos += WPA_SELECTOR_LEN; num_suites++; } if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", conf->wpa_key_mgmt); return -1; } WPA_PUT_LE16(count, num_suites); /* WPA Capabilities; use defaults, so no need to include it */ hdr->len = (pos - buf) - 2; return pos - buf;}int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, const u8 *pmkid){ struct rsn_ie_hdr *hdr; int num_suites; u8 *pos, *count; u16 capab; hdr = (struct rsn_ie_hdr *) buf; hdr->elem_id = WLAN_EID_RSN; WPA_PUT_LE16(hdr->version, RSN_VERSION); pos = (u8 *) (hdr + 1); if (conf->wpa_group == WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); } else if (conf->wpa_group == WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); } else if (conf->wpa_group == WPA_CIPHER_WEP104) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); } else if (conf->wpa_group == WPA_CIPHER_WEP40) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); } 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->rsn_pairwise & WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->rsn_pairwise & WPA_CIPHER_NONE) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); pos += RSN_SELECTOR_LEN; num_suites++; } if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", conf->rsn_pairwise); return -1; } WPA_PUT_LE16(count, num_suites); num_suites = 0; count = pos; pos += 2; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); pos += RSN_SELECTOR_LEN; num_suites++; }#ifdef CONFIG_IEEE80211R if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); pos += RSN_SELECTOR_LEN; num_suites++; }#endif /* CONFIG_IEEE80211R */#ifdef CONFIG_IEEE80211W if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); pos += RSN_SELECTOR_LEN; num_suites++; } if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); pos += RSN_SELECTOR_LEN; num_suites++; }#endif /* CONFIG_IEEE80211W */ if (num_suites == 0) { wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", conf->wpa_key_mgmt); return -1; } WPA_PUT_LE16(count, num_suites); /* RSN Capabilities */ capab = 0; if (conf->rsn_preauth) capab |= WPA_CAPABILITY_PREAUTH; if (conf->peerkey) capab |= WPA_CAPABILITY_PEERKEY_ENABLED; if (conf->wme_enabled) { /* 4 PTKSA replay counters when using WME */ capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); }#ifdef CONFIG_IEEE80211W if (conf->ieee80211w != WPA_NO_IEEE80211W) { capab |= WPA_CAPABILITY_MFPC; if (conf->ieee80211w == IEEE80211W_REQUIRED) capab |= WPA_CAPABILITY_MFPR; }#endif /* CONFIG_IEEE80211W */ WPA_PUT_LE16(pos, capab); pos += 2; if (pmkid) { if (pos + 2 + PMKID_LEN > buf + len) return -1; /* PMKID Count */ WPA_PUT_LE16(pos, 1); pos += 2; os_memcpy(pos, pmkid, PMKID_LEN); pos += PMKID_LEN; }#ifdef CONFIG_IEEE80211W if (conf->ieee80211w != WPA_NO_IEEE80211W) { if (pos + 2 + 4 > buf + len) return -1; if (pmkid == NULL) { /* PMKID Count */ WPA_PUT_LE16(pos, 0); pos += 2; } /* Management Group Cipher Suite */ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); pos += RSN_SELECTOR_LEN; }#endif /* CONFIG_IEEE80211W */ hdr->len = (pos - buf) - 2; return pos - buf;}int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth){ u8 *pos, buf[128]; int res; pos = buf; if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { res = wpa_write_rsn_ie(&wpa_auth->conf, pos, buf + sizeof(buf) - pos, NULL); if (res < 0) return res; pos += res; }#ifdef CONFIG_IEEE80211R if (wpa_auth->conf.wpa_key_mgmt & (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) { res = wpa_write_mdie(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); if (res < 0) return res; pos += res; }#endif /* CONFIG_IEEE80211R */ if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { res = wpa_write_wpa_ie(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); if (res < 0) return res; pos += res; } os_free(wpa_auth->wpa_ie); wpa_auth->wpa_ie = os_malloc(pos - buf); if (wpa_auth->wpa_ie == NULL) return -1; os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); wpa_auth->wpa_ie_len = pos - buf; return 0;}u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, const u8 *data2, size_t data2_len){ *pos++ = WLAN_EID_VENDOR_SPECIFIC; *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; RSN_SELECTOR_PUT(pos, kde); pos += RSN_SELECTOR_LEN; os_memcpy(pos, data, data_len); pos += data_len; if (data2) { os_memcpy(pos, data2, data2_len); pos += data2_len; } return pos;}static int wpa_selector_to_bitfield(const u8 *s){ if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) return WPA_CIPHER_NONE; if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) return WPA_CIPHER_WEP40; if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) return WPA_CIPHER_TKIP; if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) return WPA_CIPHER_CCMP; if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) return WPA_CIPHER_WEP104; return 0;}static int wpa_key_mgmt_to_bitfield(const u8 *s){ if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) return WPA_KEY_MGMT_WPA_NONE; return 0;}static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data){ const struct wpa_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); data->pairwise_cipher = WPA_CIPHER_TKIP; data->group_cipher = WPA_CIPHER_TKIP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->mgmt_group_cipher = 0; if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) return -1; hdr = (const struct wpa_ie_hdr *) wpa_ie; if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || hdr->len != wpa_ie_len - 2 || RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || WPA_GET_LE16(hdr->version) != WPA_VERSION) { return -2; } pos = (const 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 = WPA_GET_LE16(pos); 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 = WPA_GET_LE16(pos); 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 = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left > 0) { return -8; } return 0;}struct wpa_auth_okc_iter_data { struct rsn_pmksa_cache_entry *pmksa;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -