From: Arran Cudbard-Bell Date: Tue, 21 Feb 2023 20:11:02 +0000 (-0600) Subject: xlat: Make %{} and %() functions take the same format argument list X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=53cdefc8f90317d1d16f02e88ab60063e7077db4;p=thirdparty%2Ffreeradius-server.git xlat: Make %{} and %() functions take the same format argument list Add support for quoted arguments to curly bracketed expansions --- diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index 1f16d555850..84ddc71e66b 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -398,16 +398,14 @@ int xlat_func_args(xlat_t *x, xlat_arg_parser_t const args[]) * For xlats that take all their input as a single argument * * @param[in,out] x to have it's arguments registered - * @param[in] arg to be registered + * @param[in] args to be registered * @return * - 0 on success. * - < 0 on failure. */ -int xlat_func_mono(xlat_t *x, xlat_arg_parser_t const *arg) +int xlat_func_mono(xlat_t *x, xlat_arg_parser_t const args[]) { - if (xlat_arg_parser_validate(arg, true) < 0) return -1; - - x->args = arg; + if (xlat_func_args(x, args) < 0) return -1; x->input_type = XLAT_INPUT_MONO; return 0; @@ -969,11 +967,12 @@ static xlat_arg_parser_t const xlat_func_debug_args[] = { */ static xlat_action_t xlat_func_debug(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { int level = 0; - fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *vb, *lvl_vb; + + XLAT_ARGS(args, &lvl_vb); /* * Expand to previous (or current) level @@ -985,9 +984,9 @@ static xlat_action_t xlat_func_debug(TALLOC_CTX *ctx, fr_dcursor_t *out, /* * Assume we just want to get the current value and NOT set it to 0 */ - if (!in_head) goto done; + if (!lvl_vb) goto done; - level = in_head->vb_int8; + level = lvl_vb->vb_int8; if (level == 0) { request->log.lvl = RAD_REQUEST_LVL_NONE; } else { @@ -1136,15 +1135,17 @@ void xlat_debug_attr_list(request_t *request, fr_pair_list_t const *list) */ 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_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_pair_t *vp; fr_dcursor_t cursor; tmpl_dcursor_ctx_t cc; tmpl_t *vpt; - fr_value_box_t *attr = fr_value_box_list_head(in); + fr_value_box_t *attr; char const *fmt; + XLAT_ARGS(args, &attr); + if (!RDEBUG_ENABLED2) return XLAT_ACTION_DONE; /* NOOP if debugging isn't enabled */ fmt = attr->vb_strvalue; @@ -1191,13 +1192,15 @@ static xlat_action_t xlat_func_debug_attr(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcur */ static xlat_action_t xlat_func_flatten(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_pair_t *vp; tmpl_t *vpt; - fr_value_box_t *attr = fr_value_box_list_head(in); + fr_value_box_t *attr; char const *fmt; + XLAT_ARGS(args, &attr); + fmt = attr->vb_strvalue; if (tmpl_afrom_attr_str(request, NULL, &vpt, fmt, &(tmpl_rules_t){ @@ -1238,13 +1241,15 @@ static xlat_action_t xlat_func_flatten(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor */ static xlat_action_t xlat_func_unflatten(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_pair_t *vp; tmpl_t *vpt; - fr_value_box_t *attr = fr_value_box_list_head(in); + fr_value_box_t *attr; char const *fmt; + XLAT_ARGS(args, &attr); + fmt = attr->vb_strvalue; if (tmpl_afrom_attr_str(request, NULL, &vpt, fmt, &(tmpl_rules_t){ @@ -1324,14 +1329,18 @@ update request { */ static xlat_action_t xlat_func_explode(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { - fr_value_box_t *strings = fr_value_box_list_head(in); - FR_DLIST_HEAD(fr_value_box_list) *list = &strings->vb_group; - fr_value_box_t *delim_vb = fr_value_box_list_next(in, strings); - ssize_t delim_len; - char const *delim; - fr_value_box_t *string, *vb; + fr_value_box_t *strings; + FR_DLIST_HEAD(fr_value_box_list) *list; + fr_value_box_t *delim_vb; + ssize_t delim_len; + char const *delim; + fr_value_box_t *string, *vb; + + XLAT_ARGS(args, &strings, &delim_vb); + + list = &strings->vb_group; /* coverity[dereference] */ if (delim_vb->vb_length == 0) { @@ -1405,14 +1414,16 @@ update request { */ static xlat_action_t xlat_func_integer(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { - fr_value_box_t *in_vb = fr_value_box_list_head(in); + fr_value_box_t *in_vb; char const *p; + XLAT_ARGS(args, &in_vb); + fr_strerror_clear(); /* Make sure we don't print old errors */ - fr_value_box_list_remove(in, in_vb); + fr_value_box_list_remove(args, in_vb); switch (in_vb->type) { default: @@ -1514,10 +1525,9 @@ static xlat_action_t xlat_func_integer(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_map_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_map_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Processes fmt as a map string and applies it to the current request @@ -1534,11 +1544,11 @@ static xlat_arg_parser_t const xlat_func_map_arg = { */ static xlat_action_t xlat_func_map(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { map_t *map = NULL; int ret; - fr_value_box_t *fmt_vb = fr_value_box_list_head(in); + fr_value_box_t *fmt_vb; fr_value_box_t *vb; tmpl_rules_t attr_rules = { @@ -1549,6 +1559,8 @@ static xlat_action_t xlat_func_map(TALLOC_CTX *ctx, fr_dcursor_t *out, } }; + XLAT_ARGS(args, &fmt_vb); + if (map_afrom_attr_str(request, &map, fmt_vb->vb_strvalue, &attr_rules, &attr_rules) < 0) { RPEDEBUG("Failed parsing \"%s\" as map", fmt_vb->vb_strvalue); return XLAT_ACTION_FAIL; @@ -1613,7 +1625,7 @@ static xlat_arg_parser_t const xlat_func_next_time_args[] = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { long num; @@ -1621,9 +1633,11 @@ static xlat_action_t xlat_func_next_time(TALLOC_CTX *ctx, fr_dcursor_t *out, char *q; time_t now; struct tm *local, local_buff; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; fr_value_box_t *vb; + XLAT_ARGS(args, &in_head); + /* * We want to limit based on _now_, not on when they logged in. */ @@ -1706,10 +1720,9 @@ static xlat_action_t xlat_eval_resume(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_ return xa; } -static xlat_arg_parser_t const xlat_func_eval_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_eval_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Dynamically evaluate an expansion string @@ -1718,11 +1731,8 @@ static xlat_arg_parser_t const xlat_func_eval_arg = { */ static xlat_action_t xlat_func_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { - xlat_eval_rctx_t *rctx; - fr_value_box_t *arg = fr_value_box_list_head(in); - /* * These are escaping rules applied to the * input string. They're mostly here to @@ -1742,6 +1752,11 @@ static xlat_action_t xlat_func_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, .do_oct = false }; + xlat_eval_rctx_t *rctx; + fr_value_box_t *arg = fr_value_box_list_head(args); + + XLAT_ARGS(args, &arg); + MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), xlat_eval_rctx_t)); /* @@ -1795,11 +1810,8 @@ static xlat_action_t xlat_func_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, */ static xlat_action_t xlat_func_expr(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { - xlat_eval_rctx_t *rctx; - fr_value_box_t *arg = fr_value_box_list_head(in); - /* * These are escaping rules applied to the * input string. They're mostly here to @@ -1819,6 +1831,11 @@ static xlat_action_t xlat_func_expr(TALLOC_CTX *ctx, fr_dcursor_t *out, .do_oct = false }; + xlat_eval_rctx_t *rctx; + fr_value_box_t *arg; + + XLAT_ARGS(args, &arg); + MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), xlat_eval_rctx_t)); /* @@ -1988,17 +2005,22 @@ 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_DLIST_HEAD(fr_value_box_list) *args) { - fr_value_box_t *values = fr_value_box_list_head(args); - FR_DLIST_HEAD(fr_value_box_list) *list = &values->vb_group; - fr_value_box_t *pad = fr_value_box_list_next(args, values); + fr_value_box_t *values; + FR_DLIST_HEAD(fr_value_box_list) *list; + fr_value_box_t *pad; /* coverity[dereference] */ - size_t pad_len = (size_t)pad->vb_uint64; - fr_value_box_t *fill = fr_value_box_list_next(args, pad); + size_t pad_len; + fr_value_box_t *fill; char const *fill_str = NULL; size_t fill_len = 0; fr_value_box_t *in = NULL; + XLAT_ARGS(args, &values, &pad, &fill); + + list = &values->vb_group; + pad_len = (size_t)pad->vb_uint64; + /* * Fill is optional */ @@ -2049,10 +2071,9 @@ static xlat_action_t xlat_func_rpad(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_base64_encode_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_base64_encode_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Encode string or attribute as base64 @@ -2072,7 +2093,9 @@ static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_dcursor_t *out, ssize_t elen; char *buff; fr_value_box_t *vb; - fr_value_box_t *in = fr_value_box_list_head(args); + fr_value_box_t *in; + + XLAT_ARGS(args, &in); alen = FR_BASE64_ENC_LENGTH(in->vb_length); @@ -2096,10 +2119,9 @@ static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_base64_decode_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_base64_decode_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Decode base64 string @@ -2119,7 +2141,9 @@ static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_dcursor_t *out, ssize_t declen = 0; uint8_t *decbuf; fr_value_box_t *vb; - fr_value_box_t *in = fr_value_box_list_head(args); + fr_value_box_t *in; + + XLAT_ARGS(args, &in); alen = FR_BASE64_DEC_LENGTH(in->vb_length); MEM(vb = fr_value_box_alloc_null(ctx)); @@ -2142,10 +2166,9 @@ static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_bin_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_bin_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Convert hex string to binary @@ -2161,7 +2184,7 @@ static xlat_arg_parser_t const xlat_func_bin_arg = { */ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_value_box_t *result; char const *p, *end; @@ -2170,7 +2193,8 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_sbuff_parse_error_t err; fr_value_box_t *hex; - hex = fr_value_box_list_head(in); + XLAT_ARGS(args, &hex); + len = hex->vb_length; if ((len > 1) && (len & 0x01)) { REDEBUG("Input data length must be >1 and even, got %zu", len); @@ -2196,7 +2220,7 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_dcursor_t *out, outlen = len / 2; MEM(result = fr_value_box_alloc_null(ctx)); - MEM(fr_value_box_mem_alloc(result, &bin, result, NULL, outlen, fr_value_box_list_tainted(in)) == 0); + MEM(fr_value_box_mem_alloc(result, &bin, result, NULL, outlen, fr_value_box_list_tainted(args)) == 0); fr_base16_decode(&err, &FR_DBUFF_TMP(bin, outlen), &FR_SBUFF_IN(p, end - p), true); if (err) { REDEBUG2("Invalid hex string"); @@ -2229,12 +2253,14 @@ static xlat_arg_parser_t const xlat_func_cast_args[] = { */ static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { - fr_value_box_t *name = fr_value_box_list_head(in); + fr_value_box_t *name; fr_value_box_t *arg; fr_type_t type; + XLAT_ARGS(args, &name); + /* * Get the type, which can be in one of a few formats. */ @@ -2267,13 +2293,13 @@ static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_sbuff_t *agg; fr_value_box_t *dst; - (void) fr_value_box_list_pop_head(in); + (void) fr_value_box_list_pop_head(args); talloc_free(name); FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 256, 8192); MEM(dst = fr_value_box_alloc_null(ctx)); - if (fr_value_box_list_concat_as_string(NULL, agg, in, NULL, 0, &fr_value_escape_double, + if (fr_value_box_list_concat_as_string(NULL, agg, args, NULL, 0, &fr_value_escape_double, FR_VALUE_BOX_LIST_FREE_BOX, true, true) < 0) { RPEDEBUG("Failed concatenating string"); return XLAT_ACTION_FAIL; @@ -2289,7 +2315,7 @@ static xlat_action_t xlat_func_cast(TALLOC_CTX *ctx, fr_dcursor_t *out, * Copy inputs to outputs, casting them along the way. */ arg = name; - while ((arg = fr_value_box_list_next(in, arg)) != NULL) { + while ((arg = fr_value_box_list_next(args, arg)) != NULL) { fr_value_box_t *vb, *p; fr_assert(arg->type == FR_TYPE_GROUP); @@ -2332,14 +2358,16 @@ static xlat_arg_parser_t const xlat_func_concat_args[] = { */ static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_value_box_t *result; - fr_value_box_t *list = fr_value_box_list_head(in); - fr_value_box_t *separator = fr_value_box_list_next(in, list); + fr_value_box_t *list; + fr_value_box_t *separator; char *buff; char const *sep; + XLAT_ARGS(args, &list, &separator); + sep = (separator) ? separator->vb_strvalue : ""; result = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL, false); @@ -2352,17 +2380,16 @@ static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_dcursor_t *out, buff = fr_value_box_list_aprint(result, &list->vb_group, sep, NULL); if (!buff) goto error; - fr_value_box_bstrdup_buffer_shallow(NULL, result, NULL, buff, fr_value_box_list_tainted(in)); + fr_value_box_bstrdup_buffer_shallow(NULL, result, NULL, buff, fr_value_box_list_tainted(args)); fr_dcursor_append(out, result); return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_hex_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_hex_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Print data as hex, not as VALUE. @@ -2378,10 +2405,14 @@ static xlat_arg_parser_t const xlat_func_hex_arg = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { char *new_buff; - fr_value_box_t *bin = fr_value_box_list_pop_head(in); /* First argument */ + fr_value_box_t *bin; + + XLAT_ARGS(args, &bin); + + fr_value_box_list_remove(args, bin); /* * Use existing box, but with new buffer @@ -2410,12 +2441,11 @@ typedef enum { } hmac_type; static xlat_action_t xlat_hmac(TALLOC_CTX *ctx, fr_dcursor_t *out, - FR_DLIST_HEAD(fr_value_box_list) *in, uint8_t *digest, int digest_len, hmac_type type) + FR_DLIST_HEAD(fr_value_box_list) *args, uint8_t *digest, int digest_len, hmac_type type) { fr_value_box_t *vb, *data, *key; - data = fr_value_box_list_head(in); - key = fr_value_box_list_next(in, data); + XLAT_ARGS(args, &data, &key); if (type == HMAC_MD5) { /* coverity[dereference] */ @@ -2566,9 +2596,9 @@ static xlat_action_t xlat_func_length(TALLOC_CTX *ctx, fr_dcursor_t *out, } -static xlat_arg_parser_t const xlat_func_md4_arg = { - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_md4_arg[] = { + { .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Calculate the MD4 hash of a string or attribute. @@ -2582,11 +2612,13 @@ static xlat_arg_parser_t const xlat_func_md4_arg = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { uint8_t digest[MD5_DIGEST_LENGTH]; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); if (in_head) { fr_md4_calc(digest, in_head->vb_octets, in_head->vb_length); @@ -2603,9 +2635,9 @@ static xlat_action_t xlat_func_md4(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_md5_arg = { - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_md5_arg[] = { + { .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Calculate the MD5 hash of a string or attribute. @@ -2619,11 +2651,13 @@ static xlat_arg_parser_t const xlat_func_md5_arg = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { uint8_t digest[MD5_DIGEST_LENGTH]; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); if (in_head) { fr_md5_calc(digest, in_head->vb_octets, in_head->vb_length); @@ -2682,10 +2716,9 @@ static xlat_action_t xlat_func_module(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_func_pack_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_pack_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Pack multiple things together @@ -2736,16 +2769,18 @@ static xlat_arg_parser_t const xlat_func_pairs_args[] = { */ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { tmpl_t *vpt = NULL; fr_dcursor_t cursor; tmpl_dcursor_ctx_t cc; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; fr_pair_t *vp; + XLAT_ARGS(args, &in_head); + if (tmpl_afrom_attr_str(ctx, NULL, &vpt, in_head->vb_strvalue, &(tmpl_rules_t){ .attr = { @@ -2781,11 +2816,9 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } - -static xlat_arg_parser_t const xlat_func_rand_arg = { - .required = true, - .single = true, - .type = FR_TYPE_UINT32 +static xlat_arg_parser_t const xlat_func_rand_arg[] = { + { .required = true, .single = true, .type = FR_TYPE_UINT32 }, + XLAT_ARG_PARSER_TERMINATOR }; /** Generate a random integer value @@ -2823,11 +2856,9 @@ static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } - -static xlat_arg_parser_t const xlat_func_randstr_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_randstr_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Generate a string of random chars @@ -2858,7 +2889,7 @@ static xlat_arg_parser_t const xlat_func_randstr_arg = { */ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { /* * Lookup tables for randstr char classes @@ -2879,7 +2910,9 @@ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_dcursor_t *out, unsigned int reps; size_t outlen = 0; fr_value_box_t* vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); /** Max repetitions of a single character class * @@ -3040,11 +3073,17 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) { - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head = fr_value_box_list_head(in); + + /* + * Find the first child of the first argument group + */ + fr_value_box_t *arg = fr_value_box_list_head(&in_head->vb_group); + /* * Return the complete capture if no other capture is specified */ - if (!in_head) { + if (!arg) { fr_value_box_t *vb; char *p; @@ -3062,7 +3101,7 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } - switch (in_head->type) { + switch (arg->type) { /* * If the input is an integer value then get an * arbitrary subcapture index. @@ -3078,7 +3117,7 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_FAIL; } - if (fr_value_box_cast(NULL, &idx, FR_TYPE_UINT32, NULL, in_head) < 0) { + if (fr_value_box_cast(NULL, &idx, FR_TYPE_UINT32, NULL, arg) < 0) { RPEDEBUG("Bad subcapture index"); return XLAT_ACTION_FAIL; } @@ -3105,7 +3144,7 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, * Concatenate all input */ if (fr_value_box_list_concat_in_place(ctx, - in_head, in, FR_TYPE_STRING, + arg, &in_head->vb_group, FR_TYPE_STRING, FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) < 0) { RPEDEBUG("Failed concatenating input"); @@ -3113,7 +3152,7 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, } MEM(vb = fr_value_box_alloc_null(ctx)); - if (regex_request_to_sub_named(vb, &p, request, in_head->vb_strvalue) < 0) { + if (regex_request_to_sub_named(vb, &p, request, arg->vb_strvalue) < 0) { REDEBUG2("No previous named regex capture group"); talloc_free(vb); return XLAT_ACTION_FAIL; @@ -3129,9 +3168,9 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, } #endif -static xlat_arg_parser_t const xlat_func_sha_arg = { - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const xlat_func_sha_arg[] = { + { .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Calculate the SHA1 hash of a string or attribute. @@ -3145,12 +3184,14 @@ static xlat_arg_parser_t const xlat_func_sha_arg = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { uint8_t digest[SHA1_DIGEST_LENGTH]; fr_sha1_ctx sha1_ctx; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); fr_sha1_init(&sha1_ctx); if (in_head) { @@ -3169,7 +3210,6 @@ static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } - /** Calculate any digest supported by OpenSSL EVP_MD * * Example: @@ -3182,13 +3222,15 @@ static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, #ifdef HAVE_OPENSSL_EVP_H static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in, EVP_MD const *md) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args, EVP_MD const *md) { uint8_t digest[EVP_MAX_MD_SIZE]; unsigned int digestlen; EVP_MD_CTX *md_ctx; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); md_ctx = EVP_MD_CTX_create(); EVP_DigestInit_ex(md_ctx, md, NULL); @@ -3234,10 +3276,9 @@ EVP_MD_XLAT(sha3_512, sha3_512) #endif -static xlat_arg_parser_t const xlat_func_string_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_string_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Print data as string, if possible. @@ -3262,9 +3303,9 @@ static xlat_action_t xlat_func_string(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, } -static xlat_arg_parser_t const xlat_func_strlen_arg = { - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_strlen_arg[] = { + { .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Print length of given string @@ -3280,10 +3321,12 @@ static xlat_arg_parser_t const xlat_func_strlen_arg = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL, false)); @@ -3318,8 +3361,8 @@ static xlat_action_t xlat_func_strlen(TALLOC_CTX *ctx, fr_dcursor_t *out, * @ingroup xlat_functions */ static xlat_action_t xlat_func_subst_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, - UNUSED xlat_ctx_t const *xctx, request_t *request, - FR_DLIST_HEAD(fr_value_box_list) *in) + UNUSED xlat_ctx_t const *xctx, request_t *request, + FR_DLIST_HEAD(fr_value_box_list) *args) { char const *p, *q, *end; char const *regex; @@ -3329,9 +3372,11 @@ static xlat_action_t xlat_func_subst_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, regex_t *pattern; fr_regex_flags_t flags; fr_value_box_t *vb; - fr_value_box_t *subject_vb = fr_value_box_list_head(in); - fr_value_box_t *regex_vb = fr_value_box_list_next(in, subject_vb); - fr_value_box_t *rep_vb = fr_value_box_list_next(in, regex_vb); + fr_value_box_t *subject_vb; + fr_value_box_t *regex_vb; + fr_value_box_t *rep_vb; + + XLAT_ARGS(args, &subject_vb, ®ex_vb, &rep_vb); /* coverity[dereference] */ p = regex_vb->vb_strvalue; @@ -3392,7 +3437,6 @@ static xlat_action_t xlat_func_subst_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, } #endif - static xlat_arg_parser_t const xlat_func_subst_args[] = { { .required = true, .concat = true, .type = FR_TYPE_STRING }, { .required = true, .concat = true, .type = FR_TYPE_STRING }, @@ -3421,7 +3465,7 @@ static xlat_action_t xlat_func_subst(TALLOC_CTX *ctx, fr_dcursor_t *out, #else UNUSED xlat_ctx_t const *xctx, #endif - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { char const *p, *q, *end; char *vb_str; @@ -3430,15 +3474,16 @@ static xlat_action_t xlat_func_subst(TALLOC_CTX *ctx, fr_dcursor_t *out, size_t pattern_len, rep_len; fr_value_box_t *rep_vb, *vb; - fr_value_box_t *subject_vb = fr_value_box_list_head(in); - fr_value_box_t *pattern_vb = fr_value_box_list_next(in, subject_vb); + fr_value_box_t *subject_vb; + fr_value_box_t *pattern_vb; + + XLAT_ARGS(args, &subject_vb, &pattern_vb, &rep_vb); /* coverity[dereference] */ pattern = pattern_vb->vb_strvalue; - if (*pattern == '/') { #ifdef HAVE_REGEX_PCRE2 - return xlat_func_subst_regex(ctx, out, xctx, request, in); + return xlat_func_subst_regex(ctx, out, xctx, request, args); #else REDEBUG("regex based substitutions require libpcre2. " "Check ${features.regex-pcre2} to determine support"); @@ -3455,7 +3500,6 @@ static xlat_action_t xlat_func_subst(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_FAIL; } - rep_vb = fr_value_box_list_next(in, pattern_vb); rep = rep_vb->vb_strvalue; rep_len = rep_vb->vb_length; @@ -3489,7 +3533,6 @@ static xlat_action_t xlat_func_subst(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } - static xlat_arg_parser_t const xlat_func_time_args[] = { { .required = false, .single = true, .type = FR_TYPE_STRING }, XLAT_ARG_PARSER_TERMINATOR @@ -3514,12 +3557,14 @@ update reply { */ static xlat_action_t xlat_func_time(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { - fr_value_box_t *arg = fr_value_box_list_head(in); + fr_value_box_t *arg; fr_value_box_t *vb; fr_unix_time_t value; + XLAT_ARGS(args, &arg); + if (!arg || (strcmp(arg->vb_strvalue, "now") == 0)) { value = fr_time_to_unix_time(fr_time()); @@ -3593,11 +3638,13 @@ append: * If upper is true, change to uppercase, otherwise, change to lowercase */ static xlat_action_t xlat_change_case(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, - UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in, bool upper) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args, bool upper) { char *p; char const *end; - fr_value_box_t *vb = fr_value_box_list_pop_head(in); + fr_value_box_t *vb; + + XLAT_ARGS(args, &vb); p = UNCONST(char *, vb->vb_strvalue); end = p + vb->vb_length; @@ -3607,15 +3654,15 @@ static xlat_action_t xlat_change_case(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, p++; } + fr_value_box_list_remove(args, vb); /* Can't leave it in both lists */ fr_dcursor_append(out, vb); return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const xlat_change_case_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_change_case_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; @@ -3657,10 +3704,9 @@ static xlat_action_t xlat_func_toupper(TALLOC_CTX *ctx, fr_dcursor_t *out, } -static xlat_arg_parser_t const xlat_func_urlquote_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_urlquote_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** URLencode special characters @@ -3674,13 +3720,15 @@ static xlat_arg_parser_t const xlat_func_urlquote_arg = { */ 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_DLIST_HEAD(fr_value_box_list) *in) + UNUSED request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { char const *p, *end; char *buff_p; size_t outlen = 0; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); p = in_head->vb_strvalue; end = p + in_head->vb_length; @@ -3737,10 +3785,9 @@ static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_dcursor_t *out, } -static xlat_arg_parser_t const xlat_func_urlunquote_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const xlat_func_urlunquote_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** URLdecode special characters @@ -3756,14 +3803,16 @@ static xlat_arg_parser_t const xlat_func_urlunquote_arg = { */ static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { char const *p, *end; char *buff_p; char *c1, *c2; size_t outlen = 0; fr_value_box_t *vb; - fr_value_box_t *in_head = fr_value_box_list_head(in); + fr_value_box_t *in_head; + + XLAT_ARGS(args, &in_head); p = in_head->vb_strvalue; end = p + in_head->vb_length; @@ -3886,7 +3935,7 @@ static xlat_arg_parser_t const protocol_encode_xlat_args[] = { */ static xlat_action_t protocol_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { tmpl_t *vpt; fr_pair_t *vp; @@ -3898,11 +3947,12 @@ static xlat_action_t protocol_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, uint8_t binbuf[2048]; uint8_t *p = binbuf, *end = p + sizeof(binbuf); ssize_t len = 0; - fr_value_box_t *in_head = fr_value_box_list_head(in); - + fr_value_box_t *in_head; void *encode_ctx = NULL; fr_test_point_pair_encode_t const *tp_encode; + XLAT_ARGS(args, &in_head); + memcpy(&tp_encode, xctx->inst, sizeof(tp_encode)); /* const issues */ if (tmpl_afrom_attr_str(ctx, NULL, &vpt, in_head->vb_strvalue, @@ -4144,7 +4194,7 @@ do { \ #define XLAT_REGISTER_MONO(_xlat, _func, _return_type, _arg) \ do { \ if (!(xlat = xlat_register(NULL, _xlat, _func, _return_type, XLAT_FLAG_PURE))) return -1; \ - xlat_func_mono(xlat, &_arg); \ + xlat_func_mono(xlat, _arg); \ xlat_internal(xlat); \ } while (0) @@ -4192,7 +4242,7 @@ do { \ #define XLAT_REGISTER_MONO(_xlat, _func, _return_type, _arg) \ do { \ if (!(xlat = xlat_register(NULL, _xlat, _func, _return_type, NULL))) return -1; \ - xlat_func_mono(xlat, &_arg); \ + xlat_func_mono(xlat, _arg); \ xlat_internal(xlat); \ } while (0) diff --git a/src/lib/unlang/xlat_eval.c b/src/lib/unlang/xlat_eval.c index a73324a846a..446db673fb8 100644 --- a/src/lib/unlang/xlat_eval.c +++ b/src/lib/unlang/xlat_eval.c @@ -47,9 +47,9 @@ static fr_dict_autoload_t xlat_eval_dict[] = { { NULL } }; -fr_dict_attr_t const *attr_expr_bool_enum; /* xlat_expr.c */ -fr_dict_attr_t const *attr_module_return_code; /* xlat_expr.c */ -fr_dict_attr_t const *attr_cast_base; /* xlat_expr.c */ +fr_dict_attr_t const *attr_expr_bool_enum; /* xlat_expr.c */ +fr_dict_attr_t const *attr_module_return_code; /* xlat_expr.c */ +fr_dict_attr_t const *attr_cast_base; /* xlat_expr.c */ static fr_dict_attr_autoload_t xlat_eval_dict_attr[] = { { .out = &attr_module_return_code, .name = "Module-Return-Code", .type = FR_TYPE_UINT32, .dict = &dict_freeradius }, @@ -258,14 +258,14 @@ static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_val do { \ if ((_arg)->func && ((_vb)->tainted || (_arg)->always_escape) && \ ((_arg)->func(request, _vb, (_arg)->uctx) < 0)) { \ - RPEDEBUG("Function %s failed escaping argument %u", name, _arg_num); \ + RPEDEBUG("Function \"%s\" failed escaping argument %u", name, _arg_num); \ return XLAT_ACTION_FAIL; \ } \ } while (0) if (fr_value_box_list_empty(list)) { if (arg->required) { - RWDEBUG("Function %s is missing required argument %u", name, arg_num); + REDEBUG("Function \"%s\" is missing required argument %u", name, arg_num); return XLAT_ACTION_FAIL; } return XLAT_ACTION_DONE; @@ -288,7 +288,7 @@ do { \ vb, list, arg->type, FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) < 0) { - RPEDEBUG("Function %s failed concatenating arguments to type %s", name, fr_type_to_str(arg->type)); + RPEDEBUG("Function \"%s\" failed concatenating arguments to type %s", name, fr_type_to_str(arg->type)); return XLAT_ACTION_FAIL; } fr_assert(fr_value_box_list_num_elements(list) <= 1); @@ -302,7 +302,7 @@ do { \ */ if (arg->single) { if (fr_value_box_list_num_elements(list) > 1) { - RPEDEBUG("Function %s was provided an incorrect number of values at argument %u, " + RPEDEBUG("Function \"%s\" was provided an incorrect number of values at argument %u, " "expected %s got %u", name, arg_num, arg->required ? "0-1" : "1", @@ -316,7 +316,7 @@ do { \ cast_error: if (fr_value_box_cast_in_place(ctx, vb, arg->type, NULL) < 0) { - RPEDEBUG("Function %s failed cast argument %u to type %s", name, arg_num, fr_type_to_str(arg->type)); + RPEDEBUG("Function \"%s\" failed to cast argument %u to type %s", name, arg_num, fr_type_to_str(arg->type)); return XLAT_ACTION_FAIL; } } @@ -362,7 +362,8 @@ do { \ * @param[in] func to call */ static inline CC_HINT(always_inline) -xlat_action_t xlat_process_args(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list) *list, request_t *request, xlat_t const *func) +xlat_action_t xlat_process_args(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list) *list, + request_t *request, xlat_t const *func) { xlat_arg_parser_t const *arg_p = func->args; xlat_action_t xa; @@ -373,6 +374,7 @@ xlat_action_t xlat_process_args(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list */ if (!func->args) return XLAT_ACTION_DONE; + /* * xlat needs no input processing just return. */ @@ -384,11 +386,6 @@ xlat_action_t xlat_process_args(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list * xlat takes all input as a single vb. */ case XLAT_INPUT_MONO: - return xlat_process_arg_list(ctx, list, request, func->name, arg_p, 1); - - /* - * xlat consumes a sequence of arguments. - */ case XLAT_INPUT_ARGS: vb = fr_value_box_list_head(list); while (arg_p->type != FR_TYPE_NULL) { @@ -401,7 +398,8 @@ xlat_action_t xlat_process_args(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list if (!vb) { if (arg_p->required) { missing: - REDEBUG("Function %s is missing required argument %u", func->name, (unsigned int)((arg_p - func->args) + 1)); + REDEBUG("Function \"%s\" is missing required argument %u", + func->name, (unsigned int)((arg_p - func->args) + 1)); return XLAT_ACTION_FAIL; } @@ -553,7 +551,8 @@ bool xlat_process_return(request_t *request, xlat_t const *func, FR_DLIST_HEAD(f * */ static inline CC_HINT(always_inline) -xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list) *out, request_t *request, char letter) +xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, FR_DLIST_HEAD(fr_value_box_list) *out, + request_t *request, char letter) { char buffer[64]; @@ -788,9 +787,9 @@ void xlat_signal(xlat_func_signal_t signal, xlat_exp_t const *exp, * when it yielded. */ xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, - xlat_exp_head_t const **child, - request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in, - FR_DLIST_HEAD(fr_value_box_list) *result, xlat_func_t resume, void *rctx) + xlat_exp_head_t const **child, + request_t *request, xlat_exp_head_t const *head, xlat_exp_t const **in, + FR_DLIST_HEAD(fr_value_box_list) *result, xlat_func_t resume, void *rctx) { xlat_action_t xa; xlat_exp_t const *node = *in; diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index fc4ef326d2b..f4fc2f58c05 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -1404,8 +1404,9 @@ static int xlat_function_args_to_tmpl(xlat_inst_ctx_t const *xctx) } -static xlat_arg_parser_t const xlat_func_rcode_arg = { - .concat = true, .type = FR_TYPE_STRING, +static xlat_arg_parser_t const xlat_func_rcode_arg[] = { + { .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Return the rcode as a string, or bool match if the argument is an rcode name @@ -1420,11 +1421,12 @@ static xlat_arg_parser_t const xlat_func_rcode_arg = { */ static xlat_action_t xlat_func_rcode(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, - request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) + request_t *request, FR_DLIST_HEAD(fr_value_box_list) *args) { fr_value_box_t *vb; - fr_value_box_t *src = fr_value_box_list_head(in); + fr_value_box_t *src; + XLAT_ARGS(args, &src); /* * Query the rcode if there's no argument. Otherwise do a boolean check if the passed string * matches the current rcode. @@ -1456,8 +1458,9 @@ typedef struct { FR_DLIST_HEAD(fr_value_box_list) list; } xlat_exists_rctx_t; -static xlat_arg_parser_t const xlat_func_exists_arg = { - .concat = true, .type = FR_TYPE_STRING, +static xlat_arg_parser_t const xlat_func_exists_arg[] = { + { .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /* @@ -1665,7 +1668,7 @@ do { \ #define XLAT_REGISTER_MONO(_xlat, _func, _arg) \ do { \ if (!(xlat = xlat_register(NULL, _xlat, _func, FR_TYPE_VOID, NULL))) return -1; \ - xlat_func_mono(xlat, &_arg); \ + xlat_func_mono(xlat, _arg); \ xlat_internal(xlat); \ } while (0) diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 70416bacb46..146d9b0eeaf 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -271,7 +271,7 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head, fr_sbuff_t *in, tmpl_rules_t const *t_rules) { - xlat_exp_t *node; + xlat_exp_t *node, *arg_group; xlat_t *func; fr_sbuff_marker_t m_s; @@ -338,15 +338,75 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head, XLAT_DEBUG("FUNC-ARGS <-- %s ... %pV", node->fmt, fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in))); - fr_sbuff_marker_release(&m_s); + fr_sbuff_set(&m_s, in); /* - * Now parse the child nodes that form the - * function's arguments. + * Allocate a top level group to hold all + * the argument fragments. This gives us + * somewhere to store the quoting. */ - if (xlat_tokenize_string(node->call.args, in, true, &xlat_expansion_rules, t_rules) < 0) { - goto error; + arg_group = xlat_exp_alloc(node->call.args, XLAT_GROUP, NULL, 0); + + /* + * It's the escape char. We can't start + * a quoted string. + */ + if (fr_sbuff_is_char(in, xlat_expansion_rules.escapes->chr)) { + bareword: + arg_group->quote = T_BARE_WORD; + + if (xlat_tokenize_string(arg_group->group, in, true, &xlat_expansion_rules, t_rules) < 0) { + goto error; + } + xlat_flags_merge(&arg_group->flags, &arg_group->group->flags); + /* + * Support passing the monolithic argument + * as a string. + */ + } else if (fr_sbuff_next_if_char(in, '\'')) { + char *str; + ssize_t slen; + xlat_exp_t *literal; + + arg_group->quote = T_SINGLE_QUOTED_STRING; + + literal = xlat_exp_alloc(arg_group, XLAT_BOX, NULL, 0); + + /* + * Find the next token + */ + slen = fr_sbuff_out_aunescape_until(literal, &str, in, SIZE_MAX, + value_parse_rules_single_quoted.terminals, + value_parse_rules_single_quoted.escapes); + if (slen < 0) goto error; + + xlat_exp_set_name_buffer_shallow(literal, str); + fr_value_box_strdup_shallow(&literal->data, NULL, str, false); + literal->flags.constant = true; + xlat_exp_insert_tail(arg_group->group, literal); + + if (!fr_sbuff_next_if_char(in, '\'')) { + fr_strerror_const("Missing closing \"'\""); + goto error; + } + } else if (fr_sbuff_next_if_char(in, '"')) { + arg_group->quote = T_DOUBLE_QUOTED_STRING; + + if (xlat_tokenize_string(arg_group->group, in, false, + &value_parse_rules_double_quoted, t_rules) < 0) { + goto error; + } + if (!fr_sbuff_next_if_char(in, '"')) { + fr_strerror_const("Missing closing '\"'"); + goto error; + } + } else { + goto bareword; } + xlat_exp_set_name(arg_group, fr_sbuff_current(&m_s), fr_sbuff_behind(&m_s)); + xlat_exp_insert_tail(node->call.args, arg_group); + + fr_sbuff_marker_release(&m_s); /* * Check there's input if it's needed diff --git a/src/lib/util/dlist.h b/src/lib/util/dlist.h index 4a97e40c1ee..f5e31966802 100644 --- a/src/lib/util/dlist.h +++ b/src/lib/util/dlist.h @@ -88,12 +88,12 @@ static_assert(sizeof(unsigned int) >= 4, "Unsigned integer too small on this pla #define fr_dlist_foreach_safe(_list_head, _type, _iter) \ { \ _type *_iter; \ - fr_dlist_t _tmp; \ + fr_dlist_t _tmp ## _iter; \ for (_iter = fr_dlist_head(_list_head), \ - _tmp = fr_dlist_head(_list_head) ? *fr_dlist_item_to_entry((_list_head)->offset, fr_dlist_head(_list_head)) : (fr_dlist_t){ .prev = NULL, .next = NULL }; \ + _tmp ## _iter = fr_dlist_head(_list_head) ? *fr_dlist_item_to_entry((_list_head)->offset, fr_dlist_head(_list_head)) : (fr_dlist_t){ .prev = NULL, .next = NULL }; \ _iter; \ - _iter = _tmp.next && (_tmp.next != &(_list_head)->entry) ? fr_dlist_entry_to_item((_list_head)->offset, _tmp.next) : NULL, \ - _tmp = _tmp.next && (_tmp.next != &(_list_head)->entry) ? *_tmp.next : (fr_dlist_t){ .prev = NULL, .next = NULL }) + _iter = _tmp ## _iter.next && (_tmp ## _iter.next != &(_list_head)->entry) ? fr_dlist_entry_to_item((_list_head)->offset, _tmp ## _iter.next) : NULL, \ + _tmp ## _iter = _tmp ## _iter.next && (_tmp ## _iter.next != &(_list_head)->entry) ? *_tmp ## _iter.next : (fr_dlist_t){ .prev = NULL, .next = NULL }) /** Find the dlist pointers within a list item diff --git a/src/modules/rlm_cipher/rlm_cipher.c b/src/modules/rlm_cipher/rlm_cipher.c index b6d755aaf1c..e8323998493 100644 --- a/src/modules/rlm_cipher/rlm_cipher.c +++ b/src/modules/rlm_cipher/rlm_cipher.c @@ -563,10 +563,9 @@ static int cipher_rsa_certificate_file_load(TALLOC_CTX *ctx, void *out, void *pa return 0; } -static xlat_arg_parser_t const cipher_rsa_encrypt_xlat_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING +static xlat_arg_parser_t const cipher_rsa_encrypt_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Encrypt input data @@ -625,10 +624,9 @@ static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, } -static xlat_arg_parser_t const cipher_rsa_sign_xlat_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_STRING, +static xlat_arg_parser_t const cipher_rsa_sign_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Sign input data @@ -704,10 +702,9 @@ static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const cipher_rsa_decrypt_xlat_arg = { - .required = true, - .concat = true, - .type = FR_TYPE_OCTETS +static xlat_arg_parser_t const cipher_rsa_decrypt_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_OCTETS }, + XLAT_ARG_PARSER_TERMINATOR }; /** Decrypt input data @@ -1303,7 +1300,7 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) */ xlat_name = talloc_asprintf(inst, "%s_decrypt", mctx->inst->name); xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_decrypt_xlat, FR_TYPE_STRING, NULL); - xlat_func_mono(xlat, &cipher_rsa_decrypt_xlat_arg); + xlat_func_mono(xlat, cipher_rsa_decrypt_xlat_arg); talloc_free(xlat_name); /* @@ -1340,7 +1337,7 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) */ xlat_name = talloc_asprintf(inst, "%s_encrypt", mctx->inst->name); xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_encrypt_xlat, FR_TYPE_OCTETS, NULL); - xlat_func_mono(xlat, &cipher_rsa_encrypt_xlat_arg); + xlat_func_mono(xlat, cipher_rsa_encrypt_xlat_arg); talloc_free(xlat_name); /* @@ -1348,7 +1345,7 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) */ xlat_name = talloc_asprintf(inst, "%s_sign", mctx->inst->name); xlat = xlat_register_module(inst, mctx, xlat_name, cipher_rsa_sign_xlat, FR_TYPE_OCTETS, NULL); - xlat_func_mono(xlat, &cipher_rsa_sign_xlat_arg); + xlat_func_mono(xlat, cipher_rsa_sign_xlat_arg); talloc_free(xlat_name); /* diff --git a/src/modules/rlm_escape/rlm_escape.c b/src/modules/rlm_escape/rlm_escape.c index 078df5f19e4..861bb21192d 100644 --- a/src/modules/rlm_escape/rlm_escape.c +++ b/src/modules/rlm_escape/rlm_escape.c @@ -21,6 +21,7 @@ * * @copyright 2018 Arran Cudbard-Bell (a.cudbardb@freeradius.org) */ +#include "lib/unlang/xlat.h" RCSID("$Id$") USES_APPLE_DEPRECATED_API @@ -45,7 +46,10 @@ static const CONF_PARSER module_config[] = { static char const hextab[] = "0123456789abcdef"; -static xlat_arg_parser_t const escape_xlat_arg = { .required = true, .concat = true, .type = FR_TYPE_STRING }; +static xlat_arg_parser_t const escape_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; /** Equivalent to the old safe_characters functionality in rlm_sql but with utf8 support * @@ -116,7 +120,10 @@ static xlat_action_t escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const unescape_xlat_arg = { .required = true, .concat = true, .type = FR_TYPE_STRING }; +static xlat_arg_parser_t const unescape_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; /** Equivalent to the old safe_characters functionality in rlm_sql * @@ -190,10 +197,10 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) MEM(unescape = talloc_asprintf(NULL, "un%s", mctx->inst->name)); xlat = xlat_register_module(NULL, mctx, mctx->inst->name, escape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE); - xlat_func_mono(xlat, &escape_xlat_arg); + xlat_func_mono(xlat, escape_xlat_arg); xlat = xlat_register_module(NULL, mctx, unescape, unescape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE); - xlat_func_mono(xlat, &unescape_xlat_arg); + xlat_func_mono(xlat, unescape_xlat_arg); talloc_free(unescape); return 0; diff --git a/src/modules/rlm_idn/rlm_idn.c b/src/modules/rlm_idn/rlm_idn.c index ef6b2a48f1f..db7a5a5a9fe 100644 --- a/src/modules/rlm_idn/rlm_idn.c +++ b/src/modules/rlm_idn/rlm_idn.c @@ -86,7 +86,10 @@ static const CONF_PARSER mod_config[] = { CONF_PARSER_TERMINATOR }; -static xlat_arg_parser_t const xlat_idna_arg = { .required = true, .concat = true, .type = FR_TYPE_STRING }; +static xlat_arg_parser_t const xlat_idna_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; /** Convert domain name to ASCII punycode * @@ -150,7 +153,7 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) xlat_t *xlat; xlat = xlat_register_module(inst, mctx, mctx->inst->name, xlat_idna, FR_TYPE_STRING, XLAT_FLAG_PURE); - xlat_func_mono(xlat, &xlat_idna_arg); + xlat_func_mono(xlat, xlat_idna_arg); return 0; } diff --git a/src/modules/rlm_json/rlm_json.c b/src/modules/rlm_json/rlm_json.c index b7b38c08034..a43538d75fa 100644 --- a/src/modules/rlm_json/rlm_json.c +++ b/src/modules/rlm_json/rlm_json.c @@ -77,8 +77,9 @@ typedef struct { json_object *root; } rlm_json_jpath_to_eval_t; -static xlat_arg_parser_t const json_quote_xlat_arg = { - .concat = true, .type = FR_TYPE_STRING +static xlat_arg_parser_t const json_quote_xlat_arg[] = { + { .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Ensure contents are quoted correctly for a JSON document @@ -110,8 +111,9 @@ static xlat_action_t json_quote_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const jpath_validate_xlat_arg = { - .required = true, .concat = true, .type = FR_TYPE_STRING +static xlat_arg_parser_t const jpath_validate_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Determine if a jpath expression is valid @@ -151,8 +153,9 @@ static xlat_action_t jpath_validate_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } -static xlat_arg_parser_t const json_encode_xlat_arg = { - .required = true, .concat = true, .type = FR_TYPE_STRING +static xlat_arg_parser_t const json_encode_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Convert given attributes to a JSON document @@ -527,13 +530,13 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) fr_json_format_t *format = inst->format; xlat = xlat_register_module(inst, mctx, "jsonquote", json_quote_xlat, FR_TYPE_STRING, NULL); - if (xlat) xlat_func_mono(xlat, &json_quote_xlat_arg); + if (xlat) xlat_func_mono(xlat, json_quote_xlat_arg); xlat = xlat_register_module(inst, mctx, "jpathvalidate", jpath_validate_xlat, FR_TYPE_STRING, NULL); - if (xlat) xlat_func_mono(xlat, &jpath_validate_xlat_arg); + if (xlat) xlat_func_mono(xlat, jpath_validate_xlat_arg); name = talloc_asprintf(inst, "%s_encode", mctx->inst->name); xlat = xlat_register_module(inst, mctx, name, json_encode_xlat, FR_TYPE_STRING, NULL); - xlat_func_mono(xlat, &json_encode_xlat_arg); + xlat_func_mono(xlat, json_encode_xlat_arg); talloc_free(name); /* diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index a5fd0991ba3..6697c757c15 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -176,8 +176,10 @@ global_lib_autoinst_t const *rlm_ldap_lib[] = { GLOBAL_LIB_TERMINATOR }; - -static xlat_arg_parser_t const ldap_escape_xlat_arg = { .required = true, .concat = true, .type = FR_TYPE_STRING }; +static xlat_arg_parser_t const ldap_escape_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; /** Escape LDAP string * @@ -384,7 +386,10 @@ static fr_uri_part_t const ldap_uri_parts[] = { XLAT_URI_PART_TERMINATOR }; -static xlat_arg_parser_t const ldap_xlat_arg = { .required = true, .type = FR_TYPE_STRING }; +static xlat_arg_parser_t const ldap_xlat_arg[] = { + { .required = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; /** Expand an LDAP URL into a query, and return a string result from that query. * @@ -395,7 +400,7 @@ static xlat_action_t ldap_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, request_t *request, FR_DLIST_HEAD(fr_value_box_list) *in) { fr_ldap_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, fr_ldap_thread_t); - fr_value_box_t *in_vb = NULL; + fr_value_box_t *uri_components, *uri; char *host_url; fr_ldap_config_t const *handle_config = t->config; fr_ldap_thread_trunk_t *ttrunk; @@ -403,21 +408,27 @@ static xlat_action_t ldap_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, LDAPURLDesc *ldap_url; - if (fr_uri_escape(in, ldap_uri_parts, NULL) < 0) return XLAT_ACTION_FAIL; + XLAT_ARGS(in, &uri_components); + + if (fr_uri_escape(&uri_components->vb_group, ldap_uri_parts, NULL) < 0) return XLAT_ACTION_FAIL; + + /* + * Smush everything into the first URI box + */ + uri = fr_value_box_list_head(&uri_components->vb_group); - in_vb = fr_value_box_list_head(in); - if (fr_value_box_list_concat_in_place(in_vb, in_vb, in, FR_TYPE_STRING, FR_VALUE_BOX_LIST_FREE, - true, SIZE_MAX) < 0) { + if (fr_value_box_list_concat_in_place(uri, uri, &uri_components->vb_group, + FR_TYPE_STRING, FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) < 0) { REDEBUG("Failed concattenating input"); return XLAT_ACTION_FAIL; } - if (!ldap_is_ldap_url(in_vb->vb_strvalue)) { + if (!ldap_is_ldap_url(uri->vb_strvalue)) { REDEBUG("String passed does not look like an LDAP URL"); return XLAT_ACTION_FAIL; } - if (ldap_url_parse(in_vb->vb_strvalue, &ldap_url)){ + if (ldap_url_parse(uri->vb_strvalue, &ldap_url)){ REDEBUG("Parsing LDAP URL failed"); error: ldap_free_urldesc(ldap_url); @@ -1760,12 +1771,12 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) } xlat = xlat_register_module(NULL, mctx, mctx->inst->name, ldap_xlat, FR_TYPE_STRING, NULL); - xlat_func_mono(xlat, &ldap_xlat_arg); + xlat_func_mono(xlat, ldap_xlat_arg); xlat = xlat_register_module(NULL, mctx, "ldap_escape", ldap_escape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE); - if (xlat) xlat_func_mono(xlat, &ldap_escape_xlat_arg); + if (xlat) xlat_func_mono(xlat, ldap_escape_xlat_arg); xlat = xlat_register_module(NULL, mctx, "ldap_unescape", ldap_unescape_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE); - if (xlat) xlat_func_mono(xlat, &ldap_escape_xlat_arg); + if (xlat) xlat_func_mono(xlat, ldap_escape_xlat_arg); map_proc_register(inst, mctx->inst->name, mod_map_proc, ldap_map_verify, 0); diff --git a/src/modules/rlm_sql/rlm_sql.c b/src/modules/rlm_sql/rlm_sql.c index b6f62d91fa5..cd0c7ebd534 100644 --- a/src/modules/rlm_sql/rlm_sql.c +++ b/src/modules/rlm_sql/rlm_sql.c @@ -1064,12 +1064,14 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) * The xlat escape function needs access to inst - so * argument parser details need to be defined here */ - sql_xlat_arg = talloc_zero(inst, xlat_arg_parser_t); - sql_xlat_arg->type = FR_TYPE_STRING; - sql_xlat_arg->required = true; - sql_xlat_arg->concat = true; - sql_xlat_arg->func = sql_xlat_escape; - sql_xlat_arg->uctx = inst; + sql_xlat_arg = talloc_zero_array(inst, xlat_arg_parser_t, 2); + sql_xlat_arg[0].type = FR_TYPE_STRING; + sql_xlat_arg[0].required = true; + sql_xlat_arg[0].concat = true; + sql_xlat_arg[0].func = sql_xlat_escape; + sql_xlat_arg[0].uctx = inst; + sql_xlat_arg[1] = (xlat_arg_parser_t)XLAT_ARG_PARSER_TERMINATOR; + xlat_func_mono(xlat, sql_xlat_arg); /* diff --git a/src/modules/rlm_yubikey/rlm_yubikey.c b/src/modules/rlm_yubikey/rlm_yubikey.c index d25d5210400..b5a371f9b13 100644 --- a/src/modules/rlm_yubikey/rlm_yubikey.c +++ b/src/modules/rlm_yubikey/rlm_yubikey.c @@ -126,8 +126,9 @@ static ssize_t modhex2hex(char const *modhex, char *hex, size_t len) return i; } -static xlat_arg_parser_t const modhex_to_hex_xlat_arg = { - .required = true, .concat = true, .type = FR_TYPE_STRING +static xlat_arg_parser_t const modhex_to_hex_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR }; /** Xlat to convert Yubikey modhex to standard hex @@ -196,7 +197,7 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) #endif xlat = xlat_register_module(inst, mctx, "modhextohex", modhex_to_hex_xlat, FR_TYPE_STRING, XLAT_FLAG_PURE); - if (xlat) xlat_func_mono(xlat, &modhex_to_hex_xlat_arg); + if (xlat) xlat_func_mono(xlat, modhex_to_hex_xlat_arg); return 0; } diff --git a/src/tests/keywords/if-regex-match-named b/src/tests/keywords/if-regex-match-named index b80c9dab4fa..719e5c2f87d 100644 --- a/src/tests/keywords/if-regex-match-named +++ b/src/tests/keywords/if-regex-match-named @@ -22,7 +22,7 @@ if ("%{regex:foo}") { test_fail } -if (!(&Module-Failure-Message == "No previous named regex capture group")) { +if (!(&Module-Failure-Message[*] == "No previous named regex capture group")) { test_fail } @@ -33,7 +33,7 @@ if ("%{regex:%{Tmp-Integer-1}}") { test_fail } -if (!(&Module-Failure-Message == "No previous numbered regex capture group")) { +if (!(&Module-Failure-Message[*] == "No previous numbered regex capture group")) { test_fail } diff --git a/src/tests/keywords/xlat-subst b/src/tests/keywords/xlat-subst index 35a195caa93..34cab022c6f 100644 --- a/src/tests/keywords/xlat-subst +++ b/src/tests/keywords/xlat-subst @@ -105,7 +105,7 @@ if ("%(subst:%{Tmp-String-0} /***/g .)") { test_fail } -if !(&Module-Failure-Message[0] == 'Failed compiling regex: quantifier does not follow a repeatable item') { +if !(&Module-Failure-Message[*] == 'Failed compiling regex: quantifier does not follow a repeatable item') { test_fail } @@ -116,7 +116,7 @@ if ("%(subst:%{Tmp-String-0} //g .)") { test_fail } -if !(&Module-Failure-Message[0] == 'Failed compiling regex: Empty expression') { +if !(&Module-Failure-Message[*] == 'Failed compiling regex: Empty expression') { test_fail } } diff --git a/src/tests/modules/json/encode_error.unlang b/src/tests/modules/json/encode_error.unlang index 6356f0ad5c7..3f4c2ad76f3 100644 --- a/src/tests/modules/json/encode_error.unlang +++ b/src/tests/modules/json/encode_error.unlang @@ -2,4 +2,9 @@ # json xlat input parsing test - error with no input # -&Tmp-String-1 := "%{json_object_ex_encode:}" # ERROR +&Tmp-String-1 := %{json_object_ex_encode:} # ERROR +if (&Tmp-String-1) { + test_fail +} + +test_pass diff --git a/src/tests/modules/linelog/linelog_xlat.unlang b/src/tests/modules/linelog/linelog_xlat.unlang index 363b71bc28a..6662a88979e 100644 --- a/src/tests/modules/linelog/linelog_xlat.unlang +++ b/src/tests/modules/linelog/linelog_xlat.unlang @@ -45,3 +45,21 @@ else { # Remove the file &Tmp-String-0 := `/bin/sh -c "rm $ENV{MODULE_TEST_DIR}/test_xlat.log"` + + +# Try with some handcrafted JSON + +if (%{linelog_fmt_delim_xlat:"{ \"foo\" : \"bar\", \"baz\" : \"boink\" }"} == 36) { + test_pass +} else { + test_fail +} + +&Tmp-String-0 := `/bin/sh -c "tail -n1 $ENV{MODULE_TEST_DIR}/test_xlat.log"` + +if (&Tmp-String-0 == '{ "foo" : "bar", "baz" : "boink" }, ') { + test_pass +} +else { + test_fail +} diff --git a/src/tests/unit/xlat/base.txt b/src/tests/unit/xlat/base.txt index 1b8bcd0980d..0d2dab7e052 100644 --- a/src/tests/unit/xlat/base.txt +++ b/src/tests/unit/xlat/base.txt @@ -324,5 +324,29 @@ match %(rpad:&User-Name 5 x) xlat %(rpad:&User-Name foo x) match ERROR offset 24: Failed parsing argument 1 as type 'uint64' +# +# Argument quoting +# +# The code here isn't great. If it's ever fixes to actually show the quoting +# then these should be correct +# +xlat %{md5:"arg"} +match %{md5:"arg"} + +xlat %{md5:"arg}"} +match %{md5:"arg}"} + +xlat %{md5:"arg} +match ERROR offset 12: Missing closing '"' + +xlat %{md5:"arg\""} +match %{md5:"arg\""} + +xlat %{md5:'arg'} +match %{md5:'arg'} + +xlat %{md5:'arg"'} +match %{md5:'arg"'} + count -match 187 +match 199