remove delete_blocked_requests option due to unsafe pthread_cancel()
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2002,2006-2007  The FreeRADIUS server project
21  * Copyright 2002  Alan DeKok <aland@ox.org>
22  */
23
24 #include <freeradius-devel/ident.h>
25 RCSID("$Id$")
26
27 #include <freeradius-devel/autoconf.h>
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
34 #endif
35
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39
40 #include <freeradius-devel/radiusd.h>
41 #include <freeradius-devel/rad_assert.h>
42 #include <freeradius-devel/modules.h>
43 #include <freeradius-devel/request_list.h>
44
45 #include <sys/resource.h>
46 #include <netdb.h>
47 #include <sys/stat.h>
48 #include <grp.h>
49 #include <pwd.h>
50
51 #ifdef HAVE_SYS_PRTCL_H
52 #include <sys/prctl.h>
53 #endif
54
55 #ifdef HAVE_SYSLOG_H
56 #       include <syslog.h>
57 #endif
58
59 struct main_config_t mainconfig;
60
61 /*
62  *      Temporary local variables for parsing the configuration
63  *      file.
64  */
65 static uid_t server_uid;
66 static gid_t server_gid;
67
68 /*
69  *      These are not used anywhere else..
70  */
71 static const char *localstatedir = NULL;
72 static const char *prefix = NULL;
73 static char *syslog_facility = NULL;
74 static const LRAD_NAME_NUMBER str2fac[] = {
75 #ifdef LOG_KERN
76         { "kern", LOG_KERN },
77 #endif  
78 #ifdef LOG_USER
79         { "user", LOG_USER },
80 #endif
81 #ifdef LOG_MAIL
82         { "mail", LOG_MAIL },
83 #endif
84 #ifdef LOG_DAEMON
85         { "daemon", LOG_DAEMON },
86 #endif
87 #ifdef LOG_AUTH
88         { "auth", LOG_AUTH },
89 #endif
90 #ifdef LOG_LPR
91         { "lpr", LOG_LPR },
92 #endif
93 #ifdef LOG_NEWS
94         { "news", LOG_NEWS },
95 #endif
96 #ifdef LOG_UUCP
97         { "uucp", LOG_UUCP },
98 #endif
99 #ifdef LOG_CRON
100         { "cron", LOG_CRON },
101 #endif
102 #ifdef LOG_AUTHPRIV
103         { "authpriv", LOG_AUTHPRIV },
104 #endif
105 #ifdef LOG_FTP
106         { "ftp", LOG_FTP },
107 #endif
108 #ifdef LOG_LOCAL0
109         { "local0", LOG_LOCAL0 },
110 #endif
111 #ifdef LOG_LOCAL1
112         { "local1", LOG_LOCAL1 },
113 #endif
114 #ifdef LOG_LOCAL2
115         { "local2", LOG_LOCAL2 },
116 #endif
117 #ifdef LOG_LOCAL3
118         { "local3", LOG_LOCAL3 },
119 #endif
120 #ifdef LOG_LOCAL4
121         { "local4", LOG_LOCAL4 },
122 #endif
123 #ifdef LOG_LOCAL5
124         { "local5", LOG_LOCAL5 },
125 #endif
126 #ifdef LOG_LOCAL6
127         { "local6", LOG_LOCAL6 },
128 #endif
129 #ifdef LOG_LOCAL7
130         { "local7", LOG_LOCAL7 },
131 #endif
132         { NULL, -1 }
133 };
134
135 /*
136  *  Map the proxy server configuration parameters to variables.
137  */
138 static const CONF_PARSER proxy_config[] = {
139         { "retry_delay",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
140         { "retry_count",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
141         { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
142         { "dead_time",    PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
143         { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
144         { "proxy_fail_type", PW_TYPE_STRING_PTR, 0, &mainconfig.proxy_fail_type, NULL},
145         { NULL, -1, 0, NULL, NULL }
146 };
147
148
149 /*
150  *  Security configuration for the server.
151  */
152 static const CONF_PARSER security_config[] = {
153         { "max_attributes",  PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
154         { "reject_delay",  PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
155         { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
156         { NULL, -1, 0, NULL, NULL }
157 };
158
159
160 /*
161  *  syslog configuration for the server.
162  */
163 static const CONF_PARSER log_config[] = {
164         { "syslog_facility",  PW_TYPE_STRING_PTR, 0, &syslog_facility, Stringify(0) },
165         { NULL, -1, 0, NULL, NULL }
166 };
167
168
169 /*
170  *  A mapping of configuration file names to internal variables
171  */
172 static const CONF_PARSER server_config[] = {
173         /*
174          *      FIXME: 'prefix' is the ONLY one which should be
175          *      configured at compile time.  Hard-coding it here is
176          *      bad.  It will be cleaned up once we clean up the
177          *      hard-coded defines for the locations of the various
178          *      files.
179          */
180         { "prefix",             PW_TYPE_STRING_PTR, 0, &prefix,            "/usr/local"},
181         { "localstatedir",      PW_TYPE_STRING_PTR, 0, &localstatedir,     "${prefix}/var"},
182         { "logdir",             PW_TYPE_STRING_PTR, 0, &radlog_dir,        "${localstatedir}/log"},
183         { "libdir",             PW_TYPE_STRING_PTR, 0, &radlib_dir,        "${prefix}/lib"},
184         { "radacctdir",         PW_TYPE_STRING_PTR, 0, &radacct_dir,       "${logdir}/radacct" },
185         { "hostname_lookups",   PW_TYPE_BOOLEAN,    0, &librad_dodns,      "no" },
186 #ifdef WITH_SNMP
187         { "snmp",               PW_TYPE_BOOLEAN,    0, &mainconfig.do_snmp,      "no" },
188 #endif
189         { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
190         { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
191         { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
192 #ifdef DELETE_BLOCKED_REQUESTS
193         { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
194 #endif
195         { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
196         { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
197
198         { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
199         { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
200         { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
201         { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
202         { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
203         { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
204         { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
205         { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
206
207         { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
208
209         { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
210         { "log", PW_TYPE_SUBSECTION, 0, NULL,  (const void *) log_config},
211         { "proxy", PW_TYPE_SUBSECTION, 0, NULL, (const void *) proxy_config },
212         { "security", PW_TYPE_SUBSECTION, 0, NULL, (const void *) security_config },
213         { NULL, -1, 0, NULL, NULL }
214 };
215
216
217 #define MAX_ARGV (256)
218 /*
219  *      Xlat for %{config:section.subsection.attribute}
220  */
221 static int xlat_config(void *instance, REQUEST *request,
222                        char *fmt, char *out,
223                        size_t outlen,
224                        RADIUS_ESCAPE_STRING func)
225 {
226         CONF_SECTION *cs;
227         CONF_PAIR *cp;
228         int i, argc, left;
229         const char *from, *value;
230         char *to;
231         char myfmt[1024];
232         char argv_buf[1024];
233         char *argv[MAX_ARGV];
234
235         request = request;      /* -Wunused */
236         instance = instance;    /* -Wunused */
237
238         cp = NULL;
239         cs = NULL;
240
241         /*
242          *      Split the string into argv's BEFORE doing radius_xlat...
243          *      Copied from exec.c
244          */
245         from = fmt;
246         to = myfmt; 
247         argc = 0;
248         while (*from) {
249                 int flag, length;
250                 
251                 flag = 0;
252                 argv[argc] = to;
253                 argc++;
254                 
255                 if (argc >= (MAX_ARGV - 1)) break;
256                 
257                 /*
258                  *      Copy the argv over to our buffer.
259                  */
260                 while (*from) {
261                         if (to >= myfmt + sizeof(myfmt) - 1) {
262                                 return 0; /* no error msg */
263                         }
264
265                         switch (*from) {
266                         case '%':
267                                 if (from[1] == '{') {
268                                         *(to++) = *(from++);
269                                         
270                                         length = rad_copy_variable(to, from);
271                                         if (length < 0) {
272                                                 return -1;
273                                         }
274                                         from += length;
275                                         to += length;
276                                 } else { /* FIXME: catch %%{ ? */
277                                         *(to++) = *(from++);
278                                 }
279                                 break;
280
281                         case '[':
282                                 if (flag != 0) {
283                                         radlog(L_ERR, "config: Unexpected nested '[' in \"%s\"", fmt);
284                                         return 0;
285                                 }
286                                 flag++;
287                                 *(to++) = *(from++);
288                                 break;
289
290                         case ']':
291                                 if (flag == 0) {
292                                         radlog(L_ERR, "config: Unbalanced ']' in \"%s\"", fmt);
293                                         return 0;
294                                 }
295                                 if (from[1] != '.') {
296                                         radlog(L_ERR, "config: Unexpected text after ']' in \"%s\"", fmt);
297                                         return 0;
298                                 }
299
300                                 flag--;
301                                 *(to++) = *(from++);
302                                 break;
303
304                         case '.':
305                                 if (flag == 0) break;
306                                 /* FALL-THROUGH */
307
308                         default:
309                                 *(to++) = *(from++);
310                                 break;
311                         }
312
313                         if ((*from == '.') && (flag == 0)) {
314                                 from++;
315                                 break;
316                         }
317                 } /* end of string, or found a period */
318
319                 if (flag != 0) {
320                         radlog(L_ERR, "config: Unbalanced '[' in \"%s\"", fmt);
321                         return 0;
322                 }
323
324                 *(to++) = '\0'; /* terminate the string. */
325         }
326
327         /*
328          *      Expand each string, as appropriate
329          */
330         to = argv_buf;
331         left = sizeof(argv_buf);
332         for (i = 0; i < argc; i++) {
333                 int sublen;
334
335                 /*
336                  *      Don't touch argv's which won't be translated.
337                  */
338                 if (strchr(argv[i], '%') == NULL) continue;
339
340                 sublen = radius_xlat(to, left - 1, argv[i], request, NULL);
341                 if (sublen <= 0) {
342                         /*
343                          *      Fail to be backwards compatible.
344                          *
345                          *      It's yucky, but it won't break anything,
346                          *      and it won't cause security problems.
347                          */
348                         sublen = 0;
349                 }
350                 
351                 argv[i] = to;
352                 to += sublen;
353                 *(to++) = '\0';
354                 left -= sublen;
355                 left--;
356
357                 if (left <= 0) {
358                         return 0;
359                 }
360         }
361         argv[argc] = NULL;
362
363         cs = cf_section_find(NULL); /* get top-level section */
364
365         /*
366          *      Root through section & subsection references.
367          *      The last entry of argv MUST be the CONF_PAIR.
368          */
369         for (i = 0; i < argc - 1; i++) {
370                 char *name2 = NULL;
371                 CONF_SECTION *subcs;
372
373                 /*
374                  *      FIXME: What about RADIUS attributes containing '['?
375                  */
376                 name2 = strchr(argv[i], '[');
377                 if (name2) {
378                         char *p = strchr(name2, ']');
379                         rad_assert(p != NULL);
380                         rad_assert(p[1] =='\0');
381                         *p = '\0';
382                         *name2 = '\0';
383                         name2++;
384                 }
385
386                 if (name2) {
387                         subcs = cf_section_sub_find_name2(cs, argv[i],
388                                                           name2);
389                         if (!subcs) {
390                           radlog(L_ERR, "config: section \"%s %s {}\" not found while dereferencing \"%s\"", argv[i], name2, fmt);
391                           return 0;
392                         }
393                 } else {
394                         subcs = cf_section_sub_find(cs, argv[i]);
395                         if (!subcs) {
396                           radlog(L_ERR, "config: section \"%s {}\" not found while dereferencing \"%s\"", argv[i], fmt);
397                           return 0;
398                         }
399                 }
400                 cs = subcs;
401         } /* until argc - 1 */
402
403         /*
404          *      This can now have embedded periods in it.
405          */
406         cp = cf_pair_find(cs, argv[argc - 1]);
407         if (!cp) {
408                 radlog(L_ERR, "config: item \"%s\" not found while dereferencing \"%s\"", argv[argc], fmt);
409                 return 0;
410         }
411
412         /*
413          *  Ensure that we only copy what's necessary.
414          *
415          *  If 'outlen' is too small, then the output is chopped to fit.
416          */
417         value = cf_pair_value(cp);
418         if (value) {
419                 if (outlen > strlen(value)) {
420                         outlen = strlen(value) + 1;
421                 }
422         }
423
424         return func(out, outlen, value);
425 }
426
427
428 /*
429  *      Recursively make directories.
430  */
431 static int r_mkdir(const char *part)
432 {
433         char *ptr, parentdir[500];
434         struct stat st;
435
436         if (stat(part, &st) == 0)
437                 return(0);
438
439         ptr = strrchr(part, '/');
440
441         if (ptr == part)
442                 return(0);
443
444         snprintf(parentdir, (ptr - part)+1, "%s", part);
445
446         if (r_mkdir(parentdir) != 0)
447                 return(1);
448
449         if (mkdir(part, 0770) != 0) {
450                 radlog(L_ERR, "mkdir(%s) error: %s\n", part, strerror(errno));
451                 return(1);
452         }
453
454         return(0);
455 }
456
457 /*
458  *      Checks if the log directory is writeable by a particular user.
459  */
460 static int radlogdir_iswritable(const char *effectiveuser)
461 {
462         struct passwd *pwent;
463
464         if (!radlog_dir || radlog_dir[0] != '/')
465                 return(0);
466
467         if (r_mkdir(radlog_dir) != 0)
468                 return(1);
469
470         /* FIXME: do we have this function? */
471         if (strstr(radlog_dir, "radius") == NULL)
472                 return(0);
473
474         /* we have a logdir that mentions 'radius', so it's probably
475          * safe to chown the immediate directory to be owned by the normal
476          * process owner. we gotta do it before we give up root.  -chad
477          */
478
479         if (!effectiveuser) {
480                 return 1;
481         }
482
483         pwent = getpwnam(effectiveuser);
484
485         if (pwent == NULL) /* uh oh! */
486                 return(1);
487
488         if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
489                 return(1);
490
491         return(0);
492 }
493
494
495 /*
496  *  Switch UID and GID to what is specified in the config file
497  */
498 static int switch_users(void)
499 {
500         struct rlimit core_limits;
501
502         /*  Set GID.  */
503         if (mainconfig.gid_name != NULL) {
504                 struct group *gr;
505
506                 gr = getgrnam(mainconfig.gid_name);
507                 if (gr == NULL) {
508                         if (errno == ENOMEM) {
509                                 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
510                         } else {
511                                 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
512                         }
513                         exit(1);
514                 }
515                 server_gid = gr->gr_gid;
516                 if (setgid(server_gid) < 0) {
517                         radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
518                                mainconfig.gid_name, strerror(errno));
519                         exit(1);
520                 }
521         } else {
522                 server_gid = getgid();
523         }
524
525         /*  Set UID.  */
526         if (mainconfig.uid_name != NULL) {
527                 struct passwd *pw;
528
529                 pw = getpwnam(mainconfig.uid_name);
530                 if (pw == NULL) {
531                         if (errno == ENOMEM) {
532                                 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
533                         } else {
534                                 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
535                         }
536                         exit(1);
537                 }
538                 server_uid = pw->pw_uid;
539 #ifdef HAVE_INITGROUPS
540                 if (initgroups(mainconfig.uid_name, server_gid) < 0) {
541                         if (errno != EPERM) {
542                                 radlog(L_ERR|L_CONS, "Failed setting supplementary groups for User %s: %s", mainconfig.uid_name, strerror(errno));
543                                 exit(1);
544                         }
545                 }
546 #endif
547                 if (setuid(server_uid) < 0) {
548                         radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
549                         exit(1);
550                 }
551         }
552
553         /*  Get the current maximum for core files.  */
554         if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
555                 radlog(L_ERR|L_CONS, "Failed to get current core limit:  %s", strerror(errno));
556                 exit(1);
557         }
558
559         if (mainconfig.allow_core_dumps) {
560 #ifdef HAVE_SYS_PRTCL_H
561 #ifdef PR_SET_DUMPABLE
562                 if (prctl(PR_SET_DUMPABLE, 1) < 0) {
563                         radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
564                                strerror(errno));
565                 }
566 #endif
567 #endif
568
569                 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
570                         radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
571                                         strerror(errno));
572                         exit(1);
573
574                         /*
575                          *  If we're running as a daemon, and core
576                          *  dumps are enabled, log that information.
577                          */
578                 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
579                         radlog(L_INFO|L_CONS, "Core dumps are enabled.");
580
581         } else if (!debug_flag) {
582                 /*
583                  *  Not debugging.  Set the core size to zero, to
584                  *  prevent security breaches.  i.e. People
585                  *  reading passwords from the 'core' file.
586                  */
587                 struct rlimit limits;
588
589                 limits.rlim_cur = 0;
590                 limits.rlim_max = core_limits.rlim_max;
591
592                 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
593                         radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
594                                         strerror(errno));
595                         exit(1);
596                 }
597         }
598
599         /*
600          *      We've probably written to the log file already as
601          *      root.root, so if we have switched users, we've got to
602          *      update the ownership of the file.
603          */
604         if ((debug_flag == 0) &&
605             (mainconfig.radlog_dest == RADLOG_FILES) &&
606             (mainconfig.log_file != NULL)) {
607                 chown(mainconfig.log_file, server_uid, server_gid);
608         }
609
610         return(0);
611 }
612
613
614 /*
615  * Create the linked list of realms from the new configuration type
616  * This way we don't have to change to much in the other source-files
617  */
618 static int generate_realms(const char *filename)
619 {
620         CONF_SECTION *cs;
621         REALM *my_realms = NULL;
622         REALM *c, **tail;
623         char *s, *t, *authhost, *accthost;
624         const char *name2;
625
626         tail = &my_realms;
627         for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
628              cs != NULL;
629              cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
630                 name2 = cf_section_name2(cs);
631                 if (!name2) {
632                         radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
633                                filename, cf_section_lineno(cs));
634                         return -1;
635                 }
636                 /*
637                  * We've found a realm, allocate space for it
638                  */
639                 c = rad_malloc(sizeof(REALM));
640                 memset(c, 0, sizeof(REALM));
641
642                 c->secret[0] = '\0';
643
644                 /*
645                  *      No authhost means LOCAL.
646                  */
647                 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
648                         c->ipaddr.af = AF_INET;
649                         c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
650                         c->auth_port = 0;
651                 } else {
652                         if ((s = strchr(authhost, ':')) != NULL) {
653                                 *s++ = 0;
654                                 c->auth_port = atoi(s);
655                         } else {
656                                 c->auth_port = PW_AUTH_UDP_PORT;
657                         }
658                         if (strcmp(authhost, "LOCAL") == 0) {
659                                 /*
660                                  *      Local realms don't have an IP address,
661                                  *      secret, or port.
662                                  */
663                                 c->ipaddr.af = AF_INET;
664                                 c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
665                                 c->auth_port = 0;
666                         } else {
667                                 if (ip_hton(authhost, AF_INET,
668                                             &c->ipaddr) < 0) {
669                                         radlog(L_ERR, "%s[%d]: Host %s not found",
670                                                filename, cf_section_lineno(cs),
671                                                authhost);
672                                         return -1;
673                                 }
674                         }
675
676                         /*
677                          * Double check length, just to be sure!
678                          */
679                         if (strlen(authhost) >= sizeof(c->server)) {
680                                 radlog(L_ERR, "%s[%d]: Server name of length %u is greater than allowed: %u",
681                                        filename, cf_section_lineno(cs),
682                                        strlen(authhost),
683                                        sizeof(c->server) - 1);
684                                 return -1;
685                         }
686                 }
687
688                 /*
689                  *      No accthost means LOCAL
690                  */
691                 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
692                         c->acct_ipaddr.af = AF_INET;
693                         c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
694                         c->acct_port = 0;
695                 } else {
696                         if ((s = strchr(accthost, ':')) != NULL) {
697                                 *s++ = 0;
698                                 c->acct_port = atoi(s);
699                         } else {
700                                 c->acct_port = PW_ACCT_UDP_PORT;
701                         }
702                         if (strcmp(accthost, "LOCAL") == 0) {
703                                 /*
704                                  *      Local realms don't have an IP address,
705                                  *      secret, or port.
706                                  */
707                                 c->acct_ipaddr.af = AF_INET;
708                                 c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
709                                 c->acct_port = 0;
710                         } else {
711                                 if (ip_hton(accthost, AF_INET,
712                                             &c->acct_ipaddr) < 0) {
713                                         radlog(L_ERR, "%s[%d]: Host %s not found",
714                                                filename, cf_section_lineno(cs),
715                                                accthost);
716                                         return -1;
717                                 }
718                         }
719
720                         if (strlen(accthost) >= sizeof(c->acct_server)) {
721                                 radlog(L_ERR, "%s[%d]: Server name of length %u is greater than allowed: %u",
722                                        filename, cf_section_lineno(cs),
723                                        strlen(accthost),
724                                        sizeof(c->acct_server) - 1);
725                                 return -1;
726                         }
727                 }
728
729                 if (strlen(name2) >= sizeof(c->realm)) {
730                         radlog(L_ERR, "%s[%d]: Realm name of length %u is greater than allowed %u",
731                                filename, cf_section_lineno(cs),
732                                strlen(name2),
733                                sizeof(c->server) - 1);
734                         return -1;
735                 }
736
737                 strcpy(c->realm, name2);
738                 if (authhost) strcpy(c->server, authhost);
739                 if (accthost) strcpy(c->acct_server, accthost);
740
741                 /*
742                  *      If one or the other of authentication/accounting
743                  *      servers is set to LOCALHOST, then don't require
744                  *      a shared secret.
745                  */
746                 rad_assert(c->ipaddr.af == AF_INET);
747                 rad_assert(c->acct_ipaddr.af == AF_INET);
748                 if ((c->ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE)) ||
749                     (c->acct_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE))) {
750                         if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
751                                 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
752                                        filename, cf_section_lineno(cs), name2);
753                                 return -1;
754                         }
755
756                         if (strlen(s) >= sizeof(c->secret)) {
757                                 radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
758                                        filename, cf_section_lineno(cs),
759                                        strlen(s), sizeof(c->secret) - 1);
760                                 return -1;
761                         }
762                         strlcpy((char *)c->secret, s, sizeof(c->secret));
763                 }
764
765                 c->striprealm = 1;
766
767                 if ((cf_section_value_find(cs, "nostrip")) != NULL)
768                         c->striprealm = 0;
769                 if ((cf_section_value_find(cs, "noacct")) != NULL)
770                         c->acct_port = 0;
771                 if ((cf_section_value_find(cs, "trusted")) != NULL)
772                         c->trusted = 1;
773                 if ((cf_section_value_find(cs, "notrealm")) != NULL)
774                         c->notrealm = 1;
775                 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
776                         c->notrealm = 1;
777                 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
778                         static const LRAD_NAME_NUMBER ldflags[] = {
779                                 { "fail_over",   0 },
780                                 { "round_robin", 1 },
781                                 { NULL, 0 }
782                         };
783
784                         c->ldflag = lrad_str2int(ldflags, t, -1);
785                         if (c->ldflag == -1) {
786                                 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
787                                        filename, cf_section_lineno(cs),
788                                        t);
789                                 return -1;
790                         }
791
792                 } else {
793                         c->ldflag = 0; /* non, make it fail-over */
794                 }
795                 c->active = TRUE;
796                 c->acct_active = TRUE;
797
798                 c->next = NULL;
799                 *tail = c;
800                 tail = &c->next;
801         }
802
803         /*
804          *      And make these realms preferred over the ones
805          *      in the 'realms' file.
806          */
807         *tail = mainconfig.realms;
808         mainconfig.realms = my_realms;
809
810         /*
811          *  Ensure that all of the flags agree for the realms.
812          *
813          *      Yeah, it's O(N^2), but it's only once, and the
814          *      maximum number of realms is small.
815          */
816         for(c = mainconfig.realms; c != NULL; c = c->next) {
817                 REALM *this;
818
819                 /*
820                  *      Check that we cannot load balance to LOCAL
821                  *      realms, as that doesn't make any sense.
822                  */
823                 rad_assert(c->ipaddr.af == AF_INET);
824                 rad_assert(c->acct_ipaddr.af == AF_INET);
825                 if ((c->ldflag == 1) &&
826                     ((c->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) ||
827                      (c->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)))) {
828                         radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
829                                c->realm);
830                         exit(1);
831                 }
832
833                 /*
834                  *      Compare this realm to all others, to ensure
835                  *      that the configuration is consistent.
836                  */
837                 for (this = c->next; this != NULL; this = this->next) {
838                         if (strcasecmp(c->realm, this->realm) != 0) {
839                                 continue;
840                         }
841
842                         /*
843                          *      Same realm: Different load balancing
844                          *      flag: die.
845                          */
846                         if (c->ldflag != this->ldflag) {
847                                 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
848                                        c->realm);
849                                 exit(1);
850                         }
851                 }
852         }
853
854         return 0;
855 }
856
857
858 static const LRAD_NAME_NUMBER str2dest[] = {
859         { "null", RADLOG_NULL },
860         { "files", RADLOG_FILES },
861         { "syslog", RADLOG_SYSLOG },
862         { "stdout", RADLOG_STDOUT },
863         { "stderr", RADLOG_STDERR },
864         { NULL, RADLOG_NUM_DEST }
865 };
866
867
868 /*
869  *      Read config files.
870  *
871  *      This function can ONLY be called from the main server process.
872  */
873 int read_mainconfig(int reload)
874 {
875         static int old_debug_level = -1;
876         char buffer[1024];
877         CONF_SECTION *cs, *oldcs;
878         rad_listen_t *listener;
879         struct stat statbuf;
880
881         if (stat(radius_dir, &statbuf) < 0) {
882                 radlog(L_ERR|L_CONS, "Errors reading %s: %s",
883                        radius_dir, strerror(errno));
884                 return -1;
885         }
886
887         if ((statbuf.st_mode & S_IWOTH) != 0) {
888                 radlog(L_ERR|L_CONS, "Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
889                        radius_dir);
890           return -1;
891         }
892
893
894         if (0 && (statbuf.st_mode & S_IROTH) != 0) {
895                 radlog(L_ERR|L_CONS, "Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
896                        radius_dir);
897                 return -1;
898         }
899
900         /* Read the configuration file */
901         snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
902                  radius_dir, mainconfig.radiusd_conf);
903         if ((cs = cf_file_read(buffer)) == NULL) {
904                 radlog(L_ERR|L_CONS, "Errors reading %s", buffer);
905                 return -1;
906         }
907
908         /*
909          *      Debug flag 1 MAY go to files.
910          *      Debug flag 2 ALWAYS goes to stdout
911          *
912          *      Parse the log_destination before printing anything else.
913          *      All messages before this MUST be errors, which log.c
914          *      will print to stderr, since log_file is NULL, too.
915          */
916         if (debug_flag < 2) {
917                 int rcode;
918                 char *radlog_dest = NULL;
919
920                 rcode = cf_item_parse(cs, "log_destination",
921                                       PW_TYPE_STRING_PTR, &radlog_dest,
922                                       "files");
923                 if (rcode < 0) return -1;
924         
925                 mainconfig.radlog_dest = lrad_str2int(str2dest, radlog_dest, RADLOG_NUM_DEST);
926                 if (mainconfig.radlog_dest == RADLOG_NUM_DEST) {
927                         fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
928                                 radlog_dest);
929                         free(radlog_dest);
930                         cf_section_free(&cs);
931                         return -1;
932                 }
933                 
934                 if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
935                         static const CONF_PARSER syslog_config[] = {
936                                 { "log", PW_TYPE_SUBSECTION, 0, NULL,  (const void *) log_config},
937                                 { NULL, -1, 0, NULL, NULL }
938                         };
939                         cf_section_parse(cs, NULL, syslog_config);
940
941                         /*
942                          *      Make sure syslog_facility isn't NULL before using it
943                          */
944                         if (!syslog_facility) {
945                                 fprintf(stderr, "radiusd: Error: Unknown syslog chosen but no facility spedified\n");
946                                 free(radlog_dest);
947                                 cf_section_free(&cs);
948                                 return -1;
949                         }
950                         mainconfig.syslog_facility = lrad_str2int(str2fac, syslog_facility, -1);
951                         if (mainconfig.syslog_facility < 0) {
952                                 fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
953                                         syslog_facility);
954                                 free(radlog_dest);
955                                 free(syslog_facility);
956                                 cf_section_free(&cs);
957                                 return -1;
958                         }
959                 }
960
961                 if (mainconfig.radlog_dest == RADLOG_FILES) {
962                         static const CONF_PARSER file_config[] = {
963                                 { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
964                                 { NULL, -1, 0, NULL, NULL }
965                         };
966
967                         cf_section_parse(cs, NULL, file_config);
968                 }
969
970                 free(radlog_dest);
971         } else {
972                 mainconfig.radlog_dest = RADLOG_STDOUT;
973                 mainconfig.radlog_fd = STDOUT_FILENO;
974         }
975
976         radlog(L_INFO, "%s", radiusd_version);
977         if (!reload) {
978                 radlog(L_INFO, "Starting - reading configuration files ...");
979         } else {
980                 radlog(L_INFO, "Reloading - reading configuration files...");
981         }
982
983         /* Initialize the dictionary */
984         DEBUG2("read_config_files:  reading dictionary");
985         if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
986                 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
987                                 librad_errstr);
988                 return -1;
989         }
990
991         /*
992          *      This allows us to figure out where, relative to
993          *      radiusd.conf, the other configuration files exist.
994          */
995         cf_section_parse(cs, NULL, server_config);
996
997 #if 0
998         /*
999          *      Merge the old with the new.
1000          */
1001         if (reload) {
1002                 CONF_SECTION *newcs;
1003
1004                 newcs = cf_section_sub_find(cs, "modules");
1005                 oldcs = cf_section_sub_find(mainconfig.config, "modules");
1006                 if (newcs && oldcs) {
1007                         if (!cf_section_migrate(newcs, oldcs)) {
1008                                 radlog(L_ERR|L_CONS, "Fatal error migrating configuration data");
1009                                 return -1;
1010                         }
1011                 }
1012         }
1013 #endif
1014
1015         /*
1016          *      Free the old configuration items, and replace them
1017          *      with the new ones.
1018          *
1019          *      Note that where possible, we do atomic switch-overs,
1020          *      to ensure that the pointers are always valid.
1021          */
1022         oldcs = mainconfig.config;
1023         mainconfig.config = cs;
1024         cf_section_free(&oldcs);
1025
1026         /*
1027          *      Old-style realms file.
1028          */
1029         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
1030         DEBUG2("read_config_files:  reading realms");
1031         if (read_realms_file(buffer) < 0) {
1032                 radlog(L_ERR|L_CONS, "Errors reading realms");
1033                 return -1;
1034         }
1035
1036         /*
1037          *      If there isn't any realms it isn't fatal..
1038          */
1039         snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1040                  radius_dir, mainconfig.radiusd_conf);
1041         if (generate_realms(buffer) < 0) {
1042                 return -1;
1043         }
1044
1045         /*
1046          *  Register the %{config:section.subsection} xlat function.
1047          */
1048         xlat_register("config", xlat_config, NULL);
1049
1050         /*
1051          *      Set the libraries debugging flag to whatever the main
1052          *      flag is.  Note that on a SIGHUP, to turn the debugging
1053          *      off, we do other magic.
1054          *
1055          *      Increase the debug level, if the configuration file
1056          *      says to, OR, if we're decreasing the debug from what it
1057          *      was before, allow that, too.
1058          */
1059         if ((mainconfig.debug_level > debug_flag) ||
1060             (mainconfig.debug_level <= old_debug_level)) {
1061                 debug_flag = mainconfig.debug_level;
1062         }
1063         librad_debug = debug_flag;
1064         old_debug_level = mainconfig.debug_level;
1065
1066         /*
1067          *  Go update our behaviour, based on the configuration
1068          *  changes.
1069          */
1070
1071         /*
1072          *      The first time around, ensure that we can write to the
1073          *      log directory.
1074          */
1075         if (!reload) {
1076                 /*
1077                  *      We need root to do mkdir() and chown(), so we
1078                  *      do this before giving up root.
1079                  */
1080                 radlogdir_iswritable(mainconfig.uid_name);
1081         }
1082
1083         /*
1084          *      We should really switch users earlier in the process.
1085          */
1086         switch_users();
1087
1088         /*
1089          *      Sanity check the configuration for internal
1090          *      consistency.
1091          */
1092         if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
1093                 mainconfig.reject_delay = mainconfig.cleanup_delay;
1094         }
1095
1096         /*
1097          *      Initialize the old "bind_address" and "port", first.
1098          */
1099         listener = NULL;
1100
1101         /*
1102          *      Read the list of listeners.
1103          */
1104         snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1105                  radius_dir, mainconfig.radiusd_conf);
1106         if (listen_init(buffer, &listener) < 0) {
1107                 exit(1);
1108         }
1109
1110         if (!listener) {
1111                 radlog(L_ERR|L_CONS, "Server is not configured to listen on any ports.  Exiting.");
1112                 exit(1);
1113         }
1114
1115         listen_free(&mainconfig.listen);
1116         mainconfig.listen = listener;
1117
1118         /*
1119          *      Walk through the listeners.  If we're listening on acct
1120          *      or auth, read in the clients files, else ignore them.
1121          */
1122         for (listener = mainconfig.listen;
1123              listener != NULL;
1124              listener = listener->next) {
1125                 if ((listener->type == RAD_LISTEN_AUTH) ||
1126                     (listener->type == RAD_LISTEN_ACCT)) {
1127                         break;
1128                 }
1129         }
1130
1131         if (listener != NULL) {
1132                 RADCLIENT_LIST *clients, *old_clients;
1133
1134                 /*
1135                  *      Create the new clients first, and add them
1136                  *      to the CONF_SECTION, where they're automagically
1137                  *      freed if anything goes wrong.
1138                  */
1139                 snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
1140                          radius_dir, mainconfig.radiusd_conf);
1141                 clients = clients_parse_section(buffer, mainconfig.config);
1142                 if (!clients) {
1143                         return -1;
1144                 }
1145
1146                 /*
1147                  *      Free the old trees AFTER replacing them with
1148                  *      the new ones...
1149                  */
1150                 old_clients = mainconfig.clients;
1151                 mainconfig.clients = clients;
1152                 clients_free(old_clients);
1153         }
1154
1155         rl_init_proxy();
1156
1157         /*  Reload the modules.  */
1158         DEBUG2("radiusd:  entering modules setup");
1159         if (setup_modules(reload) < 0) {
1160                 radlog(L_ERR|L_CONS, "Errors setting up modules");
1161                 return -1;
1162         }
1163         return 0;
1164 }
1165
1166 /*
1167  *      Free the configuration.  Called only when the server is exiting.
1168  */
1169 int free_mainconfig(void)
1170 {
1171         /*
1172          *      Clean up the configuration data
1173          *      structures.
1174          */
1175         cf_section_free(&mainconfig.config);
1176         free(mainconfig.radiusd_conf);
1177         realm_free(mainconfig.realms);
1178         listen_free(&mainconfig.listen);
1179         xlat_free();
1180         dict_free();
1181         lt_dlexit();
1182
1183         return 0;
1184 }