From c123264ac77cd533a08978909f837c8f4d3e224e Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Wed, 25 Sep 2013 08:33:35 +0000 Subject: Read passwords from stdin when importing PKCS#12 files with pk12util. This works around pk12util refusing to use empty password files, which prevents the use of PKCS#12 files with empty password. https://fedorahosted.org/freeipa/ticket/3897 --- install/tools/ipa-replica-install | 34 +++++++++++++++++++---------- install/tools/ipa-server-install | 9 +++----- ipaserver/install/certs.py | 22 ++++++++++--------- ipaserver/install/installutils.py | 4 ++-- ipaserver/install/ipa_replica_prepare.py | 3 +-- ipaserver/install/ipa_server_certinstall.py | 5 ++--- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 2a88c1021..5e6941402 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -149,16 +149,31 @@ def set_owner(config, dir): pw = pwd.getpwnam(dsinstance.DS_USER) os.chown(dir, pw.pw_uid, pw.pw_gid) + +def make_pkcs12_info(directory, cert_name, password_name): + """Make pkcs12_info + + :param directory: Base directory (config.dir) + :param cert_name: Cert filename (e.g. "dscert.p12") + :param password_name: Cert filename (e.g. "dirsrv_pin.txt") + :return: a (full cert path, password) tuple, or None if cert is not found + """ + cert_path = os.path.join(directory, cert_name) + if ipautil.file_exists(cert_path): + password_file = os.path.join(directory, password_name) + password = open(password_file).read().strip() + return cert_path, password + else: + return None + + def install_replica_ds(config): dsinstance.check_ports() # if we have a pkcs12 file, create the cert db from # that. Otherwise the ds setup will create the CA # cert - pkcs12_info = None - if ipautil.file_exists(config.dir + "/dscert.p12"): - pkcs12_info = (config.dir + "/dscert.p12", - config.dir + "/dirsrv_pin.txt") + pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12", "dirsrv_pin.txt") ds = dsinstance.DsInstance() ds.create_replica( @@ -178,10 +193,8 @@ def install_krb(config, setup_pkinit=False): krb = krbinstance.KrbInstance() #pkinit files - pkcs12_info = None - if ipautil.file_exists(config.dir + "/pkinitcert.p12"): - pkcs12_info = (config.dir + "/pkinitcert.p12", - config.dir + "/pkinit_pin.txt") + pkcs12_info = make_pkcs12_info(config.dir, "pkinitcert.p12", + "pkinit_pin.txt") krb.create_replica(config.realm_name, config.master_host_name, config.host_name, @@ -206,10 +219,7 @@ def install_http(config, auto_redirect): # if we have a pkcs12 file, create the cert db from # that. Otherwise the ds setup will create the CA # cert - pkcs12_info = None - if ipautil.file_exists(config.dir + "/httpcert.p12"): - pkcs12_info = (config.dir + "/httpcert.p12", - config.dir + "/http_pin.txt") + pkcs12_info = make_pkcs12_info(config.dir, "httpcert.p12", "http_pin.txt") memcache = memcacheinstance.MemcacheInstance() memcache.create_instance('MEMCACHE', config.host_name, config.dirman_password, ipautil.realm_to_suffix(config.realm_name)) diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index cf8d3d01b..aa424c377 100644 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -882,8 +882,7 @@ def main(): confirm=False, validate=False) if options.http_pin is None: sys.exit("%s unlock password required" % options.http_pkcs12) - http_pin_file = ipautil.write_tmp_file(options.http_pin) - http_pkcs12_info = (options.http_pkcs12, http_pin_file.name) + http_pkcs12_info = (options.http_pkcs12, options.http_pin) http_cert_name = installutils.check_pkcs12( http_pkcs12_info, ca_file, host_name) @@ -894,8 +893,7 @@ def main(): confirm=False, validate=False) if options.dirsrv_pin is None: sys.exit("%s unlock password required" % options.dirsrv_pkcs12) - dirsrv_pin_file = ipautil.write_tmp_file(options.dirsrv_pin) - dirsrv_pkcs12_info = (options.dirsrv_pkcs12, dirsrv_pin_file.name) + dirsrv_pkcs12_info = (options.dirsrv_pkcs12, options.dirsrv_pin) dirsrv_cert_name = installutils.check_pkcs12( dirsrv_pkcs12_info, ca_file, host_name) @@ -906,8 +904,7 @@ def main(): confirm=False, validate=False) if options.pkinit_pin is None: sys.exit("%s unlock password required" % options.pkinit_pkcs12) - pkinit_pin_file = ipautil.write_tmp_file(options.pkinit_pin) - pkinit_pkcs12_info = (options.pkinit_pkcs12, pkinit_pin_file.name) + pkinit_pkcs12_info = (options.pkinit_pkcs12, options.pkinit_pin) if not options.dm_password: dm_password = read_dm_password() diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index f1b92fdbe..9ee854ebf 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -176,14 +176,15 @@ class NSSDatabase(object): return root_nicknames def import_pkcs12(self, pkcs12_filename, db_password_filename, - pkcs_password_filename=None): + pkcs12_passwd=None): args = ["/usr/bin/pk12util", "-d", self.secdir, "-i", pkcs12_filename, "-k", db_password_filename, '-v'] - if pkcs_password_filename: - args = args + ["-w", pkcs_password_filename] + if pkcs12_passwd is not None: + pkcs12_passwd = pkcs12_passwd + '\n' + args = args + ["-w", "/dev/stdin"] try: - ipautil.run(args) + ipautil.run(args, stdin=pkcs12_passwd) except ipautil.CalledProcessError, e: if e.returncode == 17: raise RuntimeError("incorrect password for pkcs#12 file %s" % @@ -770,9 +771,9 @@ class CertDB(object): def find_server_certs(self): return self.nssdb.find_server_certs() - def import_pkcs12(self, pkcs12_fname, passwd_fname=None): + def import_pkcs12(self, pkcs12_fname, pkcs12_passwd=None): return self.nssdb.import_pkcs12(pkcs12_fname, self.passwd_fname, - pkcs_password_filename=passwd_fname) + pkcs12_passwd=pkcs12_passwd) def export_pkcs12(self, pkcs12_fname, pkcs12_pwd_fname, nickname=None): if nickname is None: @@ -814,7 +815,7 @@ class CertDB(object): self.create_certdbs() self.load_cacert(cacert_fname) - def create_from_pkcs12(self, pkcs12_fname, pkcs12_pwd_fname, passwd=None, + def create_from_pkcs12(self, pkcs12_fname, pkcs12_passwd, passwd=None, ca_file=None): """Create a new NSS database using the certificates in a PKCS#12 file. @@ -831,7 +832,7 @@ class CertDB(object): self.create_noise_file() self.create_passwd_file(passwd) self.create_certdbs() - self.import_pkcs12(pkcs12_fname, pkcs12_pwd_fname) + self.import_pkcs12(pkcs12_fname, pkcs12_passwd) server_certs = self.find_server_certs() if len(server_certs) == 0: raise RuntimeError("Could not find a suitable server cert in import in %s" % pkcs12_fname) @@ -854,10 +855,11 @@ class CertDB(object): self.create_pin_file() self.export_ca_cert(nickname, False) - def install_pem_from_p12(self, p12_fname, p12_pwd_fname, pem_fname): + def install_pem_from_p12(self, p12_fname, p12_passwd, pem_fname): + pwd = ipautil.write_tmp_file(p12_passwd) ipautil.run(["/usr/bin/openssl", "pkcs12", "-nodes", "-in", p12_fname, "-out", pem_fname, - "-passin", "file:" + p12_pwd_fname]) + "-passin", "file:" + pwd.name]) def publish_ca_cert(self, location): shutil.copy(self.cacert_fname, location) diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py index 67c3fa9be..67eabc258 100644 --- a/ipaserver/install/installutils.py +++ b/ipaserver/install/installutils.py @@ -720,7 +720,7 @@ def check_pkcs12(pkcs12_info, ca_file, hostname): Return a (server cert name, CA cert names) tuple """ - pkcs12_filename, pin_filename = pkcs12_info + pkcs12_filename, pkcs12_passwd = pkcs12_info root_logger.debug('Checking PKCS#12 certificate %s', pkcs12_filename) db_pwd_file = ipautil.write_tmp_file(ipautil.ipa_generate_password()) with certs.NSSDatabase() as nssdb: @@ -735,7 +735,7 @@ def check_pkcs12(pkcs12_info, ca_file, hostname): raise ScriptError(str(e)) # Import everything in the PKCS#12 - nssdb.import_pkcs12(pkcs12_filename, db_pwd_file.name, pin_filename) + nssdb.import_pkcs12(pkcs12_filename, db_pwd_file.name, pkcs12_passwd) # Check we have exactly one server cert (one with a private key) server_certs = nssdb.find_server_certs() diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py index 904b8727e..55b81eeec 100644 --- a/ipaserver/install/ipa_replica_prepare.py +++ b/ipaserver/install/ipa_replica_prepare.py @@ -137,9 +137,8 @@ class ReplicaPrepare(admintool.AdminTool): "could not find directory instance: %s" % config_dir) def check_pkcs12(self, pkcs12_file, pkcs12_pin): - pin_file = ipautil.write_tmp_file(pkcs12_pin) installutils.check_pkcs12( - pkcs12_info=(pkcs12_file, pin_file.name), + pkcs12_info=(pkcs12_file, pkcs12_pin), ca_file='/etc/ipa/ca.crt', hostname=self.replica_fqdn) diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py index a9563e095..1aa27b2e6 100644 --- a/ipaserver/install/ipa_server_certinstall.py +++ b/ipaserver/install/ipa_server_certinstall.py @@ -155,9 +155,8 @@ class ServerCertInstall(admintool.AdminTool): os.chown(os.path.join(dirname, 'secmod.db'), 0, pent.pw_gid) def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command): - pw = write_tmp_file(pkcs12_passwd) server_cert = installutils.check_pkcs12( - pkcs12_info=(self.pkcs12_fname, pw.name), + pkcs12_info=(self.pkcs12_fname, pkcs12_passwd), ca_file=CACERT, hostname=api.env.host) @@ -167,7 +166,7 @@ class ServerCertInstall(admintool.AdminTool): cdb.untrack_server_cert(old_cert) cdb.delete_cert(old_cert) - cdb.import_pkcs12(self.pkcs12_fname, pw.name) + cdb.import_pkcs12(self.pkcs12_fname, pkcs12_passwd) if api.env.enable_ra: cdb.track_server_cert(server_cert, principal, cdb.passwd_fname, -- cgit