]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
use conditions to evaluate check items.
authorAlan T. DeKok <aland@freeradius.org>
Tue, 27 Apr 2021 11:31:36 +0000 (07:31 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 27 Apr 2021 11:31:36 +0000 (07:31 -0400)
Finally.

This should be moved to a common API, maybe even in users_file.c,
so that SQL, LDAP, etc. can also gain the benefit of these changes.

src/lib/server/cond_eval.c
src/lib/server/cond_eval.h
src/modules/rlm_files/rlm_files.c

index e7ad8ab63475767b616eea3170e28e1dace743e6..0e5e5f6ca2a6696892e7958e6a3abff7e0816121 100644 (file)
@@ -1108,3 +1108,34 @@ return_to_parent:
        a->state = COND_EVAL_STATE_INIT;
        goto redo;
 }
+
+/** Evaluate a map as if it is a condition.
+ *
+ */
+int fr_cond_eval_map(request_t *request, map_t const *map)
+{
+       fr_cond_t cond;
+
+       memset(&cond, 0, sizeof(cond));
+
+       /*
+        *      Convert !* and =* to existence checks.
+        */
+       switch (map->op) {
+       case T_OP_CMP_FALSE:
+               cond.negate = true;
+               FALL_THROUGH;
+
+       case T_OP_CMP_TRUE:
+               cond.type = COND_TYPE_TMPL;
+               cond.data.vpt = UNCONST(tmpl_t *, map->lhs);
+               break;
+
+       default:
+               cond.type = COND_TYPE_MAP;
+               cond.data.map = UNCONST(map_t *, map);
+               break;
+       }
+
+       return cond_eval(request, RLM_MODULE_NOOP, &cond);
+}
index 252fd97ca9048937a5e26737b220e162bdc18445..1c4c7eecf146f5758a23426f4d3b658d20527d1f 100644 (file)
@@ -27,6 +27,7 @@
 RCSIDH(cond_eval_h, "$Id$")
 
 #include <freeradius-devel/server/request.h>
+#include <freeradius-devel/server/map.h>
 #include <freeradius-devel/util/value.h>
 
 #ifdef __cplusplus
@@ -64,6 +65,8 @@ typedef struct {
 
 int cond_eval_async(request_t *request, fr_cond_async_t *a);
 
+int fr_cond_eval_map(request_t *request, map_t const *map);
+
 #ifdef __cplusplus
 }
 #endif
index a7c831e84efbaeea030d14559c8113e8085e2383..37e2c3a1382bcbce64353636139da31c50ef3fe2 100644 (file)
@@ -403,6 +403,7 @@ static unlang_action_t file_common(rlm_rcode_t *p_result, rlm_files_t const *ins
                PAIR_LIST const *pl;
                fr_pair_list_t list;
                bool fall_through = false;
+               bool match = true;
 
                /*
                 *      Figure out which entry to match on.
@@ -429,23 +430,51 @@ static unlang_action_t file_common(rlm_rcode_t *p_result, rlm_files_t const *ins
 
                /*
                 *      Realize the map to a list of VPs
-                *
-                *      @todo convert the pl->check to fr_cond_t, and just use that!
                 */
                while ((map = fr_dlist_next(&pl->check, map))) {
+                       int rcode;
                        fr_pair_list_t tmp_list;
-                       fr_pair_list_init(&tmp_list);
-                       if (map_to_vp(request->control_ctx, &tmp_list, request, map, NULL) < 0) {
-                               fr_pair_list_free(&list);
-                               RPWARN("Failed parsing map for check item, skipping entry");
+
+                       /*
+                        *      Control items get realized to VPs, and
+                        *      copied to a temporary list, which is
+                        *      then copied to control if the entire
+                        *      line matches.
+                        */
+                       switch (map->op) {
+                       case T_OP_EQ:
+                       case T_OP_SET:
+                       case T_OP_ADD:
+                               fr_pair_list_init(&tmp_list);
+                               if (map_to_vp(request->control_ctx, &tmp_list, request, map, NULL) < 0) {
+                                       fr_pair_list_free(&list);
+                                       RPWARN("Failed parsing check item, skipping entry");
+                                       match = false;
+                                       break;
+                               }
+                               LIST_VERIFY(&tmp_list);
+
+                               fr_pair_list_append(&list, &tmp_list);
+                               break;
+
+                               /*
+                                *      Evaluate the map, including regexes.
+                                */
+                       default:
+                               rcode = fr_cond_eval_map(request, map);
+                               if (rcode < 0) {
+                                       RPWARN("Failed evaluating check item, skipping entry");
+                                       break;
+                               }
+
+                               if (rcode == 0) match = false;
                                break;
                        }
-                       LIST_VERIFY(&tmp_list);
 
-                       fr_pair_list_append(&list, &tmp_list);
+                       if (!match) break;
                }
 
-               if (paircmp(request, &request->request_pairs, &list) != 0) {
+               if (!match) {
                        fr_pair_list_free(&list);
                        continue;
                }