From 0669ef8f00c1d558fd46aac725694aa385d5b42b Mon Sep 17 00:00:00 2001
From: Matthew Harmsen <mharmsen@redhat.com>
Date: Mon, 15 May 2017 20:16:53 -0600
Subject: [PATCH] Added FIPS class to pkispawn

Bugzilla Bug #1450143 - CA installation with HSM in FIPS mode fails
dogtagpki Pagure Issue #2684 - CA installation with HSM in FIPS mode fails
---
 .../python/pki/server/deployment/__init__.py       |  2 ++
 .../python/pki/server/deployment/pkihelper.py      | 41 ++++++++++++++++++++++
 .../python/pki/server/deployment/pkimessages.py    |  4 +++
 .../server/deployment/scriptlets/finalization.py   |  8 +++--
 base/server/sbin/pkispawn                          | 10 ++++++
 5 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py
index 3d719de..709fe70 100644
--- a/base/server/python/pki/server/deployment/__init__.py
+++ b/base/server/python/pki/server/deployment/__init__.py
@@ -55,6 +55,7 @@ class PKIDeployer:
         self.symlink = None
         self.war = None
         self.password = None
+        self.fips = None
         self.hsm = None
         self.certutil = None
         self.modutil = None
@@ -99,6 +100,7 @@ class PKIDeployer:
         self.symlink = util.Symlink(self)
         self.war = util.War(self)
         self.password = util.Password(self)
+        self.fips = util.FIPS(self)
         self.hsm = util.HSM(self)
         self.certutil = util.Certutil(self)
         self.modutil = util.Modutil(self)
diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py
index a1345de..b973d85 100644
--- a/base/server/python/pki/server/deployment/pkihelper.py
+++ b/base/server/python/pki/server/deployment/pkihelper.py
@@ -2172,6 +2172,47 @@ class Password:
         return token_pwd
 
 
+class FIPS:
+    """PKI Deployment FIPS class"""
+
+    def __init__(self, deployer):
+        self.mdict = deployer.mdict
+
+    def is_fips_enabled(self, critical_failure=True):
+        try:
+            # Always initialize FIPS mode as NOT enabled
+            self.mdict['pki_fips_mode_enabled'] = False
+
+            # Check to see if FIPS is enabled on this system
+            command = ["sysctl", "crypto.fips_enabled", "-bn"]
+
+            # Execute this "sysctl" command.
+            with open(os.devnull, "w") as fnull:
+                output = subprocess.check_output(command, stderr=fnull,
+                                                 close_fds=True)
+                if (output != "0"):
+                    # Set FIPS mode as enabled
+                    self.mdict['pki_fips_mode_enabled'] = True
+                    config.pki_log.info(log.PKIHELPER_FIPS_MODE_IS_ENABLED,
+                                        extra=config.PKI_INDENTATION_LEVEL_3)
+                    return True
+                else:
+                    config.pki_log.info(log.PKIHELPER_FIPS_MODE_IS_NOT_ENABLED,
+                                        extra=config.PKI_INDENTATION_LEVEL_3)
+                    return False
+        except subprocess.CalledProcessError as exc:
+            config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc,
+                                 extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure:
+                raise
+        except OSError as exc:
+            config.pki_log.error(log.PKI_OSERROR_1, exc,
+                                 extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure:
+                raise
+        return False
+
+
 class HSM:
     """PKI Deployment HSM class"""
 
diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py
index c8821bb..52c8e62 100644
--- a/base/server/python/pki/server/deployment/pkimessages.py
+++ b/base/server/python/pki/server/deployment/pkimessages.py
@@ -222,6 +222,10 @@ PKIHELPER_GROUP_ADD_2 = "adding GID '%s' for group '%s' . . ."
 PKIHELPER_GROUP_ADD_DEFAULT_2 = "adding default GID '%s' for group '%s' . . ."
 PKIHELPER_GROUP_ADD_GID_KEYERROR_1 = "KeyError:  pki_gid %s"
 PKIHELPER_GROUP_ADD_KEYERROR_1 = "KeyError:  pki_group %s"
+PKIHELPER_FIPS_MODE_IS_ENABLED = "FIPS mode is enabled on this operating "\
+    "system."
+PKIHELPER_FIPS_MODE_IS_NOT_ENABLED = "FIPS mode is NOT enabled on this "\
+    "operating system."
 PKIHELPER_HSM_CLONES_MUST_SHARE_HSM_MASTER_PRIVATE_KEYS = \
     "Since clones using Hardware Security Modules (HSMs) must share their "\
     "master's private keys, the 'pki_clone_pkcs12_path' and "\
diff --git a/base/server/python/pki/server/deployment/scriptlets/finalization.py b/base/server/python/pki/server/deployment/scriptlets/finalization.py
index 75bb80e..f0caa9a 100644
--- a/base/server/python/pki/server/deployment/scriptlets/finalization.py
+++ b/base/server/python/pki/server/deployment/scriptlets/finalization.py
@@ -58,8 +58,12 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         if config.str2bool(deployer.mdict['pki_restart_configured_instance']):
             deployer.systemd.restart()
             # wait for startup
-            # (must use 'http' protocol due to potential FIPS configuration)
-            status = deployer.instance.wait_for_startup(60, False)
+            status = None
+            if deployer.fips.is_fips_enabled():
+                # must use 'http' protocol when FIPS mode is enabled
+                status = deployer.instance.wait_for_startup(60, False)
+            else:
+                status = deployer.instance.wait_for_startup(60)
             if status is None:
                 config.pki_log.error(
                     "server failed to restart",
diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index e6e337b..9394b8e 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -756,6 +756,16 @@ def print_final_install_information(mdict):
               "      is a clone." %
               (deployer.subsystem_name, mdict['pki_instance_name']))
 
+    if mdict['pki_fips_mode_enabled']:
+        print()
+        print("      This %s subsystem of the '%s' instance\n"
+              "      has FIPS mode enabled on this operating system." %
+              (deployer.subsystem_name, mdict['pki_instance_name']))
+        print()
+        print("      REMINDER:  Don't forget to update the appropriate FIPS\n"
+              "                 algorithms in server.xml in the '%s' instance."
+              % mdict['pki_instance_name'])
+
     print(log.PKI_CHECK_STATUS_MESSAGE % mdict['pki_instance_name'])
     print(log.PKI_INSTANCE_RESTART_MESSAGE % mdict['pki_instance_name'])
 
-- 
2.9.3

