URL: https://github.com/freeipa/freeipa/pull/446
Author: stlaz
 Title: #446: No NSS database passwords in ipa-client-install
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/446/head:pr446
git checkout pr446
From 61a865d14049acb5c17fac8033f173c54cbdfa84 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Tue, 6 Dec 2016 09:14:54 +0100
Subject: [PATCH 1/3] Add password to certutil calls in NSSDatabase

NSSDatabases should have the ability to run certutil with
a password if location of the file containing it is known.

https://fedorahosted.org/freeipa/ticket/5695
---
 install/tools/ipa-replica-conncheck         | 11 +++--------
 ipaclient/install/client.py                 | 14 ++++++--------
 ipapython/certdb.py                         | 19 +++++++++++++------
 ipaserver/install/cainstance.py             | 23 +++++++++++++++++++++++
 ipaserver/install/certs.py                  |  2 +-
 ipaserver/install/installutils.py           | 18 ++++++++----------
 ipaserver/install/ipa_cacert_manage.py      |  8 ++++----
 ipaserver/install/ipa_server_certinstall.py |  7 +++----
 ipaserver/install/kra.py                    |  7 ++++---
 ipaserver/install/server/upgrade.py         |  5 +++++
 10 files changed, 70 insertions(+), 44 deletions(-)

diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
index 04e23de..896fddc 100755
--- a/install/tools/ipa-replica-conncheck
+++ b/install/tools/ipa-replica-conncheck
@@ -542,12 +542,9 @@ def main():
 
                 with certdb.NSSDatabase(nss_dir) as nss_db:
                     if options.ca_cert_file:
-                        nss_dir = nss_db.secdir
-
-                        password = ipautil.ipa_generate_password()
-                        password_file = ipautil.write_tmp_file(password)
-                        nss_db.create_db(password_file.name)
-
+                        nss_db.create_passwd_file(
+                            ipautil.ipa_generate_password())
+                        nss_db.create_db()
                         ca_certs = x509.load_certificate_list_from_file(
                             options.ca_cert_file)
                         for ca_cert in ca_certs:
@@ -555,8 +552,6 @@ def main():
                                 serialization.Encoding.DER)
                             nss_db.add_cert(
                                 data, str(DN(ca_cert.subject)), 'C,,')
-                    else:
-                        nss_dir = None
 
                     api.bootstrap(context='client',
                                   confdir=paths.ETC_IPA,
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index 2b01b0d..79686b6 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -2284,18 +2284,16 @@ def install_check(options):
 
 def create_ipa_nssdb():
     db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
-    pwdfile = os.path.join(db.secdir, 'pwdfile.txt')
 
-    ipautil.backup_file(pwdfile)
+    ipautil.backup_file(db.password_file)
     ipautil.backup_file(os.path.join(db.secdir, 'cert8.db'))
     ipautil.backup_file(os.path.join(db.secdir, 'key3.db'))
     ipautil.backup_file(os.path.join(db.secdir, 'secmod.db'))
 
-    with open(pwdfile, 'w') as f:
-        f.write(ipautil.ipa_generate_password())
-    os.chmod(pwdfile, 0o600)
+    db.create_passwd_file(ipautil.ipa_generate_password())
+    os.chmod(db.password_file, 0o600)
 
-    db.create_db(pwdfile)
+    db.create_db()
     os.chmod(os.path.join(db.secdir, 'cert8.db'), 0o644)
     os.chmod(os.path.join(db.secdir, 'key3.db'), 0o644)
     os.chmod(os.path.join(db.secdir, 'secmod.db'), 0o644)
@@ -2667,8 +2665,8 @@ def _install(options):
             for cert in ca_certs
         ]
         try:
-            pwd_file = ipautil.write_tmp_file(ipautil.ipa_generate_password())
-            tmp_db.create_db(pwd_file.name)
+            tmp_db.create_passwd_file(ipautil.ipa_generate_password())
+            tmp_db.create_db()
 
             for i, cert in enumerate(ca_certs):
                 tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1), 'C,,')
