⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wpa.c

📁 hostapd无线AP工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Host AP (software wireless LAN access point) user space daemon for * Host AP kernel driver / WPA Authenticator * Copyright (c) 2004-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 <stdlib.h>#include <stdio.h>#include <string.h>#include <netinet/in.h>#include <sys/time.h>#include <time.h>#include <unistd.h>#include "hostapd.h"#include "eapol_sm.h"#include "wpa.h"#include "driver.h"#include "sha1.h"#include "md5.h"#include "rc4.h"#include "aes_wrap.h"#include "ieee802_1x.h"#include "ieee802_11.h"#include "eloop.h"#include "sta_info.h"#include "l2_packet.h"static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);static void wpa_sm_step(struct wpa_state_machine *sm);static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len);static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);static void wpa_group_sm_step(struct hostapd_data *hapd);static void pmksa_cache_free(struct hostapd_data *hapd);static struct rsn_pmksa_cache * pmksa_cache_get(struct hostapd_data *hapd,						u8 *spa, u8 *pmkid);/* Default timeouts are 100 ms, but this seems to be a bit too fast for most * WPA Supplicants, so use a bit longer timeout. */static const u32 dot11RSNAConfigGroupUpdateTimeOut = 1000; /* ms */static const u32 dot11RSNAConfigGroupUpdateCount = 3;static const u32 dot11RSNAConfigPairwiseUpdateTimeOut = 1000; /* ms */static const u32 dot11RSNAConfigPairwiseUpdateCount = 3;/* TODO: make these configurable */static const int dot11RSNAConfigPMKLifetime = 43200;static const int dot11RSNAConfigPMKReauthThreshold = 70;static const int dot11RSNAConfigSATimeout = 60;static const int pmksa_cache_max_entries = 1024;static const int WPA_SELECTOR_LEN = 4;static const u8 WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };static const u16 WPA_VERSION = 1;static const u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };static const u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };static const u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };static const u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };static const u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };static const u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };static const u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };static const u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };static const int RSN_SELECTOR_LEN = 4;static const u16 RSN_VERSION = 1;static const u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };static const u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };static const u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };static const u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };static const u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };static const u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };static const u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };static const u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };/* EAPOL-Key Key Data Encapsulation * GroupKey and STAKey require encryption, otherwise, encryption is optional. */static const u8 RSN_KEY_DATA_GROUPKEY[] = { 0x00, 0x0f, 0xac, 1 };static const u8 RSN_KEY_DATA_STAKEY[] = { 0x00, 0x0f, 0xac, 2 };static const u8 RSN_KEY_DATA_MAC_ADDR[] = { 0x00, 0x0f, 0xac, 3 };static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 };/* WPA IE version 1 * 00-50-f2:1 (OUI:OUI type) * 0x01 0x00 (version; little endian) * (all following fields are optional:) * Group Suite Selector (4 octets) (default: TKIP) * Pairwise Suite Count (2 octets, little endian) (default: 1) * Pairwise Suite List (4 * n octets) (default: TKIP) * Authenticated Key Management Suite Count (2 octets, little endian) *    (default: 1) * Authenticated Key Management Suite List (4 * n octets) *    (default: unspec 802.1X) * WPA Capabilities (2 octets, little endian) (default: 0) */struct wpa_ie_hdr {	u8 elem_id;	u8 len;	u8 oui[3];	u8 oui_type;	u16 version;} __attribute__ ((packed));/* RSN IE version 1 * 0x01 0x00 (version; little endian) * (all following fields are optional:) * Group Suite Selector (4 octets) (default: CCMP) * Pairwise Suite Count (2 octets, little endian) (default: 1) * Pairwise Suite List (4 * n octets) (default: CCMP) * Authenticated Key Management Suite Count (2 octets, little endian) *    (default: 1) * Authenticated Key Management Suite List (4 * n octets) *    (default: unspec 802.1X) * RSN Capabilities (2 octets, little endian) (default: 0) * PMKID Count (2 octets) (default: 0) * PMKID List (16 * n octets) */struct rsn_ie_hdr {	u8 elem_id; /* WLAN_EID_RSN */	u8 len;	u16 version;} __attribute__ ((packed));static int wpa_write_wpa_ie(struct hostapd_data *hapd, u8 *buf, size_t len){	struct wpa_ie_hdr *hdr;	int num_suites;	u8 *pos, *count;	hdr = (struct wpa_ie_hdr *) buf;	hdr->elem_id = WLAN_EID_GENERIC;	memcpy(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN);	hdr->version = host_to_le16(WPA_VERSION);	pos = (u8 *) (hdr + 1);	if (hapd->conf->wpa_group == WPA_CIPHER_CCMP) {		memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);	} else if (hapd->conf->wpa_group == WPA_CIPHER_TKIP) {		memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);	} else if (hapd->conf->wpa_group == WPA_CIPHER_WEP104) {		memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN);	} else if (hapd->conf->wpa_group == WPA_CIPHER_WEP40) {		memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN);	} else {		printf("Invalid group cipher (%d).\n", hapd->conf->wpa_group);		return -1;	}	pos += WPA_SELECTOR_LEN;	num_suites = 0;	count = pos;	pos += 2;	if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {		memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);		pos += WPA_SELECTOR_LEN;		num_suites++;	}	if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {		memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);		pos += WPA_SELECTOR_LEN;		num_suites++;	}	if (hapd->conf->wpa_pairwise & WPA_CIPHER_NONE) {		memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN);		pos += WPA_SELECTOR_LEN;		num_suites++;	}	if (num_suites == 0) {		printf("Invalid pairwise cipher (%d).\n",		       hapd->conf->wpa_pairwise);		return -1;	}	*count++ = num_suites & 0xff;	*count = (num_suites >> 8) & 0xff;	num_suites = 0;	count = pos;	pos += 2;	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {		memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN);		pos += WPA_SELECTOR_LEN;		num_suites++;	}	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {		memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X,		       WPA_SELECTOR_LEN);		pos += WPA_SELECTOR_LEN;		num_suites++;	}	if (num_suites == 0) {		printf("Invalid key management type (%d).\n",		       hapd->conf->wpa_key_mgmt);		return -1;	}	*count++ = num_suites & 0xff;	*count = (num_suites >> 8) & 0xff;	/* WPA Capabilities; use defaults, so no need to include it */	hdr->len = (pos - buf) - 2;	return pos - buf;}static int wpa_write_rsn_ie(struct hostapd_data *hapd, u8 *buf, size_t len){	struct rsn_ie_hdr *hdr;	int num_suites;	u8 *pos, *count;	hdr = (struct rsn_ie_hdr *) buf;	hdr->elem_id = WLAN_EID_RSN;	pos = (u8 *) &hdr->version;	*pos++ = RSN_VERSION & 0xff;	*pos++ = RSN_VERSION >> 8;	pos = (u8 *) (hdr + 1);	if (hapd->conf->wpa_group == WPA_CIPHER_CCMP) {		memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);	} else if (hapd->conf->wpa_group == WPA_CIPHER_TKIP) {		memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);	} else if (hapd->conf->wpa_group == WPA_CIPHER_WEP104) {		memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN);	} else if (hapd->conf->wpa_group == WPA_CIPHER_WEP40) {		memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN);	} else {		printf("Invalid group cipher (%d).\n", hapd->conf->wpa_group);		return -1;	}	pos += RSN_SELECTOR_LEN;	num_suites = 0;	count = pos;	pos += 2;	if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) {		memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		num_suites++;	}	if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) {		memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		num_suites++;	}	if (hapd->conf->wpa_pairwise & WPA_CIPHER_NONE) {		memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		num_suites++;	}	if (num_suites == 0) {		printf("Invalid pairwise cipher (%d).\n",		       hapd->conf->wpa_pairwise);		return -1;	}	*count++ = num_suites & 0xff;	*count = (num_suites >> 8) & 0xff;	num_suites = 0;	count = pos;	pos += 2;	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {		memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		num_suites++;	}	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {		memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X,		       RSN_SELECTOR_LEN);		pos += RSN_SELECTOR_LEN;		num_suites++;	}	if (num_suites == 0) {		printf("Invalid key management type (%d).\n",		       hapd->conf->wpa_key_mgmt);		return -1;	}	*count++ = num_suites & 0xff;	*count = (num_suites >> 8) & 0xff;	/* RSN Capabilities */	*pos++ = hapd->conf->rsn_preauth ? BIT(0) : 0;	*pos++ = 0;	hdr->len = (pos - buf) - 2;	return pos - buf;}static int wpa_gen_wpa_ie(struct hostapd_data *hapd){	u8 *pos, buf[100];	int res;	pos = buf;	if (hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA2) {		res = wpa_write_rsn_ie(hapd, pos, buf + sizeof(buf) - pos);		if (res < 0)			return res;		pos += res;	}	if (hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA) {		res = wpa_write_wpa_ie(hapd, pos, buf + sizeof(buf) - pos);		if (res < 0)			return res;		pos += res;	}	free(hapd->wpa_ie);	hapd->wpa_ie = malloc(pos - buf);	if (hapd->wpa_ie == NULL)		return -1;	memcpy(hapd->wpa_ie, buf, pos - buf);	hapd->wpa_ie_len = pos - buf;	return 0;}static void wpa_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta){	hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID);	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);	eloop_cancel_timeout(ap_handle_timer, hapd, sta);	eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);	sta->timeout_next = STA_REMOVE;}static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx){	struct hostapd_data *hapd = eloop_ctx;	if (hapd->wpa_auth) {		if (hostapd_get_rand(hapd->wpa_auth->GMK, WPA_GMK_LEN)) {			printf("Failed to get random data for WPA "			       "initialization.\n");		} else {			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_DEBUG,				       "GMK rekeyd");		}	}	if (hapd->conf->wpa_gmk_rekey) {		eloop_register_timeout(hapd->conf->wpa_gmk_rekey, 0,				       wpa_rekey_gmk, hapd, NULL);	}}static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx){	struct hostapd_data *hapd = eloop_ctx;	if (hapd->wpa_auth) {		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_WPA,			       HOSTAPD_LEVEL_DEBUG, "rekeying GTK");		hapd->wpa_auth->GTKReKey = TRUE;		do {			hapd->wpa_auth->changed = FALSE;			wpa_group_sm_step(hapd);		} while (hapd->wpa_auth->changed);	}	if (hapd->conf->wpa_group_rekey) {		eloop_register_timeout(hapd->conf->wpa_group_rekey, 0,				       wpa_rekey_gtk, hapd, NULL);	}}#ifdef CONFIG_RSN_PREAUTHstatic void rsn_preauth_receive(void *ctx, unsigned char *src_addr,				unsigned char *buf, size_t len){	struct rsn_preauth_interface *piface = ctx;	struct hostapd_data *hapd = piface->hapd;	struct ieee802_1x_hdr *hdr;	struct sta_info *sta;	struct l2_ethhdr *ethhdr;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: receive pre-auth packet "		      "from interface '%s'\n", piface->ifname);	if (len < sizeof(*ethhdr) + sizeof(*hdr)) {		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: too short pre-auth "			      "packet (len=%lu)\n", (unsigned long) len);		return;	}	ethhdr = (struct l2_ethhdr *) buf;	hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);	if (memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for "			      "foreign address " MACSTR "\n",			      MAC2STR(ethhdr->h_dest));		return;	}	sta = ap_get_sta(hapd, ethhdr->h_source);	if (sta && (sta->flags & WLAN_STA_ASSOC)) {		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for "			      "already association STA " MACSTR "\n",			      MAC2STR(sta->addr));		return;	}	if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {		sta = (struct sta_info *) malloc(sizeof(struct sta_info));		if (sta == NULL)			return;		memset(sta, 0, sizeof(*sta));		memcpy(sta->addr, ethhdr->h_source, ETH_ALEN);		sta->flags = WLAN_STA_PREAUTH;		sta->next = hapd->sta_list;		sta->wpa = WPA_VERSION_WPA2;		hapd->sta_list = sta;		hapd->num_sta++;		ap_sta_hash_add(hapd, sta);		ieee802_1x_new_station(hapd, sta);		if (sta->eapol_sm == NULL) {			ap_free_sta(hapd, sta);			sta = NULL;		} else {			sta->eapol_sm->radius_identifier = -1;			sta->eapol_sm->portValid = TRUE;			sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;		}	}	if (sta == NULL)		return;	sta->preauth_iface = piface;	ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),			   len - sizeof(*ethhdr));}static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname){	struct rsn_preauth_interface *piface;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN pre-auth interface '%s'\n",		      ifname);	piface = malloc(sizeof(*piface));	if (piface == NULL)		return -1;	memset(piface, 0, sizeof(*piface));	piface->hapd = hapd;	piface->ifname = strdup(ifname);	if (piface->ifname == NULL) {		goto fail1;	}	piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,				    rsn_preauth_receive, piface);	if (piface->l2 == NULL) {		printf("Failed to open register layer 2 access to "		       "ETH_P_PREAUTH\n");		goto fail2;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -