28RCSID(
"$Id: 9755e088c02f2b93e2725ba01911d796054ee161 $")
34#include <freeradius-devel/server/base.h>
35#include <freeradius-devel/server/tmpl_dcursor.h>
36#include <freeradius-devel/unlang/interpret.h>
37#include <freeradius-devel/unlang/xlat_priv.h>
38#include <freeradius-devel/unlang/xlat_func.h>
39#include <freeradius-devel/unlang/xlat.h>
40#include <freeradius-devel/unlang/xlat_ctx.h>
42#include <freeradius-devel/io/test_point.h>
44#include <freeradius-devel/util/base64.h>
45#include <freeradius-devel/util/base16.h>
46#include <freeradius-devel/util/dlist.h>
47#include <freeradius-devel/util/md5.h>
48#include <freeradius-devel/util/misc.h>
49#include <freeradius-devel/util/print.h>
50#include <freeradius-devel/util/rand.h>
51#include <freeradius-devel/util/regex.h>
52#include <freeradius-devel/util/sbuff.h>
53#include <freeradius-devel/util/sha1.h>
54#include <freeradius-devel/util/value.h>
56#ifdef HAVE_OPENSSL_EVP_H
57# include <freeradius-devel/tls/openssl_user_macros.h>
58# include <openssl/evp.h>
64static char const hextab[] =
"0123456789abcdef";
97 vb->vb_int8 = request->log.lvl;
103 if (!lvl_vb)
goto done;
105 level = lvl_vb->vb_int8;
110 request->log.lvl = level;
129 switch (
vp->vp_type) {
172 switch (
vp->vp_type) {
208 if ((pad = (11 -
type->name.len)) < 0) pad = 0;
211 RDEBUG4(
"as %s%*s: %pV",
type->name.str, pad,
" ", dst);
243 fr_value_box_list_remove(
args, vb);
282 fmt = attr->vb_strvalue;
287 .dict_def = request->dict,
289 .allow_wildcard =
true,
314#pragma clang diagnostic ignored "-Wgnu-designator"
324 [ 0x00 ... 0x2d ] =
true,
326 [ 0x3A ... 0x3f ] =
true,
327 [ 0x5b ... 0x5e ] =
true,
329 [ 0x7b ... 0xff ] =
true,
340 [ 0x00 ... 0x2f ] =
true,
341 [ 0x3A ... 0x3f ] =
true,
342 [ 0x5b ... 0x5e ] =
true,
344 [ 0x7b ... 0xff ] =
true,
387 if (vb->vb_length == 0)
goto done;
389 if (vb->vb_strvalue[0] ==
'.') {
444 char const *filename;
467 char const *filename;
477 dst->vb_bool = (stat(filename, &buf) == 0);
488 char const *filename;
497 fd = open(filename, O_RDONLY);
514 if ((*p ==
'\r') || (*p ==
'\n')) {
518 if ((*p <
' ') && (*p !=
'\t')) {
520 REDEBUG(
"Invalid text in file %s", filename);
526 if ((p -
buffer) > len)
goto invalid;
546 char const *filename;
553 if (stat(filename, &buf) < 0) {
561 dst->vb_uint64 = buf.st_size;
572 char const *filename;
578 char *p, *end, *found,
buffer[256];
584 fd = open(filename, O_RDONLY);
590 offset = lseek(fd, 0, SEEK_END);
602 if (lseek(fd, offset, SEEK_SET) < 0) {
603 REDEBUG3(
"Failed seeking backwards from end of file %s - %s", filename,
fr_syserror(errno));
630 fr_assert(fr_value_box_list_num_elements(&num->vb_group) == 1);
632 num = fr_value_box_list_head(&num->vb_group);
635 if (!num->vb_uint32) {
637 }
else if (num->vb_uint32 < 15) {
638 stop = num->vb_uint64 + 1;
657 if (r ==
stop)
break;
661 }
else if (*p ==
'\n') {
664 if (
n ==
stop)
break;
678 if (!end) end =
buffer + len;
688 count = (end - found);
710 char const *filename;
719 dst->vb_bool = (unlink(filename) == 0);
735 while ((vb = fr_value_box_list_pop_head(
in)) != NULL) {
748 while ((vb = fr_value_box_list_pop_head(
in)) != NULL) {
753 while ((child = fr_value_box_list_pop_head(&vb->vb_group)) != NULL) {
754 child->tainted =
true;
790 fr_value_box_list_t *list;
801 if (delim_vb->vb_length == 0) {
802 REDEBUG(
"Delimiter must be greater than zero characters");
806 delim = delim_vb->vb_strvalue;
807 delim_len = delim_vb->vb_length;
809 while((
string = fr_value_box_list_pop_head(list))) {
821 fr_sbuff_set_to_start(&sbuff);
822 fr_sbuff_marker(&m_start, &sbuff);
841 fr_sbuff_set_to_end(&sbuff);
881 fmt = attr->vb_strvalue;
886 .dict_def = request->dict,
888 .allow_wildcard =
true,
939 fr_value_box_list_remove(
args, in_vb);
941 switch (in_vb->type) {
944 RPEDEBUG(
"Failed converting %pV (%s) to an integer", in_vb,
976 for (p = in_vb->vb_strvalue; *p !=
'\0'; p++) {
977 if (*p ==
'-')
break;
988 if (in_vb->vb_length >
sizeof(uint64_t)) {
989 fr_strerror_printf(
"Expected octets length <= %zu, got %zu",
sizeof(uint64_t), in_vb->vb_length);
993 if (in_vb->vb_length >
sizeof(
uint32_t)) {
995 }
else if (in_vb->vb_length >
sizeof(
uint16_t)) {
997 }
else if (in_vb->vb_length >
sizeof(
uint8_t)) {
1024 memcpy(&ipv6int, &in_vb->vb_ip.addr.v6.s6_addr,
sizeof(ipv6int));
1065 RINFO(
"%s", vb->vb_strvalue);
1090 RDEBUG(
"%s", vb->vb_strvalue);
1115 REDEBUG(
"%s", vb->vb_strvalue);
1140 RWDEBUG(
"%s", vb->vb_strvalue);
1177 if (!dst || !*dst->vb_strvalue) {
1185 if (lvl) level = lvl->vb_uint32;
1195 MEM(dbg = talloc_memdup(request, log,
sizeof(*log)));
1202 dbg->
file = talloc_strdup(dbg,
file->vb_strvalue);
1203 dbg->
fd = open(dbg->
file, O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
1259 if (
map_afrom_attr_str(request, &map, fmt_vb->vb_strvalue, &attr_rules, &attr_rules) < 0) {
1260 RPEDEBUG(
"Failed parsing \"%s\" as map", fmt_vb->vb_strvalue);
1268 switch (map->
lhs->type) {
1274 REDEBUG(
"Unexpected type %s in left hand side of expression",
1279 switch (map->
rhs->type) {
1289 REDEBUG(
"Unexpected type %s in right hand side of expression",
1330 struct tm *local, local_buff;
1342 p = in_head->vb_strvalue;
1344 num = strtoul(p, &q, 10);
1345 if (!q || *q ==
'\0') {
1346 REDEBUG(
"nexttime: <int> must be followed by period specifier (h|d|w|m|y)");
1361 local->tm_hour += num;
1366 local->tm_mday += num;
1371 local->tm_mday += (7 - local->tm_wday) + (7 * (num-1));
1377 local->tm_mon += num;
1384 local->tm_year += num;
1388 REDEBUG(
"nexttime: Invalid period specifier '%c', must be h|d|w|m|y", *p);
1393 fr_value_box_uint64(vb, NULL, (uint64_t)(mktime(local) - now),
false);
1426 inst->namespace = xctx->
ex->call.dict;
1478 &(fr_sbuff_parse_rules_t){
1479 .escapes = &escape_rules
1483 .dict_def = inst->namespace,
1484 .list_def = request_attr_request,
1485 .allow_unknown = false,
1486 .allow_unresolved = false,
1487 .allow_foreign = false,
1490 .runtime_el = unlang_interpret_event_list(request),
1494 RPEDEBUG(
"Failed parsing expansion");
1505 if (rctx->ex->flags.needs_resolving &&
1507 RPEDEBUG(
"Unresolved expansion functions in expansion");
1548 fr_value_box_list_t *list;
1552 char const *fill_str = NULL;
1553 size_t fill_len = 0;
1560 list = &values->vb_group;
1562 pad_len = (
size_t)pad->vb_uint64;
1568 fill_str =
fill->vb_strvalue;
1569 fill_len = talloc_array_length(fill_str) - 1;
1572 if (fill_len == 0) {
1577 while ((
in = fr_value_box_list_pop_head(list))) {
1578 size_t len = talloc_array_length(
in->vb_strvalue) - 1;
1586 if (len >= pad_len)
continue;
1589 RPEDEBUG(
"Failed reallocing input data");
1594 fr_sbuff_marker(&m_data, &sbuff);
1605 if (fill_len == 1) {
1614 size_t to_copy = remaining >= fill_len ? fill_len : remaining;
1618 fr_sbuff_set_to_end(&sbuff);
1619 fr_sbuff_terminate(&sbuff);
1643 fr_value_box_list_t *list;
1648 char const *fill_str = NULL;
1649 size_t fill_len = 0;
1655 list = &values->vb_group;
1656 pad_len = (
size_t)pad->vb_uint64;
1662 fill_str =
fill->vb_strvalue;
1663 fill_len = talloc_array_length(fill_str) - 1;
1666 if (fill_len == 0) {
1671 while ((
in = fr_value_box_list_pop_head(list))) {
1672 size_t len = talloc_array_length(
in->vb_strvalue) - 1;
1679 if (len >= pad_len)
continue;
1683 RPEDEBUG(
"Failed reallocing input data");
1690 if (fill_len == 1) {
1699 if (
fr_sbuff_in_bstrncpy(&sbuff, fill_str, remaining >= fill_len ? fill_len : remaining) < 0) {
1745 RPEDEBUG(
"Base64 encoding failed");
1750 vb->tainted =
in->tainted;
1788 if (
in->vb_length == 0) {
1789 fr_value_box_list_remove(
args,
in);
1809 vb->tainted =
in->tainted;
1837 char const *p, *end;
1845 while ((hex = fr_value_box_list_pop_head(&list->vb_group))) {
1846 len = hex->vb_length;
1847 if ((len > 1) && (len & 0x01)) {
1848 REDEBUG(
"Input data length must be >1 and even, got %zu", len);
1852 p = hex->vb_strvalue;
1858 if ((p[0] ==
'0') && (p[1] ==
'x')) {
1866 if (p == end)
continue;
1919 RPEDEBUG(
"Failed parsing '%pV' as a numerical data type",
name);
1927 RPEDEBUG(
"Failed parsing '%pV' as a string data type",
name);
1935 RDEBUG(
"Unknown data type '%s'",
name->vb_strvalue);
1943 (void) fr_value_box_list_pop_head(
args);
1977 RPEDEBUG(
"Failed concatenating string");
1992 while ((arg = fr_value_box_list_next(
args, arg)) != NULL) {
1997 vb = fr_value_box_list_head(&arg->vb_group);
1999 p = fr_value_box_list_remove(&arg->vb_group, vb);
2006 vb = fr_value_box_list_next(&arg->vb_group, p);
2041 fr_value_box_list_t *to_concat;
2047 sep = (separator) ? separator->vb_strvalue :
"";
2048 to_concat = &list->vb_group;
2053 RPEDEBUG(
"Failed concatenating input");
2058 if (!
buff)
goto error;
2092 while ((bin = fr_value_box_list_pop_head(&list->vb_group))) {
2096 MEM(new_buff = talloc_zero_array(bin,
char, (bin->vb_length * 2) + 1));
2097 if (bin->vb_length) {
2202 fr_value_box_list_remove(&arg->vb_group, vb);
2213 while ((vb = fr_value_box_list_pop_head(
in)) != NULL) {
2231 while ((arg = fr_value_box_list_next(
in, arg)) != NULL) {
2300 fr_md4_calc(digest, in_head->vb_octets, in_head->vb_length);
2340 fr_md5_calc(digest, in_head->vb_octets, in_head->vb_length);
2392 .dict_def = request->dict,
2393 .list_def = request_attr_request,
2394 .allow_wildcard = true,
2395 .prefix = TMPL_ATTR_REF_PREFIX_AUTO
2448 result = in_head->vb_uint32;
2451 if (result > (1 << 30)) result = (1 << 30);
2457 vb->vb_uint64 = result;
2502 static char randstr_punc[] =
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
2503 static char randstr_salt[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz/.";
2509 static char randstr_otp[] =
"469ACGHJKLMNPQRUVWXYabdfhijkprstuvwxyz";
2511 char const *p, *start, *end;
2514 unsigned int result;
2525#define REPETITION_MAX 1024
2527 start = p = in_head->vb_strvalue;
2528 end = p + in_head->vb_length;
2541 reps = strtol(p, &endptr, 10);
2561 reps = strtol(p, &endptr, 10);
2572 for (i = 0; i < reps; i++) {
2579 *buff_p++ =
'a' + (result % 26);
2586 *buff_p++ =
'A' + (result % 26);
2593 *buff_p++ =
'0' + (result % 10);
2600 *buff_p++ = randstr_salt[result % (
sizeof(randstr_salt) - 3)];
2607 *buff_p++ = randstr_punc[result % (
sizeof(randstr_punc) - 1)];
2614 *buff_p++ =
'!' + (result % 95);
2621 *buff_p++ = randstr_salt[result % (
sizeof(randstr_salt) - 1)];
2629 *buff_p++ = randstr_otp[result % (
sizeof(randstr_otp) - 1)];
2637 size_t copy = (reps - i) >
sizeof(result) ?
sizeof(result) : reps - i;
2639 memcpy(buff_p, (
uint8_t *)&result, copy);
2646 REDEBUG(
"Invalid character class '%c'", *p);
2664#if defined(HAVE_REGEX_PCRE) || defined(HAVE_REGEX_PCRE2)
2686 fr_value_box_t *arg = fr_value_box_list_head(&in_head->vb_group);
2696 if (regex_request_to_sub(vb, &p, request, 0) < 0) {
2697 REDEBUG2(
"No previous regex capture");
2709 switch (arg->type) {
2720 if (fr_value_box_list_next(
in, in_head)) {
2721 REDEBUG(
"Only one subcapture argument allowed");
2731 if (regex_request_to_sub(vb, &p, request, idx.vb_uint32) < 0) {
2732 REDEBUG2(
"No previous numbered regex capture group");
2755 RPEDEBUG(
"Failed concatenating input");
2760 if (regex_request_to_sub_named(vb, &p, request, arg->vb_strvalue) < 0) {
2761 REDEBUG2(
"No previous named regex capture group");
2803 fr_sha1_update(&sha1_ctx, in_head->vb_octets, in_head->vb_length);
2827#ifdef HAVE_OPENSSL_EVP_H
2832 uint8_t digest[EVP_MAX_MD_SIZE];
2833 unsigned int digestlen;
2840 md_ctx = EVP_MD_CTX_create();
2841 EVP_DigestInit_ex(md_ctx, md, NULL);
2843 EVP_DigestUpdate(md_ctx, in_head->vb_octets, in_head->vb_length);
2845 EVP_DigestUpdate(md_ctx, NULL, 0);
2847 EVP_DigestFinal_ex(md_ctx, digest, &digestlen);
2848 EVP_MD_CTX_destroy(md_ctx);
2858# define EVP_MD_XLAT(_md, _md_func) \
2859static xlat_action_t xlat_func_##_md(TALLOC_CTX *ctx, fr_dcursor_t *out,\
2860 xlat_ctx_t const *xctx, \
2861 request_t *request,\
2862 fr_value_box_list_t *in)\
2864 return xlat_evp_md(ctx, out, xctx, request, in, EVP_##_md_func());\
2867EVP_MD_XLAT(sha2_224, sha224)
2868EVP_MD_XLAT(sha2_256, sha256)
2869EVP_MD_XLAT(sha2_384, sha384)
2870EVP_MD_XLAT(sha2_512, sha512)
2875#ifdef HAVE_EVP_BLAKE2S256
2876EVP_MD_XLAT(blake2s_256, blake2s256)
2879#ifdef HAVE_EVP_BLAKE2B512
2880EVP_MD_XLAT(blake2b_512, blake2b512)
2883EVP_MD_XLAT(sha3_224, sha3_224)
2884EVP_MD_XLAT(sha3_256, sha3_256)
2885EVP_MD_XLAT(sha3_384, sha3_384)
2886EVP_MD_XLAT(sha3_512, sha3_512)
2947 vb->vb_size = strlen(in_head->vb_strvalue);
2984 bool relaxed =
false;
2988 if (relaxed_vb) relaxed = relaxed_vb->vb_bool;
2990 p = (
uint8_t const *)str->vb_strvalue;
2991 end = p + str->vb_length;
2995 vb->vb_bool =
false;
3043 in_head->vb_length) >= 0);
3052 { .single =
true, .required =
true, .type =
FR_TYPE_INT32 },
3075 int32_t start, end, len;
3086 RPEDEBUG(
"Failed casting value to string");
3094 if (start_vb->vb_int32 < 0) {
3095 start =
in->vb_length + start_vb->vb_int32;
3096 if (start < 0) start = 0;
3098 start = start_vb->vb_int32;
3102 if (len_vb->vb_int32 < 0) {
3103 end =
in->vb_length + len_vb->vb_int32;
3106 end = start + len_vb->vb_int32;
3107 if (end > (int32_t)
in->vb_length) end =
in->vb_length;
3110 end =
in->vb_length;
3126 memcpy(buf, &
in->vb_octets[start], len);
3137#ifdef HAVE_REGEX_PCRE2
3142 fr_regex_flags_t flags;
3143} xlat_subst_regex_inst_t;
3149 xlat_subst_regex_inst_t *
inst = talloc_get_type_abort(xctx->
inst, xlat_subst_regex_inst_t);
3167 sbuff =
FR_SBUFF_IN(patt_exp->data.vb_strvalue, patt_exp->data.vb_length);
3176 fr_sbuff_marker(&start_m, &sbuff);
3180 fr_sbuff_marker(&end_m, &sbuff);
3181 fr_sbuff_next(&sbuff);
3184 slen = regex_flags_parse(NULL, &
inst->flags,
3188 PERROR(
"Failed parsing regex flags in \"%s\"", patt_exp->data.vb_strvalue);
3193 if (regex_compile(
inst, &
inst->pattern,
3195 &
inst->flags,
true,
false) <= 0) {
3196 PERROR(
"Failed compiling regex \"%s\"", patt_exp->data.vb_strvalue);
3226 fr_value_box_list_t *
args)
3233 regex_t *pattern, *our_pattern = NULL;
3234 fr_regex_flags_t
const *flags;
3235 fr_regex_flags_t our_flags = {};
3246 if (!
inst->pattern) {
3247 sbuff =
FR_SBUFF_IN(regex_vb->vb_strvalue, regex_vb->vb_length);
3249 REDEBUG(
"Regex must not be empty");
3253 fr_sbuff_next(&sbuff);
3254 fr_sbuff_marker(&start_m, &sbuff);
3258 fr_sbuff_marker(&end_m, &sbuff);
3259 fr_sbuff_next(&sbuff);
3261 slen = regex_flags_parse(NULL, &our_flags, &sbuff, NULL,
true);
3263 RPEDEBUG(
"Failed parsing regex flags");
3270 if (regex_compile(NULL, &our_pattern,
3272 &our_flags,
true,
true) <= 0) {
3273 RPEDEBUG(
"Failed compiling regex");
3276 pattern = our_pattern;
3279 pattern =
inst->pattern;
3280 flags = &
inst->flags;
3284 if (regex_substitute(vb, &
buff, 0, pattern, flags,
3285 subject_vb->vb_strvalue, subject_vb->vb_length,
3286 rep_vb->vb_strvalue, rep_vb->vb_length, NULL) < 0) {
3287 RPEDEBUG(
"Failed performing substitution");
3326#ifdef HAVE_REGEX_PCRE2
3333 char const *p, *q, *end;
3336 char const *pattern, *rep;
3337 size_t pattern_len, rep_len;
3346 pattern = pattern_vb->vb_strvalue;
3347 if (*pattern ==
'/') {
3348#ifdef HAVE_REGEX_PCRE2
3349 switch (xlat_func_subst_regex(ctx,
out, xctx, request,
args)) {
3361 if (memchr(pattern,
'/', pattern_vb->vb_length - 1)) {
3362 REDEBUG(
"regex based substitutions require libpcre2. "
3363 "Check ${features.regex-pcre2} to determine support");
3372 pattern_len = pattern_vb->vb_length;
3373 if (pattern_len == 0) {
3378 rep = rep_vb->vb_strvalue;
3379 rep_len = rep_vb->vb_length;
3381 p = subject_vb->vb_strvalue;
3382 end = p + subject_vb->vb_length;
3388 q = memmem(p, end - p, pattern, pattern_len);
3396 p = q + pattern_len;
3400 RPEDEBUG(
"Failed creating output box");
3444 if (!arg || (strcmp(arg->vb_strvalue,
"now") == 0)) {
3447 }
else if (strcmp(arg->vb_strvalue,
"request") == 0) {
3450 }
else if (strcmp(arg->vb_strvalue,
"offset") == 0) {
3455 }
else if (strcmp(arg->vb_strvalue,
"dst") == 0) {
3460 }
else if (strcmp(arg->vb_strvalue,
"mday_offset") == 0) {
3468 nsec = (int64_t) 86400 * (tm.tm_mday - 1);
3469 nsec += when % 86400;
3477 }
else if (strcmp(arg->vb_strvalue,
"wday_offset") == 0) {
3485 nsec = (int64_t) 86400 * tm.tm_wday;
3486 nsec += when % 86400;
3498 REDEBUG(
"Invalid time specification '%s'", arg->vb_strvalue);
3503 vb->vb_date =
value;
3525 p =
UNCONST(
char *, vb->vb_strvalue);
3526 end = p + vb->vb_length;
3529 *(p) = upper ? toupper ((
int) *(p)) : tolower((
uint8_t) *(p));
3533 fr_value_box_list_remove(
args, vb);
3601 char const *p, *end;
3609 p = in_head->vb_strvalue;
3610 end = p + in_head->vb_length;
3633 p = in_head->vb_strvalue;
3685 char const *p, *end;
3694 p = in_head->vb_strvalue;
3695 end = p + in_head->vb_length;
3714 p = in_head->vb_strvalue;
3726 REMARKER(in_head->vb_strvalue, p - in_head->vb_strvalue,
"Non-hex char in %% sequence");
3763 void *decode_ctx = NULL;
3767 if (tp_decode->
test_ctx(&decode_ctx, ctx, request->dict) < 0) {
3773 request, decode_ctx, tp_decode->
func,
in);
3776 RPERROR(
"Protocol decoding failed");
3785 vb->vb_uint32 = decoded;
3813 vb->vb_ip.addr.v4.s_addr = htonl((
uint32_t)0xffffffff << (32 - subnet->vb_ip.prefix));
3835 vb->vb_ip.addr.v4.s_addr = htonl( ntohl(subnet->vb_ip.addr.v4.s_addr) | (
uint32_t)0xffffffff >> subnet->vb_ip.prefix);
3843 *(
void **) mctx->
inst = mctx->
uctx;
3871 bool tainted =
false;
3875 uint8_t *p = binbuf, *end = p +
sizeof(binbuf);
3883 memcpy(&tp_encode, xctx->
inst,
sizeof(tp_encode));
3888 .dict_def = request->dict,
3889 .list_def = request_attr_request,
3890 .allow_wildcard = true,
3891 .prefix = TMPL_ATTR_REF_PREFIX_AUTO
3894 RPEDEBUG(
"Failed parsing attribute reference");
3901 if (tp_encode->test_ctx) {
3902 if (tp_encode->test_ctx(&
encode_ctx,
vpt, request->dict) < 0) {
3914 if (
vp->
da->flags.internal)
continue;
3930 RPEDEBUG(
"Protocol encoding failed");
3936 tainted |=
vp->vp_tainted;
4011 for (p =
name; *p !=
'\0'; p++) {
4107#define XLAT_REGISTER_ARGS(_xlat, _func, _return_type, _args) \
4109 if (unlikely((xlat = xlat_func_register(xlat_ctx, _xlat, _func, _return_type)) == NULL)) return -1; \
4110 xlat_func_args_set(xlat, _args); \
4111 xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
4138#undef XLAT_REGISTER_ARGS
4139#define XLAT_REGISTER_ARGS(_xlat, _func, _return_type, _args) \
4141 if (unlikely((xlat = xlat_func_register(xlat_ctx, _xlat, _func, _return_type)) == NULL)) return -1; \
4142 xlat_func_args_set(xlat, _args); \
4143 xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_INTERNAL); \
4157#ifdef HAVE_REGEX_PCRE2
4176#define XLAT_REGISTER_PURE(_xlat, _func, _return_type, _arg) \
4178 if (unlikely((xlat = xlat_func_register(xlat_ctx, _xlat, _func, _return_type)) == NULL)) return -1; \
4179 xlat_func_args_set(xlat, _arg); \
4180 xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
4188#if defined(HAVE_REGEX_PCRE) || defined(HAVE_REGEX_PCRE2)
4208#ifdef HAVE_OPENSSL_EVP_H
4214# ifdef HAVE_EVP_BLAKE2S256
4217# ifdef HAVE_EVP_BLAKE2B512
static int const char char buffer[256]
static int const char * fmt
#define fr_base16_encode(_out, _in)
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define fr_base64_encode(_out, _in, _add_padding)
#define fr_base64_decode(_out, _in, _expect_padding, _no_trailing)
#define FR_BASE64_DEC_LENGTH(_inlen)
#define FR_BASE64_ENC_LENGTH(_inlen)
Encode/decode binary data using printable characters (base64 format)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dict_t * fr_dict_global_ctx_iter_next(fr_dict_global_ctx_iter_t *iter)
char const * name
Vendor name.
fr_dict_t * fr_dict_global_ctx_iter_init(fr_dict_global_ctx_iter_t *iter)
Iterate protocols by name.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
dl_t * fr_dict_dl(fr_dict_t const *dict)
uint32_t pen
Private enterprise number.
fr_dict_t const * fr_dict_internal(void)
fr_dict_vendor_t const * fr_dict_vendor_by_da(fr_dict_attr_t const *da)
Look up a vendor by one of its child attributes.
dl_loader_t * dl_loader_init(TALLOC_CTX *ctx, void *uctx, bool uctx_free, bool defer_symbol_init)
Initialise structures needed by the dynamic linker.
dl_t * dl_by_name(dl_loader_t *dl_loader, char const *name, void *uctx, bool uctx_free)
Search for a dl's shared object in various locations.
void * handle
Handle returned by dlopen.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static xlat_action_t xlat_func_next_time(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Calculate number of seconds until the next n hour(s), day(s), week(s), year(s).
static xlat_action_t xlat_func_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Dynamically evaluate an expansion string.
static xlat_action_t xlat_func_lpad(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
lpad a string
static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Convert hex string to binary.
static xlat_action_t xlat_func_subst(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Perform regex substitution.
static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
URLdecode special characters.
static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Decode base64 string.
static xlat_action_t xlat_func_hmac_md5(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Generate the HMAC-MD5 of a string or attribute.
static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Encode string or attribute as base64.
static xlat_action_t xlat_func_log_info(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Log something at INFO level.
static xlat_action_t xlat_func_log_warn(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Log something at WARN level.
static xlat_action_t xlat_func_map(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Processes fmt as a map string and applies it to the current request.
static xlat_action_t protocol_decode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Decode any protocol attribute / options.
static xlat_action_t xlat_func_debug(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Dynamically change the debugging level for the current request.
static xlat_action_t xlat_func_log_debug(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Log something at DEBUG level.
static xlat_action_t xlat_func_log_dst(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Change the log destination to the named one.
static xlat_arg_parser_t const xlat_func_string_arg[]
Calculate any digest supported by OpenSSL EVP_MD.
static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Concatenate string representation of values of given attributes using separator.
static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
URLencode special characters.
static xlat_action_t xlat_func_rpad(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Right pad a string.
static xlat_action_t xlat_func_md4(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Calculate the MD4 hash of a string or attribute.
static xlat_action_t xlat_func_explode(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Split a string into multiple new strings based on a delimiter.
static xlat_action_t xlat_func_string(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Print data as string, if possible.
static xlat_action_t xlat_func_substr(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Extract a substring from string / octets data.
static xlat_action_t xlat_func_length(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Return the on-the-wire size of the boxes in bytes.
static xlat_action_t xlat_func_immutable_attr(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Mark one or more attributes as immutable.
static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Generate a random integer value.
static xlat_action_t xlat_func_log_err(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Log something at DEBUG level.
static xlat_action_t xlat_func_hmac_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Generate the HMAC-SHA1 of a string or attribute.
static xlat_action_t xlat_func_integer(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Print data as integer, not as VALUE.
static xlat_action_t xlat_func_time(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Return the time as a FR_TYPE_DATE.
static xlat_action_t xlat_func_toupper(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Convert a string to uppercase.
static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Cast one or more output value-boxes to the given type.
static xlat_action_t xlat_func_hex(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Print data as hex, not as VALUE.
static xlat_action_t xlat_func_md5(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Calculate the MD5 hash of a string or attribute.
static xlat_action_t xlat_func_subnet_netmask(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Calculate the subnet mask from a IPv4 prefix.
static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Calculate the SHA1 hash of a string or attribute.
static xlat_action_t xlat_func_str_printable(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Return whether a string has only printable chars.
static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Generate a string of random chars.
static xlat_action_t xlat_func_tolower(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Convert a string to lowercase.
static xlat_action_t xlat_func_debug_attr(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Print out attribute info.
static xlat_action_t xlat_func_subnet_broadcast(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Calculate the broadcast address from a IPv4 prefix.
static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Encode attributes as a series of string attribute/value pairs.
static xlat_action_t xlat_func_str_utf8(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Return whether a string is valid UTF-8.
static xlat_action_t xlat_func_strlen(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Print length of given string.
static xlat_action_t protocol_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
Encode protocol attributes / options.
Stores the state of the current iteration operation.
int fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen, uint8_t const *key, size_t key_len)
Calculate HMAC using internal MD5 implementation.
int fr_hmac_sha1(uint8_t digest[static SHA1_DIGEST_LENGTH], uint8_t const *in, size_t inlen, uint8_t const *key, size_t key_len)
Calculate HMAC using internal SHA1 implementation.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
fr_log_t * log_dst_by_name(char const *name)
Get a logging destination by name.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define REDEBUG3(fmt,...)
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RMARKER(_type, _lvl, _str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RPEDEBUG(fmt,...)
#define RDEBUG_ENABLED4
True if request debug level 1-4 messages are enabled.
#define RIDEBUG2(fmt,...)
#define REDEBUG2(fmt,...)
#define RIDEBUG3(fmt,...)
#define RINDENT()
Indent R* messages by one level.
int map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, UNUSED void *uctx)
Convert a map to a fr_pair_t.
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
int map_afrom_attr_str(TALLOC_CTX *ctx, map_t **out, char const *vp_str, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
Convert a value pair string to valuepair map.
@ L_DST_NULL
Discard log messages.
@ L_DST_FILES
Log to a file on disk.
@ L_DBG_LVL_DISABLE
Don't print messages.
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ L_DBG_LVL_MAX
Lowest priority debug messages (-xxxxx | -Xxxx).
void fr_md4_calc(uint8_t out[static MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD4 hash of the contents of a buffer.
#define MD4_DIGEST_LENGTH
@ TMPL_ATTR_REF_PREFIX_AUTO
Attribute refs may have a '&' prefix.
#define MD5_DIGEST_LENGTH
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Perform a single digest operation on a single input buffer.
size_t fr_snprint_uint128(char *out, size_t outlen, uint128_t const num)
Write 128bit unsigned integer to buffer.
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
fr_slen_t fr_utf8_str(uint8_t const *str, ssize_t inlen)
Validate a complete UTF8 string.
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
static fr_internal_encode_ctx_t encode_ctx
#define RDEBUG_ENABLED2()
uint32_t fr_rand(void)
Return a 32-bit random number.
fr_dict_attr_t const * request_attr_request
void request_log_prepend(request_t *request, fr_log_t *log_dst, fr_log_lvl_t lvl)
Prepend another logging destination to the list.
#define RAD_REQUEST_LVL_NONE
No debug messages should be printed.
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
char * fr_sbuff_adv_to_str(fr_sbuff_t *sbuff, size_t len, char const *needle, size_t needle_len)
Wind position to the first instance of the specified needle.
char * fr_sbuff_adv_to_chr(fr_sbuff_t *sbuff, size_t len, char c)
Wind position to first instance of specified char.
ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len)
Copy bytes into the sbuff up to the first \0.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_current(_sbuff_or_marker)
char const * name
Name for rule set to aid we debugging.
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_init_in(_out, _start, _len_or_end)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define fr_sbuff_len(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_move(_out, _in, _len)
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_behind(_sbuff_or_marker)
#define fr_sbuff_ahead(_sbuff_or_marker)
#define fr_sbuff_in_char(_sbuff,...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Set of parsing rules for *unescape_until functions.
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
@ 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_DATA_UNRESOLVED
Unparsed literal string.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
static char const * tmpl_list_name(fr_dict_attr_t const *list, char const *def)
Return the name of a tmpl list or def if list not provided.
Optional arguments passed to vp_tmpl functions.
void fr_sha1_init(fr_sha1_ctx *context)
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
#define SHA1_DIGEST_LENGTH
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
#define fr_time()
Allow us to arbitrarily manipulate time.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_log_t * parent
Log destination this was cloned from.
fr_log_dst_t dst
Log destination.
int fd
File descriptor to write messages to.
char const * file
Path to log file.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
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.
An element in an arbitrarily ordered array of name to num mappings.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
char * talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
Append a bstr to a bstr.
#define talloc_get_type_abort_const
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_pair_decode_t func
Decoder for pairs.
Entry point for pair decoders.
Entry point for pair encoders.
bool fr_time_is_dst(void)
Whether or not we're daylight savings.
int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint)
Convert string in various formats to a fr_unix_time_t.
fr_time_delta_t fr_time_gmtoff(void)
Get the offset to gmt.
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
#define fr_time_delta_wrap(_time)
static uint64_t fr_unix_time_unwrap(fr_unix_time_t time)
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
#define tmpl_dcursor_init(_err, _ctx, _cc, _cursor, _request, _vpt)
Maintains state between cursor calls.
xlat_arg_parser_t const trigger_xlat_args[]
xlat_action_t trigger_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Retrieve attributes from a special trigger list.
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
int unlang_xlat_push(TALLOC_CTX *ctx, bool *p_success, fr_value_box_list_t *out, request_t *request, xlat_exp_head_t const *xlat, bool top_frame)
Push a pre-compiled xlat onto the stack for evaluation.
void unlang_xlat_init(void)
Register xlat operation with the interpreter.
fr_type_t type
Type to cast argument to.
bool xlat_is_literal(xlat_exp_head_t const *head)
Check to see if the expansion consists entirely of value-box elements.
bool required
Argument must be present, and non-empty.
@ XLAT_ARG_VARIADIC_EMPTY_KEEP
Empty argument groups are left alone, and either passed through as empty groups or null boxes.
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
bool concat
Concat boxes together.
bool single
Argument must only contain a single box.
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
Walk over an xlat tree recursively, resolving any unresolved functions or references.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_YIELD
An xlat function pushed a resume frame onto the stack.
@ XLAT_ACTION_PUSH_UNLANG
An xlat function pushed an unlang frame onto the unlang stack.
fr_slen_t xlat_tokenize_expression(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)
Definition for a single argument consumend by an xlat function.
static fr_slen_t fr_pair_aprint(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
static void fr_pair_set_immutable(fr_pair_t *vp)
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
#define fr_type_is_string(_x)
#define fr_type_is_numeric(_x)
#define FR_TYPE_STRUCTURAL
#define fr_type_is_null(_x)
#define fr_type_is_leaf(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_integer(_x)
size_t fr_value_box_network_length(fr_value_box_t const *value)
Get the size of the value held by the fr_value_box_t.
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Pre-allocate an octets buffer for filling by the caller.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
char * fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together.
int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
void fr_value_box_list_untaint(fr_value_box_list_t *head)
Untaint every list member (and their children)
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Alloc and assign an empty \0 terminated string to a fr_value_box_t.
ssize_t fr_value_box_list_concat_as_string(bool *tainted, bool *secret, fr_sbuff_t *sbuff, fr_value_box_list_t *list, char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules, fr_value_box_list_action_t proc_action, fr_value_box_safe_for_t safe_for, bool flatten)
Concatenate a list of value boxes together.
bool fr_value_box_list_tainted(fr_value_box_list_t const *head)
Check to see if any list members (or their children) are tainted.
int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
@ FR_VALUE_BOX_LIST_FREE_BOX
Free each processed box.
#define fr_value_box_list_foreach_safe(_list_head, _iter)
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
static bool fr_value_box_is_secret(fr_value_box_t const *box)
static void fr_value_box_set_secret(fr_value_box_t *box, bool secret)
#define fr_box_is_variable_size(_x)
#define VALUE_BOX_LIST_VERIFY(_x)
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
#define fr_value_box_list_foreach(_list_head, _iter)
static size_t char ** out
#define fr_box_bool(_val)
static xlat_arg_parser_t const xlat_func_bin_arg[]
static int xlat_protocol_register_cbor(void)
static xlat_arg_parser_t const xlat_func_map_arg[]
static xlat_arg_parser_t const xlat_func_log_dst_args[]
static xlat_arg_parser_t const protocol_decode_xlat_args[]
static xlat_arg_parser_t const xlat_func_time_args[]
static xlat_arg_parser_t const xlat_func_base64_encode_arg[]
static xlat_arg_parser_t const xlat_func_debug_attr_args[]
static int _log_dst_free(fr_log_t *log)
static xlat_action_t xlat_func_file_size(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
static xlat_action_t xlat_hmac(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_value_box_list_t *args, uint8_t *digest, int digest_len, hmac_type type)
static xlat_arg_parser_t const xlat_func_log_arg[]
static xlat_arg_parser_t const xlat_func_sha_arg[]
static xlat_arg_parser_t const xlat_func_cast_args[]
xlat_action_t xlat_transparent(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
Common function to move boxes form input list to output list.
static xlat_arg_parser_t const xlat_func_hex_arg[]
static xlat_arg_parser_t const xlat_func_pairs_args[]
static ssize_t xlat_file_escape_path(fr_sbuff_t *in, fr_value_box_t *vb)
Escape the paths as necessary.
static xlat_arg_parser_t const xlat_func_substr_args[]
static xlat_action_t xlat_func_file_exists(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
static xlat_action_t xlat_func_join(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Join a series of arguments to form a single list.
static xlat_arg_parser_t const xlat_func_subnet_args[]
#define XLAT_REGISTER_PURE(_xlat, _func, _return_type, _arg)
static xlat_arg_parser_t const xlat_func_str_printable_arg[]
static xlat_arg_parser_t const xlat_func_randstr_arg[]
static xlat_arg_parser_t const xlat_func_eval_arg[]
static xlat_arg_parser_t const xlat_func_subst_args[]
static xlat_arg_parser_t const xlat_func_explode_args[]
int xlat_protocols_register(void)
Register xlats for any loaded dictionaries.
static xlat_arg_parser_t const xlat_func_str_utf8_arg[]
void xlat_debug_attr_list(request_t *request, fr_pair_list_t const *list)
static const fr_sbuff_escape_rules_t xlat_filename_escape_dots
static dl_loader_t * cbor_loader
static xlat_arg_parser_t const xlat_change_case_arg[]
static xlat_arg_parser_t const xlat_func_strlen_arg[]
static int xlat_protocol_register(fr_dict_t const *dict)
static xlat_arg_parser_t const xlat_func_md5_arg[]
int xlat_global_init(void)
static xlat_arg_parser_t const xlat_func_urlquote_arg[]
static void ungroup(fr_dcursor_t *out, fr_value_box_list_t *in)
static xlat_arg_parser_t const xlat_func_md4_arg[]
static xlat_arg_parser_t const xlat_func_immutable_attr_args[]
static xlat_arg_parser_t const xlat_func_join_args[]
static xlat_action_t xlat_eval_resume(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
Just serves to push the result up the stack.
static xlat_action_t xlat_func_taint(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
static xlat_arg_parser_t const xlat_func_debug_args[]
static char const hextab[]
static xlat_action_t xlat_func_file_head(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
static xlat_arg_parser_t const xlat_func_pad_args[]
static xlat_arg_parser_t const protocol_encode_xlat_args[]
static int xlat_eval_instantiate(xlat_inst_ctx_t const *xctx)
static xlat_arg_parser_t const xlat_func_urlunquote_arg[]
static xlat_action_t xlat_func_file_escape(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *args)
static int xlat_protocol_register_by_name(dl_t *dl, char const *name)
void xlat_debug_attr_vp(request_t *request, fr_pair_t *vp, tmpl_t const *vpt)
static xlat_arg_parser_t const xlat_func_rand_arg[]
static xlat_action_t xlat_func_file_tail(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
static xlat_arg_parser_t const xlat_func_concat_args[]
static xlat_arg_parser_t const xlat_func_file_name_count_args[]
static xlat_arg_parser_t const xlat_func_integer_args[]
static int _xlat_global_init(UNUSED void *uctx)
Global initialisation for xlat.
#define XLAT_REGISTER_ARGS(_xlat, _func, _return_type, _args)
static xlat_action_t xlat_func_untaint(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
static xlat_arg_parser_t const xlat_func_length_args[]
static const char * xlat_file_name(fr_value_box_t *vb)
static xlat_action_t xlat_change_case(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED request_t *request, fr_value_box_list_t *args, bool upper)
Change case of a string.
static xlat_action_t xlat_func_ungroup(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
Ungroups all of its arguments into one flat list.
static int protocol_xlat_instantiate(xlat_inst_ctx_t const *mctx)
static xlat_arg_parser_t const xlat_func_file_name_args[]
static TALLOC_CTX * xlat_ctx
static xlat_arg_parser_t const xlat_func_next_time_args[]
static int _xlat_global_free(UNUSED void *uctx)
De-register all xlat functions we created.
static const fr_sbuff_escape_rules_t xlat_filename_escape
static xlat_arg_parser_t const xlat_func_base64_decode_arg[]
static xlat_arg_parser_t const xlat_hmac_args[]
static xlat_action_t xlat_func_file_rm(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
void * rctx
Resume context.
xlat_exp_t * ex
Tokenized expression to use in expansion.
void const * inst
xlat instance data.
void * uctx
Passed to the registration function.
void * inst
xlat instance data to populate.
An xlat instantiation ctx.
fr_dict_attr_t const * xlat_time_res_attr(char const *res)
void xlat_eval_free(void)
int xlat_register_expressions(void)
void xlat_func_free(void)
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
xlat_t * xlat_func_find(char const *in, ssize_t inlen)
#define xlat_func_instantiate_set(_xlat, _instantiate, _inst_struct, _detach, _uctx)
Set a callback for global instantiation of xlat functions.
#define xlat_func_safe_for_set(_xlat, _escaped)
Set the escaped values for output boxes.
@ XLAT_FUNC_FLAG_INTERNAL
int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, void *decode_ctx, fr_pair_decode_t decode, fr_value_box_list_t *in)
Decode all of the value boxes into the output cursor.
@ XLAT_GROUP
encapsulated string of xlats
xlat_type_t _CONST type
type of this expansion.