From fdd2394d36cdb37c9759afea6d87c694a5789ac9 Mon Sep 17 00:00:00 2001
From: Matthew Harmsen <mharmsen@redhat.com>
Date: Tue, 21 Apr 2015 00:49:11 -0600
Subject: [PATCH] Add HSM passwords to pkispawn

- PKI TRAC Ticket #1200 - make sure pkispawn works with hsm (passwords)
---
 .../python/pki/server/deployment/pkihelper.py      | 44 ++++++++++++++++++++++
 .../python/pki/server/deployment/pkimessages.py    |  2 +
 .../deployment/scriptlets/security_databases.py    | 24 ++++++++++--
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index 5099887..7f46c1f 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -577,6 +577,15 @@ class ConfigurationFile:
                 if not self.skip_configuration and not self.standalone:
                     self.confirm_data_exists("pki_security_domain_password")
             # If required, verify existence of Token Password
+            if config.str2bool(self.mdict['pki_hsm_enable']):
+                self.confirm_data_exists("pki_hsm_libfile")
+                self.confirm_data_exists("pki_hsm_modulename")
+                self.confirm_data_exists("pki_token_name")
+                if self.mdict['pki_token_name'] == "internal":
+                    config.pki_log.error(
+                        log.PKIHELPER_UNDEFINED_HSM_TOKEN,
+                        extra=config.PKI_INDENTATION_LEVEL_2)
+                    raise Exception(log.PKIHELPER_UNDEFINED_HSM_TOKEN)
             if not self.mdict['pki_token_name'] == "internal":
                 self.confirm_data_exists("pki_token_password")
         return
@@ -2039,6 +2048,38 @@ class Password:
                 raise
         return
 
+    def create_hsm_password_conf(self, path, pin, hsm_pin,
+                                 overwrite_flag=False, critical_failure=True):
+        try:
+            if os.path.exists(path):
+                if overwrite_flag:
+                    config.pki_log.info(
+                        log.PKIHELPER_PASSWORD_CONF_1, path,
+                        extra=config.PKI_INDENTATION_LEVEL_2)
+                    # overwrite the existing 'password.conf' file
+                    with open(path, "w") as fd:
+                        fd.write(self.mdict['pki_self_signed_token'] +
+                                 "=" + str(pin) + "\n")
+                        fd.write("hardware-" +
+                                 self.mdict['pki_token_name'] +
+                                 "=" + str(hsm_pin))
+            else:
+                config.pki_log.info(log.PKIHELPER_PASSWORD_CONF_1, path,
+                                    extra=config.PKI_INDENTATION_LEVEL_2)
+                # create a new 'password.conf' file
+                with open(path, "w") as fd:
+                    fd.write(self.mdict['pki_self_signed_token'] +
+                             "=" + str(pin) + "\n")
+                    fd.write("hardware-" +
+                             self.mdict['pki_token_name'] +
+                             "=" + str(hsm_pin))
+        except OSError as exc:
+            config.pki_log.error(log.PKI_OSERROR_1, exc,
+                                 extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure:
+                raise
+        return
+
     def create_client_pkcs12_password_conf(self, path, overwrite_flag=False,
                                            critical_failure=True):
         try:
@@ -3793,6 +3834,9 @@ class ConfigClient:
 
         # Miscellaneous Configuration Information
         data.pin = self.mdict['pki_one_time_pin']
+        if config.str2bool(self.mdict['pki_hsm_enable']):
+            data.token = self.mdict['pki_token_name']
+            data.tokenPassword = self.mdict['pki_token_password']
         data.subsystemName = self.mdict['pki_subsystem_name']
         data.standAlone = self.standalone
         data.stepTwo = self.external_step_two
diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py
index a3e1b6f..9129b84 100644
--- a/base/server/python/pki/server/deployment/pkimessages.py
+++ b/base/server/python/pki/server/deployment/pkimessages.py
@@ -304,6 +304,8 @@ PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2 = \
     "the randomly generated client pin MUST be used"
 PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 = \
     "A value for '%s' MUST be defined in '%s'"
+PKIHELPER_UNDEFINED_HSM_TOKEN = \
+    "A value other than 'internal' MUST be defined for 'pki_token_name'"
 PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME = "subsystem nickname not defined"
 PKIHELPER_UNDEFINED_TKS_HOST_PORT = "TKS Host or Port is undefined"
 PKIHELPER_UNDEFINED_TOKEN_PASSWD_1 = "Password for token '%s' not defined"
diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
index 16cd92d..83ecdf1 100644
--- a/base/server/python/pki/server/deployment/scriptlets/security_databases.py
+++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py
@@ -37,9 +37,15 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             return self.rv
         config.pki_log.info(log.SECURITY_DATABASES_SPAWN_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
-        deployer.password.create_password_conf(
-            deployer.mdict['pki_shared_password_conf'],
-            deployer.mdict['pki_pin'])
+        if config.str2bool(deployer.mdict['pki_hsm_enable']):
+            deployer.password.create_hsm_password_conf(
+                deployer.mdict['pki_shared_password_conf'],
+                deployer.mdict['pki_pin'],
+                deployer.mdict['pki_token_password'])
+        else:
+            deployer.password.create_password_conf(
+                deployer.mdict['pki_shared_password_conf'],
+                deployer.mdict['pki_pin'])
         # Since 'certutil' does NOT strip the 'token=' portion of
         # the 'token=password' entries, create a temporary server 'pfile'
         # which ONLY contains the 'password' for the purposes of
@@ -71,6 +77,11 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
         if len(deployer.instance.tomcat_instance_subsystems()) < 2:
             # only create a self signed cert for a new instance
+            #
+            # NOTE:  ALWAYS create the temporary sslserver certificate
+            #        in the software DB regardless of whether the
+            #        instance will utilize 'softokn' or an HSM
+            #
             rv = deployer.certutil.verify_certificate_exists(
                 deployer.mdict['pki_database_path'],
                 deployer.mdict['pki_cert_database'],
@@ -105,6 +116,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             if config.str2bool(deployer.mdict['pki_ds_secure_connection']):
                 # Check to see if a directory server CA certificate
                 # using the same nickname already exists
+                #
+                # NOTE:  ALWAYS use the software DB regardless of whether
+                #        the instance will utilize 'softokn' or an HSM
+                #
                 rv = deployer.certutil.verify_certificate_exists(
                     deployer.mdict['pki_database_path'],
                     deployer.mdict['pki_cert_database'],
@@ -120,7 +135,8 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                         deployer.mdict['pki_ds_secure_connection_ca_trustargs'],
                         deployer.mdict['pki_ds_secure_connection_ca_pem_file'],
                         password_file=deployer.mdict['pki_shared_pfile'],
-                        path=deployer.mdict['pki_database_path'])
+                        path=deployer.mdict['pki_database_path'],
+                        token=deployer.mdict['pki_self_signed_token'])
 
         # Always delete the temporary 'pfile'
         deployer.file.delete(deployer.mdict['pki_shared_pfile'])
-- 
1.8.3.1

