27RCSID(
"$Id: a818e4f92a8f2d5bb1583a8ebcf735e3289db139 $")
31#include <freeradius-devel/server/cf_file.h>
32#include <freeradius-devel/server/cf_parse.h>
33#include <freeradius-devel/server/cf_priv.h>
34#include <freeradius-devel/server/log.h>
35#include <freeradius-devel/server/tmpl.h>
36#include <freeradius-devel/server/virtual_servers.h>
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/util/inet.h>
39#include <freeradius-devel/util/misc.h>
40#include <freeradius-devel/util/perm.h>
41#include <freeradius-devel/util/types.h>
46#define PAIR_SPACE(_cs) ((_cs->depth + 1) * 2)
47#define SECTION_SPACE(_cs) (_cs->depth * 2)
53 char const *quote =
"";
129 cf_log_perr(cp,
"Invalid value \"%s\" for config item %s",
174 bool cant_be_empty, tmpl;
191 if (!rule->
type && !tmpl) {
192 cf_log_err(cp,
"Configuration pair \"%s\" must have a data type", cp->
attr);
200 cf_log_err(cp,
"Configuration pair \"%s\" must have a value", cp->
attr);
207 if ((cp->
value[0] ==
'\0') && cant_be_empty) {
208 cf_log_err(cp,
"Configuration pair \"%s\" must not be empty (zero length)", cp->
attr);
220 .allow_unresolved =
true,
221 .allow_foreign =
true,
241 cf_log_err(cp,
"Invalid quoting. Unquoted attribute reference is required");
248 if (!
vpt)
goto tmpl_error;
273 cf_log_perr(cp,
"Failed unboxing parsed configuration item value");
300 char const *expanded;
305 fr_assert(rule->dflt || rule->dflt_func);
308 cf_log_err(cs,
"Configuration pair \"%s\" must have a value", rule->
name1);
326 if (rule->dflt_func) {
327 if (rule->dflt_func(
out,
parent, cs, dflt_quote, rule) < 0) {
355 char *str, *unescaped, *q;
357 if (!cp->
value)
return 0;
365 if (strchr(cp->
value,
'\\') == NULL)
return 0;
367 str = talloc_strdup(cp, cp->
value);
393 if (*p >=
'0' && *p <=
'9' &&
394 sscanf(p,
"%3o", &x) == 1) {
396 cf_log_err(cp,
"Cannot have embedded zeros in value for %s", cp->
attr);
412 if (!unescaped)
return -1;
420 cp->
value = unescaped;
443 bool required, deprecated;
448 char const *dflt = rule->dflt;
461 cf_log_err(cs,
"Rule doesn't specify output destination");
487 if (deprecated)
return 0;
492 cf_log_err(cs,
"Configuration item \"%s\" must have a value", rule->name1);
502 cf_log_err(cs,
"Configuration item \"%s\" cannot be empty", rule->name1);
518 cf_log_err(cp,
"Configuration pair \"%s\" is deprecated", cp->
attr);
551 TALLOC_CTX *value_ctx = array;
580 if (array) *(
void **)
out = array;
591 if (deprecated)
return 0;
594 if (required)
goto need_value;
602 cf_log_err(cs,
"Configuration item \"%s\" cannot be empty", rule->name1);
617 if (deprecated)
goto deprecated;
623 if (ret < 0)
return -1;
730 char const *name2 = NULL;
748 is_set = rule->
data ? rule->is_set_ptr : ((
uint8_t *)base) + rule->is_set_offset;
749 if (is_set) *is_set = (subcs != NULL);
793 if (!subcs)
return -1;
810 for (rule_p = rule->subcs; rule_p->
name1; rule_p++) {
812 if (ret < 0)
return ret;
821 if (cp && cp->
parsed)
return 0;
830 *(
char **) rule->
data = NULL;
832 *(
char **) (((
char *)base) + rule->
offset) = NULL;
855 WARN(
"%s[%d]: The item '%s' is defined, but is unused by the configuration",
856 ci->filename, ci->lineno,
887 int count = 0, i = 0, ret;
889 size_t subcs_size = rule->subcs_size;
897 if (!subcs)
return 0;
924 if (rule->subcs_type) talloc_set_name_const(
buff, rule->subcs_type);
951 if (rule->subcs_type) talloc_set_name(array,
"%s *", rule->subcs_type);
970 if (rule->subcs_type) talloc_set_name_const(
buff, rule->subcs_type);
1006 bool *is_set = NULL;
1044 sub_base += rule->
offset;
1046 for (rule_p = rule->subcs; rule_p->
name1; rule_p++) {
1050 if (ret < 0)
return ret;
1072 cf_log_err(cs,
"Rule doesn't specify output destination");
1081 is_set = rule->
data ? rule->is_set_ptr : ((
uint8_t *)base) + rule->is_set_offset;
1090 if (is_set) *is_set =
false;
1095 if (is_set) *is_set =
true;
1102 if (((rule + 1)->offset && ((rule + 1)->offset == rule->
offset)) ||
1103 ((rule + 1)->data && ((rule + 1)->data == rule->
data))) {
1144 if (ret < 0)
return ret;
1167 bool attribute,
fr_dict_t const *dict_def)
1174 cf_log_perr(cp,
"Failed processing configuration item '%s'", cp->
attr);
1184 switch (
vpt->type) {
1197 cf_log_perr(cp,
"Failed processing configuration item '%s'", cp->
attr);
1237 bool attribute, multi, is_tmpl, is_xlat;
1268 len = talloc_array_length(array);
1293 if (!
data)
continue;
1308 if (!is_xlat && !is_tmpl) {
1315 if (strstr(cp->
value,
"%{") != NULL) {
1316 cf_log_err(cp,
"Found dynamic expansion in string which "
1317 "will not be dynamically expanded");
1351 .list_def = request_attr_request,
1352 .allow_unknown = false,
1353 .allow_unresolved = false,
1354 .allow_foreign = (dict == NULL)
1362 cf_log_err(cp,
"Failed parsing expansion string:");
1386 }
else if (is_tmpl && !multi) {
1391 }
else if (is_tmpl) {
1393 char const *
name = cp->attr;
1422 char const *name1, *name2;
1424 if (!cs || !rule)
return 0;
1430 cf_log_debug(cs,
"Pushed parse rule to %s section: %s %s",
1451 if (memcmp(rule, old,
sizeof(*rule)) == 0) {
1471 memcpy(&cd1, &cd,
sizeof(cd1));
1488 cf_log_err(cs,
"Failed finding '%s' subsection", name1);
1503 cf_log_err(cs,
"Data of type %s with name \"%s\" already exists. "
1504 "Existing data added %s[%i]",
"conf_parser_t",
1528 if (!cs || !rules)
return 0;
1530 for (rule_p = rules; rule_p->
name1; rule_p++) {
1558 *((
int *)
out) = num;
1574 *((int32_t *)
out) = num;
1590 cf_log_err(ci,
"Resolved value must be a positive integer, got %i", num);
static int const char char buffer[256]
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)
bool cf_file_check(CONF_PAIR *cp, bool check_perms)
Do some checks on the file as an "input" file.
int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_UINT32)
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_INT32)
static int cf_pair_default(CONF_PAIR **out, void *parent, CONF_SECTION *cs, conf_parser_t const *rule)
Allocate a pair using the dflt value and quotation.
static char const parse_spaces[]
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type.
static int cf_pair_unescape(CONF_PAIR *cp, conf_parser_t const *rule)
static void cf_section_parse_warn(CONF_SECTION *cs)
static conf_parser_t conf_term
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving GID strings to uid_t values.
int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
static int cf_pair_parse_internal(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type, with a default value.
int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving permissions to a mode-t.
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
static int cf_section_parse_init(CONF_SECTION *cs, void *base, conf_parser_t const *rule)
Pre-allocate a config section structure to allow defaults to be set.
int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
Add a single rule to a CONF_SECTION.
#define SECTION_SPACE(_cs)
int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno)
Add an array of parse rules to a CONF_SECTION.
int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
Parses a CONF_PAIR into a boxed value.
static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Parse a subsection.
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving UID strings to uid_t values.
static int cf_parse_tmpl_pass2(UNUSED CONF_SECTION *cs, tmpl_t **out, CONF_PAIR *cp, fr_type_t type, bool attribute, fr_dict_t const *dict_def)
static int cf_section_parse_rule(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
void const * uctx
User data accessible by the cf_parse_t func.
void * data
Pointer to a static variable to write the parsed value to.
#define fr_rule_dflt(_rule)
conf_parser_flags_t flags
Flags which control parsing behaviour.
#define fr_rule_not_empty(_rule)
fr_type_t type
An fr_type_t value, controls the output type.
size_t offset
Relative offset of field or structure to write the parsed value to.
#define fr_rule_multi(_rule)
char const * name2
Second identifier for CONF_SECTION.
fr_token_t quote
Quoting around the default value. Only used for templates.
fr_table_num_sorted_t const * table
#define fr_rule_file_exists(_rule)
#define fr_rule_deprecated(_rule)
int(* cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Callback for performing custom parsing of a CONF_SECTION or CONF_PAIR.
#define fr_rule_file_input(_rule)
#define cf_section_rules_push(_cs, _rule)
#define fr_rule_is_tmpl(_rule)
char const * name1
Name of the CONF_ITEM to parse.
#define fr_rule_is_attribute(_rule)
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
#define fr_rule_required(_rule)
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_IS_SET
Write whether this config item was left as the default to is_set_offset or is_set_ptr.
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
@ CONF_FLAG_XLAT
string will be dynamically expanded.
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
@ CONF_FLAG_OK_MISSING
OK if it's missing.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
Defines a CONF_PAIR to C data type mapping.
bool printed
Was this item printed already in debug mode?
CONF_ITEM item
Common set of fields.
char const * name2
Second name token. Given foo bar {} would be bar.
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.
void const * data
User data.
char const * filename
The file the config item was parsed from.
bool referenced
Was this item referenced in the config?
CONF_ITEM item
Common set of fields.
bool parsed
Was this item used during parsing?
int lineno
The line number the config item began on.
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_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
Count the number of times an attribute occurs in a parent section.
int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
Check to see if the CONF_PAIR value is present in the specified table.
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
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.
void cf_pair_mark_parsed(CONF_PAIR *cp)
Mark a pair as parsed.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
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_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
CONF_DATA const * _cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name, char const *filename, int lineno)
Add non-talloced user data to a config section.
bool cf_pair_is_parsed(CONF_PAIR *cp)
Return whether a pair has already been parsed.
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_find(_cf, _type, _name)
#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_log_debug(_cf, _fmt,...)
#define cf_data_find_next(_cf, _prev, _type, _name)
#define cf_item_debug(_cf)
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
static char const * spaces
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
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.
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
@ FR_TYPE_STRING
String of printable characters.
int fr_perm_mode_from_str(mode_t *out, char const *str)
int fr_perm_uid_from_str(TALLOC_CTX *ctx, uid_t *out, char const *name)
Resolve a user name to a GID.
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
fr_dict_attr_t const * request_attr_request
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
#define tmpl_is_attr_unresolved(vpt)
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
#define tmpl_is_attr(vpt)
@ TMPL_TYPE_REGEX_UNCOMPILED
Regex where compilation is possible but hasn't been performed yet.
@ TMPL_TYPE_MAX
Marker for the last tmpl type.
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
@ TMPL_TYPE_NULL
Has no value.
@ TMPL_TYPE_EXEC
Callout to an external script or program.
@ TMPL_TYPE_REGEX_XLAT_UNRESOLVED
A regular expression with unresolved xlat functions or attribute references.
@ TMPL_TYPE_DATA
Value in native boxed format.
@ TMPL_TYPE_REGEX
Compiled (and possibly JIT'd) regular expression.
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
@ TMPL_TYPE_REGEX_XLAT
A regex containing xlat expansions.
@ TMPL_TYPE_EXEC_UNRESOLVED
An exec with unresolved xlat function or attribute references.
@ TMPL_TYPE_UNINITIALISED
Uninitialised.
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
static char const * tmpl_attr_tail_unresolved(tmpl_t const *vpt)
Return the last attribute reference unresolved da.
int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv))
Convert tmpl_t of type TMPL_TYPE_DATA_UNRESOLVED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specifie...
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
ssize_t tmpl_cast_from_substr(tmpl_rules_t *t_rules, fr_sbuff_t *in))
Parse a cast specifier.
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Optional arguments passed to vp_tmpl functions.
static char buff[sizeof("18446744073709551615")+3]
fr_aka_sim_id_type_t type
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
uint8_t allow_unknown
Allow unknown attributes i.e.
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 char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
@ T_SOLIDUS_QUOTED_STRING
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_value_box_safe_for_t literals_safe_for)
Tokenize an xlat expansion.
void ** fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
Allocate an array of a given type.
#define fr_type_is_string(_x)
#define fr_type_is_quoted(_x)
size_t const fr_value_box_field_sizes[]
How many bytes wide each of the value data fields are.
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted[T_TOKEN_LAST]
Parse rules for non-quoted strings.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
static int fr_value_box_memcpy_out(void *out, fr_value_box_t const *vb)
Copy the value of a value box to a field in a C struct.
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.