>From cb014ebeff2dd35f2f005f6d57fae11c3c9dae6a Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Thu, 16 Apr 2015 22:26:03 -0400
Subject: [PATCH] Add nuxwdog functionality to Dogtag

This is the first of several commits.  This adds a LifecycleListener
to call init() on the nuxwdog client before any connectors or webapps
start up, and call sendEndInit() once initialization completes.

Code is also added to prompt for and test required passwords on startup.
All that is required to use nuxwdog is to start the server using nuxwdog.
An environment variable will be set that will trigger creation of the
NuxwdogPasswordStore.  We expect tags for the required passwords to be in
cms.passwordList
---
 .classpath                                         |   3 +-
 base/common/src/com/netscape/certsrv/apps/CMS.java |   2 +-
 .../src/com/netscape/certsrv/apps/ICMSEngine.java  |   2 +-
 .../netscape/cmstools/profile/ProfileAddCLI.java   |   3 -
 .../cms/servlet/csadmin/GetConfigEntries.java      |   8 +-
 base/server/cmscore/src/CMakeLists.txt             |   9 +
 .../src/com/netscape/cmscore/apps/CMSEngine.java   | 188 ++++++++++++++++++---
 .../netscape/cmscore/ldapconn/LdapAuthInfo.java    |   6 +-
 .../cmscore/profile/AbstractProfileSubsystem.java  |   1 -
 base/server/etc/default.cfg                        |   3 +
 .../deployment/scriptlets/instance_layout.py       |   7 +
 base/server/tomcat/src/CMakeLists.txt              |  17 +-
 .../tomcat/NuxwdogPasswordStoreInitializer.java    |  33 ++++
 base/util/src/CMakeLists.txt                       |  10 +-
 .../netscape/cmsutil/http/JssSSLSocketFactory.java |   1 -
 .../netscape/cmsutil/password/IPasswordStore.java  |   2 +-
 .../cmsutil/password/NuxwdogPasswordStore.java     |  49 ++++++
 .../cmsutil/password/PlainPasswordFile.java        |   4 +-
 scripts/compose_pki_test_package                   |   1 +
 specs/pki-core.spec                                |   2 +
 20 files changed, 309 insertions(+), 42 deletions(-)
 create mode 100644 base/server/tomcat/src/com/netscape/cms/tomcat/NuxwdogPasswordStoreInitializer.java
 create mode 100644 base/util/src/com/netscape/cmsutil/password/NuxwdogPasswordStore.java

diff --git a/.classpath b/.classpath
index 9886a5236a6a88398efe123efdc7688391a88279..54b0b5edd1fa9a68c8a166de9fa9ea36f2f2d734 100644
--- a/.classpath
+++ b/.classpath
@@ -50,11 +50,12 @@
 	<classpathentry kind="lib" path="/usr/share/java/xerces-j2.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/xml-commons-apis.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/istack-commons-runtime.jar"/>
-	<classpathentry kind="lib" path="/usr/lib64/jss/jss4.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/apache-commons-lang.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/resteasy/resteasy-atom-provider.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/tomcat/catalina.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/tomcat/tomcat-util.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/commons-io.jar"/>
+	<classpathentry kind="lib" path="/usr/lib/java/nuxwdog.jar"/>
+	<classpathentry kind="lib" path="/usr/lib/java/jss4.jar"/>
 	<classpathentry kind="output" path="build/classes"/>
 </classpath>
diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java
index 85c8e58ca81c5bc3afc0b13fe3f391a047ba5a8e..5ba6dc0a6b29a9f072f17a8e0d9cf5afa1ac8d69 100644
--- a/base/common/src/com/netscape/certsrv/apps/CMS.java
+++ b/base/common/src/com/netscape/certsrv/apps/CMS.java
@@ -1647,7 +1647,7 @@ public final class CMS {
         _engine.setListOfVerifiedCerts(size, interval, unknownStateInterval);
     }
 
