From: Alan T. DeKok Date: Sun, 24 Dec 2023 17:04:59 +0000 (-0500) Subject: the files module now supports "undo" for failed operations X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e0e3dbb203fd0c02e735f26dcd49e28da38ae3c8;p=thirdparty%2Ffreeradius-server.git the files module now supports "undo" for failed operations --- diff --git a/src/lib/server/pairmove.c b/src/lib/server/pairmove.c index a1bc1da7092..c2467c04303 100644 --- a/src/lib/server/pairmove.c +++ b/src/lib/server/pairmove.c @@ -504,7 +504,7 @@ static fr_pair_t *legacy_pair_build(fr_pair_t *parent, fr_dcursor_t *cursor, fr_ /** 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; @@ -515,7 +515,6 @@ int radius_legacy_map_apply(request_t *request, map_t const *map) 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; @@ -770,7 +769,7 @@ int radius_legacy_map_apply(request_t *request, map_t const *map) 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; @@ -780,7 +779,10 @@ int radius_legacy_map_list_apply(request_t *request, map_list_t const *list) 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; diff --git a/src/lib/server/pairmove.h b/src/lib/server/pairmove.h index d6b226b5046..17c1068defc 100644 --- a/src/lib/server/pairmove.h +++ b/src/lib/server/pairmove.h @@ -28,6 +28,7 @@ RCSIDH(pairmove_h, "$Id$") #include #include +#include #ifdef __cplusplus extern "C" { @@ -35,9 +36,9 @@ 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); diff --git a/src/lib/util/value.c b/src/lib/util/value.c index fb8f5fb6b97..eb6a36106b2 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -545,22 +545,26 @@ fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted = { 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 diff --git a/src/modules/rlm_exec/rlm_exec.c b/src/modules/rlm_exec/rlm_exec.c index c2bb3feaec7..33441a7b893 100644 --- a/src/modules/rlm_exec/rlm_exec.c +++ b/src/modules/rlm_exec/rlm_exec.c @@ -342,7 +342,7 @@ static unlang_action_t mod_exec_oneshot_wait_resume(rlm_rcode_t *p_result, modul 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); diff --git a/src/modules/rlm_files/rlm_files.c b/src/modules/rlm_files/rlm_files.c index a392d38daca..90009e23581 100644 --- a/src/modules/rlm_files/rlm_files.c +++ b/src/modules/rlm_files/rlm_files.c @@ -30,6 +30,7 @@ RCSID("$Id$") #include #include #include +#include #include #include @@ -445,11 +446,15 @@ static unlang_action_t file_common(rlm_rcode_t *p_result, UNUSED rlm_files_t con 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; @@ -535,7 +540,7 @@ redo: case T_OP_SET: case T_OP_ADD_EQ: fr_assert(0); - return -1; + goto fail; /* * Evaluate the map, including regexes. @@ -544,8 +549,9 @@ redo: 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) { @@ -564,9 +570,9 @@ redo: 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) { @@ -612,11 +618,13 @@ redo: /* * 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; - } diff --git a/src/modules/rlm_sql/rlm_sql.c b/src/modules/rlm_sql/rlm_sql.c index 18f39273550..b7b957c80d9 100644 --- a/src/modules/rlm_sql/rlm_sql.c +++ b/src/modules/rlm_sql/rlm_sql.c @@ -978,7 +978,7 @@ static int sql_check_groupmemb(rlm_sql_t const *inst, request_t *request, rlm_sq 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; @@ -1428,7 +1428,7 @@ static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, mod 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; diff --git a/src/tests/modules/files/authorize b/src/tests/modules/files/authorize index 7247c1967f0..a115ca1f9e7 100644 --- a/src/tests/modules/files/authorize +++ b/src/tests/modules/files/authorize @@ -141,6 +141,21 @@ digest Password.Cleartext := "woo" 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" diff --git a/src/tests/modules/files/undo.attrs b/src/tests/modules/files/undo.attrs new file mode 100644 index 00000000000..a3c66450ba5 --- /dev/null +++ b/src/tests/modules/files/undo.attrs @@ -0,0 +1,12 @@ +# +# 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 diff --git a/src/tests/modules/files/undo.unlang b/src/tests/modules/files/undo.unlang new file mode 100644 index 00000000000..ac7d33b1c54 --- /dev/null +++ b/src/tests/modules/files/undo.unlang @@ -0,0 +1,11 @@ +try { + files +} +catch fail { + # + # Make it accept, but the accept should be empty! + # see undo.attrs + # + &control.Password.Cleartext := "hello" + ok +}