|
|
0201d8 |
From 2805b17bb7f204c25ed27bea1ee4fb999ae3d9d7 Mon Sep 17 00:00:00 2001
|
|
|
0201d8 |
From: Jan Cholasta <jcholast@redhat.com>
|
|
|
0201d8 |
Date: Tue, 17 Mar 2015 09:28:47 +0000
|
|
|
0201d8 |
Subject: [PATCH] certstore: Make certificate retrieval more robust
|
|
|
0201d8 |
|
|
|
0201d8 |
https://fedorahosted.org/freeipa/ticket/4565
|
|
|
0201d8 |
|
|
|
0201d8 |
Reviewed-By: David Kupka <dkupka@redhat.com>
|
|
|
0201d8 |
---
|
|
|
0201d8 |
ipalib/certstore.py | 74 +++++++++++++++++++++++++++++++++++++----------------
|
|
|
0201d8 |
1 file changed, 52 insertions(+), 22 deletions(-)
|
|
|
0201d8 |
|
|
|
0201d8 |
diff --git a/ipalib/certstore.py b/ipalib/certstore.py
|
|
|
0201d8 |
index 8a9b41015127fcb1b2b5e01da10f0defcee18265..3a5555c95251fdf3384c7dd21cb19d2125a469f5 100644
|
|
|
0201d8 |
--- a/ipalib/certstore.py
|
|
|
0201d8 |
+++ b/ipalib/certstore.py
|
|
|
0201d8 |
@@ -239,6 +239,31 @@ def put_ca_cert(ldap, base_dn, dercert, nickname, trusted=None,
|
|
|
0201d8 |
pass
|
|
|
0201d8 |
|
|
|
0201d8 |
|
|
|
0201d8 |
+def make_compat_ca_certs(certs, realm, ipa_ca_subject):
|
|
|
0201d8 |
+ """
|
|
|
0201d8 |
+ Make CA certificates and associated key policy from DER certificates.
|
|
|
0201d8 |
+ """
|
|
|
0201d8 |
+ result = []
|
|
|
0201d8 |
+
|
|
|
0201d8 |
+ for cert in certs:
|
|
|
0201d8 |
+ subject, issuer_serial, public_key_info = _parse_cert(cert)
|
|
|
0201d8 |
+ subject = DN(subject)
|
|
|
0201d8 |
+
|
|
|
0201d8 |
+ if ipa_ca_subject is not None and subject == DN(ipa_ca_subject):
|
|
|
0201d8 |
+ nickname = get_ca_nickname(realm)
|
|
|
0201d8 |
+ ext_key_usage = {x509.EKU_SERVER_AUTH,
|
|
|
0201d8 |
+ x509.EKU_CLIENT_AUTH,
|
|
|
0201d8 |
+ x509.EKU_EMAIL_PROTECTION,
|
|
|
0201d8 |
+ x509.EKU_CODE_SIGNING}
|
|
|
0201d8 |
+ else:
|
|
|
0201d8 |
+ nickname = str(subject)
|
|
|
0201d8 |
+ ext_key_usage = {x509.EKU_SERVER_AUTH}
|
|
|
0201d8 |
+
|
|
|
0201d8 |
+ result.append((cert, nickname, True, ext_key_usage))
|
|
|
0201d8 |
+
|
|
|
0201d8 |
+ return result
|
|
|
0201d8 |
+
|
|
|
0201d8 |
+
|
|
|
0201d8 |
def get_ca_certs(ldap, base_dn, compat_realm, compat_ipa_ca,
|
|
|
0201d8 |
filter_subject=None):
|
|
|
0201d8 |
"""
|
|
|
0201d8 |
@@ -250,6 +275,7 @@ def get_ca_certs(ldap, base_dn, compat_realm, compat_ipa_ca,
|
|
|
0201d8 |
filter_subject = [str(subj).replace('\\;', '\\3b')
|
|
|
0201d8 |
for subj in filter_subject]
|
|
|
0201d8 |
|
|
|
0201d8 |
+ certs = []
|
|
|
0201d8 |
config_dn = DN(('cn', 'ipa'), ('cn', 'etc'), base_dn)
|
|
|
0201d8 |
container_dn = DN(('cn', 'certificates'), config_dn)
|
|
|
0201d8 |
try:
|
|
|
0201d8 |
@@ -265,7 +291,6 @@ def get_ca_certs(ldap, base_dn, compat_realm, compat_ipa_ca,
|
|
|
0201d8 |
'ipaPublicKey', 'ipaKeyTrust', 'ipaKeyExtUsage',
|
|
|
0201d8 |
'cACertificate;binary'])
|
|
|
0201d8 |
|
|
|
0201d8 |
- certs = []
|
|
|
0201d8 |
for entry in result:
|
|
|
0201d8 |
nickname = entry.single_value['cn']
|
|
|
0201d8 |
trusted = entry.single_value.get('ipaKeyTrust', 'unknown').lower()
|
|
|
0201d8 |
@@ -281,34 +306,39 @@ def get_ca_certs(ldap, base_dn, compat_realm, compat_ipa_ca,
|
|
|
0201d8 |
ext_key_usage.discard(x509.EKU_PLACEHOLDER)
|
|
|
0201d8 |
|
|
|
0201d8 |
for cert in entry.get('cACertificate;binary', []):
|
|
|
0201d8 |
+ try:
|
|
|
0201d8 |
+ _parse_cert(cert)
|
|
|
0201d8 |
+ except ValueError:
|
|
|
0201d8 |
+ certs = []
|
|
|
0201d8 |
+ break
|
|
|
0201d8 |
certs.append((cert, nickname, trusted, ext_key_usage))
|
|
|
0201d8 |
-
|
|
|
0201d8 |
- return certs
|
|
|
0201d8 |
except errors.NotFound:
|
|
|
0201d8 |
try:
|
|
|
0201d8 |
ldap.get_entry(container_dn, [''])
|
|
|
0201d8 |
except errors.NotFound:
|
|
|
0201d8 |
- pass
|
|
|
0201d8 |
- else:
|
|
|
0201d8 |
- return []
|
|
|
0201d8 |
-
|
|
|
0201d8 |
- # Fallback to cn=CAcert,cn=ipa,cn=etc,SUFFIX
|
|
|
0201d8 |
- dn = DN(('cn', 'CAcert'), config_dn)
|
|
|
0201d8 |
- entry = ldap.get_entry(dn, ['cACertificate;binary'])
|
|
|
0201d8 |
-
|
|
|
0201d8 |
- cert = entry.single_value['cACertificate;binary']
|
|
|
0201d8 |
- subject, issuer_serial, public_key_info = _parse_cert(cert)
|
|
|
0201d8 |
- if filter_subject is not None and subject not in filter_subject:
|
|
|
0201d8 |
- return []
|
|
|
0201d8 |
+ # Fallback to cn=CAcert,cn=ipa,cn=etc,SUFFIX
|
|
|
0201d8 |
+ dn = DN(('cn', 'CAcert'), config_dn)
|
|
|
0201d8 |
+ entry = ldap.get_entry(dn, ['cACertificate;binary'])
|
|
|
0201d8 |
+
|
|
|
0201d8 |
+ cert = entry.single_value['cACertificate;binary']
|
|
|
0201d8 |
+ try:
|
|
|
0201d8 |
+ subject, issuer_serial, public_key_info = _parse_cert(cert)
|
|
|
0201d8 |
+ except ValueError:
|
|
|
0201d8 |
+ pass
|
|
|
0201d8 |
+ else:
|
|
|
0201d8 |
+ if filter_subject is not None and subject not in filter_subject:
|
|
|
0201d8 |
+ raise errors.NotFound(reason="no matching entry found")
|
|
|
0201d8 |
|
|
|
0201d8 |
- nickname = get_ca_nickname(compat_realm)
|
|
|
0201d8 |
- ext_key_usage = {x509.EKU_SERVER_AUTH}
|
|
|
0201d8 |
- if compat_ipa_ca:
|
|
|
0201d8 |
- ext_key_usage |= {x509.EKU_CLIENT_AUTH,
|
|
|
0201d8 |
- x509.EKU_EMAIL_PROTECTION,
|
|
|
0201d8 |
- x509.EKU_CODE_SIGNING}
|
|
|
0201d8 |
+ if compat_ipa_ca:
|
|
|
0201d8 |
+ ca_subject = subject
|
|
|
0201d8 |
+ else:
|
|
|
0201d8 |
+ ca_subject = None
|
|
|
0201d8 |
+ certs = make_compat_ca_certs([cert], compat_realm, ca_subject)
|
|
|
0201d8 |
|
|
|
0201d8 |
- return [(cert, nickname, True, ext_key_usage)]
|
|
|
0201d8 |
+ if certs:
|
|
|
0201d8 |
+ return certs
|
|
|
0201d8 |
+ else:
|
|
|
0201d8 |
+ raise errors.NotFound(reason="no such entry")
|
|
|
0201d8 |
|
|
|
0201d8 |
|
|
|
0201d8 |
def trust_flags_to_key_policy(trust_flags):
|
|
|
0201d8 |
--
|
|
|
0201d8 |
2.1.0
|
|
|
0201d8 |
|