]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
vtls: use ALPN HTTP/1.0 when HTTP/1.0 is used
authorDaniel Stenberg <daniel@haxx.se>
Fri, 30 Dec 2022 16:37:11 +0000 (17:37 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 31 Dec 2022 15:53:21 +0000 (16:53 +0100)
Previously libcurl would use the HTTP/1.1 ALPN id even when the
application specified HTTP/1.0.

Reported-by: William Tang
Ref: #10183

lib/vtls/bearssl.c
lib/vtls/gtls.c
lib/vtls/mbedtls.c
lib/vtls/nss.c
lib/vtls/openssl.c
lib/vtls/rustls.c
lib/vtls/schannel.c
lib/vtls/sectransp.c
lib/vtls/vtls.h
lib/vtls/wolfssl.c

index d9c0ce0eed11d76eec82d23b1c2ea84c702d1122..86b2b3989763210e461cdd48b0ff8502d606df56 100644 (file)
@@ -698,19 +698,25 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
      * protocols array in `struct ssl_backend_data`.
      */
 
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      backend->protocols[cur++] = ALPN_HTTP_1_0;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
+    }
+    else {
 #ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
-      && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
+         && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
 #endif
-      ) {
-      backend->protocols[cur++] = ALPN_H2;
-      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
-    }
+        ) {
+        backend->protocols[cur++] = ALPN_H2;
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+      }
 #endif
 
-    backend->protocols[cur++] = ALPN_HTTP_1_1;
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      backend->protocols[cur++] = ALPN_HTTP_1_1;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+    }
 
     br_ssl_engine_set_protocol_names(&backend->ctx.eng,
                                      backend->protocols, cur);
index 104dce60935bbc6637bfcc68b7590a703e3d64f8..3857cc303a3a1feb013f6834a86bd4b11469166e 100644 (file)
@@ -704,23 +704,28 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     int cur = 0;
     gnutls_datum_t protocols[2];
 
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      protocols[cur].data = (unsigned char *)ALPN_HTTP_1_0;
+      protocols[cur++].size = ALPN_HTTP_1_0_LENGTH;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
+    }
+    else {
 #ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
-       && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
+         && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
 #endif
-       ) {
-      protocols[cur].data = (unsigned char *)ALPN_H2;
-      protocols[cur].size = ALPN_H2_LENGTH;
-      cur++;
-      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
-    }
+        ) {
+        protocols[cur].data = (unsigned char *)ALPN_H2;
+        protocols[cur++].size = ALPN_H2_LENGTH;
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+      }
 #endif
 
-    protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
-    protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
-    cur++;
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
+      protocols[cur++].size = ALPN_HTTP_1_1_LENGTH;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+    }
 
     if(gnutls_alpn_set_protocols(backend->gtls.session, protocols, cur, 0)) {
       failf(data, "failed setting ALPN");
index 0b81662b939cb0245da29306dc56b67c926d1355..5fef12fc7fa6ae1c2b9c242e9dc963681352c7a3 100644 (file)
@@ -650,11 +650,16 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 #ifdef HAS_ALPN
   if(cf->conn->bits.tls_enable_alpn) {
     const char **p = &backend->protocols[0];
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      *p++ = ALPN_HTTP_1_0;
+    }
+    else {
 #ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2)
-      *p++ = ALPN_H2;
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2)
+        *p++ = ALPN_H2;
 #endif
-    *p++ = ALPN_HTTP_1_1;
+      *p++ = ALPN_HTTP_1_1;
+    }
     *p = NULL;
     /* this function doesn't clone the protocols array, which is why we need
        to keep it around */
index 03694d22ba72478a3693a3618eaf52d6ed249c19..790f4464ec41e162e91725d92139c2ed25d5080e 100644 (file)
@@ -896,6 +896,10 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
        !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
       cf->conn->alpn = CURL_HTTP_VERSION_1_1;
     }
