Index: .classpath
===================================================================
--- .classpath	(revision 293)
+++ .classpath	(working copy)
@@ -6,5 +6,6 @@
 	<classpathentry kind="lib" path="/usr/share/java/apache-commons-logging.jar"/>
 	<classpathentry kind="lib" path="/usr/lib/java/jss4.jar"/>
 	<classpathentry kind="lib" path="/usr/share/java/tomcat/tomcat-coyote.jar"/>
+	<classpathentry kind="lib" path="/usr/lib/java/nuxwdog.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
Index: build.xml
===================================================================
--- build.xml	(revision 293)
+++ build.xml	(working copy)
@@ -104,6 +104,8 @@
   <!-- This property is set to '/dirsec' when built on rhel4 -->
   <property name="dirsec" value="" />
   <property name="jss.jar" value="${jss.home}${dirsec}/jss4.jar" />
+  <property name="nuxwdog.jar" value="${jnidir}/nuxwdog.jar" />
+  <property name="commons-lang.jar" value="${jar.home}/commons-lang.jar" />
 
   <!--
     Classpath
@@ -112,6 +114,8 @@
     <pathelement location="${jss.jar}"/>
     <pathelement location="${tomcat-coyote.jar}"/>
     <pathelement location="${commons-logging.jar}"/>
+    <pathelement location="${commons-lang.jar}"/>
+    <pathelement location="${nuxwdog.jar}"/>
   </path>
 
   <!--
Index: src/org/apache/tomcat/util/net/jss/IPasswordStore.java
===================================================================
--- src/org/apache/tomcat/util/net/jss/IPasswordStore.java	(revision 294)
+++ src/org/apache/tomcat/util/net/jss/IPasswordStore.java	(working copy)
@@ -12,7 +12,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Copyright (C) 2007 Red Hat, Inc.
  * All rights reserved.
  * END COPYRIGHT BLOCK */
