diff options
author | Daniel Stenberg <daniel@haxx.se> | 2022-12-30 17:37:11 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2022-12-31 16:53:21 +0100 |
commit | df856cb5c94665c9083dc8be5bb02392d841cc1e (patch) | |
tree | 32ae63da4d04f6fba31914e025e84649d6ac3b72 | |
parent | 49f39dfac9278060cb750e006d4f46e841cdfeb2 (diff) | |
download | curl-df856cb5c94665c9083dc8be5bb02392d841cc1e.tar.gz |
vtls: use ALPN HTTP/1.0 when HTTP/1.0 is used
Previously libcurl would use the HTTP/1.1 ALPN id even when the
application specified HTTP/1.0.
Reported-by: William Tang
Ref: #10183
-rw-r--r-- | lib/vtls/bearssl.c | 22 | ||||
-rw-r--r-- | lib/vtls/gtls.c | 29 | ||||
-rw-r--r-- | lib/vtls/mbedtls.c | 11 | ||||
-rw-r--r-- | lib/vtls/nss.c | 31 | ||||
-rw-r--r-- | lib/vtls/openssl.c | 33 | ||||
-rw-r--r-- | lib/vtls/rustls.c | 36 | ||||
-rw-r--r-- | lib/vtls/schannel.c | 28 | ||||
-rw-r--r-- | lib/vtls/sectransp.c | 23 | ||||
-rw-r--r-- | lib/vtls/vtls.h | 2 | ||||
-rw-r--r-- | lib/vtls/wolfssl.c | 19 |
10 files changed, 153 insertions, 81 deletions
diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c index d9c0ce0ee..86b2b3989 100644 --- a/lib/vtls/bearssl.c +++ b/lib/vtls/bearssl.c @@ -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); diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 104dce609..3857cc303 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -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"); diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 0b81662b9..5fef12fc7 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -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 */ diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 03694d22b..790f4464e 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -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; diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 2c2ebfff4..f5dd14d53 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -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 */ diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index 27f4ec8d8..6cb0731a9 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -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); diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 7eab9542a..7a279839f 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -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); diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c index ab7965465..aa25d1b15 100644 --- a/lib/vtls/sectransp.c +++ b/lib/vtls/sectransp.c @@ -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 */ diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 1c121ee0e..0dad7eebb 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -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" diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 7cc4774e8..9aa1e7486 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -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) { |