]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
update for string expansions on RHS of SQL
authorAlan T. DeKok <aland@freeradius.org>
Thu, 21 Dec 2023 12:56:10 +0000 (07:56 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 21 Dec 2023 12:56:10 +0000 (07:56 -0500)
and add tests

src/lib/server/map.c
src/lib/server/map.h
src/modules/rlm_sql/sql.c
src/tests/modules/sql_sqlite/xlat.attrs [new file with mode: 0644]
src/tests/modules/sql_sqlite/xlat.unlang [new file with mode: 0644]

index b9631f1f8603443b9edac867a2661ce6b6a3b8df..77df3f724d8b7c47e94588fabb9cd9c7e31771b4 100644 (file)
@@ -35,6 +35,8 @@ RCSID("$Id$")
 #include <freeradius-devel/server/tmpl.h>
 #include <freeradius-devel/server/tmpl_dcursor.h>
 
+#include <freeradius-devel/unlang/interpret.h>
+
 #include <freeradius-devel/util/debug.h>
 #include <freeradius-devel/util/base16.h>
 #include <freeradius-devel/util/pair_legacy.h>
@@ -2429,6 +2431,7 @@ void map_debug_log(request_t *request, map_t const *map, fr_pair_t const *vp)
  *
  * @param[in] ctx              where to allocate the map.
  * @param[out] out             Where to write the new map (must be freed with talloc_free()).
+ * @param[in] request          the request
  * @param[in] lhs              of map
  * @param[in] op               of map
  * @param[in] rhs              of map
@@ -2438,7 +2441,7 @@ void map_debug_log(request_t *request, map_t const *map, fr_pair_t const *vp)
  *     - 0 on success.
  *     - -1 on failure.
  */
-int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, char const *lhs, char const *op, char const *rhs,
+int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, request_t *request, char const *lhs, char const *op, char const *rhs,
                     tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
 {
        ssize_t slen;
@@ -2496,6 +2499,7 @@ int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, char const *lhs, char const *
 
        my_rules = *rhs_rules;
        my_rules.at_runtime = true;
+       my_rules.xlat.runtime_el = unlang_interpret_event_list(request);
        my_rules.enumv = tmpl_attr_tail_da(map->lhs);
 
        /*
@@ -2519,12 +2523,36 @@ int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, char const *lhs, char const *
                goto parse_quoted;
 
        } else if (rhs[0] == '\'') {
+               size_t len;
+
                quote = T_SINGLE_QUOTED_STRING;
 
        parse_quoted:
-               slen = tmpl_afrom_substr(map, &map->rhs, &FR_SBUFF_IN(rhs, strlen(rhs)),
+               len = strlen(rhs + 1);
+               if (len == 1) {
+                       if (rhs[1] != rhs[0]) {
+                               fr_strerror_const("Invalid string on right side");
+                               return -1;
+                       }
+
+                       rhs = "";
+                       goto alloc_empty;
+               }
+
+               slen = tmpl_afrom_substr(map, &map->rhs, &FR_SBUFF_IN(rhs + 1, len - 1),
                                         quote, value_parse_rules_quoted[quote], &my_rules);
-               if (slen <= 0) goto error;
+               if (slen < 0) goto error;
+
+               if (slen == 0) {
+                       rhs = "";
+                       goto alloc_empty;
+               }
+
+               ERROR("CONVERT %s --> %s", rhs, map->rhs->name);
+
+               /*
+                *      Ignore any extra data after the string.
+                */
 
        } else if (rhs[0] == '&') {
                /*
@@ -2539,8 +2567,10 @@ int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, char const *lhs, char const *
                if (slen <= 0) goto error;
 
        } else if (!rhs[0] || !my_rules.enumv || (my_rules.enumv->type == FR_TYPE_STRING)) {
+               quote = T_BARE_WORD;
 
-               MEM(map->rhs = tmpl_alloc(map, TMPL_TYPE_DATA, T_BARE_WORD, rhs, strlen(rhs)));
+       alloc_empty:
+               MEM(map->rhs = tmpl_alloc(map, TMPL_TYPE_DATA, quote, rhs, strlen(rhs)));
 
                (void) fr_value_box_strdup(map->rhs, tmpl_value(map->rhs), NULL, rhs, false);
 
@@ -2551,8 +2581,17 @@ int map_afrom_fields(TALLOC_CTX *ctx, map_t **out, char const *lhs, char const *
                slen = tmpl_afrom_substr(map, &map->rhs, &FR_SBUFF_IN(rhs, strlen(rhs)),
                                         T_BARE_WORD, value_parse_rules_unquoted[T_BARE_WORD], &my_rules);
                if (slen <= 0) goto error;
+       }
+
+       if (tmpl_needs_resolving(map->rhs)) {
+               tmpl_res_rules_t tr_rules = (tmpl_res_rules_t) {
+                       .dict_def = lhs_rules->attr.dict_def,
+                       .enumv = tmpl_attr_tail_da(map->lhs)
+               };
+
+               fr_assert(tmpl_is_data_unresolved(map->rhs));
 
-               fr_assert(!tmpl_needs_resolving(map->rhs));
+               if (tmpl_resolve(map->rhs, &tr_rules) < 0) goto error;
        }
 
        /*
index 8ee0e7d41466052a9fdf4277691115e0200069f7..f6caf8a1bc5a432491b4841af5efcfb1e9d5e9eb 100644 (file)
@@ -149,7 +149,7 @@ ssize_t             map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbu
                                tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
                                fr_sbuff_parse_rules_t const *p_rules);
 
-int            map_afrom_fields(TALLOC_CTX *ctx, map_t **out, char const *lhs, char const *op, char const *rhs,
+int            map_afrom_fields(TALLOC_CTX *ctx, map_t **out, request_t *request, char const *lhs, char const *op, char const *rhs,
                                 tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules) CC_HINT(nonnull);
 
 int            map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request,
index 482a7deba1655d093dfb3e91b35b0a379656c1db..e56dd7ea5f4c244f35cb013e3c045dccf6df1c75 100644 (file)
@@ -593,7 +593,7 @@ int sql_get_map_list(TALLOC_CTX *ctx, rlm_sql_t const *inst, request_t *request,
        while (rlm_sql_fetch_row(&row, inst, request, handle) == RLM_SQL_OK) {
                map_t *map;
 
-               if (map_afrom_fields(ctx, &map, row[2], row[4], row[3], &lhs_rules, &rhs_rules) < 0) {
+               if (map_afrom_fields(ctx, &map, request, row[2], row[4], row[3], &lhs_rules, &rhs_rules) < 0) {
                        RPEDEBUG("Error parsing user data from database result");
                        (inst->driver->sql_finish_select_query)(*handle, &inst->config);
                        return -1;
diff --git a/src/tests/modules/sql_sqlite/xlat.attrs b/src/tests/modules/sql_sqlite/xlat.attrs
new file mode 100644 (file)
index 0000000..3e1af7b
--- /dev/null
@@ -0,0 +1,13 @@
+#
+#  Input packet
+#
+Packet-Type = Access-Request
+User-Name = "xlat"
+User-Password = "password"
+NAS-IP-Address = "1.2.3.4"
+
+#
+#  Expected answer
+#
+Packet-Type == Access-Accept
+Reply-Message == "Hello xlat"
diff --git a/src/tests/modules/sql_sqlite/xlat.unlang b/src/tests/modules/sql_sqlite/xlat.unlang
new file mode 100644 (file)
index 0000000..1f45d34
--- /dev/null
@@ -0,0 +1,15 @@
+#
+#  Clear out old data
+#
+%sql("${delete_from_radcheck} 'xlat'")
+%sql("${delete_from_radreply} 'xlat'")
+
+if (%sql("${insert_into_radcheck} ('xlat', 'Password.Cleartext', ':=', 'password')") != "1") {
+       test_fail
+}
+
+if (%sql("${insert_into_radreply} ('xlat', 'Reply-Message', ':=', '\"Hello \%{User-Name}\"')") != "1") {
+       test_fail
+}
+
+sql