From: Arran Cudbard-Bell Date: Mon, 15 Mar 2021 21:38:54 +0000 (+0000) Subject: Add support for escaping xlat arguments X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=25f201a3565495886fa20363d33d155947a930bd;p=thirdparty%2Ffreeradius-server.git Add support for escaping xlat arguments --- diff --git a/src/lib/unlang/xlat.h b/src/lib/unlang/xlat.h index 1f1a501b561..9f3264ea4c0 100644 --- a/src/lib/unlang/xlat.h +++ b/src/lib/unlang/xlat.h @@ -98,13 +98,14 @@ extern size_t xlat_action_table_len; /** A function used to escape an argument passed to an xlat * + * @param[in] request being processed. Used mostly for debugging. * @param[in,out] vb to escape * @param[in] uctx a "context" for the escaping * @return * - 0 on success. * - -1 on failure. */ -typedef int (*xlat_escape_func_t)(fr_value_box_t *vb, void *uctx); +typedef int (*xlat_escape_func_t)(request_t *request, fr_value_box_t *vb, void *uctx); /** Definition for a single argument consumend by an xlat function * @@ -115,6 +116,8 @@ typedef struct { bool single; //!< Argument must only contain a single box bool variadic; //!< All additional boxes should be processed ///< using this definition. + bool always_escape; //!< Pass all arguments to escape function not just + ///< tainted ones. fr_type_t type; //!< Type to cast argument to. xlat_escape_func_t func; //!< Function to handle tainted values. void *uctx; //!< Arcument to escape callback. diff --git a/src/lib/unlang/xlat_eval.c b/src/lib/unlang/xlat_eval.c index a516537c7f6..c2ee38da399 100644 --- a/src/lib/unlang/xlat_eval.c +++ b/src/lib/unlang/xlat_eval.c @@ -237,6 +237,16 @@ static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, fr_value_box_list_t xlat_arg_parser_t const *arg, unsigned int arg_num) { fr_value_box_t *vb; + +#define DO_ESCAPE(_arg, _vb, _arg_num) \ +do { \ + if ((_arg)->func && ((_vb)->tainted || (_arg)->always_escape) && \ + ((_arg)->func(request, _vb, (_arg)->uctx) < 0)) { \ + RPEDEBUG("Failed escaping argument %u", _arg_num); \ + return XLAT_ACTION_FAIL; \ + } \ +} while (0) + if (!fr_dlist_empty(list)) { if (arg->required) { RPEDEBUG("Missing required argument %u", arg_num); @@ -245,10 +255,14 @@ static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, fr_value_box_list_t return XLAT_ACTION_DONE; } - // *todo* make this escape tainted value boxes vb = fr_dlist_head(list); if (arg->concat) { + if (arg->func) { + for (; vb; vb = fr_dlist_next(list, vb)) DO_ESCAPE(arg, vb, arg_num); + + vb = fr_dlist_head(list); /* Reset */ + } /* * Concatenate child boxes, casting to desired type, * then replace group vb with first child vb @@ -274,6 +288,9 @@ static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, fr_value_box_list_t fr_dlist_num_elements(list)); return XLAT_ACTION_FAIL; } + + DO_ESCAPE(arg, vb, arg_num); + if ((arg->type != FR_TYPE_VOID) && (vb->type != arg->type)) { cast_error: if (fr_value_box_cast_in_place(ctx, vb, @@ -292,6 +309,8 @@ static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, fr_value_box_list_t * cast all child values to the required type. */ do { + DO_ESCAPE(arg, vb, arg_num); + if (vb->type == arg->type) continue; if (fr_value_box_cast_in_place(ctx, vb, arg->type, NULL) < 0) goto cast_error;