6800264906fd1c9d36cf4f1d70b46842cd36c1c6
[freeradius.git] / src / main / mainconfig.c
1 /*
2  * mainconf.c   Handle the server's configuration.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2002  The FreeRADIUS server project
21  * Copyright 2002  Alan DeKok <aland@ox.org>
22  */
23
24 #include "autoconf.h"
25 #include "libradius.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
32 #endif
33
34 #include "radiusd.h"
35 #include "rad_assert.h"
36 #include "conffile.h"
37 #include "token.h"
38
39 #include <sys/resource.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <grp.h>
44 #include <pwd.h>
45
46
47 struct main_config_t mainconfig;
48
49 /*
50  *  Local variables for stuff.
51  */
52 static uid_t server_uid;
53 static gid_t server_gid;
54
55 /*
56  *      These are not used anywhere else..
57  */
58 static const char *localstatedir = NULL;
59 static const char *prefix = NULL;
60
61 /*
62  *  Map the proxy server configuration parameters to variables.
63  */
64 static CONF_PARSER proxy_config[] = {
65         { "retry_delay",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
66         { "retry_count",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
67         { "synchronous",  PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_synchronous, "no" },
68         { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
69         { "dead_time",    PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
70         { "post_proxy_authorize", PW_TYPE_BOOLEAN, 0, &mainconfig.post_proxy_authorize, "yes" },
71         { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
72         { NULL, -1, 0, NULL, NULL }
73 };
74
75 /*
76  *  Security configuration for the server.
77  */
78 static CONF_PARSER security_config[] = {
79         { "max_attributes",  PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
80         { "reject_delay",  PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
81         { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
82         { NULL, -1, 0, NULL, NULL }
83 };
84
85 /*
86  *  A mapping of configuration file names to internal variables
87  */
88 static CONF_PARSER server_config[] = {
89         /*
90          *      FIXME: 'prefix' is the ONLY one which should be
91          *      configured at compile time.  Hard-coding it here is
92          *      bad.  It will be cleaned up once we clean up the
93          *      hard-coded defines for the locations of the various
94          *      files.
95          */
96         { "prefix",             PW_TYPE_STRING_PTR, 0, &prefix,            "/usr/local"},
97         { "localstatedir",      PW_TYPE_STRING_PTR, 0, &localstatedir,     "${prefix}/var"}, 
98         { "logdir",             PW_TYPE_STRING_PTR, 0, &radlog_dir,        "${localstatedir}/log"},
99         { "libdir",             PW_TYPE_STRING_PTR, 0, &radlib_dir,        "${prefix}/lib"},
100         { "radacctdir",         PW_TYPE_STRING_PTR, 0, &radacct_dir,       "${logdir}/radacct" },
101         { "hostname_lookups",   PW_TYPE_BOOLEAN,    0, &librad_dodns,      "no" },
102 #ifdef WITH_SNMP
103         { "snmp",               PW_TYPE_BOOLEAN,    0, &mainconfig.do_snmp,      "no" },
104 #endif
105         { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
106         { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
107         { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
108         { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
109         { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
110         { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
111         { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
112         { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
113         { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
114         { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
115         { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
116         { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
117         { "bind_address", PW_TYPE_IPADDR, 0, &mainconfig.myip, "*" },
118         { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
119         { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
120         { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide,  "no" },
121         { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
122         { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
123         { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
124         { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
125         { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
126         { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
127         { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
128         { "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },
129         { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
130         { NULL, -1, 0, NULL, NULL }
131 };
132
133 /*
134  *      Xlat for %{config:section.subsection.attribute}
135  */
136 static int xlat_config(void *instance, REQUEST *request,
137                        char *fmt, char *out,
138                        size_t outlen,
139                        RADIUS_ESCAPE_STRING func)
140 {
141         CONF_SECTION *cs;
142         CONF_PAIR *cp;
143         char buffer[1024];
144         char *p, *value;
145         const char *start = fmt;
146
147         request = request;      /* -Wunused */
148         instance = instance;    /* -Wunused */
149
150         cp = NULL;
151         cs = NULL;
152
153         while (cp == NULL) {
154                 /*
155                  *      Find the next section.
156                  */
157                 for (p = buffer; (*fmt != 0) && (*fmt != '.'); p++, fmt++) {
158                         *p = *fmt;
159                 }
160                 *p = '\0';
161
162                 /*
163                  *  The character is a '.', find a section (as the user
164                  *  has given us a subsection to find)
165                  */
166                 if (*fmt == '.') {
167                         CONF_SECTION *next;
168
169                         fmt++;  /* skip the period */
170
171                         if (cs == NULL) {
172                           next = cf_section_find(buffer);
173                         } else {
174                           next = cf_subsection_find_next(cs, NULL, buffer);
175                         }
176                         if (next == NULL) {
177                                 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
178                                 return 0;
179                         }
180                         cs = next;
181
182                 } else {        /* no period, must be a conf-part */
183                         cp = cf_pair_find(cs, buffer);
184
185                         if (cp == NULL) {
186                                 radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
187                                 return 0;
188                         }
189                 }
190         } /* until cp is non-NULL */
191
192         /*
193          *  Ensure that we only copy what's necessary.
194          *
195          *  If 'outlen' is too small, then the output is chopped to fit.
196          */
197         value = cf_pair_value(cp);
198         if (value) {
199                 if (outlen > strlen(value)) {
200                         outlen = strlen(value) + 1;
201                 }
202         }
203         
204         return func(out, outlen, value);
205 }
206
207
208 /*
209  *      Recursively make directories.
210  */
211 static int r_mkdir(const char *part) {
212         char *ptr, parentdir[500];
213         struct stat st;
214
215         if (stat(part, &st) == 0)
216                 return(0);
217
218         ptr = strrchr(part, '/');
219
220         if (ptr == part)
221                 return(0);
222
223         snprintf(parentdir, (ptr - part)+1, "%s", part);
224
225         if (r_mkdir(parentdir) != 0)
226                 return(1);
227
228         if (mkdir(part, 0770) != 0) {
229                 fprintf(stderr, "mkdir(%s) error: %s\n", part, strerror(errno));
230                 return(1);
231         }
232
233         fprintf(stderr, "Created directory %s\n", part);
234
235         return(0);
236 }
237                 
238 /*
239  *      Checks if the log directory is writeable by a particular user.
240  */
241 static int radlogdir_iswritable(const char *effectiveuser) {
242         struct passwd *pwent;
243
244         if (radlog_dir[0] != '/')
245                 return(0);
246
247         if (r_mkdir(radlog_dir) != 0)
248                 return(1);
249
250         /* FIXME: do we have this function? */
251         if (strstr(radlog_dir, "radius") == NULL)
252                 return(0);
253
254         /* we have a logdir that mentions 'radius', so it's probably 
255          * safe to chown the immediate directory to be owned by the normal 
256          * process owner. we gotta do it before we give up root.  -chad
257          */
258         
259         if (!effectiveuser) {
260                 return 1;
261         }
262
263         pwent = getpwnam(effectiveuser);
264
265         if (pwent == NULL) /* uh oh! */
266                 return(1);
267
268         if (chown(radlog_dir, pwent->pw_uid, -1) != 0)
269                 return(1);
270
271         return(0);
272 }
273
274
275 static int switch_users(void) {
276         
277         /*
278          *  Switch UID and GID to what is specified in the config file
279          */
280
281         /*  Set GID.  */
282         if (mainconfig.gid_name != NULL) {
283                 struct group *gr;
284
285                 gr = getgrnam(mainconfig.gid_name);
286                 if (gr == NULL) {
287                         if (errno == ENOMEM) {
288                                 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: out of memory", mainconfig.gid_name);
289                         } else {
290                                 radlog(L_ERR|L_CONS, "Cannot switch group; %s doesn't exist", mainconfig.gid_name);
291                         }
292                         exit(1);
293                 }
294                 server_gid = gr->gr_gid;
295                 if (setgid(server_gid) < 0) {
296                         radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s",
297                                mainconfig.gid_name, strerror(errno));
298                         exit(1);
299                 }
300         }
301
302         /*  Set UID.  */
303         if (mainconfig.uid_name != NULL) {
304                 struct passwd *pw;
305
306                 pw = getpwnam(mainconfig.uid_name);
307                 if (pw == NULL) {
308                         if (errno == ENOMEM) {
309                                 radlog(L_ERR|L_CONS, "Cannot switch to User %s: out of memory", mainconfig.uid_name);
310                         } else {
311                                 radlog(L_ERR|L_CONS, "Cannot switch user; %s doesn't exist", mainconfig.uid_name);
312                         }
313                         exit(1);
314                 }
315                 server_uid = pw->pw_uid;
316                 if (setuid(server_uid) < 0) {
317                         radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", mainconfig.uid_name, strerror(errno));
318                         exit(1);
319                 }
320         }
321         return(0);
322 }
323
324
325 /* 
326  * Create the linked list of realms from the new configuration type
327  * This way we don't have to change to much in the other source-files
328  */
329 static int generate_realms(const char *filename)
330 {
331         CONF_SECTION *cs;
332         REALM *my_realms = NULL;
333         REALM *c, **tail;
334         char *s, *t, *authhost, *accthost;
335         char *name2;
336
337         tail = &my_realms;
338         for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
339              cs != NULL;
340              cs = cf_subsection_find_next(mainconfig.config, cs, "realm")) {
341                 name2 = cf_section_name2(cs);
342                 if (!name2) {
343                         radlog(L_CONS|L_ERR, "%s[%d]: Missing realm name",
344                                filename, cf_section_lineno(cs));
345                         return -1;
346                 }
347                 /*
348                  * We've found a realm, allocate space for it
349                  */
350                 c = rad_malloc(sizeof(REALM));
351                 memset(c, 0, sizeof(REALM));
352
353                 c->secret[0] = '\0';
354
355                 /*
356                  *      No authhost means LOCAL.
357                  */
358                 if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
359                         c->ipaddr = htonl(INADDR_NONE);
360                         c->auth_port = auth_port;
361                 } else {
362                         if ((s = strchr(authhost, ':')) != NULL) {
363                                 *s++ = 0;
364                                 c->auth_port = atoi(s);
365                         } else {
366                                 c->auth_port = auth_port;
367                         }
368                         if (strcmp(authhost, "LOCAL") == 0) {
369                                 /*
370                                  *      Local realms don't have an IP address,
371                                  *      secret, or port.
372                                  */
373                                 c->ipaddr = htonl(INADDR_NONE);
374                                 c->auth_port = auth_port;
375                         } else {
376                                 c->ipaddr = ip_getaddr(authhost);
377                                 if (c->ipaddr == htonl(INADDR_NONE)) {
378                                         radlog(L_ERR, "%s[%d]: Host %s not found",
379                                                filename, cf_section_lineno(cs),
380                                                authhost);
381                                         return -1;
382                                 }
383                         }
384
385                         /* 
386                          * Double check length, just to be sure!
387                          */
388                         if (strlen(authhost) >= sizeof(c->server)) {
389                                 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
390                                        filename, cf_section_lineno(cs),
391                                        (int) strlen(authhost),
392                                        (int) sizeof(c->server) - 1);
393                                 return -1;
394                         }
395                 }
396
397                 /*
398                  *      No accthost means LOCAL
399                  */
400                 if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
401                         c->acct_ipaddr = htonl(INADDR_NONE);
402                         c->acct_port = acct_port;
403                 } else {
404                         if ((s = strchr(accthost, ':')) != NULL) {
405                                 *s++ = 0;
406                                 c->acct_port = atoi(s); 
407                         } else {
408                                 c->acct_port = acct_port;
409                         }
410                         if (strcmp(accthost, "LOCAL") == 0) {
411                                 /*
412                                  *      Local realms don't have an IP address,
413                                  *      secret, or port.
414                                  */
415                                 c->acct_ipaddr = htonl(INADDR_NONE);
416                                 c->acct_port = acct_port;
417                         } else {
418                                 c->acct_ipaddr = ip_getaddr(accthost);
419                                 if (c->acct_ipaddr == htonl(INADDR_NONE)) {
420                                         radlog(L_ERR, "%s[%d]: Host %s not found",
421                                                filename, cf_section_lineno(cs),
422                                                accthost);
423                                         return -1;
424                                 }
425                         }                                   
426
427                         if (strlen(accthost) >= sizeof(c->acct_server)) {
428                                 radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
429                                        filename, cf_section_lineno(cs),
430                                        (int) strlen(accthost),
431                                        (int) sizeof(c->acct_server) - 1);
432                                 return -1;
433                         }
434                 }
435
436                 if (strlen(name2) >= sizeof(c->realm)) {
437                         radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
438                                filename, cf_section_lineno(cs),
439                                (int) strlen(name2),
440                                (int) sizeof(c->server) - 1);
441                         return -1;
442                 }
443                 
444                 strcpy(c->realm, name2);
445                 if (authhost) strcpy(c->server, authhost);
446                 if (accthost) strcpy(c->acct_server, accthost); 
447
448                 /*
449                  *      If one or the other of authentication/accounting
450                  *      servers is set to LOCALHOST, then don't require
451                  *      a shared secret.
452                  */
453                 if ((c->ipaddr != htonl(INADDR_NONE)) ||
454                     (c->acct_ipaddr != htonl(INADDR_NONE))) {
455                         if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
456                                 radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
457                                        filename, cf_section_lineno(cs), name2);
458                                 return -1;
459                         }
460                         
461                         if (strlen(s) >= sizeof(c->secret)) {
462                                 radlog(L_ERR, "%s[%d]: Secret of length %d is greater than the allowed maximum of %d.",
463                                        filename, cf_section_lineno(cs),
464                                        strlen(s), sizeof(c->secret) - 1);
465                                 return -1;
466                         }
467                         strNcpy((char *)c->secret, s, sizeof(c->secret));
468                 }
469
470                 c->striprealm = 1;
471                 
472                 if ((cf_section_value_find(cs, "nostrip")) != NULL)
473                         c->striprealm = 0;
474                 if ((cf_section_value_find(cs, "noacct")) != NULL)
475                         c->acct_port = 0;
476                 if ((cf_section_value_find(cs, "trusted")) != NULL)
477                         c->trusted = 1;
478                 if ((cf_section_value_find(cs, "notrealm")) != NULL)
479                         c->notrealm = 1;
480                 if ((cf_section_value_find(cs, "notsuffix")) != NULL)
481                         c->notrealm = 1;
482                 if ((t = cf_section_value_find(cs,"ldflag")) != NULL) {
483                         static const LRAD_NAME_NUMBER ldflags[] = {
484                                 { "fail_over",   0 },
485                                 { "round_robin", 1 },
486                                 { NULL, 0 }
487                         };
488
489                         c->ldflag = lrad_str2int(ldflags, t, -1);
490                         if (c->ldflag == -1) {
491                                 radlog(L_ERR, "%s[%d]: Unknown value \"%s\" for ldflag",
492                                        filename, cf_section_lineno(cs),
493                                        t);
494                                 return -1;
495                         }
496
497                 } else {
498                         c->ldflag = 0; /* non, make it fail-over */
499                 }
500                 c->active = TRUE;
501                 c->acct_active = TRUE;
502
503                 c->next = NULL;
504                 *tail = c;
505                 tail = &c->next;
506         }
507
508         /*
509          *      And make these realms preferred over the ones
510          *      in the 'realms' file.
511          */
512         *tail = mainconfig.realms;
513         mainconfig.realms = my_realms;
514
515         /*
516          *  Ensure that all of the flags agree for the realms.
517          *
518          *      Yeah, it's O(N^2), but it's only once, and the
519          *      maximum number of realms is small.
520          */
521         for(c = mainconfig.realms; c != NULL; c = c->next) {
522                 REALM *this;
523
524                 /*
525                  *      Check that we cannot load balance to LOCAL
526                  *      realms, as that doesn't make any sense.
527                  */
528                 if ((c->ldflag == 1) &&
529                     ((c->ipaddr == htonl(INADDR_NONE)) ||
530                      (c->acct_ipaddr == htonl(INADDR_NONE)))) {
531                         radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
532                                c->realm);
533                         exit(1);
534                 }
535
536                 /*
537                  *      Compare this realm to all others, to ensure
538                  *      that the configuration is consistent.
539                  */
540                 for (this = c->next; this != NULL; this = this->next) {
541                         if (strcasecmp(c->realm, this->realm) != 0) {
542                                 continue;
543                         }
544
545                         /*
546                          *      Same realm: Different load balancing
547                          *      flag: die.
548                          */
549                         if (c->ldflag != this->ldflag) {
550                                 radlog(L_ERR | L_CONS, "ERROR: Inconsistent value in realm %s for load balancing 'ldflag' attribute",
551                                        c->realm);
552                                 exit(1);
553                         }
554                 }
555         }
556
557         return 0;
558 }
559
560
561 /*
562  *      Create the linked list of realms from the new configuration
563  *      type.  This way we don't have to change too much in the other
564  *      source-files.
565  */
566 static int generate_clients(const char *filename)
567 {
568         CONF_SECTION    *cs;
569         RADCLIENT       *c;
570         char            *hostnm, *secret, *shortnm, *netmask;
571         char            *nastype, *login, *password;
572         char            *name2;
573
574         for (cs = cf_subsection_find_next(mainconfig.config, NULL, "client");
575              cs != NULL; 
576              cs = cf_subsection_find_next(mainconfig.config, cs, "client")) {
577
578                 name2 = cf_section_name2(cs);
579                 if (!name2) {
580                         radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
581                                filename, cf_section_lineno(cs));
582                         return -1;
583                 }
584                 /*
585                  * Check the lengths, we don't want any core dumps
586                  */
587                 hostnm = name2;
588
589                 if((secret = cf_section_value_find(cs, "secret")) == NULL) {
590                         radlog(L_ERR, "%s[%d]: Missing secret for client: %s",
591                                 filename, cf_section_lineno(cs), name2);
592                         return -1;
593                 }
594
595                 if((shortnm = cf_section_value_find(cs, "shortname")) == NULL) {
596                         radlog(L_ERR, "%s[%d]: Missing shortname for client: %s",
597                                 filename, cf_section_lineno(cs), name2);
598                         return -1;
599                 }
600
601                 netmask = strchr(hostnm, '/');
602
603                 if (strlen(secret) >= sizeof(c->secret)) {
604                         radlog(L_ERR, "%s[%d]: Secret of length %d is greater than the allowed maximum of %d.",
605                                 filename, cf_section_lineno(cs),
606                                 strlen(secret), sizeof(c->secret) - 1);
607                         return -1;
608                 }
609                 if (strlen(shortnm) > sizeof(c->shortname)) {
610                         radlog(L_ERR, "%s[%d]: Client short name of length %d is greater than the allowed maximum of %d.",
611                                         filename, cf_section_lineno(cs),
612                                         strlen(shortnm), sizeof(c->shortname) - 1);
613                         return -1;
614                 }
615
616                 if((nastype = cf_section_value_find(cs, "nastype")) != NULL) {
617                         if(strlen(nastype) >= sizeof(c->nastype)) { 
618                                radlog(L_ERR, "%s[%d]: nastype of length %d longer than the allowed maximum of %d",
619                                       filename, cf_section_lineno(cs), 
620                                       strlen(nastype), sizeof(c->nastype) - 1);
621                                return -1;
622                         }
623                 }
624
625                 if((login = cf_section_value_find(cs, "login")) != NULL) {
626                         if(strlen(login) >= sizeof(c->login)) { 
627                                radlog(L_ERR, "%s[%d]: login of length %d longer than the allowed maximum of %d",
628                                       filename, cf_section_lineno(cs), 
629                                       strlen(login), sizeof(c->login) - 1);
630                                return -1;
631                         }
632                 }
633
634                 if((password = cf_section_value_find(cs, "password")) != NULL) {
635                         if(strlen(password) >= sizeof(c->password)) { 
636                                radlog(L_ERR, "%s[%d]: password of length %d longer than the allowed maximum of %d",
637                                       filename, cf_section_lineno(cs), 
638                                       strlen(password), sizeof(c->password) - 1);
639                                return -1;
640                         }
641                 }
642
643                 /*
644                  * The size is fine.. Let's create the buffer
645                  */
646                 c = rad_malloc(sizeof(RADCLIENT));
647                 memset(c, 0, sizeof(RADCLIENT));
648
649                 /*
650                  *      Look for netmasks.
651                  */
652                 c->netmask = ~0;
653                 if (netmask) {
654                         int i, mask_length;
655
656                         mask_length = atoi(netmask + 1);
657                         if ((mask_length < 0) || (mask_length > 32)) {
658                                 radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
659                                                 filename, cf_section_lineno(cs), netmask + 1);
660                                 return -1;
661                         }
662                         
663                         c->netmask = (1 << 31);
664                         for (i = 1; i < mask_length; i++) {
665                                 c->netmask |= (c->netmask >> 1);
666                         }
667
668                         *netmask = '\0';
669                         c->netmask = htonl(c->netmask);
670                 }
671
672                 c->ipaddr = ip_getaddr(hostnm);
673                 if (c->ipaddr == INADDR_NONE) {
674                         radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
675                                         filename, cf_section_lineno(cs), hostnm);
676                         return -1;
677                 }
678
679                 /*
680                  *      Update the client name again...
681                  */
682                 if (netmask) {
683                         *netmask = '/';
684                         c->ipaddr &= c->netmask;
685                         strcpy(c->longname, hostnm);
686                 } else {
687                         ip_hostname(c->longname, sizeof(c->longname),
688                                         c->ipaddr);
689                 }
690
691                 strcpy((char *)c->secret, secret);
692                 strcpy(c->shortname, shortnm);
693                 if(nastype != NULL)
694                         strcpy(c->nastype, nastype);
695                 if(login != NULL)
696                         strcpy(c->login, login);
697                 if(password != NULL)
698                         strcpy(c->password, password);
699
700                 c->next =mainconfig. clients;
701                 mainconfig.clients = c;
702         }
703
704         return 0;
705 }
706
707 #ifndef RADIUS_CONFIG
708 #define RADIUS_CONFIG "radiusd.conf"
709 #endif
710
711 CONF_SECTION *read_radius_conf_file(void)
712 {
713         char buffer[256];
714         CONF_SECTION *cs;
715
716         /* Lets go look for the new configuration files */
717         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
718         if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
719                 return NULL;
720         }
721
722         /*
723          *      This allows us to figure out where, relative to
724          *      radiusd.conf, the other configuration files exist.
725          */
726         cf_section_parse(cs, NULL, server_config);
727
728         /* Initialize the dictionary */
729         DEBUG2("read_config_files:  reading dictionary");
730         if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
731                 radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
732                                 librad_errstr);
733                 cf_section_free(&cs);
734                 return NULL;
735         }
736
737         return cs;
738 }
739
740
741 /*
742  *      Read config files.
743  *
744  *      This function can ONLY be called from the main server process.
745  */
746 int read_mainconfig(int reload)
747 {
748         struct rlimit core_limits;
749         static int old_debug_level = -1;
750         char buffer[1024];
751         CONF_SECTION *cs, *oldcs;
752
753         if (!reload) {
754                 radlog(L_INFO, "Starting - reading configuration files ...");
755         } else {
756                 radlog(L_INFO, "Reloading configuration files.");
757         }
758
759         /* First read radiusd.conf */
760         DEBUG2("reread_config:  reading radiusd.conf");
761         if ((cs = read_radius_conf_file()) == NULL) {
762                 if (debug_flag ||
763                     (radlog_dir == NULL)) {
764                         radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
765                 } else {
766                         radlog(L_ERR|L_CONS, "Errors reading %s/radiusd.conf: For more information, please read the tail end of %s", radlog_dir, mainconfig.log_file);
767                 }
768                 return -1;
769         }
770
771         /*
772          *      Free the old configuration items, and replace them
773          *      with the new ones.
774          *
775          *      Note that where possible, we do atomic switch-overs,
776          *      to ensure that the pointers are always valid.
777          */
778         oldcs = mainconfig.config;
779         mainconfig.config = cs;
780         cf_section_free(&oldcs);
781
782         /* old-style naslist file */
783         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
784         DEBUG2("read_config_files:  reading naslist");
785         if (read_naslist_file(buffer) < 0) {
786                 radlog(L_ERR|L_CONS, "Errors reading naslist");
787                 return -1;
788         }
789         /* old-style clients file */
790         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
791         DEBUG2("read_config_files:  reading clients");
792         if (read_clients_file(buffer) < 0) {
793                 radlog(L_ERR|L_CONS, "Errors reading clients");
794                 return -1;
795         }
796
797         /*
798          *      Add to that, the *new* list of clients.
799          */
800         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
801         if (generate_clients(buffer) < 0) {
802                 return -1;
803         }
804
805         /* old-style realms file */
806         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
807         DEBUG2("read_config_files:  reading realms");
808         if (read_realms_file(buffer) < 0) {
809                 radlog(L_ERR|L_CONS, "Errors reading realms");
810                 return -1;
811         }
812
813         /*
814          *      If there isn't any realms it isn't fatal..
815          */
816         snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
817         if (generate_realms(buffer) < 0) {
818                 return -1;
819         }
820
821         /*
822          *  Register the %{config:section.subsection} xlat function.
823          */
824         xlat_register("config", xlat_config, NULL);
825
826         /*
827          *      Set the libraries debugging flag to whatever the main
828          *      flag is.  Note that on a SIGHUP, to turn the debugging
829          *      off, we do other magic.
830          *
831          *      Increase the debug level, if the configuration file
832          *      says to, OR, if we're decreasing the debug from what it
833          *      was before, allow that, too.
834          */
835         if ((mainconfig.debug_level > debug_flag) ||
836             (mainconfig.debug_level <= old_debug_level)) {
837           debug_flag = mainconfig.debug_level;
838         }
839         librad_debug = debug_flag;
840         old_debug_level = mainconfig.debug_level;
841         
842         /*
843          *  Go update our behaviour, based on the configuration
844          *  changes.
845          */
846
847         /*  Get the current maximum for core files.  */
848         if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
849                 radlog(L_ERR|L_CONS, "Failed to get current core limit:  %s", strerror(errno));
850                 exit(1);
851         }
852
853         if (mainconfig.allow_core_dumps) {
854                 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
855                         radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
856                                         strerror(errno));
857                         exit(1);
858
859                         /*
860                          *  If we're running as a daemon, and core
861                          *  dumps are enabled, log that information.
862                          */
863                 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
864                         radlog(L_INFO|L_CONS, "Core dumps are enabled.");
865
866         } else if (!debug_flag) {
867                 /*
868                  *  Not debugging.  Set the core size to zero, to
869                  *  prevent security breaches.  i.e. People
870                  *  reading passwords from the 'core' file.
871                  */
872                 struct rlimit limits;
873
874                 limits.rlim_cur = 0;
875                 limits.rlim_max = core_limits.rlim_max;
876                 
877                 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
878                         radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
879                                         strerror(errno));
880                         exit(1);
881                 }
882         }
883
884         /*
885          *      The first time around, ensure that we can write to the
886          *      log directory.
887          */
888         if (!reload) {
889                 /*
890                  *      We need root to do mkdir() and chown(), so we
891                  *      do this before giving up root.
892                  */
893                 radlogdir_iswritable(mainconfig.uid_name); 
894         }
895         switch_users();
896
897         /*
898          *      Sanity check the configuration for internal
899          *      consistency.
900          */
901         if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
902                 mainconfig.reject_delay = mainconfig.cleanup_delay;
903         }
904
905         return 0;
906 }
907
908 /*
909  *      Free the configuration.
910  */
911 int free_mainconfig(void)
912 {
913         /*
914          *      Clean up the configuration data
915          *      structures.
916          */
917         cf_section_free(&mainconfig.config);
918         realm_free(mainconfig.realms);
919         clients_free(mainconfig.clients);
920
921         return 0;
922 }