2 * mainconf.c Handle the server's configuration.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2002 The FreeRADIUS server project
21 * Copyright 2002 Alan DeKok <aland@ox.org>
29 #ifdef HAVE_NETINET_IN_H
30 #include <netinet/in.h>
33 #ifdef HAVE_ARPA_INET_H
34 #include <arpa/inet.h>
38 #include "rad_assert.h"
42 #include <sys/resource.h>
44 #include <sys/types.h>
45 #include <sys/socket.h>
56 struct main_config_t mainconfig;
59 * Temporary local variables for parsing the configuration
62 static uid_t server_uid;
63 static gid_t server_gid;
66 * These are not used anywhere else..
68 static const char *localstatedir = NULL;
69 static const char *prefix = NULL;
70 static char *syslog_facility = NULL;
71 static const LRAD_NAME_NUMBER str2fac[] = {
82 { "daemon", LOG_DAEMON },
100 { "authpriv", LOG_AUTHPRIV },
106 { "local0", LOG_LOCAL0 },
109 { "local1", LOG_LOCAL1 },
112 { "local2", LOG_LOCAL2 },
115 { "local3", LOG_LOCAL3 },
118 { "local4", LOG_LOCAL4 },
121 { "local5", LOG_LOCAL5 },
124 { "local6", LOG_LOCAL6 },
127 { "local7", LOG_LOCAL7 },
133 * Map the proxy server configuration parameters to variables.
135 static const CONF_PARSER proxy_config[] = {
136 { "retry_delay", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
137 { "retry_count", PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
138 { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
139 { "dead_time", PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
140 { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
141 { "proxy_fail_type", PW_TYPE_STRING_PTR, 0, &mainconfig.proxy_fail_type, NULL},
142 { NULL, -1, 0, NULL, NULL }
147 * Security configuration for the server.
149 static const CONF_PARSER security_config[] = {
150 { "max_attributes", PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
151 { "reject_delay", PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
152 { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
153 { NULL, -1, 0, NULL, NULL }
158 * syslog configuration for the server.
160 static const CONF_PARSER log_config[] = {
161 { "syslog_facility", PW_TYPE_STRING_PTR, 0, &syslog_facility, Stringify(0) },
162 { NULL, -1, 0, NULL, NULL }
167 * A mapping of configuration file names to internal variables
169 static const CONF_PARSER server_config[] = {
171 * FIXME: 'prefix' is the ONLY one which should be
172 * configured at compile time. Hard-coding it here is
173 * bad. It will be cleaned up once we clean up the
174 * hard-coded defines for the locations of the various
177 { "prefix", PW_TYPE_STRING_PTR, 0, &prefix, "/usr/local"},
178 { "localstatedir", PW_TYPE_STRING_PTR, 0, &localstatedir, "${prefix}/var"},
179 { "logdir", PW_TYPE_STRING_PTR, 0, &radlog_dir, "${localstatedir}/log"},
180 { "libdir", PW_TYPE_STRING_PTR, 0, &radlib_dir, "${prefix}/lib"},
181 { "radacctdir", PW_TYPE_STRING_PTR, 0, &radacct_dir, "${logdir}/radacct" },
182 { "hostname_lookups", PW_TYPE_BOOLEAN, 0, &librad_dodns, "no" },
184 { "snmp", PW_TYPE_BOOLEAN, 0, &mainconfig.do_snmp, "no" },
186 { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
187 { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
188 { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
189 { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
190 { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
191 { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
193 { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
194 { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
195 { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
196 { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
197 { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
198 { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
199 { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
200 { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
202 { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
204 { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
205 { "log", PW_TYPE_SUBSECTION, 0, log_config, NULL },
206 { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
207 { "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },
208 { NULL, -1, 0, NULL, NULL }
212 #define MAX_ARGV (256)
214 * Xlat for %{config:section.subsection.attribute}
216 static int xlat_config(void *instance, REQUEST *request,
217 char *fmt, char *out,
219 RADIUS_ESCAPE_STRING func)
224 const char *from, *value;
228 char *argv[MAX_ARGV];
230 request = request; /* -Wunused */
231 instance = instance; /* -Wunused */
237 * Split the string into argv's BEFORE doing radius_xlat...
250 if (argc >= (MAX_ARGV - 1)) break;
253 * Copy the argv over to our buffer.
256 if (to >= myfmt + sizeof(myfmt) - 1) {
257 return 0; /* no error msg */
262 if (from[1] == '{') {
265 length = rad_copy_variable(to, from);
271 } else { /* FIXME: catch %%{ ? */
278 radlog(L_ERR, "config: Unexpected nested '[' in \"%s\"", fmt);
287 radlog(L_ERR, "config: Unbalanced ']' in \"%s\"", fmt);
290 if (from[1] != '.') {
291 radlog(L_ERR, "config: Unexpected text after ']' in \"%s\"", fmt);
300 if (flag == 0) break;
308 if ((*from == '.') && (flag == 0)) {
312 } /* end of string, or found a period */
315 radlog(L_ERR, "config: Unbalanced '[' in \"%s\"", fmt);
319 *(to++) = '\0'; /* terminate the string. */
323 * Expand each string, as appropriate
326 left = sizeof(argv_buf);
327 for (i = 0; i < argc; i++) {
331 * Don't touch argv's which won't be translated.
333 if (strchr(argv[i], '%') == NULL) continue;
335 sublen = radius_xlat(to, left - 1, argv[i], request, NULL);
338 * Fail to be backwards compatible.
340 * It's yucky, but it won't break anything,
341 * and it won't cause security problems.
358 cs = cf_section_find(NULL); /* get top-level section */
361 * Root through section & subsection references.
362 * The last entry of argv MUST be the CONF_PAIR.
364 for (i = 0; i < argc - 1; i++) {
369 * FIXME: What about RADIUS attributes containing '['?
371 name2 = strchr(argv[i], '[');
373 char *p = strchr(name2, ']');
374 rad_assert(p != NULL);
375 rad_assert(p[1] =='\0');
382 subcs = cf_section_sub_find_name2(cs, argv[i],
385 radlog(L_ERR, "config: section \"%s %s {}\" not found while dereferencing \"%s\"", argv[i], name2, fmt);
389 subcs = cf_section_sub_find(cs, argv[i]);
391 radlog(L_ERR, "config: section \"%s {}\" not found while dereferencing \"%s\"", argv[i], fmt);
396 } /* until argc - 1 */
399 * This can now have embedded periods in it.
401 cp = cf_pair_find(cs, argv[argc - 1]);
403 radlog(L_ERR, "config: item \"%s\" not found while dereferencing \"%s\"", argv[argc], fmt);
408 * Ensure that we only copy what's necessary.
410 * If 'outlen' is too small, then the output is chopped to fit.
412 value = cf_pair_value(cp);
414 if (outlen > strlen(value)) {
415 outlen = strlen(value) + 1;
419 return func(out, outlen, value);
424 * Recursively make directories.
426 static int r_mkdir(const char *part)
428 char *ptr, parentdir[500];
431 if (stat(part, &st) == 0)
434 ptr = strrchr(part, '/');
439 snprintf(parentdir, (ptr - part)+1, "%s", part);
441 if (r_mkdir(parentdir) != 0)
444 if (mkdir(part, 0770) != 0) {
445 radlog(L_ERR, "mkdir(%s) error: %s\n", part, strerror(errno));
453 * Checks if the log directory is writeable by a particular user.
455 static int radlogdir_iswritable(const char *effectiveuser)
457 struct passwd *pwent;
459 if (radlog_dir[0] != '/')
462 if (r_mkdir(radlog_dir) != 0)
465 /* FIXME: do we have this function? */
466 if (strstr(radlog_dir, "radius") == NULL)
469 /* we have a logdir that mentions 'radius', so it's probably
470 * safe to chown the immediate directory to be owned by the normal
471 * process owner. we gotta do it before we give up root. -chad
474 if (!effectiveuser) {
478 pwent = getpwnam(effectiveuser);
480 if (pwent == NULL) /* uh oh! */
483 if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
491 * Switch UID and GID to what is specified in the config file
493 static int switch_users(void)
496 if (mainconfig.gid_name != NULL) {
499 gr = getgrnam(mainconfig.gid_name);
501 if (errno == ENOMEM) {
502 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
504 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
508 server_gid = gr->gr_gid;
509 if (setgid(server_gid) < 0) {
510 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
511 mainconfig.gid_name, strerror(errno));
515 server_gid = getgid();
519 if (mainconfig.uid_name != NULL) {
522 pw = getpwnam(mainconfig.uid_name);
524 if (errno == ENOMEM) {
525 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
527 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
531 server_uid = pw->pw_uid;
532 #ifdef HAVE_INITGROUPS
533 if (initgroups(mainconfig.uid_name, server_gid) < 0) {
534 if (errno != EPERM) {
535 radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));
540 if (setuid(server_uid) < 0) {
541 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
547 * We've probably written to the log file already as
548 * root.root, so if we have switched users, we've got to
549 * update the ownership of the file.
551 if ((debug_flag == 0) &&
552 (mainconfig.radlog_dest == RADLOG_FILES) &&
553 (mainconfig.log_file != NULL)) {
554 chown(mainconfig.log_file, server_uid, server_gid);
561 * Create the linked list of realms from the new configuration type
562 * This way we don't have to change to much in the other source-files
564 static int generate_realms(const char *filename)
567 REALM *my_realms = NULL;
569 char *s, *t, *authhost, *accthost;
573 for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
575 cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
576 name2 = cf_section_name2(cs);
578 radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
579 filename, cf_section_lineno(cs));
583 * We've found a realm, allocate space for it
585 c = rad_malloc(sizeof(REALM));
586 memset(c, 0, sizeof(REALM));
591 * No authhost means LOCAL.
593 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
594 c->ipaddr.af = AF_INET;
595 c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
598 if ((s = strchr(authhost, ':')) != NULL) {
600 c->auth_port = atoi(s);
602 c->auth_port = PW_AUTH_UDP_PORT;
604 if (strcmp(authhost, "LOCAL") == 0) {
606 * Local realms don't have an IP address,
609 c->ipaddr.af = AF_INET;
610 c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
613 if (ip_hton(authhost, AF_INET,
615 radlog(L_ERR, "%s[%d]: Host %s not found",
616 filename, cf_section_lineno(cs),
623 * Double check length, just to be sure!
625 if (strlen(authhost) >= sizeof(c->server)) {
626 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
627 filename, cf_section_lineno(cs),
628 (int) strlen(authhost),
629 (int) sizeof(c->server) - 1);
635 * No accthost means LOCAL
637 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
638 c->acct_ipaddr.af = AF_INET;
639 c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
642 if ((s = strchr(accthost, ':')) != NULL) {
644 c->acct_port = atoi(s);
646 c->acct_port = PW_ACCT_UDP_PORT;
648 if (strcmp(accthost, "LOCAL") == 0) {
650 * Local realms don't have an IP address,
653 c->acct_ipaddr.af = AF_INET;
654 c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
657 if (ip_hton(accthost, AF_INET,
658 &c->acct_ipaddr) < 0) {
659 radlog(L_ERR, "%s[%d]: Host %s not found",
660 filename, cf_section_lineno(cs),
666 if (strlen(accthost) >= sizeof(c->acct_server)) {
667 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
668 filename, cf_section_lineno(cs),
669 (int) strlen(accthost),
670 (int) sizeof(c->acct_server) - 1);
675 if (strlen(name2) >= sizeof(c->realm)) {
676 radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
677 filename, cf_section_lineno(cs),
679 (int) sizeof(c->server) - 1);
683 strcpy(c->realm, name2);
684 if (authhost) strcpy(c->server, authhost);
685 if (accthost) strcpy(c->acct_server, accthost);
688 * If one or the other of authentication/accounting
689 * servers is set to LOCALHOST, then don't require
692 rad_assert(c->ipaddr.af == AF_INET);
693 rad_assert(c->acct_ipaddr.af == AF_INET);
694 if ((c->ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE)) ||
695 (c->acct_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE))) {
696 if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
697 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
698 filename, cf_section_lineno(cs), name2);
702 if (strlen(s) >= sizeof(c->secret)) {
703 radlog(L_ERR, "%s[%d]: Secret of length %d is greater than the allowed maximum of %d.",
704 filename, cf_section_lineno(cs),
705 strlen(s), sizeof(c->secret) - 1);
708 strNcpy((char *)c->secret, s, sizeof(c->secret));
713 if ((cf_section_value_find(cs, "nostrip")) != NULL)
715 if ((cf_section_value_find(cs, "noacct")) != NULL)
717 if ((cf_section_value_find(cs, "trusted")) != NULL)
719 if ((cf_section_value_find(cs, "notrealm")) != NULL)
721 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
723 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
724 static const LRAD_NAME_NUMBER ldflags[] = {
726 { "round_robin", 1 },
730 c->ldflag = lrad_str2int(ldflags, t, -1);
731 if (c->ldflag == -1) {
732 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
733 filename, cf_section_lineno(cs),
739 c->ldflag = 0; /* non, make it fail-over */
742 c->acct_active = TRUE;
750 * And make these realms preferred over the ones
751 * in the 'realms' file.
753 *tail = mainconfig.realms;
754 mainconfig.realms = my_realms;
757 * Ensure that all of the flags agree for the realms.
759 * Yeah, it's O(N^2), but it's only once, and the
760 * maximum number of realms is small.
762 for(c = mainconfig.realms; c != NULL; c = c->next) {
766 * Check that we cannot load balance to LOCAL
767 * realms, as that doesn't make any sense.
769 rad_assert(c->ipaddr.af == AF_INET);
770 rad_assert(c->acct_ipaddr.af == AF_INET);
771 if ((c->ldflag == 1) &&
772 ((c->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) ||
773 (c->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)))) {
774 radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
780 * Compare this realm to all others, to ensure
781 * that the configuration is consistent.
783 for (this = c->next; this != NULL; this = this->next) {
784 if (strcasecmp(c->realm, this->realm) != 0) {
789 * Same realm: Different load balancing
792 if (c->ldflag != this->ldflag) {
793 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
804 static const LRAD_NAME_NUMBER str2dest[] = {
805 { "files", RADLOG_FILES },
806 { "syslog", RADLOG_SYSLOG },
807 { "stdout", RADLOG_STDOUT },
808 { "stderr", RADLOG_STDERR },
809 { NULL, RADLOG_NULL }
816 * This function can ONLY be called from the main server process.
818 int read_mainconfig(int reload)
820 struct rlimit core_limits;
821 static int old_debug_level = -1;
823 CONF_SECTION *cs, *oldcs, *newcs;
824 rad_listen_t *listener;
827 radlog(L_INFO, "Starting - reading configuration files ...");
829 radlog(L_INFO, "Reloading configuration files.");
832 /* Initialize the dictionary */
833 DEBUG2("read_config_files: reading dictionary");
834 if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
835 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
837 cf_section_free(&cs);
841 /* Read the configuration file */
842 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
843 radius_dir, mainconfig.radiusd_conf);
844 if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
845 radlog(L_ERR|L_CONS, "Errors reading %s", buffer);
850 * This allows us to figure out where, relative to
851 * radiusd.conf, the other configuration files exist.
853 cf_section_parse(cs, NULL, server_config);
857 * Merge the old with the new.
860 newcs = cf_section_sub_find(cs, "modules");
861 oldcs = cf_section_sub_find(mainconfig.config, "modules");
862 if (newcs && oldcs) {
863 if (!cf_section_migrate(newcs, oldcs)) {
864 radlog(L_ERR|L_CONS, "Fatal error migrating configuration data");
872 * Debug flag 1 MAY go to files.
873 * Debug flag 2 ALWAYS goes to stdout
875 if (debug_flag < 2) {
877 char *radlog_dest = NULL;
879 rcode = cf_item_parse(cs, "log_destination",
880 PW_TYPE_STRING_PTR, &radlog_dest,
882 if (rcode < 0) return NULL;
884 mainconfig.radlog_dest = lrad_str2int(str2dest, radlog_dest, RADLOG_NULL);
885 if (mainconfig.radlog_dest == RADLOG_NULL) {
886 fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
888 cf_section_free(&cs);
892 if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
893 mainconfig.syslog_facility = lrad_str2int(str2fac, syslog_facility, -1);
894 if (mainconfig.syslog_facility < 0) {
895 fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
897 cf_section_free(&cs);
904 * Free the old configuration items, and replace them
907 * Note that where possible, we do atomic switch-overs,
908 * to ensure that the pointers are always valid.
910 oldcs = mainconfig.config;
911 mainconfig.config = cs;
912 cf_section_free(&oldcs);
915 * Old-style realms file.
917 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
918 DEBUG2("read_config_files: reading realms");
919 if (read_realms_file(buffer) < 0) {
920 radlog(L_ERR|L_CONS, "Errors reading realms");
925 * If there isn't any realms it isn't fatal..
927 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
928 radius_dir, mainconfig.radiusd_conf);
929 if (generate_realms(buffer) < 0) {
934 * Register the %{config:section.subsection} xlat function.
936 xlat_register("config", xlat_config, NULL);
939 * Set the libraries debugging flag to whatever the main
940 * flag is. Note that on a SIGHUP, to turn the debugging
941 * off, we do other magic.
943 * Increase the debug level, if the configuration file
944 * says to, OR, if we're decreasing the debug from what it
945 * was before, allow that, too.
947 if ((mainconfig.debug_level > debug_flag) ||
948 (mainconfig.debug_level <= old_debug_level)) {
949 debug_flag = mainconfig.debug_level;
951 librad_debug = debug_flag;
952 old_debug_level = mainconfig.debug_level;
955 * Go update our behaviour, based on the configuration
959 /* Get the current maximum for core files. */
960 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
961 radlog(L_ERR|L_CONS, "Failed to get current core limit: %s", strerror(errno));
965 if (mainconfig.allow_core_dumps) {
966 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
967 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
972 * If we're running as a daemon, and core
973 * dumps are enabled, log that information.
975 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
976 radlog(L_INFO|L_CONS, "Core dumps are enabled.");
978 } else if (!debug_flag) {
980 * Not debugging. Set the core size to zero, to
981 * prevent security breaches. i.e. People
982 * reading passwords from the 'core' file.
984 struct rlimit limits;
987 limits.rlim_max = core_limits.rlim_max;
989 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
990 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
997 * The first time around, ensure that we can write to the
1002 * We need root to do mkdir() and chown(), so we
1003 * do this before giving up root.
1005 radlogdir_iswritable(mainconfig.uid_name);
1009 * We should really switch users earlier in the process.
1014 * Sanity check the configuration for internal
1017 if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1018 mainconfig.reject_delay = mainconfig.cleanup_delay;
1022 * Initialize the old "bind_address" and "port", first.
1027 * Read the list of listeners.
1029 snprintf(buffer, sizeof(buffer), "%.200s/%s", radius_dir, mainconfig.radiusd_conf);
1030 if (listen_init(buffer, &listener) < 0) {
1035 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports. Exiting.");
1039 listen_free(&mainconfig.listen);
1040 mainconfig.listen = listener;
1043 * Walk through the listeners. If we're listening on acct
1044 * or auth, read in the clients files, else ignore them.
1046 for (listener = mainconfig.listen;
1048 listener = listener->next) {
1049 if ((listener->type == RAD_LISTEN_AUTH) ||
1050 (listener->type == RAD_LISTEN_ACCT)) {
1055 if (listener != NULL) {
1056 RADCLIENT_LIST *clients, *old_clients;
1058 /* old-style naslist file */
1059 snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
1060 DEBUG2("read_config_files: reading naslist");
1061 if (read_naslist_file(buffer) < 0) {
1062 radlog(L_ERR|L_CONS, "Errors reading naslist");
1067 * Create the new clients first, and add them
1068 * to the CONF_SECTION, where they're automagically
1069 * freed if anything goes wrong.
1071 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1072 radius_dir, mainconfig.radiusd_conf);
1073 clients = clients_parse_section(buffer, mainconfig.config);
1079 * Free the old trees AFTER replacing them with
1082 old_clients = mainconfig.clients;
1083 mainconfig.clients = clients;
1086 /* Reload the modules. */
1087 DEBUG2("radiusd: entering modules setup");
1088 if (setup_modules(reload) < 0) {
1089 radlog(L_ERR|L_CONS, "Errors setting up modules");
1096 * Free the configuration.
1098 int free_mainconfig(void)
1101 * Clean up the configuration data
1104 cf_section_free(&mainconfig.config);
1105 realm_free(mainconfig.realms);
1106 listen_free(&mainconfig.listen);