]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add support for escaping xlat arguments
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 15 Mar 2021 21:38:54 +0000 (21:38 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 15 Mar 2021 21:39:04 +0000 (21:39 +0000)
src/lib/unlang/xlat.h
src/lib/unlang/xlat_eval.c

index 1f1a501b561d4869247f9e7b0863b85b749c88c4..9f3264ea4c0135262004de7c7be4a368d1b9c46d 100644 (file)
@@ -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.
index a516537c7f64138a1ee15fb37ee246dc5f78b0bd..c2ee38da399dc18bca67f5b3ff788d1b9b2aa5d8 100644 (file)
@@ -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;