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

📄 ieee802_1x.c

📁 hostapd无线AP工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Host AP (software wireless LAN access point) user space daemon for * Host AP kernel driver / IEEE 802.1X Authenticator * 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 <stdlib.h>#include <stdio.h>#include <unistd.h>#include <netinet/in.h>#include <string.h>#include <sys/ioctl.h>#include <signal.h>#include <assert.h>#include <time.h>#include <sys/time.h>#include <sys/socket.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 "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(hostapd *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 = malloc(len);	if (buf == NULL) {		printf("malloc() failed for ieee802_1x_send(len=%lu)\n",		       (unsigned long) len);		return;	}	memset(buf, 0, len);#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 = EAPOL_VERSION;	xhdr->type = type;	xhdr->length = htons(datalen);	if (datalen > 0 && data != NULL)		memcpy(xhdr + 1, data, datalen);	if (sta->wpa_sm && sta->wpa_sm->pairwise_set)		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(hostapd *hapd, struct sta_info *sta,				   int authorized){	if (sta->flags & WLAN_STA_PREAUTH)		return;	if (authorized) {		sta->flags |= WLAN_STA_AUTHORIZED;		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "authorizing port");	} else {		sta->flags &= ~WLAN_STA_AUTHORIZED;		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "unauthorizing port");	}	hostapd_set_sta_authorized(hapd, sta->addr, authorized);	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->auth_pae.eapRestart)		return;	ieee802_1x_new_auth_session(hapd, sta);	tlen = sizeof(*eap) + 1 + hapd->conf->eap_req_id_text_len;	buf = malloc(tlen);	if (buf == NULL) {		printf("Could not allocate memory for identity request\n");		return;	}	memset(buf, 0, tlen);	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->be_auth.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->auth_pae.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++;}void hostapd_get_ntp_timestamp(u8 *buf){	struct timeval now;	u32 sec, usec;	/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */	gettimeofday(&now, NULL);	sec = htonl(now.tv_sec + 2208988800U); /* Epoch to 1900 */	/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */	usec = now.tv_usec;	usec = htonl(4295 * usec - (usec >> 5) - (usec >> 9));	memcpy(buf, (u8 *) &sec, 4);	memcpy(buf + 4, (u8 *) &usec, 4);}static void ieee802_1x_tx_key_one(hostapd *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 = malloc(sizeof(*hdr) + len);	if (buf == NULL)		return;	memset(buf, 0, sizeof(*hdr) + len);	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);	hostapd_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 = 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;		}		if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL))			hostapd_hexdump("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, "WEP", sta->addr, 0, ikey,					   hapd->conf->					   individual_wep_key_len)) {			printf("Could not set individual WEP encryption.\n");		}		free(ikey);	}}static void ieee802_1x_encapsulate_radius(hostapd *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,

⌨️ 快捷键说明

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