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: bddb923af54ade4b4bf18b8e8f6f64af6382391c $
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 *
24 * Copyright 2000,2006 The FreeRADIUS server project
25 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
26 * Copyright 2000 Alan DeKok <aland@ox.org>
27 */
28
29 RCSID("$Id: bddb923af54ade4b4bf18b8e8f6f64af6382391c $")
30
31 #include <freeradius-devel/radiusd.h>
32 #include <freeradius-devel/parser.h>
33 #include <freeradius-devel/rad_assert.h>
34
35 #ifdef HAVE_DIRENT_H
36 #include <dirent.h>
37 #endif
38
39 #ifdef HAVE_SYS_STAT_H
40 #include <sys/stat.h>
41 #endif
42
43 #include <ctype.h>
44
45 bool check_config = false;
46
47 typedef enum conf_property {
48 CONF_PROPERTY_INVALID = 0,
49 CONF_PROPERTY_NAME,
50 CONF_PROPERTY_INSTANCE,
51 } CONF_PROPERTY;
52
53 static const FR_NAME_NUMBER conf_property_name[] = {
54 { "name", CONF_PROPERTY_NAME},
55 { "instance", CONF_PROPERTY_INSTANCE},
56
57 { NULL , -1 }
58 };
59
60 typedef enum conf_type {
61 CONF_ITEM_INVALID = 0,
62 CONF_ITEM_PAIR,
63 CONF_ITEM_SECTION,
64 CONF_ITEM_DATA
65 } CONF_ITEM_TYPE;
66
67 struct conf_item {
68 struct conf_item *next; //!< Sibling.
69 struct conf_part *parent; //!< Parent.
70 int lineno; //!< The line number the config item began on.
71 char const *filename; //!< The file the config item was parsed from.
72 CONF_ITEM_TYPE type; //!< Whether the config item is a config_pair, conf_section or conf_data.
73 };
74
75 /** Configuration AVP similar to a VALUE_PAIR
76 *
77 */
78 struct conf_pair {
79 CONF_ITEM item;
80 char const *attr; //!< Attribute name
81 char const *value; //!< Attribute value
82 FR_TOKEN op; //!< Operator e.g. =, :=
83 FR_TOKEN lhs_type; //!< Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
84 FR_TOKEN rhs_type; //!< Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
85 bool pass2; //!< do expansion in pass2.
86 bool parsed; //!< Was this item used during parsing?
87 };
88
89 /** Internal data that is associated with a configuration section
90 *
91 */
92 struct conf_data {
93 CONF_ITEM item;
94 char const *name;
95 int flag;
96 void *data; //!< User data
97 void (*free)(void *); //!< Free user data function
98 };
99
100 struct conf_part {
101 CONF_ITEM item;
102 char const *name1; //!< First name token. Given ``foo bar {}`` would be ``foo``.
103 char const *name2; //!< Second name token. Given ``foo bar {}`` would be ``bar``.
104
105 FR_TOKEN name2_type; //!< The type of quoting around name2.
106
107 CONF_ITEM *children;
108 CONF_ITEM *tail; //!< For speed.
109 CONF_SECTION *template;
110
111 rbtree_t *pair_tree; //!< and a partridge..
112 rbtree_t *section_tree; //!< no jokes here.
113 rbtree_t *name2_tree; //!< for sections of the same name2
114 rbtree_t *data_tree;
115
116 void *base;
117 int depth;
118
119 CONF_PARSER const *variables;
120 };
121
122 typedef struct cf_file_t {
123 char const *filename;
124 CONF_SECTION *cs;
125 struct stat buf;
126 bool from_dir;
127 } cf_file_t;
128
129 CONF_SECTION *root_config = NULL;
130 bool cf_new_escape = false;
131
132
133 static int cf_data_add_internal(CONF_SECTION *cs, char const *name, void *data,
134 void (*data_free)(void *), int flag);
135
136 static void *cf_data_find_internal(CONF_SECTION const *cs, char const *name, int flag);
137
138 static char const *cf_expand_variables(char const *cf, int *lineno,
139 CONF_SECTION *outercs,
140 char *output, size_t outsize,
141 char const *input, bool *soft_fail);
142
143 static int cf_file_include(CONF_SECTION *cs, char const *filename_in, bool from_dir);
144
145
146
147 /*
148 * Isolate the scary casts in these tiny provably-safe functions
149 */
150
151 /** Cast a CONF_ITEM to a CONF_PAIR
152 *
153 */
cf_item_to_pair(CONF_ITEM const * ci)154 CONF_PAIR *cf_item_to_pair(CONF_ITEM const *ci)
155 {
156 CONF_PAIR *out;
157
158 if (ci == NULL) return NULL;
159
160 rad_assert(ci->type == CONF_ITEM_PAIR);
161
162 memcpy(&out, &ci, sizeof(out));
163 return out;
164 }
165
166 /** Cast a CONF_ITEM to a CONF_SECTION
167 *
168 */
cf_item_to_section(CONF_ITEM const * ci)169 CONF_SECTION *cf_item_to_section(CONF_ITEM const *ci)
170 {
171 CONF_SECTION *out;
172
173 if (ci == NULL) return NULL;
174
175 rad_assert(ci->type == CONF_ITEM_SECTION);
176
177 memcpy(&out, &ci, sizeof(out));
178 return out;
179 }
180
181 /** Cast a CONF_PAIR to a CONF_ITEM
182 *
183 */
cf_pair_to_item(CONF_PAIR const * cp)184 CONF_ITEM *cf_pair_to_item(CONF_PAIR const *cp)
185 {
186 CONF_ITEM *out;
187
188 if (cp == NULL) return NULL;
189
190 memcpy(&out, &cp, sizeof(out));
191 return out;
192 }
193
194 /** Cast a CONF_SECTION to a CONF_ITEM
195 *
196 */
cf_section_to_item(CONF_SECTION const * cs)197 CONF_ITEM *cf_section_to_item(CONF_SECTION const *cs)
198 {
199 CONF_ITEM *out;
200
201 if (cs == NULL) return NULL;
202
203 memcpy(&out, &cs, sizeof(out));
204 return out;
205 }
206
207 /** Cast CONF_DATA to a CONF_ITEM
208 *
209 */
cf_data_to_item(CONF_DATA const * cd)210 static CONF_ITEM *cf_data_to_item(CONF_DATA const *cd)
211 {
212 CONF_ITEM *out;
213
214 if (cd == NULL) {
215 return NULL;
216 }
217
218 memcpy(&out, &cd, sizeof(out));
219 return out;
220 }
221
_cf_data_free(CONF_DATA * cd)222 static int _cf_data_free(CONF_DATA *cd)
223 {
224 if (cd->free) cd->free(cd->data);
225
226 return 0;
227 }
228
229 /*
230 * rbtree callback function
231 */
pair_cmp(void const * a,void const * b)232 static int pair_cmp(void const *a, void const *b)
233 {
234 CONF_PAIR const *one = a;
235 CONF_PAIR const *two = b;
236
237 return strcmp(one->attr, two->attr);
238 }
239
240
241 /*
242 * rbtree callback function
243 */
section_cmp(void const * a,void const * b)244 static int section_cmp(void const *a, void const *b)
245 {
246 CONF_SECTION const *one = a;
247 CONF_SECTION const *two = b;
248
249 return strcmp(one->name1, two->name1);
250 }
251
252
253 /*
254 * rbtree callback function
255 */
name2_cmp(void const * a,void const * b)256 static int name2_cmp(void const *a, void const *b)
257 {
258 CONF_SECTION const *one = a;
259 CONF_SECTION const *two = b;
260
261 rad_assert(strcmp(one->name1, two->name1) == 0);
262
263 if (!one->name2 && !two->name2) return 0;
264 if (one->name2 && !two->name2) return -1;
265 if (!one->name2 && two->name2) return +1;
266
267 return strcmp(one->name2, two->name2);
268 }
269
270
271 /*
272 * rbtree callback function
273 */
data_cmp(void const * a,void const * b)274 static int data_cmp(void const *a, void const *b)
275 {
276 int rcode;
277
278 CONF_DATA const *one = a;
279 CONF_DATA const *two = b;
280
281 rcode = one->flag - two->flag;
282 if (rcode != 0) return rcode;
283
284 return strcmp(one->name, two->name);
285 }
286
287 /*
288 * Functions for tracking filenames.
289 */
filename_cmp(void const * a,void const * b)290 static int filename_cmp(void const *a, void const *b)
291 {
292 cf_file_t const *one = a;
293 cf_file_t const *two = b;
294
295 if (one->buf.st_dev < two->buf.st_dev) return -1;
296 if (one->buf.st_dev > two->buf.st_dev) return +1;
297
298 if (one->buf.st_ino < two->buf.st_ino) return -1;
299 if (one->buf.st_ino > two->buf.st_ino) return +1;
300
301 return 0;
302 }
303
cf_file_open(CONF_SECTION * cs,char const * filename,bool from_dir,FILE ** fp_p)304 static int cf_file_open(CONF_SECTION *cs, char const *filename, bool from_dir, FILE **fp_p)
305 {
306 cf_file_t *file;
307 CONF_DATA *cd;
308 CONF_SECTION *top;
309 rbtree_t *tree;
310 int fd;
311 FILE *fp;
312
313 top = cf_top_section(cs);
314 cd = cf_data_find_internal(top, "filename", 0);
315 if (!cd) return -1;
316
317 tree = cd->data;
318
319 /*
320 * If we're including a wildcard directory, then ignore
321 * any files the users has already explicitly loaded in
322 * that directory.
323 */
324 if (from_dir) {
325 cf_file_t my_file;
326
327 my_file.cs = cs;
328 my_file.filename = filename;
329
330 if (stat(filename, &my_file.buf) < 0) goto error;
331
332 file = rbtree_finddata(tree, &my_file);
333 if (file && !file->from_dir) return 0;
334 }
335
336 DEBUG2("including configuration file %s", filename);
337
338 fp = fopen(filename, "r");
339 if (!fp) {
340 error:
341 ERROR("Unable to open file \"%s\": %s",
342 filename, fr_syserror(errno));
343 return -1;
344 }
345
346 fd = fileno(fp);
347
348 file = talloc(tree, cf_file_t);
349 if (!file) {
350 fclose(fp);
351 return -1;
352 }
353
354 file->filename = filename;
355 file->cs = cs;
356
357 if (fstat(fd, &file->buf) == 0) {
358 #ifdef S_IWOTH
359 if ((file->buf.st_mode & S_IWOTH) != 0) {
360 ERROR("Configuration file %s is globally writable. "
361 "Refusing to start due to insecure configuration.", filename);
362
363 fclose(fp);
364 talloc_free(file);
365 return -1;
366 }
367 #endif
368 }
369
370 /*
371 * We can include the same file twice. e.g. when it
372 * contains common definitions, such as for SQL.
373 *
374 * Though the admin should really use templates for that.
375 */
376 if (!rbtree_insert(tree, file)) {
377 talloc_free(file);
378 }
379
380 *fp_p = fp;
381 return 1;
382 }
383
384 /*
385 * Do some checks on the file
386 */
cf_file_check(CONF_SECTION * cs,char const * filename,bool check_perms)387 static bool cf_file_check(CONF_SECTION *cs, char const *filename, bool check_perms)
388 {
389 cf_file_t *file;
390 CONF_DATA *cd;
391 CONF_SECTION *top;
392 rbtree_t *tree;
393
394 top = cf_top_section(cs);
395 cd = cf_data_find_internal(top, "filename", 0);
396 if (!cd) return false;
397
398 tree = cd->data;
399
400 file = talloc(tree, cf_file_t);
401 if (!file) return false;
402
403 file->filename = filename;
404 file->cs = cs;
405
406 if (stat(filename, &file->buf) < 0) {
407 ERROR("Unable to check file \"%s\": %s", filename, fr_syserror(errno));
408 talloc_free(file);
409 return false;
410 }
411
412 if (!check_perms) {
413 talloc_free(file);
414 return true;
415 }
416
417 #ifdef S_IWOTH
418 if ((file->buf.st_mode & S_IWOTH) != 0) {
419 ERROR("Configuration file %s is globally writable. "
420 "Refusing to start due to insecure configuration.", filename);
421 talloc_free(file);
422 return false;
423 }
424 #endif
425
426 /*
427 * It's OK to include the same file twice...
428 */
429 if (!rbtree_insert(tree, file)) {
430 talloc_free(file);
431 }
432
433 return true;
434
435 }
436
437
438 typedef struct cf_file_callback_t {
439 int rcode;
440 rb_walker_t callback;
441 CONF_SECTION *modules;
442 } cf_file_callback_t;
443
444
445 /*
446 * Return 0 for keep going, 1 for stop.
447 */
file_callback(void * ctx,void * data)448 static int file_callback(void *ctx, void *data)
449 {
450 cf_file_callback_t *cb = ctx;
451 cf_file_t *file = data;
452 struct stat buf;
453
454 /*
455 * The file doesn't exist or we can no longer read it.
456 */
457 if (stat(file->filename, &buf) < 0) {
458 cb->rcode = CF_FILE_ERROR;
459 return 1;
460 }
461
462 /*
463 * The file changed, we'll need to re-read it.
464 */
465 if (file->buf.st_mtime != buf.st_mtime) {
466 if (cb->callback(cb->modules, file->cs)) {
467 cb->rcode |= CF_FILE_MODULE;
468 DEBUG3("HUP: Changed module file %s", file->filename);
469 } else {
470 DEBUG3("HUP: Changed config file %s", file->filename);
471 cb->rcode |= CF_FILE_CONFIG;
472 }
473
474 /*
475 * Presume that the file will be immediately
476 * re-read, so we update the mtime appropriately.
477 */
478 file->buf.st_mtime = buf.st_mtime;
479 }
480
481 return 0;
482 }
483
484
485 /*
486 * See if any of the files have changed.
487 */
cf_file_changed(CONF_SECTION * cs,rb_walker_t callback)488 int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback)
489 {
490 CONF_DATA *cd;
491 CONF_SECTION *top;
492 cf_file_callback_t cb;
493 rbtree_t *tree;
494
495 top = cf_top_section(cs);
496 cd = cf_data_find_internal(top, "filename", 0);
497 if (!cd) return true;
498
499 tree = cd->data;
500
501 cb.rcode = CF_FILE_NONE;
502 cb.callback = callback;
503 cb.modules = cf_section_sub_find(cs, "modules");
504
505 (void) rbtree_walk(tree, RBTREE_IN_ORDER, file_callback, &cb);
506
507 return cb.rcode;
508 }
509
_cf_section_free(CONF_SECTION * cs)510 static int _cf_section_free(CONF_SECTION *cs)
511 {
512 /*
513 * Name1 and name2 are allocated contiguous with
514 * cs.
515 */
516 if (cs->pair_tree) {
517 rbtree_free(cs->pair_tree);
518 cs->pair_tree = NULL;
519 }
520 if (cs->section_tree) {
521 rbtree_free(cs->section_tree);
522 cs->section_tree = NULL;
523 }
524 if (cs->name2_tree) {
525 rbtree_free(cs->name2_tree);
526 cs->name2_tree = NULL;
527 }
528 if (cs->data_tree) {
529 rbtree_free(cs->data_tree);
530 cs->data_tree = NULL;
531 }
532
533 return 0;
534 }
535
536 /** Allocate a CONF_PAIR
537 *
538 * @param parent CONF_SECTION to hang this CONF_PAIR off of.
539 * @param attr name.
540 * @param value of CONF_PAIR.
541 * @param op T_OP_EQ, T_OP_SET etc.
542 * @param lhs_type T_BARE_WORD, T_DOUBLE_QUOTED_STRING, T_BACK_QUOTED_STRING
543 * @param rhs_type T_BARE_WORD, T_DOUBLE_QUOTED_STRING, T_BACK_QUOTED_STRING
544 * @return NULL on error, else a new CONF_SECTION parented by parent.
545 */
cf_pair_alloc(CONF_SECTION * parent,char const * attr,char const * value,FR_TOKEN op,FR_TOKEN lhs_type,FR_TOKEN rhs_type)546 CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value,
547 FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type)
548 {
549 CONF_PAIR *cp;
550
551 rad_assert(fr_equality_op[op] || fr_assignment_op[op]);
552 if (!attr) return NULL;
553
554 cp = talloc_zero(parent, CONF_PAIR);
555 if (!cp) return NULL;
556
557 cp->item.type = CONF_ITEM_PAIR;
558 cp->item.parent = parent;
559 cp->lhs_type = lhs_type;
560 cp->rhs_type = rhs_type;
561 cp->op = op;
562
563 cp->attr = talloc_typed_strdup(cp, attr);
564 if (!cp->attr) {
565 error:
566 talloc_free(cp);
567 return NULL;
568 }
569
570 if (value) {
571 cp->value = talloc_typed_strdup(cp, value);
572 if (!cp->value) goto error;
573 }
574
575 return cp;
576 }
577
578 /** Duplicate a CONF_PAIR
579 *
580 * @param parent to allocate new pair in.
581 * @param cp to duplicate.
582 * @return NULL on error, else a duplicate of the input pair.
583 */
cf_pair_dup(CONF_SECTION * parent,CONF_PAIR * cp)584 CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp)
585 {
586 CONF_PAIR *new;
587
588 rad_assert(parent);
589 rad_assert(cp);
590
591 new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp),
592 cp->op, cp->lhs_type, cp->rhs_type);
593 if (!new) return NULL;
594
595 new->parsed = cp->parsed;
596 new->item.lineno = cp->item.lineno;
597
598 /*
599 * Avoid mallocs if possible.
600 */
601 if (!cp->item.filename || (parent->item.filename && !strcmp(parent->item.filename, cp->item.filename))) {
602 new->item.filename = parent->item.filename;
603 } else {
604 new->item.filename = talloc_strdup(new, cp->item.filename);
605 }
606
607 return new;
608 }
609
610 /** Add a configuration pair to a section
611 *
612 * @param parent section to add pair to.
613 * @param cp to add.
614 */
cf_pair_add(CONF_SECTION * parent,CONF_PAIR * cp)615 void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp)
616 {
617 cf_item_add(parent, cf_pair_to_item(cp));
618 }
619
620 /** Allocate a CONF_SECTION
621 *
622 * @param parent CONF_SECTION to hang this CONF_SECTION off of.
623 * @param name1 Primary name.
624 * @param name2 Secondary name.
625 * @return NULL on error, else a new CONF_SECTION parented by parent.
626 */
cf_section_alloc(CONF_SECTION * parent,char const * name1,char const * name2)627 CONF_SECTION *cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2)
628 {
629 CONF_SECTION *cs;
630 char buffer[1024];
631
632 if (!name1) return NULL;
633
634 if (name2 && parent) {
635 if (strchr(name2, '$')) {
636 name2 = cf_expand_variables(parent->item.filename,
637 &parent->item.lineno,
638 parent,
639 buffer, sizeof(buffer), name2, NULL);
640 if (!name2) {
641 ERROR("Failed expanding section name");
642 return NULL;
643 }
644 }
645 }
646
647 cs = talloc_zero(parent, CONF_SECTION);
648 if (!cs) return NULL;
649
650 cs->item.type = CONF_ITEM_SECTION;
651 cs->item.parent = parent;
652
653 cs->name1 = talloc_typed_strdup(cs, name1);
654 if (!cs->name1) {
655 error:
656 talloc_free(cs);
657 return NULL;
658 }
659
660 if (name2) {
661 cs->name2 = talloc_typed_strdup(cs, name2);
662 if (!cs->name2) goto error;
663 }
664
665 cs->pair_tree = rbtree_create(cs, pair_cmp, NULL, 0);
666 if (!cs->pair_tree) goto error;
667
668 talloc_set_destructor(cs, _cf_section_free);
669
670 /*
671 * Don't create a data tree, it may not be needed.
672 */
673
674 /*
675 * Don't create the section tree here, it may not
676 * be needed.
677 */
678
679 if (parent) cs->depth = parent->depth + 1;
680
681 return cs;
682 }
683
684 /** Duplicate a configuration section
685 *
686 * @note recursively duplicates any child sections.
687 * @note does not duplicate any data associated with a section, or its child sections.
688 *
689 * @param parent section (may be NULL).
690 * @param cs to duplicate.
691 * @param name1 of new section.
692 * @param name2 of new section.
693 * @param copy_meta Copy additional meta data for a section (like template, base, depth and variables).
694 * @return a duplicate of the existing section, or NULL on error.
695 */
cf_section_dup(CONF_SECTION * parent,CONF_SECTION const * cs,char const * name1,char const * name2,bool copy_meta)696 CONF_SECTION *cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs,
697 char const *name1, char const *name2, bool copy_meta)
698 {
699 CONF_SECTION *new, *subcs;
700 CONF_PAIR *cp;
701 CONF_ITEM *ci;
702
703 new = cf_section_alloc(parent, name1, name2);
704
705 if (copy_meta) {
706 new->template = cs->template;
707 new->base = cs->base;
708 new->depth = cs->depth;
709 new->variables = cs->variables;
710 }
711
712 new->item.lineno = cs->item.lineno;
713
714 if (!cs->item.filename || (parent && (strcmp(parent->item.filename, cs->item.filename) == 0))) {
715 new->item.filename = parent->item.filename;
716 } else {
717 new->item.filename = talloc_strdup(new, cs->item.filename);
718 }
719
720 for (ci = cs->children; ci; ci = ci->next) {
721 switch (ci->type) {
722 case CONF_ITEM_SECTION:
723 subcs = cf_item_to_section(ci);
724 subcs = cf_section_dup(new, subcs,
725 cf_section_name1(subcs), cf_section_name2(subcs),
726 copy_meta);
727 if (!subcs) {
728 talloc_free(new);
729 return NULL;
730 }
731 cf_section_add(new, subcs);
732 break;
733
734 case CONF_ITEM_PAIR:
735 cp = cf_pair_dup(new, cf_item_to_pair(ci));
736 if (!cp) {
737 talloc_free(new);
738 return NULL;
739 }
740 cf_pair_add(new, cp);
741 break;
742
743 case CONF_ITEM_DATA: /* Skip data */
744 break;
745
746 case CONF_ITEM_INVALID:
747 rad_assert(0);
748 }
749 }
750
751 return new;
752 }
753
cf_section_add(CONF_SECTION * parent,CONF_SECTION * cs)754 void cf_section_add(CONF_SECTION *parent, CONF_SECTION *cs)
755 {
756 cf_item_add(parent, &(cs->item));
757 }
758
759 /** Replace pair in a given section with a new pair, of the given value.
760 *
761 * @param cs to replace pair in.
762 * @param cp to replace.
763 * @param value New value to assign to cp.
764 * @return 0 on success, -1 on failure.
765 */
cf_pair_replace(CONF_SECTION * cs,CONF_PAIR * cp,char const * value)766 int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
767 {
768 CONF_PAIR *newp;
769 CONF_ITEM *ci, *cn, **last;
770
771 newp = cf_pair_alloc(cs, cp->attr, value, cp->op, cp->lhs_type, cp->rhs_type);
772 if (!newp) return -1;
773
774 ci = &(cp->item);
775 cn = &(newp->item);
776
777 /*
778 * Find the old one from the linked list, and replace it
779 * with the new one.
780 */
781 for (last = &cs->children; (*last) != NULL; last = &(*last)->next) {
782 if (*last == ci) {
783 cn->next = (*last)->next;
784 *last = cn;
785 ci->next = NULL;
786 break;
787 }
788 }
789
790 rbtree_deletebydata(cs->pair_tree, ci);
791
792 rbtree_insert(cs->pair_tree, cn);
793
794 return 0;
795 }
796
797
798 /*
799 * Add an item to a configuration section.
800 */
cf_item_add(CONF_SECTION * cs,CONF_ITEM * ci)801 void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci)
802 {
803 #ifndef NDEBUG
804 CONF_ITEM *first = ci;
805 #endif
806
807 rad_assert((void *)cs != (void *)ci);
808
809 if (!cs || !ci) return;
810
811 if (!cs->children) {
812 rad_assert(cs->tail == NULL);
813 cs->children = ci;
814 } else {
815 rad_assert(cs->tail != NULL);
816 cs->tail->next = ci;
817 }
818
819 /*
820 * Update the trees (and tail) for each item added.
821 */
822 for (/* nothing */; ci != NULL; ci = ci->next) {
823 rad_assert(ci->next != first); /* simple cycle detection */
824
825 cs->tail = ci;
826
827 /*
828 * For fast lookups, pairs and sections get
829 * added to rbtree's.
830 */
831 switch (ci->type) {
832 case CONF_ITEM_PAIR:
833 if (!rbtree_insert(cs->pair_tree, ci)) {
834 CONF_PAIR *cp = cf_item_to_pair(ci);
835
836 if (strcmp(cp->attr, "confdir") == 0) break;
837 if (!cp->value) break; /* module name, "ok", etc. */
838 }
839 break;
840
841 case CONF_ITEM_SECTION: {
842 CONF_SECTION *cs_new = cf_item_to_section(ci);
843 CONF_SECTION *name1_cs;
844
845 if (!cs->section_tree) {
846 cs->section_tree = rbtree_create(cs, section_cmp, NULL, 0);
847 if (!cs->section_tree) {
848 ERROR("Out of memory");
849 fr_exit_now(1);
850 }
851 }
852
853 name1_cs = rbtree_finddata(cs->section_tree, cs_new);
854 if (!name1_cs) {
855 if (!rbtree_insert(cs->section_tree, cs_new)) {
856 ERROR("Failed inserting section into tree");
857 fr_exit_now(1);
858 }
859 break;
860 }
861
862 /*
863 * We already have a section of
864 * this "name1". Add a new
865 * sub-section based on name2.
866 */
867 if (!name1_cs->name2_tree) {
868 name1_cs->name2_tree = rbtree_create(name1_cs, name2_cmp, NULL, 0);
869 if (!name1_cs->name2_tree) {
870 ERROR("Out of memory");
871 fr_exit_now(1);
872 }
873 }
874
875 /*
876 * We don't care if this fails.
877 * If the user tries to create
878 * two sections of the same
879 * name1/name2, the duplicate
880 * section is just silently
881 * ignored.
882 */
883 rbtree_insert(name1_cs->name2_tree, cs_new);
884 break;
885 } /* was a section */
886
887 case CONF_ITEM_DATA:
888 if (!cs->data_tree) {
889 cs->data_tree = rbtree_create(cs, data_cmp, NULL, 0);
890 }
891 if (cs->data_tree) {
892 rbtree_insert(cs->data_tree, ci);
893 }
894 break;
895
896 default: /* FIXME: assert & error! */
897 break;
898
899 } /* switch over conf types */
900 } /* loop over ci */
901 }
902
903
cf_reference_item(CONF_SECTION const * parentcs,CONF_SECTION * outercs,char const * ptr)904 CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs,
905 CONF_SECTION *outercs,
906 char const *ptr)
907 {
908 CONF_PAIR *cp;
909 CONF_SECTION *next;
910 CONF_SECTION const *cs = outercs;
911 char name[8192];
912 char *p;
913
914 if (!cs) goto no_such_item;
915
916 strlcpy(name, ptr, sizeof(name));
917 p = name;
918
919 /*
920 * ".foo" means "foo from the current section"
921 */
922 if (*p == '.') {
923 p++;
924
925 /*
926 * Just '.' means the current section
927 */
928 if (*p == '\0') {
929 return cf_section_to_item(cs);
930 }
931
932 /*
933 * ..foo means "foo from the section
934 * enclosing this section" (etc.)
935 */
936 while (*p == '.') {
937 if (cs->item.parent) {
938 cs = cs->item.parent;
939 }
940
941 /*
942 * .. means the section
943 * enclosing this section
944 */
945 if (!*++p) {
946 return cf_section_to_item(cs);
947 }
948 }
949
950 /*
951 * "foo.bar.baz" means "from the root"
952 */
953 } else if (strchr(p, '.') != NULL) {
954 if (!parentcs) goto no_such_item;
955
956 cs = parentcs;
957 }
958
959 while (*p) {
960 char *q, *r;
961
962 r = strchr(p, '[');
963 q = strchr(p, '.');
964 if (!r && !q) break;
965
966 if (r && q > r) q = NULL;
967 if (q && q < r) r = NULL;
968
969 /*
970 * Split off name2.
971 */
972 if (r) {
973 q = strchr(r + 1, ']');
974 if (!q) return NULL; /* parse error */
975
976 /*
977 * Points to foo[bar]xx: parse error,
978 * it should be foo[bar] or foo[bar].baz
979 */
980 if (q[1] && q[1] != '.') goto no_such_item;
981
982 *r = '\0';
983 *q = '\0';
984 next = cf_section_sub_find_name2(cs, p, r + 1);
985 *r = '[';
986 *q = ']';
987
988 /*
989 * Points to a named instance of a section.
990 */
991 if (!q[1]) {
992 if (!next) goto no_such_item;
993 return &(next->item);
994 }
995
996 q++; /* ensure we skip the ']' and '.' */
997
998 } else {
999 *q = '\0';
1000 next = cf_section_sub_find(cs, p);
1001 *q = '.';
1002 }
1003
1004 if (!next) break; /* it MAY be a pair in this section! */
1005
1006 cs = next;
1007 p = q + 1;
1008 }
1009
1010 if (!*p) goto no_such_item;
1011
1012 retry:
1013 /*
1014 * Find it in the current referenced
1015 * section.
1016 */
1017 cp = cf_pair_find(cs, p);
1018 if (cp) {
1019 cp->parsed = true; /* conf pairs which are referenced count as parsed */
1020 return &(cp->item);
1021 }
1022
1023 next = cf_section_sub_find(cs, p);
1024 if (next) return &(next->item);
1025
1026 /*
1027 * "foo" is "in the current section, OR in main".
1028 */
1029 if ((p == name) && (parentcs != NULL) && (cs != parentcs)) {
1030 cs = parentcs;
1031 goto retry;
1032 }
1033
1034 no_such_item:
1035 return NULL;
1036 }
1037
1038
cf_top_section(CONF_SECTION * cs)1039 CONF_SECTION *cf_top_section(CONF_SECTION *cs)
1040 {
1041 if (!cs) return NULL;
1042
1043 while (cs->item.parent != NULL) {
1044 cs = cs->item.parent;
1045 }
1046
1047 return cs;
1048 }
1049
1050
1051 /*
1052 * Expand the variables in an input string.
1053 */
cf_expand_variables(char const * cf,int * lineno,CONF_SECTION * outercs,char * output,size_t outsize,char const * input,bool * soft_fail)1054 static char const *cf_expand_variables(char const *cf, int *lineno,
1055 CONF_SECTION *outercs,
1056 char *output, size_t outsize,
1057 char const *input, bool *soft_fail)
1058 {
1059 char *p;
1060 char const *end, *ptr;
1061 CONF_SECTION const *parentcs;
1062 char name[8192];
1063
1064 if (soft_fail) *soft_fail = false;
1065
1066 /*
1067 * Find the master parent conf section.
1068 * We can't use main_config.config, because we're in the
1069 * process of re-building it, and it isn't set up yet...
1070 */
1071 parentcs = cf_top_section(outercs);
1072
1073 p = output;
1074 ptr = input;
1075 while (*ptr) {
1076 /*
1077 * Ignore anything other than "${"
1078 */
1079 if ((*ptr == '$') && (ptr[1] == '{')) {
1080 CONF_ITEM *ci;
1081 CONF_PAIR *cp;
1082 char *q;
1083
1084 /*
1085 * FIXME: Add support for ${foo:-bar},
1086 * like in xlat.c
1087 */
1088
1089 /*
1090 * Look for trailing '}', and log a
1091 * warning for anything that doesn't match,
1092 * and exit with a fatal error.
1093 */
1094 end = strchr(ptr, '}');
1095 if (end == NULL) {
1096 *p = '\0';
1097 ERROR("%s[%d]: Variable expansion missing }",
1098 cf, *lineno);
1099 return NULL;
1100 }
1101
1102 ptr += 2;
1103
1104 /*
1105 * Can't really happen because input lines are
1106 * capped at 8k, which is sizeof(name)
1107 */
1108 if ((size_t) (end - ptr) >= sizeof(name)) {
1109 ERROR("%s[%d]: Reference string is too large",
1110 cf, *lineno);
1111 return NULL;
1112 }
1113
1114 memcpy(name, ptr, end - ptr);
1115 name[end - ptr] = '\0';
1116
1117 q = strchr(name, ':');
1118 if (q) {
1119 *(q++) = '\0';
1120 }
1121
1122 ci = cf_reference_item(parentcs, outercs, name);
1123 if (!ci) {
1124 if (soft_fail) *soft_fail = true;
1125 ERROR("%s[%d]: Reference \"${%s}\" not found", cf, *lineno, name);
1126 return NULL;
1127 }
1128
1129 /*
1130 * The expansion doesn't refer to another item or section
1131 * it's the property of a section.
1132 */
1133 if (q) {
1134 CONF_SECTION *mycs = cf_item_to_section(ci);
1135
1136 if (ci->type != CONF_ITEM_SECTION) {
1137 ERROR("%s[%d]: Can only reference properties of sections", cf, *lineno);
1138 return NULL;
1139 }
1140
1141 switch (fr_str2int(conf_property_name, q, CONF_PROPERTY_INVALID)) {
1142 case CONF_PROPERTY_NAME:
1143 strcpy(p, mycs->name1);
1144 break;
1145
1146 case CONF_PROPERTY_INSTANCE:
1147 strcpy(p, mycs->name2 ? mycs->name2 : mycs->name1);
1148 break;
1149
1150 default:
1151 ERROR("%s[%d]: Invalid property '%s'", cf, *lineno, q);
1152 return NULL;
1153 }
1154 p += strlen(p);
1155 ptr = end + 1;
1156
1157 } else if (ci->type == CONF_ITEM_PAIR) {
1158 /*
1159 * Substitute the value of the variable.
1160 */
1161 cp = cf_item_to_pair(ci);
1162
1163 /*
1164 * If the thing we reference is
1165 * marked up as being expanded in
1166 * pass2, don't expand it now.
1167 * Let it be expanded in pass2.
1168 */
1169 if (cp->pass2) {
1170 if (soft_fail) *soft_fail = true;
1171
1172 ERROR("%s[%d]: Reference \"%s\" points to a variable which has not been expanded.",
1173 cf, *lineno, input);
1174 return NULL;
1175 }
1176
1177 /*
1178 * Might as well make
1179 * non-existent string be the
1180 * empty string.
1181 */
1182 if (!cp->value) {
1183 *p = '\0';
1184 goto skip_value;
1185 }
1186
1187 if (p + strlen(cp->value) >= output + outsize) {
1188 ERROR("%s[%d]: Reference \"%s\" is too long",
1189 cf, *lineno, input);
1190 return NULL;
1191 }
1192
1193 strcpy(p, cp->value);
1194 p += strlen(p);
1195 skip_value:
1196 ptr = end + 1;
1197
1198 } else if (ci->type == CONF_ITEM_SECTION) {
1199 CONF_SECTION *subcs;
1200
1201 /*
1202 * Adding an entry again to a
1203 * section is wrong. We don't
1204 * want an infinite loop.
1205 */
1206 if (ci->parent == outercs) {
1207 ERROR("%s[%d]: Cannot reference different item in same section", cf, *lineno);
1208 return NULL;
1209 }
1210
1211 /*
1212 * Copy the section instead of
1213 * referencing it.
1214 */
1215 subcs = cf_item_to_section(ci);
1216 subcs = cf_section_dup(outercs, subcs,
1217 cf_section_name1(subcs), cf_section_name2(subcs),
1218 false);
1219 if (!subcs) {
1220 ERROR("%s[%d]: Failed copying reference %s", cf, *lineno, name);
1221 return NULL;
1222 }
1223
1224 subcs->item.filename = ci->filename;
1225 subcs->item.lineno = ci->lineno;
1226 cf_item_add(outercs, &(subcs->item));
1227
1228 ptr = end + 1;
1229
1230 } else {
1231 ERROR("%s[%d]: Reference \"%s\" type is invalid", cf, *lineno, input);
1232 return NULL;
1233 }
1234 } else if (strncmp(ptr, "$ENV{", 5) == 0) {
1235 char *env;
1236
1237 ptr += 5;
1238
1239 /*
1240 * Look for trailing '}', and log a
1241 * warning for anything that doesn't match,
1242 * and exit with a fatal error.
1243 */
1244 end = strchr(ptr, '}');
1245 if (end == NULL) {
1246 *p = '\0';
1247 ERROR("%s[%d]: Environment variable expansion missing }",
1248 cf, *lineno);
1249 return NULL;
1250 }
1251
1252 /*
1253 * Can't really happen because input lines are
1254 * capped at 8k, which is sizeof(name)
1255 */
1256 if ((size_t) (end - ptr) >= sizeof(name)) {
1257 ERROR("%s[%d]: Environment variable name is too large",
1258 cf, *lineno);
1259 return NULL;
1260 }
1261
1262 memcpy(name, ptr, end - ptr);
1263 name[end - ptr] = '\0';
1264
1265 /*
1266 * Get the environment variable.
1267 * If none exists, then make it an empty string.
1268 */
1269 env = getenv(name);
1270 if (env == NULL) {
1271 *name = '\0';
1272 env = name;
1273 }
1274
1275 if (p + strlen(env) >= output + outsize) {
1276 ERROR("%s[%d]: Reference \"%s\" is too long",
1277 cf, *lineno, input);
1278 return NULL;
1279 }
1280
1281 strcpy(p, env);
1282 p += strlen(p);
1283 ptr = end + 1;
1284
1285 } else {
1286 /*
1287 * Copy it over verbatim.
1288 */
1289 *(p++) = *(ptr++);
1290 }
1291
1292
1293 if (p >= (output + outsize)) {
1294 ERROR("%s[%d]: Reference \"%s\" is too long",
1295 cf, *lineno, input);
1296 return NULL;
1297 }
1298 } /* loop over all of the input string. */
1299
1300 *p = '\0';
1301
1302 return output;
1303 }
1304
1305 static char const parse_spaces[] = " ";
1306
1307 /** Validation function for ipaddr conffile types
1308 *
1309 */
fr_item_validate_ipaddr(CONF_SECTION * cs,char const * name,PW_TYPE type,char const * value,fr_ipaddr_t * ipaddr)1310 static inline int fr_item_validate_ipaddr(CONF_SECTION *cs, char const *name, PW_TYPE type, char const *value,
1311 fr_ipaddr_t *ipaddr)
1312 {
1313 char ipbuf[128];
1314
1315 if (strcmp(value, "*") == 0) {
1316 cf_log_info(cs, "%.*s\t%s = *", cs->depth, parse_spaces, name);
1317 } else if (strspn(value, ".0123456789abdefABCDEF:%[]/") == strlen(value)) {
1318 cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, name, value);
1319 } else {
1320 cf_log_info(cs, "%.*s\t%s = %s IPv%s address [%s]", cs->depth, parse_spaces, name, value,
1321 (ipaddr->af == AF_INET ? "4" : " 6"), ip_ntoh(ipaddr, ipbuf, sizeof(ipbuf)));
1322 }
1323
1324 switch (type) {
1325 case PW_TYPE_IPV4_ADDR:
1326 case PW_TYPE_IPV6_ADDR:
1327 case PW_TYPE_COMBO_IP_ADDR:
1328 switch (ipaddr->af) {
1329 case AF_INET:
1330 if (ipaddr->prefix == 32) return 0;
1331
1332 cf_log_err(&(cs->item), "Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted for non-prefix types",
1333 ipaddr->prefix);
1334 break;
1335
1336 case AF_INET6:
1337 if (ipaddr->prefix == 128) return 0;
1338
1339 cf_log_err(&(cs->item), "Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted for non-prefix types",
1340 ipaddr->prefix);
1341 break;
1342
1343
1344 default:
1345 cf_log_err(&(cs->item), "Unknown address (%d) family passed for parsing IP address.", ipaddr->af);
1346 break;
1347 }
1348
1349 return -1;
1350
1351 default:
1352 break;
1353 }
1354
1355 return 0;
1356 }
1357
1358 /** Parses a #CONF_PAIR into a C data type, with a default value.
1359 *
1360 * Takes fields from a #CONF_PARSER struct and uses them to parse the string value
1361 * of a #CONF_PAIR into a C data type matching the type argument.
1362 *
1363 * The format of the types are the same as #value_data_t types.
1364 *
1365 * @note The dflt value will only be used if no matching #CONF_PAIR is found. Empty strings will not
1366 * result in the dflt value being used.
1367 *
1368 * **PW_TYPE to data type mappings**
1369 * | PW_TYPE | Data type | Dynamically allocated |
1370 * | ----------------------- | ------------------ | ---------------------- |
1371 * | PW_TYPE_TMPL | ``vp_tmpl_t`` | Yes |
1372 * | PW_TYPE_BOOLEAN | ``bool`` | No |
1373 * | PW_TYPE_INTEGER | ``uint32_t`` | No |
1374 * | PW_TYPE_SHORT | ``uint16_t`` | No |
1375 * | PW_TYPE_INTEGER64 | ``uint64_t`` | No |
1376 * | PW_TYPE_SIGNED | ``int32_t`` | No |
1377 * | PW_TYPE_STRING | ``char const *`` | Yes |
1378 * | PW_TYPE_IPV4_ADDR | ``fr_ipaddr_t`` | No |
1379 * | PW_TYPE_IPV4_PREFIX | ``fr_ipaddr_t`` | No |
1380 * | PW_TYPE_IPV6_ADDR | ``fr_ipaddr_t`` | No |
1381 * | PW_TYPE_IPV6_PREFIX | ``fr_ipaddr_t`` | No |
1382 * | PW_TYPE_COMBO_IP_ADDR | ``fr_ipaddr_t`` | No |
1383 * | PW_TYPE_COMBO_IP_PREFIX | ``fr_ipaddr_t`` | No |
1384 * | PW_TYPE_TIMEVAL | ``struct timeval`` | No |
1385 *
1386 * @param cs to search for matching #CONF_PAIR in.
1387 * @param name of #CONF_PAIR to search for.
1388 * @param type Data type to parse #CONF_PAIR value as.
1389 * Should be one of the following ``data`` types, and one or more of the following ``flag`` types or'd together:
1390 * - ``data`` #PW_TYPE_TMPL - @copybrief PW_TYPE_TMPL
1391 * Feeds the value into #tmpl_afrom_str. Value can be
1392 * obtained when processing requests, with #tmpl_expand or #tmpl_aexpand.
1393 * - ``data`` #PW_TYPE_BOOLEAN - @copybrief PW_TYPE_BOOLEAN
1394 * - ``data`` #PW_TYPE_INTEGER - @copybrief PW_TYPE_INTEGER
1395 * - ``data`` #PW_TYPE_SHORT - @copybrief PW_TYPE_SHORT
1396 * - ``data`` #PW_TYPE_INTEGER64 - @copybrief PW_TYPE_INTEGER64
1397 * - ``data`` #PW_TYPE_SIGNED - @copybrief PW_TYPE_SIGNED
1398 * - ``data`` #PW_TYPE_STRING - @copybrief PW_TYPE_STRING
1399 * - ``data`` #PW_TYPE_IPV4_ADDR - @copybrief PW_TYPE_IPV4_ADDR (IPv4 address with prefix 32).
1400 * - ``data`` #PW_TYPE_IPV4_PREFIX - @copybrief PW_TYPE_IPV4_PREFIX (IPv4 address with variable prefix).
1401 * - ``data`` #PW_TYPE_IPV6_ADDR - @copybrief PW_TYPE_IPV6_ADDR (IPv6 address with prefix 128).
1402 * - ``data`` #PW_TYPE_IPV6_PREFIX - @copybrief PW_TYPE_IPV6_PREFIX (IPv6 address with variable prefix).
1403 * - ``data`` #PW_TYPE_COMBO_IP_ADDR - @copybrief PW_TYPE_COMBO_IP_ADDR (IPv4/IPv6 address with
1404 * prefix 32/128).
1405 * - ``data`` #PW_TYPE_COMBO_IP_PREFIX - @copybrief PW_TYPE_COMBO_IP_PREFIX (IPv4/IPv6 address with
1406 * variable prefix).
1407 * - ``data`` #PW_TYPE_TIMEVAL - @copybrief PW_TYPE_TIMEVAL
1408 * - ``flag`` #PW_TYPE_DEPRECATED - @copybrief PW_TYPE_DEPRECATED
1409 * - ``flag`` #PW_TYPE_REQUIRED - @copybrief PW_TYPE_REQUIRED
1410 * - ``flag`` #PW_TYPE_ATTRIBUTE - @copybrief PW_TYPE_ATTRIBUTE
1411 * - ``flag`` #PW_TYPE_SECRET - @copybrief PW_TYPE_SECRET
1412 * - ``flag`` #PW_TYPE_FILE_INPUT - @copybrief PW_TYPE_FILE_INPUT
1413 * - ``flag`` #PW_TYPE_NOT_EMPTY - @copybrief PW_TYPE_NOT_EMPTY
1414 * @param data Pointer to a global variable, or pointer to a field in the struct being populated with values.
1415 * @param dflt value to use, if no #CONF_PAIR is found.
1416 * @return
1417 * - 1 if default value was used.
1418 * - 0 on success.
1419 * - -1 on error.
1420 * - -2 if deprecated.
1421 */
cf_item_parse(CONF_SECTION * cs,char const * name,unsigned int type,void * data,char const * dflt)1422 int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt)
1423 {
1424 int rcode;
1425 bool deprecated, required, attribute, secret, file_input, cant_be_empty, tmpl, multi, file_exists;
1426 char **q;
1427 char const *value;
1428 CONF_PAIR *cp = NULL;
1429 fr_ipaddr_t *ipaddr;
1430 char buffer[8192];
1431 CONF_ITEM *c_item;
1432
1433 if (!cs) {
1434 cf_log_err(&(cs->item), "No enclosing section for configuration item \"%s\"", name);
1435 return -1;
1436 }
1437
1438 c_item = &cs->item;
1439
1440 deprecated = (type & PW_TYPE_DEPRECATED);
1441 required = (type & PW_TYPE_REQUIRED);
1442 attribute = (type & PW_TYPE_ATTRIBUTE);
1443 secret = (type & PW_TYPE_SECRET);
1444 file_input = (type == PW_TYPE_FILE_INPUT); /* check, not and */
1445 file_exists = (type == PW_TYPE_FILE_EXISTS); /* check, not and */
1446 cant_be_empty = (type & PW_TYPE_NOT_EMPTY);
1447 tmpl = (type & PW_TYPE_TMPL);
1448 multi = (type & PW_TYPE_MULTI);
1449
1450 if (attribute) required = true;
1451 if (required) cant_be_empty = true; /* May want to review this in the future... */
1452
1453 /*
1454 * Everything except templates must have a base type.
1455 */
1456 if (!(type & 0xff) && !tmpl) {
1457 cf_log_err(c_item, "Configuration item \"%s\" must have a data type", name);
1458 return -1;
1459 }
1460
1461 type &= 0xff; /* normal types are small */
1462
1463 rcode = 0;
1464
1465 cp = cf_pair_find(cs, name);
1466
1467 /*
1468 * No pairs match the configuration item name in the current
1469 * section, use the default value.
1470 */
1471 if (!cp) {
1472 if (deprecated) return 0; /* Don't set the default value */
1473
1474 rcode = 1;
1475 value = dflt;
1476 /*
1477 * Something matched, used the CONF_PAIR value.
1478 */
1479 } else {
1480 CONF_PAIR *next = cp;
1481
1482 value = cp->value;
1483 cp->parsed = true;
1484 c_item = &cp->item;
1485
1486 if (deprecated) {
1487 cf_log_err(c_item, "Configuration item \"%s\" is deprecated", name);
1488 return -2;
1489 }
1490
1491 /*
1492 * A quick check to see if the next item is the same.
1493 */
1494 if (!multi && cp->item.next && (cp->item.next->type == CONF_ITEM_PAIR)) {
1495 next = cf_item_to_pair(cp->item.next);
1496
1497 if (strcmp(next->attr, name) == 0) {
1498 WARN("%s[%d]: Ignoring duplicate configuration item '%s'",
1499 next->item.filename ? next->item.filename : "unknown",
1500 next->item.lineno, name);
1501 }
1502 }
1503
1504 if (multi) {
1505 while ((next = cf_pair_find_next(cs, next, name)) != NULL) {
1506 /*
1507 * @fixme We should actually validate
1508 * the value of the pairs too
1509 */
1510 next->parsed = true;
1511 };
1512 }
1513 }
1514
1515 if (!value) {
1516 if (required) {
1517 cf_log_err(c_item, "Configuration item \"%s\" must have a value", name);
1518
1519 return -1;
1520 }
1521 return rcode;
1522 }
1523
1524 if ((value[0] == '\0') && cant_be_empty) {
1525 cant_be_empty:
1526 cf_log_err(c_item, "Configuration item \"%s\" must not be empty (zero length)", name);
1527 if (!required) cf_log_err(c_item, "Comment item to silence this message");
1528
1529 return -1;
1530 }
1531
1532
1533 /*
1534 * Process a value as a LITERAL template. Once all of
1535 * the attrs and xlats are defined, the pass2 code
1536 * converts it to the appropriate type.
1537 */
1538 if (tmpl) {
1539 vp_tmpl_t *vpt;
1540
1541 if (!value) {
1542 *(vp_tmpl_t **)data = NULL;
1543 return 0;
1544 }
1545
1546 rad_assert(!attribute);
1547 vpt = tmpl_alloc(cs, TMPL_TYPE_LITERAL, value, strlen(value));
1548 *(vp_tmpl_t **)data = vpt;
1549
1550 return 0;
1551 }
1552
1553 switch (type) {
1554 case PW_TYPE_BOOLEAN:
1555 /*
1556 * Allow yes/no, true/false, and on/off
1557 */
1558 if ((strcasecmp(value, "yes") == 0) ||
1559 (strcasecmp(value, "true") == 0) ||
1560 (strcasecmp(value, "on") == 0)) {
1561 *(bool *)data = true;
1562 } else if ((strcasecmp(value, "no") == 0) ||
1563 (strcasecmp(value, "false") == 0) ||
1564 (strcasecmp(value, "off") == 0)) {
1565 *(bool *)data = false;
1566 } else {
1567 *(bool *)data = false;
1568 cf_log_err(&(cs->item), "Invalid value \"%s\" for boolean "
1569 "variable %s", value, name);
1570 return -1;
1571 }
1572 cf_log_info(cs, "%.*s\t%s = %s",
1573 cs->depth, parse_spaces, name, value);
1574 break;
1575
1576 case PW_TYPE_INTEGER:
1577 {
1578 unsigned long v = strtoul(value, 0, 0);
1579
1580 /*
1581 * Restrict integer values to 0-INT32_MAX, this means
1582 * it will always be safe to cast them to a signed type
1583 * for comparisons, and imposes the same range limit as
1584 * before we switched to using an unsigned type to
1585 * represent config item integers.
1586 */
1587 if (v > INT32_MAX) {
1588 cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", value,
1589 name, INT32_MAX);
1590 return -1;
1591 }
1592
1593 *(uint32_t *)data = v;
1594 cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, name, *(uint32_t *)data);
1595 }
1596 break;
1597
1598 case PW_TYPE_BYTE:
1599 {
1600 unsigned long v = strtoul(value, 0, 0);
1601
1602 if (v > UINT8_MAX) {
1603 cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", value,
1604 name, UINT8_MAX);
1605 return -1;
1606 }
1607 *(uint8_t *)data = (uint8_t) v;
1608 cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, name, *(uint8_t *)data);
1609 }
1610 break;
1611
1612 case PW_TYPE_SHORT:
1613 {
1614 unsigned long v = strtoul(value, 0, 0);
1615
1616 if (v > UINT16_MAX) {
1617 cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", value,
1618 name, UINT16_MAX);
1619 return -1;
1620 }
1621 *(uint16_t *)data = (uint16_t) v;
1622 cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, name, *(uint16_t *)data);
1623 }
1624 break;
1625
1626 case PW_TYPE_INTEGER64:
1627 *(uint64_t *)data = strtoull(value, 0, 0);
1628 cf_log_info(cs, "%.*s\t%s = %" PRIu64, cs->depth, parse_spaces, name, *(uint64_t *)data);
1629 break;
1630
1631 case PW_TYPE_SIGNED:
1632 *(int32_t *)data = strtol(value, 0, 0);
1633 cf_log_info(cs, "%.*s\t%s = %d", cs->depth, parse_spaces, name, *(int32_t *)data);
1634 break;
1635
1636 case PW_TYPE_STRING:
1637 q = (char **) data;
1638 if (*q != NULL) {
1639 talloc_free(*q);
1640 }
1641
1642 /*
1643 * Expand variables which haven't already been
1644 * expanded automagically when the configuration
1645 * file was read.
1646 */
1647 if (value == dflt) {
1648 int lineno = 0;
1649
1650 lineno = cs->item.lineno;
1651
1652 value = cf_expand_variables("<internal>",
1653 &lineno,
1654 cs, buffer, sizeof(buffer),
1655 value, NULL);
1656 if (!value) {
1657 cf_log_err(&(cs->item),"Failed expanding variable %s", name);
1658 return -1;
1659 }
1660 }
1661
1662 if (cant_be_empty && (value[0] == '\0')) goto cant_be_empty;
1663
1664 if (attribute) {
1665 if (!dict_attrbyname(value)) {
1666 if (!cp) {
1667 cf_log_err(&(cs->item), "No such attribute '%s' for configuration '%s'",
1668 value, name);
1669 } else {
1670 cf_log_err(&(cp->item), "No such attribute '%s'", value);
1671 }
1672 return -1;
1673 }
1674 }
1675
1676 /*
1677 * Hide secrets when using "radiusd -X".
1678 */
1679 if (secret && (rad_debug_lvl <= 2)) {
1680 cf_log_info(cs, "%.*s\t%s = <<< secret >>>",
1681 cs->depth, parse_spaces, name);
1682 } else {
1683 cf_log_info(cs, "%.*s\t%s = \"%s\"",
1684 cs->depth, parse_spaces, name, value ? value : "(null)");
1685 }
1686 *q = value ? talloc_typed_strdup(cs, value) : NULL;
1687
1688 /*
1689 * If there's data AND it's an input file, check
1690 * that we can read it. This check allows errors
1691 * to be caught as early as possible, during
1692 * server startup.
1693 */
1694 if (*q && file_input && !cf_file_check(cs, *q, true)) {
1695 cf_log_err(&(cs->item), "Failed parsing configuration item \"%s\"", name);
1696 return -1;
1697 }
1698
1699 if (*q && file_exists && !cf_file_check(cs, *q, false)) {
1700 cf_log_err(&(cs->item), "Failed parsing configuration item \"%s\"", name);
1701 return -1;
1702 }
1703 break;
1704
1705 case PW_TYPE_IPV4_ADDR:
1706 case PW_TYPE_IPV4_PREFIX:
1707 ipaddr = data;
1708
1709 if (fr_pton4(ipaddr, value, -1, true, false) < 0) {
1710 failed:
1711 cf_log_err(&(cs->item), "Failed parsing configuration item \"%s\" - %s", name, fr_strerror());
1712 return -1;
1713 }
1714 if (fr_item_validate_ipaddr(cs, name, type, value, ipaddr) < 0) return -1;
1715 break;
1716
1717 case PW_TYPE_IPV6_ADDR:
1718 case PW_TYPE_IPV6_PREFIX:
1719 ipaddr = data;
1720
1721 if (fr_pton6(ipaddr, value, -1, true, false) < 0) goto failed;
1722 if (fr_item_validate_ipaddr(cs, name, type, value, ipaddr) < 0) return -1;
1723 break;
1724
1725 case PW_TYPE_COMBO_IP_ADDR:
1726 case PW_TYPE_COMBO_IP_PREFIX:
1727 ipaddr = data;
1728
1729 if (fr_pton(ipaddr, value, -1, AF_UNSPEC, true) < 0) goto failed;
1730 if (fr_item_validate_ipaddr(cs, name, type, value, ipaddr) < 0) return -1;
1731 break;
1732
1733 case PW_TYPE_TIMEVAL: {
1734 int sec;
1735 char *end;
1736 struct timeval tv;
1737
1738 sec = strtoul(value, &end, 10);
1739 tv.tv_sec = sec;
1740 tv.tv_usec = 0;
1741 if (*end == '.') {
1742 size_t len;
1743
1744 len = strlen(end + 1);
1745
1746 if (len > 6) {
1747 cf_log_err(&(cs->item), "Too much precision for timeval");
1748 return -1;
1749 }
1750
1751 /*
1752 * If they write "0.1", that means
1753 * "10000" microseconds.
1754 */
1755 sec = strtoul(end + 1, NULL, 10);
1756 while (len < 6) {
1757 sec *= 10;
1758 len++;
1759 }
1760
1761 tv.tv_usec = sec;
1762 }
1763 cf_log_info(cs, "%.*s\t%s = %d.%06d",
1764 cs->depth, parse_spaces, name, (int) tv.tv_sec, (int) tv.tv_usec);
1765 memcpy(data, &tv, sizeof(tv));
1766 }
1767 break;
1768
1769 default:
1770 /*
1771 * If we get here, it's a sanity check error.
1772 * It's not an error parsing the configuration
1773 * file.
1774 */
1775 rad_assert(type > PW_TYPE_INVALID);
1776 rad_assert(type < PW_TYPE_MAX);
1777
1778 cf_log_err(&(cs->item), "type '%s' is not supported in the configuration files",
1779 fr_int2str(dict_attr_types, type, "?Unknown?"));
1780 return -1;
1781 } /* switch over variable type */
1782
1783 if (!cp) {
1784 CONF_PAIR *cpn;
1785
1786 cpn = cf_pair_alloc(cs, name, value, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1787 if (!cpn) return -1;
1788 cpn->parsed = true;
1789 cpn->item.filename = "<internal>";
1790 cpn->item.lineno = 0;
1791 cf_item_add(cs, &(cpn->item));
1792 }
1793
1794 return rcode;
1795 }
1796
1797
1798 /*
1799 * A copy of cf_section_parse that initializes pointers before
1800 * parsing them.
1801 */
cf_section_parse_init(CONF_SECTION * cs,void * base,CONF_PARSER const * variables)1802 static void cf_section_parse_init(CONF_SECTION *cs, void *base,
1803 CONF_PARSER const *variables)
1804 {
1805 int i;
1806
1807 for (i = 0; variables[i].name != NULL; i++) {
1808 if (variables[i].type == PW_TYPE_SUBSECTION) {
1809 CONF_SECTION *subcs;
1810
1811 if (!variables[i].dflt) continue;
1812
1813 subcs = cf_section_sub_find(cs, variables[i].name);
1814
1815 /*
1816 * If there's no subsection in the
1817 * config, BUT the CONF_PARSER wants one,
1818 * then create an empty one. This is so
1819 * that we can track the strings,
1820 * etc. allocated in the subsection.
1821 */
1822 if (!subcs) {
1823 subcs = cf_section_alloc(cs, variables[i].name, NULL);
1824 if (!subcs) return;
1825
1826 subcs->item.filename = cs->item.filename;
1827 subcs->item.lineno = cs->item.lineno;
1828 cf_item_add(cs, &(subcs->item));
1829 }
1830
1831 cf_section_parse_init(subcs, (uint8_t *)base + variables[i].offset,
1832 (CONF_PARSER const *) variables[i].dflt);
1833 continue;
1834 }
1835
1836 if ((variables[i].type != PW_TYPE_STRING) &&
1837 (variables[i].type != PW_TYPE_FILE_INPUT) &&
1838 (variables[i].type != PW_TYPE_FILE_OUTPUT)) {
1839 continue;
1840 }
1841
1842 if (variables[i].data) {
1843 *(char **) variables[i].data = NULL;
1844 } else if (base) {
1845 *(char **) (((char *)base) + variables[i].offset) = NULL;
1846 } else {
1847 continue;
1848 }
1849 } /* for all variables in the configuration section */
1850 }
1851
1852
cf_section_parse_warn(CONF_SECTION * cs)1853 static void cf_section_parse_warn(CONF_SECTION *cs)
1854 {
1855 CONF_ITEM *ci;
1856
1857 for (ci = cs->children; ci; ci = ci->next) {
1858 /*
1859 * Don't recurse on sections. We can only safely
1860 * check conf pairs at the same level as the
1861 * section that was just parsed.
1862 */
1863 if (ci->type == CONF_ITEM_SECTION) continue;
1864 if (ci->type == CONF_ITEM_PAIR) {
1865 CONF_PAIR *cp;
1866
1867 cp = cf_item_to_pair(ci);
1868 if (cp->parsed) continue;
1869
1870 WARN("%s[%d]: The item '%s' is defined, but is unused by the configuration",
1871 cp->item.filename ? cp->item.filename : "unknown",
1872 cp->item.lineno ? cp->item.lineno : 0,
1873 cp->attr);
1874 }
1875
1876 /*
1877 * Skip everything else.
1878 */
1879 }
1880 }
1881
1882 /** Parse a configuration section into user-supplied variables
1883 *
1884 * @param cs to parse.
1885 * @param base pointer to a struct to fill with data. Any buffers will also be talloced
1886 * using this parent as a pointer.
1887 * @param variables mappings between struct fields and #CONF_ITEM s.
1888 * @return
1889 * - 0 on success.
1890 * - -1 on general error.
1891 * - -2 if a deprecated #CONF_ITEM was found.
1892 */
cf_section_parse(CONF_SECTION * cs,void * base,CONF_PARSER const * variables)1893 int cf_section_parse(CONF_SECTION *cs, void *base, CONF_PARSER const *variables)
1894 {
1895 int ret = 0;
1896 int i;
1897 void *data;
1898
1899 cs->variables = variables; /* this doesn't hurt anything */
1900
1901 if (!cs->name2) {
1902 cf_log_info(cs, "%.*s%s {", cs->depth, parse_spaces, cs->name1);
1903 } else {
1904 cf_log_info(cs, "%.*s%s %s {", cs->depth, parse_spaces, cs->name1, cs->name2);
1905 }
1906
1907 cf_section_parse_init(cs, base, variables);
1908
1909 /*
1910 * Handle the known configuration parameters.
1911 */
1912 for (i = 0; variables[i].name != NULL; i++) {
1913 /*
1914 * Handle subsections specially
1915 */
1916 if (variables[i].type == PW_TYPE_SUBSECTION) {
1917 CONF_SECTION *subcs;
1918
1919 subcs = cf_section_sub_find(cs, variables[i].name);
1920 /*
1921 * Default in this case is overloaded to mean a pointer
1922 * to the CONF_PARSER struct for the subsection.
1923 */
1924 if (!variables[i].dflt || !subcs) {
1925 ERROR("Internal sanity check 1 failed in cf_section_parse %s", variables[i].name);
1926 ret = -1;
1927 goto finish;
1928 }
1929
1930 ret = cf_section_parse(subcs, (uint8_t *)base + variables[i].offset,
1931 (CONF_PARSER const *) variables[i].dflt);
1932 if (ret < 0) goto finish;
1933 continue;
1934 } /* else it's a CONF_PAIR */
1935
1936 if (variables[i].data) {
1937 data = variables[i].data; /* prefer this. */
1938 } else if (base) {
1939 data = ((char *)base) + variables[i].offset;
1940 } else {
1941 ERROR("Internal sanity check 2 failed in cf_section_parse");
1942 ret = -1;
1943 goto finish;
1944 }
1945
1946 /*
1947 * Parse the pair we found, or a default value.
1948 */
1949 ret = cf_item_parse(cs, variables[i].name, variables[i].type, data, variables[i].dflt);
1950 switch (ret) {
1951 case 1: /* Used default */
1952 ret = 0;
1953 break;
1954
1955 case 0: /* OK */
1956 break;
1957
1958 case -1: /* Parse error */
1959 goto finish;
1960
1961 case -2: /* Deprecated CONF ITEM */
1962 if ((variables[i + 1].offset == variables[i].offset) &&
1963 (variables[i + 1].data == variables[i].data)) {
1964 cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", variables[i].name,
1965 variables[i + 1].name);
1966 } else {
1967 cf_log_err(&(cs->item), "Cannot use deprecated configuration item \"%s\"", variables[i].name);
1968 }
1969 goto finish;
1970 }
1971 } /* for all variables in the configuration section */
1972
1973 /*
1974 * Ensure we have a proper terminator, type so we catch
1975 * missing terminators reliably
1976 */
1977 rad_assert(variables[i].type == -1);
1978
1979 /*
1980 * Warn about items in the configuration which weren't
1981 * checked during parsing.
1982 */
1983 if (rad_debug_lvl >= 3) cf_section_parse_warn(cs);
1984
1985 cs->base = base;
1986
1987 cf_log_info(cs, "%.*s}", cs->depth, parse_spaces);
1988
1989 finish:
1990 return ret;
1991 }
1992
1993
1994 /*
1995 * Check XLAT things in pass 2. But don't cache the xlat stuff anywhere.
1996 */
cf_section_parse_pass2(CONF_SECTION * cs,void * base,CONF_PARSER const * variables)1997 int cf_section_parse_pass2(CONF_SECTION *cs, void *base, CONF_PARSER const *variables)
1998 {
1999 int i;
2000 ssize_t slen;
2001 char const *error;
2002 char *value = NULL;
2003 xlat_exp_t *xlat;
2004
2005 /*
2006 * Handle the known configuration parameters.
2007 */
2008 for (i = 0; variables[i].name != NULL; i++) {
2009 CONF_PAIR *cp;
2010 void *data;
2011
2012 /*
2013 * Handle subsections specially
2014 */
2015 if (variables[i].type == PW_TYPE_SUBSECTION) {
2016 CONF_SECTION *subcs;
2017 subcs = cf_section_sub_find(cs, variables[i].name);
2018
2019 if (cf_section_parse_pass2(subcs, (uint8_t *)base + variables[i].offset,
2020 (CONF_PARSER const *) variables[i].dflt) < 0) {
2021 return -1;
2022 }
2023 continue;
2024 } /* else it's a CONF_PAIR */
2025
2026 /*
2027 * Figure out which data we need to fix.
2028 */
2029 if (variables[i].data) {
2030 data = variables[i].data; /* prefer this. */
2031 } else if (base) {
2032 data = ((char *)base) + variables[i].offset;
2033 } else {
2034 data = NULL;
2035 }
2036
2037 cp = cf_pair_find(cs, variables[i].name);
2038 xlat = NULL;
2039
2040 redo:
2041 if (!cp || !cp->value || !data) continue;
2042
2043 if ((cp->rhs_type != T_DOUBLE_QUOTED_STRING) &&
2044 (cp->rhs_type != T_BARE_WORD)) continue;
2045
2046 /*
2047 * Non-xlat expansions shouldn't have xlat!
2048 */
2049 if (((variables[i].type & PW_TYPE_XLAT) == 0) &&
2050 ((variables[i].type & PW_TYPE_TMPL) == 0)) {
2051 /*
2052 * Ignore %{... in shared secrets.
2053 * They're never dynamically expanded.
2054 */
2055 if ((variables[i].type & PW_TYPE_SECRET) != 0) continue;
2056
2057 if (strstr(cp->value, "%{") != NULL) {
2058 WARN("%s[%d]: Found dynamic expansion in string which will not be dynamically expanded",
2059 cp->item.filename ? cp->item.filename : "unknown",
2060 cp->item.lineno ? cp->item.lineno : 0);
2061 }
2062 continue;
2063 }
2064
2065 /*
2066 * Parse (and throw away) the xlat string.
2067 *
2068 * FIXME: All of these should be converted from PW_TYPE_XLAT
2069 * to PW_TYPE_TMPL.
2070 */
2071 if ((variables[i].type & PW_TYPE_XLAT) != 0) {
2072 /*
2073 * xlat expansions should be parseable.
2074 */
2075 value = talloc_strdup(cs, cp->value); /* modified by xlat_tokenize */
2076 xlat = NULL;
2077
2078 slen = xlat_tokenize(cs, value, &xlat, &error);
2079 if (slen < 0) {
2080 char *spaces, *text;
2081
2082 error:
2083 fr_canonicalize_error(cs, &spaces, &text, slen, cp->value);
2084
2085 cf_log_err(&cp->item, "Failed parsing expanded string:");
2086 cf_log_err(&cp->item, "%s", text);
2087 cf_log_err(&cp->item, "%s^ %s", spaces, error);
2088
2089 talloc_free(spaces);
2090 talloc_free(text);
2091 talloc_free(value);
2092 talloc_free(xlat);
2093 return -1;
2094 }
2095
2096 talloc_free(value);
2097 talloc_free(xlat);
2098 }
2099
2100 /*
2101 * Convert the LITERAL template to the actual
2102 * type.
2103 */
2104 if ((variables[i].type & PW_TYPE_TMPL) != 0) {
2105 vp_tmpl_t *vpt;
2106
2107 slen = tmpl_afrom_str(cs, &vpt, cp->value, talloc_array_length(cp->value) - 1,
2108 cp->rhs_type,
2109 REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
2110 if (slen < 0) {
2111 error = fr_strerror();
2112 goto error;
2113 }
2114
2115 /*
2116 * Sanity check
2117 *
2118 * Don't add default - update with new types.
2119 */
2120 switch (vpt->type) {
2121 /*
2122 * All attributes should have been defined by this point.
2123 */
2124 case TMPL_TYPE_ATTR_UNDEFINED:
2125 cf_log_err(&cp->item, "Unknown attribute '%s'", vpt->tmpl_unknown_name);
2126 return -1;
2127
2128 case TMPL_TYPE_LITERAL:
2129 case TMPL_TYPE_ATTR:
2130 case TMPL_TYPE_LIST:
2131 case TMPL_TYPE_DATA:
2132 case TMPL_TYPE_EXEC:
2133 case TMPL_TYPE_XLAT:
2134 case TMPL_TYPE_XLAT_STRUCT:
2135 break;
2136
2137 case TMPL_TYPE_UNKNOWN:
2138 case TMPL_TYPE_REGEX:
2139 case TMPL_TYPE_REGEX_STRUCT:
2140 case TMPL_TYPE_NULL:
2141 rad_assert(0);
2142 }
2143
2144 talloc_free(*(vp_tmpl_t **)data);
2145 *(vp_tmpl_t **)data = vpt;
2146 }
2147
2148 /*
2149 * If the "multi" flag is set, check all of them.
2150 */
2151 if ((variables[i].type & PW_TYPE_MULTI) != 0) {
2152 cp = cf_pair_find_next(cs, cp, cp->attr);
2153 goto redo;
2154 }
2155 } /* for all variables in the configuration section */
2156
2157 return 0;
2158 }
2159
2160 /*
2161 * Merge the template so everyting else "just works".
2162 */
cf_template_merge(CONF_SECTION * cs,CONF_SECTION const * template)2163 static bool cf_template_merge(CONF_SECTION *cs, CONF_SECTION const *template)
2164 {
2165 CONF_ITEM *ci;
2166
2167 if (!cs || !template) return true;
2168
2169 cs->template = NULL;
2170
2171 /*
2172 * Walk over the template, adding its' entries to the
2173 * current section. But only if the entries don't
2174 * already exist in the current section.
2175 */
2176 for (ci = template->children; ci; ci = ci->next) {
2177 if (ci->type == CONF_ITEM_PAIR) {
2178 CONF_PAIR *cp1, *cp2;
2179
2180 /*
2181 * It exists, don't over-write it.
2182 */
2183 cp1 = cf_item_to_pair(ci);
2184 if (cf_pair_find(cs, cp1->attr)) {
2185 continue;
2186 }
2187
2188 /*
2189 * Create a new pair with all of the data
2190 * of the old one.
2191 */
2192 cp2 = cf_pair_dup(cs, cp1);
2193 if (!cp2) return false;
2194
2195 cp2->item.filename = cp1->item.filename;
2196 cp2->item.lineno = cp1->item.lineno;
2197
2198 cf_item_add(cs, &(cp2->item));
2199 continue;
2200 }
2201
2202 if (ci->type == CONF_ITEM_SECTION) {
2203 CONF_SECTION *subcs1, *subcs2;
2204
2205 subcs1 = cf_item_to_section(ci);
2206 rad_assert(subcs1 != NULL);
2207
2208 subcs2 = cf_section_sub_find_name2(cs, subcs1->name1, subcs1->name2);
2209 if (subcs2) {
2210 /*
2211 * sub-sections get merged.
2212 */
2213 if (!cf_template_merge(subcs2, subcs1)) {
2214 return false;
2215 }
2216 continue;
2217 }
2218
2219 /*
2220 * Our section doesn't have a matching
2221 * sub-section. Copy it verbatim from
2222 * the template.
2223 */
2224 subcs2 = cf_section_dup(cs, subcs1,
2225 cf_section_name1(subcs1), cf_section_name2(subcs1),
2226 false);
2227 if (!subcs2) return false;
2228
2229 subcs2->item.filename = subcs1->item.filename;
2230 subcs2->item.lineno = subcs1->item.lineno;
2231
2232 cf_item_add(cs, &(subcs2->item));
2233 continue;
2234 }
2235
2236 /* ignore everything else */
2237 }
2238
2239 return true;
2240 }
2241
cf_local_file(char const * base,char const * filename,char * buffer,size_t bufsize)2242 static char const *cf_local_file(char const *base, char const *filename,
2243 char *buffer, size_t bufsize)
2244 {
2245 size_t dirsize;
2246 char *p;
2247
2248 strlcpy(buffer, base, bufsize);
2249
2250 p = strrchr(buffer, FR_DIR_SEP);
2251 if (!p) return filename;
2252 if (p[1]) { /* ./foo */
2253 p[1] = '\0';
2254 }
2255
2256 dirsize = (p - buffer) + 1;
2257
2258 if ((dirsize + strlen(filename)) >= bufsize) {
2259 return NULL;
2260 }
2261
2262 strlcpy(p + 1, filename, bufsize - dirsize);
2263
2264 return buffer;
2265 }
2266
2267
2268 /*
2269 * Read a part of the config file.
2270 */
cf_section_read(char const * filename,int * lineno,FILE * fp,CONF_SECTION * current)2271 static int cf_section_read(char const *filename, int *lineno, FILE *fp,
2272 CONF_SECTION *current)
2273
2274 {
2275 CONF_SECTION *this, *css;
2276 CONF_PAIR *cpn;
2277 char const *ptr;
2278 char const *value;
2279 char buf[8192];
2280 char buf1[8192];
2281 char buf2[8192];
2282 char buf3[8192];
2283 char buf4[8192];
2284 FR_TOKEN t1 = T_INVALID, t2, t3;
2285 bool has_spaces = false;
2286 bool pass2;
2287 char *cbuf = buf;
2288 size_t len;
2289
2290 this = current; /* add items here */
2291
2292 /*
2293 * Read, checking for line continuations ('\\' at EOL)
2294 */
2295 for (;;) {
2296 int at_eof;
2297 css = NULL;
2298
2299 /*
2300 * Get data, and remember if we are at EOF.
2301 */
2302 at_eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL);
2303 (*lineno)++;
2304
2305 /*
2306 * We read the entire 8k worth of data: complain.
2307 * Note that we don't care if the last character
2308 * is \n: it's still forbidden. This means that
2309 * the maximum allowed length of text is 8k-1, which
2310 * should be plenty.
2311 */
2312 len = strlen(cbuf);
2313 if ((cbuf + len + 1) >= (buf + sizeof(buf))) {
2314 ERROR("%s[%d]: Line too long",
2315 filename, *lineno);
2316 return -1;
2317 }
2318
2319 if (has_spaces) {
2320 ptr = cbuf;
2321 while (isspace((int) *ptr)) ptr++;
2322
2323 if (ptr > cbuf) {
2324 memmove(cbuf, ptr, len - (ptr - cbuf));
2325 len -= (ptr - cbuf);
2326 }
2327 }
2328
2329 /*
2330 * Not doing continuations: check for edge
2331 * conditions.
2332 */
2333 if (cbuf == buf) {
2334 if (at_eof) break;
2335
2336 ptr = buf;
2337 while (*ptr && isspace((int) *ptr)) ptr++;
2338
2339 if (!*ptr || (*ptr == '#')) continue;
2340
2341 } else if (at_eof || (len == 0)) {
2342 ERROR("%s[%d]: Continuation at EOF is illegal",
2343 filename, *lineno);
2344 return -1;
2345 }
2346
2347 /*
2348 * See if there's a continuation.
2349 */
2350 while ((len > 0) &&
2351 ((cbuf[len - 1] == '\n') || (cbuf[len - 1] == '\r'))) {
2352 len--;
2353 cbuf[len] = '\0';
2354 }
2355
2356 if ((len > 0) && (cbuf[len - 1] == '\\')) {
2357 /*
2358 * Check for "suppress spaces" magic.
2359 */
2360 if (!has_spaces && (len > 2) && (cbuf[len - 2] == '"')) {
2361 has_spaces = true;
2362 }
2363
2364 cbuf[len - 1] = '\0';
2365 cbuf += len - 1;
2366 continue;
2367 }
2368
2369 ptr = cbuf = buf;
2370 has_spaces = false;
2371
2372 get_more:
2373 pass2 = false;
2374
2375 /*
2376 * The parser is getting to be evil.
2377 */
2378 while ((*ptr == ' ') || (*ptr == '\t')) ptr++;
2379
2380 if (((ptr[0] == '%') && (ptr[1] == '{')) ||
2381 (ptr[0] == '`')) {
2382 int hack;
2383
2384 if (ptr[0] == '%') {
2385 hack = rad_copy_variable(buf1, ptr);
2386 } else {
2387 hack = rad_copy_string(buf1, ptr);
2388 }
2389 if (hack < 0) {
2390 ERROR("%s[%d]: Invalid expansion: %s",
2391 filename, *lineno, ptr);
2392 return -1;
2393 }
2394
2395 ptr += hack;
2396
2397 t2 = gettoken(&ptr, buf2, sizeof(buf2), true);
2398 switch (t2) {
2399 case T_EOL:
2400 case T_HASH:
2401 goto do_bare_word;
2402
2403 default:
2404 ERROR("%s[%d]: Invalid expansion: %s",
2405 filename, *lineno, ptr);
2406 return -1;
2407 }
2408 } else {
2409 t1 = gettoken(&ptr, buf1, sizeof(buf1), true);
2410 }
2411
2412 /*
2413 * The caller eats "name1 name2 {", and calls us
2414 * for the data inside of the section. So if we
2415 * receive a closing brace, then it must mean the
2416 * end of the section.
2417 */
2418 if (t1 == T_RCBRACE) {
2419 if (this == current) {
2420 ERROR("%s[%d]: Too many closing braces",
2421 filename, *lineno);
2422 return -1;
2423 }
2424
2425 /*
2426 * Merge the template into the existing
2427 * section. This uses more memory, but
2428 * means that templates now work with
2429 * sub-sections, etc.
2430 */
2431 if (!cf_template_merge(this, this->template)) {
2432 return -1;
2433 }
2434
2435 this = this->item.parent;
2436 goto check_for_more;
2437 }
2438
2439 if (t1 != T_BARE_WORD) goto skip_keywords;
2440
2441 /*
2442 * Allow for $INCLUDE files
2443 *
2444 * This *SHOULD* work for any level include.
2445 * I really really really hate this file. -cparker
2446 */
2447 if ((strcasecmp(buf1, "$INCLUDE") == 0) ||
2448 (strcasecmp(buf1, "$-INCLUDE") == 0)) {
2449 bool relative = true;
2450
2451 t2 = getword(&ptr, buf2, sizeof(buf2), true);
2452 if (t2 != T_EOL) {
2453 ERROR("%s[%d]: Unexpected text after $INCLUDE",
2454 filename, *lineno);
2455 return -1;
2456 }
2457
2458 if (buf2[0] == '$') relative = false;
2459
2460 value = cf_expand_variables(filename, lineno, this, buf4, sizeof(buf4), buf2, NULL);
2461 if (!value) return -1;
2462
2463 if (!FR_DIR_IS_RELATIVE(value)) relative = false;
2464
2465 if (relative) {
2466 value = cf_local_file(filename, value, buf3,
2467 sizeof(buf3));
2468 if (!value) {
2469 ERROR("%s[%d]: Directories too deep.",
2470 filename, *lineno);
2471 return -1;
2472 }
2473 }
2474
2475
2476 #ifdef HAVE_DIRENT_H
2477 /*
2478 * $INCLUDE foo/
2479 *
2480 * Include ALL non-"dot" files in the directory.
2481 * careful!
2482 */
2483 if (value[strlen(value) - 1] == '/') {
2484 DIR *dir;
2485 struct dirent *dp;
2486 struct stat stat_buf;
2487
2488 DEBUG2("including files in directory %s", value );
2489 #ifdef S_IWOTH
2490 /*
2491 * Security checks.
2492 */
2493 if (stat(value, &stat_buf) < 0) {
2494 ERROR("%s[%d]: Failed reading directory %s: %s",
2495 filename, *lineno,
2496 value, fr_syserror(errno));
2497 return -1;
2498 }
2499
2500 if ((stat_buf.st_mode & S_IWOTH) != 0) {
2501 ERROR("%s[%d]: Directory %s is globally writable. Refusing to start due to "
2502 "insecure configuration", filename, *lineno, value);
2503 return -1;
2504 }
2505 #endif
2506 dir = opendir(value);
2507 if (!dir) {
2508 ERROR("%s[%d]: Error reading directory %s: %s",
2509 filename, *lineno, value,
2510 fr_syserror(errno));
2511 return -1;
2512 }
2513
2514 /*
2515 * Read the directory, ignoring "." files.
2516 */
2517 while ((dp = readdir(dir)) != NULL) {
2518 char const *p;
2519 int slen;
2520
2521 if (dp->d_name[0] == '.') continue;
2522
2523 /*
2524 * Check for valid characters
2525 */
2526 for (p = dp->d_name; *p != '\0'; p++) {
2527 if (isalpha((int)*p) ||
2528 isdigit((int)*p) ||
2529 (*p == '-') ||
2530 (*p == '_') ||
2531 (*p == '.')) continue;
2532 break;
2533 }
2534 if (*p != '\0') continue;
2535
2536 slen = snprintf(buf2, sizeof(buf2), "%s%s",
2537 value, dp->d_name);
2538 if (slen >= (int) sizeof(buf2) || slen < 0) {
2539 ERROR("%s: Full file path is too long.", dp->d_name);
2540 return -1;
2541 }
2542 if ((stat(buf2, &stat_buf) != 0) ||
2543 S_ISDIR(stat_buf.st_mode)) continue;
2544
2545 /*
2546 * Read the file into the current
2547 * configuration section.
2548 */
2549 if (cf_file_include(this, buf2, true) < 0) {
2550 closedir(dir);
2551 return -1;
2552 }
2553 }
2554 closedir(dir);
2555 } else
2556 #endif
2557 { /* it was a normal file */
2558 if (buf1[1] == '-') {
2559 struct stat statbuf;
2560
2561 if (stat(value, &statbuf) < 0) {
2562 WARN("Not including file %s: %s", value, fr_syserror(errno));
2563 continue;
2564 }
2565 }
2566
2567 if (cf_file_include(this, value, false) < 0) {
2568 return -1;
2569 }
2570 }
2571 continue;
2572 } /* we were in an include */
2573
2574 if (strcasecmp(buf1, "$template") == 0) {
2575 CONF_ITEM *ci;
2576 CONF_SECTION *parentcs, *templatecs;
2577 t2 = getword(&ptr, buf2, sizeof(buf2), true);
2578
2579 if (t2 != T_EOL) {
2580 ERROR("%s[%d]: Unexpected text after $TEMPLATE", filename, *lineno);
2581 return -1;
2582 }
2583
2584 parentcs = cf_top_section(current);
2585
2586 templatecs = cf_section_sub_find(parentcs, "templates");
2587 if (!templatecs) {
2588 ERROR("%s[%d]: No \"templates\" section for reference \"%s\"", filename, *lineno, buf2);
2589 return -1;
2590 }
2591
2592 ci = cf_reference_item(parentcs, templatecs, buf2);
2593 if (!ci || (ci->type != CONF_ITEM_SECTION)) {
2594 ERROR("%s[%d]: Reference \"%s\" not found", filename, *lineno, buf2);
2595 return -1;
2596 }
2597
2598 if (!this) {
2599 ERROR("%s[%d]: Internal sanity check error in template reference", filename, *lineno);
2600 return -1;
2601 }
2602
2603 if (this->template) {
2604 ERROR("%s[%d]: Section already has a template", filename, *lineno);
2605 return -1;
2606 }
2607
2608 this->template = cf_item_to_section(ci);
2609 continue;
2610 }
2611
2612 /*
2613 * Ensure that the user can't add CONF_PAIRs
2614 * with 'internal' names;
2615 */
2616 if (buf1[0] == '_') {
2617 ERROR("%s[%d]: Illegal configuration pair name \"%s\"", filename, *lineno, buf1);
2618 return -1;
2619 }
2620
2621 /*
2622 * Handle if/elsif specially.
2623 */
2624 if ((strcmp(buf1, "if") == 0) || (strcmp(buf1, "elsif") == 0)) {
2625 ssize_t slen;
2626 char const *error = NULL;
2627 char *p;
2628 CONF_SECTION *server;
2629 fr_cond_t *cond = NULL;
2630
2631 /*
2632 * if / elsif MUST be inside of a
2633 * processing section, which MUST in turn
2634 * be inside of a "server" directive.
2635 */
2636 if (!this->item.parent) {
2637 invalid_location:
2638 ERROR("%s[%d]: Invalid location for '%s'",
2639 filename, *lineno, buf1);
2640 return -1;
2641 }
2642
2643 /*
2644 * Can only have "if" in 3 named sections.
2645 */
2646 server = this->item.parent;
2647 while (server &&
2648 (strcmp(server->name1, "server") != 0) &&
2649 (strcmp(server->name1, "policy") != 0) &&
2650 (strcmp(server->name1, "instantiate") != 0)) {
2651 server = server->item.parent;
2652 if (!server) goto invalid_location;
2653 }
2654
2655 /*
2656 * Skip (...) to find the {
2657 */
2658 slen = fr_condition_tokenize(this, cf_section_to_item(this), ptr, &cond,
2659 &error, FR_COND_TWO_PASS);
2660 memcpy(&p, &ptr, sizeof(p));
2661
2662 if (slen < 0) {
2663 if (p[-slen] != '{') goto cond_error;
2664 slen = -slen;
2665 }
2666 TALLOC_FREE(cond);
2667
2668 /*
2669 * This hack is so that the NEXT stage
2670 * doesn't go "too far" in expanding the
2671 * variable. We can parse the conditions
2672 * without expanding the ${...} stuff.
2673 * BUT we don't want to expand all of the
2674 * stuff AFTER the condition. So we do
2675 * two passes.
2676 *
2677 * The first pass is to discover the end
2678 * of the condition. We then expand THAT
2679 * string, and do a second pass parsing
2680 * the expanded condition.
2681 */
2682 p += slen;
2683 *p = '\0';
2684
2685 /*
2686 * If there's a ${...}. If so, expand it.
2687 */
2688 if (strchr(ptr, '$') != NULL) {
2689 ptr = cf_expand_variables(filename, lineno,
2690 this,
2691 buf3, sizeof(buf3),
2692 ptr, NULL);
2693 if (!ptr) {
2694 ERROR("%s[%d]: Parse error expanding ${...} in condition",
2695 filename, *lineno);
2696 return -1;
2697 }
2698 } /* else leave it alone */
2699
2700 css = cf_section_alloc(this, buf1, ptr);
2701 if (!css) {
2702 ERROR("%s[%d]: Failed allocating memory for section",
2703 filename, *lineno);
2704 return -1;
2705 }
2706 css->item.filename = filename;
2707 css->item.lineno = *lineno;
2708
2709 slen = fr_condition_tokenize(css, cf_section_to_item(css), ptr, &cond,
2710 &error, FR_COND_TWO_PASS);
2711 *p = '{'; /* put it back */
2712
2713 cond_error:
2714 if (slen < 0) {
2715 char *spaces, *text;
2716
2717 fr_canonicalize_error(this, &spaces, &text, slen, ptr);
2718
2719 ERROR("%s[%d]: Parse error in condition",
2720 filename, *lineno);
2721 ERROR("%s[%d]: %s", filename, *lineno, text);
2722 ERROR("%s[%d]: %s^ %s", filename, *lineno, spaces, error);
2723
2724 talloc_free(spaces);
2725 talloc_free(text);
2726 talloc_free(css);
2727 return -1;
2728 }
2729
2730 if ((size_t) slen >= (sizeof(buf2) - 1)) {
2731 talloc_free(css);
2732 ERROR("%s[%d]: Condition is too large after \"%s\"",
2733 filename, *lineno, buf1);
2734 return -1;
2735 }
2736
2737 /*
2738 * Copy the expanded and parsed condition
2739 * into buf2. Then, parse the text after
2740 * the condition, which now MUST be a '{.
2741 *
2742 * If it wasn't '{' it would have been
2743 * caught in the first pass of
2744 * conditional parsing, above.
2745 */
2746 memcpy(buf2, ptr, slen);
2747 buf2[slen] = '\0';
2748 ptr = p;
2749
2750 if ((t3 = gettoken(&ptr, buf3, sizeof(buf3), true)) != T_LCBRACE) {
2751 talloc_free(css);
2752 ERROR("%s[%d]: Expected '{' %d",
2753 filename, *lineno, t3);
2754 return -1;
2755 }
2756
2757 /*
2758 * Swap the condition with trailing stuff for
2759 * the final condition.
2760 */
2761 memcpy(&p, &css->name2, sizeof(css->name2));
2762 talloc_free(p);
2763 css->name2 = talloc_typed_strdup(css, buf2);
2764
2765 cf_item_add(this, &(css->item));
2766 cf_data_add_internal(css, "if", cond, NULL, false);
2767
2768 /*
2769 * The current section is now the child section.
2770 */
2771 this = css;
2772 css = NULL;
2773 goto check_for_more;
2774 }
2775
2776 skip_keywords:
2777 /*
2778 * Grab the next token.
2779 */
2780 t2 = gettoken(&ptr, buf2, sizeof(buf2), !cf_new_escape);
2781 switch (t2) {
2782 case T_EOL:
2783 case T_HASH:
2784 case T_COMMA:
2785 do_bare_word:
2786 t3 = t2;
2787 t2 = T_OP_EQ;
2788 value = NULL;
2789 goto do_set;
2790
2791 case T_OP_INCRM:
2792 case T_OP_ADD:
2793 case T_OP_CMP_EQ:
2794 case T_OP_SUB:
2795 case T_OP_LE:
2796 case T_OP_GE:
2797 case T_OP_CMP_FALSE:
2798 if (!this || (strcmp(this->name1, "update") != 0)) {
2799 ERROR("%s[%d]: Invalid operator in assignment",
2800 filename, *lineno);
2801 return -1;
2802 }
2803 /* FALL-THROUGH */
2804
2805 case T_OP_EQ:
2806 case T_OP_SET:
2807 case T_OP_PREPEND:
2808 while (isspace((int) *ptr)) ptr++;
2809
2810 /*
2811 * Be a little more forgiving.
2812 */
2813 if (*ptr == '#') {
2814 t3 = T_HASH;
2815 } else
2816
2817 /*
2818 * New parser: non-quoted strings are
2819 * bare words, and we parse everything
2820 * until the next newline, or the next
2821 * comma. If they have { or } in a bare
2822 * word, well... too bad.
2823 */
2824 if (cf_new_escape && (*ptr != '"') && (*ptr != '\'')
2825 && (*ptr != '`') && (*ptr != '/')) {
2826 const char *q = ptr;
2827
2828 t3 = T_BARE_WORD;
2829 while (*q && (*q >= ' ') && (*q != ',') &&
2830 !isspace(*q)) q++;
2831
2832 if ((size_t) (q - ptr) >= sizeof(buf3)) {
2833 ERROR("%s[%d]: Parse error: value too long",
2834 filename, *lineno);
2835 return -1;
2836 }
2837
2838 memcpy(buf3, ptr, (q - ptr));
2839 buf3[q - ptr] = '\0';
2840 ptr = q;
2841
2842 } else {
2843 t3 = getstring(&ptr, buf3, sizeof(buf3), !cf_new_escape);
2844 }
2845
2846 if (t3 == T_INVALID) {
2847 ERROR("%s[%d]: Parse error: %s",
2848 filename, *lineno,
2849 fr_strerror());
2850 return -1;
2851 }
2852
2853 /*
2854 * Allow "foo" by itself, or "foo = bar"
2855 */
2856 switch (t3) {
2857 bool soft_fail;
2858
2859 case T_BARE_WORD:
2860 case T_DOUBLE_QUOTED_STRING:
2861 case T_BACK_QUOTED_STRING:
2862 value = cf_expand_variables(filename, lineno, this, buf4, sizeof(buf4), buf3, &soft_fail);
2863 if (!value) {
2864 if (!soft_fail) return -1;
2865
2866 /*
2867 * References an item which doesn't exist,
2868 * or which is already marked up as being
2869 * expanded in pass2. Wait for pass2 to
2870 * do the expansions.
2871 */
2872 pass2 = true;
2873 value = buf3;
2874 }
2875 break;
2876
2877 case T_EOL:
2878 case T_HASH:
2879 value = NULL;
2880 break;
2881
2882 default:
2883 value = buf3;
2884 break;
2885 }
2886
2887 /*
2888 * Add this CONF_PAIR to our CONF_SECTION
2889 */
2890 do_set:
2891 cpn = cf_pair_alloc(this, buf1, value, t2, t1, t3);
2892 if (!cpn) return -1;
2893 cpn->item.filename = filename;
2894 cpn->item.lineno = *lineno;
2895 cpn->pass2 = pass2;
2896 cf_item_add(this, &(cpn->item));
2897
2898 /*
2899 * Hacks for escaping
2900 */
2901 if (!cf_new_escape && !this->item.parent && value &&
2902 (strcmp(buf1, "correct_escapes") == 0) &&
2903 ((strcmp(value, "true") == 0) ||
2904 (strcmp(value, "yes") == 0) ||
2905 (strcmp(value, "1") == 0))) {
2906 cf_new_escape = true;
2907 }
2908
2909 /*
2910 * Require a comma, unless there's a comment.
2911 */
2912 while (isspace(*ptr)) ptr++;
2913
2914 if (*ptr == ',') {
2915 ptr++;
2916 break;
2917 }
2918
2919 /*
2920 * module # stuff!
2921 * foo = bar # other stuff
2922 */
2923 if ((t3 == T_HASH) || (t3 == T_COMMA) || (t3 == T_EOL) || (*ptr == '#')) continue;
2924
2925 if (!*ptr || (*ptr == '}')) break;
2926
2927 ERROR("%s[%d]: Syntax error: Expected comma after '%s': %s",
2928 filename, *lineno, value, ptr);
2929 return -1;
2930
2931 /*
2932 * No '=', must be a section or sub-section.
2933 */
2934 case T_BARE_WORD:
2935 case T_DOUBLE_QUOTED_STRING:
2936 case T_SINGLE_QUOTED_STRING:
2937 t3 = gettoken(&ptr, buf3, sizeof(buf3), true);
2938 if (t3 != T_LCBRACE) {
2939 ERROR("%s[%d]: Expecting section start brace '{' after \"%s %s\"",
2940 filename, *lineno, buf1, buf2);
2941 return -1;
2942 }
2943 /* FALL-THROUGH */
2944
2945 case T_LCBRACE:
2946 css = cf_section_alloc(this, buf1,
2947 t2 == T_LCBRACE ? NULL : buf2);
2948 if (!css) {
2949 ERROR("%s[%d]: Failed allocating memory for section",
2950 filename, *lineno);
2951 return -1;
2952 }
2953
2954 css->item.filename = filename;
2955 css->item.lineno = *lineno;
2956 cf_item_add(this, &(css->item));
2957
2958 /*
2959 * There may not be a name2
2960 */
2961 css->name2_type = (t2 == T_LCBRACE) ? T_INVALID : t2;
2962
2963 /*
2964 * The current section is now the child section.
2965 */
2966 this = css;
2967 break;
2968
2969 case T_INVALID:
2970 ERROR("%s[%d]: Syntax error in '%s': %s", filename, *lineno, ptr, fr_strerror());
2971
2972 return -1;
2973
2974 default:
2975 ERROR("%s[%d]: Parse error after \"%s\": unexpected token \"%s\"",
2976 filename, *lineno, buf1, fr_int2str(fr_tokens, t2, "<INVALID>"));
2977
2978 return -1;
2979 }
2980
2981 check_for_more:
2982 /*
2983 * Done parsing one thing. Skip to EOL if possible.
2984 */
2985 while (isspace(*ptr)) ptr++;
2986
2987 if (*ptr == '#') continue;
2988
2989 if (*ptr) {
2990 goto get_more;
2991 }
2992
2993 }
2994
2995 /*
2996 * See if EOF was unexpected ..
2997 */
2998 if (feof(fp) && (this != current)) {
2999 ERROR("%s[%d]: EOF reached without closing brace for section %s starting at line %d",
3000 filename, *lineno, cf_section_name1(this), cf_section_lineno(this));
3001 return -1;
3002 }
3003
3004 return 0;
3005 }
3006
3007 /*
3008 * Include one config file in another.
3009 */
cf_file_include(CONF_SECTION * cs,char const * filename_in,bool from_dir)3010 static int cf_file_include(CONF_SECTION *cs, char const *filename_in, bool from_dir)
3011 {
3012 FILE *fp;
3013 int rcode;
3014 int lineno = 0;
3015 char const *filename;
3016
3017 /*
3018 * So we only need to do this once.
3019 */
3020 filename = talloc_strdup(cs, filename_in);
3021
3022 /*
3023 * This may return "0" if we already loaded the file.
3024 */
3025 rcode = cf_file_open(cs, filename, from_dir, &fp);
3026 if (rcode <= 0) return rcode;
3027
3028 if (!cs->item.filename) cs->item.filename = filename;
3029
3030 /*
3031 * Read the section. It's OK to have EOF without a
3032 * matching close brace.
3033 */
3034 if (cf_section_read(filename, &lineno, fp, cs) < 0) {
3035 fclose(fp);
3036 return -1;
3037 }
3038
3039 fclose(fp);
3040 return 0;
3041 }
3042
3043
3044 /*
3045 * Do variable expansion in pass2.
3046 *
3047 * This is a breadth-first expansion. "deep
3048 */
cf_section_pass2(CONF_SECTION * cs)3049 static int cf_section_pass2(CONF_SECTION *cs)
3050 {
3051 CONF_ITEM *ci;
3052
3053 for (ci = cs->children; ci; ci = ci->next) {
3054 char const *value;
3055 CONF_PAIR *cp;
3056 char buffer[8192];
3057
3058 if (ci->type != CONF_ITEM_PAIR) continue;
3059
3060 cp = cf_item_to_pair(ci);
3061 if (!cp->value || !cp->pass2) continue;
3062
3063 rad_assert((cp->rhs_type == T_BARE_WORD) ||
3064 (cp->rhs_type == T_DOUBLE_QUOTED_STRING) ||
3065 (cp->rhs_type == T_BACK_QUOTED_STRING));
3066
3067 value = cf_expand_variables(ci->filename, &ci->lineno, cs, buffer, sizeof(buffer), cp->value, NULL);
3068 if (!value) return -1;
3069
3070 rad_const_free(cp->value);
3071 cp->value = talloc_typed_strdup(cp, value);
3072 }
3073
3074 for (ci = cs->children; ci; ci = ci->next) {
3075 if (ci->type != CONF_ITEM_SECTION) continue;
3076
3077 if (cf_section_pass2(cf_item_to_section(ci)) < 0) return -1;
3078 }
3079
3080 return 0;
3081 }
3082
3083
3084 /*
3085 * Bootstrap a config file.
3086 */
cf_file_read(CONF_SECTION * cs,char const * filename)3087 int cf_file_read(CONF_SECTION *cs, char const *filename)
3088 {
3089 char *p;
3090 CONF_PAIR *cp;
3091 rbtree_t *tree;
3092
3093 cp = cf_pair_alloc(cs, "confdir", filename, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
3094 if (!cp) return -1;
3095
3096 p = strrchr(cp->value, FR_DIR_SEP);
3097 if (p) *p = '\0';
3098
3099 cp->item.filename = "<internal>";
3100 cp->item.lineno = -1;
3101 cf_item_add(cs, &(cp->item));
3102
3103 tree = rbtree_create(cs, filename_cmp, NULL, 0);
3104 if (!tree) return -1;
3105
3106 cf_data_add_internal(cs, "filename", tree, NULL, 0);
3107
3108 if (cf_file_include(cs, filename, false) < 0) return -1;
3109
3110 /*
3111 * Now that we've read the file, go back through it and
3112 * expand the variables.
3113 */
3114 if (cf_section_pass2(cs) < 0) return -1;
3115
3116 return 0;
3117 }
3118
3119
cf_file_free(CONF_SECTION * cs)3120 void cf_file_free(CONF_SECTION *cs)
3121 {
3122 talloc_free(cs);
3123 }
3124
3125
3126 /*
3127 * Return a CONF_PAIR within a CONF_SECTION.
3128 */
cf_pair_find(CONF_SECTION const * cs,char const * name)3129 CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *name)
3130 {
3131 CONF_PAIR *cp, mycp;
3132
3133 if (!cs || !name) return NULL;
3134
3135 mycp.attr = name;
3136 cp = rbtree_finddata(cs->pair_tree, &mycp);
3137 if (cp) return cp;
3138
3139 if (!cs->template) return NULL;
3140
3141 return rbtree_finddata(cs->template->pair_tree, &mycp);
3142 }
3143
3144 /*
3145 * Return the attr of a CONF_PAIR
3146 */
3147
cf_pair_attr(CONF_PAIR const * pair)3148 char const *cf_pair_attr(CONF_PAIR const *pair)
3149 {
3150 return (pair ? pair->attr : NULL);
3151 }
3152
3153 /*
3154 * Return the value of a CONF_PAIR
3155 */
3156
cf_pair_value(CONF_PAIR const * pair)3157 char const *cf_pair_value(CONF_PAIR const *pair)
3158 {
3159 return (pair ? pair->value : NULL);
3160 }
3161
cf_pair_operator(CONF_PAIR const * pair)3162 FR_TOKEN cf_pair_operator(CONF_PAIR const *pair)
3163 {
3164 return (pair ? pair->op : T_INVALID);
3165 }
3166
3167 /** Return the value (lhs) type
3168 *
3169 * @param pair to extract value type from.
3170 * @return one of T_BARE_WORD, T_SINGLE_QUOTED_STRING, T_BACK_QUOTED_STRING
3171 * T_DOUBLE_QUOTED_STRING or T_INVALID if the pair is NULL.
3172 */
cf_pair_attr_type(CONF_PAIR const * pair)3173 FR_TOKEN cf_pair_attr_type(CONF_PAIR const *pair)
3174 {
3175 return (pair ? pair->lhs_type : T_INVALID);
3176 }
3177
3178 /** Return the value (rhs) type
3179 *
3180 * @param pair to extract value type from.
3181 * @return one of T_BARE_WORD, T_SINGLE_QUOTED_STRING, T_BACK_QUOTED_STRING
3182 * T_DOUBLE_QUOTED_STRING or T_INVALID if the pair is NULL.
3183 */
cf_pair_value_type(CONF_PAIR const * pair)3184 FR_TOKEN cf_pair_value_type(CONF_PAIR const *pair)
3185 {
3186 return (pair ? pair->rhs_type : T_INVALID);
3187 }
3188
3189 /*
3190 * Turn a CONF_PAIR into a VALUE_PAIR
3191 * For now, ignore the "value_type" field...
3192 */
cf_pairtovp(CONF_PAIR * pair)3193 VALUE_PAIR *cf_pairtovp(CONF_PAIR *pair)
3194 {
3195 if (!pair) {
3196 fr_strerror_printf("Internal error");
3197 return NULL;
3198 }
3199
3200 if (!pair->value) {
3201 fr_strerror_printf("No value given for attribute %s", pair->attr);
3202 return NULL;
3203 }
3204
3205 /*
3206 * false comparisons never match. BUT if it's a "string"
3207 * or `string`, then remember to expand it later.
3208 */
3209 if ((pair->op != T_OP_CMP_FALSE) &&
3210 ((pair->rhs_type == T_DOUBLE_QUOTED_STRING) ||
3211 (pair->rhs_type == T_BACK_QUOTED_STRING))) {
3212 VALUE_PAIR *vp;
3213
3214 vp = fr_pair_make(pair, NULL, pair->attr, NULL, pair->op);
3215 if (!vp) {
3216 return NULL;
3217 }
3218
3219 if (fr_pair_mark_xlat(vp, pair->value) < 0) {
3220 talloc_free(vp);
3221
3222 return NULL;
3223 }
3224
3225 return vp;
3226 }
3227
3228 return fr_pair_make(pair, NULL, pair->attr, pair->value, pair->op);
3229 }
3230
3231 /*
3232 * Return the first label of a CONF_SECTION
3233 */
3234
cf_section_name1(CONF_SECTION const * cs)3235 char const *cf_section_name1(CONF_SECTION const *cs)
3236 {
3237 return (cs ? cs->name1 : NULL);
3238 }
3239
3240 /*
3241 * Return the second label of a CONF_SECTION
3242 */
3243
cf_section_name2(CONF_SECTION const * cs)3244 char const *cf_section_name2(CONF_SECTION const *cs)
3245 {
3246 return (cs ? cs->name2 : NULL);
3247 }
3248
3249 /** Return name2 if set, else name1
3250 *
3251 */
cf_section_name(CONF_SECTION const * cs)3252 char const *cf_section_name(CONF_SECTION const *cs)
3253 {
3254 char const *name;
3255
3256 name = cf_section_name2(cs);
3257 if (name) return name;
3258
3259 return cf_section_name1(cs);
3260 }
3261
3262 /*
3263 * Find a value in a CONF_SECTION
3264 */
cf_section_value_find(CONF_SECTION const * cs,char const * attr)3265 char const *cf_section_value_find(CONF_SECTION const *cs, char const *attr)
3266 {
3267 CONF_PAIR *cp;
3268
3269 cp = cf_pair_find(cs, attr);
3270
3271 return (cp ? cp->value : NULL);
3272 }
3273
3274
cf_section_find_name2(CONF_SECTION const * cs,char const * name1,char const * name2)3275 CONF_SECTION *cf_section_find_name2(CONF_SECTION const *cs,
3276 char const *name1, char const *name2)
3277 {
3278 char const *their2;
3279 CONF_ITEM const *ci;
3280
3281 if (!cs || !name1) return NULL;
3282
3283 for (ci = &(cs->item); ci; ci = ci->next) {
3284 if (ci->type != CONF_ITEM_SECTION)
3285 continue;
3286
3287 if (strcmp(cf_item_to_section(ci)->name1, name1) != 0) {
3288 continue;
3289 }
3290
3291 their2 = cf_item_to_section(ci)->name2;
3292
3293 if ((!name2 && !their2) ||
3294 (name2 && their2 && (strcmp(name2, their2) == 0))) {
3295 return cf_item_to_section(ci);
3296 }
3297 }
3298
3299 return NULL;
3300 }
3301
3302 /** Find a pair with a name matching attr, after specified pair.
3303 *
3304 * @param cs to search in.
3305 * @param pair to search from (may be NULL).
3306 * @param attr to find (may be NULL in which case any attribute matches).
3307 * @return the next matching CONF_PAIR or NULL if none matched.
3308 */
cf_pair_find_next(CONF_SECTION const * cs,CONF_PAIR const * pair,char const * attr)3309 CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs,
3310 CONF_PAIR const *pair, char const *attr)
3311 {
3312 CONF_ITEM *ci;
3313
3314 if (!cs) return NULL;
3315
3316 /*
3317 * If pair is NULL and we're trying to find a specific
3318 * attribute this must be a first time run.
3319 *
3320 * Find the pair with correct name.
3321 */
3322 if (!pair && attr) return cf_pair_find(cs, attr);
3323
3324 /*
3325 * Start searching from the next child, or from the head
3326 * of the list of children (if no pair was provided).
3327 */
3328 for (ci = pair ? pair->item.next : cs->children;
3329 ci;
3330 ci = ci->next) {
3331 if (ci->type != CONF_ITEM_PAIR) continue;
3332
3333 if (!attr || strcmp(cf_item_to_pair(ci)->attr, attr) == 0) break;
3334 }
3335
3336 return cf_item_to_pair(ci);
3337 }
3338
3339 /*
3340 * Find a CONF_SECTION, or return the root if name is NULL
3341 */
3342
cf_section_find(char const * name)3343 CONF_SECTION *cf_section_find(char const *name)
3344 {
3345 if (name)
3346 return cf_section_sub_find(root_config, name);
3347 else
3348 return root_config;
3349 }
3350
3351 /** Find a sub-section in a section
3352 *
3353 * This finds ANY section having the same first name.
3354 * The second name is ignored.
3355 */
cf_section_sub_find(CONF_SECTION const * cs,char const * name)3356 CONF_SECTION *cf_section_sub_find(CONF_SECTION const *cs, char const *name)
3357 {
3358 CONF_SECTION mycs;
3359
3360 if (!cs || !name) return NULL; /* can't find an un-named section */
3361
3362 /*
3363 * No sub-sections have been defined, so none exist.
3364 */
3365 if (!cs->section_tree) return NULL;
3366
3367 mycs.name1 = name;
3368 mycs.name2 = NULL;
3369 return rbtree_finddata(cs->section_tree, &mycs);
3370 }
3371
3372
3373 /** Find a CONF_SECTION with both names.
3374 *
3375 */
cf_section_sub_find_name2(CONF_SECTION const * cs,char const * name1,char const * name2)3376 CONF_SECTION *cf_section_sub_find_name2(CONF_SECTION const *cs,
3377 char const *name1, char const *name2)
3378 {
3379 CONF_ITEM *ci;
3380
3381 if (!cs) cs = root_config;
3382 if (!cs) return NULL;
3383
3384 if (name1) {
3385 CONF_SECTION mycs, *master_cs;
3386
3387 if (!cs->section_tree) return NULL;
3388
3389 mycs.name1 = name1;
3390 mycs.name2 = name2;
3391
3392 master_cs = rbtree_finddata(cs->section_tree, &mycs);
3393 if (!master_cs) return NULL;
3394
3395 /*
3396 * Look it up in the name2 tree. If it's there,
3397 * return it.
3398 */
3399 if (master_cs->name2_tree) {
3400 CONF_SECTION *subcs;
3401
3402 subcs = rbtree_finddata(master_cs->name2_tree, &mycs);
3403 if (subcs) return subcs;
3404 }
3405
3406 /*
3407 * We don't insert ourselves into the name2 tree.
3408 * So if there's nothing in the name2 tree, maybe
3409 * *we* are the answer.
3410 */
3411 if (!master_cs->name2 && name2) return NULL;
3412 if (master_cs->name2 && !name2) return NULL;
3413 if (!master_cs->name2 && !name2) return master_cs;
3414
3415 if (strcmp(master_cs->name2, name2) == 0) {
3416 return master_cs;
3417 }
3418
3419 return NULL;
3420 }
3421
3422 /*
3423 * Else do it the old-fashioned way.
3424 */
3425 for (ci = cs->children; ci; ci = ci->next) {
3426 CONF_SECTION *subcs;
3427
3428 if (ci->type != CONF_ITEM_SECTION)
3429 continue;
3430
3431 subcs = cf_item_to_section(ci);
3432 if (!subcs->name2) {
3433 if (strcmp(subcs->name1, name2) == 0) break;
3434 } else {
3435 if (strcmp(subcs->name2, name2) == 0) break;
3436 }
3437 }
3438
3439 return cf_item_to_section(ci);
3440 }
3441
3442 /*
3443 * Return the next subsection after a CONF_SECTION
3444 * with a certain name1 (char *name1). If the requested
3445 * name1 is NULL, any name1 matches.
3446 */
3447
cf_subsection_find_next(CONF_SECTION const * section,CONF_SECTION const * subsection,char const * name1)3448 CONF_SECTION *cf_subsection_find_next(CONF_SECTION const *section,
3449 CONF_SECTION const *subsection,
3450 char const *name1)
3451 {
3452 CONF_ITEM *ci;
3453
3454 if (!section) return NULL;
3455
3456 /*
3457 * If subsection is NULL this must be a first time run
3458 * Find the subsection with correct name
3459 */
3460
3461 if (!subsection) {
3462 ci = section->children;
3463 } else {
3464 ci = subsection->item.next;
3465 }
3466
3467 for (; ci; ci = ci->next) {
3468 if (ci->type != CONF_ITEM_SECTION)
3469 continue;
3470 if ((name1 == NULL) ||
3471 (strcmp(cf_item_to_section(ci)->name1, name1) == 0))
3472 break;
3473 }
3474
3475 return cf_item_to_section(ci);
3476 }
3477
3478
3479 /*
3480 * Return the next section after a CONF_SECTION
3481 * with a certain name1 (char *name1). If the requested
3482 * name1 is NULL, any name1 matches.
3483 */
3484
cf_section_find_next(CONF_SECTION const * section,CONF_SECTION const * subsection,char const * name1)3485 CONF_SECTION *cf_section_find_next(CONF_SECTION const *section,
3486 CONF_SECTION const *subsection,
3487 char const *name1)
3488 {
3489 if (!section) return NULL;
3490
3491 if (!section->item.parent) return NULL;
3492
3493 return cf_subsection_find_next(section->item.parent, subsection, name1);
3494 }
3495
3496 /** Return the next item after a CONF_ITEM.
3497 *
3498 */
cf_item_find_next(CONF_SECTION const * section,CONF_ITEM const * item)3499 CONF_ITEM *cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item)
3500 {
3501 if (!section) return NULL;
3502
3503 /*
3504 * If item is NULL this must be a first time run
3505 * Return the first item
3506 */
3507 if (item == NULL) {
3508 return section->children;
3509 } else {
3510 return item->next;
3511 }
3512 }
3513
_pair_count(int * count,CONF_SECTION const * cs)3514 static void _pair_count(int *count, CONF_SECTION const *cs)
3515 {
3516 CONF_ITEM const *ci;
3517
3518 for (ci = cf_item_find_next(cs, NULL);
3519 ci != NULL;
3520 ci = cf_item_find_next(cs, ci)) {
3521
3522 if (cf_item_is_section(ci)) {
3523 _pair_count(count, cf_item_to_section(ci));
3524 continue;
3525 }
3526
3527 (*count)++;
3528 }
3529 }
3530
3531 /** Count the number of conf pairs beneath a section
3532 *
3533 * @param[in] cs to search for items in.
3534 * @return number of pairs nested within section.
3535 */
cf_pair_count(CONF_SECTION const * cs)3536 int cf_pair_count(CONF_SECTION const *cs)
3537 {
3538 int count = 0;
3539
3540 _pair_count(&count, cs);
3541
3542 return count;
3543 }
3544
cf_item_parent(CONF_ITEM const * ci)3545 CONF_SECTION *cf_item_parent(CONF_ITEM const *ci)
3546 {
3547 if (!ci) return NULL;
3548
3549 return ci->parent;
3550 }
3551
cf_section_lineno(CONF_SECTION const * section)3552 int cf_section_lineno(CONF_SECTION const *section)
3553 {
3554 return section->item.lineno;
3555 }
3556
cf_pair_filename(CONF_PAIR const * pair)3557 char const *cf_pair_filename(CONF_PAIR const *pair)
3558 {
3559 return pair->item.filename;
3560 }
3561
cf_section_filename(CONF_SECTION const * section)3562 char const *cf_section_filename(CONF_SECTION const *section)
3563 {
3564 return section->item.filename;
3565 }
3566
cf_pair_lineno(CONF_PAIR const * pair)3567 int cf_pair_lineno(CONF_PAIR const *pair)
3568 {
3569 return pair->item.lineno;
3570 }
3571
cf_item_is_section(CONF_ITEM const * item)3572 bool cf_item_is_section(CONF_ITEM const *item)
3573 {
3574 return item->type == CONF_ITEM_SECTION;
3575 }
3576
cf_item_is_pair(CONF_ITEM const * item)3577 bool cf_item_is_pair(CONF_ITEM const *item)
3578 {
3579 return item->type == CONF_ITEM_PAIR;
3580 }
3581
cf_item_is_data(CONF_ITEM const * item)3582 bool cf_item_is_data(CONF_ITEM const *item)
3583 {
3584 return item->type == CONF_ITEM_DATA;
3585 }
3586
cf_data_alloc(CONF_SECTION * parent,char const * name,void * data,void (* data_free)(void *))3587 static CONF_DATA *cf_data_alloc(CONF_SECTION *parent, char const *name,
3588 void *data, void (*data_free)(void *))
3589 {
3590 CONF_DATA *cd;
3591
3592 cd = talloc_zero(parent, CONF_DATA);
3593 if (!cd) return NULL;
3594
3595 cd->item.type = CONF_ITEM_DATA;
3596 cd->item.parent = parent;
3597 cd->name = talloc_typed_strdup(cd, name);
3598 if (!cd->name) {
3599 talloc_free(cd);
3600 return NULL;
3601 }
3602
3603 cd->data = data;
3604 cd->free = data_free;
3605
3606 if (cd->free) {
3607 talloc_set_destructor(cd, _cf_data_free);
3608 }
3609
3610 return cd;
3611 }
3612
cf_data_find_internal(CONF_SECTION const * cs,char const * name,int flag)3613 static void *cf_data_find_internal(CONF_SECTION const *cs, char const *name, int flag)
3614 {
3615 if (!cs || !name) return NULL;
3616
3617 /*
3618 * Find the name in the tree, for speed.
3619 */
3620 if (cs->data_tree) {
3621 CONF_DATA mycd;
3622
3623 mycd.name = name;
3624 mycd.flag = flag;
3625 return rbtree_finddata(cs->data_tree, &mycd);
3626 }
3627
3628 return NULL;
3629 }
3630
3631 /*
3632 * Find data from a particular section.
3633 */
cf_data_find(CONF_SECTION const * cs,char const * name)3634 void *cf_data_find(CONF_SECTION const *cs, char const *name)
3635 {
3636 CONF_DATA *cd = cf_data_find_internal(cs, name, 0);
3637
3638 if (cd) return cd->data;
3639 return NULL;
3640 }
3641
3642
3643 /*
3644 * Add named data to a configuration section.
3645 */
cf_data_add_internal(CONF_SECTION * cs,char const * name,void * data,void (* data_free)(void *),int flag)3646 static int cf_data_add_internal(CONF_SECTION *cs, char const *name,
3647 void *data, void (*data_free)(void *),
3648 int flag)
3649 {
3650 CONF_DATA *cd;
3651
3652 if (!cs || !name) return -1;
3653
3654 /*
3655 * Already exists. Can't add it.
3656 */
3657 if (cf_data_find_internal(cs, name, flag) != NULL) return -1;
3658
3659 cd = cf_data_alloc(cs, name, data, data_free);
3660 if (!cd) return -1;
3661 cd->flag = flag;
3662
3663 cf_item_add(cs, cf_data_to_item(cd));
3664
3665 return 0;
3666 }
3667
3668 /*
3669 * Add named data to a configuration section.
3670 */
cf_data_add(CONF_SECTION * cs,char const * name,void * data,void (* data_free)(void *))3671 int cf_data_add(CONF_SECTION *cs, char const *name,
3672 void *data, void (*data_free)(void *))
3673 {
3674 return cf_data_add_internal(cs, name, data, data_free, 0);
3675 }
3676
3677 /** Remove named data from a configuration section
3678 *
3679 */
cf_data_remove(CONF_SECTION * cs,char const * name)3680 void *cf_data_remove(CONF_SECTION *cs, char const *name)
3681 {
3682 CONF_DATA mycd;
3683 CONF_DATA *cd;
3684 CONF_ITEM *ci, *it;
3685 void *data;
3686
3687 if (!cs || !name) return NULL;
3688 if (!cs->data_tree) return NULL;
3689
3690 /*
3691 * Find the name in the tree, for speed.
3692 */
3693 mycd.name = name;
3694 mycd.flag = 0;
3695 cd = rbtree_finddata(cs->data_tree, &mycd);
3696 if (!cd) return NULL;
3697
3698 ci = cf_data_to_item(cd);
3699 if (cs->children == ci) {
3700 cs->children = ci->next;
3701 if (cs->tail == ci) cs->tail = NULL;
3702 } else {
3703 for (it = cs->children; it; it = it->next) {
3704 if (it->next == ci) {
3705 it->next = ci->next;
3706 if (cs->tail == ci) cs->tail = it;
3707 break;
3708 }
3709 }
3710 }
3711
3712 talloc_set_destructor(cd, NULL); /* Disarm the destructor */
3713 rbtree_deletebydata(cs->data_tree, &mycd);
3714
3715 data = cd->data;
3716 talloc_free(cd);
3717
3718 return data;
3719 }
3720
3721 /*
3722 * This is here to make the rest of the code easier to read. It
3723 * ties conffile.c to log.c, but it means we don't have to
3724 * pollute every other function with the knowledge of the
3725 * configuration internals.
3726 */
cf_log_err(CONF_ITEM const * ci,char const * fmt,...)3727 void cf_log_err(CONF_ITEM const *ci, char const *fmt, ...)
3728 {
3729 va_list ap;
3730 char buffer[256];
3731
3732 va_start(ap, fmt);
3733 vsnprintf(buffer, sizeof(buffer), fmt, ap);
3734 va_end(ap);
3735
3736 if (ci) {
3737 ERROR("%s[%d]: %s",
3738 ci->filename ? ci->filename : "unknown",
3739 ci->lineno ? ci->lineno : 0,
3740 buffer);
3741 } else {
3742 ERROR("<unknown>[*]: %s", buffer);
3743 }
3744 }
3745
cf_log_err_cs(CONF_SECTION const * cs,char const * fmt,...)3746 void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt, ...)
3747 {
3748 va_list ap;
3749 char buffer[256];
3750
3751 va_start(ap, fmt);
3752 vsnprintf(buffer, sizeof(buffer), fmt, ap);
3753 va_end(ap);
3754
3755 rad_assert(cs != NULL);
3756
3757 ERROR("%s[%d]: %s",
3758 cs->item.filename ? cs->item.filename : "unknown",
3759 cs->item.lineno ? cs->item.lineno : 0,
3760 buffer);
3761 }
3762
cf_log_err_cp(CONF_PAIR const * cp,char const * fmt,...)3763 void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt, ...)
3764 {
3765 va_list ap;
3766 char buffer[256];
3767
3768 va_start(ap, fmt);
3769 vsnprintf(buffer, sizeof(buffer), fmt, ap);
3770 va_end(ap);
3771
3772 rad_assert(cp != NULL);
3773
3774 ERROR("%s[%d]: %s",
3775 cp->item.filename ? cp->item.filename : "unknown",
3776 cp->item.lineno ? cp->item.lineno : 0,
3777 buffer);
3778 }
3779
cf_log_info(CONF_SECTION const * cs,char const * fmt,...)3780 void cf_log_info(CONF_SECTION const *cs, char const *fmt, ...)
3781 {
3782 va_list ap;
3783
3784 va_start(ap, fmt);
3785 if ((rad_debug_lvl > 1) && cs) vradlog(L_DBG, fmt, ap);
3786 va_end(ap);
3787 }
3788
3789 /*
3790 * Wrapper to simplify the code.
3791 */
cf_log_module(CONF_SECTION const * cs,char const * fmt,...)3792 void cf_log_module(CONF_SECTION const *cs, char const *fmt, ...)
3793 {
3794 va_list ap;
3795 char buffer[256];
3796
3797 va_start(ap, fmt);
3798 if (rad_debug_lvl > 1 && cs) {
3799 vsnprintf(buffer, sizeof(buffer), fmt, ap);
3800
3801 DEBUG("%.*s# %s", cs->depth, parse_spaces, buffer);
3802 }
3803 va_end(ap);
3804 }
3805
cf_section_parse_table(CONF_SECTION * cs)3806 const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs)
3807 {
3808 if (!cs) return NULL;
3809
3810 return cs->variables;
3811 }
3812
3813 /*
3814 * For "switch" and "case" statements.
3815 */
cf_section_name2_type(CONF_SECTION const * cs)3816 FR_TOKEN cf_section_name2_type(CONF_SECTION const *cs)
3817 {
3818 if (!cs) return T_INVALID;
3819
3820 return cs->name2_type;
3821 }
3822