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