Verify that the external CA certificate files are correct.

ticket 1572
This commit is contained in:
Jan Cholasta 2011-08-17 10:19:37 +02:00 committed by Rob Crittenden
parent 028a87b0da
commit c4f04dd858
2 changed files with 60 additions and 7 deletions

View File

@ -39,6 +39,7 @@ import traceback
from ConfigParser import RawConfigParser from ConfigParser import RawConfigParser
import random import random
import tempfile import tempfile
import nss.error
from ipaserver.install import dsinstance from ipaserver.install import dsinstance
from ipaserver.install import krbinstance from ipaserver.install import krbinstance
@ -59,6 +60,7 @@ from ipalib import api, errors, util
from ipalib.parameters import IA5Str from ipalib.parameters import IA5Str
from ipapython.config import IPAOptionParser from ipapython.config import IPAOptionParser
from ipalib.dn import DN from ipalib.dn import DN
from ipalib.x509 import load_certificate_from_file, load_certificate_chain_from_file
pw_name = None pw_name = None
uninstalling = False uninstalling = False
@ -567,18 +569,51 @@ def main():
# already having done the first stage of the CA install. # already having done the first stage of the CA install.
print "CA is not installed yet. To install with an external CA is a two-stage process.\nFirst run the installer with --external-ca." print "CA is not installed yet. To install with an external CA is a two-stage process.\nFirst run the installer with --external-ca."
sys.exit(1) sys.exit(1)
if not ipautil.file_exists(options.external_cert_file):
print "%s does not exist" % options.external_cert_file
sys.exit(1)
if not ipautil.file_exists(options.external_ca_file):
print "%s does not exist" % options.external_ca_file
sys.exit(1)
# This will override any settings passed in on the cmdline # This will override any settings passed in on the cmdline
if ipautil.file_exists(ANSWER_CACHE): if ipautil.file_exists(ANSWER_CACHE):
dm_password = read_password("Directory Manager", confirm=False) dm_password = read_password("Directory Manager", confirm=False)
options._update_loose(read_cache(dm_password)) options._update_loose(read_cache(dm_password))
if options.external_cert_file:
try:
extcert = load_certificate_from_file(options.external_cert_file)
except IOError, e:
print "Can't load the PKCS#10 certificate: %s." % str(e)
sys.exit(1)
except nss.error.NSPRError:
print "'%s' is not a valid PEM-encoded certificate." % options.external_cert_file
sys.exit(1)
certsubject = unicode(extcert.subject)
wantsubject = unicode(DN(('CN','Certificate Authority'), options.subject))
if certsubject.lower() != wantsubject.lower():
print "Subject of the PKCS#10 certificate is not correct (got %s, expected %s)." % (certsubject, wantsubject)
sys.exit(1)
try:
extchain = load_certificate_chain_from_file(options.external_ca_file)
except IOError, e:
print "Can't load the external CA chain: %s." % str(e)
sys.exit(1)
except nss.error.NSPRError:
print "'%s' is not a valid PEM-encoded certificate chain." % options.external_ca_file
sys.exit(1)
certdict = dict((unicode(cert.subject).lower(), cert) for cert in extchain)
certissuer = unicode(extcert.issuer)
if certissuer.lower() not in certdict:
print "The PKCS#10 certificate is not signed by the external CA (unknown issuer %s)." % certissuer
sys.exit(1)
cert = extcert
while cert.issuer != cert.subject:
certissuer = unicode(cert.issuer)
if certissuer.lower() not in certdict:
print "The external CA chain is incomplete (%s is missing from the chain)." % certissuer
sys.exit(1)
cert = certdict[certissuer.lower()]
print "==============================================================================" print "=============================================================================="
print "This program will set up the FreeIPA Server." print "This program will set up the FreeIPA Server."
print "" print ""

View File

@ -34,6 +34,7 @@
import os import os
import sys import sys
import base64 import base64
import re
import nss.nss as nss import nss.nss as nss
from nss.error import NSPRError from nss.error import NSPRError
from ipapython import ipautil from ipapython import ipautil
@ -45,6 +46,8 @@ from ipalib import errors
PEM = 0 PEM = 0
DER = 1 DER = 1
PEM_REGEX = re.compile(r'(?<=-----BEGIN CERTIFICATE-----).*?(?=-----END CERTIFICATE-----)', re.DOTALL)
def valid_issuer(issuer, realm): def valid_issuer(issuer, realm):
return issuer in ('CN=%s Certificate Authority' % realm, return issuer in ('CN=%s Certificate Authority' % realm,
'CN=Certificate Authority,O=%s' % realm,) 'CN=Certificate Authority,O=%s' % realm,)
@ -89,6 +92,21 @@ def load_certificate(data, datatype=PEM, dbdir=None):
return nss.Certificate(buffer(data)) return nss.Certificate(buffer(data))
def load_certificate_chain_from_file(filename, dbdir=None):
"""
Load a certificate chain from a PEM file.
Returns a list of nss.Certificate objects.
"""
fd = open(filename, 'r')
data = fd.read()
fd.close()
chain = PEM_REGEX.findall(data)
chain = [load_certificate(cert, PEM, dbdir) for cert in chain]
return chain
def load_certificate_from_file(filename, dbdir=None): def load_certificate_from_file(filename, dbdir=None):
""" """
Load a certificate from a PEM file. Load a certificate from a PEM file.
@ -99,7 +117,7 @@ def load_certificate_from_file(filename, dbdir=None):
data = fd.read() data = fd.read()
fd.close() fd.close()
return load_certificate(file, PEM, dbdir) return load_certificate(data, PEM, dbdir)
def get_subject(certificate, datatype=PEM, dbdir=None): def get_subject(certificate, datatype=PEM, dbdir=None):
""" """