diff --git a/doc/configuration.txt b/doc/configuration.txt index c683387d0..87de59517 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -9662,7 +9662,10 @@ req_len : integer (deprecated) req.payload(,) : binary This extracts a binary block of bytes and starting at byte - in the request buffer. + in the request buffer. As a special case, if the argument is zero, + the the whole buffer from to the end is extracted. This can be used + with ACLs in order to check for the presence of some content in a buffer at + any location. ACL alternatives : payload(,) : hex binary match @@ -9805,7 +9808,10 @@ req_ssl_ver : integer (deprecated) res.payload(,) : binary This extracts a binary block of bytes and starting at byte - in the response buffer. + in the response buffer. As a special case, if the argument is zero, + the the whole buffer from to the end is extracted. This can be used + with ACLs in order to check for the presence of some content in a buffer at + any location. res.payload_lv(,[,]) : binary This extracts a binary block whose size is specified at for diff --git a/src/payload.c b/src/payload.c index 05418aca6..227379b0d 100644 --- a/src/payload.c +++ b/src/payload.c @@ -589,7 +589,7 @@ smp_fetch_payload(struct proxy *px, struct session *s, void *l7, unsigned int op if (!chn) return 0; - if (!buf_size || buf_size > chn->buf->size || buf_offset + buf_size > chn->buf->size) { + if (buf_size > chn->buf->size || buf_offset + buf_size > chn->buf->size) { /* will never match */ smp->flags = 0; return 0; @@ -600,8 +600,11 @@ smp_fetch_payload(struct proxy *px, struct session *s, void *l7, unsigned int op /* init chunk as read only */ smp->type = SMP_T_CBIN; - chunk_initlen(&smp->data.str, chn->buf->p + buf_offset, 0, buf_size); + chunk_initlen(&smp->data.str, chn->buf->p + buf_offset, 0, buf_size ? buf_size : (chn->buf->i - buf_offset)); smp->flags = SMP_F_VOLATILE; + if (!buf_size && !channel_full(chn) && !channel_input_closed(chn)) + smp->flags |= SMP_F_MAY_CHANGE; + return 1; too_short: @@ -609,23 +612,6 @@ smp_fetch_payload(struct proxy *px, struct session *s, void *l7, unsigned int op return 0; } -/* This function is used to validate the arguments passed to a "payload" fetch - * keyword. This keyword expects two positive integers, with the second one - * being strictly positive. It is assumed that the types are already the correct - * ones. Returns 0 on error, non-zero if OK. If is not NULL, it will be - * filled with a pointer to an error message in case of error, that the caller - * is responsible for freeing. The initial location must either be freeable or - * NULL. - */ -static int val_payload(struct arg *arg, char **err_msg) -{ - if (!arg[1].data.uint) { - memprintf(err_msg, "payload length must be > 0"); - return 0; - } - return 1; -} - /* This function is used to validate the arguments passed to a "payload_lv" fetch * keyword. This keyword allows two positive integers and an optional signed one, * with the second one being strictly positive and the third one being greater than @@ -660,7 +646,7 @@ static int val_payload_lv(struct arg *arg, char **err_msg) * instance IPv4/IPv6 must be declared IPv4. */ static struct sample_fetch_kw_list smp_kws = {ILH, { - { "payload", smp_fetch_payload, ARG2(2,UINT,UINT), val_payload, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, + { "payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, { "payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, { "rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_L6REQ }, @@ -671,14 +657,14 @@ static struct sample_fetch_kw_list smp_kws = {ILH, { { "req_ssl_ver", smp_fetch_req_ssl_ver, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.len", smp_fetch_req_len, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, - { "req.payload", smp_fetch_payload, ARG2(2,UINT,UINT), val_payload, SMP_T_CBIN, SMP_USE_L6REQ }, + { "req.payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6REQ }, { "req.payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ }, { "req.rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req.rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.ssl_sni", smp_fetch_ssl_hello_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req.ssl_ver", smp_fetch_req_ssl_ver, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, - { "res.payload", smp_fetch_payload, ARG2(2,UINT,UINT), val_payload, SMP_T_CBIN, SMP_USE_L6RES }, + { "res.payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6RES }, { "res.payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6RES }, { "res.ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6RES }, { "wait_end", smp_fetch_wait_end, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },