📄 wpa.c
字号:
/* * WPA Supplicant - WPA state machine and EAPOL-Key processing * Copyright (c) 2003-2007, 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 <stdlib.h>#include <stdio.h>#ifndef CONFIG_NATIVE_WINDOWS#include <netinet/in.h>#endif /* CONFIG_NATIVE_WINDOWS */#include <string.h>#include "common.h"#include "md5.h"#include "sha1.h"#include "rc4.h"#include "aes_wrap.h"#include "wpa.h"#include "eloop.h"#include "wpa_supplicant.h"#include "config.h"#include "l2_packet.h"#include "eapol_sm.h"#include "preauth.h"#include "wpa_i.h"static const int WPA_SELECTOR_LEN = 4;static const u8 WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };static const u16 WPA_VERSION = 1;static const u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };static const u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };static const u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };static const u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };static const u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };static const u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };static const u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };static const u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };static const u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };/* WPA IE version 1 * 00-50-f2:1 (OUI:OUI type) * 0x01 0x00 (version; little endian) * (all following fields are optional:) * Group Suite Selector (4 octets) (default: TKIP) * Pairwise Suite Count (2 octets, little endian) (default: 1) * Pairwise Suite List (4 * n octets) (default: TKIP) * Authenticated Key Management Suite Count (2 octets, little endian) * (default: 1) * Authenticated Key Management Suite List (4 * n octets) * (default: unspec 802.1X) * WPA Capabilities (2 octets, little endian) (default: 0) */struct wpa_ie_hdr { u8 elem_id; u8 len; u8 oui[3]; u8 oui_type; u8 version[2];} __attribute__ ((packed));static const int RSN_SELECTOR_LEN = 4;static const u16 RSN_VERSION = 1;static const u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };static const u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };static const u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };static const u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };static const u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };static const u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };static const u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };static const u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };/* EAPOL-Key Key Data Encapsulation * GroupKey and STAKey require encryption, otherwise, encryption is optional. */static const u8 RSN_KEY_DATA_GROUPKEY[] = { 0x00, 0x0f, 0xac, 1 };static const u8 RSN_KEY_DATA_STAKEY[] = { 0x00, 0x0f, 0xac, 2 };static const u8 RSN_KEY_DATA_MAC_ADDR[] = { 0x00, 0x0f, 0xac, 3 };static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 };/* 1/4: PMKID * 2/4: RSN IE * 3/4: one or two RSN IEs + GTK IE (encrypted) * 4/4: empty * 1/2: GTK IE (encrypted) * 2/2: empty *//* RSN IE version 1 * 0x01 0x00 (version; little endian) * (all following fields are optional:) * Group Suite Selector (4 octets) (default: CCMP) * Pairwise Suite Count (2 octets, little endian) (default: 1) * Pairwise Suite List (4 * n octets) (default: CCMP) * Authenticated Key Management Suite Count (2 octets, little endian) * (default: 1) * Authenticated Key Management Suite List (4 * n octets) * (default: unspec 802.1X) * RSN Capabilities (2 octets, little endian) (default: 0) * PMKID Count (2 octets) (default: 0) * PMKID List (16 * n octets) */struct rsn_ie_hdr { u8 elem_id; /* WLAN_EID_RSN */ u8 len; u8 version[2];} __attribute__ ((packed));struct wpa_eapol_key { u8 type; /* Note: key_info, key_length, and key_data_length are unaligned */ u8 key_info[2]; u8 key_length[2]; u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; u8 key_nonce[WPA_NONCE_LEN]; u8 key_iv[16]; u8 key_rsc[8]; u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ u8 key_mic[16]; u8 key_data_length[2]; /* followed by key_data_length bytes of key_data */} __attribute__ ((packed));#define WPA_KEY_INFO_TYPE_MASK (BIT(0) | BIT(1) | BIT(2))#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key *//* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */#define WPA_KEY_INFO_TXRX BIT(6) /* group */#define WPA_KEY_INFO_ACK BIT(7)#define WPA_KEY_INFO_MIC BIT(8)#define WPA_KEY_INFO_SECURE BIT(9)#define WPA_KEY_INFO_ERROR BIT(10)#define WPA_KEY_INFO_REQUEST BIT(11)#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only *//** * wpa_cipher_txt - Convert cipher suite to a text string * @cipher: Cipher suite (WPA_CIPHER_* enum) * Returns: Pointer to a text string of the cipher suite name */static const char * wpa_cipher_txt(int cipher){ switch (cipher) { case WPA_CIPHER_NONE: return "NONE"; case WPA_CIPHER_WEP40: return "WEP-40"; case WPA_CIPHER_WEP104: return "WEP-104"; case WPA_CIPHER_TKIP: return "TKIP"; case WPA_CIPHER_CCMP: return "CCMP"; default: return "UNKNOWN"; }}/** * wpa_key_mgmt_txt - Convert key management suite to a text string * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) * @proto: WPA/WPA2 version (WPA_PROTO_*) * Returns: Pointer to a text string of the key management suite name */static const char * wpa_key_mgmt_txt(int key_mgmt, int proto){ switch (key_mgmt) { case WPA_KEY_MGMT_IEEE8021X: return proto == WPA_PROTO_RSN ? "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; case WPA_KEY_MGMT_PSK: return proto == WPA_PROTO_RSN ? "WPA2-PSK" : "WPA-PSK"; case WPA_KEY_MGMT_NONE: return "NONE"; case WPA_KEY_MGMT_IEEE8021X_NO_WPA: return "IEEE 802.1X (no WPA)"; default: return "UNKNOWN"; }}static int wpa_selector_to_bitfield(const 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(const 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; if (memcmp(s, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN) == 0) return WPA_KEY_MGMT_WPA_NONE; return 0;}static int rsn_selector_to_bitfield(const 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(const 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;}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; data->proto = WPA_PROTO_WPA; data->pairwise_cipher = WPA_CIPHER_TKIP; data->group_cipher = WPA_CIPHER_TKIP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->capabilities = 0; data->pmkid = NULL; data->num_pmkid = 0; if (wpa_ie_len == 0) { /* No WPA IE - fail silently */ return -1; } if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", __func__, (unsigned long) wpa_ie_len); return -1; } hdr = (const struct wpa_ie_hdr *) wpa_ie; if (hdr->elem_id != GENERIC_INFO_ELEM || hdr->len != wpa_ie_len - 2 || memcmp(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 || WPA_GET_LE16(hdr->version) != WPA_VERSION) { wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); return -1; } 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) { wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", __func__, left); return -1; } if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " "count %u left %u", __func__, count, left); return -1; } 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) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -1; } if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * WPA_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " "count %u left %u", __func__, count, left); return -1; } 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) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -1; } if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", __func__, left); } return 0;}static int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data){ const struct rsn_ie_hdr *hdr; const u8 *pos; int left; int i, count; data->proto = WPA_PROTO_RSN; data->pairwise_cipher = WPA_CIPHER_CCMP; data->group_cipher = WPA_CIPHER_CCMP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->capabilities = 0; data->pmkid = NULL; data->num_pmkid = 0; if (rsn_ie_len == 0) { /* No RSN IE - fail silently */ return -1; } if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", __func__, (unsigned long) rsn_ie_len); return -1; } hdr = (const struct rsn_ie_hdr *) rsn_ie; if (hdr->elem_id != RSN_INFO_ELEM || hdr->len != rsn_ie_len - 2 || WPA_GET_LE16(hdr->version) != RSN_VERSION) { wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); return -1; } pos = (const 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) { wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", __func__, left); return -1; } if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " "count %u left %u", __func__, count, left); return -1; } 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) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -1; } if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " "count %u left %u", __func__, count, left); return -1; } 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) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -