]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add, document, and test filtering operators
authorAlan T. DeKok <aland@freeradius.org>
Thu, 28 Sep 2023 14:49:56 +0000 (10:49 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 28 Sep 2023 14:49:56 +0000 (10:49 -0400)
doc/antora/modules/reference/pages/unlang/edit.adoc
raddb/policy.d/time
src/lib/unlang/edit.c
src/lib/util/edit.c
src/tests/keywords/edit-comparison-assign [new file with mode: 0644]

index 8cd14ee67d2781a25a069d995e5d6bfe365f9708..a8d6c9eceafdde01871f920618fde44c31cb9142 100644 (file)
@@ -371,6 +371,21 @@ change the attribute _value_.
 | >>=      | Perform right shift.  The value of the _<attribute>_ is shifted right by the value of _<rhs>_
 |=====
 
+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 _<lhs>_ attribute exists, and has value less than the _<rhs>_
+| <=       | Ensure that the _<lhs>_ attribute exists, and has value less than or equal to the _<rhs>_
+| >        | Ensure that the _<lhs>_ attribute exists, and has value greater than the _<rhs>_
+| >=       | Ensure that the _<lhs>_ attribute exists, and has value greater than than or equal to the _<rhs>_
+|=====
+
 The _<rhs>_ 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
index 843393d009ad0673f5e06763e99f4dd1da1596c4..b1adfd87593791dbe7cd60341afa34267123e915 100644 (file)
@@ -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
        }
 }
index 1ba66c6a9fbb6ea13e8fdd9ce22f6d8f6757c54d..02324119d77b4de92ab0c9b3cee437cd241a133a 100644 (file)
@@ -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;
 
index e147080656be72e2e4530a41499510c739ff71b6..783b8a8cee6fb519be7d1ed17568b1b2f111cc2b 100644 (file)
@@ -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 (file)
index 0000000..7487152
--- /dev/null
@@ -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