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

📄 realms.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * realms.c	Realm handling code * * Version:     $Id: realms.c,v 1.52 2008/04/18 09:29:49 aland Exp $ * *   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  The FreeRADIUS server project * Copyright 2007  Alan DeKok <aland@deployingradius.com> */#include <freeradius-devel/ident.h>RCSID("$Id: realms.c,v 1.52 2008/04/18 09:29:49 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/rad_assert.h>#include <sys/stat.h>#include <ctype.h>#include <fcntl.h>#ifdef HAVE_REGEX_H#include <regex.h>/* *  For POSIX Regular expressions. *  (0) Means no extended regular expressions. *  REG_EXTENDED means use extended regular expressions. */#ifndef REG_EXTENDED#define REG_EXTENDED (0)#endif#ifndef REG_NOSUB#define REG_NOSUB (0)#endif#ifndef REG_ICASE#define REG_ICASE (0)#endif#endifstatic rbtree_t *realms_byname = NULL;#ifdef HAVE_REGEX_Htypedef struct realm_regex_t {	REALM	*realm;	struct realm_regex_t *next;} realm_regex_t;static realm_regex_t *realms_regex = NULL;#endif /* HAVE_REGEX_H */static rbtree_t	*home_servers_byaddr = NULL;static rbtree_t	*home_servers_byname = NULL;static rbtree_t	*home_pools_byname = NULL;typedef struct realm_config_t {	CONF_SECTION	*cs;	int		dead_time;	int		retry_count;	int		retry_delay;	int		fallback;	int		wake_all_if_all_dead;} realm_config_t;static realm_config_t *realm_config = NULL;/* *  Map the proxy server configuration parameters to variables. */static const CONF_PARSER proxy_config[] = {	{ "retry_delay",  PW_TYPE_INTEGER,	  offsetof(realm_config_t, retry_delay),	  NULL, Stringify(RETRY_DELAY) },	{ "retry_count",  PW_TYPE_INTEGER,	  offsetof(realm_config_t, retry_count),	  NULL, Stringify(RETRY_COUNT) },	{ "default_fallback", PW_TYPE_BOOLEAN,	  offsetof(realm_config_t, fallback),	  NULL, "no" },	{ "dead_time",    PW_TYPE_INTEGER, 	  offsetof(realm_config_t, dead_time),	  NULL, Stringify(DEAD_TIME) },	{ "wake_all_if_all_dead", PW_TYPE_BOOLEAN,	  offsetof(realm_config_t, wake_all_if_all_dead),	  NULL, "no" },	{ NULL, -1, 0, NULL, NULL }};static int realm_name_cmp(const void *one, const void *two){	const REALM *a = one;	const REALM *b = two;	return strcasecmp(a->name, b->name);}static int home_server_name_cmp(const void *one, const void *two){	const home_server *a = one;	const home_server *b = two;	if (a->type < b->type) return -1;	if (a->type > b->type) return +1;	return strcasecmp(a->name, b->name);}static int home_server_addr_cmp(const void *one, const void *two){	const home_server *a = one;	const home_server *b = two;	if (a->server && !b->server) return -1;	if (!a->server && b->server) return +1;	if (a->server && b->server) {		int rcode = a->type - b->type;		if (rcode != 0) return rcode;		return strcmp(a->server, b->server);	}	if (a->port < b->port) return -1;	if (a->port > b->port) return +1;	return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);}static int home_pool_name_cmp(const void *one, const void *two){	const home_pool_t *a = one;	const home_pool_t *b = two;	if (a->server_type < b->server_type) return -1;	if (a->server_type > b->server_type) return +1;	return strcasecmp(a->name, b->name);}/* *	Xlat for %{home_server:foo} */static size_t xlat_home_server(UNUSED void *instance, REQUEST *request,			       char *fmt, char *out, size_t outlen,			       UNUSED RADIUS_ESCAPE_STRING func){	const char *value = NULL;	CONF_PAIR *cp;	if (!fmt || !out || (outlen < 1)) return 0;	if (!request || !request->home_server) {		*out = '\0';		return 0;	}	cp = cf_pair_find(request->home_server->cs, fmt);	if (!cp || !(value = cf_pair_value(cp))) {		*out = '\0';		return 0;	}		strlcpy(out, value, outlen);	return strlen(out);}/* *	Xlat for %{home_server_pool:foo} */static size_t xlat_server_pool(UNUSED void *instance, REQUEST *request,			       char *fmt, char *out, size_t outlen,			       UNUSED RADIUS_ESCAPE_STRING func){	const char *value = NULL;	CONF_PAIR *cp;	if (!fmt || !out || (outlen < 1)) return 0;	if (!request || !request->home_pool) {		*out = '\0';		return 0;	}	cp = cf_pair_find(request->home_pool->cs, fmt);	if (!cp || !(value = cf_pair_value(cp))) {		*out = '\0';		return 0;	}		strlcpy(out, value, outlen);	return strlen(out);}void realms_free(void){	rbtree_free(home_servers_byname);	home_servers_byname = NULL;	rbtree_free(home_servers_byaddr);	home_servers_byaddr = NULL;	rbtree_free(home_pools_byname);	home_pools_byname = NULL;	rbtree_free(realms_byname);	realms_byname = NULL;#ifdef HAVE_REGEX_H	if (realms_regex) {		realm_regex_t *this, *next;		for (this = realms_regex; this != NULL; this = next) {			next = this->next;			free(this->realm);			free(this);		}	}#endif	free(realm_config);}static struct in_addr hs_ip4addr;static struct in6_addr hs_ip6addr;static char *hs_type = NULL;static char *hs_check = NULL;static char *hs_virtual_server = NULL;static CONF_PARSER home_server_config[] = {	{ "ipaddr",  PW_TYPE_IPADDR,	  0, &hs_ip4addr,  NULL },	{ "ipv6addr",  PW_TYPE_IPV6ADDR,	  0, &hs_ip6addr, NULL },	{ "virtual_server",  PW_TYPE_STRING_PTR,	  0, &hs_virtual_server, NULL },	{ "port", PW_TYPE_INTEGER,	  offsetof(home_server,port), NULL,   "0" },	{ "type",  PW_TYPE_STRING_PTR,	  0, &hs_type, NULL },	{ "secret",  PW_TYPE_STRING_PTR,	  offsetof(home_server,secret), NULL,  NULL},	{ "response_window", PW_TYPE_INTEGER,	  offsetof(home_server,response_window), NULL,   "30" },	{ "max_outstanding", PW_TYPE_INTEGER,	  offsetof(home_server,max_outstanding), NULL,   "65536" },	{ "zombie_period", PW_TYPE_INTEGER,	  offsetof(home_server,zombie_period), NULL,   "40" },	{ "status_check", PW_TYPE_STRING_PTR,	  0, &hs_check,   "none" },	{ "ping_check", PW_TYPE_STRING_PTR,	  0, &hs_check,   "none" },	{ "ping_interval", PW_TYPE_INTEGER,	  offsetof(home_server,ping_interval), NULL,   "30" },	{ "check_interval", PW_TYPE_INTEGER,	  offsetof(home_server,ping_interval), NULL,   "30" },	{ "num_answers_to_alive", PW_TYPE_INTEGER,	  offsetof(home_server,num_pings_to_alive), NULL,   "3" },	{ "num_pings_to_alive", PW_TYPE_INTEGER,	  offsetof(home_server,num_pings_to_alive), NULL,   "3" },	{ "revive_interval", PW_TYPE_INTEGER,	  offsetof(home_server,revive_interval), NULL,   "300" },	{ "status_check_timeout", PW_TYPE_INTEGER,	  offsetof(home_server,ping_timeout), NULL,   "4" },	{ "username",  PW_TYPE_STRING_PTR,	  offsetof(home_server,ping_user_name), NULL,  NULL},	{ "password",  PW_TYPE_STRING_PTR,	  offsetof(home_server,ping_user_password), NULL,  NULL},	{ NULL, -1, 0, NULL, NULL }		/* end the list */};static int home_server_add(realm_config_t *rc, CONF_SECTION *cs, int type){	const char *name2;	home_server *home;	int dual = FALSE;	CONF_PAIR *cp;	free(hs_virtual_server); /* used only for printing during parsing */	hs_virtual_server = NULL;	name2 = cf_section_name1(cs);	if (!name2 || (strcasecmp(name2, "home_server") != 0)) {		cf_log_err(cf_sectiontoitem(cs),			   "Section is not a home_server.");		return 0;	}	name2 = cf_section_name2(cs);	if (!name2) {		cf_log_err(cf_sectiontoitem(cs),			   "Home server section is missing a name.");		return 0;	}	home = rad_malloc(sizeof(*home));	memset(home, 0, sizeof(*home));	home->name = name2;	home->cs = cs;	memset(&hs_ip4addr, 0, sizeof(hs_ip4addr));	memset(&hs_ip6addr, 0, sizeof(hs_ip6addr));	cf_section_parse(cs, home, home_server_config);	/*	 *	Figure out which one to use.	 */	if (cf_pair_find(cs, "ipaddr")) {		home->ipaddr.af = AF_INET;		home->ipaddr.ipaddr.ip4addr = hs_ip4addr;	} else if (cf_pair_find(cs, "ipv6addr")) {		home->ipaddr.af = AF_INET6;		home->ipaddr.ipaddr.ip6addr = hs_ip6addr;	} else if ((cp = cf_pair_find(cs, "virtual_server")) != NULL) {		home->ipaddr.af = AF_UNSPEC;		home->server = cf_pair_value(cp);		if (!home->server) {			cf_log_err(cf_sectiontoitem(cs),				   "Invalid value for virtual_server");			goto error;		}		if (!cf_section_sub_find_name2(rc->cs, "server", home->server)) {		  			cf_log_err(cf_sectiontoitem(cs),				   "No such server %s", home->server);			goto error;		}		free(hs_type);		hs_type = NULL;		home->secret = strdup("");		goto skip_port;	} else {		cf_log_err(cf_sectiontoitem(cs),			   "No ipaddr, ipv6addr, or virtual_server defined for home server \"%s\".",			   name2);	error:		free(home);		free(hs_type);		hs_type = NULL;		free(hs_check);		hs_check = NULL;		return 0;	}	if (!home->port || (home->port > 65535)) {		cf_log_err(cf_sectiontoitem(cs),			   "No port, or invalid port defined for home server %s.",			   name2);		goto error;	}	if (0) {		cf_log_err(cf_sectiontoitem(cs),			   "Fatal error!  Home server %s is ourselves!",			   name2);		goto error;	}	if (!home->secret) {		cf_log_err(cf_sectiontoitem(cs),			   "No shared secret defined for home server %s.",			   name2);		free(home);		return 0;	}	/*	 *	Use a reasonable default.	 */ skip_port:	if (!hs_type) hs_type = strdup("auth+acct");	if (strcasecmp(hs_type, "auth") == 0) {		home->type = HOME_TYPE_AUTH;		if (type != home->type) {			cf_log_err(cf_sectiontoitem(cs),				   "Server pool of \"acct\" servers cannot include home server %s of type \"auth\"",				   name2);			free(home);			return 0;		}	} else if (strcasecmp(hs_type, "acct") == 0) {		home->type = HOME_TYPE_ACCT;		if (type != home->type) {			cf_log_err(cf_sectiontoitem(cs),				   "Server pool of \"auth\" servers cannot include home server %s of type \"acct\"",				   name2);			free(home);			return 0;		}	} else if (strcasecmp(hs_type, "auth+acct") == 0) {		home->type = HOME_TYPE_AUTH;		dual = TRUE;	} else {		cf_log_err(cf_sectiontoitem(cs),			   "Invalid type \"%s\" for home server %s.",			   hs_type, name2);		free(home);		free(hs_type);		hs_type = NULL;		free(hs_check);		hs_check = NULL;		return 0;	}	free(hs_type);	hs_type = NULL;	if (!hs_check || (strcasecmp(hs_check, "none") == 0)) {		home->ping_check = HOME_PING_CHECK_NONE;	} else if (strcasecmp(hs_check, "status-server") == 0) {		home->ping_check = HOME_PING_CHECK_STATUS_SERVER;	} else if (strcasecmp(hs_check, "request") == 0) {		home->ping_check = HOME_PING_CHECK_REQUEST;	} else {		cf_log_err(cf_sectiontoitem(cs),			   "Invalid ping_check \"%s\" for home server %s.",			   hs_check, name2);		free(home);		free(hs_check);		hs_check = NULL;		return 0;	}	free(hs_check);	hs_check = NULL;	if ((home->ping_check != HOME_PING_CHECK_NONE) &&	    (home->ping_check != HOME_PING_CHECK_STATUS_SERVER)) {		if (!home->ping_user_name) {			cf_log_err(cf_sectiontoitem(cs), "You must supply a user name to enable ping checks");			free(home);			return 0;		}		if ((home->type == HOME_TYPE_AUTH) &&		    !home->ping_user_password) {			cf_log_err(cf_sectiontoitem(cs), "You must supply a password to enable ping checks");			free(home);			return 0;		}	}	if (rbtree_finddata(home_servers_byaddr, home)) {		DEBUG2("Ignoring duplicate home server %s.", name2);		return 1;	}	if (!rbtree_insert(home_servers_byname, home)) {		cf_log_err(cf_sectiontoitem(cs),			   "Internal error adding home server %s.",			   name2);		free(home);		return 0;	}	if (!rbtree_insert(home_servers_byaddr, home)) {		rbtree_deletebydata(home_servers_byname, home);		cf_log_err(cf_sectiontoitem(cs),			   "Internal error adding home server %s.",			   name2);		free(home);		return 0;	}	if (home->response_window < 5) home->response_window = 5;	if (home->response_window > 60) home->response_window = 60;	if (home->max_outstanding < 8) home->max_outstanding = 8;	if (home->max_outstanding > 65536*16) home->max_outstanding = 65536*16;	if (home->ping_interval < 6) home->ping_interval = 6;	if (home->ping_interval > 120) home->ping_interval = 120;	if (home->zombie_period < 20) home->zombie_period = 20;	if (home->zombie_period > 120) home->zombie_period = 120;	if (home->zombie_period < home->response_window) {		home->zombie_period = home->response_window;	}	if (home->num_pings_to_alive < 3) home->num_pings_to_alive = 3;	if (home->num_pings_to_alive > 10) home->num_pings_to_alive = 10;	if (home->ping_timeout < 3) home->ping_timeout = 3;	if (home->ping_timeout > 10) home->ping_timeout = 10;	if (home->revive_interval < 60) home->revive_interval = 60;	if (home->revive_interval > 3600) home->revive_interval = 3600;	if (dual) {		home_server *home2 = rad_malloc(sizeof(*home2));		memcpy(home2, home, sizeof(*home2));		home2->type = HOME_TYPE_ACCT;		home2->port++;		home2->ping_user_password = NULL;		home2->cs = cs;		if (!rbtree_insert(home_servers_byname, home2)) {			cf_log_err(cf_sectiontoitem(cs),				   "Internal error adding home server %s.",				   name2);			free(home2);			return 0;		}				if (!rbtree_insert(home_servers_byaddr, home2)) {			rbtree_deletebydata(home_servers_byname, home2);			cf_log_err(cf_sectiontoitem(cs),				   "Internal error adding home server %s.",				   name2);			free(home2);			return 0;		}	}	return 1;}static home_pool_t *server_pool_alloc(const char *name, home_pool_type_t type,				      int server_type, int num_home_servers){	home_pool_t *pool;	pool = rad_malloc(sizeof(*pool) + (sizeof(pool->servers[0]) *					   num_home_servers));	if (!pool) return NULL;	/* just for pairanoia */		memset(pool, 0, sizeof(*pool) + (sizeof(pool->servers[0]) *					 num_home_servers));	pool->name = name;	pool->type = type;	pool->server_type = server_type;	pool->num_home_servers = num_home_servers;	return pool;}static int pool_check_home_server(realm_config_t *rc, CONF_PAIR *cp,				  const char *name, int server_type,

⌨️ 快捷键说明

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