]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: payload/htx: Ingore L6 sample fetches for HTX streams/checks
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 25 Mar 2021 10:58:51 +0000 (11:58 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 1 Apr 2021 13:31:55 +0000 (15:31 +0200)
Use a L6 sample fetch on an HTX streams or a HTX health-check is meaningless
because data are not raw but structured. So now, these sample fetches fail
when called from an HTTP proxy. In addition, a warning has been added in the
configuration manual, at the begining of the L6 sample fetches section.

Note that req.len and res.len samples return the HTX data size instead of
failing. It is not accurate because it does not reflect the buffer size nor
the raw data length. But we keep it for backward compatibility purpose.
However it remains a bit strange to use it on an HTTP proxy.

This patch may be backported to all versions supporting the HTX, i.e as far
as 2.0. But the part about the health-checks is only valid for the 2.2 and
upper.

doc/configuration.txt
src/payload.c

index f5d19f9449d11463f4e72d5b35129a19fc34ce5e..8c33a5ca7efb92280542e4fcc3f50497fa0db47e 100644 (file)
@@ -18404,6 +18404,14 @@ sample fetch methods to ensure that the expected data are complete and usable,
 for example through TCP request content inspection. Please see the "tcp-request
 content" keyword for more detailed information on the subject.
 
+Warning : Following sample fetches are ignored if used from HTTP proxies. They
+          only deal with raw contents found in the buffers. On their side,
+          HTTTP proxies use structured content. Thus raw representation of
+          these data are meaningless. A warning is emitted if an ACL relies on
+          one of the following sample fetches. But it is not possible to detect
+          all invalid usage (for instance inside a log-format string or a
+          sample expression). So be careful.
+
 payload(<offset>,<length>) : binary (deprecated)
   This is an alias for "req.payload" when used in the context of a request (e.g.
   "stick on", "stick match"), and for "res.payload" when used in the context of
index 26994cff1af3ebb37589e033f02e58065748b579..32e5456e62a0f3320c210f4d18ab8607121a0c1b 100644 (file)
@@ -50,6 +50,8 @@ smp_fetch_len(const struct arg *args, struct sample *smp, const char *kw, void *
 {
        if (smp->strm) {
                struct channel *chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
+
+               /* Not accurate but kept for backward compatibility purpose */
                if (IS_HTX_STRM(smp->strm)) {
                        struct htx *htx = htxbuf(&chn->buf);
                        smp->data.u.sint = htx->data - co_data(chn);
@@ -59,6 +61,8 @@ smp_fetch_len(const struct arg *args, struct sample *smp, const char *kw, void *
        }
        else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) {
                struct check *check = __objt_check(smp->sess->origin);
+
+               /* Not accurate but kept for backward compatibility purpose */
                smp->data.u.sint = ((check->cs && IS_HTX_CS(check->cs)) ? (htxbuf(&check->bi))->data: b_data(&check->bi));
        }
        else
@@ -84,7 +88,13 @@ smp_fetch_req_ssl_st_ext(const struct arg *args, struct sample *smp, const char
        if (!smp->strm)
                goto not_ssl_hello;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               goto not_ssl_hello;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
+
+
        bleft = ci_data(chn);
        data = (unsigned char *)ci_head(chn);
 
@@ -214,6 +224,10 @@ smp_fetch_req_ssl_ec_ext(const struct arg *args, struct sample *smp, const char
        if (!smp->strm)
                goto not_ssl_hello;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               goto not_ssl_hello;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
        bleft = ci_data(chn);
        data = (unsigned char *)ci_head(chn);
@@ -335,6 +349,10 @@ smp_fetch_ssl_hello_type(const struct arg *args, struct sample *smp, const char
        if (!smp->strm)
                goto not_ssl_hello;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               goto not_ssl_hello;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
        bleft = ci_data(chn);
        data = (const unsigned char *)ci_head(chn);
@@ -399,7 +417,11 @@ smp_fetch_req_ssl_ver(const struct arg *args, struct sample *smp, const char *kw
        struct channel *req;
 
        if (!smp->strm)
-               return 0;
+               goto not_ssl;
+
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               goto not_ssl;
 
        req = &smp->strm->req;
        msg_len = 0;
@@ -541,6 +563,10 @@ smp_fetch_ssl_hello_sni(const struct arg *args, struct sample *smp, const char *
        if (!smp->strm)
                goto not_ssl_hello;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               goto not_ssl_hello;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
        bleft = ci_data(chn);
        data = (unsigned char *)ci_head(chn);
@@ -707,6 +733,10 @@ smp_fetch_ssl_hello_alpn(const struct arg *args, struct sample *smp, const char
        if (!smp->strm)
                goto not_ssl_hello;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               goto not_ssl_hello;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
        bleft = ci_data(chn);
        data = (unsigned char *)ci_head(chn);
@@ -933,6 +963,10 @@ smp_fetch_rdp_cookie(const struct arg *args, struct sample *smp, const char *kw,
        if (!smp->strm)
                return 0;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               return 0;
+
        return fetch_rdp_cookie_name(smp->strm, smp,
                                     args ? args->data.str.area : NULL,
                                     args ? args->data.str.data : 0);
@@ -973,14 +1007,21 @@ smp_fetch_payload_lv(const struct arg *arg_p, struct sample *smp, const char *kw
        /* buf offset could be absolute or relative to len offset + len size if prefixed by + or - */
 
        if (smp->strm) {
+               /* meaningless for HTX buffers */
+               if (IS_HTX_STRM(smp->strm))
+                       return 0;
                chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
                head = ci_head(chn);
                data = ci_data(chn);
        }
        else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) {
-               struct buffer *buf = &(__objt_check(smp->sess->origin)->bi);
-               head = b_head(buf);
-               data = b_data(buf);
+               struct check *check = __objt_check(smp->sess->origin);
+
+               /* meaningless for HTX buffers */
+               if (check->cs && IS_HTX_CS(check->cs))
+                       return 0;
+               head = b_head(&check->bi);
+               data = b_data(&check->bi);
        }
        max = global.tune.bufsize;
        if (!head)
@@ -1035,14 +1076,21 @@ smp_fetch_payload(const struct arg *arg_p, struct sample *smp, const char *kw, v
        size_t max, data;
 
        if (smp->strm) {
+               /* meaningless for HTX buffers */
+               if (IS_HTX_STRM(smp->strm))
+                       return 0;
                chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
                head = ci_head(chn);
                data = ci_data(chn);
        }
        else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) {
-               struct buffer *buf = &(__objt_check(smp->sess->origin)->bi);
-               head = b_head(buf);
-               data = b_data(buf);
+               struct check *check = __objt_check(smp->sess->origin);
+
+               /* meaningless for HTX buffers */
+               if (check->cs && IS_HTX_CS(check->cs))
+                       return 0;
+               head = b_head(&check->bi);
+               data = b_data(&check->bi);
        }
        max = global.tune.bufsize;
        if (!head)
@@ -1143,6 +1191,10 @@ smp_fetch_distcc_param(const struct arg *arg_p, struct sample *smp, const char *
        if (!smp->strm)
                return 0;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               return 0;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 
        ofs = 0; occ = 0;
@@ -1220,6 +1272,10 @@ smp_fetch_distcc_body(const struct arg *arg_p, struct sample *smp, const char *k
        if (!smp->strm)
                return 0;
 
+       /* meaningless for HTX buffers */
+       if (IS_HTX_STRM(smp->strm))
+               return 0;
+
        chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
 
        ofs = 0; occ = 0;