📄 wpa.c
字号:
/* * hostapd - IEEE 802.11i-2004 / WPA Authenticator * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.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"#ifndef CONFIG_NATIVE_WINDOWS#include "hostapd.h"#include "eapol_sm.h"#include "wpa.h"#include "sha1.h"#include "md5.h"#include "rc4.h"#include "aes_wrap.h"#include "eloop.h"#include "hostap_common.h"#include "pmksa_cache.h"#include "state_machine.h"#define STATE_MACHINE_DATA struct wpa_state_machine#define STATE_MACHINE_DEBUG_PREFIX "WPA"#define STATE_MACHINE_ADDR sm->addrstruct wpa_stakey_negotiation { struct wpa_stakey_negotiation *next; u8 initiator[ETH_ALEN]; u8 peer[ETH_ALEN]; enum { PEER, INITIATOR } state; unsigned int num_retries; u8 key[32]; size_t key_len; int alg;};struct wpa_state_machine { struct wpa_authenticator *wpa_auth; u8 addr[ETH_ALEN]; enum { WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED, WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2, WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART, WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2, WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE } wpa_ptk_state; enum { WPA_PTK_GROUP_IDLE = 0, WPA_PTK_GROUP_REKEYNEGOTIATING, WPA_PTK_GROUP_REKEYESTABLISHED, WPA_PTK_GROUP_KEYERROR } wpa_ptk_group_state; Boolean Init; Boolean DeauthenticationRequest; Boolean AuthenticationRequest; Boolean ReAuthenticationRequest; Boolean Disconnect; int TimeoutCtr; int GTimeoutCtr; Boolean TimeoutEvt; Boolean EAPOLKeyReceived; Boolean EAPOLKeyPairwise; Boolean EAPOLKeyRequest; Boolean MICVerified; Boolean GUpdateStationKeys; u8 ANonce[WPA_NONCE_LEN]; u8 SNonce[WPA_NONCE_LEN]; u8 PMK[WPA_PMK_LEN]; struct wpa_ptk PTK; Boolean PTK_valid; Boolean pairwise_set; int keycount; Boolean Pair; u8 key_replay_counter[WPA_REPLAY_COUNTER_LEN]; Boolean key_replay_counter_valid; Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ Boolean PTKRequest; /* not in IEEE 802.11i state machine */ Boolean has_GTK; u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ size_t last_rx_eapol_key_len; unsigned int changed:1; unsigned int in_step_loop:1; unsigned int pending_deinit:1; unsigned int started:1; u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; int req_replay_counter_used; u8 *wpa_ie; size_t wpa_ie_len; enum { WPA_VERSION_NO_WPA = 0 /* WPA not used */, WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */, WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */ } wpa; int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ struct rsn_pmksa_cache_entry *pmksa; u32 dot11RSNAStatsTKIPLocalMICFailures; u32 dot11RSNAStatsTKIPRemoteMICFailures;};/* per authenticator data */struct wpa_authenticator { Boolean GInit; int GNoStations; int GKeyDoneStations; Boolean GTKReKey; int GTK_len; int GN, GM; Boolean GTKAuthenticator; u8 Counter[WPA_NONCE_LEN]; enum { WPA_GROUP_GTK_INIT = 0, WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE } wpa_group_state; u8 GMK[WPA_GMK_LEN]; u8 GTK[2][WPA_GTK_MAX_LEN]; u8 GNonce[WPA_NONCE_LEN]; Boolean changed; unsigned int dot11RSNAStatsTKIPRemoteMICFailures; u8 dot11RSNAAuthenticationSuiteSelected[4]; u8 dot11RSNAPairwiseCipherSelected[4]; u8 dot11RSNAGroupCipherSelected[4]; u8 dot11RSNAPMKIDUsed[PMKID_LEN]; u8 dot11RSNAAuthenticationSuiteRequested[4]; /* FIX: update */ u8 dot11RSNAPairwiseCipherRequested[4]; /* FIX: update */ u8 dot11RSNAGroupCipherRequested[4]; /* FIX: update */ unsigned int dot11RSNATKIPCounterMeasuresInvoked; unsigned int dot11RSNA4WayHandshakeFailures; struct wpa_stakey_negotiation *stakey_negotiations; struct wpa_auth_config conf; struct wpa_auth_callbacks cb; u8 *wpa_ie; size_t wpa_ie_len; u8 addr[ETH_ALEN]; struct rsn_pmksa_cache *pmksa;};static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);static void wpa_sm_step(struct wpa_state_machine *sm);static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len);static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth);static int wpa_stakey_remove(struct wpa_authenticator *wpa_auth, struct wpa_stakey_negotiation *neg);static void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int secure, int mic, int ack, int install, int pairwise, u8 *key_rsc, u8 *nonce, u8 *ie, size_t ie_len, u8 *gtk, size_t gtk_len, int keyidx, int encr, int force_version);/* Default timeouts are 100 ms, but this seems to be a bit too fast for most * WPA Supplicants, so use a bit longer timeout. */static const u32 dot11RSNAConfigGroupUpdateTimeOut = 1000; /* ms */static const u32 dot11RSNAConfigGroupUpdateCount = 3;static const u32 dot11RSNAConfigPairwiseUpdateTimeOut = 1000; /* ms */static const u32 dot11RSNAConfigPairwiseUpdateCount = 3;/* TODO: make these configurable */static const int dot11RSNAConfigPMKLifetime = 43200;static const int dot11RSNAConfigPMKReauthThreshold = 70;static const int dot11RSNAConfigSATimeout = 60;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_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 };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 };#define GENERIC_INFO_ELEM 0xdd#define RSN_INFO_ELEM 0x30#ifdef _MSC_VER#pragma pack(push, 1)#endif /* _MSC_VER *//* 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; u16 version;} STRUCT_PACKED;/* 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; u16 version;} STRUCT_PACKED;struct rsn_stakey_kde { u8 id; u8 len; u8 oui[3]; u8 oui_type; u8 reserved[2]; u8 mac_addr[ETH_ALEN]; u8 stakey[32]; /* up to 32 bytes */} STRUCT_PACKED;#ifdef _MSC_VER#pragma pack(pop)#endif /* _MSC_VER */static inline void wpa_auth_mic_failure_report( struct wpa_authenticator *wpa_auth, const u8 *addr){ if (wpa_auth->cb.mic_failure_report) wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr);}static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, wpa_eapol_variable var, int value){ if (wpa_auth->cb.set_eapol) wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value);}static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, wpa_eapol_variable var){ if (wpa_auth->cb.get_eapol == NULL) return -1; return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var);}static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *prev_psk){ if (wpa_auth->cb.get_psk == NULL) return NULL; return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk);}static inline int wpa_auth_get_pmk(struct wpa_authenticator *wpa_auth, const u8 *addr, u8 *pmk, size_t *len){ if (wpa_auth->cb.get_pmk == NULL) return -1; return wpa_auth->cb.get_pmk(wpa_auth->cb.ctx, addr, pmk, len);}static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, const char *alg, const u8 *addr, int idx, u8 *key, size_t key_len){ if (wpa_auth->cb.set_key == NULL) return -1; return wpa_auth->cb.set_key(wpa_auth->cb.ctx, alg, addr, idx, key, key_len);}static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, const u8 *addr, int idx, u8 *seq){ if (wpa_auth->cb.get_seqnum == NULL) return -1; return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq);}static inline intwpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *data, size_t data_len, int encrypt){ if (wpa_auth->cb.send_eapol == NULL) return -1; return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, encrypt);}static inline int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_state_machine *sm, void *ctx), void *cb_ctx){ if (wpa_auth->cb.for_each_sta == NULL) return 0; return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx);}static void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *txt){ if (wpa_auth->cb.logger == NULL) return; wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt);}static void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *fmt, ...){ char *format; int maxlen; va_list ap; if (wpa_auth->cb.logger == NULL) return; maxlen = strlen(fmt) + 100; format = malloc(maxlen); if (!format) return; va_start(ap, fmt); vsnprintf(format, maxlen, fmt, ap); va_end(ap); wpa_auth_logger(wpa_auth, addr, level, format); free(format);}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_GENERIC; memcpy(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN); hdr->version = host_to_le16(WPA_VERSION); pos = (u8 *) (hdr + 1); if (conf->wpa_group == WPA_CIPHER_CCMP) { memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); } else if (conf->wpa_group == WPA_CIPHER_TKIP) { memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); } else if (conf->wpa_group == WPA_CIPHER_WEP104) { memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN); } else if (conf->wpa_group == WPA_CIPHER_WEP40) { memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN); } 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) { memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); pos += WPA_SELECTOR_LEN; num_suites++; } if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); pos += WPA_SELECTOR_LEN; num_suites++; } if (conf->wpa_pairwise & WPA_CIPHER_NONE) { memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN); pos += WPA_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, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN); pos += WPA_SELECTOR_LEN; num_suites++; } if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN); 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; } *count++ = num_suites & 0xff; *count = (num_suites >> 8) & 0xff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -