From b355cc0b4a8f61ef393f56b4cabbe8685ea16dd3 Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Sat, 27 Apr 2013 01:08:51 -0400
Subject: [PATCH] Reverting to old CLI behavior on client database
 initialization.

Recently the CLI was changed to initialize the default client database
automatically which will create it if it did not exist before. This was
causing a problem since the database was not created with a password.
To create the database properly a separate command is needed. For now
the CLI is reverted to the old behavior where it initializes the database
only if it requires for SSL connection and/or client authentication.
---
 .../src/com/netscape/certsrv/client/PKIClient.java | 47 ++++++++++++++++++++
 .../com/netscape/certsrv/client/PKIConnection.java | 14 ++++++
 .../src/com/netscape/cmstools/cli/MainCLI.java     | 50 +++-------------------
 3 files changed, 68 insertions(+), 43 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/client/PKIClient.java b/base/common/src/com/netscape/certsrv/client/PKIClient.java
index bd0d58c8877832a6f525676940f2f72364258041..f03ebf68df9a0b97836cbe753c9c49c7ce3487dd 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIClient.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIClient.java
@@ -1,8 +1,10 @@
 package com.netscape.certsrv.client;
 
+import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.security.GeneralSecurityException;
 import java.security.cert.CertificateEncodingException;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -10,10 +12,13 @@ import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.jboss.resteasy.client.ClientResponse;
+import org.mozilla.jss.CertDatabaseException;
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.CryptoManager.NicknameConflictException;
 import org.mozilla.jss.CryptoManager.NotInitializedException;
 import org.mozilla.jss.CryptoManager.UserCertConflictException;
+import org.mozilla.jss.KeyDatabaseException;
+import org.mozilla.jss.crypto.AlreadyInitializedException;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.InternalCertificate;
 import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
@@ -21,6 +26,8 @@ import org.mozilla.jss.crypto.ObjectNotFoundException;
 import org.mozilla.jss.crypto.TokenCertificate;
 import org.mozilla.jss.crypto.TokenException;
 import org.mozilla.jss.crypto.X509Certificate;
