From 3017c92709e13ea4cee6a66fd82b97a5c86a0dc8 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 25 Nov 2013 16:03:52 +0100
Subject: [PATCH] nss: use a better API for controlling SSL version

This change introduces a dependency on NSS 3.14+.
---
 configure.ac   |    4 ++--
 docs/INTERNALS |    2 +-
 lib/nss.c      |   40 +++++++++++++++++++---------------------
 3 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/configure.ac b/configure.ac
index 1347cbd..6a493fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2071,8 +2071,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
          CPPFLAGS="$CPPFLAGS $addcflags"
       fi
 
-      dnl The function PK11_CreateGenericObject is needed to load libnsspem.so
-      AC_CHECK_LIB(nss3, PK11_CreateGenericObject,
+      dnl The function SSL_VersionRangeSet() is needed to enable TLS > 1.0
+      AC_CHECK_LIB(nss3, SSL_VersionRangeSet,
        [
        AC_DEFINE(USE_NSS, 1, [if NSS is enabled])
        AC_SUBST(USE_NSS, [1])
diff --git a/docs/INTERNALS b/docs/INTERNALS
index 66e11a4..c8e433c 100644
--- a/docs/INTERNALS
+++ b/docs/INTERNALS
@@ -43,7 +43,7 @@ Portability
  openldap     2.0
  MIT krb5 lib 1.2.4
  qsossl       V5R3M0
- NSS          3.12.x
+ NSS          3.14.x
  axTLS        1.2.7
  Heimdal      ?
 
diff --git a/lib/nss.c b/lib/nss.c
index eb2fea9..9b0d43e 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -1215,9 +1215,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
 {
   PRErrorCode err = 0;
   PRFileDesc *model = NULL;
-  PRBool ssl2 = PR_FALSE;
-  PRBool ssl3 = PR_FALSE;
-  PRBool tlsv1 = PR_FALSE;
+  SSLVersionRange sslver;
   PRBool ssl_no_cache;
   PRBool ssl_cbc_random_iv;
   struct SessionHandle *data = conn->data;
@@ -1292,20 +1290,25 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
   switch (data->set.ssl.version) {
   default:
   case CURL_SSLVERSION_DEFAULT:
-    ssl3 = PR_TRUE;
-    if(data->state.ssl_connect_retry)
+    sslver.min = SSL_LIBRARY_VERSION_3_0;
+    if(data->state.ssl_connect_retry) {
       infof(data, "TLS disabled due to previous handshake failure\n");
+      sslver.max = SSL_LIBRARY_VERSION_3_0;
+    }
     else
-      tlsv1 = PR_TRUE;
+      sslver.max = SSL_LIBRARY_VERSION_TLS_1_0;
     break;
   case CURL_SSLVERSION_TLSv1:
-    tlsv1 = PR_TRUE;
+    sslver.min = SSL_LIBRARY_VERSION_TLS_1_0;
+    sslver.max = SSL_LIBRARY_VERSION_TLS_1_0;
     break;
   case CURL_SSLVERSION_SSLv2:
-    ssl2 = PR_TRUE;
+    sslver.min = SSL_LIBRARY_VERSION_2;
+    sslver.max = SSL_LIBRARY_VERSION_2;
     break;
   case CURL_SSLVERSION_SSLv3:
-    ssl3 = PR_TRUE;
+    sslver.min = SSL_LIBRARY_VERSION_3_0;
+    sslver.max = SSL_LIBRARY_VERSION_3_0;
     break;
   case CURL_SSLVERSION_TLSv1_0:
   case CURL_SSLVERSION_TLSv1_1:
@@ -1315,14 +1318,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
     goto error;
   }
 
-  if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
-    goto error;
-  if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
-    goto error;
-  if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
-    goto error;
-
-  if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
+  if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
     goto error;
 
   ssl_cbc_random_iv = !data->set.ssl_enable_beast;
@@ -1508,11 +1504,13 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
   if(model)
     PR_Close(model);
 
-    /* cleanup on connection failure */
-    Curl_llist_destroy(connssl->obj_list, NULL);
-    connssl->obj_list = NULL;
+  /* cleanup on connection failure */
+  Curl_llist_destroy(connssl->obj_list, NULL);
+  connssl->obj_list = NULL;
 
-  if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) {
+  if((sslver.min == SSL_LIBRARY_VERSION_3_0)
+      && (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0)
+      && isTLSIntoleranceError(err)) {
     /* schedule reconnect through Curl_retry_request() */
     data->state.ssl_connect_retry = TRUE;
     infof(data, "Error in TLS handshake, trying SSLv3...\n");
-- 
1.7.1


