mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
server install: fix KDC certificate validation in CA-less
Verify that the provided certificate has the extended key usage and subject alternative name required for KDC. https://pagure.io/freeipa/issue/6831 https://pagure.io/freeipa/issue/6869 Reviewed-By: Stanislav Laznicka <slaznick@redhat.com> Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
parent
cc572378a6
commit
3b5dbf7cdb
@ -24,6 +24,7 @@ import pwd
|
|||||||
import grp
|
import grp
|
||||||
import re
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
import shutil
|
import shutil
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ import cryptography.x509
|
|||||||
|
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import root_logger
|
from ipapython.ipa_log_manager import root_logger
|
||||||
|
from ipapython.kerberos import Principal
|
||||||
from ipapython import ipautil
|
from ipapython import ipautil
|
||||||
from ipalib import x509 # pylint: disable=ipa-forbidden-import
|
from ipalib import x509 # pylint: disable=ipa-forbidden-import
|
||||||
|
|
||||||
@ -179,6 +181,38 @@ def unparse_trust_flags(trust_flags):
|
|||||||
return trust_flags
|
return trust_flags
|
||||||
|
|
||||||
|
|
||||||
|
def verify_kdc_cert_validity(kdc_cert, ca_certs, realm):
|
||||||
|
pem_kdc_cert = kdc_cert.public_bytes(serialization.Encoding.PEM)
|
||||||
|
pem_ca_certs = '\n'.join(
|
||||||
|
cert.public_bytes(serialization.Encoding.PEM) for cert in ca_certs)
|
||||||
|
|
||||||
|
with NamedTemporaryFile() as kdc_file, NamedTemporaryFile() as ca_file:
|
||||||
|
kdc_file.write(pem_kdc_cert)
|
||||||
|
kdc_file.flush()
|
||||||
|
ca_file.write(pem_ca_certs)
|
||||||
|
ca_file.flush()
|
||||||
|
|
||||||
|
try:
|
||||||
|
ipautil.run(
|
||||||
|
[OPENSSL, 'verify', '-CAfile', ca_file.name, kdc_file.name])
|
||||||
|
eku = kdc_cert.extensions.get_extension_for_class(
|
||||||
|
cryptography.x509.ExtendedKeyUsage)
|
||||||
|
list(eku.value).index(
|
||||||
|
cryptography.x509.ObjectIdentifier(x509.EKU_PKINIT_KDC))
|
||||||
|
except (ipautil.CalledProcessError,
|
||||||
|
cryptography.x509.ExtensionNotFound,
|
||||||
|
ValueError):
|
||||||
|
raise ValueError("invalid for a KDC")
|
||||||
|
|
||||||
|
principal = str(Principal(['krbtgt', realm], realm))
|
||||||
|
gns = x509.process_othernames(x509.get_san_general_names(kdc_cert))
|
||||||
|
for gn in gns:
|
||||||
|
if isinstance(gn, x509.KRB5PrincipalName) and gn.name == principal:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise ValueError("invalid for realm %s" % realm)
|
||||||
|
|
||||||
|
|
||||||
class NSSDatabase(object):
|
class NSSDatabase(object):
|
||||||
"""A general-purpose wrapper around a NSS cert database
|
"""A general-purpose wrapper around a NSS cert database
|
||||||
|
|
||||||
@ -692,3 +726,10 @@ class NSSDatabase(object):
|
|||||||
if msg == BAD_USAGE_ERR:
|
if msg == BAD_USAGE_ERR:
|
||||||
msg = 'invalid for a CA.'
|
msg = 'invalid for a CA.'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
def verify_kdc_cert_validity(self, nickname, realm):
|
||||||
|
nicknames = self.get_trust_chain(nickname)
|
||||||
|
certs = [self.get_cert(nickname) for nickname in nicknames]
|
||||||
|
certs = [x509.load_certificate(cert, x509.DER) for cert in certs]
|
||||||
|
|
||||||
|
verify_kdc_cert_validity(certs[-1], certs[:-1], realm)
|
||||||
|
@ -1001,7 +1001,7 @@ def handle_error(error, log_file_name=None):
|
|||||||
|
|
||||||
|
|
||||||
def load_pkcs12(cert_files, key_password, key_nickname, ca_cert_files,
|
def load_pkcs12(cert_files, key_password, key_nickname, ca_cert_files,
|
||||||
host_name):
|
host_name=None, realm_name=None):
|
||||||
"""
|
"""
|
||||||
Load and verify server certificate and private key from multiple files
|
Load and verify server certificate and private key from multiple files
|
||||||
|
|
||||||
@ -1066,13 +1066,21 @@ def load_pkcs12(cert_files, key_password, key_nickname, ca_cert_files,
|
|||||||
"CA certificate %s in %s is not valid: %s" %
|
"CA certificate %s in %s is not valid: %s" %
|
||||||
(subject, ", ".join(cert_files), e))
|
(subject, ", ".join(cert_files), e))
|
||||||
|
|
||||||
# Check server validity
|
if host_name is not None:
|
||||||
try:
|
try:
|
||||||
nssdb.verify_server_cert_validity(key_nickname, host_name)
|
nssdb.verify_server_cert_validity(key_nickname, host_name)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ScriptError(
|
raise ScriptError(
|
||||||
"The server certificate in %s is not valid: %s" %
|
"The server certificate in %s is not valid: %s" %
|
||||||
(", ".join(cert_files), e))
|
(", ".join(cert_files), e))
|
||||||
|
|
||||||
|
if realm_name is not None:
|
||||||
|
try:
|
||||||
|
nssdb.verify_kdc_cert_validity(key_nickname, realm_name)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ScriptError(
|
||||||
|
"The KDC certificate in %s is not valid: %s" %
|
||||||
|
(", ".join(cert_files), e))
|
||||||
|
|
||||||
out_file = tempfile.NamedTemporaryFile()
|
out_file = tempfile.NamedTemporaryFile()
|
||||||
out_password = ipautil.ipa_generate_password()
|
out_password = ipautil.ipa_generate_password()
|
||||||
|
@ -520,12 +520,12 @@ def install_check(installer):
|
|||||||
if options.pkinit_pin is None:
|
if options.pkinit_pin is None:
|
||||||
raise ScriptError(
|
raise ScriptError(
|
||||||
"Kerberos KDC private key unlock password required")
|
"Kerberos KDC private key unlock password required")
|
||||||
pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12(
|
pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12(
|
||||||
cert_files=options.pkinit_cert_files,
|
cert_files=options.pkinit_cert_files,
|
||||||
key_password=options.pkinit_pin,
|
key_password=options.pkinit_pin,
|
||||||
key_nickname=options.pkinit_cert_name,
|
key_nickname=options.pkinit_cert_name,
|
||||||
ca_cert_files=options.ca_cert_files,
|
ca_cert_files=options.ca_cert_files,
|
||||||
host_name=host_name)
|
realm_name=realm_name)
|
||||||
pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
|
pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
|
||||||
|
|
||||||
if (options.http_cert_files and options.dirsrv_cert_files and
|
if (options.http_cert_files and options.dirsrv_cert_files and
|
||||||
@ -534,6 +534,13 @@ def install_check(installer):
|
|||||||
"Apache Server SSL certificate and Directory Server SSL "
|
"Apache Server SSL certificate and Directory Server SSL "
|
||||||
"certificate are not signed by the same CA certificate")
|
"certificate are not signed by the same CA certificate")
|
||||||
|
|
||||||
|
if (options.http_cert_files and
|
||||||
|
options.pkinit_cert_files and
|
||||||
|
http_ca_cert != pkinit_ca_cert):
|
||||||
|
raise ScriptError(
|
||||||
|
"Apache Server SSL certificate and PKINIT KDC "
|
||||||
|
"certificate are not signed by the same CA certificate")
|
||||||
|
|
||||||
if not options.dm_password:
|
if not options.dm_password:
|
||||||
dm_password = read_dm_password()
|
dm_password = read_dm_password()
|
||||||
|
|
||||||
|
@ -1069,12 +1069,12 @@ def promote_check(installer):
|
|||||||
if options.pkinit_pin is None:
|
if options.pkinit_pin is None:
|
||||||
raise ScriptError(
|
raise ScriptError(
|
||||||
"Kerberos KDC private key unlock password required")
|
"Kerberos KDC private key unlock password required")
|
||||||
pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12(
|
pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12(
|
||||||
cert_files=options.pkinit_cert_files,
|
cert_files=options.pkinit_cert_files,
|
||||||
key_password=options.pkinit_pin,
|
key_password=options.pkinit_pin,
|
||||||
key_nickname=options.pkinit_cert_name,
|
key_nickname=options.pkinit_cert_name,
|
||||||
ca_cert_files=options.ca_cert_files,
|
ca_cert_files=options.ca_cert_files,
|
||||||
host_name=config.host_name)
|
realm_name=config.realm_name)
|
||||||
pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
|
pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
|
||||||
|
|
||||||
if (options.http_cert_files and options.dirsrv_cert_files and
|
if (options.http_cert_files and options.dirsrv_cert_files and
|
||||||
@ -1083,6 +1083,13 @@ def promote_check(installer):
|
|||||||
"Server SSL certificate are not signed by the same"
|
"Server SSL certificate are not signed by the same"
|
||||||
" CA certificate")
|
" CA certificate")
|
||||||
|
|
||||||
|
if (options.http_cert_files and
|
||||||
|
options.pkinit_cert_files and
|
||||||
|
http_ca_cert != pkinit_ca_cert):
|
||||||
|
raise RuntimeError("Apache Server SSL certificate and PKINIT KDC "
|
||||||
|
"certificate are not signed by the same CA "
|
||||||
|
"certificate")
|
||||||
|
|
||||||
installutils.verify_fqdn(config.host_name, options.no_host_dns)
|
installutils.verify_fqdn(config.host_name, options.no_host_dns)
|
||||||
installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
|
installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user