diff options
author | Jan Cholasta <jcholast@redhat.com> | 2014-06-12 17:20:19 +0200 |
---|---|---|
committer | Petr Viktorin <pviktori@redhat.com> | 2014-07-30 16:04:21 +0200 |
commit | 55d3bab57b83a32e8c0976902deea80236f387e7 (patch) | |
tree | 7ba6e59743fb8d38f2429eba30b45a320a68a344 /ipaplatform | |
parent | 24932b2d91d3a32bc881d076562f9fe483a3d44e (diff) | |
download | freeipa-55d3bab57b83a32e8c0976902deea80236f387e7.tar.gz freeipa-55d3bab57b83a32e8c0976902deea80236f387e7.tar.xz freeipa-55d3bab57b83a32e8c0976902deea80236f387e7.zip |
Get CA certs for system-wide store from cert store in ipa-client-install.
All of the certificates and associated key policy are now stored in
/etc/pki/ca-trust/source/ipa.p11-kit.
Part of https://fedorahosted.org/freeipa/ticket/3259
Part of https://fedorahosted.org/freeipa/ticket/3520
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Diffstat (limited to 'ipaplatform')
-rw-r--r-- | ipaplatform/base/paths.py | 2 | ||||
-rw-r--r-- | ipaplatform/base/tasks.py | 10 | ||||
-rw-r--r-- | ipaplatform/fedora/tasks.py | 100 |
3 files changed, 92 insertions, 20 deletions
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index e32a4475f..2ab06e27a 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -80,7 +80,7 @@ class BasePathNamespace(object): PAM_LDAP_CONF = "/etc/pam_ldap.conf" PASSWD = "/etc/passwd" ETC_PKI_CA_DIR = "/etc/pki-ca" - SYSTEMWIDE_CA_STORE = "/etc/pki/ca-trust/source/anchors/" + IPA_P11_KIT = "/etc/pki/ca-trust/source/ipa.p11-kit" NSS_DB_DIR = "/etc/pki/nssdb" NSSDB_CERT8_DB = "/etc/pki/nssdb/cert8.db" NSSDB_KEY3_DB = "/etc/pki/nssdb/key3.db" diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index 67c20f31d..a4ef0ded0 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -49,9 +49,9 @@ class BaseTaskNamespace(object): return - def insert_ca_cert_into_systemwide_ca_store(self, path): + def insert_ca_certs_into_systemwide_ca_store(self, ca_certs): """ - Adds the CA certificate located at 'path' to the systemwide CA store + Adds CA certificates from 'ca_certs' to the systemwide CA store (if available on the platform). Returns True if the operation succeeded, False otherwise. @@ -59,10 +59,10 @@ class BaseTaskNamespace(object): return True - def remove_ca_cert_from_systemwide_ca_store(self, path): + def remove_ca_certs_from_systemwide_ca_store(self): """ - Removes the CA certificate located at 'path' from the systemwide CA - store (if available on the platform). + Removes IPA CA certificates from the systemwide CA store + (if available on the platform). Returns True if the operation succeeded, False otherwise. """ diff --git a/ipaplatform/fedora/tasks.py b/ipaplatform/fedora/tasks.py index e7583f7bd..926c0ea66 100644 --- a/ipaplatform/fedora/tasks.py +++ b/ipaplatform/fedora/tasks.py @@ -28,12 +28,18 @@ import shutil import stat import socket import sys +import urllib +import base64 from subprocess import CalledProcessError +from nss.error import NSPRError +from pyasn1.error import PyAsn1Error from ipapython.ipa_log_manager import root_logger from ipapython import ipautil +from ipalib import x509 # FIXME: do not import from ipalib + from ipaplatform.paths import paths from ipaplatform.fedora.authconfig import FedoraAuthConfig from ipaplatform.base.tasks import BaseTaskNamespace @@ -148,19 +154,88 @@ class FedoraTaskNamespace(BaseTaskNamespace): auth_config.add_option("nostart") auth_config.execute() - def insert_ca_cert_into_systemwide_ca_store(self, cacert_path): - # Add the 'ipa-' prefix to cert name to avoid name collisions - cacert_name = os.path.basename(cacert_path) - new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE, - 'ipa-%s' % cacert_name) + def insert_ca_certs_into_systemwide_ca_store(self, ca_certs): + new_cacert_path = paths.IPA_P11_KIT + + try: + f = open(new_cacert_path, 'w') + except IOError, e: + root_logger.info("Failed to open %s: %s" % (new_cacert_path, e)) + return False + + f.write("# This file was created by IPA. Do not edit.\n" + "\n") + + has_eku = set() + for cert, nickname, trusted, ext_key_usage in ca_certs: + try: + subject = x509.get_der_subject(cert, x509.DER) + issuer = x509.get_der_issuer(cert, x509.DER) + serial_number = x509.get_der_serial_number(cert, x509.DER) + public_key_info = x509.get_der_public_key_info(cert, x509.DER) + except (NSPRError, PyAsn1Error), e: + root_logger.warning( + "Failed to decode certificate \"%s\": %s", nickname, e) + continue + + label = urllib.quote(nickname) + subject = urllib.quote(subject) + issuer = urllib.quote(issuer) + serial_number = urllib.quote(serial_number) + public_key_info = urllib.quote(public_key_info) + + cert = base64.b64encode(cert) + cert = x509.make_pem(cert) + + obj = ("[p11-kit-object-v1]\n" + "class: certificate\n" + "certificate-type: x-509\n" + "certificate-category: authority\n" + "label: \"%(label)s\"\n" + "subject: \"%(subject)s\"\n" + "issuer: \"%(issuer)s\"\n" + "serial-number: \"%(serial_number)s\"\n" + "x-public-key-info: \"%(public_key_info)s\"\n" % + dict(label=label, + subject=subject, + issuer=issuer, + serial_number=serial_number, + public_key_info=public_key_info)) + if trusted is True: + obj += "trusted: true\n" + elif trusted is False: + obj += "x-distrusted: true\n" + obj += "%s\n\n" % cert + f.write(obj) + + if ext_key_usage is not None and public_key_info not in has_eku: + if not ext_key_usage: + ext_key_usage = {x509.EKU_PLACEHOLDER} + try: + ext_key_usage = x509.encode_ext_key_usage(ext_key_usage) + except PyAsn1Error, e: + root_logger.warning( + "Failed to encode extended key usage for \"%s\": %s", + nickname, e) + continue + value = urllib.quote(ext_key_usage) + obj = ("[p11-kit-object-v1]\n" + "class: x-certificate-extension\n" + "label: \"ExtendedKeyUsage for %(label)s\"\n" + "x-public-key-info: \"%(public_key_info)s\"\n" + "object-id: 2.5.29.37\n" + "value: \"%(value)s\"\n\n" % + dict(label=label, + public_key_info=public_key_info, + value=value)) + f.write(obj) + has_eku.add(public_key_info) + + f.close() # Add the CA to the systemwide CA trust database try: - shutil.copy(cacert_path, new_cacert_path) ipautil.run([paths.UPDATE_CA_TRUST]) - except OSError, e: - root_logger.info("Failed to copy %s to %s" % (cacert_path, - new_cacert_path)) except CalledProcessError, e: root_logger.info("Failed to add CA to the systemwide " "CA trust database: %s" % str(e)) @@ -171,11 +246,8 @@ class FedoraTaskNamespace(BaseTaskNamespace): return False - def remove_ca_cert_from_systemwide_ca_store(self, cacert_path): - # Derive the certificate name in the store - cacert_name = os.path.basename(cacert_path) - new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE, - 'ipa-%s' % cacert_name) + def remove_ca_certs_from_systemwide_ca_store(self): + new_cacert_path = paths.IPA_P11_KIT # Remove CA cert from systemwide store if os.path.exists(new_cacert_path): |