31 RCSID(
"$Id: 51d54f65af2e25c1aca5cafe83b6238b1ac5eaef $")
33 #include <freeradius-devel/server/cf_file.h>
34 #include <freeradius-devel/server/cf_priv.h>
35 #include <freeradius-devel/server/log.h>
36 #include <freeradius-devel/server/tmpl.h>
37 #include <freeradius-devel/server/util.h>
38 #include <freeradius-devel/server/virtual_servers.h>
39 #include <freeradius-devel/util/debug.h>
40 #include <freeradius-devel/util/file.h>
41 #include <freeradius-devel/util/misc.h>
42 #include <freeradius-devel/util/perm.h>
43 #include <freeradius-devel/util/syserror.h>
45 #include <sys/types.h>
57 #ifdef HAVE_SYS_STAT_H
58 # include <sys/stat.h>
64 #include <freeradius-devel/server/main_config.h>
92 #define MAX_STACK (32)
150 "Protocol dictionary must be NULL not %s",
164 #define RULES_VERIFY(_cs, _rules) if (cf_tmpl_rules_verify(_cs, _rules) < 0) return NULL
176 char *output,
size_t outsize,
180 char const *end, *next, *ptr;
184 if (soft_fail) *soft_fail =
false;
207 while (*ptr && (!end || (ptr < end))) {
211 if ((*ptr ==
'$') && (ptr[1] ==
'{')) {
219 ERROR(
"%s[%d]: Failed parsing variable expansion '%s''",
231 if ((
size_t) len >=
sizeof(
name)) {
232 ERROR(
"%s[%d]: Reference string is too large",
237 memcpy(
name, ptr, len - 3);
238 name[len - 3] =
'\0';
246 if (
name[0] ==
'/') {
247 int fd = open(
name, O_RDONLY);
251 ERROR(
"%s[%d]: Reference \"${%s}\" failed opening file - %s", cf, lineno,
name,
fr_syserror(errno));
255 if (fstat(fd, &buf) < 0) {
258 ERROR(
"%s[%d]: Reference \"${%s}\" failed reading file - %s", cf, lineno,
name,
fr_syserror(errno));
262 if (buf.st_size >= ((output + outsize) - p)) {
264 ERROR(
"%s[%d]: Reference \"${%s}\" file is too large (%zd >= %zd)", cf, lineno,
name,
265 (
size_t) buf.st_size, ((output + outsize) - p));
269 len = read(fd, p, (output + outsize) - p);
270 if (len < 0)
goto fail_fd;
279 q = strchr(
name,
':');
286 if (soft_fail) *soft_fail =
true;
287 ERROR(
"%s[%d]: Reference \"${%s}\" not found", cf, lineno,
name);
299 ERROR(
"%s[%d]: Can only reference properties of sections", cf, lineno);
313 ERROR(
"%s[%d]: Invalid property '%s'", cf, lineno, q);
332 if (soft_fail) *soft_fail =
true;
334 ERROR(
"%s[%d]: Reference \"%s\" points to a variable which has not been expanded.",
340 ERROR(
"%s[%d]: Reference \"%s\" has no value",
345 if (p + strlen(cp->
value) >= output + outsize) {
346 ERROR(
"%s[%d]: Reference \"%s\" is too long",
364 ERROR(
"%s[%d]: Cannot reference different item in same section", cf, lineno);
377 ERROR(
"%s[%d]: Failed copying reference %s", cf, lineno,
name);
387 ERROR(
"%s[%d]: Reference \"%s\" type is invalid", cf, lineno, input);
390 }
else if (strncmp(ptr,
"$ENV{", 5) == 0) {
400 next = strchr(ptr,
'}');
403 ERROR(
"%s[%d]: Environment variable expansion missing }",
412 if ((
size_t) (next - ptr) >=
sizeof(
name)) {
413 ERROR(
"%s[%d]: Environment variable name is too large",
418 memcpy(
name, ptr, next - ptr);
419 name[next - ptr] =
'\0';
431 if (p + strlen(env) >= output + outsize) {
432 ERROR(
"%s[%d]: Reference \"%s\" is too long",
449 if (p >= (output + outsize)) {
450 ERROR(
"%s[%d]: Reference \"%s\" is too long",
466 if (!cs || !
template)
return true;
492 if (!cp2)
return false;
524 if (!subcs2)
return false;
546 return CMP(a->
buf.st_ino, b->buf.st_ino);
578 if (
fr_dirfd(&dirfd, &r, filename) < 0) {
579 ERROR(
"Failed to open directory containing %s", filename);
583 if (fstatat(dirfd, r, &my_file.
buf, 0) < 0)
goto error;
597 if (dirfd != AT_FDCWD)
close(dirfd);
600 fd = openat(dirfd, r, O_RDONLY, 0);
601 fp = (fd < 0) ? NULL : fdopen(fd,
"r");
602 if (dirfd != AT_FDCWD)
close(dirfd);
604 fp = fopen(filename,
"r");
605 if (fp) fd = fileno(fp);
608 DEBUG2(
"including configuration file %s", filename);
618 file->filename = talloc_strdup(
file, filename);
620 file->from_dir = from_dir;
622 if (fstat(fd, &
file->buf) == 0) {
624 if ((
file->buf.st_mode & S_IWOTH) != 0) {
625 ERROR(
"Configuration file %s is globally writable. "
626 "Refusing to start due to insecure configuration.", filename);
668 if (!tree)
return false;
671 if (!
file)
return false;
673 file->filename = talloc_strdup(
file, filename);
677 if (stat(filename, &
file->buf) < 0) {
680 cf_log_perr(cp,
"Unable to open file \"%s\"", filename);
682 if (fd >= 0)
close(fd);
696 uid_t euid = (uid_t)-1;
697 gid_t egid = (gid_t)-1;
701 cf_log_perr(cp,
"Failed setting effective group ID (%i) for file check: %s",
708 cf_log_perr(cp,
"Failed setting effective user ID (%i) for file check: %s",
713 fd = open(filename, O_RDONLY);
715 if (seteuid(euid) < 0) {
716 cf_log_perr(cp,
"Failed restoring effective user ID (%i) after file check: %s",
722 if (setegid(egid) < 0) {
723 cf_log_perr(cp,
"Failed restoring effective group ID (%i) after file check: %s",
730 if (fd < 0)
goto perm_error;
731 if (fstat(fd, &
file->buf) < 0)
goto perm_error;
736 if ((
file->buf.st_mode & S_IWOTH) != 0) {
737 cf_log_perr(cp,
"Configuration file %s is globally writable. "
738 "Refusing to start due to insecure configuration.", filename);
775 if (!
value)
return -1;
792 char *
buffer,
size_t bufsize)
799 p = strrchr(
buffer, FR_DIR_SEP);
800 if (!p)
return filename;
805 dirsize = (p -
buffer) + 1;
807 if ((dirsize + strlen(filename)) >= bufsize) {
811 strlcpy(p + 1, filename, bufsize - dirsize);
821 char const *filename,
int lineno)
823 char const *ptr = *ptr_p;
835 slen =
tmpl_preparse(&
out, &outlen, ptr, strlen(ptr), token, NULL,
false,
true);
841 ERROR(
"%s[%d]: %s", filename, lineno, text);
849 if ((
size_t) slen >= buflen) {
850 ERROR(
"%s[%d]: Name is too long", filename, lineno);
858 out, outlen, NULL)) {
894 ERROR(
"%s[%d]: Parse error: Invalid location for $INCLUDE",
905 while (*ptr && !isspace((
uint8_t) *ptr)) ptr++;
923 if (*
value ==
'$') relative =
false;
927 if (!
value)
return -1;
929 if (!FR_DIR_IS_RELATIVE(
value)) relative =
false;
939 if (strchr(
value,
'*') != 0) {
946 memset(frame, 0,
sizeof(*frame));
948 frame->
type = CF_STACK_GLOB;
949 frame->required = required;
960 if (glob(
value, GLOB_ERR | GLOB_NOESCAPE, NULL, &frame->glob) < 0) {
970 if (frame->glob.gl_pathc == 0) {
991 if (stat(
value, &statbuf) < 0) {
1008 memset(frame, 0,
sizeof(*frame));
1019 #ifdef HAVE_DIRENT_H
1030 struct stat stat_buf;
1041 dir = opendir(directory);
1043 ERROR(
"%s[%d]: Error reading directory %s: %s",
1054 if (fstat(dirfd(dir), &stat_buf) < 0) {
1060 if ((stat_buf.st_mode & S_IWOTH) != 0) {
1061 ERROR(
"%s[%d]: Directory %s is globally writable. Refusing to start due to "
1062 "insecure configuration", frame->
filename, frame->
lineno, directory);
1078 .
type = CF_STACK_DIR,
1079 .directory = directory,
1093 while ((dp = readdir(dir)) != NULL) {
1096 if (dp->d_name[0] ==
'.')
continue;
1101 for (p = dp->d_name; *p !=
'\0'; p++) {
1106 (*p ==
'.'))
continue;
1109 if (*p !=
'\0')
continue;
1112 frame->directory, dp->d_name);
1114 if (stat(
stack->buff[1], &stat_buf) != 0) {
1115 ERROR(
"%s[%d]: Failed checking file %s: %s",
1116 (frame - 1)->filename, (frame - 1)->lineno,
1121 if (S_ISDIR(stat_buf.st_mode)) {
1122 WARN(
"%s[%d]: Ignoring directory %s",
1123 (frame - 1)->filename, (frame - 1)->lineno,
1142 ERROR(
"%s[%d]: Error including %s: No support for directories!",
1158 if (token !=
T_EOL) {
1164 ERROR(
"%s[%d]: Internal sanity check error in template reference", frame->
filename, frame->
lineno);
1178 parent->template = templatecs;
1186 ERROR(
"%s[%d]: Cannot find template \"%s\", as no 'templates' section exists.",
1193 ERROR(
"%s[%d]: No such template \"%s\" in the 'templates' section.",
1224 char quote, end_quote;
1225 char const *p = start;
1230 if (end && ((start + 4) > end)) {
1235 if ((*p !=
'%') && (*p !=
'$')) {
1237 return -(p - start);
1241 if ((*p !=
'{') && (*p !=
'(')) {
1247 while (isalnum((
int) *q) || (*q ==
'.') || (*q ==
'_') || (*q ==
'-')) {
1256 return -(p - start);
1267 while ((end && (p < end)) || (*p >=
' ')) {
1274 if (*p == end_quote) {
1277 if (!
depth)
return p - start;
1285 if ((p[0] ==
'$') || (p[0] ==
'%')) {
1286 if (end && (p + 2) >= end)
break;
1288 if ((p[1] ==
'{') || ((p[0] ==
'$') && (p[1] ==
'('))) {
1292 if (slen <= 0)
return -(p - start) + slen;
1308 if ((*p ==
'"') || (*p ==
'\'') || (*p ==
'`')) {
1324 if (end && ((p + 2) >= end))
break;
1329 if (p[1] <
' ')
break;
1337 return -(p - start);
1374 char const *p = start;
1375 bool was_regex =
false;
1384 while ((end && (p < end)) || *p) {
1393 if ((
depth == 0) && terminal && terminal[(
uint8_t) *p]) {
1410 return -(p - start);
1422 if ((*p ==
'$') || (*p ==
'%')) {
1423 if (end && ((p + 2) >= end)) {
1425 return -(p - start);
1428 if ((p[1] ==
'{') || ((p[0] ==
'$') && (p[1] ==
'('))) {
1432 if (slen <= 0)
return -(p - start) + slen;
1449 if ((*p ==
'"') || (*p ==
'\'') || (*p ==
'`') || (was_regex && (*p ==
'/'))) {
1463 if ((p[0] ==
'=') || (p[0] ==
'!')) {
1464 if (end && ((p + 2) >= end)) {
1466 return -(p - start);
1486 if (*p <
' ')
break;
1501 if (end && ((p + 2) >= end))
break;
1506 if (p[1] <
' ')
break;
1515 if (terminal && terminal[(
uint8_t) *p])
return p - start;
1518 return -(p - start);
1527 char const *ptr =
stack->ptr;
1546 .allow_unresolved =
true,
1547 .allow_unknown =
true
1582 if (slen > 0)
break;
1599 p = (
uint8_t const *) ptr + (-slen);
1605 if (*p && (*p <
' ')) {
1606 while ((*p ==
'\r') || (*p ==
'\n')) {
1649 buff[2][slen] =
'\0';
1654 buff[2][slen] =
'\0';
1674 cf_log_err(cs,
"Expected '{' instead of %s", ptr);
1689 char const *
value = NULL;
1692 char const *ptr =
stack->ptr;
1709 ERROR(
"%s[%d]: Invalid syntax for 'map' - module name must not be a quoted string",
1732 ERROR(
"%s[%d]: Expecting string expansions in 'map' definition",
1738 ERROR(
"%s[%d]: Expecting section start brace '{' in 'map' definition",
1751 ERROR(
"%s[%d]: Failed allocating memory for section",
1761 css->
argv = talloc_array(css,
char const *, 1);
1776 char const *mod = NULL;
1779 char const *ptr =
stack->ptr;
1810 ERROR(
"%s[%d]: The first argument to 'subrequest' must be a name or an attribute reference",
1833 ERROR(
"%s[%d]: The second argument to 'subrequest' must be an attribute reference",
1853 ERROR(
"%s[%d]: The third argument to 'subrequest' must be an attribute reference",
1860 ERROR(
"%s[%d]: Expecting section start brace '{' in 'subrequest' definition",
1872 ERROR(
"%s[%d]: Failed allocating memory for section",
1884 css->
argv = talloc_array(css,
char const *, values);
1887 for (i = 0; i < values; i++) {
1904 char const *ptr =
stack->ptr;
1928 while (isalpha((
uint8_t) *ptr)) ptr++;
1932 ERROR(
"%s[%d]: Invalid syntax for 'catch' - unknown rcode '%s'",
1937 if ((*ptr !=
'{') && !isspace((
uint8_t) *ptr)) {
1938 ERROR(
"%s[%d]: Invalid syntax for 'catch' - unexpected text at '%s'",
1944 name2 = talloc_strndup(NULL, p, len);
1949 ERROR(
"%s[%d]: Invalid syntax for 'catch' - too many arguments at'%s'",
1954 argv[argc++] = talloc_strndup(name2, p, len);
1960 ERROR(
"%s[%d]: Failed allocating memory for section",
1973 css->
argv = talloc_array(css,
char const *, argc + 1);
1977 for (i = 0; i < argc; i++) {
1982 css->
argv[argc] = NULL;
1995 char const *name1 = *attr;
2000 if (!dot[1] || (dot[1] ==
'.')) {
2001 ERROR(
"%s[%d]: Invalid name", filename, lineno);
2005 if ((
size_t) (dot - name1) >= buffer_len) {
2006 ERROR(
"%s[%d]: Name too long", filename, lineno);
2010 memcpy(
buffer, name1, dot - name1);
2011 buffer[dot - name1] =
'\0';
2022 if (!p || ((p[1] !=
'\0') && (p[1] !=
'.'))) {
2023 cf_log_err(*
parent,
"Could not parse name2 in '%s', expected 'name1[name2]", name1);
2049 p = strchr(next + 1,
'.');
2057 char *
buff,
char const *filename,
int lineno)
2076 char const *p = strchr(attr,
'.');
2089 char const *expanded;
2095 }
else if (!soft_fail) {
2142 fr_token_t name1_token, name2_token, value_token, op_token;
2145 char const *ptr =
stack->ptr;
2218 if (
parent->allow_unlang != 1) {
2219 if ((strcmp(
buff[1],
"if") == 0) ||
2220 (strcmp(
buff[1],
"elsif") == 0)) {
2221 ERROR(
"%s[%d]: Invalid location for '%s'",
2237 ci = process(
stack);
2241 parent->allow_locals =
false;
2255 if (!isalnum((
int) *ptr))
goto check_for_eol;
2263 parent->allow_locals =
false;
2268 ERROR(
"%s[%d]: Parse error: Invalid location for variable definition",
2296 if (!*ptr || (*ptr ==
'#') || (*ptr ==
',') || (*ptr ==
';') || (*ptr ==
'}')) {
2297 parent->allow_locals =
false;
2328 if ((*ptr ==
'"') || (*ptr ==
'`') || (*ptr ==
'\'') || ((*ptr ==
'&') && (ptr[1] !=
'=')) ||
2337 ERROR(
"%s[%d]: Parse error: expected '{', got text \"%s\"",
2347 ERROR(
"%s[%d]: Failed allocating memory for section",
2362 if (!frame->
special && (strcmp(css->
name1,
"update") == 0)) {
2376 }
else if ((
parent->allow_unlang == 2) && (strcmp(css->
name1,
"listen") == 0)) {
2403 if ((ptr[0] !=
'=') && (ptr[0] !=
'!') && (ptr[0] !=
'<') && (ptr[0] !=
'>') &&
2404 (ptr[1] !=
'=') && (ptr[1] !=
'~')) {
2405 ERROR(
"%s[%d]: Parse error at unexpected text: %s",
2415 switch (name2_token) {
2433 ERROR(
"%s[%d]: Invalid operator in assignment for %s ...",
2443 op_token = name2_token;
2447 ERROR(
"%s[%d]: Parse error after \"%s\": unexpected token \"%s\"",
2456 if (!*ptr || (*ptr ==
'#') || (*ptr ==
',') || (*ptr ==
';')) {
2457 ERROR(
"%s[%d]: Syntax error: Expected to see a value after the operator '%s': %s",
2475 ERROR(
"%s[%d]: Parse error: Invalid location for grouped attribute",
2480 if (*
buff[1] !=
'&') {
2481 ERROR(
"%s[%d]: Parse error: Expected '&' before attribute name",
2487 ERROR(
"%s[%d]: Parse error: Invalid assignment operator '%s' for list",
2521 char const *ptr2 = ptr;
2526 if ((*ptr ==
'(') || (*ptr ==
'%')) {
2536 parent->allow_locals =
false;
2561 ERROR(
"%s[%d]: Parse error in expression: %s",
2570 ERROR(
"%s[%d]: Expression is unfinished at end of line",
2578 memcpy(
buff[2], ptr, slen);
2579 buff[2][slen] =
'\0';
2595 if ((*ptr ==
',') || (*ptr ==
';')) ptr++;
2608 parent->allow_locals =
false;
2622 if ((*ptr ==
';') || (*ptr ==
',')) {
2641 if (*ptr && (*ptr !=
'#')) {
2642 ERROR(
"%s[%d]: Syntax error: Unexpected text: %s",
2677 memset(frame, 0,
sizeof(*frame));
2694 bool at_eof, has_spaces;
2706 at_eof = (fgets(
stack->fill,
stack->bufsize - (
stack->fill -
stack->buff[0]), frame->fp) == NULL);
2716 len = strlen(
stack->fill);
2730 if (ptr >
stack->fill) {
2731 memmove(
stack->fill, ptr, len - (ptr -
stack->fill));
2732 len -= (ptr -
stack->fill);
2741 if (at_eof)
return 0;
2743 ptr =
stack->buff[0];
2746 if (!*ptr || (*ptr ==
'#'))
goto read_more;
2748 }
else if (at_eof || (len == 0)) {
2757 ((
stack->fill[len - 1] ==
'\n') || (
stack->fill[len - 1] ==
'\r'))) {
2759 stack->fill[len] =
'\0';
2762 if ((len > 0) && (
stack->fill[len - 1] ==
'\\')) {
2766 if (!has_spaces && (len > 2) && (
stack->fill[len - 2] ==
'"')) {
2770 stack->fill[len - 1] =
'\0';
2771 stack->fill += len - 1;
2772 goto read_continuation;
2787 if (!*ptr || (*ptr ==
'#'))
goto read_more;
2808 switch (frame->
type) {
2811 if (frame->gl_current == frame->glob.gl_pathc) {
2812 globfree(&frame->glob);
2832 #ifdef HAVE_DIRENT_H
2835 if (rcode == 0)
goto do_frame;
2836 if (rcode < 0)
return -1;
2867 if (rcode < 0)
return -1;
2888 if (rcode < 0)
return -1;
2889 if (rcode == 0)
break;
2895 ptr =
stack->buff[0];
2913 if (rcode < 0)
return -1;
2914 if (rcode == 0)
continue;
2939 if (!*ptr || (*ptr ==
'#'))
break;
2945 if (rcode < 0)
return -1;
2947 }
while (rcode == 1);
2956 ERROR(
"%s[%d]: EOF reached without closing brace for section %s starting at line %d",
2968 if (
stack->depth > 0) {
2980 while (
stack->depth >= 0) {
2981 switch (frame->
type) {
2983 if (frame->fp) fclose(frame->fp);
2987 #ifdef HAVE_DIRENT_H
2995 globfree(&frame->glob);
3022 p = strrchr(cp->
value, FR_DIR_SEP);
3036 stack.buff = talloc_array(cs,
char *, 4);
3037 for (i = 0; i < 4; i++)
MEM(
stack.buff[i] = talloc_array(
stack.buff,
char, 8192));
3040 stack.bufsize = 8192;
3043 memset(frame, 0,
sizeof(*frame));
3062 cf_log_err(cs,
"Parsing config items failed");
3116 if (c) fprintf(fp,
"%c", c);
3119 fwrite(
buffer, outlen, 1, fp);
3121 if (c) fprintf(fp,
"%c", c);
3128 fprintf(fp,
"%s\n", cp->
attr);
3143 if (!fp || !cs)
return -1;
3166 fprintf(fp,
"(%s)",
buffer);
3188 if (!ci->filename || (ci->filename[0] ==
'<'))
break;
3216 if (!ptr || (!parent_cs && !outer_cs))
return NULL;
3250 }
else if (strchr(p,
'.') != NULL) {
3251 if (!parent_cs)
return NULL;
3260 if (!r && !q)
break;
3262 if (r && q > r) q = NULL;
3263 if (q && q < r) r = NULL;
3269 q = strchr(r + 1,
']');
3270 if (!q)
return NULL;
3276 if (q[1] && q[1] !=
'.')
return NULL;
3289 if (!next)
return NULL;
3290 return &(next->
item);
3308 if (!*p)
return NULL;
3323 if (next)
return &(next->
item);
3328 if ((p ==
name) && (parent_cs != NULL) && (cs != parent_cs)) {
static int const char char buffer[256]
strcpy(log_entry->msg, buffer)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
CONF_SECTION * current
sub-section we're reading
static bool cf_template_merge(CONF_SECTION *cs, CONF_SECTION const *template)
static int parse_input(cf_stack_t *stack)
char * fill
where we start filling the buffer from
struct cf_file_heap_t cf_file_heap_t
static int unlang_keywords_len
static char const * cf_local_file(char const *base, char const *filename, char *buffer, size_t bufsize)
bool require_edits
are we required to do edits?
char const * cf_expand_variables(char const *cf, int lineno, CONF_SECTION *outer_cs, char *output, size_t outsize, char const *input, ssize_t inlen, bool *soft_fail)
static CONF_ITEM * process_map(cf_stack_t *stack)
static int frame_readdir(cf_stack_t *stack)
static ssize_t fr_skip_condition(char const *start, char const *end, bool const terminal[static UINT8_MAX+1], bool *eol)
Skip a conditional expression.
static int add_pair(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t name1_token, fr_token_t op_token, fr_token_t value_token, char *buff, char const *filename, int lineno)
#define RULES_VERIFY(_cs, _rules)
static void cf_stack_cleanup(cf_stack_t *stack)
static int cf_tmpl_rules_verify(CONF_SECTION *cs, tmpl_rules_t const *rules)
static CONF_ITEM * process_catch(cf_stack_t *stack)
static ssize_t fr_skip_xlat(char const *start, char const *end)
Skip an xlat expression.
CONF_ITEM *(* cf_process_func_t)(cf_stack_t *)
static CONF_ITEM * process_subrequest(cf_stack_t *stack)
static int cf_file_open(CONF_SECTION *cs, char const *filename, bool from_dir, FILE **fp_p)
static int8_t filename_cmp(void const *one, void const *two)
int cf_section_write(FILE *fp, CONF_SECTION *cs, int depth)
bool cf_file_check(CONF_PAIR *cp, bool check_perms)
Do some checks on the file as an "input" file.
int lineno
line in that filename
int cf_file_read(CONF_SECTION *cs, char const *filename)
static const bool terminal_end_section[UINT8_MAX+1]
static size_t conf_property_name_len
static fr_table_num_sorted_t const conf_property_name[]
int cf_section_pass2(CONF_SECTION *cs)
bool from_dir
this file was read from $include foo/
static ssize_t cf_string_write(FILE *fp, char const *string, size_t len, fr_token_t t)
static char const parse_tabs[]
CONF_SECTION * special
map / update section
static int cf_file_include(cf_stack_t *stack)
static uid_t conf_check_uid
static gid_t conf_check_gid
static int cf_get_token(CONF_SECTION *parent, char const **ptr_p, fr_token_t *token, char *buffer, size_t buflen, char const *filename, int lineno)
static int8_t _inode_cmp(void const *one, void const *two)
static int cf_file_fill(cf_stack_t *stack)
char const * ptr
current parse pointer
void cf_file_check_user(uid_t uid, gid_t gid)
Set the euid/egid used when performing file checks.
static int add_section_pair(CONF_SECTION **parent, char const **attr, char const *dot, char *buffer, size_t buffer_len, char const *filename, int lineno)
enum conf_property CONF_PROPERTY
static fr_table_ptr_sorted_t unlang_keywords[]
char ** buff
buffers for reading / parsing
CONF_SECTION * parent
which started this file
static int process_template(cf_stack_t *stack)
size_t bufsize
size of the buffers
static int cf_pair_write(FILE *fp, CONF_PAIR *cp)
static int process_include(cf_stack_t *stack, CONF_SECTION *parent, char const *ptr, bool required, bool relative)
void cf_file_free(CONF_SECTION *cs)
static CONF_ITEM * process_if(cf_stack_t *stack)
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
static const bool terminal_end_line[UINT8_MAX+1]
char const * filename
filename we're reading
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
Defines a CONF_PAIR to C data type mapping.
CONF_SECTION * cs
CONF_SECTION associated with the file.
CONF_ITEM item
Common set of fields.
CONF_ITEM * parent
Parent.
fr_token_t name2_quote
The type of quoting around name2.
char const * name2
Second name token. Given foo bar {} would be bar.
bool allow_locals
allow local variables
int argc
number of additional arguments
char const * attr
Attribute name.
fr_token_t rhs_quote
Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
char const * value
Attribute value.
#define cf_item_foreach(_ci, _iter)
Iterate over the contents of a list.
char const * name1
First name token. Given foo bar {} would be foo.
int allow_unlang
depth at which we allow unlang
fr_token_t op
Operator e.g. =, :=.
CONF_ITEM item
Common set of fields.
bool pass2
do expansion in pass2.
char const * filename
The file the config item was parsed from.
struct stat buf
stat about the file
char const * filename
name of the file
bool referenced
Was this item referenced in the config?
char const ** argv
additional arguments
fr_token_t lhs_quote
Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
int lineno
The line number the config item began on.
CONF_ITEM_TYPE type
Whether the config item is a config_pair, conf_section or cf_data.
Internal data that is associated with a configuration section.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_section_find_parent(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a parent CONF_SECTION with name1 and optionally name2.
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_section_find_in_parent(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a section in the lineage of a CONF_SECTION which matches a specific name1 and optionally name2.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
CONF_SECTION * cf_section_dup(TALLOC_CTX *ctx, CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp)
Duplicate a CONF_PAIR.
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_data_find(_cf, _type, _name)
#define cf_lineno_set(_ci, _lineno)
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define CF_TO_ITEM(_cf)
Auto cast from the input type to CONF_ITEM (which is the base type)
#define cf_filename_set(_ci, _filename)
#define cf_log_warn(_cf, _fmt,...)
#define cf_log_debug(_cf, _fmt,...)
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
static char const * spaces
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_t const * fr_dict_internal(void)
int fr_dirfd(int *dirfd, char const **filename, char const *pathname)
From a pathname, return fd and filename needed for *at() functions.
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
unsigned int fr_heap_index_t
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
#define FR_HEAP_INDEX_INVALID
void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
static char * stack[MAX_STACK]
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
static uint8_t depth(fr_minmax_heap_index_t i)
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
int strncasecmp(char *s1, char *s2, int n)
void fr_perm_file_error(int num)
Write a file access error to the fr_strerror buffer, including euid/egid.
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.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
The main red black tree structure.
@ RLM_MODULE_NUMCODES
How many valid return codes there are.
fr_dict_attr_t const * request_attr_request
#define check(_handle, _len_p)
#define FR_SBUFF_OUT(_start, _len_or_end)
bool at_runtime
Produce an ephemeral/runtime tmpl.
ssize_t tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t inlen, fr_token_t *type, fr_dict_attr_t const **castda, bool require_regex, bool allow_xlat))
Preparse a string in preparation for passing it to tmpl_afrom_substr()
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
struct tmpl_rules_s tmpl_rules_t
Optional arguments passed to vp_tmpl functions.
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
uint8_t allow_foreign
Allow arguments not found in dict_def.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
An element in a lexicographically sorted array of name to ptr mappings.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int talloc_const_free(void const *ptr)
Free const'd memory.
const bool fr_list_assignment_op[T_TOKEN_LAST]
ssize_t fr_skip_string(char const *start, char const *end)
Skip a quoted string.
fr_token_t gettoken(char const **ptr, char *buf, int buflen, bool unescape)
fr_table_num_ordered_t const fr_tokens_table[]
const bool fr_str_tok[T_TOKEN_LAST]
int getword(char const **ptr, char *buf, int buflen, bool unescape)
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.