/** 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
*
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.
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);
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
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,
* 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;