From 909a68c1216b6ea5dbeceaedecec16a0599793d1 Mon Sep 17 00:00:00 2001 From: Fabian Frank Date: Sun, 9 Feb 2014 23:38:55 -0800 Subject: NPN/ALPN: allow disabling via command line when using --http2 one can now selectively disable NPN or ALPN with --no-alpn and --no-npn. for now honored with NSS only. TODO: honor this option with GnuTLS and OpenSSL --- lib/url.c | 8 ++++++++ lib/urldata.h | 3 +++ lib/vtls/nss.c | 55 +++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 46 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/url.c b/lib/url.c index 3e621bdee..3f2112d8a 100644 --- a/lib/url.c +++ b/lib/url.c @@ -563,6 +563,8 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->tcp_keepintvl = 60; set->tcp_keepidle = 60; + set->ssl_enable_npn = TRUE; + set->ssl_enable_alpn = TRUE; return res; } @@ -2478,6 +2480,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, case CURLOPT_TCP_KEEPINTVL: data->set.tcp_keepintvl = va_arg(param, long); break; + case CURLOPT_SSL_ENABLE_NPN: + data->set.ssl_enable_npn = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_SSL_ENABLE_ALPN: + data->set.ssl_enable_alpn = (0 != va_arg(param, long))?TRUE:FALSE; + break; default: /* unknown tag and its companion, just ignore: */ diff --git a/lib/urldata.h b/lib/urldata.h index 1e1ef5d6b..188e766ea 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1593,6 +1593,9 @@ struct UserDefined { long tcp_keepintvl; /* seconds between TCP keepalive probes */ size_t maxconnects; /* Max idle connections in the connection cache */ + + bool ssl_enable_npn; /* TLS NPN extension? */ + bool ssl_enable_alpn; /* TLS ALPN extension? */ }; struct Names { diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index b679c12bb..c784109f7 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -616,15 +616,16 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) { struct connectdata *conn = (struct connectdata*) arg; -#ifndef USE_NGHTTP2 - (void)sock; - (void)conn; -#else +#ifdef USE_NGHTTP2 unsigned int buflenmax = 50; unsigned char buf[50]; unsigned int buflen; SSLNextProtoState state; + if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) { + return; + } + if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { switch(state) { @@ -1311,6 +1312,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) #endif #endif + if(connssl->state == ssl_connection_complete) return CURLE_OK; @@ -1485,32 +1487,45 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) } #ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { #ifdef SSL_ENABLE_NPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess) - goto error; + if(data->set.ssl_enable_npn) { + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess) + goto error; + } #endif #ifdef SSL_ENABLE_ALPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE) != SECSuccess) - goto error; + if(data->set.ssl_enable_alpn) { + if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE) + != SECSuccess) + goto error; + } #endif #if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) - alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN; - cur++; - memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID, - NGHTTP2_PROTO_VERSION_ID_LEN); - cur += NGHTTP2_PROTO_VERSION_ID_LEN; - alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH; - cur++; - memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); - - if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len) - != SECSuccess) - goto error; + if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) { + alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN; + cur++; + memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID, + NGHTTP2_PROTO_VERSION_ID_LEN); + cur += NGHTTP2_PROTO_VERSION_ID_LEN; + alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH; + cur++; + memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + + if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len) + != SECSuccess) + goto error; + } + else { + infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n"); + } #endif + } #endif + /* Force handshake on next I/O */ SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); -- cgit v1.2.3