fef02c
From b3512bae94edc33448466cae6f2716a5527f9eed Mon Sep 17 00:00:00 2001
fef02c
From: Florence Blanc-Renaud <flo@redhat.com>
fef02c
Date: Thu, 1 Sep 2016 13:56:24 +0200
fef02c
Subject: [PATCH] Add cert checks in ipa-server-certinstall
fef02c
fef02c
When ipa-server-certinstall is called to install a new server certificate,
fef02c
the prerequisite is that the certificate issuer must be already known by IPA.
fef02c
This fix adds new checks to make sure that the tool exits before
fef02c
modifying the target NSS database if it is not the case.
fef02c
The fix consists in creating a temp NSS database with the CA certs from the
fef02c
target NSS database + the new server cert and checking the new server cert
fef02c
validity.
fef02c
fef02c
https://fedorahosted.org/freeipa/ticket/6263
fef02c
fef02c
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
fef02c
---
fef02c
 ipaserver/install/ipa_server_certinstall.py | 40 +++++++++++++++++++++++++++--
fef02c
 1 file changed, 38 insertions(+), 2 deletions(-)
fef02c
fef02c
diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
fef02c
index 0a8fb214a232e60a89b6c06940b928f97c007b93..7bc39e356ef3082ab229fa66eaeebba85eaa2802 100644
fef02c
--- a/ipaserver/install/ipa_server_certinstall.py
fef02c
+++ b/ipaserver/install/ipa_server_certinstall.py
fef02c
@@ -25,8 +25,8 @@ import optparse
fef02c
 
fef02c
 from ipaplatform.constants import constants
fef02c
 from ipaplatform.paths import paths
fef02c
-from ipapython import admintool
fef02c
-from ipapython.certdb import get_ca_nickname
fef02c
+from ipapython import admintool, ipautil
fef02c
+from ipapython.certdb import get_ca_nickname, NSSDatabase
fef02c
 from ipapython.dn import DN
fef02c
 from ipalib import api, errors
fef02c
 from ipalib.constants import CACERT
fef02c
@@ -157,6 +157,38 @@ class ServerCertInstall(admintool.AdminTool):
fef02c
         os.chown(os.path.join(dirname, 'key3.db'), 0, pent.pw_gid)
fef02c
         os.chown(os.path.join(dirname, 'secmod.db'), 0, pent.pw_gid)
fef02c
 
fef02c
+    def check_chain(self, pkcs12_filename, pkcs12_pin, nssdb):
fef02c
+        # create a temp nssdb
fef02c
+        with NSSDatabase() as tempnssdb:
fef02c
+            db_password = ipautil.ipa_generate_password()
fef02c
+            db_pwdfile = ipautil.write_tmp_file(db_password)
fef02c
+            tempnssdb.create_db(db_pwdfile.name)
fef02c
+
fef02c
+            # import the PKCS12 file, then delete all CA certificates
fef02c
+            # this leaves only the server certs in the temp db
fef02c
+            tempnssdb.import_pkcs12(
fef02c
+                pkcs12_filename, db_pwdfile.name, pkcs12_pin)
fef02c
+            for nickname, flags in tempnssdb.list_certs():
fef02c
+                if 'u' not in flags:
fef02c
+                    while tempnssdb.has_nickname(nickname):
fef02c
+                        tempnssdb.delete_cert(nickname)
fef02c
+
fef02c
+            # import all the CA certs from nssdb into the temp db
fef02c
+            for nickname, flags in nssdb.list_certs():
fef02c
+                if 'u' not in flags:
fef02c
+                    cert = nssdb.get_cert_from_db(nickname)
fef02c
+                    tempnssdb.add_cert(cert, nickname, flags)
fef02c
+
fef02c
+            # now get the server certs from tempnssdb and check their validity
fef02c
+            try:
fef02c
+                for nick, flags in tempnssdb.find_server_certs():
fef02c
+                    tempnssdb.verify_server_cert_validity(nick, api.env.host)
fef02c
+            except ValueError as e:
fef02c
+                raise admintool.ScriptError(
fef02c
+                    "Peer's certificate issuer is not trusted (%s). "
fef02c
+                    "Please run ipa-cacert-manage install and ipa-certupdate "
fef02c
+                    "to install the CA certificate." % str(e))
fef02c
+
fef02c
     def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command):
fef02c
         pkcs12_file, pin, ca_cert = installutils.load_pkcs12(
fef02c
             cert_files=self.args,
fef02c
@@ -167,6 +199,10 @@ class ServerCertInstall(admintool.AdminTool):
fef02c
 
fef02c
         dirname = os.path.normpath(dirname)
fef02c
         cdb = certs.CertDB(api.env.realm, nssdir=dirname)
fef02c
+
fef02c
+        # Check that the ca_cert is known and trusted
fef02c
+        self.check_chain(pkcs12_file.name, pin, cdb)
fef02c
+
fef02c
         try:
fef02c
             ca_enabled = api.Command.ca_is_enabled()['result']
fef02c
             if ca_enabled:
fef02c
-- 
fef02c
2.10.2
fef02c