MEDIUM: acl: implement payload and payload_lv
These ones were easy to adapt to ACL usage and may really be useful,
so let's make them available right now. It's likely that some extension
such as regex, string-to-IP and raw IP matching will be implemented in
the near future.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index c2b063a..20bb050 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -8070,6 +8070,18 @@
detect particular patterns in paths, such as "../" for example. See also
"path_dir".
+payload(<offset>,<length>) <string>
+ Returns true if the block of <length> bytes, starting at byte <offset> in the
+ request or response buffer (depending on the rule) exactly matches one of the
+ strings.
+
+payload_lv(<offset1>,<length>[,<offset2>])
+ Returns true if the block whose size is specified at <offset1> for <length>
+ bytes, and which starts at <offset2> if specified or just after the length in
+ the request or response buffer (depending on the rule) exactly matches one of
+ the strings. The <offset2> parameter also supports relative offsets if
+ prepended with a '+' or '-' sign.
+
req_ver <string>
Applies to the version string in the HTTP request, eg: "1.0". Some predefined
ACL already check for versions 1.0 and 1.1.
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index e55fd5a..69e9765 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1483,8 +1483,8 @@
}
static int
-pattern_fetch_payloadlv(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
- const struct arg *arg_p, struct sample *smp)
+smp_fetch_payload_lv(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+ const struct arg *arg_p, struct sample *smp)
{
int len_offset = arg_p[0].data.uint;
int len_size = arg_p[1].data.uint;
@@ -1502,18 +1502,20 @@
b = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? l4->rep : l4->req;
- if (!b || !b->i)
+ if (!b)
return 0;
if (len_offset + len_size > b->i)
- return 0;
+ goto too_short;
for (i = 0; i < len_size; i++) {
buf_size = (buf_size << 8) + ((unsigned char *)b->p)[i + len_offset];
}
- if (!buf_size)
+ if (!buf_size) {
+ smp->flags = 0;
return 0;
+ }
/* buf offset may be implicit, absolute or relative */
buf_offset = len_offset + len_size;
@@ -1523,18 +1525,22 @@
buf_offset += arg_p[2].data.sint;
if (buf_offset + buf_size > b->i)
- return 0;
+ goto too_short;
/* init chunk as read only */
smp->type = SMP_T_CBIN;
chunk_initlen(&smp->data.str, b->p + buf_offset, 0, buf_size);
-
+ smp->flags = SMP_F_VOLATILE;
return 1;
+
+ too_short:
+ smp->flags = SMP_F_MAY_CHANGE;
+ return 0;
}
static int
-pattern_fetch_payload(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
- const struct arg *arg_p, struct sample *smp)
+smp_fetch_payload(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+ const struct arg *arg_p, struct sample *smp)
{
int buf_offset = arg_p[0].data.uint;
int buf_size = arg_p[1].data.uint;
@@ -1545,17 +1551,21 @@
b = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? l4->rep : l4->req;
- if (!b || !b->i)
+ if (!b)
return 0;
if (buf_offset + buf_size > b->i)
- return 0;
+ goto too_short;
/* init chunk as read only */
smp->type = SMP_T_CBIN;
chunk_initlen(&smp->data.str, b->p + buf_offset, 0, buf_size);
-
+ smp->flags = SMP_F_VOLATILE;
return 1;
+
+ too_short:
+ smp->flags = SMP_F_MAY_CHANGE;
+ return 0;
}
/* This function is used to validate the arguments passed to a "payload" fetch
@@ -1614,6 +1624,8 @@
static struct acl_kw_list acl_kws = {{ },{
{ "dst", acl_parse_ip, smp_fetch_dst, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "dst_port", acl_parse_int, smp_fetch_dport, acl_match_int, ACL_USE_TCP_PERMANENT, 0 },
+ { "payload", acl_parse_str, smp_fetch_payload, acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG2(2,UINT,UINT) },
+ { "payload_lv", acl_parse_str, smp_fetch_payload_lv, acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG3(2,UINT,UINT,SINT) },
{ "req_rdp_cookie", acl_parse_str, smp_fetch_rdp_cookie, acl_match_str, ACL_USE_L6REQ_VOLATILE|ACL_MAY_LOOKUP, ARG1(0,STR) },
{ "req_rdp_cookie_cnt", acl_parse_int, acl_fetch_rdp_cookie_cnt, acl_match_int, ACL_USE_L6REQ_VOLATILE, ARG1(0,STR) },
{ "src", acl_parse_ip, smp_fetch_src, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP, 0 },
@@ -1632,8 +1644,8 @@
{ "dst", smp_fetch_dst, 0, NULL, SMP_T_IPV4, SMP_CAP_REQ|SMP_CAP_RES },
{ "dst6", pattern_fetch_dst6, 0, NULL, SMP_T_IPV6, SMP_CAP_REQ|SMP_CAP_RES },
{ "dst_port", smp_fetch_dport, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
- { "payload", pattern_fetch_payload, ARG2(2,UINT,UINT), val_payload, SMP_T_CBIN, SMP_CAP_REQ|SMP_CAP_RES },
- { "payload_lv", pattern_fetch_payloadlv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_CAP_REQ|SMP_CAP_RES },
+ { "payload", smp_fetch_payload, ARG2(2,UINT,UINT), val_payload, SMP_T_CBIN, SMP_CAP_REQ|SMP_CAP_RES },
+ { "payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_CAP_REQ|SMP_CAP_RES },
{ "rdp_cookie", pattern_fetch_rdp_cookie, ARG1(1,STR), NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
{ "src_port", smp_fetch_sport, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
{ NULL, NULL, 0, 0, 0 },