]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: reject HTTP major version switch mid connection
authorDaniel Stenberg <daniel@haxx.se>
Fri, 19 Apr 2024 08:27:04 +0000 (10:27 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 19 Apr 2024 11:34:00 +0000 (13:34 +0200)
A connection that has seen an HTTP major version now refuses any other
major HTTP version in future responses. Previously, a HTTP/1.x
connection would just silently accept HTTP/2 or HTTP/3 in the status
lines as long as it had support for those built-in. It would then just
lead to confusion and badness.

Indirectly Spotted by CodeSonar which identified a duplicate assignment
in this function.

Add test 471 to verify

Closes #13421

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

index dbec52158f7d9a14b05c38b4478ede0a0be412a7..9470d2ec62404f44245c92fa9a13ebcb145dda79 100644 (file)
@@ -3202,10 +3202,13 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
 #ifdef USE_HTTP3
   case 30:
 #endif
-    /* TODO: we should verify that responses do not switch major
-     * HTTP version of the connection. Now, it seems we might accept
-     * a HTTP/2 response on a HTTP/1.1 connection, which is wrong. */
-    conn->httpversion = (unsigned char)k->httpversion;
+    /* no major version switch mid-connection */
+    if(conn->httpversion &&
+       (k->httpversion/10 != conn->httpversion/10)) {
+      failf(data, "Version mismatch (from HTTP/%u to HTTP/%u)",
+            conn->httpversion/10, k->httpversion/10);
+      return CURLE_UNSUPPORTED_PROTOCOL;
+    }
     break;
   default:
     failf(data, "Unsupported HTTP version (%u.%d) in response",
index 1acf48109fc665662d795dd570b8786f338c4f97..97e016708089b50a1412419a813e2d26c29055f9 100644 (file)
@@ -73,7 +73,7 @@ test426 test427 test428 test429 test430 test431 test432 test433 test434 \
 test435 test436 test437 test438 test439 test440 test441 test442 test443 \
 test444 test445 test446 test447 test448 test449 test450 test451 test452 \
 test453 test454 test455 test456 test457 test458 test459 test460 test461 \
-test462 test463 test467 test468 test469 test470 \
+test462 test463 test467 test468 test469 test470 test471 \
 \
 test490 test491 test492 test493 test494 test495 test496 test497 test498 \
 test499 test500 test501 test502 test503 test504 test505 test506 test507 \
diff --git a/tests/data/test471 b/tests/data/test471
new file mode 100644 (file)
index 0000000..69ecb5e
--- /dev/null
@@ -0,0 +1,74 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+globbing
+{} list
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+<data1>
+HTTP/2 200 OK
+Content-Type: text/html
+Funny-head: swsclose
+Connection: close
+
+crap data
+</data1>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+http/2
+http
+</features>
+<server>
+http
+</server>
+<name>
+Reject HTTP/1.1 to HTTP/2 switch on the same connection
+</name>
+ <command option="no-output">
+"http://%HOSTIP:%HTTPPORT/{%TESTNUMBER,%TESTNUMBER0001}" -o "%LOGDIR/dumpit#1.dump"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+GET /%TESTNUMBER0001 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+</protocol>
+# curl: (1) Version mismatch (from HTTP/1 to HTTP/2)
+<errorcode>
+1
+</errorcode>
+</verify>
+</testcase>