Example #1
0
def makecert(reqdir, subject, principal):
    """
    Generate a certificate that can be used during unit testing.
    """

    ra = rabase.rabase(api)
    if (not os.path.exists(ra.sec_dir) and
            api.env.xmlrpc_uri == 'http://localhost:8888/ipa/xml'):
        raise AssertionError('The self-signed CA is not configured, '
                             'see ipatests/test_xmlrpc/test_cert.py')

    pwname = os.path.join(reqdir, "pwd")

    # Create an empty password file
    with open(pwname, "w") as fp:
        fp.write("\n")

    # Generate NSS cert database to store the private key for our CSR
    run_certutil(reqdir, ["-N", "-f", pwname])

    res = api.Command['config_show']()
    subject_base = res['result']['ipacertificatesubjectbase'][0]

    cert = None
    csr = unicode(generate_csr(reqdir, pwname, str(subject)))

    res = api.Command['cert_request'](csr, principal=principal, add=True)
    return x509.make_pem(res['result']['certificate'])
Example #2
0
def makecert(reqdir):
    """
    Generate a service certificate that can be used during unit testing.
    """

    ra = rabase.rabase()
    if (not os.path.exists(ra.sec_dir)
            and api.env.xmlrpc_uri == 'http://*****:*****@%s' % (api.env.host, api.env.realm)
    csr = unicode(generate_csr(reqdir, pwname, str(subject)))

    res = api.Command['cert_request'](csr, principal=princ, add=True)
    return x509.make_pem(res['result']['certificate'])
Example #3
0
    def list_users_by_cert(self, cert):
        """
        Look for users matching the cert.

        Call Users.ListByCertificate interface and return a dict
        with key = domain, value = list of uids
        corresponding to the users matching the provided cert
        :param cert: DER cert
        :raise RemoteRetrieveError: if DBus error occurs
        """
        try:
            pem = x509.make_pem(base64.b64encode(cert))
            # bug 3306 in sssd returns 0 entry when max_entries = 0
            # Temp workaround is to use a non-null value, not too high
            # to avoid reserving unneeded memory
            max_entries = dbus.UInt32(100)
            user_paths = self._users_iface.ListByCertificate(pem, max_entries)
            users = dict()
            for user_path in user_paths:
                user_obj = self._bus.get_object(DBUS_SSSD_NAME, user_path)
                user_iface = dbus.Interface(user_obj, DBUS_PROPERTY_IF)
                user_login = user_iface.Get(DBUS_SSSD_USER_IF, 'name')

                # Extract name@domain
                items = user_login.split('@')
                domain = api.env.realm if len(items) < 2 else items[1]
                name = items[0]

                # Retrieve the list of users for the given domain,
                # or initialize to an empty list
                # and add the name
                users_for_dom = users.setdefault(domain, list())
                users_for_dom.append(name)
            return users
        except dbus.DBusException as e:
            err_name = e.get_dbus_name()
            # If there is no matching user, do not consider this as an
            # exception and return an empty list
            if err_name == 'org.freedesktop.sssd.Error.NotFound':
                return dict()
            logger.error(
                'Failed to use interface %s. DBus '
                'exception is %s.', DBUS_SSSD_USERS_IF, e)
            raise errors.RemoteRetrieveError(
                reason=_('Failed to find users over SystemBus. '
                         ' See details in the error_log'))
Example #4
0
    def list_users_by_cert(self, cert):
        """
        Look for users matching the cert.

        Call Users.ListByCertificate interface and return a dict
        with key = domain, value = list of uids
        corresponding to the users matching the provided cert
        :param cert: DER cert
        :raise RemoteRetrieveError: if DBus error occurs
        """
        try:
            pem = x509.make_pem(base64.b64encode(cert))
            # bug 3306 in sssd returns 0 entry when max_entries = 0
            # Temp workaround is to use a non-null value, not too high
            # to avoid reserving unneeded memory
            max_entries = dbus.UInt32(100)
            user_paths = self._users_iface.ListByCertificate(pem, max_entries)
            users = dict()
            for user_path in user_paths:
                user_obj = self._bus.get_object(DBUS_SSSD_NAME, user_path)
                user_iface = dbus.Interface(user_obj, DBUS_PROPERTY_IF)
                user_login = user_iface.Get(DBUS_SSSD_USER_IF, 'name')

                # Extract name@domain
                items = user_login.split('@')
                domain = api.env.realm if len(items) < 2 else items[1]
                name = items[0]

                # Retrieve the list of users for the given domain,
                # or initialize to an empty list
                # and add the name
                users_for_dom = users.setdefault(domain, list())
                users_for_dom.append(name)
            return users
        except dbus.DBusException as e:
            err_name = e.get_dbus_name()
            # If there is no matching user, do not consider this as an
            # exception and return an empty list
            if err_name == 'org.freedesktop.sssd.Error.NotFound':
                return dict()
            logger.error(
                'Failed to use interface %s. DBus '
                'exception is %s.', DBUS_SSSD_USERS_IF, e)
            raise errors.RemoteRetrieveError(
                reason=_('Failed to find users over SystemBus. '
                         ' See details in the error_log'))
Example #5
0
    def forward(self, *args, **options):
        certificate_out = options.pop('certificate_out', None)
        if certificate_out is not None:
            util.check_writable_file(certificate_out)

        result = super(CertRetrieveOverride, self).forward(*args, **options)

        if certificate_out is not None:
            if options.get('chain', False):
                certs = result['result']['certificate_chain']
            else:
                certs = [result['result']['certificate']]
            certs = (x509.normalize_certificate(cert) for cert in certs)
            certs = (x509.make_pem(base64.b64encode(cert)) for cert in certs)
            with open(certificate_out, 'w') as f:
                f.write('\n'.join(certs))

        return result
Example #6
0
    def forward(self, *args, **options):
        if 'certificate_out' in options:
            certificate_out = options.pop('certificate_out')
            try:
                util.check_writable_file(certificate_out)
            except errors.FileError as e:
                raise errors.ValidationError(name='certificate-out',
                                             error=str(e))
        else:
            certificate_out = None

        result = super(CertRetrieveOverride, self).forward(*args, **options)

        if certificate_out is not None:
            if options.get('chain', False):
                certs = result['result']['certificate_chain']
            else:
                certs = [result['result']['certificate']]
            certs = (x509.normalize_certificate(cert) for cert in certs)
            certs = (x509.make_pem(base64.b64encode(cert)) for cert in certs)
            with open(certificate_out, 'w') as f:
                f.write('\n'.join(certs))

        return result
Example #7
0
    def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
        new_cacert_path = paths.SYSTEMWIDE_IPA_CA_CRT

        if os.path.exists(new_cacert_path):
            try:
                os.remove(new_cacert_path)
            except OSError as e:
                root_logger.error(
                    "Could not remove %s: %s", new_cacert_path, e)
                return False

        new_cacert_path = paths.IPA_P11_KIT

        try:
            f = open(new_cacert_path, 'w')
        except IOError as e:
            root_logger.info("Failed to open %s: %s" % (new_cacert_path, e))
            return False

        f.write("# This file was created by IPA. Do not edit.\n"
                "\n")

        has_eku = set()
        for cert, nickname, trusted, ext_key_usage in ca_certs:
            try:
                subject = x509.get_der_subject(cert, x509.DER)
                issuer = x509.get_der_issuer(cert, x509.DER)
                serial_number = x509.get_der_serial_number(cert, x509.DER)
                public_key_info = x509.get_der_public_key_info(cert, x509.DER)
            except (NSPRError, PyAsn1Error, ValueError) as e:
                root_logger.warning(
                    "Failed to decode certificate \"%s\": %s", nickname, e)
                continue

            label = urllib.parse.quote(nickname)
            subject = urllib.parse.quote(subject)
            issuer = urllib.parse.quote(issuer)
            serial_number = urllib.parse.quote(serial_number)
            public_key_info = urllib.parse.quote(public_key_info)

            cert = base64.b64encode(cert)
            cert = x509.make_pem(cert)

            obj = ("[p11-kit-object-v1]\n"
                   "class: certificate\n"
                   "certificate-type: x-509\n"
                   "certificate-category: authority\n"
                   "label: \"%(label)s\"\n"
                   "subject: \"%(subject)s\"\n"
                   "issuer: \"%(issuer)s\"\n"
                   "serial-number: \"%(serial_number)s\"\n"
                   "x-public-key-info: \"%(public_key_info)s\"\n" %
                   dict(label=label,
                        subject=subject,
                        issuer=issuer,
                        serial_number=serial_number,
                        public_key_info=public_key_info))
            if trusted is True:
                obj += "trusted: true\n"
            elif trusted is False:
                obj += "x-distrusted: true\n"
            obj += "%s\n\n" % cert
            f.write(obj)

            if ext_key_usage is not None and public_key_info not in has_eku:
                if not ext_key_usage:
                    ext_key_usage = {x509.EKU_PLACEHOLDER}
                try:
                    ext_key_usage = x509.encode_ext_key_usage(ext_key_usage)
                except PyAsn1Error as e:
                    root_logger.warning(
                        "Failed to encode extended key usage for \"%s\": %s",
                        nickname, e)
                    continue
                value = urllib.parse.quote(ext_key_usage)
                obj = ("[p11-kit-object-v1]\n"
                       "class: x-certificate-extension\n"
                       "label: \"ExtendedKeyUsage for %(label)s\"\n"
                       "x-public-key-info: \"%(public_key_info)s\"\n"
                       "object-id: 2.5.29.37\n"
                       "value: \"%(value)s\"\n\n" %
                       dict(label=label,
                            public_key_info=public_key_info,
                            value=value))
                f.write(obj)
                has_eku.add(public_key_info)

        f.close()

        # Add the CA to the systemwide CA trust database
        if not self.reload_systemwide_ca_store():
            return False

        return True
Example #8
0
    def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
        # pylint: disable=ipa-forbidden-import
        from ipalib import x509  # FixMe: break import cycle
        from ipalib.errors import CertificateError
        # pylint: enable=ipa-forbidden-import

        new_cacert_path = paths.SYSTEMWIDE_IPA_CA_CRT

        if os.path.exists(new_cacert_path):
            try:
                os.remove(new_cacert_path)
            except OSError as e:
                root_logger.error("Could not remove %s: %s", new_cacert_path,
                                  e)
                return False

        new_cacert_path = paths.IPA_P11_KIT

        try:
            f = open(new_cacert_path, 'w')
        except IOError as e:
            root_logger.info("Failed to open %s: %s" % (new_cacert_path, e))
            return False

        f.write("# This file was created by IPA. Do not edit.\n" "\n")

        has_eku = set()
        for cert, nickname, trusted, ext_key_usage in ca_certs:
            try:
                subject = x509.get_der_subject(cert, x509.DER)
                issuer = x509.get_der_issuer(cert, x509.DER)
                serial_number = x509.get_der_serial_number(cert, x509.DER)
                public_key_info = x509.get_der_public_key_info(cert, x509.DER)
            except (PyAsn1Error, ValueError, CertificateError) as e:
                root_logger.warning("Failed to decode certificate \"%s\": %s",
                                    nickname, e)
                continue

            label = urllib.parse.quote(nickname)
            subject = urllib.parse.quote(subject)
            issuer = urllib.parse.quote(issuer)
            serial_number = urllib.parse.quote(serial_number)
            public_key_info = urllib.parse.quote(public_key_info)

            cert = base64.b64encode(cert)
            cert = x509.make_pem(cert)

            obj = ("[p11-kit-object-v1]\n"
                   "class: certificate\n"
                   "certificate-type: x-509\n"
                   "certificate-category: authority\n"
                   "label: \"%(label)s\"\n"
                   "subject: \"%(subject)s\"\n"
                   "issuer: \"%(issuer)s\"\n"
                   "serial-number: \"%(serial_number)s\"\n"
                   "x-public-key-info: \"%(public_key_info)s\"\n" %
                   dict(label=label,
                        subject=subject,
                        issuer=issuer,
                        serial_number=serial_number,
                        public_key_info=public_key_info))
            if trusted is True:
                obj += "trusted: true\n"
            elif trusted is False:
                obj += "x-distrusted: true\n"
            obj += "%s\n\n" % cert
            f.write(obj)

            if ext_key_usage is not None and public_key_info not in has_eku:
                if not ext_key_usage:
                    ext_key_usage = {x509.EKU_PLACEHOLDER}
                try:
                    ext_key_usage = x509.encode_ext_key_usage(ext_key_usage)
                except PyAsn1Error as e:
                    root_logger.warning(
                        "Failed to encode extended key usage for \"%s\": %s",
                        nickname, e)
                    continue
                value = urllib.parse.quote(ext_key_usage)
                obj = ("[p11-kit-object-v1]\n"
                       "class: x-certificate-extension\n"
                       "label: \"ExtendedKeyUsage for %(label)s\"\n"
                       "x-public-key-info: \"%(public_key_info)s\"\n"
                       "object-id: 2.5.29.37\n"
                       "value: \"%(value)s\"\n\n" %
                       dict(label=label,
                            public_key_info=public_key_info,
                            value=value))
                f.write(obj)
                has_eku.add(public_key_info)

        f.close()

        # Add the CA to the systemwide CA trust database
        if not self.reload_systemwide_ca_store():
            return False

        return True
Example #9
0
    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)
