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

📄 rlm_eap2.c

📁 freeradius-server-2.1.3.tar.gz安装源文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * rlm_eap.c  contains handles that are called from modules. * * Version:     $Id$ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2007  Alan DeKok <aland@deployingradius.com> */#include <freeradius-devel/ident.h>RCSID("$Id$")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/rad_assert.h>/* *	Hostap includes. */#include <utils/includes.h>#include <utils/common.h>#include <eap_server/eap.h>#include <crypto/tls.h>struct eap_server_ctx {	struct eap_eapol_interface *eap_if;	struct eap_sm *eap;	void *tls_ctx;};#define EAP_STATE_LEN (AUTH_VECTOR_LEN)typedef struct EAP_HANDLER {	struct EAP_HANDLER *prev, *next;	uint8_t		state[EAP_STATE_LEN];	fr_ipaddr_t	src_ipaddr;	time_t		timestamp;	REQUEST		*request;	struct rlm_eap_t *inst;	struct eapol_callbacks eap_cb;	struct eap_config eap_conf;	struct eap_server_ctx server_ctx;} EAP_HANDLER;typedef struct rlm_eap_t {	rbtree_t	*session_tree;	EAP_HANDLER	*session_head, *session_tail;	/*	 *	Configuration items.	 */	int		timer_limit;	int		cisco_accounting_username_bug;	struct tls_connection_params tparams;	int		num_types;	EapType		methods[EAP_MAX_METHODS];	int		vendors[EAP_MAX_METHODS];#ifdef HAVE_PTHREAD_H	pthread_mutex_t	session_mutex;#endif	fr_randctx	rand_pool;	void *tls_ctx;} rlm_eap_t;static void eap_handler_free(EAP_HANDLER *handler){	eap_server_sm_deinit(handler->server_ctx.eap);	free(handler);}static void eaplist_free(rlm_eap_t *inst){	EAP_HANDLER *node, *next;       	for (node = inst->session_head; node != NULL; node = next) {		next = node->next;		eap_handler_free(node);	}	inst->session_head = inst->session_tail = NULL;}/* *	Return a 32-bit random number. */static uint32_t eap_rand(fr_randctx *ctx){	uint32_t num;	num = ctx->randrsl[ctx->randcnt++];	if (ctx->randcnt == 256) {		ctx->randcnt = 0;		fr_isaac(ctx);	}	return num;}/* *	Add a handler to the set of active sessions. * *	Since we're adding it to the list, we guess that this means *	the packet needs a State attribute.  So add one. */static int eaplist_add(rlm_eap_t *inst, EAP_HANDLER *handler){	int		i, status;	uint32_t	lvalue;	VALUE_PAIR	*state;	rad_assert(handler != NULL);	rad_assert(handler->request != NULL);	/*	 *	Generate State, since we've been asked to add it to	 *	the list.	 */	state = pairmake("State", "0x00", T_OP_EQ);	if (!state) return 0;	pairadd(&(handler->request->reply->vps), state);	state->length = EAP_STATE_LEN;	/*	 *	The time at which this request was made was the time	 *	at which it was received by the RADIUS server.	 */	handler->timestamp = handler->request->timestamp;	handler->src_ipaddr = handler->request->packet->src_ipaddr;	/*	 *	We don't need this any more.	 */	handler->request = NULL;	/*	 *	Playing with a data structure shared among threads	 *	means that we need a lock, to avoid conflict.	 */	pthread_mutex_lock(&(inst->session_mutex));	/*	 *	Create a completely random state.	 */	for (i = 0; i < 4; i++) {		lvalue = eap_rand(&inst->rand_pool);		memcpy(state->vp_octets + i * 4, &lvalue, sizeof(lvalue));	}	memcpy(handler->state, state->vp_strvalue, sizeof(handler->state));	/*	 *	Big-time failure.	 */	status = rbtree_insert(inst->session_tree, handler);	if (status) {		EAP_HANDLER *prev;		prev = inst->session_tail;		if (prev) {			prev->next = handler;			handler->prev = prev;			handler->next = NULL;			inst->session_tail = handler;		} else {			inst->session_head = inst->session_tail = handler;			handler->next = handler->prev = NULL;		}	}	/*	 *	Now that we've finished mucking with the list,	 *	unlock it.	 */	pthread_mutex_unlock(&(inst->session_mutex));	if (!status) {		radlog(L_ERR, "rlm_eap2: Failed to remember handler!");		eap_handler_free(handler);		return 0;	}	return 1;}/* *	Find a a previous EAP-Request sent by us, which matches *	the current EAP-Response. * *	Then, release the handle from the list, and return it to *	the caller. * *	Also since we fill the eap_ds with the present EAP-Response we *	got to free the prev_eapds & move the eap_ds to prev_eapds */static EAP_HANDLER *eaplist_find(rlm_eap_t *inst, REQUEST *request){	int		i;	VALUE_PAIR	*state;	rbnode_t	*node;	EAP_HANDLER	*handler, myHandler;	/*	 *	We key the sessions off of the 'state' attribute, so it	 *	must exist.	 */	state = pairfind(request->packet->vps, PW_STATE);	if (!state ||	    (state->length != EAP_STATE_LEN)) {		return NULL;	}	myHandler.src_ipaddr = request->packet->src_ipaddr;	memcpy(myHandler.state, state->vp_strvalue, sizeof(myHandler.state));	/*	 *	Playing with a data structure shared among threads	 *	means that we need a lock, to avoid conflict.	 */	pthread_mutex_lock(&(inst->session_mutex));	/*	 *	Check the first few handlers in the list, and delete	 *	them if they're too old.  We don't need to check them	 *	all, as incoming requests will quickly cause older	 *	handlers to be deleted.	 *	 */	for (i = 0; i < 2; i++) {		handler = inst->session_head;		if (handler &&		    ((request->timestamp - handler->timestamp) > inst->timer_limit)) {			node = rbtree_find(inst->session_tree, handler);			rad_assert(node != NULL);			rbtree_delete(inst->session_tree, node);			/*			 *	handler == inst->session_head			 */			inst->session_head = handler->next;			if (handler->next) {				handler->next->prev = NULL;			} else {				inst->session_head = NULL;			}			eap_handler_free(handler);		}	}	handler = NULL;	node = rbtree_find(inst->session_tree, &myHandler);	if (node) {		handler = rbtree_node2data(inst->session_tree, node);		/*		 *	Delete old handler from the tree.		 */		rbtree_delete(inst->session_tree, node);				/*		 *	And unsplice it from the linked list.		 */		if (handler->prev) {			handler->prev->next = handler->next;		} else {			inst->session_head = handler->next;		}		if (handler->next) {			handler->next->prev = handler->prev;		} else {			inst->session_tail = handler->prev;		}		handler->prev = handler->next = NULL;	}	pthread_mutex_unlock(&(inst->session_mutex));	/*	 *	Not found.	 */	if (!node) {		RDEBUG2("Request not found in the list");		return NULL;	}	/*	 *	Found, but state verification failed.	 */	if (!handler) {		radlog(L_ERR, "rlm_eap2: State verification failed.");		return NULL;	}	RDEBUG2("Request found, released from the list");	return handler;}/* * delete all the allocated space by eap module */static int eap_detach(void *instance){	rlm_eap_t *inst;	inst = (rlm_eap_t *)instance;	rbtree_free(inst->session_tree);	inst->session_tree = NULL;	eaplist_free(inst);	eap_server_unregister_methods();	tls_deinit(inst->tls_ctx);	pthread_mutex_destroy(&(inst->session_mutex));	free(inst);	return 0;}/* *	Compare two handlers. */static int eap_handler_cmp(const void *a, const void *b){	int rcode;	const EAP_HANDLER *one = a;	const EAP_HANDLER *two = b;	rcode = fr_ipaddr_cmp(&one->src_ipaddr, &two->src_ipaddr);	if (rcode != 0) return rcode;	return memcmp(one->state, two->state, sizeof(one->state));}static int server_get_eap_user(void *ctx, const u8 *identity,			       size_t identity_len, int phase2,			       struct eap_user *user){	int i;	VALUE_PAIR *vp;	EAP_HANDLER *handler = ctx;	REQUEST *request = handler->request;	os_memset(user, 0, sizeof(*user));	/*	 *	FIXME: Run through "authorise" again to look up	 *	password for the given identity	 */	identity = identity;	/* -Wunused */	identity_len = identity_len; /* -Wunused */	/*	 *	Do this always, just in case.	 */	vp = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);	if (vp) {		user->password = (u8 *) os_strdup(vp->vp_strvalue);		user->password_len = vp->length;	}	if (!vp) vp = pairfind(request->config_items, PW_NT_PASSWORD);	if (vp) {		user->password = (u8 *) malloc(vp->length);		memcpy(user->password, vp->vp_octets, vp->length);		user->password_len = vp->length;	}	if (!phase2) {		for (i = 0; i < handler->inst->num_types; i++) {			user->methods[i].vendor = handler->inst->vendors[i];			user->methods[i].method = handler->inst->methods[i];		}		return 0;	}	/*	 *	FIXME: run tunneled sessions through the tunneled portion...	 */	/*	 *	FIXME: Selectively control tunneled EAP types.	 */	user->methods[0].vendor = EAP_VENDOR_IETF;	user->methods[0].method = EAP_TYPE_MD5;	user->methods[1].vendor = EAP_VENDOR_IETF;	user->methods[1].method = EAP_TYPE_MSCHAPV2;	/*	 *	No password configured...	 */       	return 0;}static const char * server_get_eap_req_id_text(void *ctx, size_t *len){	ctx = ctx;		/* -Wunused */	*len = 0;	return NULL;}static CONF_PARSER tls_config[] = {	/*	 *	TLS parameters.	 */	{ "ca_cert", PW_TYPE_STRING_PTR,	  offsetof(rlm_eap_t, tparams.ca_cert),	  NULL, "${confdir}/certs/ca.pem" },	{ "server_cert", PW_TYPE_STRING_PTR,	  offsetof(rlm_eap_t, tparams.client_cert),	  NULL, "${confdir}/certs/server.pem" },	{ "private_key_file", PW_TYPE_STRING_PTR,	  offsetof(rlm_eap_t, tparams.private_key),	  NULL, "${confdir}/certs/server.pem" },	{ "private_key_password", PW_TYPE_STRING_PTR,	  offsetof(rlm_eap_t, tparams.private_key_passwd),	  NULL, "whatever" }, 	{ NULL, -1, 0, NULL, NULL }           /* end the list */};static const CONF_PARSER module_config[] = {	{ "timer_expire", PW_TYPE_INTEGER,	  offsetof(rlm_eap_t, timer_limit), NULL, "60"},	{ "cisco_accounting_username_bug", PW_TYPE_BOOLEAN,	  offsetof(rlm_eap_t, cisco_accounting_username_bug), NULL, "no" },	{ "tls", PW_TYPE_SUBSECTION, 0, NULL, (const void *) tls_config }, 	{ NULL, -1, 0, NULL, NULL }           /* end the list */};static int eap_example_server_init_tls(rlm_eap_t *inst){	struct tls_config tconf;	os_memset(&tconf, 0, sizeof(tconf));	inst->tls_ctx = tls_init(&tconf);	if (inst->tls_ctx == NULL)		return -1;	if (tls_global_set_params(inst->tls_ctx, &inst->tparams)) {		radlog(L_ERR, "rlm_eap2: Failed to set TLS parameters");		return -1;	}	if (tls_global_set_verify(inst->tls_ctx, 0)) {		radlog(L_ERR, "rlm_eap2: Failed to set check_crl");		return -1;	}	return 0;}/* * read the config section and load all the eap authentication types present. */static int eap_instantiate(CONF_SECTION *cs, void **instance){	int i, num_types;	int		has_tls, do_tls;	rlm_eap_t	*inst;

⌨️ 快捷键说明

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