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