+import org.mozilla.jss.util.IncorrectPasswordException;
+import org.mozilla.jss.util.Password;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -34,6 +41,8 @@ public class PKIClient {
     public ClientConfig config;
     public PKIConnection connection;
 
+    File certDatabase;
+
     public boolean verbose;
 
     public PKIClient(ClientConfig config) {
@@ -42,6 +51,44 @@ public class PKIClient {
         connection = new PKIConnection(this);
     }
 
+    public void initCertDatabase() throws KeyDatabaseException,
+        CertDatabaseException, AlreadyInitializedException,
+        GeneralSecurityException, NotInitializedException,
+        TokenException, IncorrectPasswordException {
+
+        if (config.getCertDatabase() == null) {
+            certDatabase = new File(
+                    System.getProperty("user.home") + File.separator +
+                    ".dogtag" + File.separator + "nssdb");
+
+            certDatabase.mkdirs();
+
+        } else {
+            certDatabase = new File(config.getCertDatabase());
+        }
+
+        if (verbose) System.out.println("Certificate database: "+certDatabase.getAbsolutePath());
+
+        CryptoManager.initialize(certDatabase.getAbsolutePath());
+
+        // If password is specified, use password to access client database
+        if (config.getCertPassword() != null) {
+            CryptoManager manager = CryptoManager.getInstance();
+            CryptoToken token = manager.getInternalKeyStorageToken();
+            Password password = new Password(config.getCertPassword().toCharArray());
+
+            try {
+                token.login(password);
+
+            } catch (IncorrectPasswordException e) {
+                System.out.println("Error: "+e.getClass().getSimpleName()+": "+e.getMessage());
+                // The original exception doesn't contain a message.
+                throw new IncorrectPasswordException("Incorrect certificate database password.");
+            }
+
+        }
+    }
+
     public <T> T createProxy(Class<T> clazz) throws URISyntaxException {
         return connection.createProxy(clazz);
     }
diff --git a/base/common/src/com/netscape/certsrv/client/PKIConnection.java b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
index e0d4598508b82a6f6786dd3d49d4b999fb8e9a34..1b9c8edc58c761797f27a522499bc79300ff99e3 100644
--- a/base/common/src/com/netscape/certsrv/client/PKIConnection.java
+++ b/base/common/src/com/netscape/certsrv/client/PKIConnection.java
@@ -61,6 +61,7 @@ import org.jboss.resteasy.client.core.BaseClientResponse;
 import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
 import org.jboss.resteasy.client.core.extractors.ClientErrorHandler;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.mozilla.jss.crypto.AlreadyInitializedException;
 import org.mozilla.jss.crypto.X509Certificate;
 import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
 import org.mozilla.jss.ssl.SSLSocket;
@@ -446,6 +447,19 @@ public class PKIConnection {
                 UnknownHostException,
                 ConnectTimeoutException {
 
+            // Make sure certificate database is initialized
+            // before using SSLSocket, otherwise it will throw
+            // UnsatisfiedLinkError.
+            try {
+                client.initCertDatabase();
+
+            } catch (AlreadyInitializedException e) {
+                // ignore
+
+            } catch (Exception e) {
+                throw new Error(e);
+            }
+
             String hostName = null;
             int port = 0;
             if (remoteAddress != null) {
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
index 3c0c3d6bc0ce15642566e818f2845a5a811e2af4..50095b173c5b9a4d43c320cc5e81b9dcc25555c2 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -29,11 +29,7 @@ import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.lang.StringUtils;
-import org.mozilla.jss.CryptoManager;
-import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
-import org.mozilla.jss.util.IncorrectPasswordException;
-import org.mozilla.jss.util.Password;
 
 import com.netscape.certsrv.account.AccountClient;
 import com.netscape.certsrv.client.ClientConfig;
@@ -232,7 +228,7 @@ public class MainCLI extends CLI {
         }
     }
 
-    public void connect() throws Exception {
+    public void init() throws Exception {
 
         client = new PKIClient(config);
         client.setVerbose(verbose);
@@ -248,6 +244,11 @@ public class MainCLI extends CLI {
         }
 
         accountClient = new AccountClient(client);
+
+        // initialize certificate database if specified
+        if (config.getCertDatabase() != null) {
+            client.initCertDatabase();
+        }
     }
 
     public void execute(String[] args) throws Exception {
@@ -334,47 +335,10 @@ public class MainCLI extends CLI {
 
         if (verbose) System.out.println("Server URI: "+config.getServerURI());
 
-        // initialize certificate database
-        if (config.getCertDatabase() == null) {
-            this.certDatabase = new File(
-                    System.getProperty("user.home") + File.separator +
-                    ".dogtag" + File.separator + "nssdb");
-
-        } else {
-            this.certDatabase = new File(config.getCertDatabase());
-        }
-
-        certDatabase.mkdirs();
-
-        try {
-            if (verbose) System.out.println("Certificate database: "+certDatabase.getAbsolutePath());
-            CryptoManager.initialize(certDatabase.getAbsolutePath());
-
-            if (config.getCertPassword() != null) {
-                try {
-                    CryptoManager manager = CryptoManager.getInstance();
-                    CryptoToken token = manager.getInternalKeyStorageToken();
-                    Password password = new Password(config.getCertPassword().toCharArray());
-                    token.login(password);
-
-                } catch (IncorrectPasswordException e) {
-                    throw new Error("Incorrect certificate database password.", e);
-                }
-            }
-
-        } catch (Throwable t) {
-            if (verbose) {
-                t.printStackTrace(System.err);
-            } else {
-                System.err.println(t.getClass().getSimpleName()+": "+t.getMessage());
-            }
-            System.exit(1);
-        }
-
         // execute command
         boolean loggedIn = false;
         try {
-            connect();
+            init();
 
             // login if username or nickname is specified
             if (config.getUsername() != null || config.getCertNickname() != null) {
-- 
1.8.1.4

