Added a bunch of 'const', and cf_pair_parse(), which should make
[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_DIRENT_H
40 #include <dirent.h>
41
42 #ifdef HAVE_SYS_STAT_H
43 #include <sys/stat.h>
44 #endif
45 #endif
46
47 #include <ctype.h>
48
49 #include "radiusd.h"
50 #include "rad_assert.h"
51 #include "conffile.h"
52 #include "token.h"
53 #include "modules.h"
54
55 static const char rcsid[] =
56 "$Id$";
57
58 typedef enum conf_type {
59         CONF_ITEM_PAIR,
60         CONF_ITEM_SECTION
61 } CONF_ITEM_TYPE;
62
63 struct conf_item {
64         struct conf_item *next;
65         struct conf_part *parent;
66         int lineno;
67         CONF_ITEM_TYPE type;
68 };
69 struct conf_pair {
70         CONF_ITEM item;
71         char *attr;
72         char *value;
73         LRAD_TOKEN operator;
74 };
75 struct conf_part {
76         CONF_ITEM item;
77         const char *name1;
78         const char *name2;
79         struct conf_item *children;
80         rbtree_t        *pair_tree; /* and a partridge.. */
81         rbtree_t        *section_tree; /* no jokes here */
82         rbtree_t        *name2_tree; /* for sections of the same name2 */
83 };
84
85 /*
86  *      Isolate the scary casts in these tiny provably-safe functions
87  */
88 CONF_PAIR *cf_itemtopair(CONF_ITEM *ci)
89 {
90         if (ci == NULL)
91                 return NULL;
92         rad_assert(ci->type == CONF_ITEM_PAIR);
93         return (CONF_PAIR *)ci;
94 }
95 CONF_SECTION *cf_itemtosection(CONF_ITEM *ci)
96 {
97         if (ci == NULL)
98                 return NULL;
99         rad_assert(ci->type == CONF_ITEM_SECTION);
100         return (CONF_SECTION *)ci;
101 }
102 CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp)
103 {
104         if (cp == NULL)
105                 return NULL;
106         return (CONF_ITEM *)cp;
107 }
108 CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs)
109 {
110         if (cs == NULL)
111                 return NULL;
112         return (CONF_ITEM *)cs;
113 }
114
115 /*
116  *      Create a new CONF_PAIR
117  */
118 static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,
119                                 LRAD_TOKEN operator, CONF_SECTION *parent)
120 {
121         CONF_PAIR *cp;
122
123         cp = rad_malloc(sizeof(*cp));
124         memset(cp, 0, sizeof(*cp));
125         cp->item.type = CONF_ITEM_PAIR;
126         cp->item.parent = parent;
127         cp->attr = strdup(attr);
128         cp->value = strdup(value);
129         cp->operator = operator;
130
131         return cp;
132 }
133
134 /*
135  *      Free a CONF_PAIR
136  */
137 void cf_pair_free(CONF_PAIR **cp)
138 {
139         if (!cp || !*cp) return;
140
141         if ((*cp)->attr)
142                 free((*cp)->attr);
143         if ((*cp)->value)
144                 free((*cp)->value);
145
146 #ifndef NDEBUG
147         memset(*cp, 0, sizeof(*cp));
148 #endif
149         free(*cp);
150
151         *cp = NULL;
152 }
153
154
155 /*
156  *      rbtree callback function
157  */
158 static int pair_cmp(const void *a, const void *b)
159 {
160         const CONF_PAIR *one = a;
161         const CONF_PAIR *two = b;
162
163         return strcmp(one->attr, two->attr);
164 }
165
166
167 /*
168  *      rbtree callback function
169  */
170 static int section_cmp(const void *a, const void *b)
171 {
172         const CONF_SECTION *one = a;
173         const CONF_SECTION *two = b;
174
175         return strcmp(one->name1, two->name1);
176 }
177
178
179 /*
180  *      rbtree callback function
181  */
182 static int name2_cmp(const void *a, const void *b)
183 {
184         const CONF_SECTION *one = a;
185         const CONF_SECTION *two = b;
186
187         rad_assert(strcmp(one->name1, two->name1) == 0);
188
189         if (!one->name2 && !two->name2) return 0;
190         if (!one->name2) return -1;
191         if (!two->name2) return +1;
192
193         return strcmp(one->name2, two->name2);
194 }
195
196
197 /*
198  *      Free a CONF_SECTION
199  */
200 void cf_section_free(CONF_SECTION **cs)
201 {
202         CONF_ITEM       *ci, *next;
203
204         if (!cs || !*cs) return;
205
206         for (ci = (*cs)->children; ci; ci = next) {
207                 next = ci->next;
208                 if (ci->type==CONF_ITEM_PAIR) {
209                         CONF_PAIR *pair = cf_itemtopair(ci);
210                         cf_pair_free(&pair);
211                 } else {
212                         CONF_SECTION *section = cf_itemtosection(ci);
213                         cf_section_free(&section);
214                 }
215         }
216
217         if ((*cs)->name1)
218                 free((*cs)->name1);
219         if ((*cs)->name2)
220                 free((*cs)->name2);
221         if ((*cs)->pair_tree)
222                 rbtree_free((*cs)->pair_tree);
223         if ((*cs)->section_tree)
224                 rbtree_free((*cs)->section_tree);
225         if ((*cs)->name2_tree)
226                 rbtree_free((*cs)->name2_tree);
227
228         /*
229          * And free the section
230          */
231 #ifndef NDEBUG
232         memset(*cs, 0, sizeof(*cs));
233 #endif
234         free(*cs);
235
236         *cs = NULL;
237 }
238
239
240 /*
241  *      Allocate a CONF_SECTION
242  */
243 static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,
244                                       CONF_SECTION *parent)
245 {
246         CONF_SECTION    *cs;
247
248         if (name1 == NULL || !name1[0])
249                 name1 = "main";
250
251         cs = rad_malloc(sizeof(*cs));
252         memset(cs, 0, sizeof(*cs));
253         cs->item.type = CONF_ITEM_SECTION;
254         cs->item.parent = parent;
255         cs->name1 = strdup(name1);
256         if (!cs->name1) {
257                 cf_section_free(&cs);
258                 return NULL;
259         }
260         
261         if (name2 && *name2) {
262                 cs->name2 = strdup(name2);
263                 if (!cs->name2) {
264                         cf_section_free(&cs);
265                         return NULL;
266                 }
267         }
268         cs->pair_tree = rbtree_create(pair_cmp, NULL, 0);
269         if (!cs->pair_tree) {
270                 cf_section_free(&cs);
271                 return NULL;
272         }
273
274         /*
275          *      Don't create the section tree here, it may not
276          *      be needed.
277          */
278         return cs;
279 }
280
281
282 /*
283  *      Add an item to a configuration section.
284  */
285 static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci_new)
286 {
287         CONF_ITEM *ci;
288
289         for (ci = cs->children; ci && ci->next; ci = ci->next)
290                 ;
291
292         if (ci == NULL)
293                 cs->children = ci_new;
294         else
295                 ci->next = ci_new;
296
297         /*
298          *      For fast lookups.
299          */
300         while (ci_new) {
301                 if (ci_new->type == CONF_ITEM_PAIR) {
302                         rbtree_insert(cs->pair_tree, ci_new);
303                         
304                 } else if (ci_new->type == CONF_ITEM_SECTION) {
305                         const CONF_SECTION *cs_new = cf_itemtosection(ci_new);
306
307                         if (!cs->section_tree) {
308                                 cs->section_tree = rbtree_create(section_cmp, NULL, 0);
309                                 /* ignore any errors */
310                         }
311                         
312                         if (cs->section_tree) {
313                                 rbtree_insert(cs->section_tree, cs_new);
314                         }
315                         
316                         /*
317                          *      Two names: find the named instance.
318                          */
319                         if (cs_new->name2) {
320                                 CONF_SECTION *old_cs;
321                                 
322                                 /*
323                                  *      Find the FIRST CONF_SECTION having the
324                                  *      given name1, and create a new tree
325                                  *      under it.
326                                  */
327                                 old_cs = rbtree_finddata(cs->section_tree, cs_new);
328                                 if (!old_cs) return; /* this is a bad error! */
329                                 
330                                 if (!old_cs->name2_tree) {
331                                         old_cs->name2_tree = rbtree_create(name2_cmp,
332                                                                            NULL, 0);
333                                 }
334                                 if (old_cs->name2_tree) {
335                                         rbtree_insert(old_cs->name2_tree, cs_new);
336                                 }
337                         } /* had a name2 */
338                 } /* was a section */
339
340                 ci_new = ci_new->next;
341         } /* loop over ci_new */
342 }
343
344 /*
345  *      Expand the variables in an input string.
346  */
347 static const char *cf_expand_variables(const char *cf, int *lineno,
348                                        const CONF_SECTION *outercs,
349                                        char *output, const char *input)
350 {
351         char *p;
352         const char *end, *ptr;
353         char name[8192];
354         const CONF_SECTION *parentcs;
355
356         /*
357          *      Find the master parent conf section.
358          *      We can't use mainconfig.config, because we're in the
359          *      process of re-building it, and it isn't set up yet...
360          */
361         for (parentcs = outercs;
362              parentcs->item.parent != NULL;
363              parentcs = parentcs->item.parent) {
364                 /* do nothing */
365         }
366
367         p = output;
368         ptr = input;
369         while (*ptr) {
370                 /*
371                  *      Ignore anything other than "${"
372                  */
373                 if ((*ptr == '$') && (ptr[1] == '{')) {
374                         int up;
375                         CONF_PAIR *cp;
376                         const CONF_SECTION *cs;
377
378                         /*
379                          *      FIXME: Add support for ${foo:-bar},
380                          *      like in xlat.c
381                          */
382
383                         /*
384                          *      Look for trailing '}', and log a
385                          *      warning for anything that doesn't match,
386                          *      and exit with a fatal error.
387                          */
388                         end = strchr(ptr, '}');
389                         if (end == NULL) {
390                                 *p = '\0';
391                                 radlog(L_INFO, "%s[%d]: Variable expansion missing }",
392                                        cf, *lineno);
393                                 return NULL;
394                         }
395
396                         ptr += 2;
397
398                         cp = NULL;
399                         up = 0;
400
401                         /*
402                          *      ${.foo} means "foo from the current section"
403                          */
404                         if (*ptr == '.') {
405                                 up = 1;
406                                 cs = outercs;
407                                 ptr++;
408
409                                 /*
410                                  *      ${..foo} means "foo from the section
411                                  *      enclosing this section" (etc.)
412                                  */
413                                 while (*ptr == '.') {
414                                         if (cs->item.parent)
415                                                 cs = cs->item.parent;
416                                         ptr++;
417                                 }
418
419                         } else {
420                                 const char *q;
421                                 /*
422                                  *      ${foo} is local, with
423                                  *      main as lower priority
424                                  */
425                                 cs = outercs;
426
427                                 /*
428                                  *      ${foo.bar.baz} is always rooted
429                                  *      from the top.
430                                  */
431                                 for (q = ptr; *q && q != end; q++) {
432                                         if (*q == '.') {
433                                                 cs = parentcs;
434                                                 up = 1;
435                                                 break;
436                                         }
437                                 }
438                         }
439
440                         while (cp == NULL) {
441                                 char *q;
442                                 /*
443                                  *      Find the next section.
444                                  */
445                                 for (q = name;
446                                      (*ptr != 0) && (*ptr != '.') &&
447                                              (ptr != end);
448                                      q++, ptr++) {
449                                         *q = *ptr;
450                                 }
451                                 *q = '\0';
452
453                                 /*
454                                  *      The character is a '.', find a
455                                  *      section (as the user has given
456                                  *      us a subsection to find)
457                                  */
458                                 if (*ptr == '.') {
459                                         CONF_SECTION *next;
460
461                                         ptr++;  /* skip the period */
462
463                                         /*
464                                          *      Find the sub-section.
465                                          */
466                                         next = cf_section_sub_find(cs, name);
467                                         if (next == NULL) {
468                                                 radlog(L_ERR, "config: No such section %s in variable %s", name, input);
469                                                 return NULL;
470                                         }
471                                         cs = next;
472
473                                 } else { /* no period, must be a conf-part */
474                                         /*
475                                          *      Find in the current referenced
476                                          *      section.
477                                          */
478                                         cp = cf_pair_find(cs, name);
479                                         if (cp == NULL) {
480                                                 /*
481                                                  *      It it was NOT ${..foo}
482                                                  *      then look in the
483                                                  *      top-level config items.
484                                                  */
485                                                 if (!up) cp = cf_pair_find(parentcs, name);
486                                         }
487                                         if (cp == NULL) {
488                                                 radlog(L_ERR, "config: No such entry %s for string %s", name, input);
489                                                 return NULL;
490                                         }
491                                 }
492                         } /* until cp is non-NULL */
493
494                         /*
495                          *  Substitute the value of the variable.
496                          */
497                         strcpy(p, cp->value);
498                         p += strlen(p);
499                         ptr = end + 1;
500
501                 } else if (memcmp(ptr, "$ENV{", 5) == 0) {
502                         char *env;
503
504                         ptr += 5;
505
506                         /*
507                          *      Look for trailing '}', and log a
508                          *      warning for anything that doesn't match,
509                          *      and exit with a fatal error.
510                          */
511                         end = strchr(ptr, '}');
512                         if (end == NULL) {
513                                 *p = '\0';
514                                 radlog(L_INFO, "%s[%d]: Environment variable expansion missing }",
515                                        cf, *lineno);
516                                 return NULL;
517                         }
518
519                         memcpy(name, ptr, end - ptr);
520                         name[end - ptr] = '\0';
521
522                         /*
523                          *      Get the environment variable.
524                          *      If none exists, then make it an empty string.
525                          */
526                         env = getenv(name);
527                         if (env == NULL) {
528                                 *name = '\0';
529                                 env = name;
530                         }
531
532                         strcpy(p, env);
533                         p += strlen(p);
534                         ptr = end + 1;
535
536                 } else {
537                         /*
538                          *      Copy it over verbatim.
539                          */
540                         *(p++) = *(ptr++);
541                 }
542         } /* loop over all of the input string. */
543
544         *p = '\0';
545
546         return output;
547 }
548
549
550 /*
551  *      Parses a CONF_PAIR into the specified format, with a default
552  *      value.
553  *
554  *      Returns -1 on error, 0 for correctly parsed, and 1 if the
555  *      default value was used.  Note that the default value will be
556  *      used ONLY if the CONF_PAIR is NULL.
557  */
558 int cf_pair_parse(const CONF_SECTION *cs, const CONF_PAIR *cp,
559                    const char *name, int type, void *data, const char *dflt)
560 {
561         int rcode = 0;
562         char **q;
563         const char *value;
564         lrad_ipaddr_t ipaddr;
565         char buffer[8192];
566
567         if (cp) {
568                 value = cp->value;
569         } else {
570                 rcode = 1;
571                 value = dflt;
572         }
573
574         switch (type) {
575         case PW_TYPE_BOOLEAN:
576                 /*
577                  *      Allow yes/no and on/off
578                  */
579                 if ((strcasecmp(value, "yes") == 0) ||
580                     (strcasecmp(value, "on") == 0)) {
581                         *(int *)data = 1;
582                 } else if ((strcasecmp(value, "no") == 0) ||
583                            (strcasecmp(value, "off") == 0)) {
584                         *(int *)data = 0;
585                 } else {
586                         *(int *)data = 0;
587                         radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, name);
588                         return -1;
589                 }
590                 DEBUG2(" %s: %s = %s", cs->name1, name, value);
591                 break;
592                 
593         case PW_TYPE_INTEGER:
594                 *(int *)data = strtol(value, 0, 0);
595                 DEBUG2(" %s: %s = %d",
596                        cs->name1, name,
597                        *(int *)data);
598                 break;
599                 
600         case PW_TYPE_STRING_PTR:
601                 q = (char **) data;
602                 if (*q != NULL) {
603                         free(*q);
604                 }
605                 
606                 /*
607                  *      Expand variables which haven't already been
608                  *      expanded automagically when the configuration
609                  *      file was read.
610                  */
611                 if (value && (value == dflt)) {
612                         int lineno = cs->item.lineno;
613                         value = cf_expand_variables("?",
614                                                     &lineno,
615                                                     cs, buffer, value);
616                         if (!value) return -1;
617                 }
618                 
619                 DEBUG2(" %s: %s = \"%s\"",
620                        cs->name1, name,
621                        value ? value : "(null)");
622                 *q = value ? strdup(value) : NULL;
623                 break;
624                 
625         case PW_TYPE_IPADDR:
626                 /*
627                  *      Allow '*' as any address
628                  */
629                 if (strcmp(value, "*") == 0) {
630                         *(uint32_t *) data = htonl(INADDR_ANY);
631                         break;
632                 }
633                 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
634                         radlog(L_ERR, "Can't find IP address for host %s", value);
635                         return -1;
636                 }
637                 DEBUG2(" %s: %s = %s IP address [%s]",
638                        cs->name1, name, value,
639                        ip_ntoh(&ipaddr, buffer, sizeof(buffer)));
640                 *(uint32_t *) data = ipaddr.ipaddr.ip4addr.s_addr;
641                 break;
642                 
643         case PW_TYPE_IPV6ADDR:
644                 /*
645                  *      Allow '*' as any address
646                  */
647                 if (strcmp(value, "*") == 0) {
648                         memcpy(data, 0, sizeof(ipaddr.ipaddr.ip6addr));
649                         break;
650                 }
651                 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
652                         radlog(L_ERR, "Can't find IPv6 address for host %s", value);
653                         return -1;
654                 }
655                 DEBUG2(" %s: %s = %s IPv6 address [%s]",
656                        cs->name1, name, value,
657                        ip_ntoh(&ipaddr, buffer, sizeof(buffer)));
658                 memcpy(data, &ipaddr.ipaddr.ip6addr,
659                        sizeof(ipaddr.ipaddr.ip6addr));
660                 break;
661                 
662         default:
663                 radlog(L_ERR, "type %d not supported yet", type);
664                 return -1;
665                 break;
666         } /* switch over variable type */
667         
668         return rcode;
669 }
670
671 /*
672  *      Parse a configuration section into user-supplied variables.
673  */
674 int cf_section_parse(const CONF_SECTION *cs, void *base,
675                      const CONF_PARSER *variables)
676 {
677         int i;
678         const CONF_PAIR *cp;
679         void *data;
680
681         /*
682          *      Handle the known configuration parameters.
683          */
684         for (i = 0; variables[i].name != NULL; i++) {
685                 /*
686                  *      Handle subsections specially
687                  */
688                 if (variables[i].type == PW_TYPE_SUBSECTION) {
689                         const CONF_SECTION *subcs;
690                         subcs = cf_section_sub_find(cs, variables[i].name);
691                         
692                         /*
693                          *      If the configuration section is NOT there,
694                          *      then ignore it.
695                          *
696                          *      FIXME! This is probably wrong... we should
697                          *      probably set the items to their default values.
698                          */
699                         if (!subcs) continue;
700
701                         if (!variables[i].data) {
702                                 DEBUG2("Internal sanity check 1 failed in cf_section_parse!");
703                                 return -1;
704                         }
705                         
706                         if (cf_section_parse(subcs, base,
707                                              (CONF_PARSER *) variables[i].data) < 0) {
708                                 return -1;
709                         }
710                         continue;
711                 } /* else it's a CONF_PAIR */
712                 
713                 if (variables[i].data) {
714                         data = variables[i].data; /* prefer this. */
715                 } else if (base) {
716                         data = ((char *)base) + variables[i].offset;
717                 } else {
718                         DEBUG2("Internal sanity check 2 failed in cf_section_parse!");
719                         return -1;
720                 }
721
722                 cp = cf_pair_find(cs, variables[i].name);
723                 if (cf_pair_parse(cs, cp, variables[i].name, variables[i].type,
724                                   data, variables[i].dflt) < 0) {
725                         return -1;
726                 }
727         } /* for all variables in the configuration section */
728
729         return 0;
730 }
731
732 /*
733  *      Used in a few places, so in one function for clarity.
734  */
735 static void cf_fixup_children(CONF_SECTION *cs, CONF_SECTION *is)
736 {
737         /*
738          *      Add the included conf
739          *      to our CONF_SECTION
740          */
741         if (is->children != NULL) {
742                 CONF_ITEM *ci;
743                 
744                 /*
745                  *      Re-write the parent of the
746                  *      moved children to be the
747                  *      upper-layer section.
748                  */
749                 for (ci = is->children; ci; ci = ci->next) {
750                         ci->parent = cs;
751                 }
752                 
753                 /*
754                  *      If there are children, then
755                  *      move them up a layer.
756                  */
757                 if (is->children) {
758                         cf_item_add(cs, is->children);
759                 }
760                 is->children = NULL;
761         }
762         /*
763          *      Always free the section for the
764          *      $INCLUDEd file.
765          */
766         cf_section_free(&is);
767 }
768
769
770 /*
771  *      Read a part of the config file.
772  */
773 static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
774                                      const char *name1, const char *name2,
775                                      CONF_SECTION *parent)
776 {
777         CONF_SECTION *cs, *css;
778         CONF_PAIR *cpn;
779         char *ptr;
780         const char *value;
781         char buf[8192];
782         char buf1[8192];
783         char buf2[8192];
784         char buf3[8192];
785         int t1, t2, t3;
786         char *cbuf = buf;
787         int len;
788
789         /*
790          *      Ensure that the user can't add CONF_SECTIONs
791          *      with 'internal' names;
792          */
793         if ((name1 != NULL) && (name1[0] == '_')) {
794                 radlog(L_ERR, "%s[%d]: Illegal configuration section name",
795                         cf, *lineno);
796                 return NULL;
797         }
798
799         /*
800          *      Allocate new section.
801          */
802         cs = cf_section_alloc(name1, name2, parent);
803         cs->item.lineno = *lineno;
804
805         /*
806          *      Read, checking for line continuations ('\\' at EOL)
807          */
808         for (;;) {
809                 int eof;
810
811                 /*
812                  *      Get data, and remember if we are at EOF.
813                  */
814                 eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL);
815                 (*lineno)++;
816
817                 len = strlen(cbuf);
818
819                 /*
820                  *      We've filled the buffer, and there isn't
821                  *      a CR in it.  Die!
822                  */
823                 if ((len == sizeof(buf)) &&
824                     (cbuf[len - 1] != '\n')) {
825                         radlog(L_ERR, "%s[%d]: Line too long",
826                                cf, *lineno);
827                         cf_section_free(&cs);
828                         return NULL;
829                 }
830
831                 /*
832                  *  Check for continuations.
833                  */
834                 if (cbuf[len - 1] == '\n') len--;
835
836                 /*
837                  *      Last character is '\\'.  Over-write it,
838                  *      and read another line.
839                  */
840                 if ((len > 0) && (cbuf[len - 1] == '\\')) {
841                         cbuf[len - 1] = '\0';
842                         cbuf += len - 1;
843                         continue;
844                 }
845
846                 /*
847                  *  We're at EOF, and haven't read anything.  Stop.
848                  */
849                 if (eof && (cbuf == buf)) {
850                         break;
851                 }
852
853                 ptr = cbuf = buf;
854                 t1 = gettoken(&ptr, buf1, sizeof(buf1));
855
856                 /*
857                  *      Skip comments and blank lines immediately.
858                  */
859                 if ((*buf1 == '#') || (*buf1 == '\0')) {
860                         continue;
861                 }
862
863                 /*
864                  *      Allow for $INCLUDE files
865                  *
866                  *      This *SHOULD* work for any level include.
867                  *      I really really really hate this file.  -cparker
868                  */
869                 if (strcasecmp(buf1, "$INCLUDE") == 0) {
870                         CONF_SECTION    *is;
871
872                         t2 = getword(&ptr, buf2, sizeof(buf2));
873
874                         value = cf_expand_variables(cf, lineno, cs, buf, buf2);
875                         if (value == NULL) {
876                                 cf_section_free(&cs);
877                                 return NULL;
878                         }
879
880 #ifdef HAVE_DIRENT_H
881                         /*
882                          *      $INCLUDE foo/
883                          *
884                          *      Include ALL non-"dot" files in the directory.
885                          *      careful!
886                          */
887                         if (value[strlen(value) - 1] == '/') {
888                                 DIR             *dir;
889                                 struct dirent   *dp;
890                                 struct stat stat_buf;
891
892                                 DEBUG2( "Config:   including files in directory: %s", value );
893                                 dir = opendir(value);
894                                 if (!dir) {
895                                         radlog(L_ERR, "%s[%d]: Error reading directory %s: %s",
896                                                cf, *lineno, value,
897                                                strerror(errno));
898                                         cf_section_free(&cs);
899                                         return NULL;
900                                 }
901
902                                 /*
903                                  *      Read the directory, ignoring "." files.
904                                  */
905                                 while ((dp = readdir(dir)) != NULL) {
906                                         const char *p;
907
908                                         if (dp->d_name[0] == '.') continue;
909
910                                         /*
911                                          *      Check for valid characters
912                                          */
913                                         for (p = dp->d_name; *p != '\0'; p++) {
914                                                 if (isalpha((int)*p) ||
915                                                     isdigit((int)*p) ||
916                                                     (*p == '_') ||
917                                                     (*p == '.')) continue;
918                                                 break;
919                                         }
920                                         if (*p != '\0') continue;
921
922                                         snprintf(buf2, sizeof(buf2), "%s%s",
923                                                  value, dp->d_name);
924                                         if ((stat(buf2, &stat_buf) != 0) ||
925                                             S_ISDIR(stat_buf.st_mode)) continue;
926                                         if ((is = conf_read(cf, *lineno, buf2, parent)) == NULL) {
927                                                 closedir(dir);
928                                                 cf_section_free(&cs);
929                                                 return NULL;
930                                         }
931                                         
932                                         cf_fixup_children(cs, is);
933                                 }
934                                 closedir(dir);
935                         }  else
936 #endif
937                         { /* it was a normal file */
938                                 DEBUG2( "Config:   including file: %s", value );
939                                 if ((is = conf_read(cf, *lineno, value, parent)) == NULL) {
940                                         cf_section_free(&cs);
941                                         return NULL;
942                                 }
943                                 cf_fixup_children(cs, is);
944                         }
945                         continue;
946                 } /* we were in an include */
947
948                 /*
949                  *      No '=': must be a section or sub-section.
950                  */
951                 if (strchr(ptr, '=') == NULL) {
952                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
953                         t3 = gettoken(&ptr, buf3, sizeof(buf3));
954                 } else {
955                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
956                         t3 = getword(&ptr, buf3, sizeof(buf3));
957                 }
958
959                 /*
960                  *      See if it's the end of a section.
961                  */
962                 if (t1 == T_RCBRACE) {
963                         if (name1 == NULL || buf2[0]) {
964                                 radlog(L_ERR, "%s[%d]: Unexpected end of section",
965                                                 cf, *lineno);
966                                 cf_section_free(&cs);
967                                 return NULL;
968                         }
969                         return cs;
970                 }
971
972                 /*
973                  * Perhaps a subsection.
974                  */
975                 if (t2 == T_LCBRACE || t3 == T_LCBRACE) {
976                         css = cf_section_read(cf, lineno, fp, buf1,
977                                               t2==T_LCBRACE ? NULL : buf2, cs);
978                         if (css == NULL) {
979                                 cf_section_free(&cs);
980                                 return NULL;
981                         }
982                         cf_item_add(cs, cf_sectiontoitem(css));
983
984                         continue;
985                 }
986
987                 /*
988                  *      Ignore semi-colons.
989                  */
990                 if (*buf2 == ';')
991                         *buf2 = '\0';
992
993                 /*
994                  *      Must be a normal attr = value line.
995                  */
996                 if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) {
997                         t2 = T_OP_EQ;
998                 } else if (buf1[0] == 0 || buf2[0] == 0 ||
999                            (t2 < T_EQSTART || t2 > T_EQEND)) {
1000                         radlog(L_ERR, "%s[%d]: Line is not in 'attribute = value' format",
1001                                         cf, *lineno);
1002                         cf_section_free(&cs);
1003                         return NULL;
1004                 }
1005
1006                 /*
1007                  *      Ensure that the user can't add CONF_PAIRs
1008                  *      with 'internal' names;
1009                  */
1010                 if (buf1[0] == '_') {
1011                         radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"",
1012                                         cf, *lineno, buf1);
1013                         cf_section_free(&cs);
1014                         return NULL;
1015                 }
1016
1017                 /*
1018                  *      Handle variable substitution via ${foo}
1019                  */
1020                 value = cf_expand_variables(cf, lineno, cs, buf, buf3);
1021                 if (!value) {
1022                         cf_section_free(&cs);
1023                         return NULL;
1024                 }
1025
1026
1027                 /*
1028                  *      Add this CONF_PAIR to our CONF_SECTION
1029                  */
1030                 cpn = cf_pair_alloc(buf1, value, t2, parent);
1031                 cpn->item.lineno = *lineno;
1032                 cf_item_add(cs, cf_pairtoitem(cpn));
1033         }
1034
1035         /*
1036          *      See if EOF was unexpected ..
1037          */
1038         if (name1 != NULL) {
1039                 radlog(L_ERR, "%s[%d]: Unexpected end of file", cf, *lineno);
1040                 cf_section_free(&cs);
1041                 return NULL;
1042         }
1043
1044         return cs;
1045 }
1046
1047 /*
1048  *      Read the config file.
1049  */
1050 CONF_SECTION *conf_read(const char *fromfile, int fromline,
1051                         const char *conffile, CONF_SECTION *parent)
1052 {
1053         FILE            *fp;
1054         int             lineno = 0;
1055         CONF_SECTION    *cs;
1056
1057         if ((fp = fopen(conffile, "r")) == NULL) {
1058                 if (fromfile) {
1059                         radlog(L_ERR|L_CONS, "%s[%d]: Unable to open file \"%s\": %s",
1060                                         fromfile, fromline, conffile, strerror(errno));
1061                 } else {
1062                         radlog(L_ERR|L_CONS, "Unable to open file \"%s\": %s",
1063                                         conffile, strerror(errno));
1064                 }
1065                 return NULL;
1066         }
1067
1068         cs = cf_section_read(conffile, &lineno, fp, NULL, NULL, parent);
1069
1070         fclose(fp);
1071
1072         return cs;
1073 }
1074
1075
1076 /*
1077  * Return a CONF_PAIR within a CONF_SECTION.
1078  */
1079 CONF_PAIR *cf_pair_find(const CONF_SECTION *cs, const char *name)
1080 {
1081         CONF_ITEM       *ci;
1082
1083         if (!cs) cs = mainconfig.config;
1084
1085         /*
1086          *      Find the name in the tree, for speed.
1087          */
1088         if (name) {
1089                 CONF_PAIR mycp;
1090
1091                 mycp.attr = name;
1092                 return rbtree_finddata(cs->pair_tree, &mycp);
1093         }
1094
1095         /*
1096          *      Else find the first one
1097          */
1098         for (ci = cs->children; ci; ci = ci->next) {
1099                 if (ci->type == CONF_ITEM_PAIR)
1100                         return cf_itemtopair(ci);
1101         }
1102         
1103         return NULL;
1104 }
1105
1106 /*
1107  * Return the attr of a CONF_PAIR
1108  */
1109
1110 char *cf_pair_attr(CONF_PAIR *pair)
1111 {
1112         return (pair ? pair->attr : NULL);
1113 }
1114
1115 /*
1116  * Return the value of a CONF_PAIR
1117  */
1118
1119 char *cf_pair_value(CONF_PAIR *pair)
1120 {
1121         return (pair ? pair->value : NULL);
1122 }
1123
1124 /*
1125  * Return the first label of a CONF_SECTION
1126  */
1127
1128 const char *cf_section_name1(const CONF_SECTION *cs)
1129 {
1130         return (cs ? cs->name1 : NULL);
1131 }
1132
1133 /*
1134  * Return the second label of a CONF_SECTION
1135  */
1136
1137 const char *cf_section_name2(const CONF_SECTION *cs)
1138 {
1139         return (cs ? cs->name2 : NULL);
1140 }
1141
1142 /*
1143  * Find a value in a CONF_SECTION
1144  */
1145 char *cf_section_value_find(const CONF_SECTION *cs, const char *attr)
1146 {
1147         CONF_PAIR       *cp;
1148
1149         cp = cf_pair_find(cs, attr);
1150
1151         return (cp ? cp->value : NULL);
1152 }
1153
1154 /*
1155  * Return the next pair after a CONF_PAIR
1156  * with a certain name (char *attr) If the requested
1157  * attr is NULL, any attr matches.
1158  */
1159
1160 CONF_PAIR *cf_pair_find_next(const CONF_SECTION *cs,
1161                              const CONF_PAIR *pair, const char *attr)
1162 {
1163         CONF_ITEM       *ci;
1164
1165         /*
1166          * If pair is NULL this must be a first time run
1167          * Find the pair with correct name
1168          */
1169
1170         if (pair == NULL){
1171                 return cf_pair_find(cs, attr);
1172         }
1173
1174         ci = cf_pairtoitem(pair)->next;
1175
1176         for (; ci; ci = ci->next) {
1177                 if (ci->type != CONF_ITEM_PAIR)
1178                         continue;
1179                 if (attr == NULL || strcmp(cf_itemtopair(ci)->attr, attr) == 0)
1180                         break;
1181         }
1182
1183         return cf_itemtopair(ci);
1184 }
1185
1186 /*
1187  * Find a CONF_SECTION, or return the root if name is NULL
1188  */
1189
1190 CONF_SECTION *cf_section_find(const char *name)
1191 {
1192         if (name)
1193                 return cf_section_sub_find(mainconfig.config, name);
1194         else
1195                 return mainconfig.config;
1196 }
1197
1198 /*
1199  * Find a sub-section in a section
1200  */
1201
1202 CONF_SECTION *cf_section_sub_find(const CONF_SECTION *cs, const char *name)
1203 {
1204         CONF_ITEM *ci;
1205
1206         /*
1207          *      Do the fast lookup if possible.
1208          */
1209         if (name && cs->section_tree) {
1210                 CONF_SECTION mycs;
1211
1212                 mycs.name1 = name;
1213                 mycs.name2 = NULL;
1214                 return rbtree_finddata(cs->section_tree, &mycs);
1215         }
1216
1217         for (ci = cs->children; ci; ci = ci->next) {
1218                 if (ci->type != CONF_ITEM_SECTION)
1219                         continue;
1220                 if (strcmp(cf_itemtosection(ci)->name1, name) == 0)
1221                         break;
1222         }
1223
1224         return cf_itemtosection(ci);
1225
1226 }
1227
1228
1229 /*
1230  * Find a CONF_SECTION with both names.
1231  */
1232 CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *cs,
1233                                         const char *name1, const char *name2)
1234 {
1235         CONF_ITEM    *ci;
1236
1237         if (!name2) return cf_section_sub_find(cs, name1);
1238
1239         if (!cs) cs = mainconfig.config;
1240
1241         if (cs->section_tree) {
1242                 CONF_SECTION mycs, *master_cs;
1243                 
1244                 mycs.name1 = name1;
1245                 mycs.name2 = name2;
1246                 
1247                 master_cs = rbtree_finddata(cs->section_tree, &mycs);
1248                 if (master_cs) {
1249                         return rbtree_finddata(master_cs->name2_tree, &mycs);
1250                 }
1251         }
1252
1253         /*
1254          *      Else do it the old-fashioned way.
1255          */
1256         for (ci = cs->children; ci; ci = ci->next) {
1257                 CONF_SECTION *subcs;
1258
1259                 if (ci->type != CONF_ITEM_SECTION)
1260                         continue;
1261
1262                 subcs = cf_itemtosection(ci);
1263                 if ((strcmp(subcs->name1, name1) == 0) &&
1264                     (subcs->name2 != NULL) &&
1265                     (strcmp(subcs->name2, name2) == 0))
1266                         break;
1267         }
1268
1269         return cf_itemtosection(ci);
1270 }
1271
1272 /*
1273  * Return the next subsection after a CONF_SECTION
1274  * with a certain name1 (char *name1). If the requested
1275  * name1 is NULL, any name1 matches.
1276  */
1277
1278 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
1279                                       CONF_SECTION *subsection,
1280                                       const char *name1)
1281 {
1282         CONF_ITEM       *ci;
1283
1284         /*
1285          * If subsection is NULL this must be a first time run
1286          * Find the subsection with correct name
1287          */
1288
1289         if (subsection == NULL){
1290                 ci = section->children;
1291         } else {
1292                 ci = cf_sectiontoitem(subsection)->next;
1293         }
1294
1295         for (; ci; ci = ci->next) {
1296                 if (ci->type != CONF_ITEM_SECTION)
1297                         continue;
1298                 if ((name1 == NULL) ||
1299                     (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
1300                         break;
1301         }
1302
1303         return cf_itemtosection(ci);
1304 }
1305
1306 /*
1307  * Return the next item after a CONF_ITEM.
1308  */
1309
1310 CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item)
1311 {
1312         /*
1313          * If item is NULL this must be a first time run
1314          * Return the first item
1315          */
1316
1317         if (item == NULL) {
1318                 return section->children;
1319         } else {
1320                 return item->next;
1321         }
1322 }
1323
1324 int cf_section_lineno(CONF_SECTION *section)
1325 {
1326         return cf_sectiontoitem(section)->lineno;
1327 }
1328
1329 int cf_pair_lineno(CONF_PAIR *pair)
1330 {
1331         return cf_pairtoitem(pair)->lineno;
1332 }
1333
1334 int cf_item_is_section(CONF_ITEM *item)
1335 {
1336         return item->type == CONF_ITEM_SECTION;
1337 }
1338
1339
1340 #if 0
1341 /*
1342  * JMG dump_config tries to dump the config structure in a readable format
1343  *
1344 */
1345
1346 static int dump_config_section(CONF_SECTION *cs, int indent)
1347 {
1348         CONF_SECTION    *scs;
1349         CONF_PAIR       *cp;
1350         CONF_ITEM       *ci;
1351
1352         /* The DEBUG macro doesn't let me
1353          *   for(i=0;i<indent;++i) debugputchar('\t');
1354          * so I had to get creative. --Pac. */
1355
1356         for (ci = cs->children; ci; ci = ci->next) {
1357                 if (ci->type == CONF_ITEM_PAIR) {
1358                         cp=cf_itemtopair(ci);
1359                         DEBUG("%.*s%s = %s",
1360                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1361                                 cp->attr, cp->value);
1362                 } else {
1363                         scs=cf_itemtosection(ci);
1364                         DEBUG("%.*s%s %s%s{",
1365                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1366                                 scs->name1,
1367                                 scs->name2 ? scs->name2 : "",
1368                                 scs->name2 ?  " " : "");
1369                         dump_config_section(scs, indent+1);
1370                         DEBUG("%.*s}",
1371                                 indent, "\t\t\t\t\t\t\t\t\t\t\t");
1372                 }
1373         }
1374
1375         return 0;
1376 }
1377
1378 int dump_config(void)
1379 {
1380         return dump_config_section(mainconfig.config, 0);
1381 }
1382 #endif