Example #10
0
 def to_pem(x):
     return x509.make_pem(x)
Example #11
0
                issuer = x509.get_der_issuer(cert, x509.DER)
                serial_number = x509.get_der_serial_number(cert, x509.DER)
                public_key_info = x509.get_der_public_key_info(cert, x509.DER)
            except (NSPRError, PyAsn1Error), e:
                root_logger.warning(
                    "Failed to decode certificate \"%s\": %s", nickname, e)
                continue

            label = urllib.quote(nickname)
            subject = urllib.quote(subject)
            issuer = urllib.quote(issuer)
            serial_number = urllib.quote(serial_number)
            public_key_info = urllib.quote(public_key_info)

            cert = base64.b64encode(cert)
            cert = x509.make_pem(cert)

            obj = ("[p11-kit-object-v1]\n"
                   "class: certificate\n"
                   "certificate-type: x-509\n"
                   "certificate-category: authority\n"
                   "label: \"%(label)s\"\n"
                   "subject: \"%(subject)s\"\n"
                   "issuer: \"%(issuer)s\"\n"
                   "serial-number: \"%(serial_number)s\"\n"
                   "x-public-key-info: \"%(public_key_info)s\"\n" %
                   dict(label=label,
                        subject=subject,
                        issuer=issuer,
                        serial_number=serial_number,
                        public_key_info=public_key_info))
