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