Don't allow escapes (\\) if the input buffer is full
[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 ((len >= (sizeof(buf) - 1)) &&
676                     (((cbuf[len - 1] != '\n')) ||
677                      (cbuf[len - 1] == '\\'))) {
678                         radlog(L_ERR, "%s[%d]: Line too long",
679                                cf, *lineno);
680                         cf_section_free(&cs);
681                         return NULL;
682                 }
683
684                 /*
685                  *  Check for continuations.
686                  */
687                 if (cbuf[len - 1] == '\n') len--;
688
689                 /*
690                  *      Last character is '\\'.  Over-write it,
691                  *      and read another line.
692                  */
693                 if ((len > 0) && (cbuf[len - 1] == '\\')) {
694                         cbuf[len - 1] = '\0';
695                         cbuf += len - 1;
696                         continue;
697                 }
698
699                 /*
700                  *  We're at EOF, and haven't read anything.  Stop.
701                  */
702                 if (eof && (cbuf == buf)) {
703                         break;
704                 }
705
706                 ptr = cbuf = buf;
707                 t1 = gettoken(&ptr, buf1, sizeof(buf1));
708
709                 /*
710                  *      Skip comments and blank lines immediately.
711                  */
712                 if ((*buf1 == '#') || (*buf1 == '\0')) {
713                         continue;
714                 }
715
716                 /*
717                  *      Allow for $INCLUDE files
718                  *
719                  *      This *SHOULD* work for any level include.
720                  *      I really really really hate this file.  -cparker
721                  */
722                 if (strcasecmp(buf1, "$INCLUDE") == 0) {
723
724                         CONF_SECTION      *is;
725
726                         t2 = getword(&ptr, buf2, sizeof(buf2));
727
728                         value = cf_expand_variables(cf, lineno, cs, buf, buf2);
729                         if (value == NULL) {
730                                 cf_section_free(&cs);
731                                 return NULL;
732                         }
733
734                         DEBUG2( "Config:   including file: %s", value );
735
736                         if ((is = conf_read(cf, *lineno, value, cs)) == NULL) {
737                                 cf_section_free(&cs);
738                                 return NULL;
739                         }
740
741                         /*
742                          *      Add the included conf to our CONF_SECTION
743                          */
744                         if (is != NULL) {
745                                 if (is->children != NULL) {
746                                         CONF_ITEM *ci;
747
748                                         /*
749                                          *      Re-write the parent of the
750                                          *      moved children to be the
751                                          *      upper-layer section.
752                                          */
753                                         for (ci = is->children; ci; ci = ci->next) {
754                                                 ci->parent = cs;
755                                         }
756
757                                         /*
758                                          *      If there are children, then
759                                          *      move them up a layer.
760                                          */
761                                         if (is->children) {
762                                                 cf_item_add(cs, is->children);
763                                         }
764                                         is->children = NULL;
765                                 }
766                                 /*
767                                  *      Always free the section for the
768                                  *      $INCLUDEd file.
769                                  */
770                                 cf_section_free(&is);
771                         }
772
773                         continue;
774                 }
775
776                 /*
777                  *      No '=': must be a section or sub-section.
778                  */
779                 if (strchr(ptr, '=') == NULL) {
780                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
781                         t3 = gettoken(&ptr, buf3, sizeof(buf3));
782                 } else {
783                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
784                         t3 = getword(&ptr, buf3, sizeof(buf3));
785                 }
786
787                 /*
788                  *      See if it's the end of a section.
789                  */
790                 if (t1 == T_RCBRACE) {
791                         if (name1 == NULL || buf2[0]) {
792                                 radlog(L_ERR, "%s[%d]: Unexpected end of section",
793                                                 cf, *lineno);
794                                 cf_section_free(&cs);
795                                 return NULL;
796                         }
797                         return cs;
798                 }
799
800                 /*
801                  * Perhaps a subsection.
802                  */
803                 if (t2 == T_LCBRACE || t3 == T_LCBRACE) {
804                         css = cf_section_read(cf, lineno, fp, buf1,
805                                               t2==T_LCBRACE ? NULL : buf2, cs);
806                         if (css == NULL) {
807                                 cf_section_free(&cs);
808                                 return NULL;
809                         }
810                         cf_item_add(cs, cf_sectiontoitem(css));
811
812                         continue;
813                 }
814
815                 /*
816                  *      Ignore semi-colons.
817                  */
818                 if (*buf2 == ';')
819                         *buf2 = '\0';
820
821                 /*
822                  *      Must be a normal attr = value line.
823                  */
824                 if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) {
825                         t2 = T_OP_EQ;
826                 } else if (buf1[0] == 0 || buf2[0] == 0 ||
827                            (t2 < T_EQSTART || t2 > T_EQEND)) {
828                         radlog(L_ERR, "%s[%d]: Line is not in 'attribute = value' format",
829                                         cf, *lineno);
830                         cf_section_free(&cs);
831                         return NULL;
832                 }
833
834                 /*
835                  *      Ensure that the user can't add CONF_PAIRs
836                  *      with 'internal' names;
837                  */
838                 if (buf1[0] == '_') {
839                         radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"",
840                                         cf, *lineno, buf1);
841                         cf_section_free(&cs);
842                         return NULL;
843                 }
844
845                 /*
846                  *      Handle variable substitution via ${foo}
847                  */
848                 value = cf_expand_variables(cf, lineno, cs, buf, buf3);
849                 if (!value) {
850                         cf_section_free(&cs);
851                         return NULL;
852                 }
853
854
855                 /*
856                  *      Add this CONF_PAIR to our CONF_SECTION
857                  */
858                 cpn = cf_pair_alloc(buf1, value, t2, parent);
859                 cpn->item.lineno = *lineno;
860                 cf_item_add(cs, cf_pairtoitem(cpn));
861         }
862
863         /*
864          *      See if EOF was unexpected ..
865          */
866         if (name1 != NULL) {
867                 radlog(L_ERR, "%s[%d]: Unexpected end of file", cf, *lineno);
868                 cf_section_free(&cs);
869                 return NULL;
870         }
871
872         return cs;
873 }
874
875 /*
876  *      Read the config file.
877  */
878 CONF_SECTION *conf_read(const char *fromfile, int fromline,
879                         const char *conffile, CONF_SECTION *parent)
880 {
881         FILE            *fp;
882         int             lineno = 0;
883         CONF_SECTION    *cs;
884         struct stat     statbuf;
885         char            buf[8192];
886
887         buf[0] = '\0';
888         if (fromfile) {
889                 snprintf(buf, sizeof(buf), "%s[%d]: ", fromfile, fromline);
890         }
891
892         if (stat(conffile, &statbuf) == 0) {
893                 if ((statbuf.st_mode & S_IWOTH) != 0) {
894                         radlog(L_ERR|L_CONS, "%sConfiguration file %s is globally writable.  Refusing to start due to insecure configuration.",
895                                buf[0] ? buf : "", conffile);
896                         return NULL;
897                 }
898
899                 if (0 && (statbuf.st_mode & S_IROTH) != 0) {
900                         radlog(L_ERR|L_CONS, "%sConfiguration file %s is globally readable.  Refusing to start due to insecure configuration.",
901                                buf[0] ? buf : "", conffile);
902                         return NULL;
903                 }
904         }
905
906         if ((fp = fopen(conffile, "r")) == NULL) {
907                 radlog(L_ERR|L_CONS, "%sUnable to open file \"%s\": %s",
908                        buf[0] ? buf : "", conffile, strerror(errno));
909                 return NULL;
910         }
911
912         cs = cf_section_read(conffile, &lineno, fp, NULL, NULL, parent);
913
914         fclose(fp);
915
916         return cs;
917 }
918
919
920 /*
921  * Return a CONF_PAIR within a CONF_SECTION.
922  */
923 CONF_PAIR *cf_pair_find(CONF_SECTION *section, const char *name)
924 {
925         CONF_ITEM       *ci;
926
927         if (section == NULL) {
928                 section = mainconfig.config;
929         }
930
931         for (ci = section->children; ci; ci = ci->next) {
932                 if (ci->type != CONF_ITEM_PAIR)
933                         continue;
934                 if (name == NULL || strcmp(cf_itemtopair(ci)->attr, name) == 0)
935                         break;
936         }
937
938         return cf_itemtopair(ci);
939 }
940
941 /*
942  * Return the attr of a CONF_PAIR
943  */
944
945 char *cf_pair_attr(CONF_PAIR *pair)
946 {
947         return (pair ? pair->attr : NULL);
948 }
949
950 /*
951  * Return the value of a CONF_PAIR
952  */
953
954 char *cf_pair_value(CONF_PAIR *pair)
955 {
956         return (pair ? pair->value : NULL);
957 }
958
959 /*
960  * Return the first label of a CONF_SECTION
961  */
962
963 char *cf_section_name1(CONF_SECTION *section)
964 {
965         return (section ? section->name1 : NULL);
966 }
967
968 /*
969  * Return the second label of a CONF_SECTION
970  */
971
972 char *cf_section_name2(CONF_SECTION *section)
973 {
974         return (section ? section->name2 : NULL);
975 }
976
977 /*
978  * Find a value in a CONF_SECTION
979  */
980 char *cf_section_value_find(CONF_SECTION *section, const char *attr)
981 {
982         CONF_PAIR       *cp;
983
984         cp = cf_pair_find(section, attr);
985
986         return (cp ? cp->value : NULL);
987 }
988
989 /*
990  * Return the next pair after a CONF_PAIR
991  * with a certain name (char *attr) If the requested
992  * attr is NULL, any attr matches.
993  */
994
995 CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *attr)
996 {
997         CONF_ITEM       *ci;
998
999         /*
1000          * If pair is NULL this must be a first time run
1001          * Find the pair with correct name
1002          */
1003
1004         if (pair == NULL){
1005                 return cf_pair_find(section, attr);
1006         }
1007
1008         ci = cf_pairtoitem(pair)->next;
1009
1010         for (; ci; ci = ci->next) {
1011                 if (ci->type != CONF_ITEM_PAIR)
1012                         continue;
1013                 if (attr == NULL || strcmp(cf_itemtopair(ci)->attr, attr) == 0)
1014                         break;
1015         }
1016
1017         return cf_itemtopair(ci);
1018 }
1019
1020 /*
1021  * Find a CONF_SECTION, or return the root if name is NULL
1022  */
1023
1024 CONF_SECTION *cf_section_find(const char *name)
1025 {
1026         if (name)
1027                 return cf_section_sub_find(mainconfig.config, name);
1028         else
1029                 return mainconfig.config;
1030 }
1031
1032 /*
1033  * Find a sub-section in a section
1034  */
1035
1036 CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name)
1037 {
1038         CONF_ITEM *ci;
1039
1040         for (ci = section->children; ci; ci = ci->next) {
1041                 if (ci->type != CONF_ITEM_SECTION)
1042                         continue;
1043                 if (strcmp(cf_itemtosection(ci)->name1, name) == 0)
1044                         break;
1045         }
1046
1047         return cf_itemtosection(ci);
1048
1049 }
1050
1051 /*
1052  * Return the next subsection after a CONF_SECTION
1053  * with a certain name1 (char *name1). If the requested
1054  * name1 is NULL, any name1 matches.
1055  */
1056
1057 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
1058                 CONF_SECTION *subsection,
1059                 const char *name1)
1060 {
1061         CONF_ITEM       *ci;
1062
1063         /*
1064          * If subsection is NULL this must be a first time run
1065          * Find the subsection with correct name
1066          */
1067
1068         if (subsection == NULL){
1069                 ci = section->children;
1070         } else {
1071                 ci = cf_sectiontoitem(subsection)->next;
1072         }
1073
1074         for (; ci; ci = ci->next) {
1075                 if (ci->type != CONF_ITEM_SECTION)
1076                         continue;
1077                 if ((name1 == NULL) ||
1078                                 (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
1079                         break;
1080         }
1081
1082         return cf_itemtosection(ci);
1083 }
1084
1085 /*
1086  * Return the next item after a CONF_ITEM.
1087  */
1088
1089 CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item)
1090 {
1091         /*
1092          * If item is NULL this must be a first time run
1093          * Return the first item
1094          */
1095
1096         if (item == NULL) {
1097                 return section->children;
1098         } else {
1099                 return item->next;
1100         }
1101 }
1102
1103 int cf_section_lineno(CONF_SECTION *section)
1104 {
1105         return cf_sectiontoitem(section)->lineno;
1106 }
1107
1108 int cf_pair_lineno(CONF_PAIR *pair)
1109 {
1110         return cf_pairtoitem(pair)->lineno;
1111 }
1112
1113 int cf_item_is_section(CONF_ITEM *item)
1114 {
1115         return item->type == CONF_ITEM_SECTION;
1116 }
1117 int cf_item_is_pair(CONF_ITEM *item)
1118 {
1119         return item->type == CONF_ITEM_PAIR;
1120 }
1121
1122
1123 #if 0
1124 /*
1125  * JMG dump_config tries to dump the config structure in a readable format
1126  *
1127 */
1128
1129 static int dump_config_section(CONF_SECTION *cs, int indent)
1130 {
1131         CONF_SECTION    *scs;
1132         CONF_PAIR       *cp;
1133         CONF_ITEM       *ci;
1134
1135         /* The DEBUG macro doesn't let me
1136          *   for(i=0;i<indent;++i) debugputchar('\t');
1137          * so I had to get creative. --Pac. */
1138
1139         for (ci = cs->children; ci; ci = ci->next) {
1140                 if (ci->type == CONF_ITEM_PAIR) {
1141                         cp=cf_itemtopair(ci);
1142                         DEBUG("%.*s%s = %s",
1143                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1144                                 cp->attr, cp->value);
1145                 } else {
1146                         scs=cf_itemtosection(ci);
1147                         DEBUG("%.*s%s %s%s{",
1148                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1149                                 scs->name1,
1150                                 scs->name2 ? scs->name2 : "",
1151                                 scs->name2 ?  " " : "");
1152                         dump_config_section(scs, indent+1);
1153                         DEBUG("%.*s}",
1154                                 indent, "\t\t\t\t\t\t\t\t\t\t\t");
1155                 }
1156         }
1157
1158         return 0;
1159 }
1160
1161 int dump_config(void)
1162 {
1163         return dump_config_section(mainconfig.config, 0);
1164 }
1165 #endif