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 5f074ff8bced43ef88dc892baa8946ee21ec085a 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                 | 23 ++++++++++++-----------
 ipapython/certdb.py                         | 19 +++++++++++++------
 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 ++++---
 8 files changed, 48 insertions(+), 47 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 aa3449c..abb5e1a 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -2288,26 +2288,26 @@ def install_check(options):
 
 
 def create_ipa_nssdb():
-    db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
-    pwdfile = os.path.join(db.secdir, 'pwdfile.txt')
+    db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR,
+                            os.path.join(paths.IPA_NSSDB_DIR, '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)
 
 
 def update_ipa_nssdb():
-    ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
+    ipa_db = certdb.NSSDatabase(
+        paths.IPA_NSSDB_DIR, os.path.join(paths.IPA_NSSDB_DIR, 'pwdfile.txt'))
     sys_db = certdb.NSSDatabase(paths.NSS_DB_DIR)
 
     if not os.path.exists(os.path.join(ipa_db.secdir, 'cert8.db')):
@@ -2672,8 +2672,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,,')
@@ -3031,7 +3031,8 @@ def uninstall(options):
     if hostname is None:
         hostname = socket.getfqdn()
 
-    ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
+    ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR,
+                                os.path.join('pwdfile.txt'))
     sys_db = certdb.NSSDatabase(paths.NSS_DB_DIR)
 
     cmonger = services.knownservices.certmonger
diff --git a/ipapython/certdb.py b/ipapython/certdb.py
index 9481326..88fbcbb 100644
--- a/ipapython/certdb.py
+++ b/ipapython/certdb.py
@@ -83,13 +83,14 @@ 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
+        self.password_file = password_file
 
     def close(self):
         if self._is_temporary:
@@ -104,14 +105,20 @@ 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
+        if self.password_file is not None:
+            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):
+        if self.password_file is None:
+            self.password_file = os.path.join(self.secdir, 'passwd.txt')
+        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/certs.py b/ipaserver/install/certs.py
index 80918d4..7528e83 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -199,7 +199,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",

From ddbf12a2512485dbec5bee21a79395e5b6837fbc 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 5d7079fd93aed30e0bf1e707f0b37bdd732778c3 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 7528e83..e29fda2 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