]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h1: permit to relax the websocket checks for missing mandatory headers
authorWilly Tarreau <w@1wt.eu>
Fri, 28 Feb 2025 12:35:13 +0000 (13:35 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 28 Feb 2025 16:31:20 +0000 (17:31 +0100)
At least one user would like to allow a standards-violating client setup
WebSocket connections through haproxy to a standards-violating server that
accepts them. While this should of course never be done over the internet,
it can make sense in the datacenter between application components which do
not need to mask the data, so this typically falls into the situation of
what the "accept-unsafe-violations-in-http-request" option and the
"accept-unsafe-violations-in-http-response" option are made for.
See GH #2876 for more context.

This patch relaxes the test on the "Sec-Websocket-Key" header field in
the request, and of the "Sec-Websocket-Accept" header in the response
when these respective options are set.

The doc was updated to reference this addition. This may be backported
to 3.1 but preferably not further.

doc/configuration.txt
src/mux_h1.c

index 942198d49893afd1ee67aa04e4f7fd646fe48aa3..941073c92c3f1db9ded28fd53dad15f311738817 100644 (file)
@@ -9444,6 +9444,9 @@ no option accept-unsafe-violations-in-http-request
       different protocol names (e.g. RTSP), and multiple digits for both the
       major and the minor version.
 
+    * In H1 only, WebSocket (RFC6455) requests failing to present a valid
+      "Sec-Websocket-Key" header field will be accepted.
+
   This option should never be enabled by default as it hides application bugs
   and open security breaches. It should only be deployed after a problem has
   been confirmed.
@@ -9494,6 +9497,9 @@ no option accept-unsafe-violations-in-http-response
       different protocol names (e.g. RTSP), and multiple digits for both the
       major and the minor version.
 
+    * In H1 only, WebSocket (RFC6455) responses failing to present a valid
+      "Sec-Websocket-Accept" header field will be accepted.
+
   This option should never be enabled by default as it hides application bugs
   and open security breaches. It should only be deployed after a problem has
   been confirmed.
index c355edd0b1e1d0fcc2493e816d74cb7575028caa..bf7fbaca5e741751b42103f75443e8007dd37045 100644 (file)
@@ -1850,7 +1850,7 @@ static void h1_set_tunnel_mode(struct h1s *h1s)
  * responsible for the generation of a key. This happens when a h2 client is
  * interfaced with a h1 server.
  *
- * Returns 0 if no key found or invalid key
+ * Returns 0 if no key found or invalid key. The message is not modified.
  */
 static int h1_search_websocket_key(struct h1s *h1s, struct h1m *h1m, struct htx *htx)
 {
@@ -1900,11 +1900,9 @@ static int h1_search_websocket_key(struct h1s *h1s, struct h1m *h1m, struct htx
                }
        }
 
-       /* missing websocket key, reject the message */
-       if (!ws_key_found) {
-               htx->flags |= HTX_FL_PARSING_ERROR;
+       /* missing websocket key, invalid message */
+       if (!ws_key_found)
                return 0;
-       }
 
        return 1;
 }
@@ -1986,13 +1984,24 @@ static size_t h1_handle_headers(struct h1s *h1s, struct h1m *h1m, struct htx *ht
        if ((h1m->flags & (H1_MF_CONN_UPG|H1_MF_UPG_WEBSOCKET)) ==
            (H1_MF_CONN_UPG|H1_MF_UPG_WEBSOCKET)) {
                int ws_ret = h1_search_websocket_key(h1s, h1m, htx);
+
                if (!ws_ret) {
-                       h1s->flags |= H1S_F_PARSING_ERROR;
-                       TRACE_ERROR("missing/invalid websocket key, reject H1 message", H1_EV_RX_DATA|H1_EV_RX_HDRS|H1_EV_H1S_ERR, h1s->h1c->conn, h1s);
                        h1_capture_bad_message(h1s->h1c, h1s, h1m, buf);
 
-                       ret = 0;
-                       goto end;
+                       if ((!(h1m->flags & H1_MF_RESP) && !(h1s->h1c->px->options2 & PR_O2_REQBUG_OK)) ||
+                           ((h1m->flags & H1_MF_RESP) && !(h1s->h1c->px->options2 & PR_O2_RSPBUG_OK))) {
+                               htx->flags |= HTX_FL_PARSING_ERROR;
+                               h1s->flags |= H1S_F_PARSING_ERROR;
+                               TRACE_ERROR("missing/invalid websocket key, reject H1 message",
+                                           H1_EV_RX_DATA|H1_EV_RX_HDRS|H1_EV_H1S_ERR, h1s->h1c->conn, h1s);
+
+                               ret = 0;
+                               goto end;
+                       } else {
+                               TRACE_ERROR("missing/invalid websocket key, but accepting this "
+                                           "violation according to configuration",
+                                           H1_EV_RX_DATA|H1_EV_RX_HDRS|H1_EV_H1S_ERR, h1s->h1c->conn, h1s);
+                       }
                }
        }