@@ -23,9 +23,9 @@
 import java.util.Enumeration;
 
 public interface IPasswordStore {
-    public void init(String pwdPath) throws IOException;
+    public void init(String pwdPath, String confFile) throws IOException;
 
-    public String getPassword(String tag);
+    public String getPassword(String tag, int iteration);
 
     public Enumeration<String> getTags();
 
Index: src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java
===================================================================
--- src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java	(revision 294)
+++ src/org/apache/tomcat/util/net/jss/JSSSocketFactory.java	(working copy)
@@ -12,7 +12,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Copyright (C) 2007 Red Hat, Inc.
  * All rights reserved.
  * END COPYRIGHT BLOCK */
@@ -29,6 +29,7 @@
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
+import java.security.GeneralSecurityException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Enumeration;
@@ -41,11 +42,17 @@
 
 // Imports required to "implement" Tomcat 7 Interface
 import org.apache.tomcat.util.net.AbstractEndpoint;
+import org.mozilla.jss.CertDatabaseException;
 import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.KeyDatabaseException;
+import org.mozilla.jss.NoSuchTokenException;
 import org.mozilla.jss.crypto.AlreadyInitializedException;
 import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.TokenException;
 import org.mozilla.jss.ssl.SSLServerSocket;
 import org.mozilla.jss.ssl.SSLSocket;
+import org.mozilla.jss.util.IncorrectPasswordException;
 import org.mozilla.jss.util.Password;
 
 public class JSSSocketFactory implements
@@ -460,10 +467,10 @@
     /*
      * setSSLVersionRangeDefault sets the range of allowed ssl versions. This
      * replaces the obsolete SSL_Option* API
-     * 
+     *
      * @param protoVariant indicates whether this setting is for type "stream"
      * or "datagram"
-     * 
+     *
      * @param sslVersionRange_s takes on the form of "min:max" where min/max
      * values can be "ssl3, tls1_0, tls1_1, or tls1_2" ssl2 is not supported for
      * tomcatjss via this interface The format is "sslVersionRange=min:max"
@@ -517,101 +524,33 @@
     }
 
     void init() throws IOException {
-        try {
-            String deb = (String) endpoint.getAttribute("debug");
-            if (deb.equals("true")) {
-                debug = true;
-                debugFile = new FileWriter("/tmp/tomcatjss.log", true);
-                debugWrite("JSSSocketFactory init - debug is on\n");
-            }
-        } catch (Exception e) {
-            // System.out.println("no tomcatjss debugging");
+
+        String deb = (String) endpoint.getAttribute("debug");
+        if (deb.equals("true")) {
+            debug = true;
+            debugFile = new FileWriter("/tmp/tomcatjss.log", true);
+            debugWrite("JSSSocketFactory init - debug is on\n");
         }
 
         try {
-            try {
-                mPwdPath = (String) endpoint.getAttribute("passwordFile");
-                mPwdClass = (String) endpoint.getAttribute("passwordClass");
-                if (mPwdClass != null) {
-                    mPasswordStore = (IPasswordStore) Class.forName(mPwdClass)
-                            .newInstance();
-                    mPasswordStore.init(mPwdPath);
-                    debugWrite("JSSSocketFactory init - password reader initialized\n");
-                }
-            } catch (Exception e) {
-                debugWrite("JSSSocketFactory init - Exception caught: "
-                        + e.toString() + "\n");
-                if (debugFile != null)
-                    debugFile.close();
-                throw new IOException(
-                        "JSSSocketFactory: no passwordFilePath defined");
-            }
+            initializePasswordStore();
 
-            String certDir = (String) endpoint.getAttribute("certdbDir");
+            CryptoManager manager = getCryptoManager();
 
-            CryptoManager.InitializationValues vals = new CryptoManager.InitializationValues(
-                    certDir, "", "", "secmod.db");
-
-            vals.removeSunProvider = false;
-            vals.installJSSProvider = true;
-            try {
-                CryptoManager.initialize(vals);
-            } catch (AlreadyInitializedException ee) {
-                // do nothing
-            }
-            CryptoManager manager = CryptoManager.getInstance();
-
             // JSSSocketFactory init - handle crypto tokens
             debugWrite("JSSSocketFactory init - about to handle crypto unit logins\n");
 
-            if (mPasswordStore != null) {
-                Enumeration<?> en = mPasswordStore.getTags();
-                while (en.hasMoreElements()) {
-                    String pwd = "";
-                    Password pw = null;
-                    String tokenName = "";
-                    String st = (String) en.nextElement();
-                    debugWrite("JSSSocketFactory init - tag name=" + st + "\n");
-                    pwd = mPasswordStore.getPassword(st);
+            //log into tokens
+            Enumeration<String> tags = mPasswordStore.getTags();
+            while (tags.hasMoreElements()) {
+                String tag = tags.nextElement();
+                if (tag.equals("internal") || (tag.startsWith("hardware-"))) {
+                    debugWrite("JSSSocketFactory init - tag name=" + tag + "\n");
+                    logIntoToken(manager, tag);
+                }
+            }
+            debugWrite("JSSSocketFactory init - tokens initialized/logged in\n");
 
-                    if (pwd != null) {
-                        debugWrite("JSSSocketFactory init - got password\n");
-                        pw = new Password(pwd.toCharArray());
-                    } else {
-                        debugWrite("JSSSocketFactory init - no pwd found in password.conf\n");
-                        continue;
-                    }
-
-                    CryptoToken token = null;
-                    if (st.equals("internal")) {
-                        debugWrite("JSSSocketFactory init - got internal software token\n");
-                        token = manager.getInternalKeyStorageToken();
-                    } else if (st.startsWith("hardware-")) {
-                        debugWrite("JSSSocketFactory init - got hardware\n");
-
-                        tokenName = st.substring(9);
-                        debugWrite("JSSSocketFactory init - tokenName="
-                                + tokenName + "\n");
-
-                        // find the hsm and log in
-                        token = manager.getTokenByName(tokenName);
-                    } else {
-                        // non-token entries
-                    }
-                    if (token != null) {
-                        if (!token.isLoggedIn()) {
-                            debugWrite("JSSSocketFactory init -not logged in...about to log in\n");
-                            token.login(pw);
-                        } else {
-                            debugWrite("JSSSocketFactory init - already logged in\n");
-                        }
-                    }
-                } // while
-                debugWrite("JSSSocketFactory init - tokens initialized/logged in\n");
-            } else {
-                debugWrite("JSSSocketFactory init - no login done\n");
-            } // mPasswordStore not null
-
             // MUST look for "clientauth" (ALL lowercase) since "clientAuth"
             // (camel case) has already been processed by Tomcat 7
             String clientAuthStr = (String) endpoint.getAttribute("clientauth");
@@ -651,8 +590,6 @@
             } catch (Exception e) {
                 debugWrite("JSSSocketFactory init - Exception caught: "
                         + e.toString() + "\n");
-                if (debugFile != null)
-                    debugFile.close();
                 throw new IOException(
                         "JSSSocketFactory: no serverCertNickFile defined");
             }
@@ -838,8 +775,6 @@
                     + ex.toString() + "\n");
             System.err.println("JSSSocketFactory init - exception thrown:"
                     + ex.toString() + "\n");
-            if (debugFile != null)
-                debugFile.close();
             // The idea is, if admin take the trouble to configure the
             // ocsp cache, and made a mistake, we want to make server
             // unavailable until they get it right
@@ -846,11 +781,106 @@
             if ((ex instanceof java.security.GeneralSecurityException)
                     || (ex instanceof java.lang.NumberFormatException))
                 throw new IOException(ex.toString());
+        } finally {
+            if (debugFile != null)
+                debugFile.close();
         }
-        if (debugFile != null)
-            debugFile.close();
     }
 
+    private CryptoToken getToken(String tag, CryptoManager manager) throws IOException, NoSuchTokenException {
+        CryptoToken token = null;
+        if (tag.equals("internal")) {
+            debugWrite("JSSSocketFactory init - got internal software token\n");
+            token = manager.getInternalKeyStorageToken();
+        } else if (tag.startsWith("hardware-")) {
+            debugWrite("JSSSocketFactory init - got hardware\n");
+
+            String tokenName = tag.substring(9);
+            debugWrite("JSSSocketFactory init - tokenName=" + tokenName + "\n");
+
+            // find the hsm and log in
+            token = manager.getTokenByName(tokenName);
+        } else {
+            // non-token password entry
+        }
+        return token;
+    }
+
+
+    private void initializePasswordStore() throws InstantiationException, IllegalAccessException,
+            ClassNotFoundException, IOException {
+        // get password store
+        mPwdClass = (String) endpoint.getAttribute("passwordClass");
+        if (mPwdClass != null) {
+            mPasswordStore = (IPasswordStore) Class.forName(mPwdClass).newInstance();
+            debugWrite("JSSSocketFactory init - password reader initialized\n");
+        } else {
+            throw new IOException("Misconfiguration: passwordClass is not defined");
+        }
+
+        // initialize the password store
+        mPwdPath = (String) endpoint.getAttribute("passwordFile");
+        String confFile = (String) endpoint.getAttribute("configFile");
+        mPasswordStore.init(mPwdPath, confFile);
+    }
+
+    private CryptoManager getCryptoManager() throws KeyDatabaseException, CertDatabaseException,
+            GeneralSecurityException, NotInitializedException {
+        String certDir = (String) endpoint.getAttribute("certdbDir");
+        CryptoManager.InitializationValues vals = new CryptoManager.InitializationValues(
+                certDir, "", "", "secmod.db");
+
+        vals.removeSunProvider = false;
+        vals.installJSSProvider = true;
+        try {
+            CryptoManager.initialize(vals);
+        } catch (AlreadyInitializedException ee) {
+            // do nothing
+        }
+        CryptoManager manager = CryptoManager.getInstance();
+        return manager;
+    }
+
+    private void logIntoToken(CryptoManager manager, String tag) throws IOException,
+            TokenException {
+        String pwd;
+        Password pw = null;
+        int iteration = 0;
+
+        CryptoToken token = null;
+        try {
+            token = getToken(tag, manager);
+        } catch (NoSuchTokenException e) {
+            debugWrite("token for " + tag + " not found by CryptoManager. Not logging in.");
+            return;
+        }
+
+        do {
+            debugWrite("JSSSocketFactory init - iteration=" + iteration + "\n");
+            pwd = mPasswordStore.getPassword(tag, iteration);
+            if (pwd == null) {
+                debugWrite("JSSSocketFactory init - no pwd gotten\n");
+                return;
+            }
+
+            pw = new Password(pwd.toCharArray());
+
+            if (!token.isLoggedIn()) {
+                debugWrite("JSSSocketFactory init -not logged in...about to log in\n");
+                try {
+                    token.login(pw);
+                    break;
+                } catch (IncorrectPasswordException e) {
+                    debugWrite("Incorrect password received");
+                    iteration ++;
+                }
+            } else {
+                debugWrite("JSSSocketFactory init - already logged in\n");
+                break;
+            }
+        } while (iteration < 3);
+    }
+
     public Socket acceptSocket(ServerSocket socket) throws IOException {
         SSLSocket asock = null;
         try {
@@ -892,10 +922,10 @@
         if (!initialized)
             init();
         SSLServerSocket socket = null;
-        socket = (SSLServerSocket) (new SSLServerSocket(port, backlog,
+        socket = (new SSLServerSocket(port, backlog,
                 ifAddress, null, reuseAddr));
         initializeSocket(socket);
-        return (ServerSocket) socket;
+        return socket;
     }
 
     private void initializeSocket(SSLServerSocket s) {
Index: src/org/apache/tomcat/util/net/jss/NuxwdogPasswordStore.java
===================================================================
--- src/org/apache/tomcat/util/net/jss/NuxwdogPasswordStore.java	(revision 0)
+++ src/org/apache/tomcat/util/net/jss/NuxwdogPasswordStore.java	(working copy)
@@ -0,0 +1,85 @@
+package org.apache.tomcat.util.net.jss;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import org.apache.commons.lang.StringUtils;
+
+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 ArrayList<String> tags = null;
+
+    private final String PROMPT_PREFIX = "Please provide the password for ";
+
+    @Override
+    public void init(String pwdPath, String confFile) throws IOException {
+        // confirm that process was started by nuxwdog
+        String wdPipeName = System.getenv("WD_PIPE_NAME");
+        if (StringUtils.isEmpty(wdPipeName)) {
+            throw new IOException(
+                "Unable to init NuxwdogPasswordStore.  Process not started by nuxwdog");
+        }
+
+        if (confFile == null) {
+            throw new IOException("confFile must be defined when NuxwdogPasswordStore is used");
+        }
+
+        tags = new ArrayList<String>();
+        populateTags(confFile);
+
+        pwCache = new Hashtable<String, String>();
+    }
+
+    private void populateTags(String confFile) throws IOException {
+        Properties props = new Properties();
+        InputStream in = new FileInputStream(confFile);
+        props.load(in);
+
+        tags.add("internal");
+
+        String tokenList = props.getProperty("cms.tokenList");
+        if (StringUtils.isNotEmpty(tokenList)) {
+            for (String token: StringUtils.split(tokenList,',')) {
+                tags.add("hardware-" + token);
+            }
+        }
+    }
+
+    @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() {
+        return  Collections.enumeration(tags);
+    }
+
+    @Override
+    public Object putPassword(String tag, String password) {
+        return pwCache.put(tag, password);
+    }
+
+    @Override
+    public void commit() throws IOException, ClassCastException, NullPointerException {
+        // Nothing required here
+    }
+
+}
Index: src/org/apache/tomcat/util/net/jss/PlainPasswordFile.java
===================================================================
--- src/org/apache/tomcat/util/net/jss/PlainPasswordFile.java	(revision 294)
+++ src/org/apache/tomcat/util/net/jss/PlainPasswordFile.java	(working copy)
@@ -12,7 +12,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Copyright (C) 2007 Red Hat, Inc.
  * All rights reserved.
  * END COPYRIGHT BLOCK */
@@ -33,7 +33,7 @@
     public PlainPasswordFile() {
     }
 
-    public void init(String pwdPath) throws IOException {
+    public void init(String pwdPath, String confFile) throws IOException {
         mPwdStore = new Properties();
         // initialize mPwdStore
         mPwdPath = pwdPath;
@@ -42,8 +42,8 @@
         mPwdStore.load(file);
     }
 
-    public String getPassword(String tag) {
-        return (String) mPwdStore.getProperty(tag);
+    public String getPassword(String tag, int iteration) {
+        return mPwdStore.getProperty(tag);
     }
 
     // return an array of String-based tag
