diff --git a/include/proto/acl.h b/include/proto/acl.h index 59c213926..896872f25 100644 --- a/include/proto/acl.h +++ b/include/proto/acl.h @@ -68,7 +68,7 @@ struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int p * This function only computes the condition, it does not apply the polarity * required by IF/UNLESS, it's up to the caller to do this. */ -int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, void *l7); +int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, void *l7, int dir); /* Return a pointer to the ACL within the list starting at , or * NULL if not found. diff --git a/include/types/acl.h b/include/types/acl.h index 02c1258b0..d67928897 100644 --- a/include/types/acl.h +++ b/include/types/acl.h @@ -61,6 +61,12 @@ enum { ACL_TEST_F_FETCH_MORE = 1 << 7, /* if test does not match, retry with next entry */ }; +/* ACLs can be evaluated on requests and on responses. */ +enum { + ACL_DIR_REQ = 0, /* ACL evaluated on request */ + ACL_DIR_RTR, /* ACL evaluated on response */ +}; + /* How to store a time range and the valid days in 29 bits */ struct acl_time { int dow:7; /* 1 bit per day of week: 0-6 */ @@ -127,7 +133,7 @@ struct session; struct acl_keyword { const char *kw; int (*parse)(const char **text, struct acl_pattern *pattern, int *opaque); - int (*fetch)(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test); + int (*fetch)(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test); int (*match)(struct acl_test *test, struct acl_pattern *pattern); int use_cnt; }; diff --git a/src/acl.c b/src/acl.c index efa785319..4443ae9ad 100644 --- a/src/acl.c +++ b/src/acl.c @@ -620,7 +620,7 @@ struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int p * This function only computes the condition, it does not apply the polarity * required by IF/UNLESS, it's up to the caller to do this. */ -int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, void *l7) +int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, void *l7, int dir) { __label__ fetch_next; struct acl_term_suite *suite; @@ -654,9 +654,10 @@ int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, v */ acl_res = ACL_PAT_FAIL; list_for_each_entry(expr, &acl->expr, list) { - test.flags = test.len = 0; + /* we need to reset context and flags */ + memset(&test, 0, sizeof(test)); fetch_next: - if (!expr->kw->fetch(px, l4, l7, expr->arg.str, &test)) + if (!expr->kw->fetch(px, l4, l7, dir, expr->arg.str, &test)) continue; /* apply all tests to this value */ diff --git a/src/client.c b/src/client.c index ddc630bf8..39d53221f 100644 --- a/src/client.c +++ b/src/client.c @@ -453,7 +453,8 @@ int event_accept(int fd) { /************************************************************************/ /* set test->ptr to point to the source IPv4/IPv6 address and test->i to the family */ -static int acl_fetch_src(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { test->i = l4->cli_addr.ss_family; if (test->i == AF_INET) @@ -466,7 +467,8 @@ static int acl_fetch_src(struct proxy *px, struct session *l4, void *l7, void *a /* set test->i to the connexion's source port */ -static int acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { if (l4->cli_addr.ss_family == AF_INET) test->i = ntohs(((struct sockaddr_in *)&l4->cli_addr)->sin_port); @@ -478,7 +480,8 @@ static int acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, void /* set test->ptr to point to the frontend's IPv4/IPv6 address and test->i to the family */ -static int acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { if (!(l4->flags & SN_FRT_ADDR_SET)) get_frt_addr(l4); @@ -494,7 +497,8 @@ static int acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, void *a /* set test->i to the frontend connexion's destination port */ -static int acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { if (!(l4->flags & SN_FRT_ADDR_SET)) get_frt_addr(l4); @@ -508,7 +512,8 @@ static int acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, void } /* set test->i to the number of connexions to the proxy */ -static int acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { test->i = px->feconn; return 1; diff --git a/src/proto_http.c b/src/proto_http.c index 839bc94d5..5f991e57a 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1681,7 +1681,7 @@ int process_cli(struct session *t) /* first check whether we have some ACLs set to block this request */ list_for_each_entry(cond, &cur_proxy->block_cond, list) { - int ret = acl_exec_cond(cond, cur_proxy, t, txn); + int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ); if (cond->pol == ACL_COND_UNLESS) ret = !ret; @@ -5164,7 +5164,8 @@ static int acl_parse_meth(const char **text, struct acl_pattern *pattern, int *o return 1; } -static int acl_fetch_meth(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_meth(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { int meth; struct http_txn *txn = l7; @@ -5207,7 +5208,8 @@ static int acl_parse_ver(const char **text, struct acl_pattern *pattern, int *op return 1; } -static int acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { struct http_txn *txn = l7; char *ptr; @@ -5227,7 +5229,8 @@ static int acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, void return 1; } -static int acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { struct http_txn *txn = l7; char *ptr; @@ -5248,7 +5251,8 @@ static int acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, void } /* 3. Check on Status Code. We manipulate integers here. */ -static int acl_fetch_stcode(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_stcode(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { struct http_txn *txn = l7; char *ptr; @@ -5263,7 +5267,8 @@ static int acl_fetch_stcode(struct proxy *px, struct session *l4, void *l7, void } /* 4. Check on URL/URI. A pointer to the URI is stored. */ -static int acl_fetch_url(struct proxy *px, struct session *l4, void *l7, void *arg, struct acl_test *test) +static int +acl_fetch_url(struct proxy *px, struct session *l4, void *l7, int dir, void *arg, struct acl_test *test) { struct http_txn *txn = l7;