]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: only act on 101 responses when they are HTTP/1.1
authorDaniel Stenberg <daniel@haxx.se>
Sat, 27 Jan 2024 12:54:10 +0000 (13:54 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 27 Jan 2024 20:49:20 +0000 (21:49 +0100)
For 101 responses claiming to be any other protocol, bail out. This
would previously trigger an assert.

Add test 1704 to verify.

Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66184
Closes #12811

lib/http.c
tests/data/Makefile.inc
tests/data/test1704 [new file with mode: 0644]

index 0c2a460903504599847a1fc58330108bb27ecca3..679931e4b4a068cbecd5939ba863ae1f898f4b19 100644 (file)
@@ -4036,34 +4036,40 @@ static CURLcode http_rw_headers(struct Curl_easy *data,
           }
           break;
         case 101:
-          /* Switching Protocols */
-          if(k->upgr101 == UPGR101_H2) {
-            /* Switching to HTTP/2 */
-            DEBUGASSERT(conn->httpversion < 20);
-            infof(data, "Received 101, Switching to HTTP/2");
-            k->upgr101 = UPGR101_RECEIVED;
-
-            /* we'll get more headers (HTTP/2 response) */
-            k->header = TRUE;
-            k->headerline = 0; /* restart the header line counter */
-            switch_to_h2 = TRUE;
-          }
+          if(conn->httpversion == 11) {
+            /* Switching Protocols only allowed from HTTP/1.1 */
+            if(k->upgr101 == UPGR101_H2) {
+              /* Switching to HTTP/2 */
+              infof(data, "Received 101, Switching to HTTP/2");
+              k->upgr101 = UPGR101_RECEIVED;
+
+              /* we'll get more headers (HTTP/2 response) */
+              k->header = TRUE;
+              k->headerline = 0; /* restart the header line counter */
+              switch_to_h2 = TRUE;
+            }
 #ifdef USE_WEBSOCKETS
-          else if(k->upgr101 == UPGR101_WS) {
-            /* verify the response */
-            result = Curl_ws_accept(data, buf, blen);
-            if(result)
-              return result;
-            k->header = FALSE; /* no more header to parse! */
-            *pconsumed += blen; /* ws accept handled the data */
-            blen = 0;
-            if(data->set.connect_only)
-              k->keepon &= ~KEEP_RECV; /* read no more content */
-          }
+            else if(k->upgr101 == UPGR101_WS) {
+              /* verify the response */
+              result = Curl_ws_accept(data, buf, blen);
+              if(result)
+                return result;
+              k->header = FALSE; /* no more header to parse! */
+              *pconsumed += blen; /* ws accept handled the data */
+              blen = 0;
+              if(data->set.connect_only)
+                k->keepon &= ~KEEP_RECV; /* read no more content */
+            }
 #endif
+            else {
+              /* Not switching to another protocol */
+              k->header = FALSE; /* no more header to parse! */
+            }
+          }
           else {
-            /* Not switching to another protocol */
-            k->header = FALSE; /* no more header to parse! */
+            /* invalid for other HTTP versions */
+            failf(data, "unexpected 101 response code");
+            return CURLE_WEIRD_SERVER_REPLY;
           }
           break;
         default:
index 5b9e3a9ed21bb1bf88ab2c91a050c16a902ececf..c3d496f6468bb8a25d25c3c191aa94fdfed5717a 100644 (file)
@@ -215,7 +215,7 @@ test1670 test1671 \
 \
 test1680 test1681 test1682 test1683 \
 \
-test1700 test1701 test1702 test1703 \
+test1700 test1701 test1702 test1703 test1704 \
 \
 test1800 test1801 \
 \
diff --git a/tests/data/test1704 b/tests/data/test1704
new file mode 100644 (file)
index 0000000..a8f285e
--- /dev/null
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP/2
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/2 101 OK\r
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT\r
+Content-Length: 6\r
+Connection: close\r
+Content-Type: text/html\r
+\r
+-maa-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+h2c
+</features>
+<server>
+http
+</server>
+<name>
+HTTP/1 doing HTTP/2 Upgrade: getting a HTTP/2 101 response
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --http2
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^X-Forwarded-Proto:.*
+^Via:.*
+</strip>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+Connection: Upgrade, HTTP2-Settings\r
+Upgrade: h2c\r
+HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r
+\r
+</protocol>
+
+# CURLE_WEIRD_SERVER_REPLY (8)
+<errorcode>
+8
+</errorcode>
+</verify>
+</testcase>