import from HEAD:
[freeradius.git] / src / main / conffile.c
1 /*
2  * conffile.c   Read the radiusd.conf file.
3  *
4  *              Yep I should learn to use lex & yacc, or at least
5  *              write a decent parser. I know how to do that, really :)
6  *              miquels@cistron.nl
7  *
8  * Version:     $Id$
9  *
10  *   This program is free software; you can redistribute it and/or modify
11  *   it under the terms of the GNU General Public License as published by
12  *   the Free Software Foundation; either version 2 of the License, or
13  *   (at your option) any later version.
14  *
15  *   This program is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with this program; if not, write to the Free Software
22  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * Copyright 2000  The FreeRADIUS server project
25  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
26  * Copyright 2000  Alan DeKok <aland@ox.org>
27  */
28
29 #include "autoconf.h"
30 #include "libradius.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #ifdef HAVE_NETINET_IN_H
36 #       include <netinet/in.h>
37 #endif
38
39 #ifdef HAVE_SYS_STAT_H
40 #include        <sys/stat.h>
41 #endif
42
43 #include "radiusd.h"
44 #include "rad_assert.h"
45 #include "conffile.h"
46 #include "token.h"
47 #include "modules.h"
48
49 static const char rcsid[] =
50 "$Id$";
51
52 #define xstrdup strdup
53
54 typedef enum conf_type {
55         CONF_ITEM_PAIR,
56         CONF_ITEM_SECTION
57 } CONF_ITEM_TYPE;
58
59 struct conf_item {
60         struct conf_item *next;
61         struct conf_part *parent;
62         int lineno;
63         CONF_ITEM_TYPE type;
64 };
65 struct conf_pair {
66         CONF_ITEM item;
67         char *attr;
68         char *value;
69         LRAD_TOKEN operator;
70 };
71 struct conf_part {
72         CONF_ITEM item;
73         char *name1;
74         char *name2;
75         void *base;
76         const CONF_PARSER *variables;
77         struct conf_item *children;
78 };
79
80 /*
81  *      Isolate the scary casts in these tiny provably-safe functions
82  */
83 CONF_PAIR *cf_itemtopair(CONF_ITEM *ci)
84 {
85         if (ci == NULL)
86                 return NULL;
87         rad_assert(ci->type == CONF_ITEM_PAIR);
88         return (CONF_PAIR *)ci;
89 }
90 CONF_SECTION *cf_itemtosection(CONF_ITEM *ci)
91 {
92         if (ci == NULL)
93                 return NULL;
94         rad_assert(ci->type == CONF_ITEM_SECTION);
95         return (CONF_SECTION *)ci;
96 }
97 CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp)
98 {
99         if (cp == NULL)
100                 return NULL;
101         return (CONF_ITEM *)cp;
102 }
103 CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs)
104 {
105         if (cs == NULL)
106                 return NULL;
107         return (CONF_ITEM *)cs;
108 }
109
110 /*
111  *      Create a new CONF_PAIR
112  */
113 static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,
114                 LRAD_TOKEN operator, CONF_SECTION *parent)
115 {
116         CONF_PAIR *cp;
117
118         cp = (CONF_PAIR *)rad_malloc(sizeof(CONF_PAIR));
119         memset(cp, 0, sizeof(CONF_PAIR));
120         cp->item.type = CONF_ITEM_PAIR;
121         cp->item.parent = parent;
122         cp->attr = xstrdup(attr);
123         cp->value = xstrdup(value);
124         cp->operator = operator;
125
126         return cp;
127 }
128
129 /*
130  *      Free a CONF_PAIR
131  */
132 void cf_pair_free(CONF_PAIR **cp)
133 {
134         if (!cp || !*cp) return;
135
136         if ((*cp)->attr)
137                 free((*cp)->attr);
138         if ((*cp)->value)
139                 free((*cp)->value);
140
141 #ifndef NDEBUG
142         memset(*cp, 0, sizeof(*cp));
143 #endif
144         free(*cp);
145
146         *cp = NULL;
147 }
148
149 /*
150  *      Free strings we've parsed into data structures.
151  */
152 static void cf_section_parse_free(void *base, const CONF_PARSER *variables)
153 {
154         int i;
155
156         /*
157          *      Don't automatically free the strings if we're being
158          *      called from a module.
159          */
160         if (base || !variables) return;
161         
162         /*
163          *      Free up dynamically allocated string pointers.
164          */
165         for (i = 0; variables[i].name != NULL; i++) {
166                 char **p;
167
168                 if (variables[i].type != PW_TYPE_STRING_PTR) {
169                         continue;
170                 }
171
172                 /*
173                  *      Prefer the data, if it's there.
174                  *      Else use the base + offset.
175                  */
176                 if (!variables[i].data) {
177                         continue;
178                 }
179
180                 /*
181                  *      FIXME: Add base
182                  */
183                 p = (char **) (variables[i].data);
184
185
186                 free(*p);
187                 *p = NULL;
188         }
189 }
190
191
192 /*
193  *      Allocate a CONF_SECTION
194  */
195 static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,
196                                       CONF_SECTION *parent, const char *cf)
197 {
198         CONF_SECTION    *cs;
199
200         if (name1 == NULL || !name1[0])
201                 name1 = "main";
202
203         cs = (CONF_SECTION *)rad_malloc(sizeof(CONF_SECTION));
204         memset(cs, 0, sizeof(CONF_SECTION));
205         cs->item.type = CONF_ITEM_SECTION;
206         cs->item.parent = parent;
207         cs->name1 = strdup(name1);
208         cs->name2 = (name2 && *name2) ? xstrdup(name2) : NULL;
209
210         return cs;
211 }
212
213 /*
214  *      Free a CONF_SECTION
215  */
216 void cf_section_free(CONF_SECTION **cs)
217 {
218         CONF_ITEM       *ci, *next;
219
220         if (!cs || !*cs) return;
221
222         if ((*cs)->variables) {
223                 cf_section_parse_free((*cs)->base, (*cs)->variables);
224         }
225
226         for (ci = (*cs)->children; ci; ci = next) {
227                 next = ci->next;
228                 if (ci->type==CONF_ITEM_PAIR) {
229                         CONF_PAIR *pair = cf_itemtopair(ci);
230                         cf_pair_free(&pair);
231                 } else {
232                         CONF_SECTION *section = cf_itemtosection(ci);
233                         cf_section_free(&section);
234                 }
235         }
236
237         if ((*cs)->name1)
238                 free((*cs)->name1);
239         if ((*cs)->name2)
240                 free((*cs)->name2);
241
242         /*
243          * And free the section
244          */
245 #ifndef NDEBUG
246         memset(*cs, 0, sizeof(*cs));
247 #endif
248         free(*cs);
249
250         *cs = NULL;
251 }
252
253 /*
254  *      Add an item to a configuration section.
255  */
256 static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci_new)
257 {
258         CONF_ITEM *ci;
259
260         for (ci = cs->children; ci && ci->next; ci = ci->next)
261                 ;
262
263         if (ci == NULL)
264                 cs->children = ci_new;
265         else
266                 ci->next = ci_new;
267 }
268
269 /*
270  *      Expand the variables in an input string.
271  */
272 static const char *cf_expand_variables(const char *cf, int *lineno,
273                                        CONF_SECTION *outercs,
274                                        char *output, const char *input)
275 {
276         char *p;
277         const char *end, *ptr;
278         char name[8192];
279         CONF_SECTION *parentcs;
280
281         /*
282          *      Find the master parent conf section.
283          *      We can't use mainconfig.config, because we're in the
284          *      process of re-building it, and it isn't set up yet...
285          */
286         for (parentcs = outercs;
287              parentcs->item.parent != NULL;
288              parentcs = parentcs->item.parent) {
289                 /* do nothing */
290         }
291
292         p = output;
293         ptr = input;
294         while (*ptr) {
295                 /*
296                  *      Ignore anything other than "${"
297                  */
298                 if ((*ptr == '$') && (ptr[1] == '{')) {
299                         int up;
300                         CONF_PAIR *cp;
301                         CONF_SECTION *cs;
302
303                         /*
304                          *      Look for trailing '}', and log a
305                          *      warning for anything that doesn't match,
306                          *      and exit with a fatal error.
307                          */
308                         end = strchr(ptr, '}');
309                         if (end == NULL) {
310                                 *p = '\0';
311                                 radlog(L_INFO, "%s[%d]: Variable expansion missing }",
312                                        cf, *lineno);
313                                 return NULL;
314                         }
315
316                         ptr += 2;
317
318                         cp = NULL;
319                         up = 0;
320
321                         /*
322                          *      ${.foo} means "foo from the current section"
323                          */
324                         if (*ptr == '.') {
325                                 up = 1;
326                                 cs = outercs;
327                                 ptr++;
328
329                                 /*
330                                  *      ${..foo} means "foo from the section
331                                  *      enclosing this section" (etc.)
332                                  */
333                                 while (*ptr == '.') {
334                                         if (cs->item.parent)
335                                                 cs = cs->item.parent;
336                                         ptr++;
337                                 }
338
339                         } else {
340                                 const char *q;
341                                 /*
342                                  *      ${foo} is local, with
343                                  *      main as lower priority
344                                  */
345                                 cs = outercs;
346
347                                 /*
348                                  *      ${foo.bar.baz} is always rooted
349                                  *      from the top.
350                                  */
351                                 for (q = ptr; *q && q != end; q++) {
352                                         if (*q == '.') {
353                                                 cs = parentcs;
354                                                 up = 1;
355                                                 break;
356                                         }
357                                 }
358                         }
359
360                         while (cp == NULL) {
361                                 char *q;
362                                 /*
363                                  *      Find the next section.
364                                  */
365                                 for (q = name;
366                                      (*ptr != 0) && (*ptr != '.') &&
367                                              (ptr != end);
368                                      q++, ptr++) {
369                                         *q = *ptr;
370                                 }
371                                 *q = '\0';
372
373                                 /*
374                                  *      The character is a '.', find a
375                                  *      section (as the user has given
376                                  *      us a subsection to find)
377                                  */
378                                 if (*ptr == '.') {
379                                         CONF_SECTION *next;
380
381                                         ptr++;  /* skip the period */
382
383                                         /*
384                                          *      Find the sub-section.
385                                          */
386                                         next = cf_section_sub_find(cs, name);
387                                         if (next == NULL) {
388                                                 radlog(L_ERR, "config: No such section %s in variable %s", name, input);
389                                                 return NULL;
390                                         }
391                                         cs = next;
392
393                                 } else { /* no period, must be a conf-part */
394                                         /*
395                                          *      Find in the current referenced
396                                          *      section.
397                                          */
398                                         cp = cf_pair_find(cs, name);
399                                         if (cp == NULL) {
400                                                 /*
401                                                  *      It it was NOT ${..foo}
402                                                  *      then look in the
403                                                  *      top-level config items.
404                                                  */
405                                                 if (!up) cp = cf_pair_find(parentcs, name);
406                                         }
407                                         if (cp == NULL) {
408                                                 radlog(L_ERR, "config: No such entry %s for string %s", name, input);
409                                                 return NULL;
410                                         }
411                                 }
412                         } /* until cp is non-NULL */
413
414                         /*
415                          *  Substitute the value of the variable.
416                          */
417                         strcpy(p, cp->value);
418                         p += strlen(p);
419                         ptr = end + 1;
420
421                 } else if (memcmp(ptr, "$ENV{", 5) == 0) {
422                         char *env;
423
424                         ptr += 5;
425
426                         /*
427                          *      Look for trailing '}', and log a
428                          *      warning for anything that doesn't match,
429                          *      and exit with a fatal error.
430                          */
431                         end = strchr(ptr, '}');
432                         if (end == NULL) {
433                                 *p = '\0';
434                                 radlog(L_INFO, "%s[%d]: Environment variable expansion missing }",
435                                        cf, *lineno);
436                                 return NULL;
437                         }
438
439                         memcpy(name, ptr, end - ptr);
440                         name[end - ptr] = '\0';
441
442                         /*
443                          *      Get the environment variable.
444                          *      If none exists, then make it an empty string.
445                          */
446                         env = getenv(name);
447                         if (env == NULL) {
448                                 *name = '\0';
449                                 env = name;
450                         }
451
452                         strcpy(p, env);
453                         p += strlen(p);
454                         ptr = end + 1;
455
456                 } else {
457                         /*
458                          *      Copy it over verbatim.
459                          */
460                         *(p++) = *(ptr++);
461                 }
462         } /* loop over all of the input string. */
463
464         *p = '\0';
465
466         return output;
467 }
468
469
470 /*
471  *      Parse a configuration section into user-supplied variables.
472  */
473 int cf_section_parse(CONF_SECTION *cs, void *base,
474                      const CONF_PARSER *variables)
475 {
476         int i;
477         int rcode;
478         char **q;
479         CONF_PAIR *cp;
480         CONF_SECTION *subsection;
481         uint32_t ipaddr;
482         char buffer[8192];
483         const char *value;
484         void *data;
485
486         /*
487          *      Handle the user-supplied variables.
488          */
489         for (i = 0; variables[i].name != NULL; i++) {
490                 value = variables[i].dflt;
491                 if (variables[i].data) {
492                         data = variables[i].data; /* prefer this. */
493                 } else if (base) {
494                         data = ((char *)base) + variables[i].offset;
495                 } else {
496                         data = variables[i].data;
497                 }
498
499                 cp = cf_pair_find(cs, variables[i].name);
500                 if (cp) {
501                         value = cp->value;
502                 }
503
504                 switch (variables[i].type)
505                 {
506                 case PW_TYPE_SUBSECTION:
507                         subsection = cf_section_sub_find(cs,variables[i].name);
508
509                         /*
510                          *      If the configuration section is NOT there,
511                          *      then ignore it.
512                          *
513                          *      FIXME! This is probably wrong... we should
514                          *      probably set the items to their default values.
515                          */
516                         if (subsection == NULL) {
517                                 break;
518                         }
519
520                         rcode = cf_section_parse(subsection, base,
521                                                  (CONF_PARSER *) data);
522                         if (rcode < 0) {
523                                 cf_section_parse_free(base, variables);
524                                 return -1;
525                         }
526                         break;
527
528                 case PW_TYPE_BOOLEAN:
529                         /*
530                          *      Allow yes/no and on/off
531                          */
532                         if ((strcasecmp(value, "yes") == 0) ||
533                                         (strcasecmp(value, "on") == 0)) {
534                                 *(int *)data = 1;
535                         } else if ((strcasecmp(value, "no") == 0) ||
536                                                 (strcasecmp(value, "off") == 0)) {
537                                 *(int *)data = 0;
538                         } else {
539                                 *(int *)data = 0;
540                                 radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, variables[i].name);
541                                 cf_section_parse_free(base, variables);
542                                 return -1;
543                         }
544                         DEBUG2(" %s: %s = %s",
545                                         cs->name1,
546                                         variables[i].name,
547                                         value);
548                         break;
549
550                 case PW_TYPE_INTEGER:
551                         *(int *)data = strtol(value, 0, 0);
552                         DEBUG2(" %s: %s = %d",
553                                         cs->name1,
554                                         variables[i].name,
555                                         *(int *)data);
556                         break;
557
558                 case PW_TYPE_STRING_PTR:
559                         q = (char **) data;
560                         if (*q != NULL) {
561                                 free(*q);
562                         }
563
564                         /*
565                          *      Expand variables while parsing,
566                          *      but ONLY expand ones which haven't already
567                          *      been expanded.
568                          */
569                         if (value && (value == variables[i].dflt)) {
570                                 value = cf_expand_variables("?",
571                                                             &cs->item.lineno,
572                                                             cs, buffer, value);
573                                 if (!value) {
574                                         cf_section_parse_free(base, variables);
575                                         return -1;
576                                 }
577                         }
578
579                         DEBUG2(" %s: %s = \"%s\"",
580                                         cs->name1,
581                                         variables[i].name,
582                                         value ? value : "(null)");
583                         *q = value ? strdup(value) : NULL;
584                         break;
585
586                 case PW_TYPE_IPADDR:
587                         /*
588                          *      Allow '*' as any address
589                          */
590                         if (strcmp(value, "*") == 0) {
591                                 *(uint32_t *) data = 0;
592                                 break;
593                         }
594                         ipaddr = ip_getaddr(value);
595                         if (ipaddr == 0) {
596                                 radlog(L_ERR, "Can't find IP address for host %s", value);
597                                 cf_section_parse_free(base, variables);
598                                 return -1;
599                         }
600                         DEBUG2(" %s: %s = %s IP address [%s]",
601                                         cs->name1,
602                                         variables[i].name,
603                                         value, ip_ntoa(buffer, ipaddr));
604                         *(uint32_t *) data = ipaddr;
605                         break;
606
607                 default:
608                         radlog(L_ERR, "type %d not supported yet", variables[i].type);
609                         cf_section_parse_free(base, variables);
610                         return -1;
611                         break;
612                 } /* switch over variable type */
613         } /* for all variables in the configuration section */
614
615         cs->base = base;
616         cs->variables = variables;
617
618         return 0;
619 }
620
621
622 /*
623  *      Read a part of the config file.
624  */
625 static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
626                                      const char *name1, const char *name2,
627                                      CONF_SECTION *parent)
628 {
629         CONF_SECTION *cs, *css;
630         CONF_PAIR *cpn;
631         char *ptr;
632         const char *value;
633         char buf[8192];
634         char buf1[8192];
635         char buf2[8192];
636         char buf3[8192];
637         int t1, t2, t3;
638         char *cbuf = buf;
639         int len;
640
641         /*
642          *      Ensure that the user can't add CONF_SECTIONs
643          *      with 'internal' names;
644          */
645         if ((name1 != NULL) && (name1[0] == '_')) {
646                 radlog(L_ERR, "%s[%d]: Illegal configuration section name",
647                         cf, *lineno);
648                 return NULL;
649         }
650
651         /*
652          *      Allocate new section.
653          */
654         cs = cf_section_alloc(name1, name2, parent, cf);
655         cs->item.lineno = *lineno;
656
657         /*
658          *      Read, checking for line continuations ('\\' at EOL)
659          */
660         for (;;) {
661                 int eof;
662
663                 /*
664                  *      Get data, and remember if we are at EOF.
665                  */
666                 eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL);
667                 (*lineno)++;
668
669                 len = strlen(cbuf);
670
671                 /*
672                  *      We've filled the buffer, and there isn't
673                  *      a CR in it.  Die!
674                  */
675                 if (cbuf[len - 1] != '\n') {
676                         radlog(L_ERR, "%s[%d]: Line too long",
677                                cf, *lineno);
678                         cf_section_free(&cs);
679                         return NULL;
680                 }
681
682                 /*
683                  *  Check for continuations.
684                  */
685                 if (cbuf[len - 1] == '\n') len--;
686
687                 /*
688                  *      Last character is '\\'.  Over-write it,
689                  *      and read another line.
690                  */
691                 if ((len > 0) && (cbuf[len - 1] == '\\')) {
692                         if (len >= (sizeof(buf) - 5)) {
693                                 radlog(L_ERR, "%s[%d]: Line too long",
694                                        cf, *lineno);
695                                 cf_section_free(&cs);
696                                 return NULL;
697                         }
698
699                         cbuf[len - 1] = '\0';
700                         cbuf += len - 1;
701                         continue;
702                 }
703
704                 /*
705                  *  We're at EOF, and haven't read anything.  Stop.
706                  */
707                 if (eof && (cbuf == buf)) {
708                         break;
709                 }
710
711                 ptr = cbuf = buf;
712                 t1 = gettoken(&ptr, buf1, sizeof(buf1));
713
714                 /*
715                  *      Skip comments and blank lines immediately.
716                  */
717                 if ((*buf1 == '#') || (*buf1 == '\0')) {
718                         continue;
719                 }
720
721                 /*
722                  *      Allow for $INCLUDE files
723                  *
724                  *      This *SHOULD* work for any level include.
725                  *      I really really really hate this file.  -cparker
726                  */
727                 if (strcasecmp(buf1, "$INCLUDE") == 0) {
728
729                         CONF_SECTION      *is;
730
731                         t2 = getword(&ptr, buf2, sizeof(buf2));
732
733                         value = cf_expand_variables(cf, lineno, cs, buf, buf2);
734                         if (value == NULL) {
735                                 cf_section_free(&cs);
736                                 return NULL;
737                         }
738
739                         DEBUG2( "Config:   including file: %s", value );
740
741                         if ((is = conf_read(cf, *lineno, value, cs)) == NULL) {
742                                 cf_section_free(&cs);
743                                 return NULL;
744                         }
745
746                         /*
747                          *      Add the included conf to our CONF_SECTION
748                          */
749                         if (is != NULL) {
750                                 if (is->children != NULL) {
751                                         CONF_ITEM *ci;
752
753                                         /*
754                                          *      Re-write the parent of the
755                                          *      moved children to be the
756                                          *      upper-layer section.
757                                          */
758                                         for (ci = is->children; ci; ci = ci->next) {
759                                                 ci->parent = cs;
760                                         }
761
762                                         /*
763                                          *      If there are children, then
764                                          *      move them up a layer.
765                                          */
766                                         if (is->children) {
767                                                 cf_item_add(cs, is->children);
768                                         }
769                                         is->children = NULL;
770                                 }
771                                 /*
772                                  *      Always free the section for the
773                                  *      $INCLUDEd file.
774                                  */
775                                 cf_section_free(&is);
776                         }
777
778                         continue;
779                 }
780
781                 /*
782                  *      No '=': must be a section or sub-section.
783                  */
784                 if (strchr(ptr, '=') == NULL) {
785                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
786                         t3 = gettoken(&ptr, buf3, sizeof(buf3));
787                 } else {
788                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
789                         t3 = getword(&ptr, buf3, sizeof(buf3));
790                 }
791
792                 /*
793                  *      See if it's the end of a section.
794                  */
795                 if (t1 == T_RCBRACE) {
796                         if (name1 == NULL || buf2[0]) {
797                                 radlog(L_ERR, "%s[%d]: Unexpected end of section",
798                                                 cf, *lineno);
799                                 cf_section_free(&cs);
800                                 return NULL;
801                         }
802                         return cs;
803                 }
804
805                 /*
806                  * Perhaps a subsection.
807                  */
808                 if (t2 == T_LCBRACE || t3 == T_LCBRACE) {
809                         css = cf_section_read(cf, lineno, fp, buf1,
810                                               t2==T_LCBRACE ? NULL : buf2, cs);
811                         if (css == NULL) {
812                                 cf_section_free(&cs);
813                                 return NULL;
814                         }
815                         cf_item_add(cs, cf_sectiontoitem(css));
816
817                         continue;
818                 }
819
820                 /*
821                  *      Ignore semi-colons.
822                  */
823                 if (*buf2 == ';')
824                         *buf2 = '\0';
825
826                 /*
827                  *      Must be a normal attr = value line.
828                  */
829                 if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) {
830                         t2 = T_OP_EQ;
831                 } else if (buf1[0] == 0 || buf2[0] == 0 ||
832                            (t2 < T_EQSTART || t2 > T_EQEND)) {
833                         radlog(L_ERR, "%s[%d]: Line is not in 'attribute = value' format",
834                                         cf, *lineno);
835                         cf_section_free(&cs);
836                         return NULL;
837                 }
838
839                 /*
840                  *      Ensure that the user can't add CONF_PAIRs
841                  *      with 'internal' names;
842                  */
843                 if (buf1[0] == '_') {
844                         radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"",
845                                         cf, *lineno, buf1);
846                         cf_section_free(&cs);
847                         return NULL;
848                 }
849
850                 /*
851                  *      Handle variable substitution via ${foo}
852                  */
853                 value = cf_expand_variables(cf, lineno, cs, buf, buf3);
854                 if (!value) {
855                         cf_section_free(&cs);
856                         return NULL;
857                 }
858
859
860                 /*
861                  *      Add this CONF_PAIR to our CONF_SECTION
862                  */
863                 cpn = cf_pair_alloc(buf1, value, t2, parent);
864                 cpn->item.lineno = *lineno;
865                 cf_item_add(cs, cf_pairtoitem(cpn));
866         }
867
868         /*
869          *      See if EOF was unexpected ..
870          */
871         if (name1 != NULL) {
872                 radlog(L_ERR, "%s[%d]: Unexpected end of file", cf, *lineno);
873                 cf_section_free(&cs);
874                 return NULL;
875         }
876
877         return cs;
878 }
879
880 /*
881  *      Read the config file.
882  */
883 CONF_SECTION *conf_read(const char *fromfile, int fromline,
884                         const char *conffile, CONF_SECTION *parent)
885 {
886         FILE            *fp;
887         int             lineno = 0;
888         CONF_SECTION    *cs;
889         struct stat     statbuf;
890         char            buf[8192];
891
892         buf[0] = '\0';
893         if (fromfile) {
894                 snprintf(buf, sizeof(buf), "%s[%d]: ", fromfile, fromline);
895         }
896
897         if (stat(conffile, &statbuf) == 0) {
898                 if ((statbuf.st_mode & S_IWOTH) != 0) {
899                         radlog(L_ERR|L_CONS, "%sConfiguration file %s is globally writable.  Refusing to start due to insecure configuration.",
900                                buf[0] ? buf : "", conffile);
901                         return NULL;
902                 }
903
904                 if (0 && (statbuf.st_mode & S_IROTH) != 0) {
905                         radlog(L_ERR|L_CONS, "%sConfiguration file %s is globally readable.  Refusing to start due to insecure configuration.",
906                                buf[0] ? buf : "", conffile);
907                         return NULL;
908                 }
909         }
910
911         if ((fp = fopen(conffile, "r")) == NULL) {
912                 radlog(L_ERR|L_CONS, "%sUnable to open file \"%s\": %s",
913                        buf[0] ? buf : "", conffile, strerror(errno));
914                 return NULL;
915         }
916
917         cs = cf_section_read(conffile, &lineno, fp, NULL, NULL, parent);
918
919         fclose(fp);
920
921         return cs;
922 }
923
924
925 /*
926  * Return a CONF_PAIR within a CONF_SECTION.
927  */
928 CONF_PAIR *cf_pair_find(CONF_SECTION *section, const char *name)
929 {
930         CONF_ITEM       *ci;
931
932         if (section == NULL) {
933                 section = mainconfig.config;
934         }
935
936         for (ci = section->children; ci; ci = ci->next) {
937                 if (ci->type != CONF_ITEM_PAIR)
938                         continue;
939                 if (name == NULL || strcmp(cf_itemtopair(ci)->attr, name) == 0)
940                         break;
941         }
942
943         return cf_itemtopair(ci);
944 }
945
946 /*
947  * Return the attr of a CONF_PAIR
948  */
949
950 char *cf_pair_attr(CONF_PAIR *pair)
951 {
952         return (pair ? pair->attr : NULL);
953 }
954
955 /*
956  * Return the value of a CONF_PAIR
957  */
958
959 char *cf_pair_value(CONF_PAIR *pair)
960 {
961         return (pair ? pair->value : NULL);
962 }
963
964 /*
965  * Return the first label of a CONF_SECTION
966  */
967
968 char *cf_section_name1(CONF_SECTION *section)
969 {
970         return (section ? section->name1 : NULL);
971 }
972
973 /*
974  * Return the second label of a CONF_SECTION
975  */
976
977 char *cf_section_name2(CONF_SECTION *section)
978 {
979         return (section ? section->name2 : NULL);
980 }
981
982 /*
983  * Find a value in a CONF_SECTION
984  */
985 char *cf_section_value_find(CONF_SECTION *section, const char *attr)
986 {
987         CONF_PAIR       *cp;
988
989         cp = cf_pair_find(section, attr);
990
991         return (cp ? cp->value : NULL);
992 }
993
994 /*
995  * Return the next pair after a CONF_PAIR
996  * with a certain name (char *attr) If the requested
997  * attr is NULL, any attr matches.
998  */
999
1000 CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *attr)
1001 {
1002         CONF_ITEM       *ci;
1003
1004         /*
1005          * If pair is NULL this must be a first time run
1006          * Find the pair with correct name
1007          */
1008
1009         if (pair == NULL){
1010                 return cf_pair_find(section, attr);
1011         }
1012
1013         ci = cf_pairtoitem(pair)->next;
1014
1015         for (; ci; ci = ci->next) {
1016                 if (ci->type != CONF_ITEM_PAIR)
1017                         continue;
1018                 if (attr == NULL || strcmp(cf_itemtopair(ci)->attr, attr) == 0)
1019                         break;
1020         }
1021
1022         return cf_itemtopair(ci);
1023 }
1024
1025 /*
1026  * Find a CONF_SECTION, or return the root if name is NULL
1027  */
1028
1029 CONF_SECTION *cf_section_find(const char *name)
1030 {
1031         if (name)
1032                 return cf_section_sub_find(mainconfig.config, name);
1033         else
1034                 return mainconfig.config;
1035 }
1036
1037 /*
1038  * Find a sub-section in a section
1039  */
1040
1041 CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name)
1042 {
1043         CONF_ITEM *ci;
1044
1045         for (ci = section->children; ci; ci = ci->next) {
1046                 if (ci->type != CONF_ITEM_SECTION)
1047                         continue;
1048                 if (strcmp(cf_itemtosection(ci)->name1, name) == 0)
1049                         break;
1050         }
1051
1052         return cf_itemtosection(ci);
1053
1054 }
1055
1056 /*
1057  * Return the next subsection after a CONF_SECTION
1058  * with a certain name1 (char *name1). If the requested
1059  * name1 is NULL, any name1 matches.
1060  */
1061
1062 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
1063                 CONF_SECTION *subsection,
1064                 const char *name1)
1065 {
1066         CONF_ITEM       *ci;
1067
1068         /*
1069          * If subsection is NULL this must be a first time run
1070          * Find the subsection with correct name
1071          */
1072
1073         if (subsection == NULL){
1074                 ci = section->children;
1075         } else {
1076                 ci = cf_sectiontoitem(subsection)->next;
1077         }
1078
1079         for (; ci; ci = ci->next) {
1080                 if (ci->type != CONF_ITEM_SECTION)
1081                         continue;
1082                 if ((name1 == NULL) ||
1083                                 (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
1084                         break;
1085         }
1086
1087         return cf_itemtosection(ci);
1088 }
1089
1090 /*
1091  * Return the next item after a CONF_ITEM.
1092  */
1093
1094 CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item)
1095 {
1096         /*
1097          * If item is NULL this must be a first time run
1098          * Return the first item
1099          */
1100
1101         if (item == NULL) {
1102                 return section->children;
1103         } else {
1104                 return item->next;
1105         }
1106 }
1107
1108 int cf_section_lineno(CONF_SECTION *section)
1109 {
1110         return cf_sectiontoitem(section)->lineno;
1111 }
1112
1113 int cf_pair_lineno(CONF_PAIR *pair)
1114 {
1115         return cf_pairtoitem(pair)->lineno;
1116 }
1117
1118 int cf_item_is_section(CONF_ITEM *item)
1119 {
1120         return item->type == CONF_ITEM_SECTION;
1121 }
1122 int cf_item_is_pair(CONF_ITEM *item)
1123 {
1124         return item->type == CONF_ITEM_PAIR;
1125 }
1126
1127
1128 #if 0
1129 /*
1130  * JMG dump_config tries to dump the config structure in a readable format
1131  *
1132 */
1133
1134 static int dump_config_section(CONF_SECTION *cs, int indent)
1135 {
1136         CONF_SECTION    *scs;
1137         CONF_PAIR       *cp;
1138         CONF_ITEM       *ci;
1139
1140         /* The DEBUG macro doesn't let me
1141          *   for(i=0;i<indent;++i) debugputchar('\t');
1142          * so I had to get creative. --Pac. */
1143
1144         for (ci = cs->children; ci; ci = ci->next) {
1145                 if (ci->type == CONF_ITEM_PAIR) {
1146                         cp=cf_itemtopair(ci);
1147                         DEBUG("%.*s%s = %s",
1148                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1149                                 cp->attr, cp->value);
1150                 } else {
1151                         scs=cf_itemtosection(ci);
1152                         DEBUG("%.*s%s %s%s{",
1153                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1154                                 scs->name1,
1155                                 scs->name2 ? scs->name2 : "",
1156                                 scs->name2 ?  " " : "");
1157                         dump_config_section(scs, indent+1);
1158                         DEBUG("%.*s}",
1159                                 indent, "\t\t\t\t\t\t\t\t\t\t\t");
1160                 }
1161         }
1162
1163         return 0;
1164 }
1165
1166 int dump_config(void)
1167 {
1168         return dump_config_section(mainconfig.config, 0);
1169 }
1170 #endif