📄 ieee802_11.c
字号:
/* * hostapd / IEEE 802.11 Management * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#ifndef CONFIG_NATIVE_WINDOWS#include <net/if.h>#include "eloop.h"#include "hostapd.h"#include "ieee802_11.h"#include "beacon.h"#include "hw_features.h"#include "radius.h"#include "radius_client.h"#include "ieee802_11_auth.h"#include "sta_info.h"#include "eapol_sm.h"#include "rc4.h"#include "ieee802_1x.h"#include "wpa.h"#include "accounting.h"#include "driver.h"#include "hostap_common.h"u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid){ u8 *pos = eid; int i, num, count; if (hapd->iface->current_rates == NULL) return eid; *pos++ = WLAN_EID_SUPP_RATES; num = hapd->iface->num_rates; if (num > 8) { /* rest of the rates are encoded in Extended supported * rates element */ num = 8; } *pos++ = num; count = 0; for (i = 0, count = 0; i < hapd->iface->num_rates && count < num; i++) { count++; *pos = hapd->iface->current_rates[i].rate / 5; if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) *pos |= 0x80; pos++; } return pos;}u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid){ u8 *pos = eid; int i, num, count; if (hapd->iface->current_rates == NULL) return eid; num = hapd->iface->num_rates; if (num <= 8) return eid; num -= 8; *pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = num; count = 0; for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8; i++) { count++; if (count <= 8) continue; /* already in SuppRates IE */ *pos = hapd->iface->current_rates[i].rate / 5; if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) *pos |= 0x80; pos++; } return pos;}u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, int probe){ int capab = WLAN_CAPABILITY_ESS; int privacy; privacy = hapd->conf->ssid.wep.keys_set; if (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)) privacy = 1; if (hapd->conf->wpa) privacy = 1; if (sta) { int policy, def_klen; if (probe && sta->ssid_probe) { policy = sta->ssid_probe->security_policy; def_klen = sta->ssid_probe->wep.default_len; } else { policy = sta->ssid->security_policy; def_klen = sta->ssid->wep.default_len; } privacy = policy != SECURITY_PLAINTEXT; if (policy == SECURITY_IEEE_802_1X && def_klen == 0) privacy = 0; } if (privacy) capab |= WLAN_CAPABILITY_PRIVACY; return capab;}static const u8 WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors){ size_t left = len; u8 *pos = start; int unknown = 0; memset(elems, 0, sizeof(*elems)); while (left >= 2) { u8 id, elen; id = *pos++; elen = *pos++; left -= 2; if (elen > left) { if (show_errors) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.11 element parse " "failed (id=%d elen=%d " "left=%lu)\n", 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_EXT_SUPP_RATES: elems->ext_supp_rates = pos; elems->ext_supp_rates_len = elen; break; case WLAN_EID_GENERIC: if (elen > 4 && memcmp(pos, WPA_OUI_TYPE, 4) == 0) { elems->wpa_ie = pos; elems->wpa_ie_len = elen; } else if (show_errors) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "IEEE 802.11 element parse " "ignored unknown generic element" " (id=%d elen=%d OUI:type=" "%02x-%02x-%02x:%d)\n", id, elen, elen >= 1 ? pos[0] : 0, elen >= 2 ? pos[1] : 0, elen >= 3 ? pos[2] : 0, elen >= 4 ? pos[3] : 0); unknown++; } else { unknown++; } break; case WLAN_EID_RSN: elems->rsn_ie = pos; elems->rsn_ie_len = elen; break; default: unknown++; if (!show_errors) break; HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "IEEE 802.11 element parse ignored " "unknown element (id=%d elen=%d)\n", id, elen); break; } left -= elen; pos += elen; } if (left) return ParseFailed; return unknown ? ParseUnknown : ParseOK;}void ieee802_11_print_ssid(const u8 *ssid, u8 len){ int i; for (i = 0; i < len; i++) { if (ssid[i] >= 32 && ssid[i] < 127) printf("%c", ssid[i]); else printf("<%02x>", ssid[i]); }}static void ieee802_11_sta_authenticate(void *eloop_ctx, void *timeout_ctx){ struct hostapd_data *hapd = eloop_ctx; struct ieee80211_mgmt mgmt; if (hapd->assoc_ap_state == WAIT_BEACON) hapd->assoc_ap_state = AUTHENTICATE; if (hapd->assoc_ap_state != AUTHENTICATE) return; printf("Authenticate with AP " MACSTR " SSID=", MAC2STR(hapd->conf->assoc_ap_addr)); ieee802_11_print_ssid((u8 *) hapd->assoc_ap_ssid, hapd->assoc_ap_ssid_len); printf(" (as station)\n"); memset(&mgmt, 0, sizeof(mgmt)); mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_AUTH); /* Request TX callback */ mgmt.frame_control |= host_to_le16(BIT(1)); memcpy(mgmt.da, hapd->conf->assoc_ap_addr, ETH_ALEN); memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); memcpy(mgmt.bssid, hapd->conf->assoc_ap_addr, ETH_ALEN); mgmt.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN); mgmt.u.auth.auth_transaction = host_to_le16(1); mgmt.u.auth.status_code = host_to_le16(0); if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + sizeof(mgmt.u.auth), 0) < 0) perror("ieee802_11_sta_authenticate: send"); /* Try to authenticate again, if this attempt fails or times out. */ eloop_register_timeout(5, 0, ieee802_11_sta_authenticate, hapd, NULL);}static void ieee802_11_sta_associate(void *eloop_ctx, void *timeout_ctx){ struct hostapd_data *hapd = eloop_ctx; u8 buf[256]; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; u8 *p; if (hapd->assoc_ap_state == AUTHENTICATE) hapd->assoc_ap_state = ASSOCIATE; if (hapd->assoc_ap_state != ASSOCIATE) return; printf("Associate with AP " MACSTR " SSID=", MAC2STR(hapd->conf->assoc_ap_addr)); ieee802_11_print_ssid((u8 *) hapd->assoc_ap_ssid, hapd->assoc_ap_ssid_len); printf(" (as station)\n"); memset(mgmt, 0, sizeof(*mgmt)); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ASSOC_REQ); /* Request TX callback */ mgmt->frame_control |= host_to_le16(BIT(1)); memcpy(mgmt->da, hapd->conf->assoc_ap_addr, ETH_ALEN); memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); memcpy(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN); mgmt->u.assoc_req.capab_info = host_to_le16(0); mgmt->u.assoc_req.listen_interval = host_to_le16(1); p = &mgmt->u.assoc_req.variable[0]; *p++ = WLAN_EID_SSID; *p++ = hapd->assoc_ap_ssid_len; memcpy(p, hapd->assoc_ap_ssid, hapd->assoc_ap_ssid_len); p += hapd->assoc_ap_ssid_len; p = hostapd_eid_supp_rates(hapd, p); p = hostapd_eid_ext_supp_rates(hapd, p); if (hostapd_send_mgmt_frame(hapd, mgmt, p - (u8 *) mgmt, 0) < 0) perror("ieee802_11_sta_associate: send"); /* Try to authenticate again, if this attempt fails or times out. */ eloop_register_timeout(5, 0, ieee802_11_sta_associate, hapd, NULL);}static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, u16 auth_transaction, u8 *challenge, int iswep){ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "authentication (shared key, transaction %d)", auth_transaction); if (auth_transaction == 1) { if (!sta->challenge) { /* Generate a pseudo-random challenge */ u8 key[8]; time_t now; int r; sta->challenge = wpa_zalloc(WLAN_AUTH_CHALLENGE_LEN); if (sta->challenge == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; now = time(NULL); r = random(); memcpy(key, &now, 4); memcpy(key + 4, &r, 4); rc4(sta->challenge, WLAN_AUTH_CHALLENGE_LEN, key, sizeof(key)); } return 0; } if (auth_transaction != 3) return WLAN_STATUS_UNSPECIFIED_FAILURE; /* Transaction 3 */ if (!iswep || !sta->challenge || !challenge || memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "shared key authentication - invalid " "challenge-response"); return WLAN_STATUS_CHALLENGE_FAIL; } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "authentication OK (shared key)");#ifdef IEEE80211_REQUIRE_AUTH_ACK /* Station will be marked authenticated if it ACKs the * authentication reply. */#else sta->flags |= WLAN_STA_AUTH; wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);#endif free(sta->challenge); sta->challenge = NULL; return 0;}static void send_auth_reply(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, u16 auth_alg, u16 auth_transaction, u16 resp, u8 *challenge){ u8 buf[IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2 + WLAN_AUTH_CHALLENGE_LEN]; struct ieee80211_mgmt *reply; size_t rlen; memset(buf, 0, sizeof(buf)); reply = (struct ieee80211_mgmt *) buf; reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_AUTH); /* Request TX callback */ reply->frame_control |= host_to_le16(BIT(1)); memcpy(reply->da, mgmt->sa, ETH_ALEN); memcpy(reply->sa, hapd->own_addr, ETH_ALEN); memcpy(reply->bssid, mgmt->bssid, ETH_ALEN); reply->u.auth.auth_alg = host_to_le16(auth_alg); reply->u.auth.auth_transaction = host_to_le16(auth_transaction); reply->u.auth.status_code = host_to_le16(resp); rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth); if (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 2 && challenge) { u8 *p = reply->u.auth.variable; *p++ = WLAN_EID_CHALLENGE; *p++ = WLAN_AUTH_CHALLENGE_LEN; memcpy(p, challenge, WLAN_AUTH_CHALLENGE_LEN); rlen += 2 + WLAN_AUTH_CHALLENGE_LEN; } else challenge = NULL; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "authentication reply: STA=" MACSTR " auth_alg=%d " "auth_transaction=%d resp=%d%s\n", MAC2STR(mgmt->sa), auth_alg, auth_transaction, resp, challenge ? " challenge" : ""); if (hostapd_send_mgmt_frame(hapd, reply, rlen, 0) < 0) perror("send_auth_reply: send");}static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -