import from HEAD:
[freeradius.git] / src / main / mainconfig.c
1 /*
2  * mainconf.c   Handle the server's configuration.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2002  The FreeRADIUS server project
21  * Copyright 2002  Alan DeKok <aland@ox.org>
22  */
23
24 #include "autoconf.h"
25 #include "libradius.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
32 #endif
33
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37
38 #include "radiusd.h"
39 #include "rad_assert.h"
40 #include "conffile.h"
41 #include "token.h"
42
43 #include <sys/resource.h>
44 #include <unistd.h>
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <netdb.h>
48 #include <sys/stat.h>
49 #include <grp.h>
50 #include <pwd.h>
51
52 #ifdef HAVE_SYS_PRCTL_H
53 #include <sys/prctl.h>
54 #endif
55
56 #ifdef WITH_UDPFROMTO
57 #include "udpfromto.h"
58 #endif
59
60
61 struct main_config_t mainconfig;
62
63 /*
64  *  Local variables for stuff.
65  */
66 static uid_t server_uid;
67 static gid_t server_gid;
68
69 /*
70  *      These are not used anywhere else..
71  */
72 static const char *localstatedir = NULL;
73 static const char *prefix = NULL;
74 static int auth_port = 0;
75
76 /*
77  *  Map the proxy server configuration parameters to variables.
78  */
79 static CONF_PARSER proxy_config[] = {
80         { "retry_delay",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
81         { "retry_count",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
82         { "synchronous",  PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_synchronous, "no" },
83         { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
84         { "dead_time",    PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
85         { "post_proxy_authorize", PW_TYPE_BOOLEAN, 0, &mainconfig.post_proxy_authorize, "yes" },
86         { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
87         { NULL, -1, 0, NULL, NULL }
88 };
89
90 /*
91  *  Security configuration for the server.
92  */
93 static CONF_PARSER security_config[] = {
94         { "max_attributes",  PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
95         { "reject_delay",  PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
96         { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
97         { NULL, -1, 0, NULL, NULL }
98 };
99
100 /*
101  *  A mapping of configuration file names to internal variables
102  */
103 static CONF_PARSER server_config[] = {
104         /*
105          *      FIXME: 'prefix' is the ONLY one which should be
106          *      configured at compile time.  Hard-coding it here is
107          *      bad.  It will be cleaned up once we clean up the
108          *      hard-coded defines for the locations of the various
109          *      files.
110          */
111         { "prefix",             PW_TYPE_STRING_PTR, 0, &prefix,            "/usr/local"},
112         { "localstatedir",      PW_TYPE_STRING_PTR, 0, &localstatedir,     "${prefix}/var"},
113         { "logdir",             PW_TYPE_STRING_PTR, 0, &radlog_dir,        "${localstatedir}/log"},
114         { "libdir",             PW_TYPE_STRING_PTR, 0, &radlib_dir,        "${prefix}/lib"},
115         { "radacctdir",         PW_TYPE_STRING_PTR, 0, &radacct_dir,       "${logdir}/radacct" },
116         { "hostname_lookups",   PW_TYPE_BOOLEAN,    0, &librad_dodns,      "no" },
117 #ifdef WITH_SNMP
118         { "snmp",               PW_TYPE_BOOLEAN,    0, &mainconfig.do_snmp,      "no" },
119 #endif
120         { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
121         { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
122         { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
123         { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
124         { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
125         { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
126         { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
127         { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
128         { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
129         { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
130         { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
131         { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
132         { "bind_address", PW_TYPE_IPADDR, 0, &mainconfig.myip, "*" },
133         { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
134         { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
135         { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide,  "no" },
136         { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
137         { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
138         { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
139         { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
140         { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
141         { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
142         { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
143         { "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },
144         { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
145         { NULL, -1, 0, NULL, NULL }
146 };
147
148 /*
149  *      Xlat for %{config:section.subsection.attribute}
150  */
151 static int xlat_config(void *instance, REQUEST *request,
152                        char *fmt, char *out,
153                        size_t outlen,
154                        RADIUS_ESCAPE_STRING func)
155 {
156         CONF_SECTION *cs;
157         CONF_PAIR *cp;
158         char buffer[1024];
159         char *p, *value;
160         const char *start = fmt;
161
162         request = request;      /* -Wunused */
163         instance = instance;    /* -Wunused */
164
165         cp = NULL;
166         cs = NULL;
167
168         while (cp == NULL) {
169                 /*
170                  *      Find the next section.
171                  */
172                 for (p = buffer; (*fmt != 0) && (*fmt != '.'); p++, fmt++) {
173                         *p = *fmt;
174                 }
175                 *p = '\0';
176
177                 /*
178                  *  The character is a '.', find a section (as the user
179                  *  has given us a subsection to find)
180                  */
181                 if (*fmt == '.') {
182                         CONF_SECTION *next;
183
184                         fmt++;  /* skip the period */
185
186                         if (cs == NULL) {
187                           next = cf_section_find(buffer);
188                         } else {
189                           next = cf_subsection_find_next(cs, NULL, buffer);
190                         }
191                         if (next == NULL) {
192                                 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
193                                 return 0;
194                         }
195                         cs = next;
196
197                 } else {        /* no period, must be a conf-part */
198                         cp = cf_pair_find(cs, buffer);
199
200                         if (cp == NULL) {
201                                 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
202                                 return 0;
203                         }
204                 }
205         } /* until cp is non-NULL */
206
207         /*
208          *  Ensure that we only copy what's necessary.
209          *
210          *  If 'outlen' is too small, then the output is chopped to fit.
211          */
212         value = cf_pair_value(cp);
213         if (value) {
214                 if (outlen > strlen(value)) {
215                         outlen = strlen(value) + 1;
216                 }
217         }
218
219         return func(out, outlen, value);
220 }
221
222
223 /*
224  *      Recursively make directories.
225  */
226 static int r_mkdir(const char *part)
227 {
228         char *ptr, parentdir[500];
229         struct stat st;
230
231         if (stat(part, &st) == 0)
232                 return(0);
233
234         ptr = strrchr(part, '/');
235
236         if (ptr == part)
237                 return(0);
238
239         snprintf(parentdir, (ptr - part)+1, "%s", part);
240
241         if (r_mkdir(parentdir) != 0)
242                 return(1);
243
244         if (mkdir(part, 0770) != 0) {
245                 fprintf(stderr, "mkdir(%s) error: %s\n", part, strerror(errno));
246                 return(1);
247         }
248
249         return(0);
250 }
251
252 /*
253  *      Checks if the log directory is writeable by a particular user.
254  */
255 static int radlogdir_iswritable(const char *effectiveuser)
256 {
257         struct passwd *pwent;
258
259         if (radlog_dir[0] != '/')
260                 return(0);
261
262         if (r_mkdir(radlog_dir) != 0)
263                 return(1);
264
265         /* FIXME: do we have this function? */
266         if (strstr(radlog_dir, "radius") == NULL)
267                 return(0);
268
269         /* we have a logdir that mentions 'radius', so it's probably
270          * safe to chown the immediate directory to be owned by the normal
271          * process owner. we gotta do it before we give up root.  -chad
272          */
273
274         if (!effectiveuser) {
275                 return 1;
276         }
277
278         pwent = getpwnam(effectiveuser);
279
280         if (pwent == NULL) /* uh oh! */
281                 return(1);
282
283         if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
284                 return(1);
285
286         return(0);
287 }
288
289
290 /*
291  *  Switch UID and GID to what is specified in the config file
292  */
293 static int switch_users(void)
294 {
295         /*  Set GID.  */
296         if (mainconfig.gid_name != NULL) {
297                 struct group *gr;
298
299                 gr = getgrnam(mainconfig.gid_name);
300                 if (gr == NULL) {
301                         if (errno == ENOMEM) {
302                                 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
303                         } else {
304                                 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
305                         }
306                         exit(1);
307                 }
308                 server_gid = gr->gr_gid;
309                 if (setgid(server_gid) < 0) {
310                         radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
311                                mainconfig.gid_name, strerror(errno));
312                         exit(1);
313                 }
314         } else {
315                 server_gid = getgid();
316         }
317
318         /*  Set UID.  */
319         if (mainconfig.uid_name != NULL) {
320                 struct passwd *pw;
321
322                 pw = getpwnam(mainconfig.uid_name);
323                 if (pw == NULL) {
324                         if (errno == ENOMEM) {
325                                 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
326                         } else {
327                                 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
328                         }
329                         exit(1);
330                 }
331                 server_uid = pw->pw_uid;
332 #ifdef HAVE_INITGROUPS
333                 if (initgroups(mainconfig.uid_name, server_gid) < 0) {
334                         if (errno != EPERM) {
335                                 radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));
336                                 exit(1);
337                         }
338                 }
339 #endif
340                 if (setuid(server_uid) < 0) {
341                         radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
342                         exit(1);
343                 }
344         }
345         return(0);
346 }
347
348
349 /*
350  * Create the linked list of realms from the new configuration type
351  * This way we don't have to change to much in the other source-files
352  */
353 static int generate_realms(const char *filename)
354 {
355         CONF_SECTION *cs;
356         REALM *my_realms = NULL;
357         REALM *c, **tail;
358         char *s, *t, *authhost, *accthost;
359         char *name2;
360
361         tail = &my_realms;
362         for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
363              cs != NULL;
364              cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
365                 name2 = cf_section_name2(cs);
366                 if (!name2) {
367                         radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
368                                filename, cf_section_lineno(cs));
369                         return -1;
370                 }
371                 /*
372                  * We've found a realm, allocate space for it
373                  */
374                 c = rad_malloc(sizeof(REALM));
375                 memset(c, 0, sizeof(REALM));
376
377                 c->secret[0] = '\0';
378
379                 /*
380                  *      No authhost means LOCAL.
381                  */
382                 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
383                         c->ipaddr = htonl(INADDR_NONE);
384                         c->auth_port = 0;
385                 } else {
386                         if ((s = strchr(authhost, ':')) != NULL) {
387                                 *s++ = 0;
388                                 c->auth_port = atoi(s);
389                         } else {
390                                 c->auth_port = PW_AUTH_UDP_PORT;
391                         }
392                         if (strcmp(authhost, "LOCAL") == 0) {
393                                 /*
394                                  *      Local realms don't have an IP address,
395                                  *      secret, or port.
396                                  */
397                                 c->ipaddr = htonl(INADDR_NONE);
398                                 c->auth_port = 0;
399                         } else {
400                                 c->ipaddr = ip_getaddr(authhost);
401                                 if (c->ipaddr == htonl(INADDR_NONE)) {
402                                         free(c);
403                                         radlog(L_ERR, "%s[%d]: Host %s not found",
404                                                filename, cf_section_lineno(cs),
405                                                authhost);
406                                         return -1;
407                                 }
408                         }
409
410                         /*
411                          * Double check length, just to be sure!
412                          */
413                         if (strlen(authhost) >= sizeof(c->server)) {
414                                 free(c);
415                                 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
416                                        filename, cf_section_lineno(cs),
417                                        (int) strlen(authhost),
418                                        (int) sizeof(c->server) - 1);
419                                 return -1;
420                         }
421                 }
422
423                 /*
424                  *      No accthost means LOCAL
425                  */
426                 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
427                         c->acct_ipaddr = htonl(INADDR_NONE);
428                         c->acct_port = 0;
429                 } else {
430                         if ((s = strchr(accthost, ':')) != NULL) {
431                                 *s++ = 0;
432                                 c->acct_port = atoi(s);
433                         } else {
434                                 c->acct_port = PW_ACCT_UDP_PORT;
435                         }
436                         if (strcmp(accthost, "LOCAL") == 0) {
437                                 /*
438                                  *      Local realms don't have an IP address,
439                                  *      secret, or port.
440                                  */
441                                 c->acct_ipaddr = htonl(INADDR_NONE);
442                                 c->acct_port = 0;
443                         } else {
444                                 c->acct_ipaddr = ip_getaddr(accthost);
445                                 if (c->acct_ipaddr == htonl(INADDR_NONE)) {
446                                         free(c);
447                                         radlog(L_ERR, "%s[%d]: Host %s not found",
448                                                filename, cf_section_lineno(cs),
449                                                accthost);
450                                         return -1;
451                                 }
452                         }
453
454                         if (strlen(accthost) >= sizeof(c->acct_server)) {
455                                 free(c);
456                                 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
457                                        filename, cf_section_lineno(cs),
458                                        (int) strlen(accthost),
459                                        (int) sizeof(c->acct_server) - 1);
460                                 return -1;
461                         }
462                 }
463
464                 if (strlen(name2) >= sizeof(c->realm)) {
465                         free(c);
466                         radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
467                                filename, cf_section_lineno(cs),
468                                (int) strlen(name2),
469                                (int) sizeof(c->server) - 1);
470                         return -1;
471                 }
472
473                 strcpy(c->realm, name2);
474                 if (authhost) strcpy(c->server, authhost);
475                 if (accthost) strcpy(c->acct_server, accthost);
476
477                 /*
478                  *      If one or the other of authentication/accounting
479                  *      servers is set to LOCALHOST, then don't require
480                  *      a shared secret.
481                  */
482                 if ((c->ipaddr != htonl(INADDR_NONE)) ||
483                     (c->acct_ipaddr != htonl(INADDR_NONE))) {
484                         if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
485                                 free(c);
486                                 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
487                                        filename, cf_section_lineno(cs), name2);
488                                 return -1;
489                         }
490
491                         if (strlen(s) >= sizeof(c->secret)) {
492                                 free(c);
493                                 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
494                                        filename, cf_section_lineno(cs),
495                                        strlen(s), sizeof(c->secret) - 1);
496                                 return -1;
497                         }
498                         strNcpy((char *)c->secret, s, sizeof(c->secret));
499                 }
500
501                 c->striprealm = 1;
502
503                 if ((cf_section_value_find(cs, "nostrip")) != NULL)
504                         c->striprealm = 0;
505                 if ((cf_section_value_find(cs, "noacct")) != NULL)
506                         c->acct_port = 0;
507                 if ((cf_section_value_find(cs, "trusted")) != NULL)
508                         c->trusted = 1;
509                 if ((cf_section_value_find(cs, "notrealm")) != NULL)
510                         c->notrealm = 1;
511                 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
512                         c->notrealm = 1;
513                 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
514                         static const LRAD_NAME_NUMBER ldflags[] = {
515                                 { "fail_over",   0 },
516                                 { "round_robin", 1 },
517                                 { NULL, 0 }
518                         };
519
520                         c->ldflag = lrad_str2int(ldflags, t, -1);
521                         if (c->ldflag == -1) {
522                                 free(c);
523                                 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
524                                        filename, cf_section_lineno(cs),
525                                        t);
526                                 return -1;
527                         }
528
529                 } else {
530                         c->ldflag = 0; /* non, make it fail-over */
531                 }
532                 c->active = TRUE;
533                 c->acct_active = TRUE;
534
535                 c->next = NULL;
536                 *tail = c;
537                 tail = &c->next;
538         }
539
540         /*
541          *      And make these realms preferred over the ones
542          *      in the 'realms' file.
543          */
544         *tail = mainconfig.realms;
545         mainconfig.realms = my_realms;
546
547         /*
548          *  Ensure that all of the flags agree for the realms.
549          *
550          *      Yeah, it's O(N^2), but it's only once, and the
551          *      maximum number of realms is small.
552          */
553         for(c = mainconfig.realms; c != NULL; c = c->next) {
554                 REALM *this;
555
556                 /*
557                  *      Check that we cannot load balance to LOCAL
558                  *      realms, as that doesn't make any sense.
559                  */
560                 if ((c->ldflag == 1) &&
561                     ((c->ipaddr == htonl(INADDR_NONE)) ||
562                      (c->acct_ipaddr == htonl(INADDR_NONE)))) {
563                         radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
564                                c->realm);
565                         exit(1);
566                 }
567
568                 /*
569                  *      Compare this realm to all others, to ensure
570                  *      that the configuration is consistent.
571                  */
572                 for (this = c->next; this != NULL; this = this->next) {
573                         if (strcasecmp(c->realm, this->realm) != 0) {
574                                 continue;
575                         }
576
577                         /*
578                          *      Same realm: Different load balancing
579                          *      flag: die.
580                          */
581                         if (c->ldflag != this->ldflag) {
582                                 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
583                                        c->realm);
584                                 exit(1);
585                         }
586                 }
587         }
588
589         return 0;
590 }
591
592
593 /*
594  *      Create the linked list of realms from the new configuration
595  *      type.  This way we don't have to change too much in the other
596  *      source-files.
597  */
598 static RADCLIENT *generate_clients(const char *filename, CONF_SECTION *section)
599 {
600         CONF_SECTION    *cs;
601         RADCLIENT       *list, *c;
602         char            *hostnm, *secret, *shortnm, *netmask;
603         char            *nastype, *login, *password;
604         char            *name2;
605
606         list = NULL;
607         for (cs = cf_subsection_find_next(section, NULL, "client");
608              cs != NULL;
609              cs = cf_subsection_find_next(section, cs, "client")) {
610
611                 name2 = cf_section_name2(cs);
612                 if (!name2) {
613                         radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
614                                filename, cf_section_lineno(cs));
615                         clients_free(list);
616                         return NULL;
617                 }
618                 /*
619                  * Check the lengths, we don't want any core dumps
620                  */
621                 hostnm = name2;
622
623                 if((secret = cf_section_value_find(cs, "secret")) == NULL) {
624                         radlog(L_ERR, "%s[%d]: Missing secret for client: %s",
625                                 filename, cf_section_lineno(cs), name2);
626                         clients_free(list);
627                         return NULL;
628                 }
629
630                 if((shortnm = cf_section_value_find(cs, "shortname")) == NULL) {
631                         radlog(L_ERR, "%s[%d]: Missing shortname for client: %s",
632                                 filename, cf_section_lineno(cs), name2);
633                         clients_free(list);
634                         return NULL;
635                 }
636
637                 netmask = strchr(hostnm, '/');
638
639                 if (strlen(secret) >= sizeof(c->secret)) {
640                         radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
641                                 filename, cf_section_lineno(cs),
642                                 strlen(secret), sizeof(c->secret) - 1);
643                         clients_free(list);
644                         return NULL;
645                 }
646
647                 if (strlen(shortnm) > sizeof(c->shortname)) {
648                         radlog(L_ERR, "%s[%d]: Client short name of length %u is greater than the allowed maximum of %u.",
649                                         filename, cf_section_lineno(cs),
650                                strlen(shortnm), sizeof(c->shortname) - 1);
651                         clients_free(list);
652                         return NULL;
653                 }
654
655                 if((nastype = cf_section_value_find(cs, "nastype")) != NULL) {
656                         if(strlen(nastype) >= sizeof(c->nastype)) {
657                                radlog(L_ERR, "%s[%d]: nastype of length %u longer than the allowed maximum of %u",
658                                       filename, cf_section_lineno(cs),
659                                       strlen(nastype), sizeof(c->nastype) - 1);
660                                clients_free(list);
661                                return NULL;
662                         }
663                 }
664
665                 if((login = cf_section_value_find(cs, "login")) != NULL) {
666                         if(strlen(login) >= sizeof(c->login)) {
667                                radlog(L_ERR, "%s[%d]: login of length %u longer than the allowed maximum of %u",
668                                       filename, cf_section_lineno(cs),
669                                       strlen(login), sizeof(c->login) - 1);
670                                clients_free(list);
671                                return NULL;
672                         }
673                 }
674
675                 if((password = cf_section_value_find(cs, "password")) != NULL) {
676                         if(strlen(password) >= sizeof(c->password)) {
677                                radlog(L_ERR, "%s[%d]: password of length %u longer than the allowed maximum of %u",
678                                       filename, cf_section_lineno(cs),
679                                       strlen(password), sizeof(c->password) - 1);
680                                clients_free(list);
681                                return NULL;
682                         }
683                 }
684
685                 /*
686                  * The size is fine.. Let's create the buffer
687                  */
688                 c = rad_malloc(sizeof(RADCLIENT));
689                 memset(c, 0, sizeof(RADCLIENT));
690
691                 /*
692                  *      Look for netmasks.
693                  */
694                 c->netmask = ~0;
695                 if (netmask) {
696                         int mask_length;
697
698                         mask_length = atoi(netmask + 1);
699                         if ((mask_length < 0) || (mask_length > 32)) {
700                                 radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
701                                                 filename, cf_section_lineno(cs), netmask + 1);
702                                 clients_free(list);
703                                 free(c);
704                                 return NULL;
705                         }
706
707                         if (mask_length == 0) {
708                                 c->netmask = 0;
709                         } else {
710                                 c->netmask = ~0 << (32 - mask_length);
711                         }
712
713                         *netmask = '\0';
714                         c->netmask = htonl(c->netmask);
715                 }
716
717                 c->ipaddr = ip_getaddr(hostnm);
718                 if (c->ipaddr == INADDR_NONE) {
719                         radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
720                                         filename, cf_section_lineno(cs), hostnm);
721                         clients_free(list);
722                         free(c);
723                         return NULL;
724                 }
725
726                 /*
727                  *      Update the client name again...
728                  */
729                 if (netmask) {
730                         *netmask = '/';
731                         c->ipaddr &= c->netmask;
732                         strcpy(c->longname, hostnm);
733                 } else {
734                         ip_hostname(c->longname, sizeof(c->longname),
735                                         c->ipaddr);
736                 }
737
738                 strcpy((char *)c->secret, secret);
739                 strcpy(c->shortname, shortnm);
740                 if(nastype != NULL)
741                         strcpy(c->nastype, nastype);
742                 if(login != NULL)
743                         strcpy(c->login, login);
744                 if(password != NULL)
745                         strcpy(c->password, password);
746
747                 c->next = list;
748                 list = c;
749         }
750
751         return list;
752 }
753
754
755 /*
756  *      Code for handling listening on multiple ports.
757  */
758 static rad_listen_t listen_inst;
759 static const char *listen_type = NULL;
760
761 static const CONF_PARSER listen_config[] = {
762         { "ipaddr", PW_TYPE_IPADDR,
763           offsetof(rad_listen_t,ipaddr), NULL, "0.0.0.0" },
764
765         { "port", PW_TYPE_INTEGER,
766           offsetof(rad_listen_t,port), NULL, "0" },
767
768         { "type", PW_TYPE_STRING_PTR,
769           0, &listen_type, "" },
770
771         { NULL, -1, 0, NULL, NULL }             /* end the list */
772 };
773
774 static const LRAD_NAME_NUMBER listen_compare[] = {
775         { "auth",       RAD_LISTEN_AUTH },
776         { "acct",       RAD_LISTEN_ACCT },
777         { NULL, 0 },
778 };
779
780
781 /*
782  *      Free a linked list of listeners;
783  */
784 static void listen_free(rad_listen_t *list)
785 {
786         while (list) {
787                 rad_listen_t *next = list->next;
788                 
789                 /*
790                  *      The code below may have eaten the FD.
791                  */
792                 if (list->fd >= 0) close(list->fd);
793                 free(list);
794                 
795                 list = next;
796         }
797 }
798
799 /*
800  *      Binds a listener to a socket.
801  */
802 static int listen_bind(rad_listen_t *this)
803 {
804         struct sockaddr salocal;
805         struct sockaddr_in *sa;
806
807         rad_listen_t    **last;
808
809         /*
810          *      If the port is zero, then it means the appropriate
811          *      thing from /etc/services.
812          */
813         if (this->port == 0) {
814                 struct servent  *svp;
815
816                 switch (this->type) {
817                 case RAD_LISTEN_AUTH:
818                         svp = getservbyname ("radius", "udp");
819                         if (svp != NULL) {
820                                 this->port = ntohs(svp->s_port);
821                         } else {
822                                 this->port = PW_AUTH_UDP_PORT;
823                         }
824                         break;
825
826                 case RAD_LISTEN_ACCT:
827                         svp = getservbyname ("radacct", "udp");
828                         if (svp != NULL) {
829                                 this->port = ntohs(svp->s_port);
830                         } else {
831                                 this->port = PW_ACCT_UDP_PORT;
832                         }
833                         break;
834
835                 default:
836                         radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
837                         return -1;
838                 }
839         }
840
841         /*
842          *      Find it in the old list, AFTER updating the port.  If
843          *      it's there, use that, rather than creating a new
844          *      socket.  This allows HUP's to re-use the old sockets,
845          *      which means that packets waiting in the socket queue
846          *      don't get lost.  */
847         for (last = &mainconfig.listen;
848              *last != NULL;
849              last = &((*last)->next)) {
850                 if ((this->ipaddr == (*last)->ipaddr) &&
851                     (this->type == (*last)->type) &&
852                     (this->port == (*last)->port)) {
853                         this->fd = (*last)->fd;
854                         (*last)->fd = -1;
855                         return 0;
856                 }
857         }
858
859         /*
860          *      Create the socket.
861          */
862         this->fd = socket(AF_INET, SOCK_DGRAM, 0);
863         if (this->fd < 0) {
864                 return -1;
865         }
866         
867
868 #ifdef WITH_UDPFROMTO
869         /*
870          *      Initialize udpfromto for all sockets.
871          */
872         if (udpfromto_init(this->fd) != 0) {
873                 radlog(L_ERR|L_CONS, "ERROR: udpfromto init failed.");
874         }
875 #endif
876
877         sa = (struct sockaddr_in *) &salocal;
878         memset ((char *) sa, '\0', sizeof(salocal));
879         sa->sin_family = AF_INET;
880         sa->sin_addr.s_addr = this->ipaddr;
881         sa->sin_port = htons(this->port);
882         
883         if (bind(this->fd, &salocal, sizeof(*sa)) < 0) {
884                 close(this->fd);
885                 this->fd = -1;
886                 return -1;
887         }
888
889         return 0;
890 }
891
892
893 static int last_proxy_port = 0;
894
895 /*
896  *      Externally visible function for creating a new proxy LISTENER.
897  *
898  *      For now, don't take ipaddr or port.
899  */
900 int proxy_new_listener(void)
901 {
902         int port;
903         rad_listen_t *this;
904
905         this = rad_malloc(sizeof(*this));
906
907         memset(this, 0, sizeof(*this));
908
909         this->ipaddr = mainconfig.myip;
910         this->type = RAD_LISTEN_PROXY;
911
912         /*
913          *      Proxying was not previously defined: die.
914          */
915         if (last_proxy_port == 0) {
916                 free(this);
917                 return -1;
918         }
919
920         /*
921          *      Keep going until we find an unused port.
922          */
923         for (port = last_proxy_port + 1; port < 64000; port++) {
924                 this->port = port;
925                 if (listen_bind(this) == 0) {
926                         rad_listen_t **last;
927
928                         last_proxy_port = port;
929
930                         /*
931                          *      Add the new listener to the list of
932                          *      listeners.
933                          */
934                         for (last = &mainconfig.listen;
935                              *last != NULL;
936                              last = &((*last)->next)) {
937                                 /* do nothing */
938                         }
939
940                         *last = this;
941                         return this->fd;
942                 }
943         }
944
945         free(this);
946         return -1;
947 }
948
949
950 /*
951  *      Generate a list of listeners.  Takes an input list of
952  *      listeners, too, so we don't close sockets with waiting packets.
953  */
954 static int listen_init(const char *filename, rad_listen_t **head)
955 {
956         CONF_SECTION    *cs;
957         rad_listen_t    **last;
958         char            buffer[32];
959         rad_listen_t    *this;
960
961         /*
962          *      Add to the end of the list.
963          */
964         for (last = head; *last != NULL; last = &((*last)->next)) {
965                 /* do nothing */
966         }
967
968         /*
969          *      Find the first one (if any).
970          */
971         for (cs = cf_subsection_find_next(mainconfig.config,
972                                           NULL, "listen");
973              cs != NULL;
974              cs = cf_subsection_find_next(mainconfig.config,
975                                           cs, "listen")) {
976                 memset(&listen_inst, 0, sizeof(listen_inst));
977                 
978                 /*
979                  *      Fix errors for later.
980                  */
981                 if (cf_section_parse(cs, &listen_inst, listen_config) < 0) {
982                         radlog(L_CONS|L_ERR, "%s[%d]: Error parsing listen section.",
983                                filename, cf_section_lineno(cs));
984                         return -1;
985                 }
986
987                 if (listen_type) {
988                         listen_inst.type = lrad_str2int(listen_compare,
989                                                         listen_type, 0);
990                 }
991                 if (listen_inst.type == RAD_LISTEN_NONE) {
992                         radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
993                                filename, cf_section_lineno(cs));
994                         return -1;
995                 }
996
997                 this = rad_malloc(sizeof(*this));
998                 memcpy(this, &listen_inst, sizeof(*this));
999                 
1000                 /*
1001                  *      And bind it to the port.
1002                  */
1003                 if (listen_bind(this) < 0) {
1004                         radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s:%d",
1005                                filename, cf_section_lineno(cs),
1006                                ip_ntoa(buffer, this->ipaddr), this->port);
1007                         free(this);
1008                         return -1;
1009                 }
1010
1011                 *last = this;
1012                 last = &(this->next);           
1013         }
1014
1015         /*
1016          *      If we're proxying requests, open the proxy FD.
1017          *      Otherwise, don't do anything.
1018          */
1019         if (mainconfig.proxy_requests == TRUE) {
1020                 int             port = -1;
1021                 rad_listen_t    *auth;
1022                 int             num_realms = 0;
1023                 int             localhost = 0;
1024                 int             otherhost = 0;
1025                 REALM           *realm;
1026                 uint32_t        proxy_ip;
1027                 uint32_t        ipaddr;
1028
1029                 /*
1030                  *      If there are no realms configured, don't
1031                  *      open the proxy port.
1032                  */
1033                 for (realm = mainconfig.realms;
1034                      realm != NULL;
1035                      realm = realm->next) {
1036                         /*
1037                          *      Ignore LOCAL realms.
1038                          */
1039                         if ((realm->ipaddr == htonl(INADDR_NONE)) &&
1040                             (realm->acct_ipaddr == htonl(INADDR_NONE))) {
1041                                 continue;
1042                         }
1043                         num_realms++;
1044
1045                         /*
1046                          *      Loopback addresses
1047                          */
1048                         if (realm->ipaddr == htonl(INADDR_LOOPBACK)) {
1049                                 localhost = 1;
1050                         } else {
1051                                 otherhost = 1;
1052                         }
1053                         if (realm->acct_ipaddr == htonl(INADDR_LOOPBACK)) {
1054                                 localhost = 1;
1055                         } else {
1056                                 otherhost = 1;
1057                         }
1058                 }
1059
1060                 /*
1061                  *      No external realms.  Don't open another port.
1062                  */
1063                 if (num_realms == 0) {
1064                         return 0;
1065                 }
1066
1067                 /*
1068                  *      All of the realms are localhost, don't open
1069                  *      an external port.
1070                  */
1071                 if (localhost && !otherhost) {
1072                         proxy_ip = htonl(INADDR_LOOPBACK);
1073                 } else {
1074                         /*
1075                          *      Multiple external realms, listen
1076                          *      on any address that will send packets.
1077                          */
1078                         proxy_ip = htonl(INADDR_NONE);
1079                 }
1080
1081                 /*
1082                  *      Find the first authentication port,
1083                  *      and use it
1084                  */
1085                 ipaddr = htonl(INADDR_NONE);
1086                 for (auth = *head; auth != NULL; auth = auth->next) {
1087                         /*
1088                          *      Listening on ANY, use that.
1089                          */
1090                         if (ipaddr != htonl(INADDR_ANY)) {
1091                                 /*
1092                                  *      Not set.  Pick the first one.
1093                                  *      Or, ANY, pick that.
1094                                  */
1095                                 if ((ipaddr == htonl(INADDR_NONE)) ||
1096                                     (auth->ipaddr == htonl(INADDR_ANY))) {
1097                                         ipaddr = auth->ipaddr;
1098
1099                                         /*
1100                                          *      Else listening on multiple
1101                                          *      IP's, use ANY for proxying.
1102                                          */
1103                                 } else if (ipaddr != auth->ipaddr) {
1104                                         ipaddr = htonl(INADDR_ANY);
1105                                 }
1106                         }
1107                         if (auth->type == RAD_LISTEN_AUTH) {
1108                                 port = auth->port + 2;
1109                                 break;
1110                         }
1111                 }
1112
1113                 /*
1114                  *      Not found, pick an accounting port.
1115                  */
1116                 if (port < 0) for (auth = *head; auth != NULL; auth = auth->next) {
1117                         if (auth->type == RAD_LISTEN_ACCT) {
1118                                 port = auth->port + 1;
1119                                 break;
1120                         }
1121                 }
1122
1123                 /*
1124                  *      Still no port.  Don't do anything.
1125                  */
1126                 if (port < 0) {
1127                         return 0;
1128                 }
1129
1130                 this = rad_malloc(sizeof(*this));
1131                 memset(this, 0, sizeof(*this));
1132
1133                 /*
1134                  *      More checks to do the right thing.
1135                  */
1136                 if (proxy_ip == htonl(INADDR_NONE)) {
1137                         proxy_ip = ipaddr;
1138                 }
1139                 
1140                 /*
1141                  *      Create the proxy socket.
1142                  */
1143                 this->ipaddr = proxy_ip;
1144                 this->type = RAD_LISTEN_PROXY;
1145
1146                 /*
1147                  *      Try to find a proxy port (value doesn't matter)
1148                  */
1149                 for (this->port = port;
1150                      this->port < 64000;
1151                      this->port++) {
1152                         if (listen_bind(this) == 0) {
1153                                 last_proxy_port = this->port;
1154                                 *last = this;
1155                                 return 0;
1156                         }
1157                 }
1158
1159                 radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1160                 free(this);
1161                 return -1;
1162         }
1163
1164         return 0;
1165 }
1166
1167
1168 /*
1169  *      Hack the OLD way of listening on a socket.
1170  */
1171 static int old_listen_init(rad_listen_t **head)
1172 {
1173         CONF_PAIR       *cp;
1174         rad_listen_t    *this, **last;
1175
1176         /*
1177          *      No "bind_address": all listen directives
1178          *      are in the "listen" clauses.
1179          */
1180         cp = cf_pair_find(mainconfig.config, "bind_address");
1181         if (!cp) return 0;
1182         
1183         last = head;
1184
1185         this = rad_malloc(sizeof(*this));
1186         memset(this, 0, sizeof(*this));
1187
1188         /*
1189          *      Create the authentication socket.
1190          */
1191         this->ipaddr = mainconfig.myip;
1192         this->type = RAD_LISTEN_AUTH;
1193         this->port = auth_port;
1194
1195         if (listen_bind(this) < 0) {
1196                 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", this->port);
1197                 free(this);
1198                 return -1;
1199         }
1200         auth_port = this->port; /* may have been updated in listen_bind */
1201         *last = this;
1202         last = &(this->next);
1203
1204         /*
1205          *  Open Accounting Socket.
1206          *
1207          *  If we haven't already gotten acct_port from /etc/services,
1208          *  then make it auth_port + 1.
1209          */
1210         this = rad_malloc(sizeof(*this));
1211         memset(this, 0, sizeof(*this));
1212
1213         /*
1214          *      Create the accounting socket.
1215          *
1216          *      The accounting port is always the authentication port + 1
1217          */
1218         this->ipaddr = mainconfig.myip;
1219         this->type = RAD_LISTEN_ACCT;
1220         this->port = auth_port + 1;
1221
1222         if (listen_bind(this) < 0) {
1223                 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", this->port);
1224                 free(this);
1225                 return -1;
1226         }
1227         *last = this;
1228
1229         return 0;
1230 }
1231
1232
1233 #ifndef RADIUS_CONFIG
1234 #define RADIUS_CONFIG "radiusd.conf"
1235 #endif
1236
1237 CONF_SECTION *read_radius_conf_file(void)
1238 {
1239         char buffer[256];
1240         CONF_SECTION *cs;
1241         struct stat statbuf;
1242
1243         if (stat(radius_dir, &statbuf) < 0) {
1244                 radlog(L_ERR|L_CONS, "Errors reading %s: %s",
1245                        radius_dir, strerror(errno));
1246                 return NULL;
1247         }
1248
1249         if ((statbuf.st_mode & S_IWOTH) != 0) {
1250                 radlog(L_ERR|L_CONS, "Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
1251                        radius_dir);
1252           return NULL;
1253         }
1254
1255
1256         if (0 && (statbuf.st_mode & S_IROTH) != 0) {
1257                 radlog(L_ERR|L_CONS, "Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
1258                        radius_dir);
1259                 return NULL;
1260         }
1261
1262         /* Lets go look for the new configuration files */
1263         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1264         if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
1265                 return NULL;
1266         }
1267
1268         /*
1269          *      This allows us to figure out where, relative to
1270          *      radiusd.conf, the other configuration files exist.
1271          */
1272         cf_section_parse(cs, NULL, server_config);
1273
1274         /* Initialize the dictionary */
1275         DEBUG2("read_config_files:  reading dictionary");
1276         if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
1277                 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
1278                                 librad_errstr);
1279                 cf_section_free(&cs);
1280                 return NULL;
1281         }
1282
1283         return cs;
1284 }
1285
1286
1287 /*
1288  *      Read config files.
1289  *
1290  *      This function can ONLY be called from the main server process.
1291  */
1292 int read_mainconfig(int reload)
1293 {
1294         struct rlimit core_limits;
1295         static int old_debug_level = -1;
1296         char buffer[1024];
1297         CONF_SECTION *cs, *oldcs;
1298         rad_listen_t *listener;
1299         RADCLIENT *c, *tail;
1300
1301         if (!reload) {
1302                 radlog(L_INFO, "Starting - reading configuration files ...");
1303         } else {
1304                 radlog(L_INFO, "Reloading configuration files.");
1305         }
1306
1307         /* First read radiusd.conf */
1308         DEBUG2("reread_config:  reading radiusd.conf");
1309         if ((cs = read_radius_conf_file()) == NULL) {
1310                 if (debug_flag ||
1311                     (radlog_dir == NULL)) {
1312                         radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
1313                 } else {
1314                         radlog(L_ERR|L_CONS, "Errors reading %s/radiusd.conf: For more information, please read the tail end of %s", radius_dir, mainconfig.log_file);
1315                 }
1316                 return -1;
1317         }
1318
1319         /*
1320          *      Free the old configuration items, and replace them
1321          *      with the new ones.
1322          *
1323          *      Note that where possible, we do atomic switch-overs,
1324          *      to ensure that the pointers are always valid.
1325          */
1326         oldcs = mainconfig.config;
1327         mainconfig.config = cs;
1328         cf_section_free(&oldcs);
1329
1330         /* old-style naslist file */
1331         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
1332         DEBUG2("read_config_files:  reading naslist");
1333         if (read_naslist_file(buffer) < 0) {
1334                 radlog(L_ERR|L_CONS, "Errors reading naslist");
1335                 return -1;
1336         }
1337         /* old-style clients file */
1338         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
1339         DEBUG2("read_config_files:  reading clients");
1340         if (read_clients_file(buffer) < 0) {
1341                 radlog(L_ERR|L_CONS, "Errors reading clients");
1342                 return -1;
1343         }
1344
1345         /*
1346          *      Add to that, the *new* list of clients.
1347          */
1348         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1349         c = generate_clients(buffer, mainconfig.config);
1350         if (!c) {
1351                 return -1;
1352         }
1353
1354         /*
1355          *      The new list of clients takes precedence over the old one.
1356          */
1357         for (tail = c; tail->next != NULL; tail = tail->next) {
1358           /* do nothing */
1359         }
1360         tail->next = mainconfig.clients;
1361         mainconfig.clients = c;
1362         
1363         /* old-style realms file */
1364         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
1365         DEBUG2("read_config_files:  reading realms");
1366         if (read_realms_file(buffer) < 0) {
1367                 radlog(L_ERR|L_CONS, "Errors reading realms");
1368                 return -1;
1369         }
1370
1371         /*
1372          *      If there isn't any realms it isn't fatal..
1373          */
1374         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
1375         if (generate_realms(buffer) < 0) {
1376                 return -1;
1377         }
1378
1379         /*
1380          *  Register the %{config:section.subsection} xlat function.
1381          */
1382         xlat_register("config", xlat_config, NULL);
1383
1384         /*
1385          *      Set the libraries debugging flag to whatever the main
1386          *      flag is.  Note that on a SIGHUP, to turn the debugging
1387          *      off, we do other magic.
1388          *
1389          *      Increase the debug level, if the configuration file
1390          *      says to, OR, if we're decreasing the debug from what it
1391          *      was before, allow that, too.
1392          */
1393         if ((mainconfig.debug_level > debug_flag) ||
1394             (mainconfig.debug_level <= old_debug_level)) {
1395           debug_flag = mainconfig.debug_level;
1396         }
1397         librad_debug = debug_flag;
1398         old_debug_level = mainconfig.debug_level;
1399
1400         /*
1401          *  Go update our behaviour, based on the configuration
1402          *  changes.
1403          */
1404
1405         /*  Get the current maximum for core files.  */
1406         if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
1407                 radlog(L_ERR|L_CONS, "Failed to get current core limit:  %s", strerror(errno));
1408                 exit(1);
1409         }
1410
1411         if (mainconfig.allow_core_dumps) {
1412                 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
1413                         radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
1414                                         strerror(errno));
1415                         exit(1);
1416
1417                         /*
1418                          *  If we're running as a daemon, and core
1419                          *  dumps are enabled, log that information.
1420                          */
1421                 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
1422                         radlog(L_INFO|L_CONS, "Core dumps are enabled.");
1423
1424         } else if (!debug_flag) {
1425                 /*
1426                  *  Not debugging.  Set the core size to zero, to
1427                  *  prevent security breaches.  i.e. People
1428                  *  reading passwords from the 'core' file.
1429                  */
1430                 struct rlimit limits;
1431
1432                 limits.rlim_cur = 0;
1433                 limits.rlim_max = core_limits.rlim_max;
1434
1435                 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
1436                         radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
1437                                         strerror(errno));
1438                         exit(1);
1439                 }
1440         }
1441
1442         /*
1443          *      The first time around, ensure that we can write to the
1444          *      log directory.
1445          */
1446         if (!reload) {
1447                 /*
1448                  *      We need root to do mkdir() and chown(), so we
1449                  *      do this before giving up root.
1450                  */
1451                 radlogdir_iswritable(mainconfig.uid_name);
1452         }
1453         switch_users();
1454
1455 #ifdef HAVE_SYS_PRCTL_H
1456 #ifdef HAVE_PR_SET_DUMPABLE
1457         if (mainconfig.allow_core_dumps) {
1458                 if (prctl(PR_SET_DUMPABLE, 1) < 0) {
1459                         radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
1460                                strerror(errno));
1461                 }
1462         }
1463 #endif
1464 #endif
1465
1466         /*
1467          *      Sanity check the configuration for internal
1468          *      consistency.
1469          */
1470         if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1471                 mainconfig.reject_delay = mainconfig.cleanup_delay;
1472         }
1473
1474         /*
1475          *      Initialize the old "bind_address" and "port", first.
1476          */
1477         listener = NULL;
1478         if (old_listen_init(&listener) < 0) {
1479                 exit(1);
1480         }
1481
1482         /*
1483          *      Read the list of listeners.
1484          */
1485         snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
1486         if (listen_init(buffer, &listener) < 0) {
1487                 exit(1);
1488         }
1489
1490         if (!listener) {
1491                 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports.  Exiting.");
1492                 exit(1);
1493         }
1494
1495         listen_free(mainconfig.listen);
1496         mainconfig.listen = listener;
1497
1498         return 0;
1499 }
1500
1501 /*
1502  *      Free the configuration.
1503  */
1504 int free_mainconfig(void)
1505 {
1506         /*
1507          *      Clean up the configuration data
1508          *      structures.
1509          */
1510         cf_section_free(&mainconfig.config);
1511         realm_free(mainconfig.realms);
1512         clients_free(mainconfig.clients);
1513         read_naslist_file(NULL);
1514
1515         rl_free();
1516         listen_free(mainconfig.listen);
1517         paircompare_builtin_free();
1518         xlat_free();
1519         dict_free();
1520         lt_dlexit();
1521
1522         return 0;
1523 }