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

📄 mainconfig.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * mainconf.c	Handle the server's configuration. * * Version:	$Id: mainconfig.c,v 1.36.2.3 2004/09/30 14:49:55 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2002  The FreeRADIUS server project * Copyright 2002  Alan DeKok <aland@ox.org> */#include "autoconf.h"#include "libradius.h"#include <stdlib.h>#include <string.h>#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#include "radiusd.h"#include "rad_assert.h"#include "conffile.h"#include "token.h"#include <sys/resource.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <sys/stat.h>#include <grp.h>#include <pwd.h>#ifdef WITH_UDPFROMTO#include "udpfromto.h"#endifstruct main_config_t mainconfig;/* *  Local variables for stuff. */static uid_t server_uid;static gid_t server_gid;/* *	These are not used anywhere else.. */static const char *localstatedir = NULL;static const char *prefix = NULL;static int auth_port = 0;/* *  Map the proxy server configuration parameters to variables. */static CONF_PARSER proxy_config[] = {	{ "retry_delay",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },	{ "retry_count",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },	{ "synchronous",  PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_synchronous, "no" },	{ "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },	{ "dead_time",    PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },        { "post_proxy_authorize", PW_TYPE_BOOLEAN, 0, &mainconfig.post_proxy_authorize, "yes" },	{ "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },	{ NULL, -1, 0, NULL, NULL }};/* *  Security configuration for the server. */static CONF_PARSER security_config[] = {	{ "max_attributes",  PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },	{ "reject_delay",  PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },	{ "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},	{ NULL, -1, 0, NULL, NULL }};/* *  A mapping of configuration file names to internal variables */static CONF_PARSER server_config[] = {	/*	 *	FIXME: 'prefix' is the ONLY one which should be	 *	configured at compile time.  Hard-coding it here is	 *	bad.  It will be cleaned up once we clean up the	 *	hard-coded defines for the locations of the various	 *	files.	 */	{ "prefix",             PW_TYPE_STRING_PTR, 0, &prefix,            "/usr/local"},	{ "localstatedir",      PW_TYPE_STRING_PTR, 0, &localstatedir,     "${prefix}/var"},	{ "logdir",             PW_TYPE_STRING_PTR, 0, &radlog_dir,        "${localstatedir}/log"},	{ "libdir",             PW_TYPE_STRING_PTR, 0, &radlib_dir,        "${prefix}/lib"},	{ "radacctdir",         PW_TYPE_STRING_PTR, 0, &radacct_dir,       "${logdir}/radacct" },	{ "hostname_lookups",   PW_TYPE_BOOLEAN,    0, &librad_dodns,      "no" },#ifdef WITH_SNMP	{ "snmp",   		PW_TYPE_BOOLEAN,    0, &mainconfig.do_snmp,      "no" },#endif	{ "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },	{ "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },	{ "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },	{ "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },	{ "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },	{ "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },	{ "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },	{ "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },	{ "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },	{ "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },	{ "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },	{ "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},	{ "bind_address", PW_TYPE_IPADDR, 0, &mainconfig.myip, "*" },	{ "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},	{ "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},	{ "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide,  "no" },	{ "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },	{ "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },	{ "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },	{ "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },	{ "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },	{ "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },	{ "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },	{ "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },	{ "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},	{ NULL, -1, 0, NULL, NULL }};/* *	Xlat for %{config:section.subsection.attribute} */static int xlat_config(void *instance, REQUEST *request,		       char *fmt, char *out,		       size_t outlen,		       RADIUS_ESCAPE_STRING func){	CONF_SECTION *cs;	CONF_PAIR *cp;	char buffer[1024];	char *p, *value;	const char *start = fmt;	request = request;	/* -Wunused */	instance = instance;	/* -Wunused */	cp = NULL;	cs = NULL;	while (cp == NULL) {		/*		 *	Find the next section.		 */		for (p = buffer; (*fmt != 0) && (*fmt != '.'); p++, fmt++) {			*p = *fmt;		}		*p = '\0';		/*		 *  The character is a '.', find a section (as the user		 *  has given us a subsection to find)		 */		if (*fmt == '.') {			CONF_SECTION *next;			fmt++;	/* skip the period */			if (cs == NULL) {			  next = cf_section_find(buffer);			} else {			  next = cf_subsection_find_next(cs, NULL, buffer);			}			if (next == NULL) {				radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);				return 0;			}			cs = next;		} else {	/* no period, must be a conf-part */			cp = cf_pair_find(cs, buffer);			if (cp == NULL) {				radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);				return 0;			}		}	} /* until cp is non-NULL */	/*	 *  Ensure that we only copy what's necessary.	 *	 *  If 'outlen' is too small, then the output is chopped to fit.	 */	value = cf_pair_value(cp);	if (value) {		if (outlen > strlen(value)) {			outlen = strlen(value) + 1;		}	}	return func(out, outlen, value);}/* *	Recursively make directories. */static int r_mkdir(const char *part){	char *ptr, parentdir[500];	struct stat st;	if (stat(part, &st) == 0)		return(0);	ptr = strrchr(part, '/');	if (ptr == part)		return(0);	snprintf(parentdir, (ptr - part)+1, "%s", part);	if (r_mkdir(parentdir) != 0)		return(1);	if (mkdir(part, 0770) != 0) {		fprintf(stderr, "mkdir(%s) error: %s\n", part, strerror(errno));		return(1);	}	return(0);}/* *	Checks if the log directory is writeable by a particular user. */static int radlogdir_iswritable(const char *effectiveuser){	struct passwd *pwent;	if (radlog_dir[0] != '/')		return(0);	if (r_mkdir(radlog_dir) != 0)		return(1);	/* FIXME: do we have this function? */	if (strstr(radlog_dir, "radius") == NULL)		return(0);	/* we have a logdir that mentions 'radius', so it's probably	 * safe to chown the immediate directory to be owned by the normal	 * process owner. we gotta do it before we give up root.  -chad	 */	if (!effectiveuser) {		return 1;	}	pwent = getpwnam(effectiveuser);	if (pwent == NULL) /* uh oh! */		return(1);	if (chown(radlog_dir, pwent->pw_uid, -1) != 0)		return(1);	return(0);}/* *  Switch UID and GID to what is specified in the config file */static int switch_users(void){	/*  Set GID.  */	if (mainconfig.gid_name != NULL) {		struct group *gr;		gr = getgrnam(mainconfig.gid_name);		if (gr == NULL) {			if (errno == ENOMEM) {				radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);			} else {				radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);			}			exit(1);		}		server_gid = gr->gr_gid;		if (setgid(server_gid) < 0) {			radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",			       mainconfig.gid_name, strerror(errno));			exit(1);		}	} else {		server_gid = getgid();	}	/*  Set UID.  */	if (mainconfig.uid_name != NULL) {		struct passwd *pw;		pw = getpwnam(mainconfig.uid_name);		if (pw == NULL) {			if (errno == ENOMEM) {				radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);			} else {				radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);			}			exit(1);		}		server_uid = pw->pw_uid;#ifdef HAVE_INITGROUPS		if (initgroups(mainconfig.uid_name, server_gid) < 0) {			if (errno != EPERM) {				radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));				exit(1);			}		}#endif		if (setuid(server_uid) < 0) {			radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));			exit(1);		}	}	return(0);}/* * Create the linked list of realms from the new configuration type * This way we don't have to change to much in the other source-files */static int generate_realms(const char *filename){	CONF_SECTION *cs;	REALM *my_realms = NULL;	REALM *c, **tail;	char *s, *t, *authhost, *accthost;	char *name2;	tail = &my_realms;	for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");	     cs != NULL;	     cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {		name2 = cf_section_name2(cs);		if (!name2) {			radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",			       filename, cf_section_lineno(cs));			return -1;		}		/*		 * We've found a realm, allocate space for it		 */		c = rad_malloc(sizeof(REALM));		memset(c, 0, sizeof(REALM));		c->secret[0] = '\0';		/*		 *	No authhost means LOCAL.		 */		if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {			c->ipaddr = htonl(INADDR_NONE);			c->auth_port = auth_port;		} else {			if ((s = strchr(authhost, ':')) != NULL) {				*s++ = 0;				c->auth_port = atoi(s);			} else {				c->auth_port = auth_port;			}			if (strcmp(authhost, "LOCAL") == 0) {				/*				 *	Local realms don't have an IP address,				 *	secret, or port.				 */				c->ipaddr = htonl(INADDR_NONE);				c->auth_port = auth_port;			} else {				c->ipaddr = ip_getaddr(authhost);				if (c->ipaddr == htonl(INADDR_NONE)) {					radlog(L_ERR, "%s[%d]: Host %s not found",					       filename, cf_section_lineno(cs),					       authhost);					return -1;				}			}			/*			 * Double check length, just to be sure!			 */			if (strlen(authhost) >= sizeof(c->server)) {				radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",				       filename, cf_section_lineno(cs),				       (int) strlen(authhost),				       (int) sizeof(c->server) - 1);				return -1;			}		}		/*		 *	No accthost means LOCAL		 */		if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {			c->acct_ipaddr = htonl(INADDR_NONE);			c->acct_port = 0;		} else {			if ((s = strchr(accthost, ':')) != NULL) {				*s++ = 0;				c->acct_port = atoi(s);			} else {				c->acct_port = auth_port + 1;			}			if (strcmp(accthost, "LOCAL") == 0) {				/*				 *	Local realms don't have an IP address,				 *	secret, or port.				 */				c->acct_ipaddr = htonl(INADDR_NONE);				c->acct_port = 0;			} else {				c->acct_ipaddr = ip_getaddr(accthost);				if (c->acct_ipaddr == htonl(INADDR_NONE)) {					radlog(L_ERR, "%s[%d]: Host %s not found",					       filename, cf_section_lineno(cs),					       accthost);					return -1;				}			}			if (strlen(accthost) >= sizeof(c->acct_server)) {				radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",				       filename, cf_section_lineno(cs),				       (int) strlen(accthost),				       (int) sizeof(c->acct_server) - 1);				return -1;			}		}		if (strlen(name2) >= sizeof(c->realm)) {			radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",			       filename, cf_section_lineno(cs),			       (int) strlen(name2),			       (int) sizeof(c->server) - 1);

⌨️ 快捷键说明

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