23 RCSID(
"$Id: 63a433682c1679280aa500653bc3674f4117d2a6 $")
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/modpriv.h>
27 #include <freeradius-devel/modcall.h>
28 #include <freeradius-devel/parser.h>
29 #include <freeradius-devel/map_proc.h>
30 #include <freeradius-devel/rad_assert.h>
43 #define MOD_ACTION_RETURN (-1)
44 #define MOD_ACTION_REJECT (-2)
84 #define MOD_LOG_OPEN_BRACE RDEBUG2("%s {", c->debug_name)
86 #define MOD_LOG_CLOSE_BRACE RDEBUG2("} # %s = %s", c->debug_name, fr_int2str(mod_rcode_table, result, "<invalid>"))
171 (void) talloc_steal(g, c);
206 char const *attr, *value;
210 if (!value)
return 0;
221 else if (strspn(value,
"0123456789")==strlen(value)) {
222 action = atoi(value);
227 if (action == 0)
return 0;
237 rcode =
fr_str2int(mod_rcode_table, attr, -1);
240 "Unknown module rcode '%s'.\n",
274 #ifdef HAVE_PTHREAD_H
296 #define safe_lock(foo)
297 #define safe_unlock(foo)
303 int indent = request->log.indent;
311 RDEBUG3(
"modsingle[%s]: calling %s (%s) for request %d",
312 comp2str[component], sp->modinst->name,
313 sp->modinst->entry->name, request->number);
314 request->log.indent = 0;
316 if (sp->modinst->force) {
317 request->rcode = sp->modinst->code;
324 request->module = sp->modinst->name;
327 request->rcode = sp->modinst->entry->module->methods[component](sp->modinst->insthandle, request);
330 request->module =
"";
337 RWARN(
"Module %s became unblocked for request %u", sp->modinst->entry->name, request->number);
341 request->log.indent = indent;
342 RDEBUG3(
"modsingle[%s]: returned from %s (%s) for request %d",
343 comp2str[component], sp->modinst->name,
344 sp->modinst->entry->name, request->number);
346 return request->rcode;
368 char const *unlang_keyword[] = {
372 "load-balance group",
373 "redundant-load-balance group",
394 #define MODCALL_STACK_MAX (32)
421 ERROR(
"Internal sanity check failed: module stack is too deep");
435 depth, next, do_next_sibling)) {
459 bool if_taken, was_if;
464 was_if = if_taken =
false;
509 REDEBUG(
"Condition evaluation failed because a referenced attribute "
510 "was not found in the request");
514 REDEBUG(
"Condition evaluation failed because the value of an operand "
515 "could not be determined");
521 unlang_keyword[c->
type],
522 c->
name, condition ?
"TRUE" :
"FALSE");
547 if (!was_if)
goto elsif_error;
553 RDEBUG2(
"... skipping %s for request %d: Preceding \"if\" was taken",
572 RDEBUG2(
"... skipping %s for request %d: No preceding \"if\"",
578 RDEBUG2(
"... skipping %s for request %d: Preceding \"if\" was taken",
610 result = call_modsingle(c->
method, sp, request);
612 fr_int2str(mod_rcode_table, result,
"<invalid>"));
613 goto calculate_result;
627 for (map = g->
map; map != NULL; map = map->
next) {
633 goto calculate_result;
639 goto calculate_result;
652 goto calculate_result;
659 int i, foreach_depth = -1;
666 ERROR(
"Internal sanity check failed: module stack is too deep");
674 for (i = 0; i < 8; i++) {
681 if (foreach_depth < 0) {
682 REDEBUG(
"foreach Nesting too deep!");
684 goto calculate_result;
696 goto calculate_result;
715 RDEBUG2(
"# Foreach-Variable-%d = %s", foreach_depth, buffer);
769 goto calculate_result;
782 for (i = 8; i >= 0; i--) {
786 RDEBUG2(
"# break Foreach-Variable-%d", i);
826 goto calculate_result;
829 RDEBUG2(
"%s { ... } # empty sub-section is ignored", c->
name);
838 goto calculate_result;
854 memset(&cond, 0,
sizeof(cond));
855 memset(&map, 0,
sizeof(map));
865 null_case = found = NULL;
878 if (h->
vpt)
continue;
899 if (len < 0)
goto find_null_case;
917 if (!null_case) null_case =
this;
967 if (!found) found = null_case;
970 talloc_free(data.ptr);
971 modcall_child(request, component, depth + 1, entry, found, &result,
true);
973 goto calculate_result;
995 if ((count * (
fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
1002 depth + 1, entry, found,
1010 depth + 1, entry,
this,
1019 }
while (
this != found);
1022 goto calculate_result;
1033 char const *server = request->
server;
1036 RWDEBUG(
"Suppressing recursive call to server %s", server);
1044 request->
server = server;
1045 goto calculate_result;
1075 RDEBUG(
"(%s, %d) ? (%s, %d)",
1076 fr_int2str(mod_rcode_table, result,
"<invalid>"),
1108 priority = c->
actions[result];
1133 RDEBUG2(
"# unwind to enclosing foreach");
1142 if (do_next_sibling) {
1143 entry->
c = entry->
c->
next;
1145 if (entry->
c)
goto redo;
1166 memset(stack, 0,
sizeof(stack));
1172 stack[0].
result = default_component_results[component];
1191 static char const *action2str(
int action)
1193 static char buf[32];
1198 snprintf(buf,
sizeof buf,
"%d", action);
1211 DEBUG(
"%.*s%s {", indent,
"\t\t\t\t\t\t\t\t\t\t\t",
1216 DEBUG(
"%.*s%s {", indent,
"\t\t\t\t\t\t\t\t\t\t\t",
1217 unlang_keyword[c->
type]);
1219 dump_mc(p, indent+1);
1223 DEBUG(
"%.*s%s = %s", indent+1,
"\t\t\t\t\t\t\t\t\t\t\t",
1228 DEBUG(
"%.*s}", indent,
"\t\t\t\t\t\t\t\t\t\t\t");
1233 DEBUG(
"[%s]", comp2str[comp]);
1237 #define dump_tree(a, b)
1565 WARN(
"%s[%d]: Please change attribute reference to '&%s %s ...'",
1571 WARN(
"%s[%d]: Please change attribute reference to '... %s &%s'",
1584 cf_log_err(map->
ci,
"Left side of map must be an attribute "
1585 "or an xlat (that expands to an attribute), not a %s",
1599 cf_log_err(map->
ci,
"Right side of map must be an attribute, literal, xlat or exec");
1604 cf_log_err(map->
ci,
"Invalid operator \"%s\" in map section. "
1605 "Only assignment or filter operators are allowed",
1631 WARN(
"%s[%d]: Please change attribute reference to '&%s %s ...'",
1637 WARN(
"%s[%d]: Please change attribute reference to '... %s &%s'",
1650 WARN(
"%s[%d] Wildcard deletion MUST use '!* ANY'",
1654 TALLOC_FREE(map->
rhs);
1668 cf_log_err(map->
ci,
"Can't copy list into an attribute");
1676 cf_log_err(map->
ci,
"Invalid operator \"%s\" in update section. "
1677 "Only assignment or filter operators are allowed",
1694 cf_log_err(map->
ci,
"Can't copy value into list (we don't know which attribute to create)");
1719 WARN(
"%s[%d]: Please change ':=' to '=' for list assignment",
1737 cf_log_err(map->
ci,
"Operator \"%s\" not allowed for list assignment",
1762 (map->
rhs->
len > 2) && ((map->
rhs->
len & 0x01) == 0)) {
1786 if (map->
lhs->tmpl_da->
type != map->
rhs->tmpl_data_type) {
1790 map->
rhs->tmpl_data_type);
1794 "<INVALID>"), map->
lhs->tmpl_da->
name);
1797 map->
lhs->tmpl_da = da;
1814 char const *tmpl_str;
1817 size_t tmpl_len, quoted_len;
1828 cf_log_err_cs(cs,
"'map' sections require a 'modules' section");
1834 cf_log_err_cs(cs,
"Failed to find map processor '%s'", name2);
1844 tmpl_len = strlen(tmpl_str);
1859 switch (vpt->
type) {
1877 if (rcode < 0)
return NULL;
1887 cf_log_err_cs(cs,
"Failed instantiating map function '%s'", name2);
1893 csingle->
parent = parent;
1894 csingle->
next = NULL;
1915 quoted_str = talloc_array(csingle,
char, quoted_len);
1916 fr_snprint(quoted_str, quoted_len, tmpl_str, tmpl_len, quote);
1918 csingle->
name = talloc_asprintf(csingle,
"map %s %s", name2, quoted_str);
1920 csingle->
method = component;
1922 talloc_free(quoted_str);
1930 g->
map = talloc_steal(g, head);
1931 g->
vpt = talloc_steal(g, vpt);
1959 if (rcode < 0)
return NULL;
1968 csingle->
parent = parent;
1969 csingle->
next = NULL;
1972 csingle->
name = name2;
1977 csingle->
method = component;
1985 g->
map = talloc_steal(g, head);
1987 #ifdef WITH_CONF_WRITE
2000 bool had_seen_default =
false;
2008 cf_log_err_cs(cs,
"You must specify a variable to switch over for 'switch'");
2025 if ((slen < 0) && ((type !=
T_BARE_WORD) || (name2[0] !=
'&'))) {
2034 talloc_free(spaces);
2058 cf_log_err(ci,
"\"switch\" sections can only have \"case\" subsections");
2066 if (strcmp(name1,
"case") != 0) {
2067 cf_log_err(ci,
"\"switch\" sections can only have \"case\" subsections");
2074 if (!had_seen_default) {
2075 had_seen_default =
true;
2079 cf_log_err(ci,
"Cannot have two 'default' case statements");
2095 g->
vpt = talloc_steal(g, vpt);
2109 cf_log_err_cs(cs,
"\"case\" statements may only appear within a \"switch\" section");
2125 if ((slen < 0) && ((type !=
T_BARE_WORD) || (name2[0] !=
'&'))) {
2134 talloc_free(spaces);
2163 csingle->
name = name2;
2166 g->
vpt = talloc_steal(g, vpt);
2193 "You must specify an attribute to loop over in 'foreach'");
2210 if ((slen < 0) && ((type !=
T_BARE_WORD) || (name2[0] !=
'&'))) {
2219 talloc_free(spaces);
2232 cf_log_err_cs(cs,
"MUST use attribute or list reference in 'foreach'");
2244 GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2272 cf_log_err(ci,
"'break' can only be used in a 'foreach' section");
2277 GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2294 cf_log_err(ci,
"Server %s has no %s section",
2295 server, comp2str[component]);
2299 mr = talloc_zero(parent,
modref);
2302 csingle->
parent = parent;
2303 csingle->
next = NULL;
2306 csingle->
method = component;
2323 mx = talloc_zero(parent,
modxlat);
2326 csingle->
parent = parent;
2327 csingle->
next = NULL;
2328 csingle->
name =
"expand";
2330 csingle->
method = component;
2336 if (fmt[0] !=
'%') {
2369 if ((strcmp(name1,
"if") == 0) ||
2370 (strcmp(name1,
"else") == 0) ||
2371 (strcmp(name1,
"elsif") == 0) ||
2372 (strcmp(name1,
"update") == 0) ||
2373 (strcmp(name1,
"switch") == 0) ||
2374 (strcmp(name1,
"case") == 0)) {
2375 cf_log_err(ci,
"%s sections cannot contain a \"%s\" statement",
2386 "Entry with no value is invalid");
2408 char const *real_name,
char const *virtual_name,
char const *method_name)
2421 if (strcmp(comp2str[i], method_name) == 0)
break;
2424 if (i != MOD_COUNT) {
2428 virtual_name = real_name;
2446 *pcomponent = method;
2457 if (!cs)
return NULL;
2466 if (subcs) *pcomponent = method;
2477 snprintf(buffer,
sizeof(buffer),
"%s.%s",
2478 virtual_name, comp2str[method]);
2480 if (subcs)
return subcs;
2492 char const **modname)
2494 char const *modrefname, *p;
2500 char const *realname;
2509 if (!name2) name2 =
"";
2517 if (strcmp(modrefname,
"group") == 0) {
2523 }
else if (strcmp(modrefname,
"redundant") == 0) {
2531 GROUPTYPE_REDUNDANT,
2534 }
else if (strcmp(modrefname,
"load-balance") == 0) {
2545 }
else if (strcmp(modrefname,
"redundant-load-balance") == 0) {
2553 GROUPTYPE_REDUNDANT,
2557 }
else if (strcmp(modrefname,
"if") == 0) {
2567 if (!csingle)
return NULL;
2572 }
else if (strcmp(modrefname,
"elsif") == 0) {
2576 cf_log_err(ci,
"'elsif' cannot be used in this section");
2590 }
else if (strcmp(modrefname,
"else") == 0) {
2594 cf_log_err(ci,
"'else' cannot be used in this section section");
2599 cf_log_err(ci,
"Cannot have conditions on 'else'");
2608 }
else if (strcmp(modrefname,
"update") == 0) {
2614 }
else if (strcmp(modrefname,
"map") == 0) {
2620 }
else if (strcmp(modrefname,
"switch") == 0) {
2625 }
else if (strcmp(modrefname,
"case") == 0) {
2630 }
else if (strcmp(modrefname,
"foreach") == 0) {
2654 cf_log_err(ci,
"Entry is not a reference to a module");
2663 if (((modrefname[0] ==
'%') && (modrefname[1] ==
'{')) ||
2664 (modrefname[0] ==
'`')) {
2674 if (strcmp(modrefname,
"break") == 0) {
2676 cf_log_err(ci,
"Invalid use of 'break' as section name.");
2683 if (strcmp(modrefname,
"return") == 0) {
2685 cf_log_err(ci,
"Invalid use of 'return' as section name.");
2690 GROUPTYPE_SIMPLE, GROUPTYPE_SIMPLE,
2699 if (strncmp(modrefname,
"server[", 7) == 0) {
2707 strlcpy(buffer, modrefname + 7,
sizeof(buffer));
2708 p = strrchr(buffer,
']');
2709 if (!p || p[1] !=
'\0' || (p == buffer)) {
2710 cf_log_err(ci,
"Invalid server reference in \"%s\".", modrefname);
2714 buffer[p - buffer] =
'\0';
2718 cf_log_err(ci,
"No such server \"%s\".", buffer);
2727 modrefname, cs, buffer);
2769 p = strrchr(modrefname,
'.');
2775 strlcpy(buffer, modrefname,
sizeof(buffer));
2776 buffer[p - modrefname] =
'\0';
2790 if (loop == subcs) {
2839 if (!csingle)
return NULL;
2846 goto action_override;
2854 realname = modrefname;
2860 if (realname[0] ==
'-') realname++;
2869 if (
this)
goto allocate_csingle;
2875 if (realname != modrefname) {
2876 *modname = modrefname;
2885 cf_log_err(ci,
"Failed to find \"%s\" as a module or policy.", modrefname);
2886 cf_log_err(ci,
"Please verify that the configuration exists in %s/mods-enabled/%s.",
get_radius_dir(), modrefname);
2898 if (!this->entry->module->methods[method]) {
2899 cf_log_err(ci,
"\"%s\" modules aren't allowed in '%s' sections -- they have no such method.", this->entry->module->name,
2904 single = talloc_zero(parent,
modsingle);
2906 *modname = this->entry->module->
name;
2909 csingle->
parent = parent;
2910 csingle->
next = NULL;
2915 memcpy(csingle->
actions, authtype_actions[grouptype],
2919 csingle->
name = realname;
2921 csingle->
method = method;
2936 cf_log_err(csi,
"Subsection of module instance call not allowed");
2937 talloc_free(csingle);
2944 talloc_free(csingle);
2956 char const **modname)
2966 memset(g, 0,
sizeof(*g));
3000 int grouptype,
int parentgrouptype,
int mod_type)
3032 if ((strcmp(c->
name,
"group") == 0) ||
3033 (strcmp(c->
name,
"redundant") == 0)) {
3055 INFO(
" # Skipping contents of '%s' as it is always 'false' -- %s:%d",
3056 unlang_keyword[g->
mc.
type],
3069 if (!p->
tail)
goto elsif_fail;
3080 cf_log_err_cs(g->
cs,
"Invalid location for 'elsif'. There is no preceding 'if' statement");
3095 INFO(
" # Skipping contents of '%s' as previous '%s' is always 'true' -- %s:%d",
3096 unlang_keyword[g->
mc.
type],
3097 unlang_keyword[f->
mc.
type],
3110 if (!p->
tail)
goto else_fail;
3116 cf_log_err_cs(g->
cs,
"Invalid location for 'else'. There is no preceding 'if' statement");
3146 char const *junk = NULL;
3153 cf_log_err(ci,
"Failed to parse \"%s\" subsection.",
3164 char const *attr, *value;
3177 char const *junk = NULL;
3191 "Failed to parse \"%s\" entry.",
3218 c->
actions[i] = authtype_actions[parentgrouptype][i];
3228 if (grouptype != GROUPTYPE_REDUNDANT)
break;
3296 cf_log_err(ci,
"Failed parsing expanded string:");
3300 talloc_free(spaces);
3317 if (attr->tmpl_da->flags.virtual) {
3326 if (da && (da->
type != attr->tmpl_da->
type)) {
3334 WARN(
"%s[%d]: Please change \"%%{%s}\" to &%s",
3340 WARN(
"%s[%d]: Please change \"%%{%s}\" to &%s",
3354 vpt->tmpl_xlat = head;
3379 if (strchr(vpt->
name,
'%')) {
3384 slen = regex_compile(vpt, &preg, vpt->
name, vpt->
len,
3385 vpt->tmpl_iflag, vpt->tmpl_mflag,
true,
false);
3391 cf_log_err(ci,
"Invalid regular expression:");
3395 talloc_free(spaces);
3402 vpt->tmpl_preg = preg;
3416 cf_log_err(ci,
"Unknown attribute '%s'", vpt->tmpl_unknown_name);
3488 cf_log_err(map->
ci,
"Invalid reference to non-existent %s %s { ... }",
3558 (map->
rhs->
len > 2) && ((map->
rhs->
len & 0x01) == 0)) {
3569 }
else if ((map->
rhs->
len > 0) ||
3575 cf_log_err(map->
ci,
"Failed to parse data type %s from string: %s",
3582 vpt = talloc_steal(c, map->
lhs);
3584 talloc_free(c->
data.map);
3594 WARN(
"%s[%d]: Please change (\"%%{%s}\" %s '') to %c&%s",
3623 if (!c->
cast) da = map->
lhs->tmpl_da;
3640 (strncmp(map->
lhs->
name,
"Foreach-Variable-", 17) == 0)) {
3644 fmt = talloc_asprintf(map->
lhs,
"%%{%s}", map->
lhs->
name);
3645 slen =
tmpl_afrom_str(map, &vpt, fmt, talloc_array_length(fmt) - 1,
3656 talloc_free(spaces);
3662 talloc_free(map->
lhs);
3668 if (!pass2_regex_compile(map->
ci, map->
rhs)) {
3681 vpt = c->
data.map->lhs;
3683 if (!c->
cast) c->
cast = vpt->tmpl_da;
3706 cf_log_err(map->
ci,
"Cannot compare virtual attribute %s to another attribute",
3712 cf_log_err(map->
ci,
"Cannot compare virtual attribute %s via a regex",
3718 cf_log_err(map->
ci,
"Cannot cast virtual attribute %s",
3724 cf_log_err(map->
ci,
"Must use '==' for comparisons with virtual attribute %s",
3746 for (map = g->
map; map != NULL; map = map->
next) {
3821 for (c = mc; c != NULL; c = c->
next) {
3836 c->
debug_name = talloc_asprintf(c,
"update %s", name2);
3873 c->
debug_name = talloc_asprintf(c,
"%s %s", unlang_keyword[c->
type], name2);
3900 c->
debug_name = talloc_asprintf(c,
"%s %s", unlang_keyword[c->
type], name2);
3924 talloc_free(spaces);
3938 &g->
vpt,
true, NULL)) {
3967 if (slen < 0)
goto parse_error;
3969 talloc_free(g->
vpt);
3983 (c->
name[0] !=
'&')) {
3984 WARN(
"%s[%d]: Please change %s to &%s",
4003 c->
debug_name = talloc_asprintf(c,
"%s %s", unlang_keyword[c->
type], name2);
4016 (c->
name[0] ==
'&') &&
4021 if (slen < 0)
goto parse_error;
4029 if (!g->
vpt)
goto do_children;
4074 &g->
vpt,
true, f->
vpt->tmpl_da)) {
4079 &g->
vpt,
true, NULL)) {
4094 c->
debug_name = talloc_asprintf(c,
"%s %s", unlang_keyword[c->
type], name2);
4099 if (g->
vpt)
goto check_children;
4117 if (slen < 0)
goto parse_error;
4154 if (strcmp(name1, unlang_keyword[c->
type]) != 0) {
4160 c->
debug_name = talloc_asprintf(c,
"%s %s", name1, name2);
4185 for (
this = mc;
this != NULL;
this = this->next) {
4186 switch (this->type) {
4193 DEBUG(
"%.*s%s", depth, modcall_spaces,
4201 DEBUG(
"%.*s%s %s {", depth, modcall_spaces,
4202 unlang_keyword[this->type],
4208 DEBUG(
"%.*s%s {", depth, modcall_spaces,
4209 unlang_keyword[this->type]);
4212 for (map = g->
map; map != NULL; map = map->
next) {
4214 DEBUG(
"%.*s%s", depth + 1, modcall_spaces, buffer);
4217 DEBUG(
"%.*s}", depth, modcall_spaces);
4222 DEBUG(
"%.*s%s {", depth, modcall_spaces,
4223 unlang_keyword[this->type]);
4225 DEBUG(
"%.*s}", depth, modcall_spaces);
4232 DEBUG(
"%.*s%s (%s) {", depth, modcall_spaces,
4233 unlang_keyword[this->type], buffer);
4235 DEBUG(
"%.*s}", depth, modcall_spaces);
4242 DEBUG(
"%.*s%s %s {", depth, modcall_spaces,
4243 unlang_keyword[this->type], buffer);
4245 DEBUG(
"%.*s}", depth, modcall_spaces);
4251 DEBUG(
"%.*s%s %s {", depth, modcall_spaces,
4252 unlang_keyword[this->type], this->
name);
4254 DEBUG(
"%.*s}", depth, modcall_spaces);
4258 DEBUG(
"%.*sbreak", depth, modcall_spaces);
4264 DEBUG(
"%.*s%s {", depth, modcall_spaces,
4265 unlang_keyword[this->type]);
4267 DEBUG(
"%.*s}", depth, modcall_spaces);
4274 DEBUG(
"%.*s%s {", depth, modcall_spaces,
4275 unlang_keyword[this->type]);
4277 DEBUG(
"%.*s}", depth, modcall_spaces);
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
size_t map_snprint(char *out, size_t outlen, vp_map_t const *map)
Print a map to a string.
static modcallable * do_compile_modbreak(modcallable *parent, rlm_components_t component, CONF_ITEM const *ci)
char const * cf_pair_filename(CONF_PAIR const *pair)
int radius_exec_program(TALLOC_CTX *ctx, char *out, size_t outlen, VALUE_PAIR **output_pairs, REQUEST *request, char const *cmd, VALUE_PAIR *input_pairs, bool exec_wait, bool shell_escape, int timeout) CC_HINT(nonnull(5
int modcall_fixup_update(vp_map_t *map, UNUSED void *ctx)
Validate and fixup a map that's part of an update section.
rad_master_state_t master_state
Set by the master thread to signal the child that's currently working with the request, to do something.
VALUE_PAIR * fr_cursor_first(vp_cursor_t *cursor)
Rewind cursor to the start of the list.
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.
#define RINDENT()
Indent R* messages by one level.
int int map_to_request(REQUEST *request, vp_map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert vp_map_t to VALUE_PAIR (s) and add them to a REQUEST.
static modcallable * do_compile_modupdate(modcallable *parent, rlm_components_t component, CONF_SECTION *cs, char const *name2)
Main server configuration.
The module is OK, continue.
static void modcall_child(REQUEST *request, rlm_components_t component, int depth, modcall_stack_entry_t *entry, modcallable *c, rlm_rcode_t *result, bool do_next_sibling)
static modcallable * do_compile_modsingle(modcallable *parent, rlm_components_t component, CONF_ITEM *ci, int grouptype, char const **modname)
#define MOD_ACTION_RETURN
bool fr_condition_walk(fr_cond_t *head, bool(*callback)(void *, fr_cond_t *), void *ctx)
static CONF_SECTION * virtual_module_find_cs(rlm_components_t *pcomponent, char const *real_name, char const *virtual_name, char const *method_name)
Load a named module from "instantiate" or "policy".
static modcallable * do_compile_modcase(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
char const * cf_section_filename(CONF_SECTION const *section)
char const * name
Raw string used to create the template.
Break statement (within a MOD_FOREACH).
uint32_t fr_rand(void)
Return a 32-bit random number.
vp_tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
FR_TOKEN cf_section_name2_type(CONF_SECTION const *cs)
Redundant load balance section.
static modcallable * mod_singletocallable(modsingle *p)
static int all_children_are_modules(CONF_SECTION *cs, char const *name)
bool auto_converted
Attr-26.9.1 –> Cisco-AVPair.
static modref * mod_callabletoref(modcallable *p)
static modgroup * mod_callabletogroup(modcallable *p)
vp_tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
static bool pass2_xlat_compile(CONF_ITEM const *ci, vp_tmpl_t **pvpt, bool convert, fr_dict_attr_t const *da)
Pre-parsed XLAT expansion.
#define MODCALL_STACK_MAX
rlm_rcode_t indexed_modcall(rlm_components_t comp, int idx, REQUEST *request)
const FR_NAME_NUMBER mod_rcode_table[]
void size_t fr_pair_value_snprint(char *out, size_t outlen, VALUE_PAIR const *vp, char quote)
Print the value of an attribute to a string.
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Error resolving rcode (should not be returned by modules).
const FR_NAME_NUMBER fr_tokens_table[]
void * request_data_reference(REQUEST *request, void *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
void void void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt,...) CC_HINT(format(printf
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
fr_dict_attr_t const * cast
xlat_exp_t * xlat_from_tmpl_attr(TALLOC_CTX *ctx, vp_tmpl_t *vpt)
Try to convert attr tmpl to an xlat for &attr[*] and artificially constructing expansions.
The module considers the request invalid.
mod_type_t
Types of modcallable_t nodes.
unsigned int number
Monotonically increasing request number. Reset on server restart.
static modcallable * mod_reftocallable(modref *p)
CONF_SECTION * cf_item_to_section(CONF_ITEM const *item)
Cast a CONF_ITEM to a CONF_SECTION.
int radius_find_compare(fr_dict_attr_t const *attribute)
Find a comparison function for two attributes.
FR_TOKEN cf_section_argv_type(CONF_SECTION const *cs, int argc)
static bool pass2_map_compile(modgroup *g)
static bool pass2_callback(void *ctx, fr_cond_t *c)
vp_tmpl_t * vpt
MOD_SWITCH, MOD_MAP.
void modcall_debug(modcallable *mc, int depth)
fr_dict_enum_t * fr_dict_enum_by_name(fr_dict_t *dict, fr_dict_attr_t const *da, char const *val)
static char const *const comp2str[]
static char const modcall_spaces[]
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
char const * cf_pair_value(CONF_PAIR const *pair)
struct vp_map * next
The next valuepair map.
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.
size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
Find the length of the buffer required to fully escape a string with fr_prints.
static rlm_rcode_t CC_HINT(nonnull)
const bool fr_equality_op[]
modcallable * compile_modsingle(TALLOC_CTX *ctx, modcallable **parent, rlm_components_t component, CONF_ITEM *ci, char const **modname)
static int default_component_results[MOD_COUNT]
int cf_section_lineno(CONF_SECTION const *section)
Attribute not found in the global dictionary.
int map_afrom_cs(vp_map_t **out, CONF_SECTION *cs, pair_lists_t dst_list_def, pair_lists_t src_list_def, map_validate_t validate, void *ctx, unsigned int max) CC_HINT(nonnull(1
rlm_rcode_t map_proc(REQUEST *request, map_proc_inst_t const *inst)
Evaluate a set of maps using the specified map processor.
Reject the request (user is locked out).
Pre-parsed regular expression.
vp_tmpl_t * xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_t *xlat)
Try to convert an xlat to a tmpl for efficiency.
#define MOD_ACTION_REJECT
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
static bool pass2_fixup_undefined(CONF_ITEM const *ci, vp_tmpl_t *vpt)
#define pthread_mutex_unlock(_x)
char const * cf_pair_attr(CONF_PAIR const *pair)
int tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
Returns the first VP matching a vp_tmpl_t.
static int comp(void const *a, void const *b)
static modcallable * mod_grouptocallable(modgroup *p)
static modcallable * mod_xlattocallable(modxlat *p)
bool cf_item_is_section(CONF_ITEM const *item)
const bool fr_assignment_op[]
const FR_NAME_NUMBER dict_attr_types[]
Map data types to names representing those types.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *item)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_item_parent(CONF_ITEM const *ci)
modcallable * tail
of the children list.
#define MOD_LOG_CLOSE_BRACE
map_proc_t * map_proc_find(char const *name)
Find a map processor by name.
Immediately reject the request.
Attributes in incoming or internally proxied request.
void * request_data_get(REQUEST *request, void *unique_ptr, int unique_int)
Get opaque data from a request.
struct modcallable * next
static modcallable * do_compile_modmap(modcallable *parent, rlm_components_t component, CONF_SECTION *cs, char const *name2, int grouptype)
static modsingle * mod_callabletosingle(modcallable *p)
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
void void int radius_get_vp(VALUE_PAIR **out, REQUEST *request, char const *name)
Return a VP from the specified request.
module_instance_t * module_instantiate_method(CONF_SECTION *modules, char const *askedname, rlm_components_t *method)
modcallable * compile_modgroup(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
static modcallable * do_compile_modxlat(modcallable *parent, rlm_components_t component, char const *fmt)
int radius_evaluate_map(REQUEST *request, int modreturn, int depth, fr_cond_t const *c)
Stores an attribute, a value and various bits of other data.
map_proc_inst_t * proc_inst
Instantiation data for MOD_MAP.
ssize_t tmpl_aexpand(TALLOC_CTX *ctx, char **out, REQUEST *request, vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx)
Expand a template to a string, allocing a new buffer to hold the string.
void void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
0 methods index for authenticate section.
#define MOD_LOG_OPEN_BRACE
bool cf_item_is_pair(CONF_ITEM const *item)
int cf_pair_lineno(CONF_PAIR const *pair)
#define REXDENT()
Exdent (unindent) R* messages by one level.
Configuration AVP similar to a VALUE_PAIR.
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
tmpl_type_t type
What type of value tmpl refers to.
char const * fr_strerror(void)
Get the last library error.
int strcasecmp(char *s1, char *s2)
Map processor registration.
size_t len
Length of the raw string used to create the template.
CONF_SECTION * cf_section_sub_find(CONF_SECTION const *, char const *name)
Find a sub-section in a section.
int tmpl_copy_vps(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
Copy pairs matching a vp_tmpl_t in the current REQUEST.
static bool pass2_update_compile(modgroup *g)
char const * cf_section_name1(CONF_SECTION const *cs)
vp_tmpl_t * tmpl_init(vp_tmpl_t *vpt, tmpl_type_t type, char const *name, ssize_t len, FR_TOKEN quote)
Initialise stack allocated vp_tmpl_t.
10 how many components there are.
fr_dict_attr_t const * fr_dict_attr_by_type(fr_dict_t *dict, unsigned int vendor, unsigned int attr, PW_TYPE type)
Lookup a attribute by its its vendor and attribute numbers and data type.
int actions[RLM_MODULE_NUMCODES]
Module succeeded without doing anything.
Callout to an external script or program.
char const * cf_section_argv(CONF_SECTION const *cs, int argc)
char const * unlang_keyword[]
static bool modcall_recurse(REQUEST *request, rlm_components_t component, int depth, modcall_stack_entry_t *entry, bool do_next_sibling)
void bool map_cast_from_hex(vp_map_t *map, FR_TOKEN rhs_type, char const *rhs)
re-parse a map where the lhs is an unknown attribute.
static modcallable * do_compile_modgroup(modcallable *, rlm_components_t, CONF_SECTION *, int, int, int)
Module failed, don't reply.
void cf_log_err(CONF_ITEM const *ci, char const *fmt,...) CC_HINT(format(printf
CONF_SECTION * config
Root of the server config.
FR_TOKEN op
The operator that controls insertion of the dst attribute.
size_t fr_cond_snprint(char *buffer, size_t bufsize, fr_cond_t const *c)
log_lvl_t rad_debug_lvl
Global debugging level.
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
enum rlm_components rlm_components_t
The different section components of the server.
fr_cond_pass2_t pass2_fixup
map_proc_inst_t * map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc, vp_tmpl_t const *src, vp_map_t const *maps)
Create a new map proc instance.
size_t tmpl_snprint(char *buffer, size_t bufsize, vp_tmpl_t const *vpt, fr_dict_attr_t const *values)
Print a vp_tmpl_t to a string.
fr_cond_t * cond
MOD_IF, MOD_ELSIF.
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.
vp_map_t * map
MOD_UPDATE, MOD_MAP.
RADIUS_PACKET * packet
Incoming request.
void add_to_modcallable(modcallable *parent, modcallable *this)
ssize_t ssize_t ssize_t ssize_t ssize_t xlat_tokenize(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head, char const **error)
int request_data_add(REQUEST *request, void *unique_ptr, int unique_int, void *opaque, bool free_on_replace, bool free_on_parent, bool persist)
Add opaque data to a REQUEST.
struct modcall_stack_entry_t modcall_stack_entry_t
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
CONF_ITEM * cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item)
Return the next item after a CONF_ITEM.
int map_to_vp(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx) CC_HINT(nonnull(2
bool modcall_pass2(modcallable *mc)
enum modgroup::@13 grouptype
After mc.
static modcallable * do_compile_modswitch(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
Case section (within a MOD_SWITCH).
Mapping section (like MOD_UPDATE, but uses values from a map_proc_t call).
#define pthread_mutex_lock(_x)
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
module_instance_t * modinst
static int compile_action(modcallable *c, CONF_PAIR *cp)
int radius_evaluate_cond(REQUEST *request, int modreturn, int depth, fr_cond_t const *c)
Evaluate a fr_cond_t;.
static modcallable * do_compile_modforeach(modcallable *parent, rlm_components_t component, CONF_SECTION *cs)
void * cf_data_find(CONF_SECTION const *, char const *)
static modcallable * do_compile_modserver(modcallable *parent, rlm_components_t component, CONF_ITEM *ci, char const *name, CONF_SECTION *cs, char const *server)
How many valid return codes there are.
String of printable characters.
static const int authtype_actions[GROUPTYPE_COUNT][RLM_MODULE_NUMCODES]
CONF_SECTION * cf_section_sub_find_name2(CONF_SECTION const *, char const *name1, char const *name2)
Find a CONF_SECTION with both names.
char const * get_radius_dir(void)
Get the global radius config directory.
int modcall(rlm_components_t component, modcallable *c, REQUEST *request)
Call a module, iteratively, with a local stack, rather than recursively.
static int modcall_fixup_map(vp_map_t *map, UNUSED void *ctx)
Validate and fixup a map that's part of an map section.
static void add_child(modgroup *g, modcallable *c)
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
int tmpl_cast_in_place(vp_tmpl_t *vpt, PW_TYPE type, fr_dict_attr_t const *enumv)
Convert vp_tmpl_t of type TMPL_TYPE_UNPARSED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specified...
The module handled the request, so stop.
A source or sink of value data.
const FR_NAME_NUMBER tmpl_names[]
Map tmpl_type_t values to descriptive strings.
vp_tmpl_t * tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, char const *name, ssize_t len, FR_TOKEN quote)
Create a new heap allocated vp_tmpl_t.
CONF_ITEM * ci
Config item that the map was created from.
char const * cf_section_name2(CONF_SECTION const *cs)
static modxlat * mod_callabletoxlat(modcallable *p)
static const int defaultactions[MOD_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES]
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_t *dict, char const *attr)
Locate a fr_dict_attr_t by its name.