Example #12
0
                issuer = x509.get_der_issuer(cert, x509.DER)
                serial_number = x509.get_der_serial_number(cert, x509.DER)
                public_key_info = x509.get_der_public_key_info(cert, x509.DER)
            except (NSPRError, PyAsn1Error), e:
                root_logger.warning("Failed to decode certificate \"%s\": %s",
                                    nickname, e)
                continue

            label = urllib.quote(nickname)
            subject = urllib.quote(subject)
            issuer = urllib.quote(issuer)
            serial_number = urllib.quote(serial_number)
            public_key_info = urllib.quote(public_key_info)

            cert = base64.b64encode(cert)
            cert = x509.make_pem(cert)

            obj = ("[p11-kit-object-v1]\n"
                   "class: certificate\n"
                   "certificate-type: x-509\n"
                   "certificate-category: authority\n"
                   "label: \"%(label)s\"\n"
                   "subject: \"%(subject)s\"\n"
                   "issuer: \"%(issuer)s\"\n"
                   "serial-number: \"%(serial_number)s\"\n"
                   "x-public-key-info: \"%(public_key_info)s\"\n" %
                   dict(label=label,
                        subject=subject,
                        issuer=issuer,
                        serial_number=serial_number,
                        public_key_info=public_key_info))
Example #13
0
 def to_pem(x):
     return x509.make_pem(x)
Example #14
0
    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 ValueError 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 ValueError:
                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)))

        certs = x509.load_certificate_list(extracted_certs)
        for cert in certs:
            nickname = str(DN(cert.subject))
            data = cert.public_bytes(serialization.Encoding.DER)
            self.add_cert(data, nickname, ',,')

        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)