BUG/MINOR: http-htx: Expect no body for 204/304 internal HTTP responses
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 9 Oct 2020 06:50:26 +0000 (08:50 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 9 Oct 2020 09:20:22 +0000 (11:20 +0200)
204 and 304 HTTP responses must no contain message body. These status codes are
correctly handled when the responses are received from a server. But there is no
specific processing for internal HTTP reponses (errorfile and http replies).

Now, when errorfiles or an http replies are parsed during the configuration
parsing, an error is triggered if a 204/304 message contains a body. An extra
check is also performed to ensure the body length matches the announce
content-length.

This patch should fix the issue #891. It must be backported as far as 2.0. For
2.1 and 2.0, only the http_str_to_htx() function must be fixed.
http_parse_http_reply() function does not exist.

(cherry picked from commit b8d148a93f0daff9821cb9ecc5934499f8d128a2)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit dde6c42da611badbf515c687a69c457aa8ecc40b)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/http_htx.c

index 154af3e..91f6a17 100644 (file)
@@ -793,17 +793,36 @@ int http_str_to_htx(struct buffer *buf, struct ist raw)
        if (h1sl.st.status < 200 && (h1sl.st.status == 100 || h1sl.st.status >= 102))
                goto error;
 
+       if (h1sl.st.status == 204 || h1sl.st.status == 304) {
+               /* Responses known to have no body. */
+               h1m.flags &= ~(H1_MF_CLEN|H1_MF_CHNK);
+               h1m.flags |= H1_MF_XFER_LEN;
+               h1m.curr_len = h1m.body_len = 0;
+       }
+       else if (h1m.flags & (H1_MF_CLEN|H1_MF_CHNK))
+               h1m.flags |= H1_MF_XFER_LEN;
+
        if (h1m.flags & H1_MF_VER_11)
                flags |= HTX_SL_F_VER_11;
        if (h1m.flags & H1_MF_XFER_ENC)
                flags |= HTX_SL_F_XFER_ENC;
-       if (h1m.flags & H1_MF_CLEN) {
-               flags |= (HTX_SL_F_XFER_LEN|HTX_SL_F_CLEN);
-               if (h1m.body_len == 0)
+       if (h1m.flags & H1_MF_XFER_LEN) {
+               flags |= HTX_SL_F_XFER_LEN;
+               if (h1m.flags & H1_MF_CHNK)
+                       goto error; /* Unsupported because there is no body parsing */
+               else if (h1m.flags & H1_MF_CLEN) {
+                       flags |= HTX_SL_F_CLEN;
+                       if (h1m.body_len == 0)
+                               flags |= HTX_SL_F_BODYLESS;
+               }
+               else
                        flags |= HTX_SL_F_BODYLESS;
        }
-       if (h1m.flags & H1_MF_CHNK)
-               goto error; /* Unsupported because there is no body parsing */
+
+       if ((flags & HTX_SL_F_BODYLESS) && raw.len > ret)
+               goto error; /* No body expected */
+       if ((flags & HTX_SL_F_CLEN) && h1m.body_len != (raw.len - ret))
+               goto error; /* body with wrong length */
 
        htx = htx_from_buf(buf);
        sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, h1sl.st.v, h1sl.st.c, h1sl.st.r);