From: Alan T. DeKok Date: Tue, 27 Apr 2021 11:31:36 +0000 (-0400) Subject: use conditions to evaluate check items. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a7f92746833d12fae5ea38cba97e7ef834ec628;p=thirdparty%2Ffreeradius-server.git use conditions to evaluate check items. 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. --- diff --git a/src/lib/server/cond_eval.c b/src/lib/server/cond_eval.c index e7ad8ab6347..0e5e5f6ca2a 100644 --- a/src/lib/server/cond_eval.c +++ b/src/lib/server/cond_eval.c @@ -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); +} diff --git a/src/lib/server/cond_eval.h b/src/lib/server/cond_eval.h index 252fd97ca90..1c4c7eecf14 100644 --- a/src/lib/server/cond_eval.h +++ b/src/lib/server/cond_eval.h @@ -27,6 +27,7 @@ RCSIDH(cond_eval_h, "$Id$") #include +#include #include #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 diff --git a/src/modules/rlm_files/rlm_files.c b/src/modules/rlm_files/rlm_files.c index a7c831e84ef..37e2c3a1382 100644 --- a/src/modules/rlm_files/rlm_files.c +++ b/src/modules/rlm_files/rlm_files.c @@ -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; }