From 4bcc532de5b639ace6f96f0a30524a08861843b1 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 13 Dec 2015 09:23:36 +0100 Subject: http: add libcurl option to allow HTTP/2 for HTTPS only ... and stick to 1.1 for HTTP. This is in line with what browsers do and should have very little risk. --- docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 | 9 ++++++++- docs/libcurl/symbols-in-versions | 1 + include/curl/curl.h | 3 ++- lib/http.c | 16 +++++++++------- lib/url.c | 4 ++-- lib/vtls/gtls.c | 4 ++-- lib/vtls/mbedtls.c | 4 ++-- lib/vtls/nss.c | 4 ++-- lib/vtls/openssl.c | 8 ++++---- lib/vtls/polarssl.c | 4 ++-- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 index aed7c0efe..262365e06 100644 --- a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 +++ b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 @@ -45,8 +45,15 @@ Enforce HTTP 1.0 requests. .IP CURL_HTTP_VERSION_1_1 Enforce HTTP 1.1 requests. .IP CURL_HTTP_VERSION_2_0 -Attempt HTTP 2 requests. libcurl will fall back to HTTP 1.x if HTTP 2 can't be +Attempt HTTP 2 requests. libcurl will fall back to HTTP 1.1 if HTTP 2 can't be negotiated with the server. (Added in 7.33.0) + +The alias \fICURL_HTTP_VERSION_2\fI was added in 7.43.0 to better reflect the +actual protocol name. +.IP CURL_HTTP_VERSION_2TLS +Attempt HTTP 2 over TLS (HTTPS) only. libcurl will fall back to HTTP 1.1 if +HTTP 2 can't be negotiated with the HTTPS server. For clear text HTTP servers, +libcurl will use 1.1. (Added in 7.47.0) .SH DEFAULT CURL_HTTP_VERSION_NONE .SH PROTOCOLS diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index ef7981fd9..629d2241c 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -692,6 +692,7 @@ CURL_HTTP_VERSION_1_0 7.9.1 CURL_HTTP_VERSION_1_1 7.9.1 CURL_HTTP_VERSION_2 7.43.0 CURL_HTTP_VERSION_2_0 7.33.0 +CURL_HTTP_VERSION_2TLS 7.47.0 CURL_HTTP_VERSION_NONE 7.9.1 CURL_IPRESOLVE_V4 7.10.8 CURL_IPRESOLVE_V6 7.10.8 diff --git a/include/curl/curl.h b/include/curl/curl.h index 7fd533e51..84229bb69 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1722,7 +1722,8 @@ enum { for us! */ CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ - CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ }; diff --git a/lib/http.c b/lib/http.c index 3c9fde54a..b77003fe7 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1539,11 +1539,13 @@ CURLcode Curl_http_done(struct connectdata *conn, static bool use_http_1_1plus(const struct SessionHandle *data, const struct connectdata *conn) { - return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) || - ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && - ((conn->httpversion == 11) || - ((conn->httpversion != 10) && - (data->state.httpversion != 10))))) ? TRUE : FALSE; + if((data->state.httpversion == 10) || (conn->httpversion == 10)) + return FALSE; + if((data->set.httpversion == 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)); } /* check and possibly add an Expect: header */ @@ -1785,7 +1787,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->httpversion < 20) { /* unless the connection is re-used and already http2 */ switch(conn->negnpn) { - case CURL_HTTP_VERSION_2_0: + case CURL_HTTP_VERSION_2: conn->httpversion = 20; /* we know we're on HTTP/2 now */ result = Curl_http2_init(conn); if(result) @@ -2338,7 +2340,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(!(conn->handler->flags&PROTOPT_SSL) && conn->httpversion != 20 && - (data->set.httpversion == CURL_HTTP_VERSION_2_0)) { + (data->set.httpversion == 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_buffer, conn); diff --git a/lib/url.c b/lib/url.c index 13e95f42c..5a83207da 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1294,7 +1294,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, */ arg = va_arg(param, long); #ifndef USE_NGHTTP2 - if(arg == CURL_HTTP_VERSION_2_0) + if(arg >= CURL_HTTP_VERSION_2) return CURLE_UNSUPPORTED_PROTOCOL; #endif data->set.httpversion = arg; @@ -2865,7 +2865,7 @@ static bool IsPipeliningPossible(const struct SessionHandle *handle, return TRUE; if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) && - (handle->set.httpversion == CURL_HTTP_VERSION_2_0)) + (handle->set.httpversion >= CURL_HTTP_VERSION_2)) /* allows HTTP/2 */ return TRUE; } diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 1c1cc2f7b..59cd7fb11 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -638,7 +638,7 @@ gtls_connect_step1(struct connectdata *conn, gnutls_datum_t protocols[2]; #ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; cur++; @@ -1242,7 +1242,7 @@ gtls_connect_step3(struct connectdata *conn, if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN && !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = CURL_HTTP_VERSION_2; } else #endif diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 0616e6836..2fbf9b8d2 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -374,7 +374,7 @@ mbedtls_connect_step1(struct connectdata *conn, } #ifdef HAS_ALPN - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { if(data->set.ssl_enable_alpn) { static const char* protocols[] = { NGHTTP2_PROTO_VERSION_ID, ALPN_HTTP_1_1, NULL @@ -475,7 +475,7 @@ mbedtls_connect_step2(struct connectdata *conn, if(strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = CURL_HTTP_VERSION_2; } else if(strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_1_1; diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index c8bd0cef6..aacdd6c85 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -720,7 +720,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) #ifdef USE_NGHTTP2 if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = CURL_HTTP_VERSION_2; } else #endif @@ -1779,7 +1779,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) unsigned char protocols[128]; #ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN); diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index fdc27b04d..e5b0bb99b 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -1582,12 +1582,12 @@ select_next_proto_cb(SSL *ssl, (void)ssl; #ifdef USE_NGHTTP2 - if(conn->data->set.httpversion == CURL_HTTP_VERSION_2_0 && + if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 && !select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN)) { infof(conn->data, "NPN, negotiated HTTP2 (%s)\n", NGHTTP2_PROTO_VERSION_ID); - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = CURL_HTTP_VERSION_2; return SSL_TLSEXT_ERR_OK; } #endif @@ -1859,7 +1859,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) unsigned char protocols[128]; #ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, @@ -2185,7 +2185,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) #ifdef USE_NGHTTP2 if(len == NGHTTP2_PROTO_VERSION_ID_LEN && !memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = CURL_HTTP_VERSION_2; } else #endif diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c index cf7c344a5..e7bcf2f9b 100644 --- a/lib/vtls/polarssl.c +++ b/lib/vtls/polarssl.c @@ -359,7 +359,7 @@ polarssl_connect_step1(struct connectdata *conn, int cur = 0; #ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } @@ -463,7 +463,7 @@ polarssl_connect_step2(struct connectdata *conn, #ifdef USE_NGHTTP2 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + conn->negnpn = CURL_HTTP_VERSION_2; } else #endif -- cgit v1.2.3