[MINOR] acl: add the "wait_end" acl verb
The new "wait_end" acl delays evaluation of the rule (and the next ones)
to the end of the analysis period. This is intented to be used with TCP
content analysis. A rule referencing such an ACL will not match until
the delay is over. An equivalent default ACL "WAIT_END" has been created.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 8e5f707..e0e6d7e 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -3771,6 +3771,29 @@
that TLSv1 is announced as SSL version 3.1. This test was designed to be used
with TCP request content inspection.
+wait_end
+ Waits for the end of the analysis period to return true. This may be used in
+ conjunction with content analysis to avoid returning a wrong verdict early.
+ It may also be used to delay some actions, such as a delayed reject for some
+ special addresses. Since it either stops the rules evaluation or immediately
+ returns true, it is recommended to use this acl as the last one in a rule.
+ Please note that the default ACL "WAIT_END" is always usable without prior
+ declaration. This test was designed to be used with TCP request content
+ inspection.
+
+ Examples :
+ # delay every incoming request by 2 seconds
+ tcp-request inspect-delay 2s
+ tcp-request content accept if WAIT_END
+
+ # don't immediately tell bad guys they are rejected
+ tcp-request inspect-delay 10s
+ acl goodguys src 10.0.0.0/24
+ acl badguys src 10.0.1.0/24
+ tcp-request content accept if goodguys
+ tcp-request content reject if badguys WAIT_END
+ tcp-request content reject
+
2.3.5.3) Matching at Layer 7
----------------------------
@@ -3957,6 +3980,7 @@
HTTP_URL_STAR url * match URL equal to "*"
HTTP_CONTENT hdr_val(content-length) gt 0 match an existing content-length
REQ_CONTENT req_len gt 0 match data in the request buffer
+WAIT_END wait_end wait for end of content analysis
---------------+-----------------------------+---------------------------------
diff --git a/src/acl.c b/src/acl.c
index e66d502..c02ad70 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -39,6 +39,21 @@
return 1;
}
+/* wait for more data as long as possible, then return TRUE. This should be
+ * used with content inspection.
+ */
+static int
+acl_fetch_wait_end(struct proxy *px, struct session *l4, void *l7, int dir,
+ struct acl_expr *expr, struct acl_test *test)
+{
+ if (dir & ACL_PARTIAL) {
+ test->flags |= ACL_TEST_F_MAY_CHANGE;
+ return 0;
+ }
+ test->flags |= ACL_TEST_F_SET_RES_PASS;
+ return 1;
+}
+
/* force FALSE to be returned at the fetch level */
static int
acl_fetch_false(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -772,6 +787,7 @@
{ .name = "HTTP_URL_STAR", .expr = {"url","*",""}},
{ .name = "HTTP_CONTENT", .expr = {"hdr_val(content-length)","gt","0",""}},
{ .name = "REQ_CONTENT", .expr = {"req_len","gt","0",""}},
+ { .name = "WAIT_END", .expr = {"wait_end",""}},
{ .name = NULL, .expr = {""}}
};
@@ -1064,6 +1080,7 @@
static struct acl_kw_list acl_kws = {{ },{
{ "always_true", acl_parse_nothing, acl_fetch_true, acl_match_nothing },
{ "always_false", acl_parse_nothing, acl_fetch_false, acl_match_nothing },
+ { "wait_end", acl_parse_nothing, acl_fetch_wait_end, acl_match_nothing },
#if 0
{ "time", acl_parse_time, acl_fetch_time, acl_match_time },
#endif
diff --git a/tests/test-inspect-smtp.cfg b/tests/test-inspect-smtp.cfg
index 1c0d46d..5cfc864 100644
--- a/tests/test-inspect-smtp.cfg
+++ b/tests/test-inspect-smtp.cfg
@@ -3,7 +3,7 @@
# - if the address is in the white list, then accept it and forward the
# connection to the server (local port 25)
# - if the address is in the black list, then immediately drop it
-# - otherwise, wait up to 3 seconds. If the client talks during this time,
+# - otherwise, wait up to 35 seconds. If the client talks during this time,
# drop the connection.
# - then accept the connection if it passes all the tests.
#
@@ -17,19 +17,28 @@
mode tcp
bind :8025
- timeout client 6s
- timeout server 6s
- timeout connect 6s
+ timeout client 60s
+ timeout server 60s
+ timeout queue 60s
+ timeout connect 5s
- tcp-request inspect-delay 4s
+ tcp-request inspect-delay 35s
acl white_list src 127.0.0.2
- acl black_list src 127.0.0.3
- acl talkative req_len gt 0
+ acl black_fast src 127.0.0.3 # those ones are immediately rejected
+ acl black_slow src 127.0.0.4 # those ones are rejected after a delay
tcp-request content accept if white_list
- tcp-request content reject if black_list
- tcp-request content reject if talkative
+ tcp-request content reject if black_fast
+ tcp-request content reject if black_slow WAIT_END
+ tcp-request content reject if REQ_CONTENT
+ # note that it is possible to wait for the end of the analysis period
+ # before rejecting undesired contents
+ # tcp-request content reject if REQ_CONTENT WAIT_END
+
+ # on Linux+transparent proxy patch, it's useful to reuse the client'IP
+ # source 0.0.0.0 usesrc clientip
balance roundrobin
server mail 127.0.0.1:25
+