]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: acl: add acl_cond_find_positive_use() to find positive terms by usage
authorWilly Tarreau <w@1wt.eu>
Wed, 11 Nov 2026 10:42:38 +0000 (12:42 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 12 Nov 2026 17:12:23 +0000 (18:12 +0100)
This function looks for a term of a condition which makes the condition
true when it matches (a non-negated term after "if", or a negated one
after "unless") and which involves a sample fetch having certain
SMP_USE_* bits. It returns the first matching ACL and keyword, in the
same way as acl_cond_kw_conflicts() does. The combination of terms is
not considered, a single positive term is enough.

It will be used to detect deny-lists built on aliasable contents.

include/haproxy/acl.h
src/acl.c

index af48dba38aff70b17091ead75b9b612632ed50ee..5da8bfbfa8e04ce5bd6fdf5c206181e97de07385 100644 (file)
@@ -139,6 +139,14 @@ const struct acl *acl_cond_conflicts(const struct acl_cond *cond, unsigned int w
  */
 int acl_cond_kw_conflicts(const struct acl_cond *cond, unsigned int where, struct acl const **acl, char const **kw);
 
+/* Looks for a term of condition <cond> which may make the condition true when
+ * it matches, i.e. a non-negated term after "if" or a negated one after
+ * "unless", and which involves a sample fetch having one of the SMP_USE_*
+ * bits from <use>. Returns true if such a term is found, with <acl> and <kw>
+ * set (if non null) to the first matching ACL and keyword, otherwise false.
+ */
+int acl_cond_find_positive_use(const struct acl_cond *cond, unsigned int use, struct acl const **acl, char const **kw);
+
 /*
  * Find targets for userlist and groups in acl. Function returns the number
  * of errors or OK if everything is fine.
index 7b1990aaf500ca2303bc5662c2c9ab7cde17b9c4..40043f5375d8044838f80d6adbfaa145949d020e 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -1190,6 +1190,45 @@ int acl_cond_kw_conflicts(const struct acl_cond *cond, unsigned int where, struc
        return 0;
 }
 
+/* Looks for a term of condition <cond> which may make the condition true when
+ * it matches, i.e. a non-negated term after "if" or a negated one after
+ * "unless", and which involves a sample fetch having one of the SMP_USE_*
+ * bits from <use>. Returns true if such a term is found, with <acl> and <kw>
+ * set (if non null) to the first matching ACL and keyword, otherwise false.
+ * This is used to detect deny-lists built on certain types of contents.
+ */
+int acl_cond_find_positive_use(const struct acl_cond *cond, unsigned int use, struct acl const **acl, char const **kw)
+{
+       struct acl_term_suite *suite;
+       struct acl_term *term;
+       struct acl_expr *expr;
+
+       if (!(cond->use & use))
+               return 0;
+
+       list_for_each_entry(suite, &cond->suites, list) {
+               list_for_each_entry(term, &suite->terms, list) {
+                       /* only keep terms whose match makes the condition true */
+                       if (!!term->neg != (cond->pol == ACL_COND_UNLESS))
+                               continue;
+
+                       if (!(term->acl->use & use))
+                               continue;
+
+                       list_for_each_entry(expr, &term->acl->expr, list) {
+                               if (expr->smp->fetch->use & use) {
+                                       if (acl)
+                                               *acl = term->acl;
+                                       if (kw)
+                                               *kw = expr->kw;
+                                       return 1;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
 /*
  * Find targets for userlist and groups in acl. Function returns the number
  * of errors or OK if everything is fine. It must be called only once sample