summaryrefslogtreecommitdiffstats
path: root/ipaserver
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2010-10-29 16:23:21 -0400
committerSimo Sorce <ssorce@redhat.com>2010-11-18 15:09:36 -0500
commit52a46d121bf760f6beca4622ace0a4554a679c3c (patch)
tree550a2bddf9ab3848da9ab33ca73529060b9e4c68 /ipaserver
parent74ba0cc7c1bdb9c560324a68c16593755bcda5d8 (diff)
downloadfreeipa-52a46d121bf760f6beca4622ace0a4554a679c3c.tar.gz
freeipa-52a46d121bf760f6beca4622ace0a4554a679c3c.tar.xz
freeipa-52a46d121bf760f6beca4622ace0a4554a679c3c.zip
Add support for configuring KDC certs for PKINIT
This patch adds support only for the selfsign case. Replica support is also still missing at this stage.
Diffstat (limited to 'ipaserver')
-rw-r--r--ipaserver/install/certs.py88
-rw-r--r--ipaserver/install/krbinstance.py46
2 files changed, 129 insertions, 5 deletions
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index d4728b80e..3fa65207c 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -180,6 +180,7 @@ class CertDB(object):
self.certreq_fname = None
self.certder_fname = None
self.host_name = host_name
+ self.subject_base = subject_base
try:
self.cwd = os.getcwd()
except OSError, e:
@@ -187,10 +188,9 @@ class CertDB(object):
self.self_signed_ca = ipa_self_signed()
- if subject_base:
- self.subject_format = "CN=%%s,%s" % subject_base
- else:
- self.subject_format = "CN=%s,O=IPA"
+ if not subject_base:
+ self.subject_base = "O=IPA"
+ self.subject_format = "CN=%%s,%s" % self.subject_base
self.cacert_name = get_ca_nickname(self.realm)
self.valid_months = "120"
@@ -937,6 +937,86 @@ class CertDB(object):
except:
pass
+ def create_kdc_cert(self, nickname, hostname, destdir):
+ """Create a new certificate with the spcial othername encoding needed
+ by a KDC certificate.
+
+ nickname: the CN name set in the certificate
+ destdir: the location where cert and key are to be installed
+
+ destdir will contain kdc.pem if the operation is successful
+ """
+
+ reqcfg = "kdc_req.conf"
+ extcfg = ipautil.SHARE_DIR + "kdc_extensions.template"
+ key_fname = destdir + "/kdckey.pem"
+ cert_fname = destdir + "/kdccert.pem"
+ key_cert_fname = destdir + "/kdc.pem"
+
+ # Setup the temp dir
+ self.setup_cert_request()
+
+ # Copy the CA password file because openssl apparently can't use
+ # the same file twice within the same command and throws an error
+ ca_pwd_file = self.reqdir + "pwdfile.txt"
+ shutil.copyfile(self.passwd_fname, ca_pwd_file)
+
+ # Extract the cacert.pem file used by openssl to sign the certs
+ ipautil.run(["/usr/bin/openssl", "pkcs12",
+ "-in", self.pk12_fname,
+ "-passin", "file:" + self.passwd_fname,
+ "-passout", "file:" + ca_pwd_file,
+ "-out", "cacert.pem"])
+
+ # Create the kdc key
+ ipautil.run(["/usr/bin/openssl", "genrsa",
+ "-out", key_fname, "2048"])
+
+ # Prepare a simple cert request
+ req_dict = dict(PASSWORD=self.gen_password(),
+ SUBJBASE=self.subject_base,
+ CERTNAME="CN="+nickname)
+ req_template = ipautil.SHARE_DIR + reqcfg + ".template"
+ conf = ipautil.template_file(req_template, req_dict)
+ fd = open(reqcfg, "w+")
+ fd.write(conf)
+ fd.close()
+
+ base = self.subject_base.replace(",", "/")
+ esc_subject = "CN=%s/%s" % (nickname, base)
+
+ ipautil.run(["/usr/bin/openssl", "req", "-new",
+ "-config", reqcfg,
+ "-subj", esc_subject,
+ "-key", key_fname,
+ "-out", "kdc.req"])
+
+ # Finally, sign the cert using the extensions file to set the
+ # special name
+ ipautil.run(["/usr/bin/openssl", "x509", "-req",
+ "-CA", "cacert.pem",
+ "-extfile", extcfg,
+ "-extensions", "kdc_cert",
+ "-passin", "file:" + ca_pwd_file,
+ "-set_serial", next_serial(),
+ "-in", "kdc.req",
+ "-out", cert_fname],
+ env = { 'REALM':self.realm, 'HOST_FQDN':hostname })
+
+ # Merge key and cert in a single file
+ fd = open(key_fname, "r")
+ key = fd.read()
+ fd.close()
+ fd = open(cert_fname, "r")
+ cert = fd.read()
+ fd.close()
+ fd = open(key_cert_fname, "w")
+ fd.write(key)
+ fd.write(cert)
+ fd.close()
+ os.unlink(key_fname)
+ os.unlink(cert_fname)
+
def backup_files(self):
self.fstore.backup_file(self.noise_fname)
self.fstore.backup_file(self.passwd_fname)
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index d8a5eff24..bfcb86999 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -44,8 +44,21 @@ import pyasn1.codec.ber.encoder
import pyasn1.codec.ber.decoder
import struct
+import certs
+import httpinstance
+
KRBMKEY_DENY_ACI = '(targetattr = "krbMKey")(version 3.0; acl "No external access"; deny (read,write,search,compare) userdn != "ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";)'
+def check_pkinit_plugin():
+ LIB32 = '/usr/lib/krb5/plugins/preauth/pkinit.so'
+ LIB64 = '/usr/lib64/krb5/plugins/preauth/pkinit.so'
+ if not os.path.exists(LIB32) and not os.path.exists(LIB64):
+ print "The pkinit plugin is missing"
+ print "Please install the 'krb5-pkinit-openssl' package and start the installation again"
+ return False
+
+ return True
+
def update_key_val_in_file(filename, key, val):
if os.path.exists(filename):
pattern = "^[\s#]*%s\s*=\s*%s\s*" % (re.escape(key), re.escape(val))
@@ -83,6 +96,8 @@ class KrbInstance(service.Service):
self.suffix = None
self.kdc_password = None
self.sub_dict = None
+ self.pkcs12_info = None
+ self.self_signed_ca = None
if fstore:
self.fstore = fstore
@@ -158,8 +173,11 @@ class KrbInstance(service.Service):
self.step("starting the KDC", self.__start_instance)
self.step("configuring KDC to start on boot", self.__enable)
- def create_instance(self, ds_user, realm_name, host_name, domain_name, admin_password, master_password):
+ def create_instance(self, ds_user, realm_name, host_name, domain_name, admin_password, master_password, setup_pkinit=False, pkcs12_info=None, self_signed_ca=False, subject_base=None):
self.master_password = master_password
+ self.pkcs12_info = pkcs12_info
+ self.self_signed_ca = self_signed_ca
+ self.subject_base = subject_base
self.__common_setup(ds_user, realm_name, host_name, domain_name, admin_password)
@@ -175,6 +193,8 @@ class KrbInstance(service.Service):
self.step("exporting the kadmin keytab", self.__export_kadmin_changepw_keytab)
self.step("adding the password extension to the directory", self.__add_pwd_extop_module)
self.step("adding the kerberos master key to the directory", self.__add_master_key)
+ if setup_pkinit:
+ self.step("creating X509 Certificate for PKINIT", self.__setup_pkinit)
self.__common_post_setup()
@@ -477,6 +497,30 @@ class KrbInstance(service.Service):
self.fstore.backup_file("/etc/sysconfig/ipa_kpasswd")
update_key_val_in_file("/etc/sysconfig/ipa_kpasswd", "export KRB5_KTNAME", "/var/kerberos/krb5kdc/kpasswd.keytab")
+ def __setup_pkinit(self):
+ if self.self_signed_ca:
+ ca_db = certs.CertDB(httpinstance.NSS_DIR, self.realm,
+ subject_base=self.subject_base)
+ else:
+ ca_db = certs.CertDB(httpinstance.NSS_DIR, self.realm,
+ host_name=self.fqdn,
+ subject_base=self.subject_base)
+ if self.pkcs12_info:
+
+ raise RuntimeError("Using PKCS12 Certs not supported yet\n")
+
+ else:
+ if self.self_signed_ca:
+ ca_db.create_kdc_cert("KDC-Cert", self.fqdn,
+ "/var/kerberos/krb5kdc")
+ else:
+ raise RuntimeError("Using PKCS12 Certs not supported yet\n")
+
+ # Finally copy the cacert in the krb directory so we don't
+ # have any selinux issues with the file context
+ shutil.copyfile("/usr/share/ipa/html/ca.crt",
+ "/var/kerberos/krb5kdc/cacert.pem")
+
def uninstall(self):
if self.is_configured():
self.print_msg("Unconfiguring %s" % self.service_name)