From: Alan T. DeKok Date: Thu, 28 Sep 2023 14:49:56 +0000 (-0400) Subject: add, document, and test filtering operators X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18384b21f41d336d691e05ab2dac3eaf3b39aaf3;p=thirdparty%2Ffreeradius-server.git add, document, and test filtering operators --- diff --git a/doc/antora/modules/reference/pages/unlang/edit.adoc b/doc/antora/modules/reference/pages/unlang/edit.adoc index 8cd14ee67d2..a8d6c9eceaf 100644 --- a/doc/antora/modules/reference/pages/unlang/edit.adoc +++ b/doc/antora/modules/reference/pages/unlang/edit.adoc @@ -371,6 +371,21 @@ change the attribute _value_. | >>= | Perform right shift. The value of the __ is shifted right by the value of __ |===== +There are also _filtering_operators. These operators ensure that the +value of the attribute passes the filter. If the attribute being +checked does not exist, it is created. + +.Attribute Filtering Operators +[options="header"] +[cols="10%,90%"] +|===== +| Operator | Description +| < | Ensure that the __ attribute exists, and has value less than the __ +| <= | Ensure that the __ attribute exists, and has value less than or equal to the __ +| > | Ensure that the __ attribute exists, and has value greater than the __ +| >= | Ensure that the __ attribute exists, and has value greater than than or equal to the __ +|===== + The __ can be a reference to another attribute (e.g. `request.Filter-Id`). If the field is a double-quoted string, it undergoes xref:xlat/index.adoc[dynamic expansion], and the resulting diff --git a/raddb/policy.d/time b/raddb/policy.d/time index 843393d009a..b1adfd87593 100644 --- a/raddb/policy.d/time +++ b/raddb/policy.d/time @@ -3,12 +3,18 @@ # expiration { if (&control.Expiration) { - if (&control.Expiration < "%l") { + time_delta timeout + + # + # %l is "when the server received the reuest" + # + if (&control.Expiration < %l) { disallow + return } - elsif (!&reply.Session-Timeout || (&Session-Timeout > "%{expr:%{Expiration} - %l}")) { - &reply.Session-Timeout := %{expr:%{Expiration} - %l} - } + &timeout = &control.Expiration - %l + + &reply.Session-Timeout <= &timeout } } diff --git a/src/lib/unlang/edit.c b/src/lib/unlang/edit.c index 1ba66c6a9fb..02324119d77 100644 --- a/src/lib/unlang/edit.c +++ b/src/lib/unlang/edit.c @@ -1258,7 +1258,8 @@ static int check_lhs(request_t *request, unlang_frame_state_edit_t *state, edit_ /* * Create the attribute, including any necessary parents. */ - if (map->op == T_OP_EQ) { + if ((map->op == T_OP_EQ) || + (fr_type_is_leaf(tmpl_attr_tail_da(current->lhs.vpt)->type) && fr_comparison_op[map->op])) { if (tmpl_attr_tail_num(current->lhs.vpt) == NUM_UNSPEC) { current->lhs.create = true; diff --git a/src/lib/util/edit.c b/src/lib/util/edit.c index e147080656b..783b8a8cee6 100644 --- a/src/lib/util/edit.c +++ b/src/lib/util/edit.c @@ -896,6 +896,31 @@ static int fr_edit_list_delete_list(fr_edit_list_t *el, fr_pair_list_t *list, fr */ int fr_edit_list_apply_pair_assignment(fr_edit_list_t *el, fr_pair_t *vp, fr_token_t op, fr_value_box_t const *in) { + fr_value_box_t box; + + switch (op) { + case T_OP_LE: + case T_OP_LT: + case T_OP_GT: + case T_OP_GE: + if (fr_value_calc_binary_op(vp, &box, FR_TYPE_BOOL, &vp->data, op, in) < 0) return -1; + + if (box.vb_bool) return 0; + + if (el && (fr_edit_list_save_pair_value(el, vp) < 0)) return -1; + + fr_value_box_clear_value(&vp->data); + + /* + * The input type may be different, so we can't just copy it. + */ + return fr_value_box_cast(vp, &vp->data, vp->vp_type, vp->data.enumv, in); + + default: + break; + + } + if (el && (fr_edit_list_save_pair_value(el, vp) < 0)) return -1; return fr_value_calc_assignment_op(vp, &vp->data, op, in); diff --git a/src/tests/keywords/edit-comparison-assign b/src/tests/keywords/edit-comparison-assign new file mode 100644 index 00000000000..74871525842 --- /dev/null +++ b/src/tests/keywords/edit-comparison-assign @@ -0,0 +1,20 @@ +group { + uint32 small + uint32 large + + &User-Name := 'foo' + +# &large = 10000 + &small = 10 + + # + # Enforce it + # + &large <= &small + + if !(&large == &small) { + test_fail + } + +} +success