def regenerate_ca_file(self, ca_file): dm_pwd_fd = ipautil.write_tmp_file(self.dirman_password) keydb_pwd = "" with open(paths.PKI_TOMCAT_PASSWORD_CONF) as f: for line in f.readlines(): key, value = line.strip().split("=") if key == "internal": keydb_pwd = value break keydb_pwd_fd = ipautil.write_tmp_file(keydb_pwd) ipautil.run( [ paths.PKCS12EXPORT, "-d", paths.PKI_TOMCAT_ALIAS_DIR, "-p", keydb_pwd_fd.name, "-w", dm_pwd_fd.name, "-o", ca_file, ] )
def synconce_ntp(server_fqdn, debug=False): """ Syncs time with specified server using ntpd. Primarily designed to be used before Kerberos setup to get time following the KDC time Returns True if sync was successful """ ntpd = paths.NTPD if not os.path.exists(ntpd): return False # The ntpd command will never exit if it is unable to reach the # server, so timeout after 15 seconds. timeout = 15 tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn) args = [paths.BIN_TIMEOUT, str(timeout), ntpd, '-qgc', tmp_ntp_conf.name] if debug: args.append('-d') try: logger.info('Attempting to sync time using ntpd. ' 'Will timeout after %d seconds', timeout) ipautil.run(args) return True except ipautil.CalledProcessError as e: if e.returncode == 124: logger.debug('Process did not complete before timeout') return False
def __create_instance(self): pent = pwd.getpwnam(DS_USER) self.backup_state("serverid", self.serverid) self.fstore.backup_file(paths.SYSCONFIG_DIRSRV) self.sub_dict['BASEDC'] = self.realm.split('.')[0].lower() base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict) root_logger.debug(base_txt) target_fname = paths.DIRSRV_BOOT_LDIF base_fd = open(target_fname, "w") base_fd.write(base_txt) base_fd.close() # Must be readable for dirsrv os.chmod(target_fname, 0440) os.chown(target_fname, pent.pw_uid, pent.pw_gid) inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict) root_logger.debug("writing inf template") inf_fd = ipautil.write_tmp_file(inf_txt) inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt) root_logger.debug(inf_txt) if ipautil.file_exists(paths.SETUP_DS_PL): args = [paths.SETUP_DS_PL, "--silent", "--logfile", "-", "-f", inf_fd.name] root_logger.debug("calling setup-ds.pl") else: args = [paths.DS_NEWINST_PL, inf_fd.name] root_logger.debug("calling ds_newinst.pl") try: ipautil.run(args) root_logger.debug("completed creating ds instance") except ipautil.CalledProcessError, e: root_logger.critical("failed to create ds instance %s" % e)
def check_chain(self, pkcs12_filename, pkcs12_pin, nssdb): # create a temp nssdb with NSSDatabase() as tempnssdb: db_password = ipautil.ipa_generate_password() db_pwdfile = ipautil.write_tmp_file(db_password) tempnssdb.create_db(db_pwdfile.name) # import the PKCS12 file, then delete all CA certificates # this leaves only the server certs in the temp db tempnssdb.import_pkcs12( pkcs12_filename, db_pwdfile.name, pkcs12_pin) for nickname, flags in tempnssdb.list_certs(): if 'u' not in flags: while tempnssdb.has_nickname(nickname): tempnssdb.delete_cert(nickname) # import all the CA certs from nssdb into the temp db for nickname, flags in nssdb.list_certs(): if 'u' not in flags: cert = nssdb.get_cert_from_db(nickname) tempnssdb.add_cert(cert, nickname, flags) # now get the server certs from tempnssdb and check their validity try: for nick, flags in tempnssdb.find_server_certs(): tempnssdb.verify_server_cert_validity(nick, api.env.host) except ValueError as e: raise admintool.ScriptError( "Peer's certificate issuer is not trusted (%s). " "Please run ipa-cacert-manage install and ipa-certupdate " "to install the CA certificate." % str(e))
def validate_options(self): options = self.options super(Backup, self).validate_options(needs_root=True) installutils.check_server_configuration() if options.gpg_keyring is not None: print( "--gpg-keyring is no longer supported, use GNUPGHOME " "environment variable to use a custom GnuPG2 directory.", file=sys.stderr ) options.gpg = True if options.online and not options.data_only: self.option_parser.error("You cannot specify --online " "without --data") if options.gpg: tmpfd = write_tmp_file('encryptme') newfile = encrypt_file(tmpfd.name, False) os.unlink(newfile) if options.data_only and options.logs: self.option_parser.error("You cannot specify --data " "with --logs")
def __create_instance(self): pent = pwd.getpwnam(DS_USER) self.backup_state("serverid", self.serverid) self.fstore.backup_file("/etc/sysconfig/dirsrv") self.sub_dict['BASEDC'] = self.realm.split('.')[0].lower() base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict) root_logger.debug(base_txt) target_fname = '/var/lib/dirsrv/boot.ldif' base_fd = open(target_fname, "w") base_fd.write(base_txt) base_fd.close() # Must be readable for dirsrv os.chmod(target_fname, 0440) os.chown(target_fname, pent.pw_uid, pent.pw_gid) inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict) root_logger.debug("writing inf template") inf_fd = ipautil.write_tmp_file(inf_txt) inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt) root_logger.debug(inf_txt) if ipautil.file_exists("/usr/sbin/setup-ds.pl"): args = ["/usr/sbin/setup-ds.pl", "--silent", "--logfile", "-", "-f", inf_fd.name] root_logger.debug("calling setup-ds.pl") else: args = ["/usr/bin/ds_newinst.pl", inf_fd.name] root_logger.debug("calling ds_newinst.pl") try: ipautil.run(args) root_logger.debug("completed creating ds instance") except ipautil.CalledProcessError, e: root_logger.critical("failed to create ds instance %s" % e)
def execute(self, ldapuri, bindpw, **options): ldap = self.api.Backend.ldap2 self.normalize_options(options) config = ldap.get_ipa_config() ds_base_dn = options.get('basedn') if ds_base_dn is not None: assert isinstance(ds_base_dn, DN) # check if migration mode is enabled if config.get('ipamigrationenabled', ('FALSE', ))[0] == 'FALSE': return dict(result={}, failed={}, enabled=False, compat=True) # connect to DS ds_ldap = ldap2(self.api, ldap_uri=ldapuri) cacert = None if options.get('cacertfile') is not None: # store CA cert into file tmp_ca_cert_f = write_tmp_file(options['cacertfile']) cacert = tmp_ca_cert_f.name # start TLS connection ds_ldap.connect(bind_dn=options['binddn'], bind_pw=bindpw, cacert=cacert) tmp_ca_cert_f.close() else: ds_ldap.connect(bind_dn=options['binddn'], bind_pw=bindpw) # check whether the compat plugin is enabled if not options.get('compat'): try: ldap.get_entry(DN(('cn', 'compat'), (api.env.basedn))) return dict(result={}, failed={}, enabled=True, compat=False) except errors.NotFound: pass if not ds_base_dn: # retrieve base DN from remote LDAP server entries, _truncated = ds_ldap.find_entries( '', ['namingcontexts', 'defaultnamingcontext'], DN(''), ds_ldap.SCOPE_BASE, size_limit=-1, time_limit=0, ) if 'defaultnamingcontext' in entries[0]: ds_base_dn = DN(entries[0]['defaultnamingcontext'][0]) assert isinstance(ds_base_dn, DN) else: try: ds_base_dn = DN(entries[0]['namingcontexts'][0]) assert isinstance(ds_base_dn, DN) except (IndexError, KeyError) as e: raise Exception(str(e)) # migrate! (migrated, failed) = self.migrate( ldap, config, ds_ldap, ds_base_dn, options ) return dict(result=migrated, failed=failed, enabled=True, compat=True)
def import_pkcs12(self, pkcs12_filename, pkcs12_passwd=None): args = [ "-i", pkcs12_filename, "-k", self.pwd_file, "-v" ] pkcs12_password_file = None if pkcs12_passwd is not None: pkcs12_password_file = ipautil.write_tmp_file(pkcs12_passwd + '\n') args.extend(["-w", pkcs12_password_file.name]) try: self.run_pk12util(args) except ipautil.CalledProcessError as e: if e.returncode == 17 or e.returncode == 18: raise Pkcs12ImportIncorrectPasswordError( "incorrect password for pkcs#12 file %s" % pkcs12_filename) elif e.returncode == 10: raise Pkcs12ImportOpenError( "Failed to open %s" % pkcs12_filename) else: raise Pkcs12ImportUnknownError( "unknown error import pkcs#12 file %s" % pkcs12_filename) finally: if pkcs12_password_file is not None: pkcs12_password_file.close()
def execute(self, ldapuri, bindpw, **options): ldap = self.api.Backend.ldap2 self.normalize_options(options) config = ldap.get_ipa_config()[1] ds_base_dn = options.get('basedn') if ds_base_dn is not None: assert isinstance(ds_base_dn, DN) # check if migration mode is enabled if config.get('ipamigrationenabled', ('FALSE', ))[0] == 'FALSE': return dict(result={}, failed={}, enabled=False, compat=True) # connect to DS ds_ldap = ldap2(shared_instance=False, ldap_uri=ldapuri, base_dn='') cacert = None if options.get('cacertfile') is not None: #store CA cert into file tmp_ca_cert_f = write_tmp_file(options['cacertfile']) cacert = tmp_ca_cert_f.name #start TLS connection ds_ldap.connect(bind_dn=options['binddn'], bind_pw=bindpw, tls_cacertfile=cacert) tmp_ca_cert_f.close() else: ds_ldap.connect(bind_dn=options['binddn'], bind_pw=bindpw) #check whether the compat plugin is enabled if not options.get('compat'): try: (dn,check_compat) = ldap.get_entry(_compat_dn) assert isinstance(dn, DN) if check_compat is not None and \ check_compat.get('nsslapd-pluginenabled', [''])[0].lower() == 'on': return dict(result={}, failed={}, enabled=True, compat=False) except errors.NotFound: pass if not ds_base_dn: # retrieve base DN from remote LDAP server entries, truncated = ds_ldap.find_entries( '', ['namingcontexts', 'defaultnamingcontext'], DN(''), ds_ldap.SCOPE_BASE, size_limit=-1, time_limit=0, ) if 'defaultnamingcontext' in entries[0][1]: ds_base_dn = DN(entries[0][1]['defaultnamingcontext'][0]) assert isinstance(ds_base_dn, DN) else: try: ds_base_dn = DN(entries[0][1]['namingcontexts'][0]) assert isinstance(ds_base_dn, DN) except (IndexError, KeyError), e: raise StandardError(str(e))
def install(self): print("Installing CA certificate, please wait") options = self.options cert_filename = self.args[1] nss_cert = None try: try: nss_cert = x509.load_certificate_from_file(cert_filename) except IOError as e: raise admintool.ScriptError( "Can't open \"%s\": %s" % (cert_filename, e)) except (TypeError, NSPRError, ValueError) as e: raise admintool.ScriptError("Not a valid certificate: %s" % e) subject = nss_cert.subject cert = nss_cert.der_data finally: del nss_cert nickname = options.nickname or str(subject) ca_certs = certstore.get_ca_certs_nss(api.Backend.ldap2, api.env.basedn, api.env.realm, False) with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(cert, nickname, 'C,,') for ca_cert, ca_nickname, ca_trust_flags in ca_certs: tmpdb.add_cert(ca_cert, ca_nickname, ca_trust_flags) try: tmpdb.verify_ca_cert_validity(nickname) except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_flags = options.trust_flags if ((set(trust_flags) - set(',CPTcgpuw')) or len(trust_flags.split(',')) != 3): raise admintool.ScriptError("Invalid trust flags") try: certstore.put_ca_cert_nss( api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) except ValueError as e: raise admintool.ScriptError( "Failed to install the certificate: %s" % e) print("CA certificate successfully installed")
def regenerate_ca_file(self, ca_file): dm_pwd_fd = ipautil.write_tmp_file(self.dirman_password) keydb_pwd = '' with open(paths.PKI_TOMCAT_PASSWORD_CONF) as f: for line in f.readlines(): key, value = line.strip().split('=') if key == 'internal': keydb_pwd = value break keydb_pwd_fd = ipautil.write_tmp_file(keydb_pwd) ipautil.run([ paths.PKCS12EXPORT, '-d', paths.PKI_TOMCAT_ALIAS_DIR, '-p', keydb_pwd_fd.name, '-w', dm_pwd_fd.name, '-o', ca_file ])
def regenerate_ca_file(self, ca_file): dm_pwd_fd = ipautil.write_tmp_file(self.dirman_password) keydb_pwd = '' with open('/etc/pki/pki-tomcat/password.conf') as f: for line in f.readlines(): key, value = line.strip().split('=') if key == 'internal': keydb_pwd = value break keydb_pwd_fd = ipautil.write_tmp_file(keydb_pwd) ipautil.run([ '/usr/bin/PKCS12Export', '-d', '/etc/pki/pki-tomcat/alias/', '-p', keydb_pwd_fd.name, '-w', dm_pwd_fd.name, '-o', ca_file ])
def _ldap_mod(self, ldif, sub_dict=None, raise_on_err=False): pw_name = None fd = None path = ipautil.SHARE_DIR + ldif nologlist = [] if sub_dict is not None: txt = ipautil.template_file(path, sub_dict) fd = ipautil.write_tmp_file(txt) path = fd.name # do not log passwords if 'PASSWORD' in sub_dict: nologlist.append(sub_dict['PASSWORD']) if 'RANDOM_PASSWORD' in sub_dict: nologlist.append(sub_dict['RANDOM_PASSWORD']) args = [paths.LDAPMODIFY, "-v", "-f", path] # As we always connect to the local host, # use URI of admin connection if not self.admin_conn: self.ldap_connect() args += ["-H", self.admin_conn.ldap_uri] # If DM password is available, use it if self.dm_password: [pw_fd, pw_name] = tempfile.mkstemp() os.write(pw_fd, self.dm_password) os.close(pw_fd) auth_parms = ["-x", "-D", "cn=Directory Manager", "-y", pw_name] # Use GSSAPI auth when not using DM password or not being root elif os.getegid() != 0: auth_parms = ["-Y", "GSSAPI"] # Default to EXTERNAL auth mechanism else: auth_parms = ["-Y", "EXTERNAL"] args += auth_parms try: try: ipautil.run(args, nolog=nologlist) except ipautil.CalledProcessError as e: if raise_on_err: raise root_logger.critical("Failed to load %s: %s" % (ldif, str(e))) finally: if pw_name: os.remove(pw_name) if fd is not None: fd.close()
def export_ra_pkcs12(self): if (os.path.exists(paths.RA_AGENT_PEM) and os.path.exists(paths.RA_AGENT_KEY)): with ipautil.write_tmp_file(self.dirman_password) as f: ipautil.run([ paths.OPENSSL, "pkcs12", "-export", "-inkey", paths.RA_AGENT_KEY, "-in", paths.RA_AGENT_PEM, "-out", os.path.join(self.dir, "ra.p12"), "-passout", "file:{pwfile}".format(pwfile=f.name) ])
def _ldap_mod(self, ldif, sub_dict=None, raise_on_err=True, ldap_uri=None, dm_password=None): pw_name = None fd = None path = os.path.join(paths.USR_SHARE_IPA_DIR, ldif) nologlist = [] if sub_dict is not None: txt = ipautil.template_file(path, sub_dict) fd = ipautil.write_tmp_file(txt) path = fd.name # do not log passwords if 'PASSWORD' in sub_dict: nologlist.append(sub_dict['PASSWORD']) if 'RANDOM_PASSWORD' in sub_dict: nologlist.append(sub_dict['RANDOM_PASSWORD']) args = [paths.LDAPMODIFY, "-v", "-f", path] # As we always connect to the local host, # use URI of admin connection if not ldap_uri: ldap_uri = api.Backend.ldap2.ldap_uri args += ["-H", ldap_uri] if dm_password: with tempfile.NamedTemporaryFile( mode='w', delete=False) as pw_file: pw_file.write(dm_password) pw_name = pw_file.name auth_parms = ["-x", "-D", "cn=Directory Manager", "-y", pw_name] # Use GSSAPI auth when not using DM password or not being root elif os.getegid() != 0: auth_parms = ["-Y", "GSSAPI"] # Default to EXTERNAL auth mechanism else: auth_parms = ["-Y", "EXTERNAL"] args += auth_parms try: try: ipautil.run(args, nolog=nologlist) except ipautil.CalledProcessError as e: root_logger.critical("Failed to load %s: %s" % (ldif, str(e))) if raise_on_err: raise finally: if pw_name: os.remove(pw_name)
def install_key_from_p12( p12_fname, p12_passwd, pem_fname, out_passwd_fname=None): pwd = ipautil.write_tmp_file(p12_passwd) args = [ paths.OPENSSL, "pkcs12", "-nocerts", "-in", p12_fname, "-out", pem_fname, "-passin", "file:" + pwd.name] if out_passwd_fname is not None: args.extend(['-passout', 'file:{}'.format(out_passwd_fname)]) else: args.append('-nodes') ipautil.run(args, umask=0o077)
def execute(self, ldapuri, bindpw, **options): ldap = self.api.Backend.ldap2 self.normalize_options(options) config = ldap.get_ipa_config() ds_base_dn = options.get("basedn") if ds_base_dn is not None: assert isinstance(ds_base_dn, DN) # check if migration mode is enabled if config.get("ipamigrationenabled", ("FALSE",))[0] == "FALSE": return dict(result={}, failed={}, enabled=False, compat=True) # connect to DS ds_ldap = ldap2(self.api, ldap_uri=ldapuri) cacert = None if options.get("cacertfile") is not None: # store CA cert into file tmp_ca_cert_f = write_tmp_file(options["cacertfile"]) cacert = tmp_ca_cert_f.name # start TLS connection ds_ldap.connect(bind_dn=options["binddn"], bind_pw=bindpw, tls_cacertfile=cacert) tmp_ca_cert_f.close() else: ds_ldap.connect(bind_dn=options["binddn"], bind_pw=bindpw) # check whether the compat plugin is enabled if not options.get("compat"): try: ldap.get_entry(DN(("cn", "compat"), (api.env.basedn))) return dict(result={}, failed={}, enabled=True, compat=False) except errors.NotFound: pass if not ds_base_dn: # retrieve base DN from remote LDAP server entries, truncated = ds_ldap.find_entries( "", ["namingcontexts", "defaultnamingcontext"], DN(""), ds_ldap.SCOPE_BASE, size_limit=-1, time_limit=0 ) if "defaultnamingcontext" in entries[0]: ds_base_dn = DN(entries[0]["defaultnamingcontext"][0]) assert isinstance(ds_base_dn, DN) else: try: ds_base_dn = DN(entries[0]["namingcontexts"][0]) assert isinstance(ds_base_dn, DN) except (IndexError, KeyError), e: raise StandardError(str(e))
def synconce_ntp(server_fqdn): """ Syncs time with specified server using ntpd. Primarily designed to be used before Kerberos setup to get time following the KDC time Returns True if sync was successful """ ntpd = '/usr/sbin/ntpd' if not os.path.exists(ntpd): return False tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn) try: ipautil.run([ntpd, '-qgc', tmp_ntp_conf.name]) return True except ipautil.CalledProcessError: return False
def install_check(api, replica_config, options): if replica_config is not None and not replica_config.setup_kra: return kra = krainstance.KRAInstance(api.env.realm) if kra.is_installed(): raise RuntimeError("KRA is already installed.") if not options.setup_ca: if cainstance.is_ca_installed_locally(): if api.env.dogtag_version >= 10: # correct dogtag version of CA installed pass else: raise RuntimeError( "Dogtag must be version 10.2 or above to install KRA") else: raise RuntimeError( "Dogtag CA is not installed. Please install the CA first") if replica_config is not None: if not api.Command.kra_is_enabled()['result']: raise RuntimeError( "KRA is not installed on the master system. Please use " "'ipa-kra-install' command to install the first instance.") if options.promote: return with certdb.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.import_pkcs12(replica_config.dir + "/cacert.p12", pw.name, replica_config.dirman_password) kra_cert_nicknames = [ "storageCert cert-pki-kra", "transportCert cert-pki-kra", "auditSigningCert cert-pki-kra" ] if not all(tmpdb.has_nickname(nickname) for nickname in kra_cert_nicknames): raise RuntimeError("Missing KRA certificates, please create a " "new replica file.")
def pkcs12_to_certkeys(p12_fname, p12_passwd=None): """ Deserializes pkcs12 file to python objects :param p12_fname: A PKCS#12 filename :param p12_passwd: Optional password for the pkcs12_fname file """ args = [paths.OPENSSL, "pkcs12", "-in", p12_fname, "-nodes"] if p12_passwd: pwd = ipautil.write_tmp_file(p12_passwd) args.extend(["-passin", "file:{fname}".format(fname=pwd.name)]) else: args.extend(["-passin", "pass:"]) pems = ipautil.run(args, capture_output=True).raw_output certs = x509.load_certificate_list(pems) priv_keys = x509.load_private_key_list(pems) return (certs, priv_keys)
def __create_instance(self): pent = pwd.getpwnam(DS_USER) self.backup_state("serverid", self.serverid) self.fstore.backup_file(paths.SYSCONFIG_DIRSRV) self.sub_dict['BASEDC'] = self.realm.split('.')[0].lower() base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict) logger.debug("%s", base_txt) target_fname = paths.DIRSRV_BOOT_LDIF base_fd = open(target_fname, "w") base_fd.write(base_txt) base_fd.close() # Must be readable for dirsrv os.chmod(target_fname, 0o440) os.chown(target_fname, pent.pw_uid, pent.pw_gid) inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict) logger.debug("writing inf template") inf_fd = ipautil.write_tmp_file(inf_txt) inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt) logger.debug("%s", inf_txt) args = [ paths.SETUP_DS_PL, "--silent", "--logfile", "-", "-f", inf_fd.name, ] logger.debug("calling setup-ds.pl") try: ipautil.run(args) logger.debug("completed creating DS instance") except ipautil.CalledProcessError as e: raise RuntimeError("failed to create DS instance %s" % e) # check for open port 389 from now on self.open_ports.append(389) inf_fd.close() os.remove(paths.DIRSRV_BOOT_LDIF)
def migrate_to_mod_ssl(self): """For upgrades only, migrate from mod_nss to mod_ssl""" db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR) nickname = self.get_mod_nss_nickname() with tempfile.NamedTemporaryFile() as temp: pk12_password = ipautil.ipa_generate_password() pk12_pwdfile = ipautil.write_tmp_file(pk12_password) db.export_pkcs12(temp.name, pk12_pwdfile.name, nickname) certs.install_pem_from_p12(temp.name, pk12_password, paths.HTTPD_CERT_FILE) passwd_fname = paths.HTTPD_PASSWD_FILE_FMT.format( host=api.env.host) with open(passwd_fname, 'wb') as passwd_file: os.fchmod(passwd_file.fileno(), 0o600) passwd_file.write( ipautil.ipa_generate_password().encode('utf-8')) certs.install_key_from_p12(temp.name, pk12_password, paths.HTTPD_KEY_FILE, out_passwd_fname=passwd_fname) self.backup_ssl_conf() self.configure_mod_ssl_certs() self.set_mod_ssl_protocol() self.set_mod_ssl_logdir() self.__add_include() self.cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) if self.ca_is_configured: db.untrack_server_cert(nickname) self.start_tracking_certificates() # remove nickname and CA certs from NSS db self.disable_nss_conf()
def import_pkcs12(self, pkcs12_filename, pkcs12_passwd=None): args = [PK12UTIL, "-d", self.secdir, "-i", pkcs12_filename, "-k", self.pwd_file, '-v'] pkcs12_password_file = None if pkcs12_passwd is not None: pkcs12_password_file = ipautil.write_tmp_file(pkcs12_passwd + '\n') args = args + ["-w", pkcs12_password_file.name] try: ipautil.run(args) except ipautil.CalledProcessError as e: if e.returncode == 17: raise RuntimeError("incorrect password for pkcs#12 file %s" % pkcs12_filename) elif e.returncode == 10: raise RuntimeError("Failed to open %s" % pkcs12_filename) else: raise RuntimeError("unknown error import pkcs#12 file %s" % pkcs12_filename) finally: if pkcs12_password_file is not None: pkcs12_password_file.close()
def validate_options(self): options = self.options super(Backup, self).validate_options(needs_root=True) installutils.check_server_configuration() if options.gpg_keyring is not None: if not os.path.exists(options.gpg_keyring + '.pub'): raise admintool.ScriptError('No such key %s' % options.gpg_keyring) options.gpg = True if options.online and not options.data_only: self.option_parser.error("You cannot specify --online " "without --data") if options.gpg: tmpfd = write_tmp_file('encryptme') newfile = encrypt_file(tmpfd.name, options.gpg_keyring, False) os.unlink(newfile) if options.data_only and options.logs: self.option_parser.error("You cannot specify --data " "with --logs")
def synconce_ntp(server_fqdn): """ Syncs time with specified server using ntpd. Primarily designed to be used before Kerberos setup to get time following the KDC time Returns True if sync was successful """ ntpd = paths.NTPD if not os.path.exists(ntpd): return False tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn) try: # The ntpd command will never exit if it is unable to reach the # server, so timeout after 15 seconds. timeout = 15 root_logger.info('Attempting to sync time using ntpd. ' 'Will timeout after %d seconds' % timeout) ipautil.run([ntpd, '-qgc', tmp_ntp_conf.name], timeout=timeout) return True except ipautil.CalledProcessError: return False
def export_pkcs12(self, nickname, pkcs12_filename, pkcs12_passwd=None): args = [ "-o", pkcs12_filename, "-n", nickname, "-k", self.pwd_file ] pkcs12_password_file = None if pkcs12_passwd is not None: pkcs12_password_file = ipautil.write_tmp_file(pkcs12_passwd + '\n') args.extend(["-w", pkcs12_password_file.name]) try: self.run_pk12util(args) except ipautil.CalledProcessError as e: if e.returncode == 17: raise RuntimeError("incorrect password for pkcs#12 file %s" % pkcs12_filename) elif e.returncode == 10: raise RuntimeError("Failed to open %s" % pkcs12_filename) else: raise RuntimeError("unknown error exporting pkcs#12 file %s" % pkcs12_filename) finally: if pkcs12_password_file is not None: pkcs12_password_file.close()
def test_from_json_file(self): file = write_tmp_file(json.dumps(self.get_input_dict())) conf = config.Config.from_env({'IPATEST_JSON_CONFIG': file.name}) assert_deepequal(self.get_output_dict(), conf.to_dict()) self.check_config(conf)
def install_key_from_p12(p12_fname, p12_passwd, pem_fname): pwd = ipautil.write_tmp_file(p12_passwd) ipautil.run([paths.OPENSSL, "pkcs12", "-nodes", "-nocerts", "-in", p12_fname, "-out", pem_fname, "-passin", "file:" + pwd.name], umask=0o077)
def import_files(self, files, db_password_filename, import_keys=False, key_password=None, key_nickname=None): """ Import certificates and a single private key from multiple files The files may be in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. :param files: Names of files to import :param db_password_filename: Name of file containing the database password :param import_keys: Whether to import private keys :param key_password: Password to decrypt private keys :param key_nickname: Nickname of the private key to import from PKCS#12 files """ key_file = None extracted_key = None extracted_certs = '' for filename in files: try: with open(filename, 'rb') as f: data = f.read() except IOError as e: raise RuntimeError("Failed to open %s: %s" % (filename, e.strerror)) # Try to parse the file as PEM file matches = list( re.finditer(r'-----BEGIN (.+?)-----(.*?)-----END \1-----', data, re.DOTALL)) if matches: loaded = False for match in matches: body = match.group() label = match.group(1) line = len(data[:match.start() + 1].splitlines()) if label in ('CERTIFICATE', 'X509 CERTIFICATE', 'X.509 CERTIFICATE'): try: x509.load_certificate(match.group(2)) except NSPRError as e: if label != 'CERTIFICATE': root_logger.warning( "Skipping certificate in %s at line %s: %s", filename, line, e) continue else: extracted_certs += body + '\n' loaded = True continue if label in ('PKCS7', 'PKCS #7 SIGNED DATA', 'CERTIFICATE'): args = [ paths.OPENSSL, 'pkcs7', '-print_certs', ] try: result = ipautil.run(args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: if label == 'CERTIFICATE': root_logger.warning( "Skipping certificate in %s at line %s: %s", filename, line, e) else: root_logger.warning( "Skipping PKCS#7 in %s at line %s: %s", filename, line, e) continue else: extracted_certs += result.output + '\n' loaded = True continue if label in ('PRIVATE KEY', 'ENCRYPTED PRIVATE KEY', 'RSA PRIVATE KEY', 'DSA PRIVATE KEY', 'EC PRIVATE KEY'): if not import_keys: continue if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) args = [ paths.OPENSSL, 'pkcs8', '-topk8', '-passout', 'file:' + db_password_filename, ] if ((label != 'PRIVATE KEY' and key_password) or label == 'ENCRYPTED PRIVATE KEY'): key_pwdfile = ipautil.write_tmp_file(key_password) args += [ '-passin', 'file:' + key_pwdfile.name, ] try: result = ipautil.run(args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: root_logger.warning( "Skipping private key in %s at line %s: %s", filename, line, e) continue else: extracted_key = result.output key_file = filename loaded = True continue if loaded: continue raise RuntimeError("Failed to load %s" % filename) # Try to load the file as DER certificate try: x509.load_certificate(data, x509.DER) except NSPRError: pass else: data = x509.make_pem(base64.b64encode(data)) extracted_certs += data + '\n' continue # Try to import the file as PKCS#12 file if import_keys: try: self.import_pkcs12(filename, db_password_filename, key_password) except RuntimeError: pass else: if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) key_file = filename server_certs = self.find_server_certs() if key_nickname: for nickname, _trust_flags in server_certs: if nickname == key_nickname: break else: raise RuntimeError( "Server certificate \"%s\" not found in %s" % (key_nickname, filename)) else: if len(server_certs) > 1: raise RuntimeError( "%s server certificates found in %s, " "expecting only one" % (len(server_certs), filename)) continue raise RuntimeError("Failed to load %s" % filename) if import_keys and not key_file: raise RuntimeError("No server certificates found in %s" % (', '.join(files))) nss_certs = x509.load_certificate_list(extracted_certs) nss_cert = None for nss_cert in nss_certs: nickname = str(nss_cert.subject) self.add_cert(nss_cert.der_data, nickname, ',,') del nss_certs, nss_cert if extracted_key: in_file = ipautil.write_tmp_file(extracted_certs + extracted_key) out_file = tempfile.NamedTemporaryFile() out_password = ipautil.ipa_generate_password() out_pwdfile = ipautil.write_tmp_file(out_password) args = [ paths.OPENSSL, 'pkcs12', '-export', '-in', in_file.name, '-out', out_file.name, '-passin', 'file:' + db_password_filename, '-passout', 'file:' + out_pwdfile.name, ] try: ipautil.run(args) except ipautil.CalledProcessError as e: raise RuntimeError( "No matching certificate found for private key from %s" % key_file) self.import_pkcs12(out_file.name, db_password_filename, out_password)
def import_files(self, files, import_keys=False, key_password=None, key_nickname=None): """ Import certificates and a single private key from multiple files The files may be in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. :param files: Names of files to import :param import_keys: Whether to import private keys :param key_password: Password to decrypt private keys :param key_nickname: Nickname of the private key to import from PKCS#12 files """ key_file = None extracted_key = None extracted_certs = [] for filename in files: try: with open(filename, 'rb') as f: data = f.read() except IOError as e: raise RuntimeError("Failed to open %s: %s" % (filename, e.strerror)) # Try to parse the file as PEM file matches = list( re.finditer(br'-----BEGIN (.+?)-----(.*?)-----END \1-----', data, re.DOTALL)) if matches: loaded = False for match in matches: body = match.group() label = match.group(1) line = len(data[:match.start() + 1].splitlines()) if label in (b'CERTIFICATE', b'X509 CERTIFICATE', b'X.509 CERTIFICATE'): try: cert = x509.load_pem_x509_certificate(body) except ValueError as e: if label != b'CERTIFICATE': logger.warning( "Skipping certificate in %s at line %s: " "%s", filename, line, e) continue else: extracted_certs.append(cert) loaded = True continue if label in (b'PKCS7', b'PKCS #7 SIGNED DATA', b'CERTIFICATE'): try: certs = x509.pkcs7_to_certs(body) except ipautil.CalledProcessError as e: if label == b'CERTIFICATE': logger.warning( "Skipping certificate in %s at line %s: " "%s", filename, line, e) else: logger.warning( "Skipping PKCS#7 in %s at line %s: %s", filename, line, e) continue else: extracted_certs.extend(certs) loaded = True continue if label in (b'PRIVATE KEY', b'ENCRYPTED PRIVATE KEY', b'RSA PRIVATE KEY', b'DSA PRIVATE KEY', b'EC PRIVATE KEY'): if not import_keys: continue if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) # the args -v2 aes256 -v2prf hmacWithSHA256 are needed # on OpenSSL 1.0.2 (fips mode). As soon as FreeIPA # requires OpenSSL 1.1.0 we'll be able to drop them args = [ paths.OPENSSL, 'pkcs8', '-topk8', '-v2', 'aes256', '-v2prf', 'hmacWithSHA256', '-passout', 'file:' + self.pwd_file, ] if ((label != b'PRIVATE KEY' and key_password) or label == b'ENCRYPTED PRIVATE KEY'): key_pwdfile = ipautil.write_tmp_file(key_password) args += [ '-passin', 'file:' + key_pwdfile.name, ] try: result = ipautil.run(args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: logger.warning( "Skipping private key in %s at line %s: %s", filename, line, e) continue else: extracted_key = result.raw_output key_file = filename loaded = True continue if loaded: continue raise RuntimeError("Failed to load %s" % filename) # Try to load the file as DER certificate try: cert = x509.load_der_x509_certificate(data) except ValueError: pass else: extracted_certs.append(cert) continue # Try to import the file as PKCS#12 file if import_keys: try: self.import_pkcs12(filename, key_password) except Pkcs12ImportUnknownError: # the file may not be a PKCS#12 file, # go to the generic error about unrecognized format pass except RuntimeError as e: raise RuntimeError("Failed to load %s: %s" % (filename, str(e))) else: if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) key_file = filename server_certs = self.find_server_certs() if key_nickname: for nickname, _trust_flags in server_certs: if nickname == key_nickname: break else: raise RuntimeError( "Server certificate \"%s\" not found in %s" % (key_nickname, filename)) else: if len(server_certs) > 1: raise RuntimeError( "%s server certificates found in %s, " "expecting only one" % (len(server_certs), filename)) continue # Supported formats were tried but none succeeded raise RuntimeError("Failed to load %s: unrecognized format" % filename) if import_keys and not key_file: raise RuntimeError("No server certificates found in %s" % (', '.join(files))) for cert in extracted_certs: nickname = str(DN(cert.subject)) self.add_cert(cert, nickname, EMPTY_TRUST_FLAGS) if extracted_key: with tempfile.NamedTemporaryFile() as in_file, \ tempfile.NamedTemporaryFile() as out_file: for cert in extracted_certs: in_file.write(cert.public_bytes(x509.Encoding.PEM)) in_file.write(extracted_key) in_file.flush() out_password = ipautil.ipa_generate_password() out_pwdfile = ipautil.write_tmp_file(out_password) args = [ paths.OPENSSL, 'pkcs12', '-export', '-in', in_file.name, '-out', out_file.name, '-passin', 'file:' + self.pwd_file, '-passout', 'file:' + out_pwdfile.name, '-certpbe', 'aes-128-cbc', '-keypbe', 'aes-128-cbc', ] try: ipautil.run(args) except ipautil.CalledProcessError as e: raise RuntimeError( "No matching certificate found for private key from " "%s" % key_file) self.import_pkcs12(out_file.name, out_password)
def load_pkcs12(cert_files, key_password, key_nickname, ca_cert_files, host_name=None, realm_name=None): """ Load and verify server certificate and private key from multiple files The files are accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. :param cert_files: Names of server certificate and private key files to import :param key_password: Password to decrypt private keys :param key_nickname: Nickname of the private key to import from PKCS#12 files :param ca_cert_files: Names of CA certificate files to import :param host_name: Host name of the server :returns: Temporary PKCS#12 file with the server certificate, private key and CA certificate chain, password to unlock the PKCS#12 file and the CA certificate of the CA that issued the server certificate """ with certs.NSSDatabase() as nssdb: nssdb.create_db() try: nssdb.import_files(cert_files, True, key_password, key_nickname) except RuntimeError as e: raise ScriptError(str(e)) if ca_cert_files: try: nssdb.import_files(ca_cert_files) except RuntimeError as e: raise ScriptError(str(e)) for nickname, trust_flags in nssdb.list_certs(): if trust_flags.has_key: key_nickname = nickname continue nssdb.trust_root_cert(nickname, EXTERNAL_CA_TRUST_FLAGS) # Check we have the whole cert chain & the CA is in it trust_chain = list(reversed(nssdb.get_trust_chain(key_nickname))) ca_cert = None for nickname in trust_chain[1:]: cert = nssdb.get_cert(nickname) if ca_cert is None: ca_cert = cert subject = DN(cert.subject) issuer = DN(cert.issuer) if subject == issuer: break else: raise ScriptError( "The full certificate chain is not present in %s" % (", ".join(cert_files))) # verify CA validity and pathlen. The trust_chain list is in reverse # order. trust_chain[1] is the first intermediate CA cert and must # have pathlen >= 0. for minpathlen, nickname in enumerate(trust_chain[1:], start=0): try: nssdb.verify_ca_cert_validity(nickname, minpathlen) except ValueError as e: raise ScriptError("CA certificate %s in %s is not valid: %s" % (subject, ", ".join(cert_files), e)) if host_name is not None: try: nssdb.verify_server_cert_validity(key_nickname, host_name) except ValueError as e: raise ScriptError( "The server certificate in %s is not valid: %s" % (", ".join(cert_files), e)) if realm_name is not None: try: nssdb.verify_kdc_cert_validity(key_nickname, realm_name) except ValueError as e: raise ScriptError( "The KDC certificate in %s is not valid: %s" % (", ".join(cert_files), e)) out_file = tempfile.NamedTemporaryFile() out_password = ipautil.ipa_generate_password() out_pwdfile = ipautil.write_tmp_file(out_password) args = [ paths.PK12UTIL, '-o', out_file.name, '-n', key_nickname, '-d', nssdb.secdir, '-k', nssdb.pwd_file, '-w', out_pwdfile.name, ] ipautil.run(args) return out_file, out_password, ca_cert
def install_pem_from_p12(p12_fname, p12_passwd, pem_fname): pwd = ipautil.write_tmp_file(p12_passwd) ipautil.run([ paths.OPENSSL, "pkcs12", "-nokeys", "-clcerts", "-in", p12_fname, "-out", pem_fname, "-passin", "file:" + pwd.name ])
def import_files(self, files, import_keys=False, key_password=None, key_nickname=None): """ Import certificates and a single private key from multiple files The files may be in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. :param files: Names of files to import :param import_keys: Whether to import private keys :param key_password: Password to decrypt private keys :param key_nickname: Nickname of the private key to import from PKCS#12 files """ key_file = None extracted_key = None extracted_certs = [] for filename in files: try: with open(filename, 'rb') as f: data = f.read() except IOError as e: raise RuntimeError( "Failed to open %s: %s" % (filename, e.strerror)) # Try to parse the file as PEM file matches = list( re.finditer( br'-----BEGIN (.+?)-----(.*?)-----END \1-----', data, re.DOTALL ) ) if matches: loaded = False for match in matches: body = match.group() label = match.group(1) line = len(data[:match.start() + 1].splitlines()) if label in (b'CERTIFICATE', b'X509 CERTIFICATE', b'X.509 CERTIFICATE'): try: cert = x509.load_pem_x509_certificate(body) except ValueError as e: if label != b'CERTIFICATE': logger.warning( "Skipping certificate in %s at line %s: " "%s", filename, line, e) continue else: extracted_certs.append(cert) loaded = True continue if label in (b'PKCS7', b'PKCS #7 SIGNED DATA', b'CERTIFICATE'): try: certs = x509.pkcs7_to_certs(body) except ipautil.CalledProcessError as e: if label == b'CERTIFICATE': logger.warning( "Skipping certificate in %s at line %s: " "%s", filename, line, e) else: logger.warning( "Skipping PKCS#7 in %s at line %s: %s", filename, line, e) continue else: extracted_certs.extend(certs) loaded = True continue if label in (b'PRIVATE KEY', b'ENCRYPTED PRIVATE KEY', b'RSA PRIVATE KEY', b'DSA PRIVATE KEY', b'EC PRIVATE KEY'): if not import_keys: continue if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) # the args -v2 aes256 -v2prf hmacWithSHA256 are needed # on OpenSSL 1.0.2 (fips mode). As soon as FreeIPA # requires OpenSSL 1.1.0 we'll be able to drop them args = [ paths.OPENSSL, 'pkcs8', '-topk8', '-v2', 'aes256', '-v2prf', 'hmacWithSHA256', '-passout', 'file:' + self.pwd_file, ] if ((label != b'PRIVATE KEY' and key_password) or label == b'ENCRYPTED PRIVATE KEY'): key_pwdfile = ipautil.write_tmp_file(key_password) args += [ '-passin', 'file:' + key_pwdfile.name, ] try: result = ipautil.run( args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: logger.warning( "Skipping private key in %s at line %s: %s", filename, line, e) continue else: extracted_key = result.raw_output key_file = filename loaded = True continue if loaded: continue raise RuntimeError("Failed to load %s" % filename) # Try to load the file as DER certificate try: cert = x509.load_der_x509_certificate(data) except ValueError: pass else: extracted_certs.append(cert) continue # Try to import the file as PKCS#12 file if import_keys: try: self.import_pkcs12(filename, key_password) except RuntimeError: pass else: if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) key_file = filename server_certs = self.find_server_certs() if key_nickname: for nickname, _trust_flags in server_certs: if nickname == key_nickname: break else: raise RuntimeError( "Server certificate \"%s\" not found in %s" % (key_nickname, filename)) else: if len(server_certs) > 1: raise RuntimeError( "%s server certificates found in %s, " "expecting only one" % (len(server_certs), filename)) continue raise RuntimeError("Failed to load %s" % filename) if import_keys and not key_file: raise RuntimeError( "No server certificates found in %s" % (', '.join(files))) for cert in extracted_certs: nickname = str(DN(cert.subject)) self.add_cert(cert, nickname, EMPTY_TRUST_FLAGS) if extracted_key: with tempfile.NamedTemporaryFile() as in_file, \ tempfile.NamedTemporaryFile() as out_file: for cert in extracted_certs: in_file.write(cert.public_bytes(x509.Encoding.PEM)) in_file.write(extracted_key) in_file.flush() out_password = ipautil.ipa_generate_password() out_pwdfile = ipautil.write_tmp_file(out_password) args = [ paths.OPENSSL, 'pkcs12', '-export', '-in', in_file.name, '-out', out_file.name, '-passin', 'file:' + self.pwd_file, '-passout', 'file:' + out_pwdfile.name, ] try: ipautil.run(args) except ipautil.CalledProcessError as e: raise RuntimeError( "No matching certificate found for private key from " "%s" % key_file) self.import_pkcs12(out_file.name, out_password)
def execute(self, ldapuri, bindpw, **options): ldap = self.api.Backend.ldap2 self.normalize_options(options) config = ldap.get_ipa_config() ds_base_dn = options.get('basedn') if ds_base_dn is not None: assert isinstance(ds_base_dn, DN) # check if migration mode is enabled if config.get('ipamigrationenabled', ('FALSE', ))[0] == 'FALSE': return dict(result={}, failed={}, enabled=False, compat=True) # connect to DS cacert = None if options.get('cacertfile') is not None: # store CA cert into file tmp_ca_cert_f = write_tmp_file(options['cacertfile']) cacert = tmp_ca_cert_f.name # start TLS connection ds_ldap = LDAPClient(ldapuri, cacert=cacert) ds_ldap.simple_bind(options['binddn'], bindpw) tmp_ca_cert_f.close() else: ds_ldap = LDAPClient(ldapuri, cacert=cacert) ds_ldap.simple_bind(options['binddn'], bindpw) # check whether the compat plugin is enabled if not options.get('compat'): try: ldap.get_entry(DN(('cn', 'compat'), (api.env.basedn))) return dict(result={}, failed={}, enabled=True, compat=False) except errors.NotFound: pass if not ds_base_dn: # retrieve base DN from remote LDAP server entries, _truncated = ds_ldap.find_entries( '', ['namingcontexts', 'defaultnamingcontext'], DN(''), ds_ldap.SCOPE_BASE, size_limit=-1, time_limit=0, ) if 'defaultnamingcontext' in entries[0]: ds_base_dn = DN(entries[0]['defaultnamingcontext'][0]) assert isinstance(ds_base_dn, DN) else: try: ds_base_dn = DN(entries[0]['namingcontexts'][0]) assert isinstance(ds_base_dn, DN) except (IndexError, KeyError) as e: raise Exception(str(e)) # migrate! (migrated, failed) = self.migrate(ldap, config, ds_ldap, ds_base_dn, options) return dict(result=migrated, failed=failed, enabled=True, compat=True)
def renew_external_step_2(self, ca, old_cert_der): print("Importing the renewed CA certificate, please wait") options = self.options conn = api.Backend.ldap2 cert_file, ca_file = installutils.load_external_cert( options.external_cert_files, x509.subject_base()) old_cert_obj = x509.load_certificate(old_cert_der, x509.DER) old_der_subject = x509.get_der_subject(old_cert_der, x509.DER) old_spki = old_cert_obj.public_key().public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo) with open(cert_file.name) as f: new_cert_data = f.read() new_cert_der = x509.normalize_certificate(new_cert_data) new_cert_obj = x509.load_certificate(new_cert_der, x509.DER) new_der_subject = x509.get_der_subject(new_cert_der, x509.DER) new_spki = new_cert_obj.public_key().public_bytes( serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo) if new_cert_obj.subject != old_cert_obj.subject: raise admintool.ScriptError( "Subject name mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") if new_der_subject != old_der_subject: raise admintool.ScriptError( "Subject name encoding mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") if new_spki != old_spki: raise admintool.ScriptError( "Subject public key info mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(old_cert_der, 'IPA CA', 'C,,') try: tmpdb.add_cert(new_cert_der, 'IPA CA', 'C,,') except ipautil.CalledProcessError as e: raise admintool.ScriptError( "Not compatible with the current CA certificate: %s" % e) ca_certs = x509.load_certificate_list_from_file(ca_file.name) for ca_cert in ca_certs: data = ca_cert.public_bytes(serialization.Encoding.DER) tmpdb.add_cert(data, str(DN(ca_cert.subject)), 'C,,') try: tmpdb.verify_ca_cert_validity('IPA CA') except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1] for nickname in trust_chain: try: ca_cert = tmpdb.get_cert(nickname) except RuntimeError: break certstore.put_ca_cert_nss(conn, api.env.basedn, ca_cert, nickname, ',,') dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: entry = conn.get_entry(dn, ['usercertificate']) entry['usercertificate'] = [new_cert_der] conn.update_entry(entry) except errors.NotFound: entry = conn.make_entry( dn, objectclass=['top', 'pkiuser', 'nscontainer'], cn=[self.cert_nickname], usercertificate=[new_cert_der]) conn.add_entry(entry) except errors.EmptyModlist: pass try: ca.set_renewal_master() except errors.NotFound: raise admintool.ScriptError("CA renewal master not found") self.resubmit_request(ca, 'ipaRetrieval') print("CA certificate successfully renewed")
def renew_external_step_2(self, ca, old_cert): print("Importing the renewed CA certificate, please wait") options = self.options conn = api.Backend.ldap2 cert_file, ca_file = installutils.load_external_cert( options.external_cert_files, x509.subject_base()) nss_cert = None nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR) try: nss_cert = x509.load_certificate(old_cert, x509.DER) subject = nss_cert.subject der_subject = x509.get_der_subject(old_cert, x509.DER) #pylint: disable=E1101 pkinfo = nss_cert.subject_public_key_info.format() #pylint: enable=E1101 nss_cert = x509.load_certificate_from_file(cert_file.name) cert = nss_cert.der_data if nss_cert.subject != subject: raise admintool.ScriptError( "Subject name mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") if x509.get_der_subject(cert, x509.DER) != der_subject: raise admintool.ScriptError( "Subject name encoding mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: disable=E1101 if nss_cert.subject_public_key_info.format() != pkinfo: raise admintool.ScriptError( "Subject public key info mismatch (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)") #pylint: enable=E1101 finally: del nss_cert nss.nss_shutdown() with certs.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) tmpdb.add_cert(old_cert, 'IPA CA', 'C,,') try: tmpdb.add_cert(cert, 'IPA CA', 'C,,') except ipautil.CalledProcessError as e: raise admintool.ScriptError( "Not compatible with the current CA certificate: %s" % e) ca_certs = x509.load_certificate_list_from_file(ca_file.name) for ca_cert in ca_certs: tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,') del ca_certs del ca_cert try: tmpdb.verify_ca_cert_validity('IPA CA') except ValueError as e: raise admintool.ScriptError( "Not a valid CA certificate: %s (visit " "http://www.freeipa.org/page/Troubleshooting for " "troubleshooting guide)" % e) trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1] for nickname in trust_chain: try: ca_cert = tmpdb.get_cert(nickname) except RuntimeError: break certstore.put_ca_cert_nss( conn, api.env.basedn, ca_cert, nickname, ',,') dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: entry = conn.get_entry(dn, ['usercertificate']) entry['usercertificate'] = [cert] conn.update_entry(entry) except errors.NotFound: entry = conn.make_entry( dn, objectclass=['top', 'pkiuser', 'nscontainer'], cn=[self.cert_nickname], usercertificate=[cert]) conn.add_entry(entry) except errors.EmptyModlist: pass try: ca.set_renewal_master() except errors.NotFound: raise admintool.ScriptError("CA renewal master not found") self.resubmit_request(ca, 'ipaRetrieval') print("CA certificate successfully renewed")