cURL / Mailing Lists / curl-library / Single Mail

curl-library

[PATCH] SSL: Legacy support for SSLv3 or later

From: Jay Satiro <raysatiro_at_yahoo.com>
Date: Fri, 2 Jan 2015 02:41:21 -0500

New value for CURLOPT_SSLVERSION: CURL_SSLVERSION_SSLv3_OR_LATER.

- The new value supports the old behavior of CURL_SSLVERSION_DEFAULT which
included SSLv3 when figuring out which version to use.

---
 docs/libcurl/opts/CURLOPT_SSLVERSION.3 |  9 +++++++++
 include/curl/curl.h                    |  1 +
 lib/vtls/axtls.c                       |  1 +
 lib/vtls/curl_darwinssl.c              | 26 ++++++++++++++++++++++++++
 lib/vtls/curl_schannel.c               |  6 ++++++
 lib/vtls/cyassl.c                      | 19 +++++++++++++++++++
 lib/vtls/gskit.c                       |  4 ++++
 lib/vtls/gtls.c                        | 12 +++++++++++-
 lib/vtls/nss.c                         | 11 +++++++++++
 lib/vtls/openssl.c                     | 11 +++++++++++
 lib/vtls/polarssl.c                    |  5 +++++
 11 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/docs/libcurl/opts/CURLOPT_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
index a10dabd..e34e977 100644
--- a/docs/libcurl/opts/CURLOPT_SSLVERSION.3
+++ b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
@@ -42,6 +42,15 @@ TLSv1.x
 SSLv2
 .IP CURL_SSLVERSION_SSLv3
 SSLv3
+.IP CURL_SSLVERSION_SSLv3_OR_LATER
+SSLv3 or later (Added in 7.40.0)
+
+SSLv3 is included when attempting to figure which minimum protocol version to
+use. This define has the same behavior as CURL_SSLVERSION_DEFAULT did in
+versions prior to 7.39.0, except that the fallback implementation for buggy
+SSLv3 servers (only used for NSS SSL) no longer exists. Regardless of what SSL
+library libcurl is built against if you are trying to connect to a buggy SSLv3
+server you may have to specify exclusive SSLv3 by using CURL_SSLVERSION_SSLv3.
 .IP CURL_SSLVERSION_TLSv1_0
 TLSv1.0 (Added in 7.34.0)
 .IP CURL_SSLVERSION_TLSv1_1
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 44b1b7e..2677415 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1715,6 +1715,7 @@ enum {
   CURL_SSLVERSION_TLSv1_0,
   CURL_SSLVERSION_TLSv1_1,
   CURL_SSLVERSION_TLSv1_2,
+  CURL_SSLVERSION_SSLv3_OR_LATER,
 
   CURL_SSLVERSION_LAST /* never use, keep last */
 };
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index 1b577b1..c0069dd 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -162,6 +162,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
   switch(data->set.ssl.version) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
     break;
   default:
     failf(data, "axTLS only supports TLS 1.0 and 1.1, "
diff --git a/lib/vtls/curl_darwinssl.c b/lib/vtls/curl_darwinssl.c
index 5658673..ca1bd4e 100644
--- a/lib/vtls/curl_darwinssl.c
+++ b/lib/vtls/curl_darwinssl.c
@@ -1064,6 +1064,10 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
         break;
+      case CURL_SSLVERSION_SSLv3_OR_LATER:
+        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+        break;
       case CURL_SSLVERSION_TLSv1_0:
         (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
         (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
@@ -1112,6 +1116,20 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
                                            kTLSProtocol12,
                                            true);
         break;
+      case CURL_SSLVERSION_SSLv3_OR_LATER:
+        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                           kSSLProtocol3,
+                                           true);
+        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                           kTLSProtocol1,
+                                           true);
+        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                           kTLSProtocol11,
+                                           true);
+        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                           kTLSProtocol12,
+                                           true);
+        break;
       case CURL_SSLVERSION_TLSv1_0:
         (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                            kTLSProtocol1,
@@ -1159,6 +1177,14 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
                                          kTLSProtocol1,
                                          true);
       break;
+    case CURL_SSLVERSION_SSLv3_OR_LATER:
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kSSLProtocol3,
+                                         true);
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol1,
+                                         true);
+      break;
     case CURL_SSLVERSION_TLSv1_1:
       failf(data, "Your version of the OS does not support TLSv1.1");
       return CURLE_SSL_CONNECT_ERROR;
diff --git a/lib/vtls/curl_schannel.c b/lib/vtls/curl_schannel.c
index b3fe526..756db6f 100644
--- a/lib/vtls/curl_schannel.c
+++ b/lib/vtls/curl_schannel.c
@@ -171,6 +171,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
                                               SP_PROT_TLS1_1_CLIENT |
                                               SP_PROT_TLS1_2_CLIENT;
         break;
+      case CURL_SSLVERSION_SSLv3_OR_LATER:
+        schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
+                                              SP_PROT_TLS1_1_CLIENT |
+                                              SP_PROT_TLS1_2_CLIENT |
+                                              SP_PROT_SSL3_CLIENT;
+        break;
       case CURL_SSLVERSION_TLSv1_0:
         schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
         break;
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 3333fc3..c19b9e2 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -106,6 +106,9 @@ cyassl_connect_step1(struct connectdata *conn,
           "TLS 1.0 is used exclusively\n");
     req_method = TLSv1_client_method();
     break;
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
+    req_method = SSLv23_client_method();
+    break;
   case CURL_SSLVERSION_TLSv1_0:
     req_method = TLSv1_client_method();
     break;
