Use information from the certificate subject when setting the NSS nickname.

There were a few places in the code where certs were loaded from a
PKCS#7 file or a chain in a PEM file. The certificates got very
generic nicknames.

We can instead pull the subject from the certificate and use that as
the nickname.

https://fedorahosted.org/freeipa/ticket/1141
This commit is contained in:
Rob Crittenden
2011-07-11 17:39:30 -04:00
parent 038089a0c9
commit 2f650b60a4
4 changed files with 57 additions and 21 deletions

View File

@@ -94,7 +94,7 @@ def subject_callback(option, opt_str, value, parser):
raise ValueError('invalid attribute: %s' % dn[x][0].attr.lower()) raise ValueError('invalid attribute: %s' % dn[x][0].attr.lower())
except ValueError, e: except ValueError, e:
raise ValueError('Invalid subject base format: %s' % str(e)) raise ValueError('Invalid subject base format: %s' % str(e))
parser.values.subject = value parser.values.subject = str(dn) # may as well normalize it
def parse_options(): def parse_options():
# Guaranteed to give a random 200k range below the 2G mark (uint32_t limit) # Guaranteed to give a random 200k range below the 2G mark (uint32_t limit)

View File

@@ -71,27 +71,45 @@ def load_certificate(data, datatype=PEM, dbdir=None):
data = base64.b64decode(data) data = base64.b64decode(data)
if dbdir is None: if dbdir is None:
if api.env.in_tree: if 'in_tree' in api.env:
dbdir = api.env.dot_ipa + os.sep + 'alias' if api.env.in_tree:
dbdir = api.env.dot_ipa + os.sep + 'alias'
else:
dbdir = "/etc/httpd/alias"
nss.nss_init(dbdir)
else: else:
dbdir = "/etc/httpd/alias" nss.nss_init_nodb()
else:
nss.nss_init(dbdir)
nss.nss_init(dbdir)
return nss.Certificate(buffer(data)) return nss.Certificate(buffer(data))
def get_subject(certificate, datatype=PEM): def load_certificate_from_file(filename, dbdir=None):
"""
Load a certificate from a PEM file.
Returns a nss.Certificate type
"""
fd = open(filename, 'r')
data = fd.read()
fd.close()
return load_certificate(file, PEM, dbdir)
def get_subject(certificate, datatype=PEM, dbdir=None):
""" """
Load an X509.3 certificate and get the subject. Load an X509.3 certificate and get the subject.
""" """
nsscert = load_certificate(certificate, datatype) nsscert = load_certificate(certificate, datatype, dbdir)
return nsscert.subject return nsscert.subject
def get_serial_number(certificate, datatype=PEM): def get_serial_number(certificate, datatype=PEM, dbdir=None):
""" """
Return the decimal value of the serial number. Return the decimal value of the serial number.
""" """
nsscert = load_certificate(certificate, datatype) nsscert = load_certificate(certificate, datatype, dbdir)
return nsscert.serial_number return nsscert.serial_number
def make_pem(data): def make_pem(data):

View File

@@ -39,6 +39,7 @@ import socket
from ipapython import dogtag from ipapython import dogtag
from ipapython.certdb import get_ca_nickname from ipapython.certdb import get_ca_nickname
from ipalib import pkcs10, x509 from ipalib import pkcs10, x509
from ipalib.dn import DN
import subprocess import subprocess
from nss.error import NSPRError from nss.error import NSPRError
@@ -919,7 +920,7 @@ class CAInstance(service.Service):
# makes openssl throw up. # makes openssl throw up.
data = base64.b64decode(chain) data = base64.b64decode(chain)
(certs, stderr, returncode) = ipautil.run(["/usr/bin/openssl", (certlist, stderr, returncode) = ipautil.run(["/usr/bin/openssl",
"pkcs7", "pkcs7",
"-inform", "-inform",
"DER", "DER",
@@ -932,18 +933,20 @@ class CAInstance(service.Service):
st = 1 st = 1
en = 0 en = 0
subid = 0 subid = 0
normalized_base = str(DN(self.subject_base))
while st > 0: while st > 0:
st = certs.find('-----BEGIN', en) st = certlist.find('-----BEGIN', en)
en = certs.find('-----END', en+1) en = certlist.find('-----END', en+1)
if st > 0: if st > 0:
try: try:
(chain_fd, chain_name) = tempfile.mkstemp() (chain_fd, chain_name) = tempfile.mkstemp()
os.write(chain_fd, certs[st:en+25]) os.write(chain_fd, certlist[st:en+25])
os.close(chain_fd) os.close(chain_fd)
if subid == 0: (rdn, subject) = certs.get_cert_nickname(certlist[st:en+25])
nick = self.canickname if subject.lower() == ('CN=Certificate Authority,%s' % normalized_base).lower():
nick = get_ca_nickname(self.realm)
else: else:
nick = "%s sub %d" % (self.canickname, subid) nick = subject
self.__run_certutil( self.__run_certutil(
['-A', '-t', 'CT,C,C', '-n', nick, '-a', ['-A', '-t', 'CT,C,C', '-n', nick, '-a',
'-i', chain_name] '-i', chain_name]

View File

@@ -38,6 +38,7 @@ from ipalib import pkcs10
from ConfigParser import RawConfigParser, MissingSectionHeaderError from ConfigParser import RawConfigParser, MissingSectionHeaderError
import service import service
from ipalib import x509 from ipalib import x509
from ipalib.dn import DN
from ipalib.errors import CertificateOperationError from ipalib.errors import CertificateOperationError
from nss.error import NSPRError from nss.error import NSPRError
@@ -82,6 +83,20 @@ def find_cert_from_txt(cert, start=0):
cert = cert[s:e] cert = cert[s:e]
return (cert, e) return (cert, e)
def get_cert_nickname(cert):
"""
Using the subject from cert come up with a nickname suitable
for NSS. The caller can decide whether to use just the RDN
or the whole subject.
Returns a tuple of (rdn, subject)
"""
nsscert = x509.load_certificate(cert)
subject = str(nsscert.subject)
dn = DN(subject)
return (str(dn[0]), str(dn))
def next_serial(serial_file=CA_SERIALNO): def next_serial(serial_file=CA_SERIALNO):
""" """
Get the next serial number if we're using an NSS-based self-signed CA. Get the next serial number if we're using an NSS-based self-signed CA.
@@ -415,16 +430,16 @@ class CertDB(object):
certs = fd.read() certs = fd.read()
fd.close() fd.close()
normalized_base = str(DN(self.subject_base))
st = 0 st = 0
subid=0
while True: while True:
try: try:
(cert, st) = find_cert_from_txt(certs, st) (cert, st) = find_cert_from_txt(certs, st)
if subid == 0: (nick, subject) = get_cert_nickname(cert)
nick = self.cacert_name if subject.lower() == ('CN=Certificate Authority,%s' % normalized_base).lower():
nick = get_ca_nickname(self.realm)
else: else:
nick = "%s sub %d" % (self.cacert_name, subid) nick = subject
subid = subid + 1
self.run_certutil(["-A", "-n", nick, self.run_certutil(["-A", "-n", nick,
"-t", "CT,,C", "-t", "CT,,C",
"-a"], "-a"],