+    else if(buflen == ALPN_HTTP_1_0_LENGTH &&
+            !memcmp(ALPN_HTTP_1_0, buf, ALPN_HTTP_1_0_LENGTH)) {
+      cf->conn->alpn = CURL_HTTP_VERSION_1_0;
+    }
 
     /* This callback might get called when PR_Recv() is used within
      * close_one() during a connection shutdown. At that point there might not
@@ -2167,20 +2171,27 @@ static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
     int cur = 0;
     unsigned char protocols[128];
 
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      protocols[cur++] = ALPN_HTTP_1_0_LENGTH;
+      memcpy(&protocols[cur], ALPN_HTTP_1_0, ALPN_HTTP_1_0_LENGTH);
+      cur += ALPN_HTTP_1_0_LENGTH;
+    }
+    else {
 #ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
-       && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
+         && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
 #endif
-      ) {
-      protocols[cur++] = ALPN_H2_LENGTH;
-      memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
-      cur += ALPN_H2_LENGTH;
-    }
+        ) {
+        protocols[cur++] = ALPN_H2_LENGTH;
+        memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
+        cur += ALPN_H2_LENGTH;
+      }
 #endif
-    protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
-    memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
-    cur += ALPN_HTTP_1_1_LENGTH;
+      protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
+      memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
+      cur += ALPN_HTTP_1_1_LENGTH;
+    }
 
     if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess)
       goto error;
index 2c2ebfff4fdd7cceb28ee4fc356155a17f2787b8..f5dd14d53f89494f5a4a716aa3dd5c0fcde106b1 100644 (file)
@@ -3642,25 +3642,32 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
     int cur = 0;
     unsigned char protocols[128];
 
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      protocols[cur++] = ALPN_HTTP_1_0_LENGTH;
+      memcpy(&protocols[cur], ALPN_HTTP_1_0, ALPN_HTTP_1_0_LENGTH);
+      cur += ALPN_HTTP_1_0_LENGTH;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
+    }
+    else {
 #ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
-       && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
+         && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
 #endif
-      ) {
-      protocols[cur++] = ALPN_H2_LENGTH;
+        ) {
+        protocols[cur++] = ALPN_H2_LENGTH;
 
-      memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
-      cur += ALPN_H2_LENGTH;
-      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
-    }
+        memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
+        cur += ALPN_H2_LENGTH;
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+      }
 #endif
 
-    protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
-    memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
-    cur += ALPN_HTTP_1_1_LENGTH;
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
+      protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
+      memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
+      cur += ALPN_HTTP_1_1_LENGTH;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+    }
     /* expects length prefixed preference ordered list of protocols in wire
      * format
      */
index 27f4ec8d8c2ad204c184a910ede7228347412e1b..6cb0731a98c6d6de862e9713fb83e62ea644a6f6 100644 (file)
@@ -349,22 +349,40 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
   char errorbuf[256];
   size_t errorlen;
   int result;
-  rustls_slice_bytes alpn[2] = {
-    { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH },
-    { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH },
-  };
 
   DEBUGASSERT(backend);
   rconn = backend->conn;
 
   config_builder = rustls_client_config_builder_new();
