>From 08ba560ca769a780284480a13205a2cf4e6e5629 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Fri, 10 Jul 2015 11:41:22 -0700
Subject: [PATCH] Ticket 1459 Dogtag clients cannot connect when CS is
 configured with ECC   clients are: cli, HttpClient, and java console

---
 .../com/netscape/certsrv/client/PKIConnection.java |  4 ++
 base/console/src/CMakeLists.txt                    | 10 ++++-
 .../admin/certsrv/connection/JSSConnection.java    |  5 +++
 base/console/templates/pki_console_wrapper         |  2 +
 .../src/com/netscape/cmstools/HttpClient.java      |  5 +++
 .../com/netscape/cmsutil/crypto/CryptoUtil.java    | 44 ++++++++++++++++++++++
 6 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/base/common/src/com/netscape/certsrv/client/PKIConnection.java b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
index 1f9b6dff16e88bd3746b2d9627fa14b1d1cd1cd5..85b6c208227c0f079e69abfab3a24d953bb26716 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIConnection.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
@@ -82,6 +82,7 @@ import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
 import org.mozilla.jss.ssl.SSLSocket;
 
 import com.netscape.certsrv.base.PKIException;
+import com.netscape.cmsutil.crypto.CryptoUtil;
 
 
 public class PKIConnection {
@@ -346,6 +347,9 @@ public class PKIConnection {
             SSLSocket.setSSLVersionRangeDefault(
                     org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM,
                     datagram_range);
+
+            CryptoUtil.setClientCiphers();
+
             SSLSocket socket;
             if (sock == null) {
                 socket = new SSLSocket(InetAddress.getByName(hostName),
diff --git a/base/console/src/CMakeLists.txt b/base/console/src/CMakeLists.txt
index 3dc0f5d4152544ecade008362c2fb01a93e97d5c..c1a86b7c4c0e6245a3d58675cc63c6287a573ecc 100644
--- a/base/console/src/CMakeLists.txt
+++ b/base/console/src/CMakeLists.txt
@@ -17,6 +17,14 @@ find_file(PKI_CERTSRV_JAR
         /usr/share/java/pki
 )
 
+find_file(PKI_CMSUTIL_JAR
+    NAMES
+        pki-cmsutil.jar
+    PATHS
+        ${JAVA_LIB_INSTALL_DIR}
+        /usr/share/java/pki
+)
+
 
 # '/usr/share/java' jars
 find_file(BASE_JAR
@@ -92,7 +100,7 @@ javac(pki-console-classes
         ${CMAKE_BINARY_DIR}/classes
         ${BASE_JAR} ${LDAPJDK_JAR} ${MMC_JAR}
         ${MMC_EN_JAR} ${NMCLF_JAR} ${NMCLF_EN_JAR}
-        ${PKI_NSUTIL_JAR} ${PKI_CERTSRV_JAR}
+        ${PKI_CMSUTIL_JAR} ${PKI_NSUTIL_JAR} ${PKI_CERTSRV_JAR}
         ${JSS_JAR} ${COMMONS_CODEC_JAR}
     OUTPUT_DIR
         ${CMAKE_BINARY_DIR}/classes
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..6908ed992154ef3bd04124cc2ba116e49bb865cf 100644
--- a/base/console/src/com/netscape/admin/certsrv/connection/JSSConnection.java
+++ b/base/console/src/com/netscape/admin/certsrv/connection/JSSConnection.java
@@ -34,6 +34,8 @@ import org.mozilla.jss.pkcs11.*;
 import javax.swing.*;
 import java.awt.*;
 
+import com.netscape.cmsutil.crypto.CryptoUtil;
+
 /**
  * JSSConnection deals with establishing a connection to
  * a server, sending requests and reading responses.
@@ -113,6 +115,9 @@ public class JSSConnection implements IConnection, SSLCertificateApprovalCallbac
         SSLSocket.setSSLVersionRangeDefault(
             org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM,
             datagram_range);
+
+        CryptoUtil.setClientCiphers();
+
         s = new SSLSocket(host, port, null, 0, this, this);
 
         // Initialze Http Input and Output Streams
diff --git a/base/console/templates/pki_console_wrapper b/base/console/templates/pki_console_wrapper
index 2f110ed8501696a33139585022ffa4c7cea13c80..296eba24d4934303197a49230e33613a92265ece 100755
--- a/base/console/templates/pki_console_wrapper
+++ b/base/console/templates/pki_console_wrapper
@@ -138,6 +138,8 @@ CP=/usr/share/java/idm-console-mcc.jar:${CP}
 CP=/usr/share/java/idm-console-mcc_en.jar:${CP}
 CP=/usr/share/java/idm-console-base.jar:${CP}
 CP=/usr/share/java/389-console_en.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-nsutil.jar:${CP}
+CP=/usr/share/java/${PRODUCT}/pki-cmsutil.jar:${CP}
 CP=/usr/share/java/${PRODUCT}/pki-certsrv.jar:${CP}
 CP=/usr/share/java/${PRODUCT}/pki-console-theme.jar:${CP}
 CP=/usr/share/java/${PRODUCT}/pki-console.jar:${CP}
diff --git a/base/java-tools/src/com/netscape/cmstools/HttpClient.java b/base/java-tools/src/com/netscape/cmstools/HttpClient.java
index f0603a4bd10f17240b5f3957d8d91da5af7b07a1..432be9c15c271e1739d14f31f9d6d695e2782023 100644
--- a/base/java-tools/src/com/netscape/cmstools/HttpClient.java
+++ b/base/java-tools/src/com/netscape/cmstools/HttpClient.java
@@ -40,6 +40,7 @@ import org.mozilla.jss.ssl.SSLHandshakeCompletedListener;
 import org.mozilla.jss.ssl.SSLSocket;
 import org.mozilla.jss.util.Password;
 
+import com.netscape.cmsutil.crypto.CryptoUtil;
 import com.netscape.cmsutil.util.Utils;
 
 /**
@@ -49,6 +50,7 @@ import com.netscape.cmsutil.util.Utils;
  */
 public class HttpClient {
     public static final String PR_INTERNAL_TOKEN_NAME = "internal";
+
     private String _host = null;
     private int _port = 0;
     private boolean _secure = false;
@@ -144,6 +146,9 @@ public class HttpClient {
                 SSLSocket.setSSLVersionRangeDefault(
                     org.mozilla.jss.ssl.SSLSocket.SSLProtocolVariant.DATA_GRAM,
                     datagram_range);
+
+                CryptoUtil.setClientCiphers();
+
                 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);
diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
index 3b1041a74bb4b663dd9c5f4c9fa983da133f04a3..8ef96d564de166002c73c8e78139bf3919ad870f 100644
--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
+++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java
@@ -24,6 +24,7 @@ import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.math.BigInteger;
+import java.net.SocketException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.KeyPair;
@@ -36,9 +37,12 @@ import java.security.cert.CertificateException;
 import java.security.interfaces.DSAParams;
 import java.security.interfaces.DSAPublicKey;
 import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Random;
 import java.util.StringTokenizer;
 import java.util.Vector;
@@ -122,6 +126,7 @@ import org.mozilla.jss.pkix.crmf.PKIArchiveOptions;
 import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
 import org.mozilla.jss.pkix.primitive.Name;
 import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
+import org.mozilla.jss.ssl.SSLSocket;
 import org.mozilla.jss.util.Base64OutputStream;
 import org.mozilla.jss.util.Password;
 
@@ -136,6 +141,17 @@ public class CryptoUtil {
     public static final String CERT_BEGIN_HEADING = "-----BEGIN CERTIFICATE-----";
     public static final String CERT_END_HEADING = "-----END CERTIFICATE-----";
 
+    static public final Integer[] clientECCiphers = {
+        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
+    };
+    static public List<Integer> clientECCipherList = new ArrayList<Integer>(Arrays.asList(clientECCiphers));
+
     private static final String[] ecCurves = {
             "nistp256", "nistp384", "nistp521", "sect163k1", "nistk163", "sect163r1", "sect163r2",
             "nistb163", "sect193r1", "sect193r2", "sect233k1", "nistk233", "sect233r1", "nistb233", "sect239k1",
@@ -676,6 +692,34 @@ public class CryptoUtil {
         return pair;
     }
 
+    public static void setClientCiphers()
+            throws SocketException {
+        int ciphers[] = SSLSocket.getImplementedCipherSuites();
+        for (int j = 0; ciphers != null && j < ciphers.length; j++) {
+            boolean enabled = SSLSocket.getCipherPreferenceDefault(ciphers[j]);
+            //System.out.println("CryptoUtil: 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("CryptoUtil: 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) && clientECCipherList.contains(ciphers[j])) {
+                  //System.out.println("CryptoUtil: enabling ECC NSS Cipher '0x" +
+                  //    Integer.toHexString(ciphers[j]) + "'");
+                  SSLSocket.setCipherPreferenceDefault(ciphers[j], true);
+                }
+            }
+        }
+    }
+
     public static byte[] getModulus(PublicKey pubk) {
         RSAPublicKey rsaKey = (RSAPublicKey) pubk;
 
-- 
1.8.4.2

