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

📄 ieee802_1x.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * hostapd / IEEE 802.1X Authenticator * Copyright (c) 2002-2006, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include <assert.h>#include "hostapd.h"#include "ieee802_1x.h"#include "accounting.h"#include "radius.h"#include "radius_client.h"#include "eapol_sm.h"#include "md5.h"#include "rc4.h"#include "eloop.h"#include "sta_info.h"#include "wpa.h"#include "preauth.h"#include "pmksa_cache.h"#include "driver.h"#include "eap.h"static void ieee802_1x_new_auth_session(struct hostapd_data *hapd,					struct sta_info *sta);static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,			    u8 type, u8 *data, size_t datalen){	u8 *buf;	struct ieee802_1x_hdr *xhdr;	size_t len;	int encrypt = 0;	len = sizeof(*xhdr) + datalen;	buf = wpa_zalloc(len);	if (buf == NULL) {		printf("malloc() failed for ieee802_1x_send(len=%lu)\n",		       (unsigned long) len);		return;	}#if 0	/* TODO:	 * According to IEEE 802.1aa/D4 EAPOL-Key should be sent before any	 * remaining EAP frames, if possible. This would allow rest of the	 * frames to be encrypted. This code could be used to request	 * encryption from the kernel driver. */	if (sta->eapol_sm &&	    sta->eapol_sm->be_auth.state == BE_AUTH_SUCCESS &&	    sta->eapol_sm->keyTxEnabled)		encrypt = 1;#endif	xhdr = (struct ieee802_1x_hdr *) buf;	xhdr->version = hapd->conf->eapol_version;	xhdr->type = type;	xhdr->length = htons(datalen);	if (datalen > 0 && data != NULL)		memcpy(xhdr + 1, data, datalen);	if (wpa_auth_pairwise_set(sta->wpa_sm))		encrypt = 1;	if (sta->flags & WLAN_STA_PREAUTH) {		rsn_preauth_send(hapd, sta, buf, len);	} else {		hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt);	}	free(buf);}void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,				   struct sta_info *sta, int authorized){	int res;	if (sta->flags & WLAN_STA_PREAUTH)		return;	if (authorized) {		sta->flags |= WLAN_STA_AUTHORIZED;		res = hostapd_sta_set_flags(hapd, sta->addr,					    WLAN_STA_AUTHORIZED, ~0);		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "authorizing port");	} else {		sta->flags &= ~WLAN_STA_AUTHORIZED;		res = hostapd_sta_set_flags(hapd, sta->addr,					    0, ~WLAN_STA_AUTHORIZED);		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "unauthorizing port");	}	if (res && errno != ENOENT) {		printf("Could not set station " MACSTR " flags for kernel "		       "driver (errno=%d).\n", MAC2STR(sta->addr), errno);	}	if (authorized)		accounting_sta_start(hapd, sta);}static void ieee802_1x_eap_timeout(void *eloop_ctx, void *timeout_ctx){	struct sta_info *sta = eloop_ctx;	struct eapol_state_machine *sm = sta->eapol_sm;	if (sm == NULL)		return;	hostapd_logger(sm->hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,		       HOSTAPD_LEVEL_DEBUG, "EAP timeout");	sm->eapTimeout = TRUE;	eapol_sm_step(sm);}void ieee802_1x_request_identity(struct hostapd_data *hapd,				 struct sta_info *sta){	u8 *buf;	struct eap_hdr *eap;	int tlen;	u8 *pos;	struct eapol_state_machine *sm = sta->eapol_sm;	if (hapd->conf->eap_server) {		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,			      "IEEE 802.1X: Integrated EAP server in "			      "use - do not generate EAP-Request/Identity\n");		return;	}	if (sm == NULL || !sm->eapRestart)		return;	ieee802_1x_new_auth_session(hapd, sta);	tlen = sizeof(*eap) + 1 + hapd->conf->eap_req_id_text_len;	buf = wpa_zalloc(tlen);	if (buf == NULL) {		printf("Could not allocate memory for identity request\n");		return;	}	eap = (struct eap_hdr *) buf;	eap->code = EAP_CODE_REQUEST;	eap->identifier = ++sm->currentId;	eap->length = htons(tlen);	pos = (u8 *) (eap + 1);	*pos++ = EAP_TYPE_IDENTITY;	if (hapd->conf->eap_req_id_text) {		memcpy(pos, hapd->conf->eap_req_id_text,		       hapd->conf->eap_req_id_text_len);	}	sm->eapReq = TRUE;	free(sm->last_eap_radius);	sm->last_eap_radius = buf;	sm->last_eap_radius_len = tlen;	eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);	eloop_register_timeout(30, 0, ieee802_1x_eap_timeout, sta, NULL);	sm->eapTimeout = FALSE;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "IEEE 802.1X: Generated EAP Request-Identity for " MACSTR		      " (identifier %d, timeout 30)\n", MAC2STR(sta->addr),		      eap->identifier);	sm->eapRestart = FALSE;}void ieee802_1x_tx_canned_eap(struct hostapd_data *hapd, struct sta_info *sta,			      int success){	struct eap_hdr eap;	struct eapol_state_machine *sm = sta->eapol_sm;	memset(&eap, 0, sizeof(eap));	eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;	eap.identifier = 1;	if (sm && sm->last_eap_radius) {		struct eap_hdr *hdr = (struct eap_hdr *) sm->last_eap_radius;		eap.identifier = hdr->identifier + 1;	}	eap.length = htons(sizeof(eap));	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "IEEE 802.1X: Sending canned EAP packet %s to " MACSTR		      " (identifier %d)\n", success ? "SUCCESS" : "FAILURE",		      MAC2STR(sta->addr), eap.identifier);	ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAP_PACKET, (u8 *) &eap,			sizeof(eap));	if (sm)		sm->dot1xAuthEapolFramesTx++;}void ieee802_1x_tx_req(struct hostapd_data *hapd, struct sta_info *sta){	struct eap_hdr *eap;	struct eapol_state_machine *sm = sta->eapol_sm;	u8 *type;	if (sm == NULL)		return;	if (sm->last_eap_radius == NULL) {		printf("Error: TxReq called for station " MACSTR ", but there "		       "is no EAP request from the authentication server\n",		       MAC2STR(sm->addr));		return;	}	eap = (struct eap_hdr *) sm->last_eap_radius;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "IEEE 802.1X: Sending EAP Packet to " MACSTR		      " (identifier %d)\n", MAC2STR(sm->addr),		      eap->identifier);	sm->currentId = eap->identifier;	ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAP_PACKET,			sm->last_eap_radius, sm->last_eap_radius_len);	sm->dot1xAuthEapolFramesTx++;	type = (u8 *) (eap + 1);	if (sm->last_eap_radius_len > sizeof(*eap) &&	    *type == EAP_TYPE_IDENTITY)		sm->dot1xAuthEapolReqIdFramesTx++;	else		sm->dot1xAuthEapolReqFramesTx++;}static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,				  struct sta_info *sta,				  int index, int broadcast,				  u8 *key_data, size_t key_len){	u8 *buf, *ekey;	struct ieee802_1x_hdr *hdr;	struct ieee802_1x_eapol_key *key;	size_t len, ekey_len;	struct eapol_state_machine *sm = sta->eapol_sm;	if (sm == NULL)		return;	len = sizeof(*key) + key_len;	buf = wpa_zalloc(sizeof(*hdr) + len);	if (buf == NULL)		return;	hdr = (struct ieee802_1x_hdr *) buf;	key = (struct ieee802_1x_eapol_key *) (hdr + 1);	key->type = EAPOL_KEY_TYPE_RC4;	key->key_length = htons(key_len);	wpa_get_ntp_timestamp(key->replay_counter);	if (hostapd_get_rand(key->key_iv, sizeof(key->key_iv))) {		printf("Could not get random numbers\n");		free(buf);		return;	}	key->key_index = index | (broadcast ? 0 : BIT(7));	if (hapd->conf->eapol_key_index_workaround) {		/* According to some information, WinXP Supplicant seems to		 * interpret bit7 as an indication whether the key is to be		 * activated, so make it possible to enable workaround that		 * sets this bit for all keys. */		key->key_index |= BIT(7);	}	/* Key is encrypted using "Key-IV + sm->eapol_key_crypt" as the	 * RC4-key */	memcpy((u8 *) (key + 1), key_data, key_len);	ekey_len = sizeof(key->key_iv) + sm->eapol_key_crypt_len;	ekey = malloc(ekey_len);	if (ekey == NULL) {		printf("Could not encrypt key\n");		free(buf);		return;	}	memcpy(ekey, key->key_iv, sizeof(key->key_iv));	memcpy(ekey + sizeof(key->key_iv), sm->eapol_key_crypt,	       sm->eapol_key_crypt_len);	rc4((u8 *) (key + 1), key_len, ekey, ekey_len);	free(ekey);	/* This header is needed here for HMAC-MD5, but it will be regenerated	 * in ieee802_1x_send() */	hdr->version = hapd->conf->eapol_version;	hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;	hdr->length = htons(len);	hmac_md5(sm->eapol_key_sign, sm->eapol_key_sign_len,		 buf, sizeof(*hdr) + len,		 key->key_signature);	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "IEEE 802.1X: Sending EAPOL-Key to " MACSTR		      " (%s index=%d)\n", MAC2STR(sm->addr),		      broadcast ? "broadcast" : "unicast", index);	ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len);	if (sta->eapol_sm)		sta->eapol_sm->dot1xAuthEapolFramesTx++;	free(buf);}void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta){	struct eapol_state_machine *sm = sta->eapol_sm;	if (sm == NULL || !sm->eapol_key_sign || !sm->eapol_key_crypt)		return;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR "\n",		      MAC2STR(sta->addr));	if (hapd->default_wep_key)		ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1,				      hapd->default_wep_key,				      hapd->conf->default_wep_key_len);	if (hapd->conf->individual_wep_key_len > 0) {		u8 *ikey;		ikey = malloc(hapd->conf->individual_wep_key_len);		if (ikey == NULL ||		    hostapd_get_rand(ikey,				     hapd->conf->individual_wep_key_len)) {			printf("Could not generate random individual WEP "			       "key.\n");			free(ikey);			return;		}		wpa_hexdump_key(MSG_DEBUG, "Individual WEP key",				ikey, hapd->conf->individual_wep_key_len);		ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey,				      hapd->conf->individual_wep_key_len);		/* TODO: set encryption in TX callback, i.e., only after STA		 * has ACKed EAPOL-Key frame */		if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP",					   sta->addr, 0, ikey,					   hapd->conf->individual_wep_key_len,					   1)) {			printf("Could not set individual WEP encryption.\n");		}		free(ikey);	}}static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,					  struct sta_info *sta,					  u8 *eap, size_t len){	struct radius_msg *msg;	char buf[128];	struct eapol_state_machine *sm = sta->eapol_sm;	if (sm == NULL)		return;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "Encapsulating EAP message into a RADIUS packet\n");	sm->radius_identifier = radius_client_get_id(hapd->radius);	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,			     sm->radius_identifier);	if (msg == NULL) {		printf("Could not create net RADIUS packet\n");		return;	}	radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));	if (sm->identity &&	    !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,				 sm->identity, sm->identity_len)) {		printf("Could not add User-Name\n");		goto fail;	}	if (hapd->conf->own_ip_addr.af == AF_INET &&	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,				 (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {		printf("Could not add NAS-IP-Address\n");		goto fail;	}#ifdef CONFIG_IPV6	if (hapd->conf->own_ip_addr.af == AF_INET6 &&	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,				 (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {		printf("Could not add NAS-IPv6-Address\n");		goto fail;	}#endif /* CONFIG_IPV6 */	if (hapd->conf->nas_identifier &&	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,				 (u8 *) hapd->conf->nas_identifier,				 strlen(hapd->conf->nas_identifier))) {		printf("Could not add NAS-Identifier\n");		goto fail;	}	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {		printf("Could not add NAS-Port\n");		goto fail;	}	snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",		 MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,				 (u8 *) buf, strlen(buf))) {		printf("Could not add Called-Station-Id\n");		goto fail;	}	snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,		 MAC2STR(sta->addr));	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,				 (u8 *) buf, strlen(buf))) {		printf("Could not add Calling-Station-Id\n");		goto fail;	}

⌨️ 快捷键说明

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