aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/url.c11
-rw-r--r--lib/urldata.h1
-rw-r--r--lib/vtls/axtls.c6
-rw-r--r--lib/vtls/cyassl.c5
-rw-r--r--lib/vtls/darwinssl.c145
-rw-r--r--lib/vtls/gskit.c48
-rw-r--r--lib/vtls/gtls.c135
-rw-r--r--lib/vtls/mbedtls.c91
-rw-r--r--lib/vtls/nss.c100
-rw-r--r--lib/vtls/openssl.c120
-rw-r--r--lib/vtls/polarssl.c88
-rw-r--r--lib/vtls/schannel.c49
-rw-r--r--lib/vtls/vtls.c19
13 files changed, 620 insertions, 198 deletions
diff --git a/lib/url.c b/lib/url.c
index 300fc4d14..5943896eb 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -695,6 +695,9 @@ CURLcode Curl_open(struct Curl_easy **curl)
return result;
}
+#define C_SSLVERSION_VALUE(x) (x & 0xffff)
+#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
+
CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
va_list param)
{
@@ -927,7 +930,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* implementations are lame.
*/
#ifdef USE_SSL
- data->set.ssl.primary.version = va_arg(param, long);
+ arg = va_arg(param, long);
+ data->set.ssl.primary.version = C_SSLVERSION_VALUE(arg);
+ data->set.ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
#else
result = CURLE_UNKNOWN_OPTION;
#endif
@@ -938,7 +943,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* implementations are lame.
*/
#ifdef USE_SSL
- data->set.proxy_ssl.primary.version = va_arg(param, long);
+ arg = va_arg(param, long);
+ data->set.proxy_ssl.primary.version = C_SSLVERSION_VALUE(arg);
+ data->set.proxy_ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
#else
result = CURLE_UNKNOWN_OPTION;
#endif
diff --git a/lib/urldata.h b/lib/urldata.h
index 7f87913a9..ef6a78846 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -350,6 +350,7 @@ struct ssl_connect_data {
struct ssl_primary_config {
long version; /* what version the client wants to use */
+ long version_max; /* max supported version the client wants to use*/
bool verifypeer; /* set TRUE if this is desired */
bool verifyhost; /* set TRUE if CN/SAN must match hostname */
bool verifystatus; /* set TRUE if certificate status must be checked */
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index 1de758b0c..af01fe314 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -156,6 +156,12 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
same connection */
return CURLE_OK;
+ if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "axtls does not support CURL_SSLVERSION_MAX");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+
/* axTLS only supports TLSv1 */
/* check to see if we've been told to use an explicit SSL/TLS version */
switch(SSL_CONN_CONFIG(version)) {
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 1e3b346d6..2dfd79dce 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -149,6 +149,11 @@ cyassl_connect_step1(struct connectdata *conn,
if(conssl->state == ssl_connection_complete)
return CURLE_OK;
+ if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "CyaSSL does not support to set maximum SSL/TLS version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
/* check to see if we've been told to use an explicit SSL/TLS version */
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index 25a8ab8b6..26ea04cbb 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -1044,6 +1044,109 @@ CF_INLINE bool is_file(const char *filename)
return false;
}
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+static CURLcode darwinssl_version_from_curl(long *darwinver, long version)
+{
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *darwinver = kTLSProtocol1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *darwinver = kTLSProtocol11;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *darwinver = kTLSProtocol12;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+#endif
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+ if(SSLSetProtocolVersionMax != NULL) {
+ SSLProtocol darwin_ver_min = kTLSProtocol1;
+ SSLProtocol darwin_ver_max = kTLSProtocol1;
+ CURLcode result = darwinssl_version_from_curl(&darwin_ver_min,
+ ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = darwinssl_version_from_curl(&darwin_ver_max,
+ ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min);
+ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max);
+ return result;
+ }
+ else {
+#if CURL_SUPPORT_MAC_10_8
+ long i = ssl_version;
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kSSLProtocolAll,
+ false);
+ for(; i <= (ssl_version_max >> 16); i++) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol1,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol11,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+ kTLSProtocol12,
+ true);
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+#endif /* CURL_SUPPORT_MAC_10_8 */
+ }
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+ failf(data, "DarwinSSL: cannot set SSL protocol");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
int sockindex)
{
@@ -1113,20 +1216,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
break;
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
- break;
case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
- break;
case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
- (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
if(err != noErr) {
@@ -1167,23 +1265,15 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
true);
break;
case CURL_SSLVERSION_TLSv1_0:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol1,
- true);
- break;
case CURL_SSLVERSION_TLSv1_1:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol11,
- true);
- break;
case CURL_SSLVERSION_TLSv1_2:
- (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
- kTLSProtocol12,
- true);
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
kSSLProtocol3,
@@ -1209,6 +1299,11 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_SUPPORT_MAC_10_8 */
}
#else
+ if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "Your version of the OS does not support to set maximum"
+ " SSL/TLS version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index a0d462b70..d760b6a87 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -748,6 +748,40 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
return (ssize_t) nread;
}
+static CURLcode
+set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long i = ssl_version;
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_TLSv1_2;
+ break;
+ }
+ for(; i <= (ssl_version_max >> 16); ++i) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GSKit: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ return CURLE_OK;
+}
static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
{
@@ -764,7 +798,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
conn->host.name;
const char *sni;
- unsigned int protoflags;
+ unsigned int protoflags = 0;
long timeout;
Qso_OverlappedIO_t commarea;
int sockpair[2];
@@ -849,17 +883,13 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
break;
case CURL_SSLVERSION_TLSv1_0:
- protoflags = CURL_GSKPROTO_TLSV10_MASK;
- break;
case CURL_SSLVERSION_TLSv1_1:
- protoflags = CURL_GSKPROTO_TLSV11_MASK;
- break;
case CURL_SSLVERSION_TLSv1_2:
- protoflags = CURL_GSKPROTO_TLSV12_MASK;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GSKit: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ result = set_ssl_version_min_max(&protoflags, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index faa70aca2..f41036049 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -375,6 +375,100 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
return -1;
}
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+static CURLcode
+set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long i = ssl_version;
+ long protocol_priority_idx = 0;
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ for(; i <= (ssl_version_max >> 16) &&
+ protocol_priority_idx < list_size; ++i) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+}
+#else
+#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
+/* If GnuTLS was compiled without support for SRP it will error out if SRP is
+ requested in the priority string, so treat it specially
+ */
+#define GNUTLS_SRP "+SRP"
+
+static CURLcode
+set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ if(ssl_version == CURL_SSLVERSION_TLSv1_3 ||
+ ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) {
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+ ssl_version_max = ssl_version << 16;
+ }
+ switch(ssl_version | ssl_version_max) {
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:" GNUTLS_SRP;
+ return CURLE_OK;
+ }
+
+ failf(data, "GnuTLS: cannot set ssl protocol");
+ return CURLE_SSL_CONNECT_ERROR;
+}
+#endif
+
static CURLcode
gtls_connect_step1(struct connectdata *conn,
int sockindex)
@@ -406,13 +500,8 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_CIPHER_3DES_CBC,
};
static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
- static int protocol_priority[] = { 0, 0, 0, 0 };
+ int protocol_priority[] = { 0, 0, 0, 0 };
#else
-#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
-/* If GnuTLS was compiled without support for SRP it will error out if SRP is
- requested in the priority string, so treat it specially
- */
-#define GNUTLS_SRP "+SRP"
const char *prioritylist;
const char *err = NULL;
#endif
@@ -576,7 +665,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
- switch(SSL_CONN_CONFIG(version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_SSLv3:
protocol_priority[0] = GNUTLS_SSL3;
break;
@@ -587,17 +676,16 @@ gtls_connect_step1(struct connectdata *conn,
protocol_priority[2] = GNUTLS_TLS1_2;
break;
case CURL_SSLVERSION_TLSv1_0:
- protocol_priority[0] = GNUTLS_TLS1_0;
- break;
case CURL_SSLVERSION_TLSv1_1:
- protocol_priority[0] = GNUTLS_TLS1_1;
- break;
case CURL_SSLVERSION_TLSv1_2:
- protocol_priority[0] = GNUTLS_TLS1_2;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GnuTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(protocol_priority,
+ sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv2:
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
@@ -625,20 +713,15 @@ gtls_connect_step1(struct connectdata *conn,
prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
break;
case CURL_SSLVERSION_TLSv1_0:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.0:" GNUTLS_SRP;
- break;
case CURL_SSLVERSION_TLSv1_1:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.1:" GNUTLS_SRP;
- break;
case CURL_SSLVERSION_TLSv1_2:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.2:" GNUTLS_SRP;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "GnuTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv2:
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 07239bf26..dbcb1690c 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -157,6 +157,71 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
static Curl_recv mbed_recv;
static Curl_send mbed_send;
+static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
+{
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
+ int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ CURLcode result = CURLE_OK;
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ver_min);
+ mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ver_max);
+
+ return result;
+}
+
static CURLcode
mbed_connect_step1(struct connectdata *conn,
int sockindex)
@@ -333,29 +398,15 @@ mbed_connect_step1(struct connectdata *conn,
infof(data, "mbedTLS: Set SSL version to SSLv3\n");
break;
case CURL_SSLVERSION_TLSv1_0:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_1);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_1);
- infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
- break;
case CURL_SSLVERSION_TLSv1_1:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_2);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_2);
- infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
- break;
case CURL_SSLVERSION_TLSv1_2:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_3);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_3);
- infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "mbedTLS: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index d5158acef..a09f457f8 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -1512,78 +1512,108 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode nss_init_sslver(SSLVersionRange *sslver,
- struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
{
- switch(SSL_CONN_CONFIG(version)) {
- case CURL_SSLVERSION_DEFAULT:
- /* map CURL_SSLVERSION_DEFAULT to NSS default */
- if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
- return CURLE_SSL_CONNECT_ERROR;
- /* ... but make sure we use at least TLSv1.0 according to libcurl API */
- if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
- return CURLE_OK;
-
+ switch(version) {
case CURL_SSLVERSION_TLSv1:
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
/* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
#elif defined SSL_LIBRARY_VERSION_TLS_1_1
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
#else
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
#endif
return CURLE_OK;
case CURL_SSLVERSION_SSLv2:
- sslver->min = SSL_LIBRARY_VERSION_2;
- sslver->max = SSL_LIBRARY_VERSION_2;
+ *nssver = SSL_LIBRARY_VERSION_2;
return CURLE_OK;
case CURL_SSLVERSION_SSLv3:
- sslver->min = SSL_LIBRARY_VERSION_3_0;
- sslver->max = SSL_LIBRARY_VERSION_3_0;
+ *nssver = SSL_LIBRARY_VERSION_3_0;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_0:
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_1:
#ifdef SSL_LIBRARY_VERSION_TLS_1_1
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
return CURLE_OK;
+#else
+ return CURLE_SSL_CONNECT_ERROR;
#endif
- break;
case CURL_SSLVERSION_TLSv1_2:
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
return CURLE_OK;
+#else
+ return CURLE_SSL_CONNECT_ERROR;
#endif
- break;
case CURL_SSLVERSION_TLSv1_3:
#ifdef SSL_LIBRARY_VERSION_TLS_1_3
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_3;
- sslver->max = SSL_LIBRARY_VERSION_TLS_1_3;
+ *nssver = SSL_LIBRARY_VERSION_TLS_1_3;
return CURLE_OK;
+#else
+ return CURLE_SSL_CONNECT_ERROR;
#endif
- break;
default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
+}
- failf(data, "TLS minor version cannot be set");
- return CURLE_SSL_CONNECT_ERROR;
+static CURLcode nss_init_sslver(SSLVersionRange *sslver,
+ struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ const long min = SSL_CONN_CONFIG(version);
+ const long max = SSL_CONN_CONFIG(version_max);
+
+ /* map CURL_SSLVERSION_DEFAULT to NSS default */
+ if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) {
+ /* map CURL_SSLVERSION_DEFAULT to NSS default */
+ if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
+ return CURLE_SSL_CONNECT_ERROR;
+ /* ... but make sure we use at least TLSv1.0 according to libcurl API */
+ if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ }
+
+ switch(min) {
+ case CURL_SSLVERSION_DEFAULT:
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+ break;
+ default:
+ result = nss_sslver_from_curl(&sslver->min, min);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ if(max == CURL_SSLVERSION_MAX_NONE)
+ sslver->max = sslver->min;
+ }
+
+ switch(max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ break;
+ default:
+ result = nss_sslver_from_curl(&sslver->max, max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ }
+
+ return CURLE_OK;
}
static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 20626fec9..8881b57ac 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -1692,6 +1692,71 @@ get_ssl_version_txt(SSL *ssl)
return "unknown";
}
+static CURLcode
+set_ssl_version_min_max(long *ctx_options, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+ ssl_version_max = ssl_version << 16;
+ }
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS1_3_VERSION
+ SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+ *ctx_options |= SSL_OP_NO_TLSv1_2;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ case CURL_SSLVERSION_TLSv1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1_1;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ case CURL_SSLVERSION_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ case CURL_SSLVERSION_TLSv1_0:
+ *ctx_options |= SSL_OP_NO_SSLv2;
+ *ctx_options |= SSL_OP_NO_SSLv3;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_TLSv1_0:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1_1;
+#endif
+ case CURL_SSLVERSION_MAX_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ *ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+ case CURL_SSLVERSION_MAX_TLSv1_2:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+#ifdef TLS1_3_VERSION
+ *ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_3:
+#ifdef TLS1_3_VERSION
+ break;
+#else
+ failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ }
+ return CURLE_OK;
+}
+
static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
@@ -1701,7 +1766,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
X509_LOOKUP *lookup = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- long ctx_options;
+ long ctx_options = 0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
#ifdef ENABLE_IPV6
@@ -1888,60 +1953,13 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
break;
case CURL_SSLVERSION_TLSv1_0:
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
-#endif
- break;
-
case CURL_SSLVERSION_TLSv1_1:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
- break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
- return CURLE_NOT_BUILT_IN;
-#endif
-
case CURL_SSLVERSION_TLSv1_2:
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
- ctx_options |= SSL_OP_NO_TLSv1_1;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
- break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
- return CURLE_NOT_BUILT_IN;
-#endif
-
case CURL_SSLVERSION_TLSv1_3:
-#ifdef TLS1_3_VERSION
- SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
+ result = set_ssl_version_min_max(&ctx_options, conn);
+ if(result != CURLE_OK)
+ return result;
break;
-#else
- failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
- return CURLE_NOT_BUILT_IN;
-#endif
case CURL_SSLVERSION_SSLv2:
#ifndef OPENSSL_NO_SSL2
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index e5346ce3d..aa34bbc43 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -140,6 +140,68 @@ static void polarssl_debug(void *context, int level, const char *line)
static Curl_recv polarssl_recv;
static Curl_send polarssl_send;
+static CURLcode polarssl_version_from_curl(int *polarver, long version)
+{
+ switch(ssl_version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *polarver = SSL_MINOR_VERSION_1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *polarver = SSL_MINOR_VERSION_2;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *polarver = SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex);
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ int ssl_min_ver = SSL_MINOR_VERSION_1;
+ int ssl_max_ver = SSL_MINOR_VERSION_1;
+ CURLcode result = CURLE_OK;
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ result = polarssl_version_from_curl(&ssl_min_ver, ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
+ ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
+
+ return result;
+}
static CURLcode
polarssl_connect_step1(struct connectdata *conn,
@@ -287,29 +349,15 @@ polarssl_connect_step1(struct connectdata *conn,
infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
break;
case CURL_SSLVERSION_TLSv1_0:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_1);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_1);
- infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
- break;
case CURL_SSLVERSION_TLSv1_1:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_2);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_2);
- infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
- break;
case CURL_SSLVERSION_TLSv1_2:
- ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_3);
- ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_3);
- infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "PolarSSL: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index bd9239956..47356a53d 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -103,6 +103,41 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
}
static CURLcode
+set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
+{
+ struct Curl_easy *data = conn->data;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ long i = ssl_version;
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+ for(; i <= (ssl_version_max >> 16); ++i) {
+ switch(i) {
+ case CURL_SSLVERSION_TLSv1_0:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "Schannel: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
{
ssize_t written = -1;
@@ -216,17 +251,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SP_PROT_TLS1_2_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_0:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_1:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_2:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_3:
- failf(data, "Schannel: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ {
+ CURLcode result = set_ssl_version_min_max(&schannel_cred, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
break;
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index f40a97712..693380fb9 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -95,6 +95,7 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
struct ssl_primary_config* needle)
{
if((data->version == needle->version) &&
+ (data->version_max == needle->version_max) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
@@ -113,6 +114,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->verifyhost = source->verifyhost;
dest->verifypeer = source->verifypeer;
dest->version = source->version;
+ dest->version_max = source->version_max;
CLONE_STRING(CAfile);
CLONE_STRING(CApath);
@@ -173,11 +175,24 @@ void Curl_ssl_cleanup(void)
static bool ssl_prefs_check(struct Curl_easy *data)
{
/* check for CURLOPT_SSLVERSION invalid parameter value */
- if((data->set.ssl.primary.version < 0)
- || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
+ const long sslver = data->set.ssl.primary.version;
+ if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
return FALSE;
}
+
+ switch(data->set.ssl.primary.version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ break;
+
+ default:
+ if((data->set.ssl.primary.version_max >> 16) < sslver) {
+ failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION");
+ return FALSE;
+ }
+ }
+
return TRUE;
}