summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2022-12-30 17:37:11 +0100
committerDaniel Stenberg <daniel@haxx.se>2022-12-31 16:53:21 +0100
commitdf856cb5c94665c9083dc8be5bb02392d841cc1e (patch)
tree32ae63da4d04f6fba31914e025e84649d6ac3b72
parent49f39dfac9278060cb750e006d4f46e841cdfeb2 (diff)
downloadcurl-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.c22
-rw-r--r--lib/vtls/gtls.c29
-rw-r--r--lib/vtls/mbedtls.c11
-rw-r--r--lib/vtls/nss.c31
-rw-r--r--lib/vtls/openssl.c33
-rw-r--r--lib/vtls/rustls.c36
-rw-r--r--lib/vtls/schannel.c28
-rw-r--r--lib/vtls/sectransp.c23
-rw-r--r--lib/vtls/vtls.h2
-rw-r--r--lib/vtls/wolfssl.c19
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) {