From e736e75ce9724ae8298a5b69d093313cd6e62b60 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 27 Mar 2013 14:25:18 +0100 Subject: Drop --selfsign server functionality Design: http://freeipa.org/page/V3/Drop_selfsign_functionality Ticket: https://fedorahosted.org/freeipa/ticket/3494 --- ipaserver/install/certs.py | 583 ++++++------------------------- ipaserver/install/dsinstance.py | 45 +-- ipaserver/install/httpinstance.py | 17 +- ipaserver/install/ipa_replica_prepare.py | 36 +- ipaserver/install/krbinstance.py | 21 +- ipaserver/plugins/rabase.py | 2 - ipaserver/plugins/selfsign.py | 230 ------------ 7 files changed, 137 insertions(+), 797 deletions(-) delete mode 100644 ipaserver/plugins/selfsign.py (limited to 'ipaserver') diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index 4f16e4d0..b170c7cb 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -17,20 +17,20 @@ # along with this program. If not, see . # -import os, stat, subprocess, re +import os +import stat +import re import sys import tempfile import shutil -from ipapython.ipa_log_manager import * import xml.dom.minidom import pwd -import fcntl import base64 from hashlib import sha1 -from ConfigParser import RawConfigParser, MissingSectionHeaderError from nss import nss +from ipapython.ipa_log_manager import root_logger from ipapython import dogtag from ipapython import sysrestore from ipapython import ipautil @@ -46,32 +46,6 @@ from ipalib.text import _ # where apache can reach NSS_DIR = "/etc/httpd/alias" -CA_SERIALNO="/var/lib/ipa/ca_serialno" - -def ipa_self_signed(): - """ - Determine if the current IPA CA is self-signed or using another CA - - We do this based on the CA plugin that is currently in use. - """ - if api.env.ra_plugin == 'selfsign': - return True - else: - return False - -def ipa_self_signed_master(): - """ - The selfsign backend is enabled only one a single master. - - Return True/False whether this is that master. - - Returns None if not a self-signed server. - """ - if ipa_self_signed(): - return api.env.enable_ra - else: - return None - def find_cert_from_txt(cert, start=0): """ Given a cert blob (str) which may or may not contian leading and @@ -106,90 +80,6 @@ def get_cert_nickname(cert): return (str(dn[0]), dn) -def next_serial(serial_file=CA_SERIALNO): - """ - Get the next serial number if we're using an NSS-based self-signed CA. - - The file is an ini-like file with following properties: - lastvalue = the last serial number handed out - nextreplica = the serial number the next replica should start with - replicainterval = the number to add to nextreplica the next time a - replica is created - - File locking is attempted so we have unique serial numbers. - """ - fp = None - parser = RawConfigParser() - if ipautil.file_exists(serial_file): - try: - fp = open(serial_file, "r+") - fcntl.flock(fp.fileno(), fcntl.LOCK_EX) - parser.readfp(fp) - serial = parser.getint('selfsign', 'lastvalue') - cur_serial = serial + 1 - except IOError, e: - raise RuntimeError("Unable to determine serial number: %s" % str(e)) - except MissingSectionHeaderError: - fcntl.flock(fp.fileno(), fcntl.LOCK_UN) - fp.close() - f=open(serial_file,"r") - r = f.readline() - f.close() - cur_serial = int(r) + 1 - fp = open(serial_file, "w") - fcntl.flock(fp.fileno(), fcntl.LOCK_EX) - parser.add_section('selfsign') - parser.set('selfsign', 'nextreplica', 500000) - parser.set('selfsign', 'replicainterval', 500000) - else: - fp = open(serial_file, "w") - fcntl.flock(fp.fileno(), fcntl.LOCK_EX) - parser.add_section('selfsign') - parser.set('selfsign', 'nextreplica', 500000) - parser.set('selfsign', 'replicainterval', 500000) - cur_serial = 1000 - - try: - fp.seek(0) - parser.set('selfsign', 'lastvalue', cur_serial) - parser.write(fp) - fp.flush() - fcntl.flock(fp.fileno(), fcntl.LOCK_UN) - fp.close() - except IOError, e: - raise RuntimeError("Unable to increment serial number: %s" % str(e)) - - return str(cur_serial) - -def next_replica(serial_file=CA_SERIALNO): - """ - Return the starting serial number for a new self-signed replica - """ - fp = None - parser = RawConfigParser() - if ipautil.file_exists(serial_file): - try: - fp = open(serial_file, "r+") - fcntl.flock(fp.fileno(), fcntl.LOCK_EX) - parser.readfp(fp) - serial = parser.getint('selfsign', 'nextreplica') - nextreplica = serial + parser.getint('selfsign', 'replicainterval') - except IOError, e: - raise RuntimeError("Unable to determine serial number: %s" % str(e)) - else: - raise RuntimeError("%s does not exist, cannot create replica" % serial_file) - try: - fp.seek(0) - parser.set('selfsign', 'nextreplica', nextreplica) - parser.write(fp) - fp.flush() - fcntl.flock(fp.fileno(), fcntl.LOCK_UN) - fp.close() - except IOError, e: - raise RuntimeError("Unable to increment serial number: %s" % str(e)) - - return str(serial) - class NSSDatabase(object): """A general-purpose wrapper around a NSS cert database @@ -440,15 +330,10 @@ class CertDB(object): except OSError, e: raise RuntimeError("Unable to determine the current directory: %s" % str(e)) - self.self_signed_ca = ipa_self_signed() - if not subject_base: self.subject_base = DN(('O', 'IPA')) - if self.self_signed_ca: - self.cacert_name = get_ca_nickname(self.realm, 'CN=%s Certificate Authority') - else: - self.cacert_name = get_ca_nickname(self.realm) + self.cacert_name = get_ca_nickname(self.realm) self.valid_months = "120" self.keysize = "1024" @@ -495,22 +380,6 @@ class CertDB(object): # sure we are in a unique place when this happens os.chdir(self.reqdir) - def set_serial_from_pkcs12(self): - """A CA cert was loaded from a PKCS#12 file. Set up our serial file""" - - cur_serial = self.find_cacert_serial() - try: - fp = open(CA_SERIALNO, "w") - parser = RawConfigParser() - parser.add_section('selfsign') - parser.set('selfsign', 'lastvalue', cur_serial) - parser.set('selfsign', 'nextreplica', 500000) - parser.set('selfsign', 'replicainterval', 500000) - parser.write(fp) - fp.close() - except IOError, e: - raise RuntimeError("Unable to increment serial number: %s" % str(e)) - def set_perms(self, fname, write=False, uid=None): if uid: pent = pwd.getpwnam(uid) @@ -529,13 +398,10 @@ class CertDB(object): return self.nssdb.run_certutil(args, stdin) def run_signtool(self, args, stdin=None): - if not self.self_signed_ca: - f = open(self.passwd_fname, "r") + with open(self.passwd_fname, "r") as f: password = f.readline() - f.close() - new_args = ["/usr/bin/signtool", "-d", self.secdir, "-p", password] - else: - new_args = ["/usr/bin/signtool", "-d", self.secdir] + new_args = ["/usr/bin/signtool", "-d", self.secdir, "-p", password] + new_args = new_args + args ipautil.run(new_args, stdin) @@ -585,41 +451,6 @@ class CertDB(object): return False - def create_ca_cert(self): - os.chdir(self.secdir) - subject = DN(('cn', '%s Certificate Authority' % self.realm)) - p = subprocess.Popen(["/usr/bin/certutil", - "-d", self.secdir, - "-S", "-n", self.cacert_name, - "-s", str(subject), - "-x", - "-t", "CT,,C", - "-1", - "-2", - "-5", - "-m", next_serial(), - "-v", self.valid_months, - "-z", self.noise_fname, - "-f", self.passwd_fname], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - # Create key usage extension - # 0 - Digital Signature - # 1 - Non-repudiation - # 5 - Cert signing key - # Is this a critical extension [y/N]? y - p.stdin.write("0\n1\n5\n9\ny\n") - # Create basic constraint extension - # 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 - # 5 6 7 9 n -> SSL, S/MIME, Object signing CA - p.stdin.write("y\n\ny\n") - p.stdin.write("5\n6\n7\n9\nn\n") - p.wait() - os.chdir(self.cwd) - def export_ca_cert(self, nickname, create_pkcs12=False): """create_pkcs12 tells us whether we should create a PKCS#12 file of the CA or not. If we are running on a replica then we won't @@ -686,16 +517,6 @@ class CertDB(object): except ipautil.CalledProcessError: return '' - def find_cacert_serial(self): - (out, err, returncode) = self.run_certutil(["-L", "-n", self.cacert_name]) - data = out.split('\n') - for line in data: - x = re.match(r'\s+Serial Number: (\d+) .*', line) - if x is not None: - return x.group(1) - - raise RuntimeError("Unable to find serial number") - def track_server_cert(self, nickname, principal, password_file=None, command=None): """ Tell certmonger to track the given certificate nickname. @@ -752,12 +573,7 @@ class CertDB(object): def create_server_cert(self, nickname, hostname, other_certdb=None, subject=None): """ - other_certdb can mean one of two things, depending on the context. - - If we are using a self-signed CA then other_certdb contains the - CA that will be signing our CSR. - - If we are using a dogtag CA then it contains the RA agent key + If we are using a dogtag CA then other_certdb contains the RA agent key that will issue our cert. You can override the certificate Subject by specifying a subject. @@ -802,179 +618,117 @@ class CertDB(object): "-k", certtype, "-g", keysize, "-z", self.noise_fname, - "-f", self.passwd_fname] - if not self.self_signed_ca: - args.append("-a") + "-f", self.passwd_fname, + "-a"] (stdout, stderr, returncode) = self.run_certutil(args) os.remove(self.noise_fname) return (stdout, stderr) def issue_server_cert(self, certreq_fname, cert_fname): self.setup_cert_request() - if self.self_signed_ca: - p = subprocess.Popen(["/usr/bin/certutil", - "-d", self.secdir, - "-C", "-c", self.cacert_name, - "-i", certreq_fname, - "-o", cert_fname, - "-m", next_serial(), - "-v", self.valid_months, - "-f", self.passwd_fname, - "-1", "-5"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - - # Bah - this sucks, but I guess it isn't possible to fully - # control this with command line arguments. - # - # What this is requesting is: - # -1 (Create key usage extension) - # 2 - Key encipherment - # 9 - done - # n - not critical - # - # -5 (Create netscape cert type extension) - # 1 - SSL Server - # 9 - done - # n - not critical - p.stdin.write("2\n9\nn\n1\n9\nn\n") - p.wait() - else: - if self.host_name is None: - raise RuntimeError("CA Host is not set.") - f = open(certreq_fname, "r") - csr = f.readlines() - f.close() - csr = "".join(csr) + if self.host_name is None: + raise RuntimeError("CA Host is not set.") - # We just want the CSR bits, make sure there is nothing else - csr = pkcs10.strip_header(csr) + f = open(certreq_fname, "r") + csr = f.readlines() + f.close() + csr = "".join(csr) - params = {'profileId': 'caIPAserviceCert', - 'cert_request_type': 'pkcs10', - 'requestor_name': 'IPA Installer', - 'cert_request': csr, - 'xmlOutput': 'true'} + # We just want the CSR bits, make sure there is nothing else + csr = pkcs10.strip_header(csr) - # Send the request to the CA - f = open(self.passwd_fname, "r") - password = f.readline() - f.close() - result = dogtag.https_request( - self.host_name, - api.env.ca_ee_install_port or - dogtag.configured_constants().EE_SECURE_PORT, - "/ca/ee/ca/profileSubmitSSLClient", - self.secdir, password, "ipaCert", **params) - http_status, http_reason_phrase, http_headers, http_body = result - - if http_status != 200: - raise CertificateOperationError( - error=_('Unable to communicate with CMS (%s)') % - http_reason_phrase) - - # The result is an XML blob. Pull the certificate out of that - doc = xml.dom.minidom.parseString(http_body) - item_node = doc.getElementsByTagName("b64") + params = {'profileId': 'caIPAserviceCert', + 'cert_request_type': 'pkcs10', + 'requestor_name': 'IPA Installer', + 'cert_request': csr, + 'xmlOutput': 'true'} + + # Send the request to the CA + f = open(self.passwd_fname, "r") + password = f.readline() + f.close() + result = dogtag.https_request( + self.host_name, + api.env.ca_ee_install_port or + dogtag.configured_constants().EE_SECURE_PORT, + "/ca/ee/ca/profileSubmitSSLClient", + self.secdir, password, "ipaCert", **params) + http_status, http_reason_phrase, http_headers, http_body = result + + if http_status != 200: + raise CertificateOperationError( + error=_('Unable to communicate with CMS (%s)') % + http_reason_phrase) + + # The result is an XML blob. Pull the certificate out of that + doc = xml.dom.minidom.parseString(http_body) + item_node = doc.getElementsByTagName("b64") + try: try: - try: - cert = item_node[0].childNodes[0].data - except IndexError: - raise RuntimeError("Certificate issuance failed") - finally: - doc.unlink() - - # base64-decode the result for uniformity - cert = base64.b64decode(cert) - - # Write the certificate to a file. It will be imported in a later - # step. This file will be read later to be imported. - f = open(cert_fname, "w") - f.write(cert) - f.close() + cert = item_node[0].childNodes[0].data + except IndexError: + raise RuntimeError("Certificate issuance failed") + finally: + doc.unlink() - return + # base64-decode the result for uniformity + cert = base64.b64decode(cert) + + # Write the certificate to a file. It will be imported in a later + # step. This file will be read later to be imported. + f = open(cert_fname, "w") + f.write(cert) + f.close() def issue_signing_cert(self, certreq_fname, cert_fname): self.setup_cert_request() - if self.self_signed_ca: - p = subprocess.Popen(["/usr/bin/certutil", - "-d", self.secdir, - "-C", "-c", self.cacert_name, - "-i", certreq_fname, - "-o", cert_fname, - "-m", next_serial(), - "-v", self.valid_months, - "-f", self.passwd_fname, - "-1", "-5"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - - # Bah - this sucks, but I guess it isn't possible to fully - # control this with command line arguments. - # - # What this is requesting is: - # -1 (Create key usage extension) - # 0 - Digital Signature - # 5 - Cert signing key - # 9 - done - # n - not critical - # - # -5 (Create netscape cert type extension) - # 3 - Object Signing - # 9 - done - # n - not critical - p.stdin.write("0\n5\n9\nn\n3\n9\nn\n") - p.wait() - else: - if self.host_name is None: - raise RuntimeError("CA Host is not set.") - - f = open(certreq_fname, "r") - csr = f.readlines() - f.close() - csr = "".join(csr) - - # We just want the CSR bits, make sure there is no thing else - csr = pkcs10.strip_header(csr) - params = {'profileId': 'caJarSigningCert', - 'cert_request_type': 'pkcs10', - 'requestor_name': 'IPA Installer', - 'cert_request': csr, - 'xmlOutput': 'true'} + if self.host_name is None: + raise RuntimeError("CA Host is not set.") - # Send the request to the CA - f = open(self.passwd_fname, "r") - password = f.readline() - f.close() - result = dogtag.https_request( - self.host_name, - api.env.ca_ee_install_port or - dogtag.configured_constants().EE_SECURE_PORT, - "/ca/ee/ca/profileSubmitSSLClient", - self.secdir, password, "ipaCert", **params) - http_status, http_reason_phrase, http_headers, http_body = result - if http_status != 200: - raise RuntimeError("Unable to submit cert request") - - # The result is an XML blob. Pull the certificate out of that - doc = xml.dom.minidom.parseString(http_body) - item_node = doc.getElementsByTagName("b64") - cert = item_node[0].childNodes[0].data - doc.unlink() + f = open(certreq_fname, "r") + csr = f.readlines() + f.close() + csr = "".join(csr) - # base64-decode the cert for uniformity - cert = base64.b64decode(cert) + # We just want the CSR bits, make sure there is no thing else + csr = pkcs10.strip_header(csr) - # Write the certificate to a file. It will be imported in a later - # step. This file will be read later to be imported. - f = open(cert_fname, "w") - f.write(cert) - f.close() + params = {'profileId': 'caJarSigningCert', + 'cert_request_type': 'pkcs10', + 'requestor_name': 'IPA Installer', + 'cert_request': csr, + 'xmlOutput': 'true'} - return + # Send the request to the CA + f = open(self.passwd_fname, "r") + password = f.readline() + f.close() + result = dogtag.https_request( + self.host_name, + api.env.ca_ee_install_port or + dogtag.configured_constants().EE_SECURE_PORT, + "/ca/ee/ca/profileSubmitSSLClient", + self.secdir, password, "ipaCert", **params) + http_status, http_reason_phrase, http_headers, http_body = result + if http_status != 200: + raise RuntimeError("Unable to submit cert request") + + # The result is an XML blob. Pull the certificate out of that + doc = xml.dom.minidom.parseString(http_body) + item_node = doc.getElementsByTagName("b64") + cert = item_node[0].childNodes[0].data + doc.unlink() + + # base64-decode the cert for uniformity + cert = base64.b64decode(cert) + + # Write the certificate to a file. It will be imported in a later + # step. This file will be read later to be imported. + f = open(cert_fname, "w") + f.write(cert) + f.close() def add_cert(self, cert_fname, nickname): """ @@ -1020,48 +774,11 @@ class CertDB(object): """ root_nicknames = self.nssdb.get_trust_chain(nickname) - # Try to work around a change in the F-11 certutil where untrusted - # CA's are not shown in the chain. This will make a default IPA - # server installable. - if len(root_nicknames) == 0 and self.self_signed_ca: - return [self.cacert_name] - return root_nicknames def find_root_cert_from_pkcs12(self, pkcs12_fname, passwd_fname=None): - """Given a PKCS#12 file, try to find any certificates that do - not have a key. The assumption is that these are the root CAs. - """ - args = ["/usr/bin/pk12util", "-d", self.secdir, - "-l", pkcs12_fname, - "-k", passwd_fname] - if passwd_fname: - args = args + ["-w", passwd_fname] - try: - (stdout, stderr, returncode) = ipautil.run(args) - except ipautil.CalledProcessError, e: - if e.returncode == 17: - raise RuntimeError("incorrect password") - else: - raise RuntimeError("unknown error using pkcs#12 file") - - lines = stdout.split('\n') - - # A simple state machine. - # 1 = looking for "Certificate:" - # 2 = looking for the Friendly name (nickname) - nicknames = [] - state = 1 - for line in lines: - if state == 2: - m = re.match("\W+Friendly Name: (.*)", line) - if m: - nicknames.append( m.groups(0)[0]) - state = 1 - if line == "Certificate:": - state = 2 - - return nicknames + return self.nssdb.find_root_cert_from_pkcs12(pkcs12_fname, + passwd_fname=passwd_fname) def trust_root_cert(self, root_nickname): if root_nickname is None: @@ -1097,14 +814,6 @@ class CertDB(object): "-in", pem_fname, "-out", pkcs12_fname, "-passout", "file:" + pkcs12_pwd_fname]) - def create_self_signed(self, passwd=None): - self.create_noise_file() - self.create_passwd_file(passwd) - self.create_certdbs() - self.create_ca_cert() - self.export_ca_cert(self.cacert_name, True) - self.create_pin_file() - def create_from_cacert(self, cacert_fname, passwd=None): if ipautil.file_exists(self.certdb_fname): # We already have a cert db, see if it is for the same CA. @@ -1167,94 +876,6 @@ class CertDB(object): self.create_pin_file() self.export_ca_cert(nickname, False) - self.self_signed_ca=False - - # This file implies that we have our own self-signed CA. Ensure - # that it no longer exists (from previous installs, for example). - try: - os.remove(CA_SERIALNO) - 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=DN(('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 = str(self.subject_base).replace(",", "/") - esc_subject = DN(('CN', '%s/%s' % (nickname, base))) - - ipautil.run(["/usr/bin/openssl", "req", "-new", - "-config", reqcfg, - "-subj", str(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 install_pem_from_p12(self, p12_fname, p12_pwd_fname, pem_fname): ipautil.run(["/usr/bin/openssl", "pkcs12", "-nodes", diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 4b0c580a..e6bb054d 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -36,7 +36,7 @@ import certs import ldap from ipaserver.install import ldapupdate from ipaserver.install import replication -from ipalib import errors, api +from ipalib import errors from ipapython.dn import DN SERVER_ROOT_64 = "/usr/lib64/dirsrv" @@ -228,8 +228,7 @@ class DsInstance(service.Service): self.step("configuring directory to start on boot", self.__enable) def init_info(self, realm_name, fqdn, domain_name, dm_password, - self_signed_ca, subject_base, idstart, idmax, pkcs12_info, - ca_file=None): + subject_base, idstart, idmax, pkcs12_info, ca_file=None): self.realm_name = realm_name.upper() self.serverid = realm_to_serverid(self.realm_name) self.suffix = ipautil.realm_to_suffix(self.realm_name) @@ -237,7 +236,6 @@ class DsInstance(service.Service): self.dm_password = dm_password self.domain = domain_name self.principal = "ldap/%s@%s" % (self.fqdn, self.realm_name) - self.self_signed_ca = False self.subject_base = subject_base self.idstart = idstart self.idmax = idmax @@ -247,11 +245,11 @@ class DsInstance(service.Service): self.__setup_sub_dict() def create_instance(self, realm_name, fqdn, domain_name, - dm_password, pkcs12_info=None, self_signed_ca=False, + dm_password, pkcs12_info=None, idstart=1100, idmax=999999, subject_base=None, hbac_allow=True, ca_file=None): self.init_info( - realm_name, fqdn, domain_name, dm_password, self_signed_ca, + realm_name, fqdn, domain_name, dm_password, subject_base, idstart, idmax, pkcs12_info, ca_file=ca_file) self.__common_setup() @@ -282,7 +280,7 @@ class DsInstance(service.Service): idmax = 1100 self.init_info( - realm_name, fqdn, domain_name, dm_password, None, None, + realm_name, fqdn, domain_name, dm_password, None, idstart, idmax, pkcs12_info, ca_file=ca_file) self.master_fqdn = master_fqdn @@ -545,30 +543,21 @@ class DsInstance(service.Service): # We only handle one server cert nickname = server_certs[0][0] self.dercert = dsdb.get_cert_from_db(nickname, pem=False) - if api.env.enable_ra: - dsdb.track_server_cert( - nickname, self.principal, dsdb.passwd_fname, - 'restart_dirsrv %s' % self.serverid) + dsdb.track_server_cert(nickname, self.principal, dsdb.passwd_fname, + 'restart_dirsrv %s' % self.serverid) else: nickname = self.nickname cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) - if self.self_signed_ca: - dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) - self.dercert = dsdb.create_server_cert(nickname, self.fqdn, cadb) - dsdb.track_server_cert( - nickname, self.principal, dsdb.passwd_fname, - 'restart_dirsrv %s' % self.serverid) - dsdb.create_pin_file() - else: - # FIXME, need to set this nickname in the RA plugin - cadb.export_ca_cert('ipaCert', False) - dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) - self.dercert = dsdb.create_server_cert( - nickname, self.fqdn, cadb) - dsdb.track_server_cert( - nickname, self.principal, dsdb.passwd_fname, - 'restart_dirsrv %s' % self.serverid) - dsdb.create_pin_file() + + # FIXME, need to set this nickname in the RA plugin + cadb.export_ca_cert('ipaCert', False) + dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) + self.dercert = dsdb.create_server_cert( + nickname, self.fqdn, cadb) + dsdb.track_server_cert( + nickname, self.principal, dsdb.passwd_fname, + 'restart_dirsrv %s' % self.serverid) + dsdb.create_pin_file() conn = ipaldap.IPAdmin(self.fqdn) conn.do_simple_bind(DN(('cn', 'directory manager')), self.dm_password) diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index e134fbef..6da212ce 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -63,15 +63,13 @@ class HTTPInstance(service.Service): def create_instance(self, realm, fqdn, domain_name, dm_password=None, autoconfig=True, pkcs12_info=None, - self_signed_ca=False, subject_base=None, - auto_redirect=True, ca_file=None): + subject_base=None, auto_redirect=True, ca_file=None): self.fqdn = fqdn self.realm = realm self.domain = domain_name self.dm_password = dm_password self.suffix = ipautil.realm_to_suffix(self.realm) self.pkcs12_info = pkcs12_info - self.self_signed_ca = self_signed_ca self.principal = "HTTP/%s@%s" % (self.fqdn, self.realm) self.dercert = None self.subject_base = subject_base @@ -237,9 +235,7 @@ class HTTPInstance(service.Service): print "Adding Include conf.d/ipa-rewrite to %s failed." % NSS_CONF def __setup_ssl(self): - fqdn = None - if not self.self_signed_ca: - fqdn = self.fqdn + fqdn = self.fqdn ca_db = certs.CertDB(self.realm, host_name=fqdn, subject_base=self.subject_base) @@ -262,8 +258,6 @@ class HTTPInstance(service.Service): self.__set_mod_nss_nickname(nickname) else: - if self.self_signed_ca: - db.create_from_cacert(ca_db.cacert_fname) db.create_password_conf() self.dercert = db.create_server_cert(self.cert_nickname, self.fqdn, @@ -288,13 +282,6 @@ class HTTPInstance(service.Service): ipaservices.restore_context(certs.NSS_DIR + "/cert8.db") ipaservices.restore_context(certs.NSS_DIR + "/key3.db") - # In case this got generated as part of the install, reset the - # context - if ipautil.file_exists(certs.CA_SERIALNO): - ipaservices.restore_context(certs.CA_SERIALNO) - os.chown(certs.CA_SERIALNO, 0, pent.pw_gid) - os.chmod(certs.CA_SERIALNO, 0664) - def __setup_autoconfig(self): target_fname = '/usr/share/ipa/html/preferences.html' ipautil.copy_template_file( diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py index d047890b..b6b06333 100644 --- a/ipaserver/install/ipa_replica_prepare.py +++ b/ipaserver/install/ipa_replica_prepare.py @@ -130,13 +130,6 @@ class ReplicaPrepare(admintool.AdminTool): if api.env.host == self.replica_fqdn: raise admintool.ScriptError("You can't create a replica on itself") - # FIXME: certs.ipa_self_signed_master return value can be - # True, False, None, with different meanings. - # So, we need to explicitly compare to False - if certs.ipa_self_signed_master() == False: - raise admintool.ScriptError("A selfsign CA backend can only " - "prepare on the original master") - if not api.env.enable_ra and not options.http_pkcs12: raise admintool.ScriptError( "Cannot issue certificates: a CA is not installed. Use the " @@ -227,8 +220,7 @@ class ReplicaPrepare(admintool.AdminTool): options.reverse_zone, options.ip_address): raise admintool.ScriptError("Invalid reverse zone") - if (not certs.ipa_self_signed() and - not ipautil.file_exists( + if (not ipautil.file_exists( dogtag.configured_constants().CS_CFG_PATH) and not options.dirsrv_pin): self.log.info("If you installed IPA with your own certificates " @@ -281,17 +273,17 @@ class ReplicaPrepare(admintool.AdminTool): options.dirsrv_pkcs12) self.copy_info_file(options.dirsrv_pkcs12, "dscert.p12") else: - if not certs.ipa_self_signed(): - if ipautil.file_exists(options.ca_file): - self.copy_info_file(options.ca_file, "cacert.p12") - else: - raise admintool.ScriptError("Root CA PKCS#12 not " - "found in %s" % options.ca_file) + if ipautil.file_exists(options.ca_file): + self.copy_info_file(options.ca_file, "cacert.p12") + else: + raise admintool.ScriptError("Root CA PKCS#12 not " + "found in %s" % options.ca_file) + self.log.info( "Creating SSL certificate for the Directory Server") self.export_certdb("dscert", passwd_fname) - if not options.dirsrv_pkcs12 and not certs.ipa_self_signed(): + if not options.dirsrv_pkcs12: self.log.info( "Creating SSL certificate for the dogtag Directory Server") self.export_certdb("dogtagcert", passwd_fname) @@ -318,8 +310,7 @@ class ReplicaPrepare(admintool.AdminTool): self.export_certdb("httpcert", passwd_fname) self.log.info("Exporting RA certificate") - if not certs.ipa_self_signed(): - self.export_ra_pkcs12() + self.export_ra_pkcs12() def copy_pkinit_certificate(self): options = self.options @@ -464,19 +455,14 @@ class ReplicaPrepare(admintool.AdminTool): nickname = "Server-Cert" try: - self_signed = certs.ipa_self_signed() - db = certs.CertDB( api.env.realm, nssdir=self.dir, subject_base=subject_base) db.create_passwd_file() ca_db = certs.CertDB( api.env.realm, host_name=api.env.host, subject_base=subject_base) - if is_kdc: - ca_db.create_kdc_cert("KDC-Cert", hostname, self.dir) - else: - db.create_from_cacert(ca_db.cacert_fname) - db.create_server_cert(nickname, hostname, ca_db) + db.create_from_cacert(ca_db.cacert_fname) + db.create_server_cert(nickname, hostname, ca_db) pkcs12_fname = os.path.join(self.dir, fname + ".p12") diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py index 51c54273..6f9f1f5c 100644 --- a/ipaserver/install/krbinstance.py +++ b/ipaserver/install/krbinstance.py @@ -81,7 +81,6 @@ class KrbInstance(service.Service): self.kdc_password = None self.sub_dict = None self.pkcs12_info = None - self.self_signed_ca = None if fstore: self.fstore = fstore @@ -158,10 +157,9 @@ 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, realm_name, host_name, domain_name, admin_password, master_password, setup_pkinit=False, pkcs12_info=None, self_signed_ca=False, subject_base=None): + def create_instance(self, realm_name, host_name, domain_name, admin_password, master_password, setup_pkinit=False, pkcs12_info=None, 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(realm_name, host_name, domain_name, admin_password) @@ -189,9 +187,8 @@ class KrbInstance(service.Service): master_fqdn, host_name, domain_name, admin_password, setup_pkinit=False, pkcs12_info=None, - self_signed_ca=False, subject_base=None): + subject_base=None): self.pkcs12_info = pkcs12_info - self.self_signed_ca = self_signed_ca self.subject_base = subject_base self.master_fqdn = master_fqdn @@ -412,23 +409,15 @@ class KrbInstance(service.Service): self.move_service_to_host(host_principal) def __setup_pkinit(self): - if self.self_signed_ca: - ca_db = certs.CertDB(self.realm, - subject_base=self.subject_base) - else: - ca_db = certs.CertDB(self.realm, host_name=self.fqdn, - subject_base=self.subject_base) + ca_db = certs.CertDB(self.realm, host_name=self.fqdn, + subject_base=self.subject_base) if self.pkcs12_info: ca_db.install_pem_from_p12(self.pkcs12_info[0], self.pkcs12_info[1], "/var/kerberos/krb5kdc/kdc.pem") else: - if self.self_signed_ca: - ca_db.create_kdc_cert("KDC-Cert", self.fqdn, - "/var/kerberos/krb5kdc") - else: - raise RuntimeError("PKI not supported yet\n") + raise RuntimeError("PKI not supported yet\n") # Finally copy the cacert in the krb directory so we don't # have any selinux issues with the file context diff --git a/ipaserver/plugins/rabase.py b/ipaserver/plugins/rabase.py index 1d8713f4..aa379be6 100644 --- a/ipaserver/plugins/rabase.py +++ b/ipaserver/plugins/rabase.py @@ -44,11 +44,9 @@ class rabase(Backend): if api.env.in_tree: self.sec_dir = api.env.dot_ipa + os.sep + 'alias' self.pwd_file = self.sec_dir + os.sep + '.pwd' - self.serial_file = self.sec_dir + os.sep + 'ca_serialno' else: self.sec_dir = "/etc/httpd/alias" self.pwd_file = "/etc/httpd/alias/pwdfile.txt" - self.serial_file = certs.CA_SERIALNO super(rabase, self).__init__() diff --git a/ipaserver/plugins/selfsign.py b/ipaserver/plugins/selfsign.py deleted file mode 100644 index 8118d88c..00000000 --- a/ipaserver/plugins/selfsign.py +++ /dev/null @@ -1,230 +0,0 @@ -# Authors: -# Rob Crittenden -# John Dennis -# -# 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, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# 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, see . - -""" -Backend plugin for RA activities. - -The `ra` plugin provides access to the CA to issue, retrieve, and revoke -certificates via the following methods: - - * `ra.check_request_status()` - check certificate request status. - * `ra.get_certificate()` - retrieve an existing certificate. - * `ra.request_certificate()` - request a new certificate. - * `ra.revoke_certificate()` - revoke a certificate. - * `ra.take_certificate_off_hold()` - take a certificate off hold. -""" - -from ipalib import api, SkipPluginModule -if api.env.ra_plugin != 'selfsign': - # In this case, abort loading this plugin module... - raise SkipPluginModule(reason='selfsign is not selected as RA plugin, it is %s' % api.env.ra_plugin) -from ipalib import Backend -from ipalib import errors -from ipalib import x509 -from ipalib import pkcs10 -from ipapython.dn import DN, EditableDN, RDN -from ipapython.certdb import get_ca_nickname -import subprocess -import os -import re -from ipaserver.plugins import rabase -from ipaserver.install import certs -import tempfile -from ipalib import _ -from ipalib import api -from ipalib.plugins.cert import get_csr_hostname -from nss.error import NSPRError - -class ra(rabase.rabase): - """ - Request Authority backend plugin. - """ - - def request_certificate(self, csr, request_type='pkcs10'): - """ - :param csr: The certificate signing request. - :param request_type: The request type (defaults to ``'pkcs10'``). - - Submit certificate signing request. - - The command returns a dict with these possible key/value pairs. - Some key/value pairs may be absent. - - +---------------+---------------+---------------+ - |result name |result type |comments | - +===============+===============+===============+ - |serial_number |unicode [1]_ | | - +---------------+---------------+---------------+ - |certificate |unicode [2]_ | | - +---------------+---------------+---------------+ - |request_id |unicode | | - +---------------+---------------+---------------+ - |subject |unicode | | - +---------------+---------------+---------------+ - - .. [1] Passed through XMLRPC as decimal string. Can convert to - optimal integer type (int or long) via int(serial_number) - - .. [2] Base64 encoded - - """ - try: - config = api.Command['config_show']()['result'] - subject_base = EditableDN(config.get('ipacertificatesubjectbase')[0]) - hostname = get_csr_hostname(csr) - subject_base.insert(0, RDN(('CN', hostname))) - request = pkcs10.load_certificate_request(csr) - # python-nss normalizes the request subject - request_subject = DN(str(pkcs10.get_subject(request))) - - if subject_base != request_subject: - raise errors.CertificateOperationError(error=_('Request subject "%(request_subject)s" does not match the form "%(subject_base)s"') % \ - {'request_subject' : request_subject, 'subject_base' : subject_base}) - except errors.CertificateOperationError, e: - raise e - except NSPRError, e: - raise errors.CertificateOperationError(error=_('unable to decode csr: %s') % e) - - # certutil wants the CSR to have have a header and footer. Add one - # if it isn't there. - s = csr.find('-----BEGIN NEW CERTIFICATE REQUEST-----') - if s == -1: - s = csr.find('-----BEGIN CERTIFICATE REQUEST-----') - if s == -1: - csr = '-----BEGIN NEW CERTIFICATE REQUEST-----\n' + csr + \ - '\n-----END NEW CERTIFICATE REQUEST-----\n' - - try: - (csr_fd, csr_name) = tempfile.mkstemp() - os.write(csr_fd, csr) - os.close(csr_fd) - except Exception, e: - try: - os.remove(csr_name) - except: - pass - self.log.error('unable to create temporary csr file: %s' % e) - raise errors.CertificateOperationError(error=_('file operation')) - - try: - (cert_fd, cert_name) = tempfile.mkstemp() - os.close(cert_fd) - except Exception, e: - try: - os.remove(csr_name) - except: - pass - try: - os.remove(cert_name) - except: - pass - self.log.error('unable to create temporary certificate file: %s' % e) - raise errors.CertificateOperationError(error=_('file operation')) - - try: - serialno = certs.next_serial(self.serial_file) - except Exception, e: - try: - os.remove(csr_name) - except: - pass - try: - os.remove(cert_name) - except: - pass - self.log.error('next_serial() failed: %s' % e) - raise errors.CertificateOperationError(error=_('cannot obtain next serial number')) - - try: - args = [ - "/usr/bin/certutil", - "-C", - "-d", self.sec_dir, - "-c", get_ca_nickname(api.env.realm), - "-i", csr_name, - "-o", cert_name, - "-m", str(serialno), - "-v", "60", - "-1", - "-5", - "-6", - "-a", - "-f", self.pwd_file] - self.log.debug("issue cert: %s" % str(args)) - p = subprocess.Popen(args, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True) - p.stdin.write("0\n1\n2\n3\n9\ny\n") - p.stdin.write("0\n9\nn\n") - p.stdin.write("1\n9\nn\n") - (stdout, stderr) = p.communicate() - status = p.returncode - self.log.debug("stdout = %s" % stdout) - self.log.debug("stderr = %s" % stderr) - if status != 0: - try: - os.remove(cert_name) - except: - pass - self.log.error('certutil failed: %s' % stderr) - raise errors.CertificateOperationError(error=_('certutil failure')) - finally: - try: - os.remove(csr_name) - except: - pass - - try: - cert_fd = open(cert_name) - cert = cert_fd.read() - cert_fd.close() - finally: - try: - os.remove(cert_name) - except: - pass - - try: - subject = x509.get_subject(cert) - - serial = x509.get_serial_number(cert) - except NSPRError, e: - self.log.error('Unable to decode certificate in entry: %s' % str(e)) - raise errors.CertificateOperationError( - error=_('Unable to decode certificate in entry: %s') % str(e)) - - # To make it look like dogtag return just the base64 data. - cert = cert.replace('\n','') - cert = cert.replace('\r','') - s = cert.find('-----BEGIN CERTIFICATE-----') - e = cert.find('-----END CERTIFICATE-----') - s = s + 27 - cert = cert[s:e] - - cmd_result = {} - cmd_result['serial_number'] = unicode(serial) # convert long to decimal unicode string - cmd_result['serial_number_hex'] = u'0x%X' % serial - cmd_result['certificate'] = unicode(cert) - cmd_result['subject'] = unicode(subject) - - return cmd_result - -api.register(ra) -- cgit