>From 892722568eb1c169bdfee062b17c8c385a3cfb7a Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Fri, 10 Jul 2015 11:41:22 -0700
Subject: [PATCH 84/84] Ticket 1459 Dogtag clients cannot connect when CS is
 configured with ECC

---
 .../com/netscape/certsrv/client/PKIConnection.java | 44 ++++++++++++++++++++++
 .../admin/certsrv/connection/JSSConnection.java    | 36 ++++++++++++++++++
 .../src/com/netscape/cmstools/HttpClient.java      | 40 ++++++++++++++++++++
 3 files changed, 120 insertions(+)

diff --git a/base/common/src/com/netscape/certsrv/client/PKIConnection.java b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
index 1f9b6dff16e88bd3746b2d9627fa14b1d1cd1cd5..0c543d2442e978c78b0651fbf547111c33af233a 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIConnection.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.Integer;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
@@ -102,6 +103,17 @@ public class PKIConnection {
 
     File output;
 
+    static final Integer[] clientECCciphers = {
+        SSLSocket.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+        SSLSocket.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+        SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    };
+    ArrayList<Integer> eccCiphers = new ArrayList(Arrays.asList(clientECCciphers));
+
     public PKIConnection(ClientConfig config) {
 
         this.config = config;
@@ -346,6 +358,38 @@ public class PKIConnection {
             SSLSocket.setSSLVersionRangeDefault(
                     org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM,
                     datagram_range);
+
+            int ciphers[] = SSLSocket.getImplementedCipherSuites();
+            for (int j = 0; ciphers != null && j < ciphers.length; j++) {
+                boolean enabled = SSLSocket.getCipherPreferenceDefault(ciphers[j]);
+                if (verbose) {
+                    System.out.println("Debug: cipher '0x" +
+                        Integer.toHexString(ciphers[j]) + "'" + " enabled? " +
+                        enabled);
+                }
+                // make sure SSLv2 ciphers are not enabled
+                if ((ciphers[j] & 0xfff0) ==0xff00) {
+                    if (enabled) {
+                        if (verbose) {
+                          System.out.println("Debug: disabling SSL2 NSS Cipher '0x" +
+                          Integer.toHexString(ciphers[j]) + "'");
+                        }
+                        SSLSocket.setCipherPreferenceDefault(ciphers[j], false);
+                    }
+                } else {
+                    /*
+                     * unlike RSA ciphers, ECC ciphers are not enabled by default
+                     */
+                    if ((!enabled) && eccCiphers.contains(ciphers[j])) {
+                        if (verbose) {
+                          System.out.println("Debug: enabling ECC NSS Cipher '0x" +
+                          Integer.toHexString(ciphers[j]) + "'");
+                        }
+                        SSLSocket.setCipherPreferenceDefault(ciphers[j], true);
+                    }
+                }
+            }
+
             SSLSocket socket;
             if (sock == null) {
                 socket = new SSLSocket(InetAddress.getByName(hostName),
diff --git a/base/console/src/com/netscape/admin/certsrv/connection/JSSConnection.java b/base/console/src/com/netscape/admin/certsrv/connection/JSSConnection.java
index 43d1c234b39df8e4c133cb6b6368e3f1a9c0d9f9..84257f4db096317185ffb7c84011eadd3ed33ff9 100644
--- a/base/console/src/com/netscape/admin/certsrv/connection/JSSConnection.java
+++ b/base/console/src/com/netscape/admin/certsrv/connection/JSSConnection.java
@@ -60,6 +60,16 @@ public class JSSConnection implements IConnection, SSLCertificateApprovalCallbac
     static CertificateFactory cf;
     static SelectCertDialog selectCertDialog = null;
     static PromptForTrustDialog promptForTrustDialog = null;
+    static final Integer[] clientECCciphers = {
+        SSLSocket.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+        SSLSocket.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+        SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    };
+    ArrayList<Integer> eccCiphers = new ArrayList(Arrays.asList(clientECCciphers));
 
     /* private valiable */
     private InputStream httpIn;
@@ -113,6 +123,32 @@ public class JSSConnection implements IConnection, SSLCertificateApprovalCallbac
         SSLSocket.setSSLVersionRangeDefault(
             org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM,
             datagram_range);
+
+        int ciphers[] = SSLSocket.getImplementedCipherSuites();
+        for (int i = 0; ciphers != null && i < ciphers.length; i++) {
+            boolean enabled = SSLSocket.getCipherPreferenceDefault(ciphers[i]);
+            Debug.println("JSSConnection Debug: cipher '0x" +
+                Integer.toHexString(ciphers[i]) + "'" + " enabled? " +
+                enabled);
+            // make sure SSLv2 ciphers are not enabled
+            if ((ciphers[i] & 0xfff0) ==0xff00) {
+                if (enabled) {
+                    Debug.println("JSSConnection Debug: disabling SSL2 NSS Cipher '0x" +
+                    Integer.toHexString(ciphers[i]) + "'");
+                    SSLSocket.setCipherPreferenceDefault(ciphers[i], false);
+                }
+            } else {
+                /*
+                 * unlike RSA ciphers, ECC ciphers are not enabled by default
+                 */
+                if ((!enabled) && eccCiphers.contains(ciphers[i])) {
+                    Debug.println("JSSConnection Debug: enabling ECC NSS Cipher '0x" +
+                        Integer.toHexString(ciphers[i]) + "'");
+                    SSLSocket.setCipherPreferenceDefault(ciphers[i], true);
+                }
+            }
+        }
+
         s = new SSLSocket(host, port, null, 0, this, this);
 
         // Initialze Http Input and Output Streams
diff --git a/base/java-tools/src/com/netscape/cmstools/HttpClient.java b/base/java-tools/src/com/netscape/cmstools/HttpClient.java
index f0603a4bd10f17240b5f3957d8d91da5af7b07a1..90ce3871a74f69157d43f36572e6673a07b3b365 100644
--- a/base/java-tools/src/com/netscape/cmstools/HttpClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/HttpClient.java
@@ -31,6 +31,8 @@ import java.io.InputStreamReader;
 import java.io.PrintStream;
 import java.net.Socket;
 import java.util.StringTokenizer;
+import java.util.Arrays;
+import java.util.ArrayList;
 
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.crypto.CryptoToken;
@@ -49,6 +51,18 @@ import com.netscape.cmsutil.util.Utils;
  */
 public class HttpClient {
     public static final String PR_INTERNAL_TOKEN_NAME = "internal";
+
+    static final Integer[] clientECCciphers = {
+        SSLSocket.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+        SSLSocket.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+        SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+        SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+    };
+    ArrayList<Integer> eccCiphers = new ArrayList(Arrays.asList(clientECCciphers));
+
     private String _host = null;
     private int _port = 0;
     private boolean _secure = false;
@@ -144,6 +158,32 @@ public class HttpClient {
                 SSLSocket.setSSLVersionRangeDefault(
                     org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM,
                     datagram_range);
+
+                int ciphers[] = SSLSocket.getImplementedCipherSuites();
+                for (int j = 0; ciphers != null && j < ciphers.length; j++) {
+                    boolean enabled = SSLSocket.getCipherPreferenceDefault(ciphers[j]);
+                    //System.out.println("HttpClient Debug: cipher '0x" +
+                    //    Integer.toHexString(ciphers[j]) + "'" + " enabled? " +
+                    //    enabled);
+                    // make sure SSLv2 ciphers are not enabled
+                    if ((ciphers[j] & 0xfff0) ==0xff00) {
+                        if (enabled) {
+                            //System.out.println("HttpClient Debug: disabling SSL2 NSS Cipher '0x" +
+                            //    Integer.toHexString(ciphers[j]) + "'");
+                            SSLSocket.setCipherPreferenceDefault(ciphers[j], false);
+                        }
+                    } else {
+                        /*
+                         * unlike RSA ciphers, ECC ciphers are not enabled by default
+                         */
+                        if ((!enabled) && eccCiphers.contains(ciphers[j])) {
+                          //System.out.println("Debug: enabling ECC NSS Cipher '0x" +
+                          //    Integer.toHexString(ciphers[j]) + "'");
+                          SSLSocket.setCipherPreferenceDefault(ciphers[j], true);
+                        }
+                    }
+                }
+
                 sslSocket = new SSLSocket(_host, _port);
                 // setSSLVersionRange needs to be exposed in jss
                 // sslSocket.setSSLVersionRange(org.mozilla.jss.ssl.SSLSocket.SSLVersionRange.tls1_0, org.mozilla.jss.ssl.SSLSocket.SSLVersionRange.tls1_2);
-- 
1.8.4.2