+  if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+    rustls_slice_bytes alpn[] = {
+      { (const uint8_t *)ALPN_HTTP_1_0, ALPN_HTTP_1_0_LENGTH }
+    };
+    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
+    rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 1);
+  }
+  else {
+    rustls_slice_bytes alpn[2] = {
+      { (const uint8_t *)ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH },
+      { (const uint8_t *)ALPN_H2, ALPN_H2_LENGTH },
+    };
 #ifdef USE_HTTP2
-  infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
-  rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 2);
-#else
-  rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 1);
+    if(data->state.httpwant >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+       && (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
 #endif
-  infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      ) {
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+      rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 2);
+    }
+    else
+#endif
+    {
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      rustls_client_config_builder_set_alpn_protocols(config_builder, alpn, 1);
+    }
+  }
   if(!verifypeer) {
     rustls_client_config_builder_dangerous_set_certificate_verifier(
       config_builder, cr_verify_none);
index 7eab9542af335b71cfc1ff70e0dacbf85dcb7e71..7a279839f085c0b449596602df6812c3dc4f5278 100644 (file)
@@ -1215,19 +1215,27 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
 
     list_start_index = cur;
 
-#ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
-      alpn_buffer[cur++] = ALPN_H2_LENGTH;
-      memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
-      cur += ALPN_H2_LENGTH;
-      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      alpn_buffer[cur++] = ALPN_HTTP_1_0_LENGTH;
+      memcpy(&alpn_buffer[cur], ALPN_HTTP_1_0, ALPN_HTTP_1_0_LENGTH);
+      cur += ALPN_HTTP_1_0_LENGTH;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
     }
+    else {
+#ifdef USE_HTTP2
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
+        alpn_buffer[cur++] = ALPN_H2_LENGTH;
+        memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
+        cur += ALPN_H2_LENGTH;
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+      }
 #endif
 
-    alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
-    memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
-    cur += ALPN_HTTP_1_1_LENGTH;
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
+      memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
+      cur += ALPN_HTTP_1_1_LENGTH;
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+    }
 
     *list_len = curlx_uitous(cur - list_start_index);
     *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
index ab7965465f5a321930071aea159afdf1c8a2bb38..aa25d1b15c65e498dc56ea100c72714248464e3d 100644 (file)
@@ -1790,20 +1790,25 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
       CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
                                                        &kCFTypeArrayCallBacks);
 
+      if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+        CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_0));
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
+      }
+      else {
 #ifdef USE_HTTP2
-      if(data->state.httpwant >= CURL_HTTP_VERSION_2
+        if(data->state.httpwant >= CURL_HTTP_VERSION_2
 #ifndef CURL_DISABLE_PROXY
-         && (!isproxy || !cf->conn->bits.tunnel_proxy)
+           && (!isproxy || !cf->conn->bits.tunnel_proxy)
 #endif
-        ) {
-        CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
-        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
-      }
+          ) {
+          CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
+          infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+        }
 #endif
 
-      CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
-      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
+        CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+      }
       /* expects length prefixed preference ordered list of protocols in wire
        * format
        */
index 1c121ee0e46adfae457e192c102821a5d5a649a0..0dad7eebb53b78d165a94e013443024077a4805a 100644 (file)
@@ -69,6 +69,8 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
 /* see https://www.iana.org/assignments/tls-extensiontype-values/ */
 #define ALPN_HTTP_1_1_LENGTH 8
 #define ALPN_HTTP_1_1 "http/1.1"
+#define ALPN_HTTP_1_0_LENGTH 8
+#define ALPN_HTTP_1_0 "http/1.0"
 #define ALPN_H2_LENGTH 2
 #define ALPN_H2 "h2"
 
index 7cc4774e83237e2630f075320f83b900fb39bb7b..9aa1e7486568633234dc31e35c3e2274ab2be62f 100644 (file)
@@ -640,16 +640,21 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     /* wolfSSL's ALPN protocol name list format is a comma separated string of
        protocols in descending order of preference, eg: "h2,http/1.1" */
 
-#ifdef USE_HTTP2
-    if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
-      strcpy(protocols + strlen(protocols), ALPN_H2 ",");
-      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+    if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+      strcpy(protocols, ALPN_HTTP_1_0);
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_0);
     }
+    else {
+#ifdef USE_HTTP2
+      if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
+        strcpy(protocols + strlen(protocols), ALPN_H2 ",");
+        infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
+      }
 #endif
 
-    strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
-    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
-
+      strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
+      infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
+    }
     if(wolfSSL_UseALPN(backend->handle, protocols,
                        (unsigned)strlen(protocols),
                        WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {