/** Move a map using the operators from the old pairmove functionality.
*
*/
-int radius_legacy_map_apply(request_t *request, map_t const *map)
+int radius_legacy_map_apply(request_t *request, map_t const *map, fr_edit_list_t *el)
{
int16_t num;
int err, rcode;
TALLOC_CTX *ctx;
fr_value_box_t *to_free = NULL;
fr_value_box_t const *box;
- fr_edit_list_t *el = NULL;
tmpl_dcursor_ctx_t cc;
fr_dcursor_t cursor;
return 0;
}
-int radius_legacy_map_list_apply(request_t *request, map_list_t const *list)
+int radius_legacy_map_list_apply(request_t *request, map_list_t const *list, fr_edit_list_t *el)
{
map_t const *map;
RDEBUG2("&%s %s %s", map->lhs->name, fr_tokens[map->op],
map->rhs ? map->rhs->name : "{ ... }");
- if (radius_legacy_map_apply(request, map) < 0) return -1;
+ if (radius_legacy_map_apply(request, map, el) < 0) {
+ RPEDEBUG("Failed applying result");
+ return -1;
+ }
}
return 0;
#include <freeradius-devel/server/request.h>
#include <freeradius-devel/server/map.h>
+#include <freeradius-devel/util/edit.h>
#ifdef __cplusplus
extern "C" {
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from) CC_HINT(nonnull);
-int radius_legacy_map_apply(request_t *request, map_t const *map) CC_HINT(nonnull);
+int radius_legacy_map_apply(request_t *request, map_t const *map, fr_edit_list_t *el) CC_HINT(nonnull(1,2));
-int radius_legacy_map_list_apply(request_t *request, map_list_t const *list) CC_HINT(nonnull);
+int radius_legacy_map_list_apply(request_t *request, map_list_t const *list, fr_edit_list_t *el) CC_HINT(nonnull(1,2));
int radius_legacy_map_cmp(request_t *request, map_t const *map) CC_HINT(nonnull);
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted = {
.escapes = &fr_value_unescape_double,
- .terminals = &FR_SBUFF_TERM("\"")
+ .terminals = &FR_SBUFF_TERMS(
+ L(""), L("\n"), L("\r"), L("\""))
};
fr_sbuff_parse_rules_t const value_parse_rules_single_quoted = {
.escapes = &fr_value_unescape_single,
- .terminals = &FR_SBUFF_TERM("'")
+ .terminals = &FR_SBUFF_TERMS(
+ L(""), L("\n"), L("\r"), L("'"))
};
fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted = {
.escapes = &fr_value_unescape_solidus,
- .terminals = &FR_SBUFF_TERM("/")
+ .terminals = &FR_SBUFF_TERMS(
+ L(""), L("\n"), L("\r"), L("/"))
};
fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted = {
.escapes = &fr_value_unescape_backtick,
- .terminals = &FR_SBUFF_TERM("`")
+ .terminals = &FR_SBUFF_TERMS(
+ L(""), L("\n"), L("\r"), L("`"))
};
/** Parse rules for quoted strings
RDEBUG("applying %s %s %s",
map->lhs->name, fr_tokens[map->op], map->rhs->name);
- if (radius_legacy_map_apply(request, map) < 0) {
+ if (radius_legacy_map_apply(request, map, NULL) < 0) {
RPEDEBUG("Failed applying assignment");
TALLOC_FREE(map);
#include <freeradius-devel/server/users_file.h>
#include <freeradius-devel/util/htrie.h>
#include <freeradius-devel/unlang/call_env.h>
+#include <freeradius-devel/unlang/transaction.h>
#include <ctype.h>
#include <fcntl.h>
PAIR_LIST_LIST my_list;
uint8_t key_buffer[16], *key;
size_t keylen = 0;
+ fr_edit_list_t *el, *child;
if (!tree && !default_list) RETURN_MODULE_NOOP;
RDEBUG2("Looking for key \"%pV\"", &env->key);
+ el = unlang_interpret_edit_list(request);
+ MEM(child = fr_edit_list_alloc(request, 50, el));
+
if (tree) {
my_list.name = NULL;
my_list.box = &env->key;
case T_OP_SET:
case T_OP_ADD_EQ:
fr_assert(0);
- return -1;
+ goto fail;
/*
* Evaluate the map, including regexes.
rcode = radius_legacy_map_cmp(request, map);
if (rcode < 0) {
RPWARN("Failed parsing map for check item %s, skipping it", map->lhs->name);
- match = false;
- break;
+ fail:
+ fr_edit_list_abort(child);
+ RETURN_MODULE_FAIL;
}
if (!rcode) {
found = true;
/* ctx may be reply */
- if (radius_legacy_map_list_apply(request, &pl->reply) < 0) {
+ if (radius_legacy_map_list_apply(request, &pl->reply, child) < 0) {
RPWARN("Failed parsing reply item");
- RETURN_MODULE_FAIL;
+ goto fail;
}
if (pl->fall_through) {
/*
* See if we succeeded.
*/
- if (!found)
+ if (!found) {
+ fr_edit_list_abort(child);
RETURN_MODULE_NOOP; /* on to the next module */
+ }
+ fr_edit_list_commit(child);
RETURN_MODULE_OK;
-
}
RDEBUG2("Group \"%s\": Merging reply items", group_name);
*rcode = RLM_MODULE_UPDATED;
- if (radius_legacy_map_list_apply(request, &reply_tmp) < 0) {
+ if (radius_legacy_map_list_apply(request, &reply_tmp, NULL) < 0) {
RPEDEBUG("Failed applying reply item");
map_list_talloc_free(&reply_tmp);
return -1;
RDEBUG2("User found in radreply table, merging reply items");
user_found = true;
- if (radius_legacy_map_list_apply(request, &reply_tmp) < 0) {
+ if (radius_legacy_map_list_apply(request, &reply_tmp, NULL) < 0) {
RPEDEBUG("Failed applying reply item");
map_list_talloc_free(&reply_tmp);
rcode = RLM_MODULE_FAIL;
DEFAULT User-Name == "cmp_eq", Password.Cleartext := "hopping"
Reply-Message := "success-cmp_eq"
+#
+# Do something, and then undo it
+#
+undo Password.Cleartext := "hello"
+ Reply-Message := "hello %{User-Name}",
+ Fall-Through := yes
+
+#
+# This should fail, which means that the previous Reply-Message
+# gets deleted as part of the "undo" operation.
+#
+undo
+ Framed-IP-Address := "this is not an IP address"
+
+
$INCLUDE cmp
DEFAULT Password.Cleartext := "stuffnsuch"
--- /dev/null
+#
+# Input packet
+#
+Packet-Type = Access-Request
+User-Name = "undo"
+User-Password = "hello"
+NAS-IP-Address = 192.0.2.1
+
+#
+# Expected answer
+#
+Packet-Type == Access-Accept
--- /dev/null
+try {
+ files
+}
+catch fail {
+ #
+ # Make it accept, but the accept should be empty!
+ # see undo.attrs
+ #
+ &control.Password.Cleartext := "hello"
+ ok
+}