summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-02-11 16:30:32 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-02-11 16:30:32 +0100
commitffec6111a5dba38dc418b5583b03fab0052b05f6 (patch)
tree23f6ec48ae762dde34fc4c656a6072ab820e931f
parent1560cd1f9f5a2ecfe91d138a3189160c212855a4 (diff)
downloadcurl-bagder/http-state-version.tar.gz
urldata: don't touch data->set.httpversion at run-timebagder/http-state-version
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
-rw-r--r--lib/c-hyper.c2
-rw-r--r--lib/http.c37
-rw-r--r--lib/multi.c2
-rw-r--r--lib/setopt.c2
-rw-r--r--lib/transfer.c4
-rw-r--r--lib/url.c4
-rw-r--r--lib/urldata.h13
-rw-r--r--lib/vtls/bearssl.c2
-rw-r--r--lib/vtls/gtls.c2
-rw-r--r--lib/vtls/mbedtls.c2
-rw-r--r--lib/vtls/nss.c2
-rw-r--r--lib/vtls/openssl.c4
-rw-r--r--lib/vtls/schannel.c2
-rw-r--r--lib/vtls/sectransp.c2
-rw-r--r--lib/vtls/wolfssl.c4
-rw-r--r--tests/data/Makefile.inc2
-rw-r--r--tests/data/test12957
17 files changed, 109 insertions, 34 deletions
diff --git a/lib/c-hyper.c b/lib/c-hyper.c
index 10bd7ef9b..8b4abd37f 100644
--- a/lib/c-hyper.c
+++ b/lib/c-hyper.c
@@ -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");
diff --git a/lib/http.c b/lib/http.c
index 1141102f6..d6eceb7d5 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -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 */
diff --git a/lib/multi.c b/lib/multi.c
index e0862551d..bae8398bc 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -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)
diff --git a/lib/setopt.c b/lib/setopt.c
index 715b2f284..a12873760 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -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:
diff --git a/lib/transfer.c b/lib/transfer.c
index c3b2d11a2..0b27b3455 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -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;
diff --git a/lib/url.c b/lib/url.c
index f160b1596..d21e4ad4f 100644
--- 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;
}
diff --git a/lib/urldata.h b/lib/urldata.h
index 6a9c52c44..b78bf905c 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -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 */
diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
index 8efb7b96f..36c32d8d5 100644
--- a/lib/vtls/bearssl.c
+++ b/lib/vtls/bearssl.c
@@ -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
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index be2a43077..333ff8b2f 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -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
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 1739b6eb1..99affe092 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -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;
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 1314e2c06..bc6c3caeb 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -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
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index c4621d8d3..ed374dc32 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -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
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index bdc0e133b..d7abd5966 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -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);
diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index f117e7f64..def325c24 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -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
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index 169614c29..dc79d8b14 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -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))
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index e162abba9..0b0e90d3e 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -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
index 000000000..6fe4ad9c5
--- /dev/null
+++ b/tests/data/test129
@@ -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
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+# CURLE_UNSUPPORTED_PROTOCOL
+<errorcode>
+1
+</errorcode>
+</verify>
+</testcase>