summaryrefslogtreecommitdiffstats
path: root/ipaplatform
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2014-06-12 17:20:19 +0200
committerPetr Viktorin <pviktori@redhat.com>2014-07-30 16:04:21 +0200
commit55d3bab57b83a32e8c0976902deea80236f387e7 (patch)
tree7ba6e59743fb8d38f2429eba30b45a320a68a344 /ipaplatform
parent24932b2d91d3a32bc881d076562f9fe483a3d44e (diff)
downloadfreeipa-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.py2
-rw-r--r--ipaplatform/base/tasks.py10
-rw-r--r--ipaplatform/fedora/tasks.py100
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):