]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
urldata: don't touch data->set.httpversion at run-time
authorDaniel Stenberg <daniel@haxx.se>
Thu, 11 Feb 2021 15:30:32 +0000 (16:30 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 12 Feb 2021 07:13:37 +0000 (08:13 +0100)
Rename it to 'httpwant' and make a cloned field in the state struct as
well for run-time updates.

Also: refuse non-supported HTTP versions. Verified with test 129.

Closes #6585

17 files changed:
lib/c-hyper.c
lib/http.c
lib/multi.c
lib/setopt.c
lib/transfer.c
lib/url.c
lib/urldata.h
lib/vtls/bearssl.c
lib/vtls/gtls.c
lib/vtls/mbedtls.c
lib/vtls/nss.c
lib/vtls/openssl.c
lib/vtls/schannel.c
lib/vtls/sectransp.c
lib/vtls/wolfssl.c
tests/data/Makefile.inc
tests/data/test129 [new file with mode: 0644]

index 10bd7ef9bf193776666f4311398d032aac92d53a..8b4abd37f856104e7e2fa78b42cda16cc6565516 100644 (file)
@@ -741,7 +741,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     goto error;
   }
 
-  if(data->set.httpversion == CURL_HTTP_VERSION_1_0) {
+  if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
     if(HYPERE_OK != hyper_request_set_version(req,
                                               HYPER_HTTP_VERSION_1_0)) {
       failf(data, "error setting HTTP version");
index 1141102f68bf11fc93aa65aef5b024d8db26e421..d6eceb7d58766feab71ef3171b80d6be08450e36 100644 (file)
@@ -183,7 +183,7 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
   Curl_mime_initpart(&http->form, data);
   data->req.p.http = http;
 
-  if(data->set.httpversion == CURL_HTTP_VERSION_3) {
+  if(data->state.httpwant == CURL_HTTP_VERSION_3) {
     if(conn->handler->flags & PROTOPT_SSL)
       /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
          the QUIC dance. */
@@ -595,7 +595,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
        conn->httpversion > 11) {
       infof(data, "Forcing HTTP/1.1 for NTLM");
       connclose(conn, "Force HTTP/1.1 connection");
-      data->set.httpversion = CURL_HTTP_VERSION_1_1;
+      data->state.httpwant = CURL_HTTP_VERSION_1_1;
     }
   }
 #ifndef CURL_DISABLE_PROXY
@@ -1625,11 +1625,11 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
 {
   if((data->state.httpversion == 10) || (conn->httpversion == 10))
     return FALSE;
-  if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
+  if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
      (conn->httpversion <= 10))
     return FALSE;
-  return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
-          (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
+  return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
+          (data->state.httpwant >= CURL_HTTP_VERSION_1_1));
 }
 
 #ifndef USE_HYPER
@@ -1637,7 +1637,7 @@ static const char *get_http_string(const struct Curl_easy *data,
                                    const struct connectdata *conn)
 {
 #ifdef ENABLE_QUIC
-  if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
+  if((data->state.httpwant == CURL_HTTP_VERSION_3) ||
      (conn->httpversion == 30))
     return "3";
 #endif
@@ -2950,7 +2950,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
       default:
         /* Check if user wants to use HTTP/2 with clear TCP*/
 #ifdef USE_NGHTTP2
-        if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+        if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
 #ifndef CURL_DISABLE_PROXY
           if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
             /* We don't support HTTP/2 proxies yet. Also it's debatable
@@ -3156,7 +3156,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
 
   if(!(conn->handler->flags&PROTOPT_SSL) &&
      conn->httpversion != 20 &&
-     (data->set.httpversion == CURL_HTTP_VERSION_2)) {
+     (data->state.httpwant == CURL_HTTP_VERSION_2)) {
     /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
        over SSL */
     result = Curl_http2_request_upgrade(&req, conn);
@@ -4148,10 +4148,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
          */
         char separator;
         char twoorthree[2];
+        int httpversion = 0;
         nc = sscanf(HEADER1,
                     " HTTP/%1d.%1d%c%3d",
                     &httpversion_major,
-                    &conn->httpversion,
+                    &httpversion,
                     &separator,
                     &k->httpcode);
 
@@ -4163,7 +4164,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
 
         if((nc == 4) && (' ' == separator)) {
-          conn->httpversion += 10 * httpversion_major;
+          httpversion += 10 * httpversion_major;
+          switch(httpversion) {
+          case 10:
+          case 11:
+#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+          case 20:
+#endif
+#if defined(ENABLE_QUIC)
+          case 30:
+#endif
+            conn->httpversion = (unsigned char)httpversion;
+            break;
+          default:
+            failf(data, "Unsupported HTTP version (%u.%d) in response",
+                  httpversion/10, httpversion%10);
+            return CURLE_UNSUPPORTED_PROTOCOL;
+          }
 
           if(k->upgr101 == UPGR101_RECEIVED) {
             /* supposedly upgraded to http2 now */
index e0862551d94c9c68b1a751c0a22acde686f151a6..bae8398bcaab7bce9ae405e1510c7e6a4f2b2f96 100644 (file)
@@ -2173,7 +2173,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 
         if(!ret) {
           infof(data, "Downgrades to HTTP/1.1!\n");
-          data->set.httpversion = CURL_HTTP_VERSION_1_1;
+          data->state.httpwant = CURL_HTTP_VERSION_1_1;
           /* clear the error message bit too as we ignore the one we got */
           data->state.errorbuf = FALSE;
           if(!newurl)
index 715b2f284c12b3245a66e4c89f3f479faf508fb8..a12873760170229be7a2197943b0ec9f70455eb8 100644 (file)
@@ -888,7 +888,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     if(arg == CURL_HTTP_VERSION_NONE)
       arg = CURL_HTTP_VERSION_2TLS;
 #endif
-    data->set.httpversion = arg;
+    data->set.httpwant = (unsigned char)arg;
     break;
 
   case CURLOPT_EXPECT_100_TIMEOUT_MS:
index c3b2d11a2ce5bf7ce2888e75831058bb282fe932..0b27b3455eef15124471a557619a7aea5090048a 100644 (file)
@@ -1431,8 +1431,8 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
   data->state.followlocation = 0; /* reset the location-follow counter */
   data->state.this_is_a_follow = FALSE; /* reset this */
   data->state.errorbuf = FALSE; /* no error has occurred */
-  data->state.httpversion = 0; /* don't assume any particular server version */
-
+  data->state.httpwant = data->set.httpwant;
+  data->state.httpversion = 0;
   data->state.authproblem = FALSE;
   data->state.authhost.want = data->set.httpauth;
   data->state.authproxy.want = data->set.proxyauth;
index f160b1596b367f6249247bcfe36bab19a2c75f3f..d21e4ad4ff1a7dbcfdde3e4426d568532b1ada92 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -609,7 +609,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
   set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
   set->maxage_conn = 118;
   set->http09_allowed = FALSE;
-  set->httpversion =
+  set->httpwant =
 #ifdef USE_NGHTTP2
     CURL_HTTP_VERSION_2TLS
 #else
@@ -887,7 +887,7 @@ static int IsMultiplexingPossible(const struct Curl_easy *handle,
      (!conn->bits.protoconnstart || !conn->bits.close)) {
 
     if(Curl_multiplex_wanted(handle->multi) &&
-       (handle->set.httpversion >= CURL_HTTP_VERSION_2))
+       (handle->state.httpwant >= CURL_HTTP_VERSION_2))
       /* allows HTTP/2 */
       avail |= CURLPIPE_MULTIPLEX;
   }
index 6a9c52c44fc46521fe877810975045fd2ccf98f4..b78bf905ca1d476572aa51e0f9f118e035893e04 100644 (file)
@@ -991,7 +991,7 @@ struct connectdata {
   char *passwd;  /* password string, allocated */
   char *options; /* options string, allocated */
   char *sasl_authzid;     /* authorisation identity string, allocated */
-  int httpversion;        /* the HTTP version*10 reported by the server */
+  unsigned char httpversion; /* the HTTP version*10 reported by the server */
   struct curltime now;     /* "current" time */
   struct curltime created; /* creation time */
   struct curltime lastused; /* when returned to the connection cache */
@@ -1375,9 +1375,10 @@ struct UrlState {
 
   /* a place to store the most recently set FTP entrypath */
   char *most_recent_ftp_entrypath;
-
-  int httpversion;       /* the lowest HTTP version*10 reported by any server
-                            involved in this request */
+  unsigned char httpwant; /* when non-zero, a specific HTTP version requested
+                             to be used in the library's request(s) */
+  unsigned char httpversion; /* the lowest HTTP version*10 reported by any
+                                server involved in this request */
 
 #if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
 /* do FTP line-end conversions on most platforms */
@@ -1718,8 +1719,8 @@ struct UserDefined {
   curl_proxytype proxytype; /* what kind of proxy that is in use */
   time_t timevalue;       /* what time to compare with */
   Curl_HttpReq method;   /* what kind of HTTP request (if any) is this */
-  long httpversion; /* when non-zero, a specific HTTP version requested to
-                       be used in the library's request(s) */
+  unsigned char httpwant; /* when non-zero, a specific HTTP version requested
+                             to be used in the library's request(s) */
   struct ssl_config_data ssl;  /* user defined SSL stuff */
 #ifndef CURL_DISABLE_PROXY
   struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
index 8efb7b96f3fea88b03f2025339c2d4ca42c6ed9d..36c32d8d55bef1fdf5994fd1cdc578de09bfc309 100644 (file)
@@ -390,7 +390,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
      */
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+    if(data->state.httpversion >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
       && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
 #endif
index be2a43077de1c954d27a617e91f7c584a1e6e1bc..333ff8b2f234751069f4f13786ce18c8b1887047 100644 (file)
@@ -618,7 +618,7 @@ gtls_connect_step1(struct Curl_easy *data,
     gnutls_datum_t protocols[2];
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+    if(data->state.httpversion >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
        && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
 #endif
index 1739b6eb12a1bb8335994ad549f1d5e57560711e..99affe0920550fa117a55cc908fbae9a61e5178f 100644 (file)
@@ -495,7 +495,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
   if(conn->bits.tls_enable_alpn) {
     const char **p = &backend->protocols[0];
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2)
+    if(data->state.httpversion >= CURL_HTTP_VERSION_2)
       *p++ = NGHTTP2_PROTO_VERSION_ID;
 #endif
     *p++ = ALPN_HTTP_1_1;
index 1314e2c06e681361bb3edcfabf9e6dc1377ad55f..bc6c3caeb9dcb2780c0a989b3e704728b4381147 100644 (file)
@@ -2080,7 +2080,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
     unsigned char protocols[128];
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+    if(data->state.httpversion >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
       && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
 #endif
index c4621d8d3387b93690565d6560277dc29ac5d325..ed374dc326ada27f60a5955be6e655558abe78b6 100644 (file)
@@ -2222,7 +2222,7 @@ select_next_proto_cb(SSL *ssl,
   (void)ssl;
 
 #ifdef USE_NGHTTP2
-  if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+  if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
      !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
                            NGHTTP2_PROTO_VERSION_ID_LEN)) {
     infof(data, "NPN, negotiated HTTP2 (%s)\n",
@@ -2749,7 +2749,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
     unsigned char protocols[128];
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+    if(data->state.httpwant >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
        && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
 #endif
index bdc0e133b34c8ee08763c41a4a74f8be0eb02cd9..d7abd59666098772eae49c3f83993a12012179d7 100644 (file)
@@ -861,7 +861,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
     list_start_index = cur;
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
+    if(data->state.httpversion >= CURL_HTTP_VERSION_2) {
       memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN);
       cur += NGHTTP2_PROTO_ALPN_LEN;
       infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
index f117e7f640e1e0063faeb3c080696e2dbaa723c2..def325c24f4fd4ba5ee104e2621448c62433e585 100644 (file)
@@ -1611,7 +1611,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
                                                        &kCFTypeArrayCallBacks);
 
 #ifdef USE_NGHTTP2
-      if(data->set.httpversion >= CURL_HTTP_VERSION_2
+      if(data->state.httpversion >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
          && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
 #endif
index 169614c292cb8cbc495838a2544ed9349f6b7dcc..dc79d8b141e313dbe4f44f0c601368087af2a89b 100644 (file)
@@ -475,7 +475,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
        protocols in descending order of preference, eg: "h2,http/1.1" */
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
+    if(data->state.httpversion >= CURL_HTTP_VERSION_2) {
       strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ",");
       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
     }
@@ -724,7 +724,7 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
          !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
         conn->negnpn = CURL_HTTP_VERSION_1_1;
 #ifdef USE_NGHTTP2
-      else if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+      else if(data->state.httpversion >= CURL_HTTP_VERSION_2 &&
               protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
               !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
                       NGHTTP2_PROTO_VERSION_ID_LEN))
index e162abba9f7c351b45f73ede0d839bec476875c9..0b0e90d3e455866da3b901cf869787f7a6477776 100644 (file)
@@ -34,7 +34,7 @@ test90 test91 test92 test93 test94 test95 test96 test97 test98 test99   \
 test100 test101 test102 test103 test104 test105 test106 test107 test108 \
 test109 test110 test111 test112 test113 test114 test115 test116 test117 \
 test118 test119 test120 test121 test122 test123 test124 test125 test126 \
-test127 test128         test130 test131 test132 test133 test134 test135 \
+test127 test128 test129 test130 test131 test132 test133 test134 test135 \
 test136 test137 test138 test139 test140 test141 test142 test143 test144 \
 test145 test146 test147 test148 test149 test150 test151 test152 test153 \
 test154 test155 test156 test157 test158 test159 test160 test161 test162 \
diff --git a/tests/data/test129 b/tests/data/test129
new file mode 100644 (file)
index 0000000..6fe4ad9
--- /dev/null
@@ -0,0 +1,57 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.2 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
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP/1.2 is rejected
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/129
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /129 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+</protocol>
+# CURLE_UNSUPPORTED_PROTOCOL
+<errorcode>
+1
+</errorcode>
+</verify>
+</testcase>