📄 mainconfig.c
字号:
/* * mainconf.c Handle the server's configuration. * * Version: $Id: mainconfig.c,v 1.147 2008/03/06 10:28:36 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 2002,2006-2007 The FreeRADIUS server project * Copyright 2002 Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: mainconfig.c,v 1.147 2008/03/06 10:28:36 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/rad_assert.h>#include <sys/stat.h>#ifdef HAVE_SYS_RESOURCE_H#include <sys/resource.h>#endif#ifdef HAVE_PWD_H#include <pwd.h>#endif#ifdef HAVE_GRP_H#include <grp.h>#endif#ifdef HAVE_SYS_PRCTL_H#include <sys/prctl.h>#endif#ifdef HAVE_SYSLOG_H# include <syslog.h>#endifstruct main_config_t mainconfig;/* * Temporary local variables for parsing the configuration * file. */static uid_t server_uid;static gid_t server_gid;static const char *uid_name = NULL;static const char *gid_name = NULL;static int allow_core_dumps = 0;static const char *radlog_dest = NULL;/* * These are not used anywhere else.. */static const char *localstatedir = NULL;static const char *prefix = NULL;static char *syslog_facility = NULL;static const FR_NAME_NUMBER str2fac[] = {#ifdef LOG_KERN { "kern", LOG_KERN },#endif#ifdef LOG_USER { "user", LOG_USER },#endif#ifdef LOG_MAIL { "mail", LOG_MAIL },#endif#ifdef LOG_DAEMON { "daemon", LOG_DAEMON },#endif#ifdef LOG_AUTH { "auth", LOG_AUTH },#endif#ifdef LOG_LPR { "lpr", LOG_LPR },#endif#ifdef LOG_NEWS { "news", LOG_NEWS },#endif#ifdef LOG_UUCP { "uucp", LOG_UUCP },#endif#ifdef LOG_CRON { "cron", LOG_CRON },#endif#ifdef LOG_AUTHPRIV { "authpriv", LOG_AUTHPRIV },#endif#ifdef LOG_FTP { "ftp", LOG_FTP },#endif#ifdef LOG_LOCAL0 { "local0", LOG_LOCAL0 },#endif#ifdef LOG_LOCAL1 { "local1", LOG_LOCAL1 },#endif#ifdef LOG_LOCAL2 { "local2", LOG_LOCAL2 },#endif#ifdef LOG_LOCAL3 { "local3", LOG_LOCAL3 },#endif#ifdef LOG_LOCAL4 { "local4", LOG_LOCAL4 },#endif#ifdef LOG_LOCAL5 { "local5", LOG_LOCAL5 },#endif#ifdef LOG_LOCAL6 { "local6", LOG_LOCAL6 },#endif#ifdef LOG_LOCAL7 { "local7", LOG_LOCAL7 },#endif { NULL, -1 }};/* * Security configuration for the server. */static const 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 }};/* * Logging configuration for the server. */static const CONF_PARSER log_config[] = { { "destination", PW_TYPE_STRING_PTR, 0, &radlog_dest, "files" }, { "syslog_facility", PW_TYPE_STRING_PTR, 0, &syslog_facility, Stringify(0) }, { "stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" }, { "file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" }, { "auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" }, { "auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" }, { "auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" }, { NULL, -1, 0, NULL, NULL }};/* * A mapping of configuration file names to internal variables */static const 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" }, { "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) },#ifdef DELETE_BLOCKED_REQUESTS { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },#endif { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &allow_core_dumps, "no" }, { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"}, { "user", PW_TYPE_STRING_PTR, 0, &uid_name, NULL}, { "group", PW_TYPE_STRING_PTR, 0, &gid_name, NULL}, { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" }, { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"}, { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" }, { "security", PW_TYPE_SUBSECTION, 0, NULL, (const void *) security_config }, { NULL, -1, 0, NULL, NULL }};static const CONF_PARSER serverlog_config[] = { { "log", PW_TYPE_SUBSECTION, 0, NULL, (const void *) log_config}, /* * People with old configs will have these. They are listed * AFTER the "log" section, so if they exist in radiusd.conf, * it will prefer "log_foo = bar" to "log { foo = bar }". * They're listed with default values of NULL, so that if they * DON'T exist in radiusd.conf, then the previously parsed * values for "log { foo = bar}" will be used. */ { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, NULL }, { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, NULL }, { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, NULL }, { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names, NULL }, { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, NULL }, { "log_destination", PW_TYPE_STRING_PTR, -1, &radlog_dest, NULL }, { NULL, -1, 0, NULL, NULL }};#define MAX_ARGV (256)static size_t config_escape_func(char *out, size_t outlen, const char *in){ size_t len = 0; static const char *disallowed = "%{}\\'\"`"; while (in[0]) { /* * Non-printable characters get replaced with their * mime-encoded equivalents. */ if ((in[0] < 32)) { if (outlen <= 3) break; snprintf(out, outlen, "=%02X", (unsigned char) in[0]); in++; out += 3; outlen -= 3; len += 3; continue; } else if (strchr(disallowed, *in) != NULL) { if (outlen <= 2) break; out[0] = '\\'; out[1] = *in; in++; out += 2; outlen -= 2; len += 2; continue; } /* * Only one byte left. */ if (outlen <= 1) { break; } /* * Allowed character. */ *out = *in; out++; in++; outlen--; len++; } *out = '\0'; return len;}/* * Xlat for %{config:section.subsection.attribute} */static size_t xlat_config(void *instance, REQUEST *request, char *fmt, char *out, size_t outlen, RADIUS_ESCAPE_STRING func){ const char *value; CONF_PAIR *cp; CONF_ITEM *ci; char buffer[1024]; request = request; /* -Wunused */ instance = instance; /* -Wunused */ /* * Expand it safely. */ if (!radius_xlat(buffer, sizeof(buffer), fmt, request, config_escape_func)) { return 0; } ci = cf_reference_item(request->root->config, request->root->config, buffer); if (!ci || !cf_item_is_pair(ci)) { *out = '\0'; return 0; } cp = cf_itemtopair(ci); /* * 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);}/* * Xlat for %{client:foo} */static size_t xlat_client(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->client) { *out = '\0'; return 0; } cp = cf_pair_find(request->client->cs, fmt); if (!cp || !(value = cf_pair_value(cp))) { *out = '\0'; return 0; } strlcpy(out, value, outlen); return strlen(out);}/* * 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, FR_DIR_SEP); if (ptr == part) return(0); snprintf(parentdir, (ptr - part)+1, "%s", part); if (r_mkdir(parentdir) != 0) return(1); if (mkdir(part, 0770) != 0) { radlog(L_ERR, "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){#ifdef HAVE_GETPWNAM struct passwd *pwent;#endif if (!radlog_dir || FR_DIR_IS_RELATIVE(radlog_dir)) 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; }#ifdef HAVE_GETPWNAM pwent = getpwnam(effectiveuser);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -