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
This commit is contained in:
Daniel Stenberg 2022-12-30 17:37:11 +01:00
Родитель 49f39dfac9
Коммит df856cb5c9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 5CC908FDB71E12C2
10 изменённых файлов: 164 добавлений и 92 удалений

Просмотреть файл

@ -698,19 +698,25 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
* protocols array in `struct ssl_backend_data`.
*/
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_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);
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
#ifndef CURL_DISABLE_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);
}
#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);

Просмотреть файл

@ -704,23 +704,28 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
int cur = 0;
gnutls_datum_t protocols[2];
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_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);
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
#ifndef CURL_DISABLE_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;
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");

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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];
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_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;
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
#ifndef CURL_DISABLE_PROXY
&& (!Curl_ssl_cf_is_proxy(cf) || !cf->conn->bits.tunnel_proxy)
#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_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;
}
if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess)
goto error;

Просмотреть файл

@ -3642,25 +3642,32 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
int cur = 0;
unsigned char protocols[128];
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_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;
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
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
#ifndef CURL_DISABLE_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;
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
*/

Просмотреть файл

@ -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);

Просмотреть файл

@ -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);

Просмотреть файл

@ -1790,20 +1790,25 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
&kCFTypeArrayCallBacks);
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2
#ifndef CURL_DISABLE_PROXY
&& (!isproxy || !cf->conn->bits.tunnel_proxy)
#endif
) {
CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
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
#ifndef CURL_DISABLE_PROXY
&& (!isproxy || !cf->conn->bits.tunnel_proxy)
#endif
) {
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
*/

Просмотреть файл

@ -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"

Просмотреть файл

@ -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) {