diff --git a/ipapython/certdb.py b/ipapython/certdb.py
index 9481326..597aa71 100644
--- a/ipapython/certdb.py
+++ b/ipapython/certdb.py
@@ -83,13 +83,17 @@ class NSSDatabase(object):
     # got too tied to IPA server details, killing reusability.
     # BaseCertDB is a class that knows nothing about IPA.
     # Generic NSS DB code should be moved here.
-    def __init__(self, nssdir=None):
+    def __init__(self, nssdir=None, password_file=None):
         if nssdir is None:
             self.secdir = tempfile.mkdtemp()
             self._is_temporary = True
         else:
             self.secdir = nssdir
             self._is_temporary = False
+        if password_file is None:
+            self.password_file = os.path.join(self.secdir, 'pwdfile.txt')
+        else:
+            self.password_file = password_file
 
     def close(self):
         if self._is_temporary:
@@ -104,14 +108,17 @@ def __exit__(self, type, value, tb):
     def run_certutil(self, args, stdin=None, **kwargs):
         new_args = [CERTUTIL, "-d", self.secdir]
         new_args = new_args + args
+        new_args.extend(['-f', self.password_file])
         return ipautil.run(new_args, stdin, **kwargs)
 
-    def create_db(self, password_filename):
-        """Create cert DB
+    def create_passwd_file(self, passwd):
+        with open(self.password_file, 'w') as psswdfile:
+            psswdfile.write(passwd)
 
-        :param password_filename: Name of file containing the database password
-        """
-        self.run_certutil(["-N", "-f", password_filename])
+    def create_db(self):
+        """Create cert DB"""
+        assert os.path.exists(self.password_file)
+        self.run_certutil(["-N"])
 
     def list_certs(self):
         """Return nicknames and cert flags for all certs in the database
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index d869641..5b386d5 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -394,6 +394,8 @@ def configure_instance(self, host_name, dm_password, admin_password,
                 self.step("creating installation admin user", self.setup_admin)
             self.step("configuring certificate server instance",
                       self.__spawn_instance)
+            self.step("exporting Dogtag certificate store pin",
+                      self.create_certstore_passwdfile)
             self.step("stopping certificate server instance to update CS.cfg", self.stop_instance)
             self.step("backing up CS.cfg", self.backup_config)
             self.step("disabling nonces", self.__disable_nonce)
@@ -627,6 +629,27 @@ def backup_config(self):
         except Exception as e:
             root_logger.warning("Failed to backup CS.cfg: %s", e)
 
+    def create_certstore_passwdfile(self):
+        """
+        This method creates a 'pwdfile.txt' file in the Dogtag certificate
+        store so that this file can be assumed and used for NSSDatabase/CertDB
+        operations in 'certutil' calls.
+        """
+        passwd = None
+        token = 'internal'
+        with open(paths.PKI_TOMCAT_PASSWORD_CONF, 'r') as f:
+            for line in f:
+                (tok, pin) = line.split('=', 1)
+                if token == tok:
+                    passwd = pin.strip()
+                    break
+            else:
+                raise RuntimeError(
+                    "The password to the 'internal' token of the Dogtag "
+                    "certificate store was not found.")
+        db = certs.CertDB(self.realm, nssdir=paths.PKI_TOMCAT_ALIAS_DIR)
+        db.create_passwd_file(passwd)
+
     def __update_topology(self):
         ld = ldapupdate.LDAPUpdate(ldapi=True, sub_dict={
             'SUFFIX': api.env.basedn,
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index d484d8a..282e3be 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -197,7 +197,7 @@ def create_certdbs(self):
         ipautil.backup_file(self.certdb_fname)
         ipautil.backup_file(self.keydb_fname)
         ipautil.backup_file(self.secmod_fname)
-        self.nssdb.create_db(self.passwd_fname)
+        self.nssdb.create_db()
         self.set_perms(self.passwd_fname, write=True)
 
     def list_certs(self):
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index ab2596c..c1851b6 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -1003,19 +1003,18 @@ def load_pkcs12(cert_files, key_password, key_nickname, ca_cert_files,
         the CA certificate of the CA that issued the server certificate
     """
     with certs.NSSDatabase() as nssdb:
