]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Replace vb->safe with vb->safe_for
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 26 Jan 2024 00:19:33 +0000 (18:19 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 26 Jan 2024 00:19:41 +0000 (18:19 -0600)
This is usually a pointer to a function used for escaping.  This is still only partially integrated and requires more work.

21 files changed:
src/bin/unit_test_attribute.c
src/lib/curl/all.mk.in
src/lib/curl/base.c
src/lib/curl/base.h
src/lib/curl/xlat.c [new file with mode: 0644]
src/lib/curl/xlat.h [new file with mode: 0644]
src/lib/server/tmpl_escape.h
src/lib/server/tmpl_eval.c
src/lib/server/tmpl_tokenize.c
src/lib/server/trigger.c
src/lib/unlang/xlat.h
src/lib/unlang/xlat_eval.c
src/lib/unlang/xlat_func.c
src/lib/unlang/xlat_func.h
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_tokenize.c
src/lib/util/value.c
src/lib/util/value.h
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_rest/rlm_rest.c
src/modules/rlm_sql/rlm_sql.c

index ec356f1dab2f87b652563f2a6c41b00b0b10208e..b0d9f49e65c45b5237ede319074528461924d0c2 100644 (file)
@@ -2913,7 +2913,7 @@ static size_t command_xlat_argv(command_result_t *result, command_file_ctx_t *cc
        char            buff[1024];
 
        slen = xlat_tokenize_argv(cc->tmp_ctx, &head, &FR_SBUFF_IN(in, input_len),
-                                 NULL,
+                                 NULL, NULL,
                                  &(tmpl_rules_t) {
                                          .attr = {
                                                  .dict_def = cc->tmpl_rules.attr.dict_def ?
index 70054f577479f2057613a2669b7a03f9c8776019..edb51b1f3e7858d1417f60c053a5b8ea844e20d9 100644 (file)
@@ -5,7 +5,7 @@ ifneq "$(TARGETNAME)" ""
 TARGET         := $(TARGETNAME)$(L)
 endif
 
-SOURCES                := base.c io.c
+SOURCES                := base.c io.c xlat.c
 
 SRC_CFLAGS     := @mod_cflags@
 
index a8767303181cc93aa7e28c8edd4e437de937994d..ad184d054b37441035b13265faca1576c8d5772e 100644 (file)
 #endif
 
 #include <freeradius-devel/util/talloc.h>
+#include <freeradius-devel/unlang/xlat_func.h>
 
 #include "attrs.h"
+#include "xlat.h"
 
 fr_dict_attr_t const *attr_tls_certificate;
 static fr_dict_t const *dict_freeradius; /*internal dictionary for server*/
@@ -197,6 +199,39 @@ int fr_curl_response_certinfo(request_t *request, fr_curl_io_request_t *randle)
        return 0;
 }
 
+/** Free the curl easy handle
+ *
+ * @param[in] arg              curl easy handle to free.
+ */
+static int _curl_tmpl_handle(void *arg)
+{
+       curl_easy_cleanup(arg);
+       return 0;
+}
+
+/** Return a thread local curl easy handle
+ *
+ * This should only be used for calls into libcurl functions
+ * which don't operate on an active request, like the
+ * escape/unescape functions.
+ *
+ * @return
+ *     - A thread local curl easy handle.
+ *     - NULL on failure.
+ */
+CURL *fr_curl_tmp_handle(void)
+{
+       static _Thread_local CURL       *t_candle;
+
+       if (unlikely(t_candle == NULL)) {
+               CURL *candle;
+
+               MEM(candle = curl_easy_init());
+               fr_atexit_thread_local(t_candle, _curl_tmpl_handle, candle);
+       }
+
+       return t_candle;
+}
 
 /** Initialise global curl options
  *
@@ -242,6 +277,16 @@ static int fr_curl_init(void)
 
        INFO("libcurl version: %s", curl_version());
 
+       {
+               xlat_t *xlat;
+
+               xlat = xlat_func_register(NULL, "uri.escape", fr_curl_xlat_uri_escape, FR_TYPE_STRING);
+               xlat_func_args_set(xlat, &fr_curl_xlat_uri_args);
+               xlat_func_safe_for_set(xlat, fr_curl_xlat_uri_escape);
+               xlat = xlat_func_register(NULL, "uri.unescape", fr_curl_xlat_uri_unescape, FR_TYPE_STRING);
+               xlat_func_args_set(xlat, &fr_curl_xlat_uri_args);
+       }
+
        return 0;
 }
 
@@ -253,6 +298,9 @@ static void fr_curl_free(void)
        fr_openssl_free();
 #endif
        curl_global_cleanup();
+
+       xlat_func_unregister("uri.escape");
+       xlat_func_unregister("uri.unescape");
 }
 
 /*
index aa2ec8513e18ea70692b5ad4015b767aa6fe14d0..ebda6f66dfa9fa95d80cb1560b656c012af9a169 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 #include <freeradius-devel/server/request.h>
 #include <freeradius-devel/util/event.h>
 #include <freeradius-devel/util/slab.h>
+#include <freeradius-devel/unlang/xlat.h>
 
 DIAG_OFF(DIAG_UNKNOWN_PRAGMAS)
 DIAG_OFF(disabled-macro-expansion)
@@ -138,6 +139,16 @@ int                        fr_curl_response_certinfo(request_t *request, fr_curl_io_request_t *randle
 
 int                    fr_curl_easy_tls_init (fr_curl_io_request_t *randle, fr_curl_tls_t const *conf);
 
+CURL                   *fr_curl_tmp_handle(void);
+
+xlat_action_t          fr_curl_xlat_uri_escape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+                                               UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request,
+                                               fr_value_box_list_t *in);
+
+xlat_action_t          fr_curl_xlat_uri_unescape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+                                                 UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request,
+                                                 fr_value_box_list_t *in);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/lib/curl/xlat.c b/src/lib/curl/xlat.c
new file mode 100644 (file)
index 0000000..5e80f4b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *   This program is is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or (at
+ *   your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file curl/xlat.c
+ * @brief Generic xlat functions dependent on libcurl
+ *
+ * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+
+#include <freeradius-devel/util/value.h>
+#include <freeradius-devel/unlang/xlat.h>
+#include <freeradius-devel/curl/base.h>
+
+#include "base.h"
+
+int fr_curl_xlat_refs = 0;
+
+xlat_arg_parser_t const fr_curl_xlat_uri_args[] = {
+       { .required = true, .concat = true, .type = FR_TYPE_STRING },
+       XLAT_ARG_PARSER_TERMINATOR
+};
+
+/** xlat function to escape URI encoded strings
+ *
+ */
+xlat_action_t fr_curl_xlat_uri_escape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+                                     UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request,
+                                     fr_value_box_list_t *in)
+{
+       fr_value_box_t  *to_escape = fr_value_box_list_head(in);
+       char            *escaped;
+
+       escaped = curl_easy_escape(fr_curl_tmp_handle(), to_escape->vb_strvalue, to_escape->vb_length);
+       if (!escaped) return -1;
+
+       /*
+        *      Returned string the same length - nothing changed
+        */
+       if (strlen(escaped) == to_escape->vb_length) {
+               curl_free(escaped);
+               return 0;
+       }
+
+       fr_value_box_clear_value(to_escape);
+       fr_value_box_strdup(to_escape, to_escape, NULL, escaped, to_escape->tainted);
+
+       curl_free(escaped);
+
+       fr_value_box_list_remove(in, to_escape);
+       fr_dcursor_insert(out, to_escape);
+
+       return XLAT_ACTION_FAIL;
+}
+
+/** xlat function to unescape URI encoded strings
+ *
+ */
+xlat_action_t fr_curl_xlat_uri_unescape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+                                       UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request,
+                                       fr_value_box_list_t *in)
+{
+       fr_value_box_t  *to_unescape = fr_value_box_list_head(in);
+       int             unescaped_len;
+       char            *unescaped;
+
+       fr_value_box_list_remove(in, to_unescape);
+
+       unescaped = curl_easy_unescape(fr_curl_tmp_handle(), to_unescape->vb_strvalue, to_unescape->vb_length, &unescaped_len);
+       if (!unescaped) {
+               talloc_free(to_unescape);
+               return XLAT_ACTION_FAIL;
+       }
+
+       /*
+        *      Returned string the same length - nothing changed
+        */
+       if ((size_t)unescaped_len == to_unescape->vb_length) {
+               curl_free(unescaped);
+               fr_dcursor_insert(out, to_unescape);
+               return XLAT_ACTION_DONE;
+       }
+
+       fr_value_box_clear_value(to_unescape);
+       fr_value_box_bstrndup(to_unescape, to_unescape, NULL, unescaped, unescaped_len, to_unescape->tainted);
+       curl_free(unescaped);
+       fr_dcursor_insert(out, to_unescape);
+
+       return XLAT_ACTION_DONE;
+}
diff --git a/src/lib/curl/xlat.h b/src/lib/curl/xlat.h
new file mode 100644 (file)
index 0000000..16ad2e2
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Generic xlat functions dependent on libcurl
+ *
+ * @file src/lib/curl/xlat.h
+ *
+ * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+RCSIDH(curl_xlat_h, "$Id$")
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <curl/curl.h>
+#include <freeradius-devel/unlang/xlat.h>
+
+extern xlat_arg_parser_t const fr_curl_xlat_uri_args;
+
+xlat_action_t          fr_curl_xlat_uri_escape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+                                               UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request,
+                                               fr_value_box_list_t *in);
+
+xlat_action_t          fr_curl_xlat_uri_unescape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
+                                                 UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request,
+                                                 fr_value_box_list_t *in);
+
+#ifdef __cplusplus
+}
+#endif
index 42faac73a50a4a94dc92ec433c3e7bf48cb89a37..8f12ebc363f1b46d3f554abfda21360715cb169c 100644 (file)
@@ -56,7 +56,9 @@ typedef void(*tmpl_escape_uctx_free_t)(void *uctx);
 /** When to apply escaping
  */
 typedef enum {
-       TMPL_ESCAPE_PRE_CONCAT = 0,                     //!< Pre-concatenation escaping is useful for
+       TMPL_ESCAPE_NONE = 0,                           //!< No escaping is performed.
+
+       TMPL_ESCAPE_PRE_CONCAT,                         //!< Pre-concatenation escaping is useful for
                                                        ///< DSLs where elements of the expansion are
                                                        ///< static, specified by the user, and other parts
                                                        ///< are dynamic, which may or may not need to be
@@ -78,6 +80,8 @@ typedef enum {
 typedef struct {
        fr_value_box_escape_t           func;           //!< How to escape when returned from evaluation.
                                                        ///< Currently only used for async evaluation.
+       fr_value_box_safe_for_t         safe_for;       //!< Value to set on boxes which have been escaped
+                                                       ///< by the #fr_value_box_escape_t function.
 
        tmpl_escape_mode_t              mode;           //!< Whether to apply escape function after
                                                        ///< concatenation, i.e. to the final output
index eb0cd84551487a73e60bb941bd5cf9395738c504..56a50081438ca345ee2a86961c5b7b93db75a6d0 100644 (file)
@@ -1358,7 +1358,11 @@ int tmpl_eval_cast_in_place(fr_value_box_list_t *list, request_t *request, tmpl_
 
                if (tmpl_escape_pre_concat(vpt)) {
                        uctx = tmpl_eval_escape_uctx_alloc(request, &vpt->rules.escape);
-                       if (unlikely(fr_value_box_list_escape_in_place(list, vpt->rules.escape.func, uctx) < 0)) {
+                       /*
+                        *      Sets escaped values, so boxes don't get re-escaped
+                        */
+                       if (unlikely(fr_value_box_list_escape_in_place(list, vpt->rules.escape.func,
+                                                                      vpt->rules.escape.safe_for, uctx) < 0)) {
                        error:
                                tmpl_eval_escape_uctx_free(&vpt->rules.escape, uctx);
                                return -1;
@@ -1410,7 +1414,22 @@ int tmpl_eval_cast_in_place(fr_value_box_list_t *list, request_t *request, tmpl_
         */
        if ((!did_concat && tmpl_escape_pre_concat(vpt)) || tmpl_escape_post_concat(vpt)) {
                uctx = tmpl_eval_escape_uctx_alloc(request, &vpt->rules.escape);
-               if (unlikely(fr_value_box_list_escape_in_place(list, vpt->rules.escape.func, uctx) < 0)) goto error;
+               if (unlikely(fr_value_box_list_escape_in_place(list, vpt->rules.escape.func,
+                                                              vpt->rules.escape.safe_for, uctx) < 0)) goto error;
+       }
+
+       /*
+        *      If there's no escape function, but there is
+        *      an escaped value, mark all the boxes up with
+        *      this value.
+        *
+        *      This is mostly useful for call_env usage in
+        *      modules where certain values are implicitly safe
+        *      for consumption, like SQL statements in the SQL
+        *      module.
+        */
+       if (!vpt->rules.escape.func && vpt->rules.escape.safe_for) {
+               fr_value_box_list_mark_safe_for(list, vpt->rules.escape.safe_for);
        }
 
        VALUE_BOX_LIST_VERIFY(list);
index 9ebf6c194966a4fac2e3dfd85445ced1d4abdf5a..689e4628eb59704998d90dc553225ff5fb54759d 100644 (file)
@@ -3321,7 +3321,7 @@ fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      FIXME - We need an ephemeral version of this
                 *      too.
                 */
-               slen = xlat_tokenize_argv(vpt, &head, &our_in, p_rules, t_rules, false, false);
+               slen = xlat_tokenize_argv(vpt, &head, &our_in, NULL, p_rules, t_rules, false, false);
                if ((slen <= 0) || !head) {
                        talloc_free(vpt);
                        FR_SBUFF_ERROR_RETURN(&our_in);
index 26f1f687071b669a1fa6f114ddc8286a0fdac66e..b3cf109b7c3851aa89ffdefcd25a6140260507b6 100644 (file)
@@ -430,7 +430,8 @@ int trigger_exec(unlang_interpret_t *intp,
        trigger->timeout = fr_time_delta_from_sec(5);   /* FIXME - Should be configurable? */
 
        slen = xlat_tokenize_argv(trigger, &trigger->xlat,
-                                 &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1), NULL, NULL, false, false);
+                                 &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1),
+                                 NULL, NULL, NULL, false, false);
        if (slen <= 0) {
                char *spaces, *text;
 
index 3ecf2ad7c1b8b7ab6cfccba3a95ff07bf097d71c..6d14aca27047ab26d210d99ebce7b25b2759b353 100644 (file)
@@ -152,6 +152,8 @@ typedef struct {
                                                        ///< tainted ones.
        fr_type_t                       type;           //!< Type to cast argument to.
        xlat_escape_func_t              func;           //!< Function to handle tainted values.
+       fr_value_box_safe_for_t         safe_for;       //!< Escaped value to set for boxes processed by
+                                                       ///< this escape function.
        void                            *uctx;          //!< Argument to pass to escape callback.
 } xlat_arg_parser_t;
 
@@ -392,6 +394,7 @@ fr_slen_t   xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sb
                                        fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
 
 fr_slen_t      xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
+                                  xlat_t const *xlat,
                                   fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr);
 
 fr_slen_t      xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
index 07a7f55d48ec254c99d7e009b85ef49aef9c3493..9dd48a413e10824dee54685397d9ae572aee0492 100644 (file)
@@ -221,10 +221,12 @@ static xlat_action_t xlat_process_arg_list(TALLOC_CTX *ctx, fr_value_box_list_t
 
 #define ESCAPE(_arg, _vb, _arg_num) \
 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); \
-               return XLAT_ACTION_FAIL; \
+       if ((_arg)->func && (!(_vb)->safe_for || !fr_value_box_is_safe_for((_vb), (_arg)->safe_for) || (_arg)->always_escape)) { \
+               if ((_arg)->func(request, _vb, (_arg)->uctx) < 0) { \
+                       RPEDEBUG("Function \"%s\" failed escaping argument %u", name, _arg_num); \
+                       return XLAT_ACTION_FAIL; \
+               } \
+               fr_value_box_mark_safe_for((_vb), (_arg)->safe_for); \
        } \
 } while (0)
 
@@ -520,6 +522,7 @@ bool xlat_process_return(request_t *request, xlat_t const *func, fr_value_box_li
                        /* We are not forgiving for debug builds */
                        fr_assert_fail("Treating invalid return type as fatal");
                }
+               fr_value_box_mark_safe_for(pos, func->return_safe_for); /* Always set this */
                count++;
        } while ((pos = fr_value_box_list_next(returned, pos)));
 
@@ -845,6 +848,7 @@ xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_dcursor_t *out,
 
        return xa;
 }
+
 /** Process the result of a previous nested expansion
  *
  * @param[in] ctx              to allocate value boxes in.
@@ -1305,7 +1309,7 @@ static ssize_t xlat_eval_sync(TALLOC_CTX *ctx, char **out, request_t *request, x
                                }
 
                                len = vb->vb_length * 3;
-                               escaped = talloc_array(pool, char, len);
+                               MEM(escaped = talloc_array(pool, char, len));
                                real_len = escape(request, escaped, len, vb->vb_strvalue, UNCONST(void *, escape_ctx));
 
                                entry = vb->entry;
index cb9b1f9edf95e64c0edc7132108b771755e2a584..ffbc950e23971e1e92ee3e6ebb799a664f9c2b95 100644 (file)
@@ -439,6 +439,16 @@ void xlat_purify_func_set(xlat_t *xlat, xlat_purify_t func)
        xlat->purify = func;
 }
 
+/** Set the escaped values for output boxes
+ *
+ * @param[in] xlat             function to set the escaped value for (as returned by xlat_register).
+ * @param[in] safe_for         escaped value to write to output boxes.
+ */
+void _xlat_func_safe_for_set(xlat_t *xlat, fr_value_box_safe_for_t safe_for)
+{
+       xlat->return_safe_for = safe_for;
+}
+
 /** Set global instantiation/detach callbacks
  *
  * @param[in] xlat             to set instantiation callbacks for.
index 565cb7be0e420fe5ecc6b6c3ae51b96ed85da920..4fc69b1c01dfd0010865a7a72cbe905d0dd27d37 100644 (file)
@@ -72,6 +72,14 @@ void         xlat_func_resolve_set(xlat_t *xlat, xlat_resolve_t func);
 
 void           xlat_purify_func_set(xlat_t *xlat, xlat_purify_t func);
 
+/** Set the escaped values for output boxes
+ *
+ * @param[in] _xlat            function to set the escaped value for (as returned by xlat_register).
+ * @param[in] _escaped         escaped value to write to output boxes.
+ */
+#define                xlat_func_safe_for_set(_xlat, _escaped) _xlat_func_safe_for_set(_xlat, (uintptr_t) (_escaped))
+void           _xlat_func_safe_for_set(xlat_t *xlat, uintptr_t escaped);
+
 /** Set a callback for global instantiation of xlat functions
  *
  * @param[in] _xlat            function to set the callback for (as returned by xlat_register).
index 4d1c7dc9ad5458f19b8dcfd80685f63c5e245672..7a656094602c13d0f493f2ab50f5f3fa1e8bc44e 100644 (file)
@@ -92,6 +92,7 @@ typedef struct xlat_s {
                                                        ///< xlat.  Typically used for xlats which refer to tmpls
                                                        ///< in their module config.
 
+       fr_value_box_safe_for_t return_safe_for;        //!< Escaped value to set in output boxes.
        fr_type_t               return_type;            //!< Function is guaranteed to return one or more boxes
                                                        ///< of this type.  If the return type is FR_TYPE_VOID
                                                        ///< then the xlat function can return any type of output.
index 231f72ba45ed796fff02ab044f65233e661b88ce..aba71092bebe7465e59d68ef0bed1e4c62f202a5 100644 (file)
@@ -25,6 +25,7 @@
  * @copyright 2000,2006 The FreeRADIUS server project
  */
 
+#include "lib/util/value.h"
 RCSID("$Id$")
 
 #include <freeradius-devel/util/debug.h>
@@ -111,7 +112,7 @@ static fr_sbuff_parse_rules_t const xlat_new_arg_rules = {
 };
 
 static int xlat_tokenize_input(xlat_exp_head_t *head, fr_sbuff_t *in,
-                               fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
+                               fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_value_box_safe_for_t safe_for);
 
 #ifdef HAVE_REGEX
 /** Parse an xlat reference
@@ -285,8 +286,7 @@ int xlat_validate_function_args(xlat_exp_t *node)
  *     - 0 if the string was parsed into a function.
  *     - <0 on parse error.
  */
-int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
-                               tmpl_rules_t const *t_rules)
+int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in, tmpl_rules_t const *t_rules)
 {
        xlat_exp_t              *node;
        xlat_t                  *func;
@@ -355,7 +355,7 @@ int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
         *      Now parse the child nodes that form the
         *      function's arguments.
         */
-       if (xlat_tokenize_argv(node, &node->call.args, in, &xlat_multi_arg_rules, t_rules, false, false) < 0) {
+       if (xlat_tokenize_argv(node, &node->call.args, in, func, &xlat_multi_arg_rules, t_rules, false, false) < 0) {
                goto error;
        }
        xlat_flags_merge(&node->flags, &node->call.args->flags);
@@ -500,7 +500,8 @@ static int xlat_tokenize_function_new(xlat_exp_head_t *head, fr_sbuff_t *in, tmp
         *      Now parse the child nodes that form the
         *      function's arguments.
         */
-       if (xlat_tokenize_argv(node, &node->call.args, in, &xlat_new_arg_rules, t_rules, true, (node->call.input_type == XLAT_INPUT_MONO)) < 0) {
+       if (xlat_tokenize_argv(node, &node->call.args, in, func,
+                              &xlat_new_arg_rules, t_rules, true, (node->call.input_type == XLAT_INPUT_MONO)) < 0) {
 error:
                talloc_free(node);
                return -1;
@@ -889,12 +890,14 @@ check_for_attr:
  * @param[in] in               sbuff to parse.
  * @param[in] p_rules          that control parsing.
  * @param[in] t_rules          that control attribute reference and xlat function parsing.
+ * @param[in] safe_for         mark up literal values as being pre-escaped.  May be merged
+ *                             with t_rules in future.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
 static int xlat_tokenize_input(xlat_exp_head_t *head, fr_sbuff_t *in,
-                              fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+                              fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_value_box_safe_for_t safe_for)
 {
        xlat_exp_t                      *node = NULL;
        fr_slen_t                       slen;
@@ -944,6 +947,7 @@ static int xlat_tokenize_input(xlat_exp_head_t *head, fr_sbuff_t *in,
                do_value_box:
                        xlat_exp_set_name_buffer_shallow(node, str);
                        fr_value_box_strdup(node, &node->data, NULL, str, false);
+                       fr_value_box_mark_safe_for(&node->data, safe_for);
                        node->flags.constant = true;
                        fr_assert(node->flags.pure);
 
@@ -1379,6 +1383,7 @@ ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_head_t const *head, fr_sbuff_escape
  *                             later.
  * @param[out] out             the head of the xlat list / tree structure.
  * @param[in] in               the format string to expand.
+ * @param[in] xlat             we're tokenizing arguments for.
  * @param[in] p_rules          controlling how to parse the string outside of
  *                             any expansions.
  * @param[in] t_rules          controlling how attribute references are parsed.
@@ -1389,15 +1394,24 @@ ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_head_t const *head, fr_sbuff_escape
  *     - >0  on success which is the number of characters parsed.
  */
 fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
+                            xlat_t const *xlat,
                             fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr)
 {
        int                             argc = 0;
        fr_sbuff_t                      our_in = FR_SBUFF(in);
        ssize_t                         slen;
        fr_sbuff_marker_t               m;
-       fr_sbuff_parse_rules_t const    *our_p_rules;   /* Bareword parse rules */
+       fr_sbuff_parse_rules_t const    *our_p_rules;           /* Bareword parse rules */
        fr_sbuff_parse_rules_t          tmp_p_rules;
        xlat_exp_head_t                 *head;
+       xlat_arg_parser_t const         *arg = NULL;
+
+       if (xlat && xlat->args) {
+               arg = xlat->args;       /* Track the arguments as we parse */
+       } else {
+               static xlat_arg_parser_t        default_arg = { .variadic = XLAT_ARG_VARIADIC_EMPTY_SQUASH };
+               arg = &default_arg;
+       }
 
        MEM(head = xlat_exp_head_alloc(ctx));
        if (p_rules && p_rules->terminals) {
@@ -1468,7 +1482,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
                        }
 
                        if (xlat_tokenize_input(node->group, &our_in,
-                                               our_p_rules, t_rules) < 0) {
+                                               our_p_rules, t_rules, arg->safe_for) < 0) {
                        error:
                                if (our_p_rules != &value_parse_rules_bareword_quoted) {
                                        talloc_const_free(our_p_rules->terminals);
@@ -1486,7 +1500,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
                        XLAT_DEBUG("ARGV double quotes <-- %.*s", (int) fr_sbuff_remaining(&our_in), fr_sbuff_current(&our_in));
 
                        if (xlat_tokenize_input(node->group, &our_in,
-                                               &value_parse_rules_double_quoted, t_rules) < 0) goto error;
+                                               &value_parse_rules_double_quoted, t_rules, arg->safe_for) < 0) goto error;
                        break;
 
                /*
@@ -1507,6 +1521,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
 
                        xlat_exp_set_name_buffer_shallow(child, str);
                        fr_value_box_strdup(child, &child->data, NULL, str, false);
+                       fr_value_box_mark_safe_for(&child->data, arg->safe_for);        /* Literal values are treated as implicitly safe */
                        child->flags.constant = true;
                        fr_assert(child->flags.pure);
                        xlat_exp_insert_tail(node->group, child);
@@ -1576,6 +1591,14 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
                        fr_strerror_const("Unexpected text after argument");
                        goto error;
                }
+
+               if (!arg->variadic) {
+                       arg++;
+                       if (arg->type == FR_TYPE_NULL) {
+                               fr_strerror_printf("Too many arguments, expected %u", argc - 1);
+                               goto error;
+                       }
+               }
        }
 
        if (our_p_rules != &value_parse_rules_bareword_quoted) talloc_const_free(our_p_rules->terminals);
@@ -1613,7 +1636,7 @@ fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
 
        fr_strerror_clear();    /* Clear error buffer */
 
-       if (xlat_tokenize_input(head, &our_in, p_rules, t_rules) < 0) {
+       if (xlat_tokenize_input(head, &our_in, p_rules, t_rules, 0) < 0) {
                talloc_free(head);
                FR_SBUFF_ERROR_RETURN(&our_in);
        }
index e2c0ac3237af0cd19e9697b24f1bc97242108151..f1141e65c30e9d3b91944e787c831b3102b2fcfd 100644 (file)
@@ -621,8 +621,8 @@ static inline void fr_value_box_copy_meta(fr_value_box_t *dst, fr_value_box_t co
        dst->enumv = src->enumv;
        dst->type = src->type;
        dst->tainted = src->tainted;
+       dst->safe_for = src->safe_for;
        dst->secret = src->secret;
-       dst->safe = src->safe;
        fr_value_box_list_entry_init(dst);
 }
 
@@ -5866,22 +5866,33 @@ int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx,
  *
  * @param[in] vb               to escape.
  * @param[in] escape           function to apply to the value box.
+ * @param[in] safe_for         the escaped value to check value boxes again.
+ *                             box has an escaped value that matches, it will
+ *                             not be re-escaped.
  * @param[in] uctx             user context to pass to the escape function.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
-int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t escape, void *uctx)
+int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t escape,
+                                fr_value_box_safe_for_t safe_for, void *uctx)
 {
+       int ret;
+
        switch (vb->type) {
        case FR_TYPE_GROUP:
-               return fr_value_box_list_escape_in_place(&vb->vb_group, escape, uctx);
+               return fr_value_box_list_escape_in_place(&vb->vb_group, escape, safe_for, uctx);
 
        default:
                break;
        }
 
-       return escape(vb, uctx);
+       ret = escape(vb, uctx);
+       if (unlikely(ret < 0)) return ret;
+
+       vb->safe_for = safe_for;
+
+       return 0;
 }
 
 /** Escape a list of value boxes in place
@@ -5892,17 +5903,21 @@ int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t escap
  *
  * @param[in] list             to escape.
  * @param[in] escape           function to apply to the value box.
+ * @param[in] safe_for         the escaped value to check value boxes again.
+ *                             box has an escaped value that matches, it will
+ *                             not be re-escaped.
  * @param[in] uctx             user context to pass to the escape function.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
-int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t escape, void *uctx)
+int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t escape,
+                                     fr_value_box_safe_for_t safe_for, void *uctx)
 {
        int ret = 0;
 
        fr_value_box_list_foreach(list, vb) {
-               ret = fr_value_box_escape_in_place(vb, escape, uctx);
+               ret = fr_value_box_escape_in_place(vb, escape, safe_for, uctx);
                if (unlikely(ret < 0)) return ret;
        }
 
@@ -6205,34 +6220,31 @@ void fr_value_box_list_verify(char const *file, int line, fr_value_box_list_t co
 
 /** Mark a value-box as "safe", of a particular type.
  *
- *  This means that users of that data who understand this particular value of the "safe" flag
- *  can then ignore the "tainted" flag, and use the value as if it was untainted.  Every other user
- *  of the data must still treat it as tainted.
- *
- *  Tainted data can be marked "safe".  But marking it "safe" does not remove the "tainted" flag.
- *
- *  Once data is marked safe, it cannot be marked as a different type of "safe".
  */
-int fr_value_box_mark_safe(fr_value_box_t *box, uint16_t safe)
+void _fr_value_box_mark_safe_for(fr_value_box_t *vb, fr_value_box_safe_for_t safe_for)
 {
-       if (box->safe == safe) return 0;
-
-       if (box->safe != 0) {
-               fr_strerror_const("Data was already marked 'safe', of a different type");
-               return -1;
-       }
-
-       box->safe = safe;
-       return 0;
+       vb->safe_for = safe_for;
 }
 
 /** Mark a value-box as "unsafe"
  *
  *  This always succeeds, and there are no side effects.
  */
-void fr_value_box_mark_unsafe(fr_value_box_t *box)
+void fr_value_box_mark_unsafe(fr_value_box_t *vb)
+{
+       vb->safe_for = 0;
+}
+
+/** Set the escaped flag for all value boxes in a list
+ *
+ * @note Only operates on a single level.
+ *
+ * @param[in] list     to operate on.
+ * @param[in] safe_for value to set.
+ */
+void fr_value_box_list_mark_safe_for(fr_value_box_list_t *list, fr_value_box_safe_for_t safe_for)
 {
-       box->safe = 0;
+       fr_value_box_list_foreach(list, vb) vb->safe_for = safe_for;
 }
 
 /** Check truthiness of values.
index f6764067b4cfd5c9bdf85ed8d945dacd8b80f21c..d2901a73352c08c391af3ad99bc7ff888b276ada 100644 (file)
@@ -146,6 +146,14 @@ typedef union {
        fr_value_box_list_t                     children;               //!< for groups
 } fr_value_box_datum_t;
 
+/** Escaping that's been applied to a value box
+ *
+ * This should be a unique value for each dialect being escaped.  If the value is 0,
+ * then the box is not escaped.  If the escaped value matches the escaped value of
+ * the function performing the escaping then it should not be re-escaped.
+ */
+typedef uintptr_t fr_value_box_safe_for_t;
+
 /** Union containing all data types supported by the server
  *
  * This union contains all data types that can be represented by fr_pair_ts. It may also be used in other parts
@@ -164,8 +172,12 @@ struct value_box_s {
        unsigned int                            secret : 1;             //!< Same as #fr_dict_attr_flags_t secret
        unsigned int                            immutable : 1;          //!< once set, the value cannot be changed
        unsigned int                            talloced : 1;           //!< Talloced, not stack or text allocated.
-
-       uint16_t                _CONST          safe;                   //!< more detailed safety
+       fr_value_box_safe_for_t _CONST          safe_for;               //!< A unique value to indicate if that value box is safe
+                                                                       ///< for consumption by a particular module for a particular
+                                                                       ///< purpose.  e.g. LDAP, SQL, etc.
+                                                                       ///< Usually set by the xlat framework on behalf of an xlat
+                                                                       ///< escaping function, and checked by a #fr_value_box_escape_t
+                                                                       ///< to see if it needs to operate.
 
        fr_value_box_entry_t                    entry;                  //!< Doubly linked list entry.
 
@@ -180,14 +192,6 @@ struct value_box_s {
 #endif
 };
 
-/** Macro to automatically define a value for the "safe" field based on the current module / library.
- *
- * Functions which escape tainted data can mark it "safe" for a
- * particular purpose.  Each module has it's own version of safety.
- * e.g. LDAP, SQL, etc.  Each module can then manage its own list of sub-types for safety.
- */
-#define FR_VALUE_BOX_SAFE(_x) ((LOG_ID_LIB << 8) | _x)
-
 /** @name List and cursor function definitions
  */
 FR_DLIST_FUNCS(fr_value_box_list, fr_value_box_t, entry)
@@ -633,9 +637,11 @@ fr_value_box_t *_fr_value_box_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, fr_typ
   */
 typedef int (*fr_value_box_escape_t)(fr_value_box_t *vb, void *uctx);
 
-int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t escape, void *uctx)
+int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t escape,
+                                fr_value_box_safe_for_t escaped, void *uctx)
                                 CC_HINT(nonnull(1,2));
-int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t escape, void *uctx)
+int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t escape,
+                                     fr_value_box_safe_for_t escaped, void *uctx)
                                      CC_HINT(nonnull(1,2));
 /** @} */
 
@@ -1026,20 +1032,17 @@ int             fr_value_box_ipaddr(fr_value_box_t *dst, fr_dict_attr_t const *enumv,
 int            fr_value_unbox_ipaddr(fr_ipaddr_t *dst, fr_value_box_t *src)
                CC_HINT(nonnull);
 
-static inline CC_HINT(nonnull, always_inline)
-bool fr_value_box_is_safe(fr_value_box_t const *box, uint16_t safe)
-{
-       if (!safe) return false;
-
-       return (box->safe == safe);
-}
-
-int            fr_value_box_mark_safe(fr_value_box_t *box, uint16_t safe)
+#define                fr_value_box_mark_safe_for(_box, _safe_for) _fr_value_box_mark_safe_for(_box, (fr_value_box_safe_for_t)_safe_for)
+void           _fr_value_box_mark_safe_for(fr_value_box_t *box, fr_value_box_safe_for_t safe_for)
                CC_HINT(nonnull);
 
 void           fr_value_box_mark_unsafe(fr_value_box_t *box)
                CC_HINT(nonnull);
 
+#define                fr_value_box_is_safe_for(_box, _safe_for) (_box->safe_for == (fr_value_box_safe_for_t)_safe_for)
+
+void           fr_value_box_list_mark_safe_for(fr_value_box_list_t *list, fr_value_box_safe_for_t safe_for);
+
 static inline CC_HINT(nonnull, always_inline)
 bool fr_value_box_is_secret(fr_value_box_t const *box)
 {
index a64c3a6e6070af2ac5306d8a299af0995afd0473..19f10472d05a0f5f0c98f61879071e458302190e 100644 (file)
@@ -27,6 +27,7 @@
  * @copyright 2012 Alan DeKok (aland@freeradius.org)
  * @copyright 1999-2013 The FreeRADIUS Server Project.
  */
+#include "lib/util/value.h"
 RCSID("$Id$")
 
 USES_APPLE_DEPRECATED_API
@@ -370,7 +371,7 @@ static xlat_action_t ldap_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
        /*
         *      If it's already safe, just copy it over.
         */
-       if (in_vb->safe == FR_VALUE_BOX_SAFE(1)) {
+       if (fr_value_box_is_safe_for(in_vb, ldap_escape_xlat)) {
                fr_value_box_copy(vb, vb, in_vb);
 
                fr_dcursor_append(out, vb);
@@ -397,7 +398,7 @@ static xlat_action_t ldap_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
         */
        fr_sbuff_trim_talloc(&sbuff, len);
        fr_value_box_strdup_shallow(vb, NULL, fr_sbuff_buff(&sbuff), in_vb->tainted);
-       fr_value_box_mark_safe(vb, FR_VALUE_BOX_SAFE(1));
+       fr_value_box_mark_safe_for(vb, ldap_escape_xlat);
 
        fr_dcursor_append(out, vb);
        return XLAT_ACTION_DONE;
@@ -453,7 +454,7 @@ static int uri_part_escape(fr_value_box_t *vb, UNUSED void *uctx)
        /*
         *      If it's already safe, don't do anything.
         */
-       if (vb->safe == FR_VALUE_BOX_SAFE(1)) return 0;
+       if (fr_value_box_is_safe_for(vb, uri_part_escape)) return 0;
 
        /*
         *      Maximum space needed for output would be 3 times the input if every
@@ -472,7 +473,7 @@ static int uri_part_escape(fr_value_box_t *vb, UNUSED void *uctx)
        fr_sbuff_trim_talloc(&sbuff, len);
        fr_value_box_clear_value(vb);
        fr_value_box_strdup_shallow(vb, NULL, fr_sbuff_buff(&sbuff), vb->tainted);
-       fr_value_box_mark_safe(vb, FR_VALUE_BOX_SAFE(1));
+       fr_value_box_mark_safe_for(vb, uri_part_escape);
 
        return 0;
 }
index 5f40300bfbc3e8f13219faaa85d6a3a8e2f5dcd8..48742b76f0d816791fd5569d4a16ea755434c95f 100644 (file)
@@ -35,13 +35,16 @@ RCSID("$Id$")
 #include <freeradius-devel/server/tmpl.h>
 #include <freeradius-devel/server/tmpl_escape.h>
 #include <freeradius-devel/server/pairmove.h>
+#include <freeradius-devel/server/log.h>
 #include <freeradius-devel/tls/base.h>
 #include <freeradius-devel/util/atexit.h>
 #include <freeradius-devel/util/debug.h>
 #include <freeradius-devel/util/table.h>
 #include <freeradius-devel/util/uri.h>
+#include <freeradius-devel/util/value.h>
 #include <freeradius-devel/unlang/call_env.h>
 #include <freeradius-devel/unlang/xlat_func.h>
+#include <freeradius-devel/unlang/xlat.h>
 
 #include "rest.h"
 
@@ -212,7 +215,8 @@ static const call_env_method_t _var = { \
                                                                                                        .uctx = rest_uri_parts \
                                                                                                } , \
                                                                                                .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC\
-                                                                                       } \
+                                                                                       }, \
+                                                                                       .safe_for = (fr_value_box_safe_for_t)fr_curl_xlat_uri_escape \
                                                                                      }}, /* Do not concat */ \
                                                                REST_CALL_ENV_REQUEST_COMMON(_dflt_username, _dflt_password) \
                                                                CALL_ENV_TERMINATOR \
@@ -356,17 +360,6 @@ static void *uri_part_escape_uctx_alloc(UNUSED request_t *request, void const *u
        return t_ctx;
 }
 
-
-/** Free the curl easy handle
- *
- * @param[in] arg              curl easy handle to free.
- */
-static int _uri_part_escape_free_on_exit(void *arg)
-{
-       curl_easy_cleanup(arg);
-       return 0;
-}
-
 /** URL escape a single box forming part of a URL
  *
  * @param[in] vb               to escape
@@ -377,21 +370,9 @@ static int _uri_part_escape_free_on_exit(void *arg)
  */
 static int uri_part_escape(fr_value_box_t *vb, UNUSED void *uctx)
 {
-       static _Thread_local CURL       *t_candle;
        char                            *escaped;
 
-       /*
-        *      libcurl doesn't actually use the handle, but we pass one
-        *      in anyway, just in case it does in the future.
-        */
-       if (unlikely(t_candle == NULL)) {
-               CURL *candle;
-
-               MEM(candle = curl_easy_init());
-               fr_atexit_thread_local(t_candle, _uri_part_escape_free_on_exit, candle);
-       }
-
-       escaped = curl_easy_escape(t_candle, vb->vb_strvalue, vb->vb_length);
+       escaped = curl_easy_escape(fr_curl_tmp_handle(), vb->vb_strvalue, vb->vb_length);
        if (!escaped) return -1;
 
        /*
@@ -761,7 +742,10 @@ static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, mod
        void                            *handle;
        int                             ret;
 
-       if (!section->name) RETURN_MODULE_NOOP;
+       if (!section->name) {
+               RDEBUG2("No authorize section configured");
+               RETURN_MODULE_NOOP;
+       }
 
        handle = rest_slab_reserve(t->slab);
        if (!handle) RETURN_MODULE_FAIL;
@@ -870,7 +854,10 @@ static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result,
 
        int                             ret;
 
-       if (!section->name) RETURN_MODULE_NOOP;
+       if (!section->name) {
+               RDEBUG2("No authentication section configured");
+               RETURN_MODULE_NOOP;
+       }
 
        /*
         *      We can only authenticate user requests which HAVE
@@ -976,7 +963,10 @@ static unlang_action_t CC_HINT(nonnull) mod_accounting(rlm_rcode_t *p_result, mo
        void                            *handle;
        int                             ret;
 
-       if (!section->name) RETURN_MODULE_NOOP;
+       if (!section->name) {
+               RDEBUG2("No accounting section configured");
+               RETURN_MODULE_NOOP;
+       }
 
        handle = rest_slab_reserve(t->slab);
        if (!handle) RETURN_MODULE_FAIL;
@@ -1051,7 +1041,10 @@ static unlang_action_t CC_HINT(nonnull) mod_post_auth(rlm_rcode_t *p_result, mod
        void                            *handle;
        int                             ret;
 
-       if (!section->name) RETURN_MODULE_NOOP;
+       if (!section->name) {
+               RDEBUG2("No post-auth section configured");
+               RETURN_MODULE_NOOP;
+       }
 
        handle = rest_slab_reserve(t->slab);
        if (!handle) RETURN_MODULE_FAIL;
index 3e8f3a4eda865f45ea34e6f8dda2b9d2b01e0db9..32e81734afa43623222b6c55401c3f3cf7933fbd 100644 (file)
  * @copyright 2000 Mike Machado (mike@innercite.com)
  * @copyright 2000 Alan DeKok (aland@freeradius.org)
  */
+
 RCSID("$Id$")
 
 #define LOG_PREFIX mctx->inst->name
 
-#include <ctype.h>
-
 #include <freeradius-devel/server/base.h>
 #include <freeradius-devel/server/exfile.h>
 #include <freeradius-devel/server/map_proc.h>
@@ -196,7 +195,7 @@ static int sql_xlat_escape(request_t *request, fr_value_box_t *vb, void *uctx)
        /*
         *      If it's already safe, don't do anything.
         */
-       if (vb->safe == FR_VALUE_BOX_SAFE(inst->driver->number)) return 0;
+       if (fr_value_box_is_safe_for(vb, inst->driver)) return 0;
 
        handle = fr_pool_connection_get(inst->pool, request);
        if (!handle) {
@@ -234,7 +233,7 @@ static int sql_xlat_escape(request_t *request, fr_value_box_t *vb, void *uctx)
         *      safe value.  This means that we don't
         *      cross-contaminate "safe" values across databases.
         */
-       fr_value_box_mark_safe(vb, FR_VALUE_BOX_SAFE(inst->driver->number));
+       fr_value_box_mark_safe_for(vb, inst->driver);
        vb->entry = entry;
 
        fr_pool_connection_release(inst->pool, request, handle);
@@ -248,7 +247,7 @@ static int sql_xlat_escape(request_t *request, fr_value_box_t *vb, void *uctx)
  * be returned instead.
  *
 @verbatim
-%{sql:<sql statement>}
+%sql(<sql statement>)
 @endverbatim
  *
  * @ingroup xlat_functions