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

📄 radius_server.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * hostapd / RADIUS authentication server * Copyright (c) 2005-2008, Jouni Malinen <j@w1.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 <net/if.h>#include "common.h"#include "radius.h"#include "eloop.h"#include "defs.h"#include "eap_server/eap.h"#include "radius_server.h"#define RADIUS_SESSION_TIMEOUT 60#define RADIUS_MAX_SESSION 100#define RADIUS_MAX_MSG_LEN 3000static struct eapol_callbacks radius_server_eapol_cb;struct radius_client;struct radius_server_data;struct radius_server_counters {	u32 access_requests;	u32 invalid_requests;	u32 dup_access_requests;	u32 access_accepts;	u32 access_rejects;	u32 access_challenges;	u32 malformed_access_requests;	u32 bad_authenticators;	u32 packets_dropped;	u32 unknown_types;};struct radius_session {	struct radius_session *next;	struct radius_client *client;	struct radius_server_data *server;	unsigned int sess_id;	struct eap_sm *eap;	struct eap_eapol_interface *eap_if;	struct radius_msg *last_msg;	char *last_from_addr;	int last_from_port;	struct sockaddr_storage last_from;	socklen_t last_fromlen;	u8 last_identifier;	struct radius_msg *last_reply;	u8 last_authenticator[16];};struct radius_client {	struct radius_client *next;	struct in_addr addr;	struct in_addr mask;#ifdef CONFIG_IPV6	struct in6_addr addr6;	struct in6_addr mask6;#endif /* CONFIG_IPV6 */	char *shared_secret;	int shared_secret_len;	struct radius_session *sessions;	struct radius_server_counters counters;};struct radius_server_data {	int auth_sock;	struct radius_client *clients;	unsigned int next_sess_id;	void *conf_ctx;	int num_sess;	void *eap_sim_db_priv;	void *ssl_ctx;	u8 *pac_opaque_encr_key;	u8 *eap_fast_a_id;	size_t eap_fast_a_id_len;	char *eap_fast_a_id_info;	int eap_fast_prov;	int pac_key_lifetime;	int pac_key_refresh_time;	int eap_sim_aka_result_ind;	int tnc;	struct wps_context *wps;	int ipv6;	struct os_time start_time;	struct radius_server_counters counters;	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,			    int phase2, struct eap_user *user);	char *eap_req_id_text;	size_t eap_req_id_text_len;};extern int wpa_debug_level;#define RADIUS_DEBUG(args...) \wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)#define RADIUS_ERROR(args...) \wpa_printf(MSG_ERROR, "RADIUS SRV: " args)#define RADIUS_DUMP(args...) \wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args)#define RADIUS_DUMP_ASCII(args...) \wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args)static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);static struct radius_client *radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,			 int ipv6){	struct radius_client *client = data->clients;	while (client) {#ifdef CONFIG_IPV6		if (ipv6) {			struct in6_addr *addr6;			int i;			addr6 = (struct in6_addr *) addr;			for (i = 0; i < 16; i++) {				if ((addr6->s6_addr[i] &				     client->mask6.s6_addr[i]) !=				    (client->addr6.s6_addr[i] &				     client->mask6.s6_addr[i])) {					i = 17;					break;				}			}			if (i == 16) {				break;			}		}#endif /* CONFIG_IPV6 */		if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) ==		    (addr->s_addr & client->mask.s_addr)) {			break;		}		client = client->next;	}	return client;}static struct radius_session *radius_server_get_session(struct radius_client *client, unsigned int sess_id){	struct radius_session *sess = client->sessions;	while (sess) {		if (sess->sess_id == sess_id) {			break;		}		sess = sess->next;	}	return sess;}static void radius_server_session_free(struct radius_server_data *data,				       struct radius_session *sess){	eloop_cancel_timeout(radius_server_session_timeout, data, sess);	eap_server_sm_deinit(sess->eap);	if (sess->last_msg) {		radius_msg_free(sess->last_msg);		os_free(sess->last_msg);	}	os_free(sess->last_from_addr);	if (sess->last_reply) {		radius_msg_free(sess->last_reply);		os_free(sess->last_reply);	}	os_free(sess);	data->num_sess--;}static void radius_server_session_remove_timeout(void *eloop_ctx,						 void *timeout_ctx);static void radius_server_session_remove(struct radius_server_data *data,					 struct radius_session *sess){	struct radius_client *client = sess->client;	struct radius_session *session, *prev;	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);	prev = NULL;	session = client->sessions;	while (session) {		if (session == sess) {			if (prev == NULL) {				client->sessions = sess->next;			} else {				prev->next = sess->next;			}			radius_server_session_free(data, sess);			break;		}		prev = session;		session = session->next;	}}static void radius_server_session_remove_timeout(void *eloop_ctx,						 void *timeout_ctx){	struct radius_server_data *data = eloop_ctx;	struct radius_session *sess = timeout_ctx;	RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id);	radius_server_session_remove(data, sess);}static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx){	struct radius_server_data *data = eloop_ctx;	struct radius_session *sess = timeout_ctx;	RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id);	radius_server_session_remove(data, sess);}static struct radius_session *radius_server_new_session(struct radius_server_data *data,			  struct radius_client *client){	struct radius_session *sess;	if (data->num_sess >= RADIUS_MAX_SESSION) {		RADIUS_DEBUG("Maximum number of existing session - no room "			     "for a new session");		return NULL;	}	sess = os_zalloc(sizeof(*sess));	if (sess == NULL)		return NULL;	sess->server = data;	sess->client = client;	sess->sess_id = data->next_sess_id++;	sess->next = client->sessions;	client->sessions = sess;	eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0,			       radius_server_session_timeout, data, sess);	data->num_sess++;	return sess;}static struct radius_session *radius_server_get_new_session(struct radius_server_data *data,			      struct radius_client *client,			      struct radius_msg *msg){	u8 *user;	size_t user_len;	int res;	struct radius_session *sess;	struct eap_config eap_conf;	RADIUS_DEBUG("Creating a new session");	user = os_malloc(256);	if (user == NULL) {		return NULL;	}	res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);	if (res < 0 || res > 256) {		RADIUS_DEBUG("Could not get User-Name");		os_free(user);		return NULL;	}	user_len = res;	RADIUS_DUMP_ASCII("User-Name", user, user_len);	res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);	os_free(user);	if (res == 0) {		RADIUS_DEBUG("Matching user entry found");		sess = radius_server_new_session(data, client);		if (sess == NULL) {			RADIUS_DEBUG("Failed to create a new session");			return NULL;		}	} else {		RADIUS_DEBUG("User-Name not found from user database");		return NULL;	}	os_memset(&eap_conf, 0, sizeof(eap_conf));	eap_conf.ssl_ctx = data->ssl_ctx;	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;	eap_conf.backend_auth = TRUE;	eap_conf.eap_server = 1;	eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;	eap_conf.eap_fast_a_id = data->eap_fast_a_id;	eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;	eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;	eap_conf.eap_fast_prov = data->eap_fast_prov;	eap_conf.pac_key_lifetime = data->pac_key_lifetime;	eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;	eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;	eap_conf.tnc = data->tnc;	eap_conf.wps = data->wps;	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,				       &eap_conf);	if (sess->eap == NULL) {		RADIUS_DEBUG("Failed to initialize EAP state machine for the "			     "new session");		radius_server_session_free(data, sess);		return NULL;	}	sess->eap_if = eap_get_interface(sess->eap);	sess->eap_if->eapRestart = TRUE;	sess->eap_if->portEnabled = TRUE;	RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id);	return sess;}static struct radius_msg *radius_server_encapsulate_eap(struct radius_server_data *data,			      struct radius_client *client,			      struct radius_session *sess,			      struct radius_msg *request){	struct radius_msg *msg;	int code;	unsigned int sess_id;	if (sess->eap_if->eapFail) {		sess->eap_if->eapFail = FALSE;		code = RADIUS_CODE_ACCESS_REJECT;	} else if (sess->eap_if->eapSuccess) {		sess->eap_if->eapSuccess = FALSE;		code = RADIUS_CODE_ACCESS_ACCEPT;	} else {		sess->eap_if->eapReq = FALSE;		code = RADIUS_CODE_ACCESS_CHALLENGE;	}	msg = radius_msg_new(code, request->hdr->identifier);	if (msg == NULL) {		RADIUS_DEBUG("Failed to allocate reply message");		return NULL;	}	sess_id = htonl(sess->sess_id);	if (code == RADIUS_CODE_ACCESS_CHALLENGE &&	    !radius_msg_add_attr(msg, RADIUS_ATTR_STATE,				 (u8 *) &sess_id, sizeof(sess_id))) {		RADIUS_DEBUG("Failed to add State attribute");	}	if (sess->eap_if->eapReqData &&	    !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData),				wpabuf_len(sess->eap_if->eapReqData))) {		RADIUS_DEBUG("Failed to add EAP-Message attribute");	}	if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) {		int len;		if (sess->eap_if->eapKeyDataLen > 64) {			len = 32;		} else {			len = sess->eap_if->eapKeyDataLen / 2;		}		if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,					      (u8 *) client->shared_secret,					      client->shared_secret_len,					      sess->eap_if->eapKeyData + len,					      len, sess->eap_if->eapKeyData,					      len)) {			RADIUS_DEBUG("Failed to add MPPE key attributes");		}	}	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");		radius_msg_free(msg);		os_free(msg);		return NULL;	}	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,				  client->shared_secret_len,				  request->hdr->authenticator) < 0) {		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");	}	return msg;}static int radius_server_reject(struct radius_server_data *data,				struct radius_client *client,				struct radius_msg *request,				struct sockaddr *from, socklen_t fromlen,				const char *from_addr, int from_port){	struct radius_msg *msg;	int ret = 0;

⌨️ 快捷键说明

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