-        db_password = ipautil.ipa_generate_password()
-        db_pwdfile = ipautil.write_tmp_file(db_password)
-        nssdb.create_db(db_pwdfile.name)
+        nssdb.create_passwd_file(ipautil.ipa_generate_password())
+        nssdb.create_db()
 
         try:
-            nssdb.import_files(cert_files, db_pwdfile.name,
+            nssdb.import_files(cert_files, nssdb.password_file,
                                True, key_password, key_nickname)
         except RuntimeError as e:
             raise ScriptError(str(e))
 
         if ca_cert_files:
             try:
-                nssdb.import_files(ca_cert_files, db_pwdfile.name)
+                nssdb.import_files(ca_cert_files, nssdb.password_file)
             except RuntimeError as e:
                 raise ScriptError(str(e))
 
@@ -1068,7 +1067,7 @@ def load_pkcs12(cert_files, key_password, key_nickname, ca_cert_files,
             '-o', out_file.name,
             '-n', key_nickname,
             '-d', nssdb.secdir,
-            '-k', db_pwdfile.name,
+            '-k', nssdb.password_file,
             '-w', out_pwdfile.name,
         ]
         ipautil.run(args)
@@ -1143,12 +1142,11 @@ def load_external_cert(files, ca_subject):
         with the external CA certificate chain
     """
     with certs.NSSDatabase() as nssdb:
-        db_password = ipautil.ipa_generate_password()
-        db_pwdfile = ipautil.write_tmp_file(db_password)
-        nssdb.create_db(db_pwdfile.name)
+        nssdb.create_passwd_file(ipautil.ipa_generate_password)
+        nssdb.create_db()
 
         try:
-            nssdb.import_files(files, db_pwdfile.name)
+            nssdb.import_files(files, nssdb.password_file)
         except RuntimeError as e:
             raise ScriptError(str(e))
 
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index 1d1ae2f..7c819c4 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -230,8 +230,8 @@ def renew_external_step_2(self, ca, old_cert_der):
                 "troubleshooting guide)")
 
         with certs.NSSDatabase() as tmpdb:
-            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
-            tmpdb.create_db(pw.name)
+            tmpdb.create_passwd_file(ipautil.ipa_generate_password())
+            tmpdb.create_db()
             tmpdb.add_cert(old_cert_der, 'IPA CA', 'C,,')
 
             try:
@@ -330,8 +330,8 @@ def install(self):
                                               False)
 
         with certs.NSSDatabase() as tmpdb:
-            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
-            tmpdb.create_db(pw.name)
+            tmpdb.create_passwd_file(ipautil.ipa_generate_password())
+            tmpdb.create_db()
             tmpdb.add_cert(cert, nickname, 'C,,')
             for ca_cert, ca_nickname, ca_trust_flags in ca_certs:
                 tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags)
diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
index d07c7de..6a76b2d 100644
--- a/ipaserver/install/ipa_server_certinstall.py
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -164,14 +164,13 @@ def install_http_cert(self):
     def check_chain(self, pkcs12_filename, pkcs12_pin, nssdb):
         # create a temp nssdb
         with NSSDatabase() as tempnssdb:
-            db_password = ipautil.ipa_generate_password()
-            db_pwdfile = ipautil.write_tmp_file(db_password)
-            tempnssdb.create_db(db_pwdfile.name)
+            tempnssdb.create_passwd_file(ipautil.ipa_generate_password())
+            tempnssdb.create_db()
 
             # import the PKCS12 file, then delete all CA certificates
             # this leaves only the server certs in the temp db
             tempnssdb.import_pkcs12(
-                pkcs12_filename, db_pwdfile.name, pkcs12_pin)
+                pkcs12_filename, tempnssdb.password_filename, pkcs12_pin)
             for nickname, flags in tempnssdb.list_certs():
                 if 'u' not in flags:
                     while tempnssdb.has_nickname(nickname):
diff --git a/ipaserver/install/kra.py b/ipaserver/install/kra.py
index 0d1ed8e..649eb47 100644
--- a/ipaserver/install/kra.py
+++ b/ipaserver/install/kra.py
@@ -54,9 +54,10 @@ def install_check(api, replica_config, options):
             return
 
         with certdb.NSSDatabase() as tmpdb:
-            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
-            tmpdb.create_db(pw.name)
-            tmpdb.import_pkcs12(replica_config.dir + "/cacert.p12", pw.name,
+            tmpdb.create_passwd_file(ipautil.ipa_generate_password())
+            tmpdb.create_db()
+            tmpdb.import_pkcs12(replica_config.dir + "/cacert.p12",
+                                tmpdb.password_file,
                                 replica_config.dirman_password)
             kra_cert_nicknames = [
                 "storageCert cert-pki-kra", "transportCert cert-pki-kra",
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 0e034ef..4da7ddc 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1521,6 +1521,11 @@ def upgrade_configuration():
             api.env.realm, certs.NSS_DIR, host_name=api.env.host)
     ca_running = ca.is_running()
 
+    # create passswd.txt file in PKI_TOMCAT_ALIAS_DIR if it does not exist
+    # this file will be required on most actions over this NSS DB in FIPS
+    if not os.path.exists(paths.PKI_TOMCAT_ALIAS_DIR, 'passwd.txt'):
+        ca.create_certstore_passwdfile()
+
     with installutils.stopped_service('pki-tomcatd', 'pki-tomcat'):
         # Dogtag must be stopped to be able to backup CS.cfg config
         ca.backup_config()

From 47dfd057b6634db5fb7e43c2c77a5e3258231e6d Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Fri, 6 Jan 2017 14:19:12 +0100
Subject: [PATCH 2/3] custodiainstance: don't use IPA-specific CertDB

Replaced CertDB with NSSDatabase. CertDB expects the password
to be stored in nss_dir/passwd.txt but custodia creates its
temporary NSS database with a different password file.
---
 ipaserver/install/custodiainstance.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py
index a0bb399..31c02a1 100644
--- a/ipaserver/install/custodiainstance.py
+++ b/ipaserver/install/custodiainstance.py
@@ -2,12 +2,12 @@
 
 from ipaserver.secrets.kem import IPAKEMKeys
 from ipaserver.secrets.client import CustodiaClient
-from ipaserver.install.certs import CertDB
 from ipaplatform.paths import paths
 from ipaplatform.constants import constants
 from ipaserver.install.service import SimpleServiceInstance
 from ipapython import ipautil
 from ipapython.ipa_log_manager import root_logger
+from ipapython.certdb import NSSDatabase
 from ipaserver.install import installutils
 from ipaserver.install import ldapupdate
 from ipaserver.install import sysupgrade
@@ -159,7 +159,7 @@ def __get_keys(self, ca_host, cacerts_file, cacerts_pwd, data):
                              '-w', pk12pwfile])
 
             # Add CA certificates
-            tmpdb = CertDB(self.realm, nssdir=tmpnssdir)
+            tmpdb = NSSDatabase(tmpnssdir, password_file=nsspwfile)
             self.suffix = ipautil.realm_to_suffix(self.realm)
             self.import_ca_certs(tmpdb, True)
 

From ca9a33b170913451d9a666263ca6729033c8e355 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Wed, 8 Feb 2017 16:03:05 +0100
Subject: [PATCH 3/3] Don't prompt for NSS database psswd during client-install

In FIPS, the client-installation prompts for NSS database password
when it tries to add a certificate to this database. Since
NSSDatabase now accepts password_filename to grab the password from,
use this instead.

https://fedorahosted.org/freeipa/ticket/5695
---
 ipaserver/install/certs.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 282e3be..bcf59f3 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -83,8 +83,6 @@ class CertDB(object):
     def __init__(
             self, realm, nssdir=NSS_DIR, fstore=None, host_name=None,
             subject_base=None, ca_subject=None):
-        self.nssdb = NSSDatabase(nssdir)
-
         self.secdir = nssdir
         self.realm = realm
 
@@ -97,6 +95,9 @@ def __init__(
         self.pk12_fname = self.secdir + "/cacert.p12"
         self.pin_fname = self.secdir + "/pin.txt"
         self.pwd_conf = paths.HTTPD_PASSWORD_CONF
+        self.nssdb = NSSDatabase(
+            self.secdir, password_file=self.passwd_fname)
+
         self.reqdir = None
         self.certreq_fname = None
         self.certder_fname = None
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to