We were improperly creating the IPA self-signed CA during installation. It lacked a certificate extension marking it as a CA. This causes the certificates that IPA generates to not work with Firefox 3.5.

I'm working on a fix for this. If someone wants to give it a test that would be helpful.

There are several steps you need to take on the initial master. If you have replica's I'll get back to that:

- Apply the patch to certs.py to (/usr/lib/python*/site-packages/ipaserver/certs.py)
- Back up /etc/dirsrv/slapd-INSTANCE/*.db and *.txt
- Back up /etc/httpd/alias/*.db
- Run ipa-ca with the following options

As root:

# service dirsrv stop
# service httpd stop
# rm -f /etc/dirsrv/slapd-<INSTANCE>/cert8.db
# python ipa-ca -g
# python ipa-ca -i -s yourhost.example.com -o ds.p12 -p password
# python ipa-ca -i -s yourhost.example.com -o http.p12 -p password
# pk12util -i ds.p12 -d /etc/dirsrv/slapd-<INSTANCE> -k /etc/dirsrv/slapd-<INSTANCE>/pwdfile.txt
# rm -f /etc/httpd/alias/*.db
# certutil -N -d /etc/httpd/alias (press enter twice, no password)
# chown apache /etc/httpd/alias/*.db
# pk12util -i http.p12  -d /etc/httpd/alias
# certutil -M -t "CT,,C" -n "CA certificate" -d /etc/httpd/alias
# service dirsrv start
# service httpd start

Your new CA is in /etc/dirsrv/slapd-INSTANCE/cacert.p12. You'll want to back this up somewhere (and probably remove the .p12 file).

This should generate a new CA, issue 2 certificates and put them into PKCS#12 files, then import them into your instances.

If you have any replicas then do the same steps without the "ipa-ca -g" step. ipa-ca should always be run on the initial IPA master.

The basic idea is that 'ipa-ca -g' generates a new CA using the certs.py patch that you applied. Then you create a PKCS#12 file for each of the two services on each IPA instace. The process of generating a new CA creates a new DS database so you just have to import the cert you generated.

For Apache we have to remove the database and re-create it, fixing permissions along the way. Then the cert is imported and the CA trusted.

This works for me with IPA v1.2. I wouldn't recommend doing this on a production server yet.

diff --git a/ipa-server/ipaserver/certs.py b/ipa-server/ipaserver/certs.py
index 8cb1d08..d7c02c4 100644
--- a/ipa-server/ipaserver/certs.py
+++ b/ipa-server/ipaserver/certs.py
@@ -155,17 +155,25 @@ class CertDB(object):
         self.set_perms(self.passwd_fname, write=True)
     def create_ca_cert(self):
-        # Generate the encryption key
-        self.run_certutil(["-G", "-z", self.noise_fname, "-f", 
-        # Generate the self-signed cert
-        self.run_certutil(["-S", "-n", self.cacert_name,
-                           "-s", "cn=IPA Test Certificate Authority",
-                           "-x",
-                           "-t", "CT,,C",
-                           "-m", self.next_serial(),
-                           "-v", self.valid_months,
-                           "-z", self.noise_fname,
-                           "-f", self.passwd_fname])
+        p = subprocess.Popen(["/usr/bin/certutil",
+                              "-d", self.secdir,
+                              "-S", "-n", self.cacert_name,
+                              "-s", "cn=IPA Test Certificate Authority",
+                              "-x",
+                              "-t", "CT,,C",
+                              "-2",
+                              "-m", self.next_serial(),
+                              "-v", self.valid_months,
+                              "-z", self.noise_fname,
+                              "-f", self.passwd_fname],
+                               stdin=subprocess.PIPE,
+                               stdout=subprocess.PIPE,
+                               stderr=subprocess.PIPE)
+        # Is this a CA certificate [y/N]?  y
+        # Enter the path length constraint, enter to skip [<0 for unlimited pat
+        # Is this a critical extension [y/N]? y
+        p.stdin.write("y\n\n7\n")
+        p.wait()
     def export_ca_cert(self, nickname, create_pkcs12=False):
         """create_pkcs12 tells us whether we should create a PKCS#12 file
#! /usr/bin/python -E
# Authors: Rob Crittenden <rcrit...@redhat.com>
# Copyright (C) 2009  Red Hat
# see file 'COPYING' for use and warranty information
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; version 2 only
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

import sys
import os
import subprocess
import shutil
import glob
import traceback
from optparse import OptionParser
import krbV
import tempfile

from ipaserver import dsinstance
from ipaserver import certs
import ipa.ipautil as ipautil

def parse_options():
    parser = OptionParser()

    parser.add_option("-g", "--generate", dest="generate", action="store_true",
                      default=False, help="Generate a new CA")
    parser.add_option("-i", "--issue", dest="issue", action="store_true",
                      default=False, help="issue a server cert")
    parser.add_option("-s", "--subject", dest="hostname",
                      help="hostname for server cert")
    parser.add_option("-o", "--pk12", dest="pk12file",
                      help="PKCS#12 file to store new cert in")
    parser.add_option("-p", "--password", dest="password",
                      help="password for PKCS#12 file")

    options, args = parser.parse_args()

    if options.generate and options.issue:
        parser.error("generate and issue are mutually-exclusive")

    if options.issue and (not options.hostname or not options.pk12file or not 
        parser.error("to issue a cert the hostname, PKCS#12 file and password 
are all required")

    return options

def get_realm_name():
        c = krbV.default_context()
        return c.default_realm
    except Exception, e:
        return None

def main():

    options = parse_options()

    if os.getegid() != 0:
        print "Must be root to setup server"
        return 1

    realm_name = get_realm_name()
    ds_dir = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name))

    ca_db = certs.CertDB(ds_dir)

    tmpdb = certs.CertDB(dir)

    options, args = parser.parse_args()

    return options

def main():

    options = parse_options()

    if os.getegid() != 0:
        print "Must be root to setup server"
        return 1

    realm_name = get_realm_name()
    ds_dir = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name))

    if options.generate:
        print "Generating new CA certificate in %s" % ds_dir
        if ipautil.file_exists(ds_dir + "/cert8.db"):
            raise RuntimeError("Directory server certificate database already 
exists. Back it up and remove it in order to generate a new one.")
        ca_db = certs.CertDB(ds_dir)
        print "Publishing new CA cert to /usr/share/ipa/html/ca.crt"
        shutil.copy(ca_db.cacert_fname, "/usr/share/ipa/html/ca.crt")
        print "Publishing new CA cert to /etc/ipa/ca.crt"

    if options.issue:
            certdir = tempfile.mkdtemp(prefix = "tmp-")
            tmpdb = certs.CertDB(certdir)
            ca_db = certs.CertDB(ds_dir)
            print "Creating temporary certificate database"
            subject = "CN=%s,ou=test-ipa,O=IPA" % options.hostname
            print "Generating new certificate for %s" % options.hostname
            tmpdb.create_server_cert("Server-Cert", subject, ca_db)
            (pk12_fd, pk12_name) = tempfile.mkstemp()
            os.write(pk12_fd, options.password)
                print "Creating PKCS#12 file %s" % options.pk12file
                tmpdb.export_pkcs12(options.pk12file, pk12_name, "Server-Cert")
            print "Cleaning up"
            shutil.rmtree(certdir, ignore_errors=True)

    return 0

except SystemExit, e:
except Exception, e:
    print str(e)

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Freeipa-devel mailing list

Reply via email to