diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/url.c | 11 | ||||
| -rw-r--r-- | lib/urldata.h | 1 | ||||
| -rw-r--r-- | lib/vtls/axtls.c | 6 | ||||
| -rw-r--r-- | lib/vtls/cyassl.c | 5 | ||||
| -rw-r--r-- | lib/vtls/darwinssl.c | 145 | ||||
| -rw-r--r-- | lib/vtls/gskit.c | 48 | ||||
| -rw-r--r-- | lib/vtls/gtls.c | 135 | ||||
| -rw-r--r-- | lib/vtls/mbedtls.c | 91 | ||||
| -rw-r--r-- | lib/vtls/nss.c | 100 | ||||
| -rw-r--r-- | lib/vtls/openssl.c | 120 | ||||
| -rw-r--r-- | lib/vtls/polarssl.c | 88 | ||||
| -rw-r--r-- | lib/vtls/schannel.c | 49 | ||||
| -rw-r--r-- | lib/vtls/vtls.c | 19 | 
13 files changed, 620 insertions, 198 deletions
@@ -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;  }  | 