@@ -211,6 +214,22 @@ cyassl_connect_step1(struct connectdata *conn,
     return CURLE_OUT_OF_MEMORY;
   }
 
+  switch(data->set.ssl.version) {
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
+#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
+    /* short circuit evaluation to find minimum supported SSL version */
+    if((CyaSSL_SetMinVersion(conssl->handle, CYASSL_SSLV3) != SSL_SUCCESS)
+      &&(CyaSSL_SetMinVersion(conssl->handle, CYASSL_TLSV1) != SSL_SUCCESS)
+      &&(CyaSSL_SetMinVersion(conssl->handle, CYASSL_TLSV1_1) != SSL_SUCCESS)
+      &&(CyaSSL_SetMinVersion(conssl->handle, CYASSL_TLSV1_2) != SSL_SUCCESS))
+    {
+        failf(data, "SSL: couldn't set the minimum version");
+        return CURLE_SSL_CONNECT_ERROR;
+    }
+#endif
+    break;
+  }
+
   /* Check if there's a cached ID we can/should use here! */
   if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
     /* we got a session id, use it! */
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index ac05f05..3993462 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -628,6 +628,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     protoflags = CURL_GSKPROTO_SSLV2_MASK;
     sni = (char *) NULL;
     break;
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
+    protoflags = CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
+                 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
+    break;
   case CURL_SSLVERSION_TLSv1:
     protoflags = CURL_GSKPROTO_TLSV10_MASK |
                  CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 5d4e48a..2d8fd02 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -382,7 +382,7 @@ 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 };
+  static int protocol_priority[] = { 0, 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
@@ -531,6 +531,12 @@ gtls_connect_step1(struct connectdata *conn,
       protocol_priority[1] = GNUTLS_TLS1_1;
       protocol_priority[2] = GNUTLS_TLS1_2;
       break;
+    case CURL_SSLVERSION_SSLv3_OR_LATER:
+      protocol_priority[0] = GNUTLS_SSL3;
+      protocol_priority[1] = GNUTLS_TLS1_0;
+      protocol_priority[2] = GNUTLS_TLS1_1;
+      protocol_priority[3] = GNUTLS_TLS1_2;
+      break;
     case CURL_SSLVERSION_TLSv1_0:
       protocol_priority[0] = GNUTLS_TLS1_0;
       break;
@@ -565,6 +571,10 @@ gtls_connect_step1(struct connectdata *conn,
     case CURL_SSLVERSION_TLSv1:
       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
       break;
+    case CURL_SSLVERSION_SSLv3_OR_LATER:
+      prioritylist = GNUTLS_CIPHERS ":+VERS-SSL3.0:+VERS-TLS1.0:+VERS-TLS1.1:"
+                     "+VERS-TLS1.2:" GNUTLS_SRP;
+      break;
     case CURL_SSLVERSION_TLSv1_0:
       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
                      "+VERS-TLS1.0:" GNUTLS_SRP;
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index dd83a9d..3a514d3 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -1336,6 +1336,17 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
 #endif
     return CURLE_OK;
 
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
+    sslver->min = SSL_LIBRARY_VERSION_3_0;
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+    sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+#elif defined SSL_LIBRARY_VERSION_TLS_1_1
+    sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+#else
+    sslver->max = 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;
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index a68d88e..8cc4216 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -1568,6 +1568,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   default:
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
   case CURL_SSLVERSION_TLSv1_0:
   case CURL_SSLVERSION_TLSv1_1:
   case CURL_SSLVERSION_TLSv1_2:
@@ -1706,6 +1707,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     ctx_options |= SSL_OP_NO_SSLv3;
     break;
 
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
+#ifdef USE_TLS_SRP
+    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+      infof(data, "Set version TLSv1.x for SRP authorisation\n");
+      ctx_options |= SSL_OP_NO_SSLv3;
+    }
+#endif
+    ctx_options |= SSL_OP_NO_SSLv2;
+    break;
+
   case CURL_SSLVERSION_TLSv1_0:
     ctx_options |= SSL_OP_NO_SSLv2;
     ctx_options |= SSL_OP_NO_SSLv3;
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index 05fcfc2..8663850 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -297,6 +297,11 @@ polarssl_connect_step1(struct connectdata *conn,
                         SSL_MINOR_VERSION_0);
     infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
     break;
+  case CURL_SSLVERSION_SSLv3_OR_LATER:
+    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+                        SSL_MINOR_VERSION_0);
+    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);
-- 
1.9.4.msysgit.2
--------------000205070802030202000002
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLQpMaXN0IGFkbWluOiBodHRwOi8vY29vbC5oYXh4LnNlL2xpc3QvbGlzdGluZm8v
Y3VybC1saWJyYXJ5CkV0aXF1ZXR0ZTogIGh0dHA6Ly9jdXJsLmhheHguc2UvbWFpbC9ldGlxdWV0
dGUuaHRtbA==
--------------000205070802030202000002--
Received on 2001-09-17