-    public static IPasswordStore getPasswordStore() {
+    public static IPasswordStore getPasswordStore() throws EBaseException {
         return _engine.getPasswordStore();
     }
 
diff --git a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
index 5c78a7c0f9c4144df8369a6017876f900e57605d..294447d293c9c3c6ab0d78611d27cdca3e56e982 100644
--- a/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
+++ b/base/common/src/com/netscape/certsrv/apps/ICMSEngine.java
@@ -1135,7 +1135,7 @@ public interface ICMSEngine extends ISubsystem {
      */
     public void forceShutdown();
 
-    public IPasswordStore getPasswordStore();
+    public IPasswordStore getPasswordStore() throws EBaseException;
 
     public ISecurityDomainSessionTable getSecurityDomainSessionTable();
 
diff --git a/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java b/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java
index 306ff19058e22017ea0b4bd502958ab17130c6d3..fc144c13dd555330b4d153bee709e9f36dcb7624 100644
--- a/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/profile/ProfileAddCLI.java
@@ -1,11 +1,8 @@
 package com.netscape.cmstools.profile;
 
-import java.io.IOException;
 import java.util.Arrays;
 import java.util.Properties;
 
-import javax.xml.bind.JAXBException;
-
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.ParseException;
diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java
index dcb8bdf8a1c5c82fd1718a625ef34e2aa5d66578..8250b3b744e0444b846cf2c6114b05412eb53531 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java
@@ -219,14 +219,14 @@ public class GetConfigEntries extends CMSServlet {
     protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript.
     }
 
-    private String getLDAPPassword() {
+    private String getLDAPPassword() throws EBaseException {
         IPasswordStore pwdStore = CMS.getPasswordStore();
-        return pwdStore.getPassword("internaldb");
+        return pwdStore.getPassword("internaldb", 0);
     }
 
-    private String getReplicationPassword() {
+    private String getReplicationPassword() throws EBaseException {
         IPasswordStore pwdStore = CMS.getPasswordStore();
-        return pwdStore.getPassword("replicationdb");
+        return pwdStore.getPassword("replicationdb", 0);
     }
 
 }
diff --git a/base/server/cmscore/src/CMakeLists.txt b/base/server/cmscore/src/CMakeLists.txt
index 94f5f138c4e48161392412770d85dbe1a0c8f28d..ef12938652250b98187e1e8157d12df902179ade 100644
--- a/base/server/cmscore/src/CMakeLists.txt
+++ b/base/server/cmscore/src/CMakeLists.txt
@@ -118,6 +118,14 @@ find_file(HTTPCORE_JAR
         /usr/share/java/httpcomponents
 )
 
+find_file(NUXWDOG_JAR
+    NAMES
+        nuxwdog.jar
+    PATHS
+        ${JAVA_LIB_INSTALL_DIR}
+        /usr/share/java
+)
+
 # build pki-cmscore
 javac(pki-cmscore-classes
     SOURCES
@@ -130,6 +138,7 @@ javac(pki-cmscore-classes
         ${TOMCAT_CATALINA_JAR} ${TOMCAT_UTIL_JAR} ${SYMKEY_JAR}
         ${JAXRS_API_JAR} ${RESTEASY_JAXRS_JAR} ${RESTEASY_ATOM_PROVIDER_JAR}
         ${HTTPCLIENT_JAR} ${HTTPCORE_JAR}
+        ${NUXWDOG_JAR}
     OUTPUT_DIR
         ${CMAKE_BINARY_DIR}/classes
     DEPENDS
diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
index b682130dd43810d7cd2122e5390a2a08889c372d..dac71ec28700e75c834634911ac3b6f0b42b0870 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java
@@ -58,6 +58,7 @@ import netscape.security.x509.X509CRLImpl;
 import netscape.security.x509.X509CertImpl;
 import netscape.security.x509.X509CertInfo;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.xerces.parsers.DOMParser;
 import org.mozilla.jss.CryptoManager.CertificateUsage;
 import org.mozilla.jss.util.PasswordCallback;
@@ -260,6 +261,14 @@ public class CMSEngine implements ICMSEngine {
             { null, null, null } //ssl_clientauth_EE
     };
 
+    private static final int PW_OK =0;
+    private static final int PW_BAD_SETUP = 1;
+    private static final int PW_INVALID_PASSWORD = 2;
+    private static final int PW_CANNOT_CONNECT = 3;
+    private static final int PW_NO_USER = 4;
+    private static final int PW_MAX_ATTEMPTS = 3;
+
+
     /**
      * private constructor.
      */
@@ -281,41 +290,166 @@ public class CMSEngine implements ICMSEngine {
     }
 
     /**
-     * Retrieves the instance roort path of this server.
+     * Retrieves the instance root path of this server.
      */
     public String getInstanceDir() {
         return instanceDir;
     }
 
-    public synchronized IPasswordStore getPasswordStore() {
-        // initialize the PasswordReader and PasswordWriter
-        try {
-            String pwdPath = mConfig.getString("passwordFile");
-            if (mPasswordStore == null) {
-                CMS.debug("CMSEngine: getPasswordStore(): password store not initialized before.");
-                String pwdClass = mConfig.getString("passwordClass");
+    public boolean startedByNuxwdog() {
+        String wdPipeName = System.getenv("WD_PIPE_NAME");
+        if (StringUtils.isNotEmpty(wdPipeName)) {
+            return true;
+        }
+        return false;
+    }
 
-                try {
-                    mPasswordStore = (IPasswordStore) Class.forName(pwdClass).newInstance();
-                } catch (Exception e) {
-                    CMS.debug("CMSEngine: getPasswordStore(): password store initialization failure:"
-                            + e.toString());
-                    throw e;
-                }
+    public synchronized IPasswordStore getPasswordStore() throws EBaseException {
+        if (mPasswordStore == null) {
+            String pwdClass = null;
+            String pwdPath = null;
+
+            if (startedByNuxwdog()) {
+                pwdClass = mConfig.getString("nuxwdogPasswordClass",
+                        "com.netscape.cmsutil.password.NuxwdogPasswordStore");
             } else {
-                CMS.debug("CMSEngine: getPasswordStore(): password store initialized before.");
+                pwdClass = mConfig.getString("passwordClass");
+                pwdPath = mConfig.getString("passwordFile", null);
             }
 
-            // have to initialize it because other places don't always
-            mPasswordStore.init(pwdPath);
-            CMS.debug("CMSEngine: getPasswordStore(): password store initialized.");
-        } catch (Exception e) {
-            CMS.debug("CMSEngine: getPasswordStore(): failure:" + e.toString());
+            try {
+                mPasswordStore = (IPasswordStore) Class.forName(pwdClass).newInstance();
+                mPasswordStore.init(pwdPath);
+            } catch (Exception e) {
+                System.out.println("Cannot get password store: " + e);
+                throw new EBaseException(e);
+            }
         }
-
         return mPasswordStore;
     }
 
+    public void initializePasswordStore(IConfigStore config) throws EBaseException, IOException {
+        // create and initialize mPasswordStore
+        getPasswordStore();
+
+        boolean skipPublishingCheck = config.getBoolean(
+                "cms.password.ignore.publishing.failure", true);
+        String pwList = config.getString("cms.passwordlist", "internaldb,replicationdb");
+        String tags[] = StringUtils.split(pwList, ",");
+
+        for (String tag : tags) {
+            int iteration = 0;
+            int result = PW_INVALID_PASSWORD;
+            String binddn;
+            String authType;
+            LdapConnInfo connInfo = null;
+
+            if (tag.equals("internaldb")) {
+                authType = config.getString("internaldb.ldapauth.authtype", "BasicAuth");
+                if (!authType.equals("BasicAuth"))
+                    continue;
+
+                connInfo = new LdapConnInfo(
+                        config.getString("internaldb.ldapconn.host"),
+                        config.getInteger("internaldb.ldapconn.port"),
+                        config.getBoolean("internaldb.ldapconn.secureConn"));
+
+                binddn = config.getString("internaldb.ldapauth.bindDN");
+            } else if (tag.equals("replicationdb")) {
+                authType = config.getString("internaldb.ldapauth.authtype", "BasicAuth");
+                if (!authType.equals("BasicAuth"))
+                    continue;
+
+                connInfo = new LdapConnInfo(
+                        config.getString("internaldb.ldapconn.host"),
+                        config.getInteger("internaldb.ldapconn.port"),
+                        config.getBoolean("internaldb.ldapconn.secureConn"));
+
+                binddn = "cn=Replication Manager masterAgreement1-" + config.getString("machineName", "") + "-" +
+                        config.getString("instanceId", "") + ",cn=config";
+            } else if (tags.equals("CA LDAP Publishing")) {
+                authType = config.getString("ca.publish.ldappublish.ldap.ldapauth.authtype", "BasicAuth");
+                if (!authType.equals("BasicAuth"))
+                    continue;
+
+                connInfo = new LdapConnInfo(
+                        config.getString("ca.publish.ldappublish.ldap.ldapconn.host"),
+                        config.getInteger("ca.publish.ldappublish.ldap.ldapconn.port"),
+                        config.getBoolean("ca.publish.ldappublish.ldap.ldapconn.secureConn"));
+
+                binddn = config.getString("ca.publish.ldappublish.ldap.ldapauth.bindDN");
+
+            } else {
+                // ignore any others for now
+                continue;
+            }
+
+            do {
+                String passwd = mPasswordStore.getPassword(tag, iteration);
+                result = testLDAPConnection(tag, connInfo, binddn, passwd);
+                iteration++;
+            } while ((result == PW_INVALID_PASSWORD) && (iteration < PW_MAX_ATTEMPTS));
+
+            if (result != PW_OK) {
+                if ((result == PW_NO_USER) && (tag.equals("replicationdb"))) {
+                    System.out.println(
+                        "CMSEngine: init(): password test execution failed for replicationdb" +
+                        "with NO_SUCH_USER.  This may not be a latest instance.  Ignoring ..");
+                } else if (skipPublishingCheck && (result == PW_CANNOT_CONNECT) && (tag.equals("CA LDAP Publishing"))) {
+                    System.out.println(
+                        "Unable to connect to the publishing database to check password, " +
+                        "but continuing to start up.  Please check if publishing is operational.");
+                } else {
+                    // password test failed
+                    System.out.println("CMSEngine: init(): password test execution failed: " + result);
+                    throw new EBaseException("Password test execution failed. Is the database up?");
+                }
+            }
+        }
+    }
+
+    public int testLDAPConnection(String name, LdapConnInfo info, String binddn, String pwd) {
+        int ret = PW_OK;
+
+        if (StringUtils.isEmpty(pwd))
+            return PW_INVALID_PASSWORD;
+
+        String host = info.getHost();
+        int port = info.getPort();
+
+        LDAPConnection conn = info.getSecure() ?
+                new LDAPConnection(CMS.getLdapJssSSLSocketFactory()) :
+                new LDAPConnection();
+
+        System.out.println("testLDAPConnection connecting to " + host + ":" + port);
+
+        try {
+            conn.connect(host, port, binddn, pwd);
+        } catch (LDAPException e) {
+            switch (e.getLDAPResultCode()) {
+            case LDAPException.NO_SUCH_OBJECT:
+                System.out.println("testLDAPConnection: The specified user " + binddn + " does not exist");
+                ret = PW_NO_USER;
+                break;
+            case LDAPException.INVALID_CREDENTIALS:
+                System.out.println("testLDAPConnection: Invalid Password");
+                ret = PW_INVALID_PASSWORD;
+                break;
+            default:
+                System.out.println("testLDAPConnection: Unable to connect to " + name + ": " + e);
+                ret = PW_CANNOT_CONNECT;
+                break;
+            }
+        } finally {
+            try {
+                if (conn != null)
+                    conn.disconnect();
+            } catch (Exception e) {
+            }
+        }
+        return ret;
+    }
+
     /**
      * initialize all static, dynamic and final static subsystems.
      *
@@ -332,6 +466,16 @@ public class CMSEngine implements ICMSEngine {
 
         serverStatus = "starting";
 
+        if (state == 1) {
+            // configuration is complete, initialize password store
+            try {
+                initializePasswordStore(config);
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new EBaseException("Exception while initializing password store: " + e);
+            }
+        }
+
         // my default is 1 day
         String flush_timeout = config.getString("securitydomain.flushinterval", "86400000");
         String secdomain_source = config.getString("securitydomain.source", "memory");
diff --git a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java
index eb3fde26c55730cf56ea586991566ec8654a856d..4fd09a711539102e74f48a744289ca3664dd9ed1 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/ldapconn/LdapAuthInfo.java
@@ -62,7 +62,7 @@ public class LdapAuthInfo implements ILdapAuthInfo {
         init(config, host, port, secure);
     }
 
-    public String getPasswordFromStore(String prompt) {
+    public String getPasswordFromStore(String prompt) throws EBaseException {
         String pwd = null;
         CMS.debug("LdapAuthInfo: getPasswordFromStore: try to get it from password store");
 
@@ -82,7 +82,7 @@ public class LdapAuthInfo implements ILdapAuthInfo {
         // Finally, interactively obtain the password from the user
         if (pwdStore != null) {
             CMS.debug("LdapAuthInfo: getPasswordFromStore: password store available");
-            pwd = pwdStore.getPassword(prompt);
+            pwd = pwdStore.getPassword(prompt, 0);
             //            pwd = pstore.getString(prompt);
             if (pwd == null) {
                 CMS.debug("LdapAuthInfo: getPasswordFromStore: password for " + prompt +
@@ -90,7 +90,7 @@ public class LdapAuthInfo implements ILdapAuthInfo {
 
                 //               pwd = pstore.getString("internaldb");
 
-                pwd = pwdStore.getPassword("internaldb"); // last resort
+                pwd = pwdStore.getPassword("internaldb", 0); // last resort
             } else
                 CMS.debug("LdapAuthInfo: getPasswordFromStore: password found for prompt in password store");
         } else
diff --git a/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java b/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java
index 642f60232806eaadc68398bd21d2912dc920cda9..8125dfac9f7980f3be9e464c9091e00d267f02d1 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/profile/AbstractProfileSubsystem.java
@@ -34,7 +34,6 @@ public abstract class AbstractProfileSubsystem implements IProfileSubsystem {
     protected static final String PROP_ENABLE_BY = "enableBy";
 
     protected IConfigStore mConfig = null;
-    @SuppressWarnings("unused")
     protected ISubsystem mOwner;
     protected Hashtable<String, IProfile> mProfiles;
     protected Hashtable<String, String> mProfileClassIds;
diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index 50117a20e1f2574f9025974cadfa8e1dd8ed1fb6..a0b6924dbef1cfd1a4ce477740c49d5ed4da683b 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -322,6 +322,9 @@ pki_resteasy_jaxrs_api_jar=%(resteasy_lib)s/jaxrs-api.jar
 pki_resteasy_jaxrs_jar=%(resteasy_lib)s/resteasy-jaxrs.jar
 pki_resteasy_jackson_provider_jar=%(resteasy_lib)s/resteasy-jackson-provider.jar
 
+# nuxwdog
+pki_nuxwdog_client_jar=/usr/lib/java/nuxwdog.jar
+
 
 ###############################################################################
 ##  CA Configuration:                                                        ##
diff --git a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
index 98efcd04f835350309d4c5c67fa641da5ad08f7a..3a4d3faa394fc8cb433f838d7837df6a29924a45 100644
--- a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
+++ b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py
@@ -255,6 +255,13 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                     deployer.mdict['pki_tomcat_common_lib_path'],
                     'resteasy-jackson-provider.jar'))
 
+            # nuxwdog
+            deployer.symlink.create(
+                deployer.mdict['pki_nuxwdog_client_jar'],
+                os.path.join(
+                    deployer.mdict['pki_tomcat_common_lib_path'],
+                    'nuxwdog.jar'))
+
             # establish shared NSS security databases for this instance
             deployer.directory.create(deployer.mdict['pki_database_path'])
             # establish instance convenience symbolic links
diff --git a/base/server/tomcat/src/CMakeLists.txt b/base/server/tomcat/src/CMakeLists.txt
index d9808a8033e2c43a4653652f74e6e9b687be8e62..1e4f087cf5407d992d125aadc9d963447e0a53d2 100644
--- a/base/server/tomcat/src/CMakeLists.txt
+++ b/base/server/tomcat/src/CMakeLists.txt
@@ -118,12 +118,27 @@ find_file(HTTPCORE_JAR
         /usr/share/java/httpcomponents
 )
 
+find_file(NUXWDOG_JAR
+    NAMES
+        nuxwdog.jar
+    PATHS
+        ${JAVA_LIB_INSTALL_DIR}
+        /usr/share/java
+)
+
+find_file(APACHE_COMMONS_LANG_JAR
+    NAMES
+        apache-commons-lang.jar
+    PATHS
+        /usr/share/java
+)
+
 # build pki-tomcat
 javac(pki-tomcat-classes
     SOURCES
         com/netscape/cms/tomcat/*.java
     CLASSPATH
-        ${SERVLET_JAR} ${TOMCAT_CATALINA_JAR}
+        ${SERVLET_JAR} ${TOMCAT_CATALINA_JAR} ${NUXWDOG_JAR} ${APACHE_COMMONS_LANG_JAR}
     OUTPUT_DIR
         ${CMAKE_BINARY_DIR}/classes
 )
diff --git a/base/server/tomcat/src/com/netscape/cms/tomcat/NuxwdogPasswordStoreInitializer.java b/base/server/tomcat/src/com/netscape/cms/tomcat/NuxwdogPasswordStoreInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4c25306da959b3f90b1aaafa8ff18acbb5c1582
--- /dev/null
+++ b/base/server/tomcat/src/com/netscape/cms/tomcat/NuxwdogPasswordStoreInitializer.java
@@ -0,0 +1,33 @@
+package com.netscape.cms.tomcat;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.commons.lang.StringUtils;
+
+import com.redhat.nuxwdog.WatchdogClient;
+
+public class NuxwdogPasswordStoreInitializer implements LifecycleListener {
+
+    private boolean startedByWD = false;
+
+    @Override
+    public void lifecycleEvent(LifecycleEvent event) {
+        String method = "NuxwdogReader:lifecycleEvent";
+        if (event.getType().equals(Lifecycle.BEFORE_INIT_EVENT)) {
+            System.out.println(method + ": before init event");
+            String wdPipeName = System.getenv("WD_PIPE_NAME");
+            if (StringUtils.isNotEmpty(wdPipeName)) {
+                startedByWD = true;
+                System.out.println(method + ": Initializing the watchdog");
+                WatchdogClient.init();
+            }
+        } else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
+            System.out.println(method + "After start event");
+            if (startedByWD) {
+                System.out.println(method + ": Sending endInit to the Watchdog");
+                WatchdogClient.sendEndInit(0);
+            }
+        }
+    }
+
+}
diff --git a/base/util/src/CMakeLists.txt b/base/util/src/CMakeLists.txt
index efef8af536bad8a2410c7b64abbfa8868e501612..f374c01def727eab178ed04320b1e8ed5fa1cb77 100644
--- a/base/util/src/CMakeLists.txt
+++ b/base/util/src/CMakeLists.txt
@@ -60,6 +60,14 @@ find_file(XERCES_JAR
         /usr/share/java
 )
 
+find_file(NUXWDOG_JAR
+    NAMES
+        nuxwdog.jar
+    PATHS
+        ${JAVA_LIB_INSTALL_DIR}
+        /usr/share/java
+)
+
 # build pki-nsutil
 javac(pki-nsutil-classes
     SOURCES
@@ -108,7 +116,7 @@ javac(pki-cmsutil-classes
     CLASSPATH
         ${APACHE_COMMONS_LANG_JAR} ${HTTPCORE_JAR} ${HTTPCLIENT_JAR}
         ${LDAPJDK_JAR} ${XALAN_JAR} ${XERCES_JAR}
-        ${JSS_JAR} ${COMMONS_CODEC_JAR}
+        ${JSS_JAR} ${COMMONS_CODEC_JAR} ${NUXWDOG_JAR}
     OUTPUT_DIR
         ${CMAKE_BINARY_DIR}/classes
     DEPENDS
diff --git a/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java b/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java
index 2f8a40ca2f8901596ce487e430b76efd8529dbf6..166479d5aad9eb4790c01cbaa92c9d56e69d6726 100644
--- a/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java
+++ b/base/util/src/com/netscape/cmsutil/http/JssSSLSocketFactory.java
@@ -19,7 +19,6 @@ package com.netscape.cmsutil.http;
 
 import java.io.IOException;
 import java.net.Socket;
-import java.net.SocketException;
 import java.net.UnknownHostException;
 
 import org.mozilla.jss.CryptoManager;
diff --git a/base/util/src/com/netscape/cmsutil/password/IPasswordStore.java b/base/util/src/com/netscape/cmsutil/password/IPasswordStore.java
index 49b2610fa8a47cb6e9b712a05d887d22cb491c29..00ec4ccdfeb7156dfa34e15977c7868ab2bd49e8 100644
--- a/base/util/src/com/netscape/cmsutil/password/IPasswordStore.java
+++ b/base/util/src/com/netscape/cmsutil/password/IPasswordStore.java
@@ -23,7 +23,7 @@ import java.util.Enumeration;
 public interface IPasswordStore {
     public void init(String pwdPath) throws IOException;
 
-    public String getPassword(String tag);
+    public String getPassword(String tag, int iteration);
 
     public Enumeration<String> getTags();
 
diff --git a/base/util/src/com/netscape/cmsutil/password/NuxwdogPasswordStore.java b/base/util/src/com/netscape/cmsutil/password/NuxwdogPasswordStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b50c0c13afe2b182bedb49af5c235d2b2ff1b85
--- /dev/null
+++ b/base/util/src/com/netscape/cmsutil/password/NuxwdogPasswordStore.java
@@ -0,0 +1,49 @@
+package com.netscape.cmsutil.password;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.redhat.nuxwdog.WatchdogClient;
+
+public class NuxwdogPasswordStore implements IPasswordStore {
+
+    // Note: pwCache is a temporary construct needed because nuxwdog currently
+    // does not expose a putPassword() method.  When this is added, pwCache will
+    // no longer be needed.
+    private Hashtable<String, String> pwCache = null;
+
+    private final String PROMPT_PREFIX = "Please provide the password for ";
+
+    @Override
+    public void init(String pwdPath) throws IOException {
+        pwCache = new Hashtable<String, String>();
+    }
+
+    @Override
+    public String getPassword(String tag, int iteration) {
+        if (pwCache.containsKey(tag)) {
+            return pwCache.get(tag);
+        }
+
+        String prompt = PROMPT_PREFIX + tag + " :";
+        return WatchdogClient.getPassword(prompt, iteration);
+    }
+
+    @Override
+    public Enumeration<String> getTags() {
+        // not yet implemented for this password store
+        return null;
+    }
+
+    @Override
+    public Object putPassword(String tag, String password) {
+        return pwCache.put(tag, password);
+    }
+
+    @Override
+    public void commit() throws IOException, ClassCastException, NullPointerException {
+        // Nothing required here
+    }
+
+}
diff --git a/base/util/src/com/netscape/cmsutil/password/PlainPasswordFile.java b/base/util/src/com/netscape/cmsutil/password/PlainPasswordFile.java
index 990d0c156fb1d26092125851e6f8b3c9a99e5133..a3cd598c5ffef45a7a2e2fb59d208daea4da682e 100644
--- a/base/util/src/com/netscape/cmsutil/password/PlainPasswordFile.java
+++ b/base/util/src/com/netscape/cmsutil/password/PlainPasswordFile.java
@@ -30,11 +30,11 @@ public class PlainPasswordFile implements IPasswordStore {
     private static final String PASSWORD_WRITER_HEADER = "";
 
     public PlainPasswordFile() {
+        mPwdStore = new Properties();
     }
 
     public void init(String pwdPath)
             throws IOException {
-        mPwdStore = new Properties();
         // initialize mPwdStore
         mPwdPath = pwdPath;
         FileInputStream file = null;
@@ -48,7 +48,7 @@ public class PlainPasswordFile implements IPasswordStore {
         }
     }
 
-    public String getPassword(String tag) {
+    public String getPassword(String tag, int iteration) {
         return mPwdStore.getProperty(tag);
     }
 
diff --git a/scripts/compose_pki_test_package b/scripts/compose_pki_test_package
index b738c6e2b146f6a64bc070ab3758507c6bd83d3e..069292017fccf639f3f218bccc6fd414bd9e03ed 100755
--- a/scripts/compose_pki_test_package
+++ b/scripts/compose_pki_test_package
@@ -129,6 +129,7 @@ CLASSPATH=$CLASSPATH:/usr/share/java/xml-commons-apis.jar
 CLASSPATH=$CLASSPATH:/usr/share/java/tomcat/catalina.jar
 CLASSPATH=$CLASSPATH:/usr/share/java/tomcat/tomcat-util.jar
 CLASSPATH=$CLASSPATH:/usr/share/java/commons-io.jar
+CLASSPATH=$CLASSPATH:/usr/lib/java/nuxwdog.jar
 
 javac -classpath $CLASSPATH -d bin src/*java
 
diff --git a/specs/pki-core.spec b/specs/pki-core.spec
index 5117695a1c5af0c7772f524af692e416c4cd7bf9..71444ecae252c71dc6bc568fd44d2b9dd3176aea 100644
--- a/specs/pki-core.spec
+++ b/specs/pki-core.spec
@@ -30,6 +30,7 @@ BuildRequires:    apache-commons-io
 BuildRequires:    jakarta-commons-httpclient
 BuildRequires:    nspr-devel
 BuildRequires:    nss-devel >= 3.14.3
+BuildRequires:    nuxwdog-client-java
 BuildRequires:    openldap-devel
 BuildRequires:    pkgconfig
 BuildRequires:    policycoreutils
@@ -326,6 +327,7 @@ Obsoletes:        pki-silent < %{version}-%{release}
 
 Requires:         java-headless >= 1:1.7.0
 Requires:         net-tools
+Requires:         nuxwdog
 Requires:         perl(File::Slurp)
 Requires:         policycoreutils
 Requires:         openldap-clients
-- 
1.9.3

