Exemple #1
0
    def test_1_load_der_cert(self):
        """
        Test loading a DER certificate.
        """

        der = base64.b64decode(goodcert)

        # Load a good cert
        x509.load_certificate(der, x509.DER)
Exemple #2
0
    def test_1_load_der_cert(self):
        """
        Test loading a DER certificate.
        """

        der = base64.b64decode(goodcert)

        # Load a good cert
        x509.load_certificate(der, x509.DER)
Exemple #3
0
    def test_Backend(self):
        """
        Test using the ldap2 Backend directly (ala ipa-server-install)
        """

        # Create our own api because the one generated for the tests is
        # a client-only api. Then we register in the commands and objects
        # we need for the test.
        myapi = create_api(mode=None)
        myapi.bootstrap(context='cli', in_server=True, confdir=paths.ETC_IPA)
        myapi.finalize()

        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            with open(pwfile, "r") as fp:
                dm_password = fp.read().rstrip()
        else:
            raise nose.SkipTest("No directory manager password in %s" % pwfile)
        myapi.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
                                    bind_pw=dm_password)

        result = myapi.Command['service_show']('ldap/%s@%s' % (
            api.env.host,
            api.env.realm,
        ))
        entry_attrs = result['result']
        cert = entry_attrs.get('usercertificate')
        cert = cert[0]
        serial = x509.load_certificate(cert, x509.DER).serial_number
        assert serial is not None
Exemple #4
0
def set_certificate_attrs(entry_attrs):
    """
    Set individual attributes from some values from a certificate.

    entry_attrs is a dict of an entry

    returns nothing
    """
    if not 'usercertificate' in entry_attrs:
        return
    if type(entry_attrs['usercertificate']) in (list, tuple):
        cert = entry_attrs['usercertificate'][0]
    else:
        cert = entry_attrs['usercertificate']
    cert = x509.normalize_certificate(cert)
    cert = x509.load_certificate(cert, datatype=x509.DER)
    entry_attrs['subject'] = unicode(cert.subject)
    entry_attrs['serial_number'] = unicode(cert.serial_number)
    entry_attrs['serial_number_hex'] = u'0x%X' % cert.serial_number
    entry_attrs['issuer'] = unicode(cert.issuer)
    entry_attrs['valid_not_before'] = unicode(cert.valid_not_before_str)
    entry_attrs['valid_not_after'] = unicode(cert.valid_not_after_str)
    entry_attrs['md5_fingerprint'] = unicode(
        nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
    entry_attrs['sha1_fingerprint'] = unicode(
        nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
Exemple #5
0
    def execute(self, serial_number, **kw):
        ca_enabled_check()

        # Make sure that the cert specified by issuer+serial exists.
        # Will raise NotFound if it does not.
        resp = api.Command.cert_show(unicode(serial_number), cacn=kw['cacn'])

        try:
            self.check_access()
        except errors.ACIError as acierr:
            self.debug(
                "Not granted by ACI to revoke certificate, looking at principal"
            )
            try:
                cert = x509.load_certificate(resp['result']['certificate'])
                if not bind_principal_can_manage_cert(cert):
                    raise acierr
            except errors.NotImplementedError:
                raise acierr
        revocation_reason = kw['revocation_reason']
        if revocation_reason == 7:
            raise errors.CertificateOperationError(
                error=_('7 is not a valid revocation reason'))
        return dict(
            # Dogtag lightweight CAs have shared serial number domain, so
            # we don't tell Dogtag the issuer (but we already checked that
            # the given serial was issued by the named ca).
            result=self.Backend.ra.revoke_certificate(
                str(serial_number), revocation_reason=revocation_reason))
Exemple #6
0
    def _convert_options_to_certmap(cls, entry_attrs, issuer=None,
                                    subject=None, certificates=()):
        """
        Converts options to ipacertmapdata

        When --subject --issuer or --certificate options are used,
        the value for ipacertmapdata is built from extracting subject and
        issuer,
        converting their values to X500 ordering and using the format
        X509:<I>issuer<S>subject
        For instance:
        X509:<I>O=DOMAIN,CN=Certificate Authority<S>O=DOMAIN,CN=user
        A list of values can be returned if --certificate is used multiple
        times, or in conjunction with --subject --issuer.
        """
        data = []
        data.extend(entry_attrs.get(cls.attribute, list()))

        if issuer or subject:
            data.append(cls._build_mapdata(subject, issuer))

        for dercert in certificates:
            cert = x509.load_certificate(dercert, x509.DER)
            issuer = DN(cert.issuer)
            subject = DN(cert.subject)
            if not subject:
                raise errors.ValidationError(
                    name='certificate',
                    error=_('cannot have an empty subject'))
            data.append(cls._build_mapdata(subject, issuer))

        entry_attrs[cls.attribute] = data
Exemple #7
0
def set_certificate_attrs(entry_attrs):
    """
    Set individual attributes from some values from a certificate.

    entry_attrs is a dict of an entry

    returns nothing
    """
    if not 'usercertificate' in entry_attrs:
        return
    if type(entry_attrs['usercertificate']) in (list, tuple):
        cert = entry_attrs['usercertificate'][0]
    else:
        cert = entry_attrs['usercertificate']
    cert = x509.normalize_certificate(cert)
    cert = x509.load_certificate(cert, datatype=x509.DER)
    entry_attrs['subject'] = unicode(DN(cert.subject))
    entry_attrs['serial_number'] = unicode(cert.serial_number)
    entry_attrs['serial_number_hex'] = u'0x%X' % cert.serial_number
    entry_attrs['issuer'] = unicode(DN(cert.issuer))
    entry_attrs['valid_not_before'] = x509.format_datetime(
        cert.not_valid_before)
    entry_attrs['valid_not_after'] = x509.format_datetime(cert.not_valid_after)
    entry_attrs['sha1_fingerprint'] = x509.to_hex_with_colons(
        cert.fingerprint(hashes.SHA1()))
    entry_attrs['sha256_fingerprint'] = x509.to_hex_with_colons(
        cert.fingerprint(hashes.SHA256()))
Exemple #8
0
    def execute(self, serial_number, **options):
        ca_enabled_check()
        hostname = None
        try:
            self.check_access()
        except errors.ACIError as acierr:
            self.debug("Not granted by ACI to retrieve certificate, looking at principal")
            bind_principal = getattr(context, 'principal')
            if not bind_principal.startswith('host/'):
                raise acierr
            hostname = get_host_from_principal(bind_principal)

        result=self.Backend.ra.get_certificate(serial_number)
        cert = x509.load_certificate(result['certificate'])
        result['subject'] = unicode(cert.subject)
        result['issuer'] = unicode(cert.issuer)
        result['valid_not_before'] = unicode(cert.valid_not_before_str)
        result['valid_not_after'] = unicode(cert.valid_not_after_str)
        result['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
        result['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
        if hostname:
            # If we have a hostname we want to verify that the subject
            # of the certificate matches it, otherwise raise an error
            if hostname != cert.subject.common_name:    #pylint: disable=E1101
                raise acierr

        return dict(result=result)
Exemple #9
0
    def execute(self, serial_number, **kw):
        ca_enabled_check()

        # Make sure that the cert specified by issuer+serial exists.
        # Will raise NotFound if it does not.
        resp = api.Command.cert_show(unicode(serial_number), cacn=kw['cacn'])

        try:
            self.check_access()
        except errors.ACIError as acierr:
            self.debug("Not granted by ACI to revoke certificate, looking at principal")
            try:
                cert = x509.load_certificate(resp['result']['certificate'])
                if not bind_principal_can_manage_cert(cert):
                    raise acierr
            except errors.NotImplementedError:
                raise acierr
        revocation_reason = kw['revocation_reason']
        if revocation_reason == 7:
            raise errors.CertificateOperationError(error=_('7 is not a valid revocation reason'))
        return dict(
            # Dogtag lightweight CAs have shared serial number domain, so
            # we don't tell Dogtag the issuer (but we already checked that
            # the given serial was issued by the named ca).
            result=self.Backend.ra.revoke_certificate(
                str(serial_number), revocation_reason=revocation_reason)
        )
Exemple #10
0
    def test_Backend(self):
        """
        Test using the ldap2 Backend directly (ala ipa-server-install)
        """

        # Create our own api because the one generated for the tests is
        # a client-only api. Then we register in the commands and objects
        # we need for the test.
        myapi = create_api(mode=None)
        myapi.bootstrap(context='cli', in_server=True, confdir=paths.ETC_IPA)
        myapi.finalize()

        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            with open(pwfile, "r") as fp:
                dm_password = fp.read().rstrip()
        else:
            raise nose.SkipTest("No directory manager password in %s" % pwfile)
        myapi.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password)

        result = myapi.Command['service_show']('ldap/%s@%s' %  (api.env.host, api.env.realm,))
        entry_attrs = result['result']
        cert = entry_attrs.get('usercertificate')
        cert = cert[0]
        serial = x509.load_certificate(cert, x509.DER).serial_number
        assert serial is not None
Exemple #11
0
    def track_server_cert(self,
                          nickname,
                          principal,
                          password_file=None,
                          command=None):
        """
        Tell certmonger to track the given certificate nickname.

        If command is not a full path then it is prefixed with
        /usr/lib[64]/ipa/certmonger.
        """
        if command is not None and not os.path.isabs(command):
            command = paths.CERTMONGER_COMMAND_TEMPLATE % (command)
        try:
            request_id = certmonger.start_tracking(nickname, self.secdir,
                                                   password_file, command)
        except RuntimeError as e:
            root_logger.error(
                "certmonger failed starting to track certificate: %s" % str(e))
            return

        cert = self.get_cert_from_db(nickname)
        nsscert = x509.load_certificate(cert, dbdir=self.secdir)
        subject = str(nsscert.subject)
        certmonger.add_principal(request_id, principal)
        certmonger.add_subject(request_id, subject)
Exemple #12
0
    def execute(self, serial_number, **options):
        ca_enabled_check()
        hostname = None
        try:
            self.check_access()
        except errors.ACIError as acierr:
            self.debug(
                "Not granted by ACI to retrieve certificate, looking at principal"
            )
            bind_principal = getattr(context, 'principal')
            if not bind_principal.startswith('host/'):
                raise acierr
            hostname = get_host_from_principal(bind_principal)

        result = self.Backend.ra.get_certificate(serial_number)
        cert = x509.load_certificate(result['certificate'])
        result['subject'] = unicode(cert.subject)
        result['issuer'] = unicode(cert.issuer)
        result['valid_not_before'] = unicode(cert.valid_not_before_str)
        result['valid_not_after'] = unicode(cert.valid_not_after_str)
        result['md5_fingerprint'] = unicode(
            nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
        result['sha1_fingerprint'] = unicode(
            nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
        if hostname:
            # If we have a hostname we want to verify that the subject
            # of the certificate matches it, otherwise raise an error
            if hostname != cert.subject.common_name:  #pylint: disable=E1101
                raise acierr

        return dict(result=result)
Exemple #13
0
def set_certificate_attrs(entry_attrs):
    """
    Set individual attributes from some values from a certificate.

    entry_attrs is a dict of an entry

    returns nothing
    """
    if not 'usercertificate' in entry_attrs:
        return
    if type(entry_attrs['usercertificate']) in (list, tuple):
        cert = entry_attrs['usercertificate'][0]
    else:
        cert = entry_attrs['usercertificate']
    cert = x509.normalize_certificate(cert)
    cert = x509.load_certificate(cert, datatype=x509.DER)
    entry_attrs['subject'] = unicode(DN(cert.subject))
    entry_attrs['serial_number'] = unicode(cert.serial)
    entry_attrs['serial_number_hex'] = u'0x%X' % cert.serial
    entry_attrs['issuer'] = unicode(DN(cert.issuer))
    entry_attrs['valid_not_before'] = x509.format_datetime(
            cert.not_valid_before)
    entry_attrs['valid_not_after'] = x509.format_datetime(cert.not_valid_after)
    entry_attrs['md5_fingerprint'] = x509.to_hex_with_colons(
        cert.fingerprint(hashes.MD5()))
    entry_attrs['sha1_fingerprint'] = x509.to_hex_with_colons(
        cert.fingerprint(hashes.SHA1()))
Exemple #14
0
def load_external_cert(files, subject_base):
    """
    Load and verify external CA certificate chain from multiple files.

    The files are accepted in PEM and DER certificate and PKCS#7 certificate
    chain formats.

    :param files: Names of files to import
    :param subject_base: Subject name base for IPA certificates
    :returns: Temporary file with the IPA CA certificate and temporary file
        with the external CA certificate chain
    """
    with certs.NSSDatabase() as nssdb:
        db_password = ipautil.ipa_generate_password()
        db_pwdfile = ipautil.write_tmp_file(db_password)
        nssdb.create_db(db_pwdfile.name)

        try:
            nssdb.import_files(files, db_pwdfile.name)
        except RuntimeError as e:
            raise ScriptError(str(e))

        ca_subject = DN(('CN', 'Certificate Authority'), subject_base)
        ca_nickname = None
        cache = {}
        for nickname, trust_flags in nssdb.list_certs():
            cert = nssdb.get_cert(nickname, pem=True)

            nss_cert = x509.load_certificate(cert)
            subject = DN(str(nss_cert.subject))
            issuer = DN(str(nss_cert.issuer))
            del nss_cert

            cache[nickname] = (cert, subject, issuer)
            if subject == ca_subject:
                ca_nickname = nickname
            nssdb.trust_root_cert(nickname)

        if ca_nickname is None:
            raise ScriptError("IPA CA certificate not found in %s" %
                              (", ".join(files)))

        trust_chain = reversed(nssdb.get_trust_chain(ca_nickname))
        ca_cert_chain = []
        for nickname in trust_chain:
            cert, subject, issuer = cache[nickname]
            ca_cert_chain.append(cert)
            if subject == issuer:
                break
        else:
            raise ScriptError("CA certificate chain in %s is incomplete" %
                              (", ".join(files)))

        for nickname in trust_chain:
            try:
                nssdb.verify_ca_cert_validity(nickname)
            except ValueError, e:
                raise ScriptError("CA certificate %s in %s is not valid: %s" %
                                  (subject, ", ".join(files), e))
Exemple #15
0
def load_pem_certificate(cert):
    """Abstract load PEM certificate by IPA version"""
    if version.NUM_VERSION < 40600:
        return x509.load_certificate(cert, x509.PEM)
    elif version.NUM_VERSION < 40700:
        return x509.load_pem_x509_certificate(cert)
    else:
        return x509.load_pem_x509_certificate(bytes(cert, 'utf-8'))
def nssdb_cert_to_basecertificate(cert_text):
    from ipapython import certdb
    from ipalib import x509

    cert, _ = certdb.find_cert_from_txt(cert_text, start=0)
    cert = x509.strip_header(cert)
    cert = base64.b64decode(cert)
    cert = x509.load_certificate(cert, x509.DER)
    return cert
Exemple #17
0
 def test_GSSAPI(self):
     """
     Test a GSSAPI LDAP bind using ldap2
     """
     self.conn = ldap2(api, ldap_uri=self.ldapuri)
     self.conn.connect()
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial
     assert serial is not None
Exemple #18
0
 def test_GSSAPI(self):
     """
     Test a GSSAPI LDAP bind using ldap2
     """
     self.conn = ldap2(api, ldap_uri=self.ldapuri)
     self.conn.connect()
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial
     assert serial is not None
Exemple #19
0
 def test_GSSAPI(self):
     """
     Test a GSSAPI LDAP bind using ldap2
     """
     self.conn = ldap2(api)
     self.conn.connect(autobind=AUTOBIND_DISABLED)
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #20
0
 def test_GSSAPI(self):
     """
     Test a GSSAPI LDAP bind using ldap2
     """
     self.conn = ldap2(api)
     self.conn.connect(autobind=AUTOBIND_DISABLED)
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #21
0
    def test_1_load_base64_cert(self):
        """
        Test loading a base64-encoded certificate.
        """

        # Load a good cert
        cert = x509.load_certificate(goodcert)

        # Load a good cert with headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert + '-----END CERTIFICATE-----'
        cert = x509.load_certificate(newcert)

        # Load a good cert with bad headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert
        with pytest.raises((TypeError, ValueError)):
            cert = x509.load_certificate(newcert)

        # Load a bad cert
        with pytest.raises(NSPRError):
            cert = x509.load_certificate(badcert)
Exemple #22
0
    def _get_cert_key(self, cert):
        try:
            nss_cert = x509.load_certificate(cert, x509.DER)
        except NSPRError as e:
            message = messages.SearchResultTruncated(
                reason=_("failed to load certificate: %s") % e, )
            self.add_message(message)

            raise ValueError("failed to load certificate")

        return (DN(unicode(nss_cert.issuer)), nss_cert.serial_number)
Exemple #23
0
    def _get_cert_key(self, cert):
        try:
            nss_cert = x509.load_certificate(cert, x509.DER)
        except NSPRError as e:
            message = messages.SearchResultTruncated(
                reason=_("failed to load certificate: %s") % e,
            )
            self.add_message(message)

            raise ValueError("failed to load certificate")

        return (DN(unicode(nss_cert.issuer)), nss_cert.serial_number)
def load_cert_from_str(cert):
    cert = cert.strip()
    if not cert.startswith("-----BEGIN CERTIFICATE-----"):
        cert = "-----BEGIN CERTIFICATE-----\n" + cert
    if not cert.endswith("-----END CERTIFICATE-----"):
        cert += "\n-----END CERTIFICATE-----"

    if load_pem_x509_certificate is not None:
        cert = load_pem_x509_certificate(cert.encode('utf-8'))
    else:
        cert = load_certificate(cert.encode('utf-8'))
    return cert
Exemple #25
0
    def execute(self,
                serial_number,
                all=False,
                raw=False,
                no_members=False,
                **options):
        ca_enabled_check()

        # Dogtag lightweight CAs have shared serial number domain, so
        # we don't tell Dogtag the issuer (but we check the cert after).
        #
        result = self.Backend.ra.get_certificate(str(serial_number))
        cert = x509.load_certificate(result['certificate'])

        try:
            self.check_access()
        except errors.ACIError as acierr:
            self.debug(
                "Not granted by ACI to retrieve certificate, looking at principal"
            )
            if not bind_principal_can_manage_cert(cert):
                raise acierr  # pylint: disable=E0702

        ca_obj = api.Command.ca_show(options['cacn'])['result']
        if DN(unicode(cert.issuer)) != DN(ca_obj['ipacasubjectdn'][0]):
            # DN of cert differs from what we requested
            raise errors.NotFound(
                reason=_("Certificate with serial number %(serial)s "
                         "issued by CA '%(ca)s' not found") %
                dict(serial=serial_number, ca=options['cacn']))

        if all or not no_members:
            ldap = self.api.Backend.ldap2
            filter = ldap.make_filter_from_attr(
                'usercertificate', base64.b64decode(result['certificate']))
            try:
                entries = ldap.get_entries(base_dn=self.api.env.basedn,
                                           filter=filter,
                                           attrs_list=[''])
            except errors.EmptyResult:
                entries = []
            for entry in entries:
                result.setdefault('owner', []).append(entry.dn)

        if not raw:
            result['certificate'] = result['certificate'].replace('\r\n', '')
            self.obj._parse(result, all)
            result['revoked'] = ('revocation_reason' in result)
            self.obj._fill_owners(result)
            result['cacn'] = ca_obj['cn'][0]

        return dict(result=result, value=pkey_to_value(serial_number, options))
Exemple #26
0
 def test_autobind(self):
     """
     Test an autobind LDAP bind using ldap2
     """
     self.conn = ldap2(api)
     try:
         self.conn.connect(autobind=True)
     except errors.ACIError:
         raise nose.SkipTest("Only executed as root")
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #27
0
def get_cert_nickname(cert):
    """
    Using the subject from cert come up with a nickname suitable
    for NSS. The caller can decide whether to use just the RDN
    or the whole subject.

    Returns a tuple of (rdn, subject_dn) when rdn is the string
    representation of the first RDN in the subject and subject_dn
    is a DN object.
    """
    cert_obj = x509.load_certificate(cert)
    dn = DN(cert_obj.subject)

    return (str(dn[0]), dn)
Exemple #28
0
def get_cert_nickname(cert):
    """
    Using the subject from cert come up with a nickname suitable
    for NSS. The caller can decide whether to use just the RDN
    or the whole subject.

    Returns a tuple of (rdn, subject_dn) when rdn is the string
    representation of the first RDN in the subject and subject_dn
    is a DN object.
    """
    cert_obj = x509.load_certificate(cert)
    dn = DN(cert_obj.subject)

    return (str(dn[0]), dn)
Exemple #29
0
    def test_3_cert_contents(self):
        """
        Test the contents of a certificate
        """
        # Verify certificate contents. This exercises python-nss more than
        # anything but confirms our usage of it.

        cert = x509.load_certificate(goodcert)

        assert DN(str(cert.subject)) == DN(('CN','ipa.example.com'),('O','IPA'))
        assert DN(str(cert.issuer)) == DN(('CN','IPA Test Certificate Authority'))
        assert cert.serial_number == 1093
        assert cert.valid_not_before_str == 'Fri Jun 25 13:00:42 2010 UTC'
        assert cert.valid_not_after_str == 'Thu Jun 25 13:00:42 2015 UTC'
Exemple #30
0
 def test_autobind(self):
     """
     Test an autobind LDAP bind using ldap2
     """
     self.conn = ldap2(api)
     try:
         self.conn.connect(autobind=True)
     except errors.ACIError:
         raise nose.SkipTest("Only executed as root")
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #31
0
    def test_1_load_base64_cert(self):
        """
        Test loading a base64-encoded certificate.
        """

        # Load a good cert
        cert = x509.load_certificate(goodcert)

        # Load a good cert with headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert + '-----END CERTIFICATE-----'
        cert = x509.load_certificate(newcert)

        # Load a good cert with bad headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert
        try:
            cert = x509.load_certificate(newcert)
        except TypeError:
            pass

        # Load a bad cert
        try:
            cert = x509.load_certificate(badcert)
        except NSPRError:
            pass
Exemple #32
0
 def test_autobind(self):
     """
     Test an autobind LDAP bind using ldap2
     """
     ldapuri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % api.env.realm.replace('.','-')
     self.conn = ldap2(api, ldap_uri=ldapuri)
     try:
         self.conn.connect(autobind=True)
     except errors.ACIError:
         raise nose.SkipTest("Only executed as root")
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial
     assert serial is not None
Exemple #33
0
def _parse_cert(dercert):
    try:
        cert = x509.load_certificate(dercert, x509.DER)
        subject = DN(cert.subject)
        issuer = DN(cert.issuer)
        serial_number = cert.serial
        public_key_info = x509.get_der_public_key_info(dercert, x509.DER)
    except (ValueError, PyAsn1Error) as e:
        raise ValueError("failed to decode certificate: %s" % e)

    subject = str(subject).replace('\\;', '\\3b')
    issuer = str(issuer).replace('\\;', '\\3b')
    issuer_serial = '%s;%s' % (issuer, serial_number)

    return subject, issuer_serial, public_key_info
Exemple #34
0
    def test_1_load_base64_cert(self):
        """
        Test loading a base64-encoded certificate.
        """

        # Load a good cert
        cert = x509.load_certificate(goodcert)

        # Load a good cert with headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert + '-----END CERTIFICATE-----'
        cert = x509.load_certificate(newcert)

        # Load a good cert with bad headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert
        try:
            cert = x509.load_certificate(newcert)
        except TypeError:
            pass

        # Load a bad cert
        try:
            cert = x509.load_certificate(badcert)
        except NSPRError:
            pass
Exemple #35
0
def _parse_cert(dercert):
    try:
        cert = x509.load_certificate(dercert, x509.DER)
        subject = DN(cert.subject)
        issuer = DN(cert.issuer)
        serial_number = cert.serial_number
        public_key_info = x509.get_der_public_key_info(dercert, x509.DER)
    except (ValueError, PyAsn1Error) as e:
        raise ValueError("failed to decode certificate: %s" % e)

    subject = str(subject).replace('\\;', '\\3b')
    issuer = str(issuer).replace('\\;', '\\3b')
    issuer_serial = '%s;%s' % (issuer, serial_number)

    return subject, issuer_serial, public_key_info
Exemple #36
0
 def test_autobind(self):
     """
     Test an autobind LDAP bind using ldap2
     """
     ldapuri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % api.env.realm.replace(
         '.', '-')
     self.conn = ldap2(api, ldap_uri=ldapuri)
     try:
         self.conn.connect(autobind=True)
     except errors.ACIError:
         raise nose.SkipTest("Only executed as root")
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #37
0
    def test_3_cert_contents(self):
        """
        Test the contents of a certificate
        """
        # Verify certificate contents. This exercises python-nss more than
        # anything but confirms our usage of it.

        cert = x509.load_certificate(goodcert)

        assert DN(str(cert.subject)) == DN(('CN', 'ipa.example.com'),
                                           ('O', 'IPA'))
        assert DN(str(cert.issuer)) == DN(
            ('CN', 'IPA Test Certificate Authority'))
        assert cert.serial_number == 1093
        assert cert.valid_not_before_str == 'Fri Jun 25 13:00:42 2010 UTC'
        assert cert.valid_not_after_str == 'Thu Jun 25 13:00:42 2015 UTC'
Exemple #38
0
    def test_3_cert_contents(self):
        """
        Test the contents of a certificate
        """
        # Verify certificate contents. This exercises python-cryptography
        # more than anything but confirms our usage of it.

        not_before = datetime.datetime(2010, 6, 25, 13, 0, 42)
        not_after = datetime.datetime(2015, 6, 25, 13, 0, 42)
        cert = x509.load_certificate(goodcert)

        assert DN(cert.subject) == DN(('CN', 'ipa.example.com'), ('O', 'IPA'))
        assert DN(cert.issuer) == DN(('CN', 'IPA Test Certificate Authority'))
        assert cert.serial == 1093
        assert cert.not_valid_before == not_before
        assert cert.not_valid_after == not_after
Exemple #39
0
    def test_3_cert_contents(self):
        """
        Test the contents of a certificate
        """
        # Verify certificate contents. This exercises python-cryptography
        # more than anything but confirms our usage of it.

        not_before = datetime.datetime(2010, 6, 25, 13, 0, 42)
        not_after = datetime.datetime(2015, 6, 25, 13, 0, 42)
        cert = x509.load_certificate(goodcert)

        assert DN(cert.subject) == DN(('CN', 'ipa.example.com'), ('O', 'IPA'))
        assert DN(cert.issuer) == DN(('CN', 'IPA Test Certificate Authority'))
        assert cert.serial_number == 1093
        assert cert.not_valid_before == not_before
        assert cert.not_valid_after == not_after
Exemple #40
0
    def _parse(self, obj, full=True):
        """Extract certificate-specific data into a result object.

        ``obj``
            Result object containing certificate, into which extracted
            data will be inserted.
        ``full``
            Whether to include all fields, or only the ones we guess
            people want to see most of the time.  Also add
            recognised otherNames to the generic ``san_other``
            attribute when ``True`` in addition to the specialised
            attribute.

        """
        cert = obj.get('certificate')
        if cert is not None:
            cert = x509.load_certificate(cert)
            obj['subject'] = DN(unicode(cert.subject))
            obj['issuer'] = DN(unicode(cert.issuer))
            obj['serial_number'] = cert.serial_number
            if full:
                obj['valid_not_before'] = unicode(cert.valid_not_before_str)
                obj['valid_not_after'] = unicode(cert.valid_not_after_str)
                obj['md5_fingerprint'] = unicode(
                    nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
                obj['sha1_fingerprint'] = unicode(
                    nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])

            try:
                ext_san = cert.get_extension(nss.SEC_OID_X509_SUBJECT_ALT_NAME)
                general_names = x509.decode_generalnames(ext_san.value)
            except KeyError:
                general_names = []

            for name_type, desc, name, der_name in general_names:
                try:
                    self._add_san_attribute(
                        obj, full, name_type, name, der_name)
                except Exception as e:
                    # Invalid GeneralName (i.e. not a valid X.509 cert);
                    # don't fail but log something about it
                    root_logger.warning(
                        "Encountered bad GeneralName; skipping", exc_info=True)

        serial_number = obj.get('serial_number')
        if serial_number is not None:
            obj['serial_number_hex'] = u'0x%X' % serial_number
Exemple #41
0
    def _parse(self, obj, full=True):
        """Extract certificate-specific data into a result object.

        ``obj``
            Result object containing certificate, into which extracted
            data will be inserted.
        ``full``
            Whether to include all fields, or only the ones we guess
            people want to see most of the time.  Also add
            recognised otherNames to the generic ``san_other``
            attribute when ``True`` in addition to the specialised
            attribute.

        """
        cert = obj.get('certificate')
        if cert is not None:
            cert = x509.load_certificate(cert)
            obj['subject'] = DN(unicode(cert.subject))
            obj['issuer'] = DN(unicode(cert.issuer))
            obj['serial_number'] = cert.serial_number
            if full:
                obj['valid_not_before'] = unicode(cert.valid_not_before_str)
                obj['valid_not_after'] = unicode(cert.valid_not_after_str)
                obj['md5_fingerprint'] = unicode(
                    nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
                obj['sha1_fingerprint'] = unicode(
                    nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])

            try:
                ext_san = cert.get_extension(nss.SEC_OID_X509_SUBJECT_ALT_NAME)
                general_names = x509.decode_generalnames(ext_san.value)
            except KeyError:
                general_names = []

            for name_type, _desc, name, der_name in general_names:
                try:
                    self._add_san_attribute(obj, full, name_type, name,
                                            der_name)
                except Exception:
                    # Invalid GeneralName (i.e. not a valid X.509 cert);
                    # don't fail but log something about it
                    root_logger.warning(
                        "Encountered bad GeneralName; skipping", exc_info=True)

        serial_number = obj.get('serial_number')
        if serial_number is not None:
            obj['serial_number_hex'] = u'0x%X' % serial_number
Exemple #42
0
    def execute(self, serial_number, all=False, raw=False, no_members=False,
                **options):
        ca_enabled_check()

        # Dogtag lightweight CAs have shared serial number domain, so
        # we don't tell Dogtag the issuer (but we check the cert after).
        #
        result = self.Backend.ra.get_certificate(str(serial_number))
        cert = x509.load_certificate(result['certificate'])

        try:
            self.check_access()
        except errors.ACIError as acierr:
            self.debug("Not granted by ACI to retrieve certificate, looking at principal")
            if not bind_principal_can_manage_cert(cert):
                raise acierr  # pylint: disable=E0702

        ca_obj = api.Command.ca_show(options['cacn'])['result']
        if DN(unicode(cert.issuer)) != DN(ca_obj['ipacasubjectdn'][0]):
            # DN of cert differs from what we requested
            raise errors.NotFound(
                reason=_("Certificate with serial number %(serial)s "
                    "issued by CA '%(ca)s' not found")
                    % dict(serial=serial_number, ca=options['cacn']))

        if all or not no_members:
            ldap = self.api.Backend.ldap2
            filter = ldap.make_filter_from_attr(
                'usercertificate', base64.b64decode(result['certificate']))
            try:
                entries = ldap.get_entries(base_dn=self.api.env.basedn,
                                           filter=filter,
                                           attrs_list=[''])
            except errors.EmptyResult:
                entries = []
            for entry in entries:
                result.setdefault('owner', []).append(entry.dn)

        if not raw:
            result['certificate'] = result['certificate'].replace('\r\n', '')
            self.obj._parse(result, all)
            result['revoked'] = ('revocation_reason' in result)
            self.obj._fill_owners(result)
            result['cacn'] = ca_obj['cn'][0]

        return dict(result=result, value=pkey_to_value(serial_number, options))
Exemple #43
0
    def track_server_cert(self, nickname, principal, password_file=None, command=None):
        """
        Tell certmonger to track the given certificate nickname.
        """
        try:
            request_id = certmonger.start_tracking(
                self.secdir, nickname=nickname, pinfile=password_file,
                post_command=command)
        except RuntimeError as e:
            root_logger.error("certmonger failed starting to track certificate: %s" % str(e))
            return

        cert = self.get_cert_from_db(nickname)
        cert_obj = x509.load_certificate(cert)
        subject = str(DN(cert_obj.subject))
        certmonger.add_principal(request_id, principal)
        certmonger.add_subject(request_id, subject)
Exemple #44
0
 def test_simple(self):
     """
     Test a simple LDAP bind using ldap2
     """
     pwfile = api.env.dot_ipa + os.sep + ".dmpw"
     if ipautil.file_exists(pwfile):
         with open(pwfile, "r") as fp:
             dm_password = fp.read().rstrip()
     else:
         raise nose.SkipTest("No directory manager password in %s" % pwfile)
     self.conn = ldap2(api)
     self.conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #45
0
    def __create_kra_agent(self):
        """
        Create KRA agent, assign a certificate, and add the user to
        the appropriate groups for accessing KRA services.
        """

        # get ipaCert certificate
        with certdb.NSSDatabase(paths.HTTPD_ALIAS_DIR) as ipa_nssdb:
            cert_data = ipa_nssdb.get_cert("ipaCert")
        cert = x509.load_certificate(cert_data, x509.DER)

        # connect to KRA database
        server_id = installutils.realm_to_serverid(api.env.realm)
        dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
        conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
        conn.connect(autobind=True)

        # create ipakra user with ipaCert certificate
        user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn)
        entry = conn.make_entry(
            user_dn,
            objectClass=[
                'top', 'person', 'organizationalPerson', 'inetOrgPerson',
                'cmsuser'
            ],
            uid=["ipakra"],
            sn=["IPA KRA User"],
            cn=["IPA KRA User"],
            usertype=["undefined"],
            userCertificate=[cert_data],
            description=[
                '2;%s;%s;%s' %
                (cert.serial_number,
                 DN(('CN', 'Certificate Authority'),
                    self.subject_base), DN(
                        ('CN', 'IPA RA'), self.subject_base))
            ])
        conn.add_entry(entry)

        # add ipakra user to Data Recovery Manager Agents group
        group_dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'),
                      self.basedn)
        conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember')

        conn.disconnect()
Exemple #46
0
 def test_simple(self):
     """
     Test a simple LDAP bind using ldap2
     """
     pwfile = api.env.dot_ipa + os.sep + ".dmpw"
     if ipautil.file_exists(pwfile):
         with open(pwfile, "r") as fp:
             dm_password = fp.read().rstrip()
     else:
         raise nose.SkipTest("No directory manager password in %s" % pwfile)
     self.conn = ldap2(api)
     self.conn.connect(bind_dn=DN(('cn', 'directory manager')),
                       bind_pw=dm_password)
     entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
     cert = entry_attrs.get('usercertificate')
     cert = cert[0]
     serial = x509.load_certificate(cert, x509.DER).serial_number
     assert serial is not None
Exemple #47
0
    def track_server_cert(self, nickname, principal, password_file=None, command=None):
        """
        Tell certmonger to track the given certificate nickname.
        """
        try:
            request_id = certmonger.start_tracking(
                self.secdir, nickname=nickname, pinfile=password_file,
                post_command=command)
        except RuntimeError as e:
            logger.error("certmonger failed starting to track certificate: %s",
                         str(e))
            return

        cert = self.get_cert_from_db(nickname)
        cert_obj = x509.load_certificate(cert)
        subject = str(DN(cert_obj.subject))
        certmonger.add_principal(request_id, principal)
        certmonger.add_subject(request_id, subject)
Exemple #48
0
    def test_1_load_base64_cert(self):
        """
        Test loading a base64-encoded certificate.
        """

        # Load a good cert
        x509.load_certificate(goodcert)

        # Load a good cert with headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert + '-----END CERTIFICATE-----'
        x509.load_certificate(newcert)

        # Load a good cert with bad headers
        newcert = '-----BEGIN CERTIFICATE-----' + goodcert
        with pytest.raises((TypeError, ValueError)):
            x509.load_certificate(newcert)

        # Load a bad cert
        with pytest.raises(NSPRError):
            x509.load_certificate(badcert)
Exemple #49
0
    def test_1_load_der_cert(self):
        """
        Test loading a DER certificate.
        """

        der = base64.b64decode(goodcert)

        # Load a good cert
        x509.load_certificate(der, x509.DER)

        # Should handle list/tuple
        x509.load_certificate((der,), x509.DER)
        x509.load_certificate([der], x509.DER)
Exemple #50
0
    def test_1_load_der_cert(self):
        """
        Test loading a DER certificate.
        """

        der = base64.b64decode(goodcert)

        # Load a good cert
        x509.load_certificate(der, x509.DER)

        # Should handle list/tuple
        x509.load_certificate((der, ), x509.DER)
        x509.load_certificate([der], x509.DER)
Exemple #51
0
    def __create_kra_agent(self):
        """
        Create KRA agent, assign a certificate, and add the user to
        the appropriate groups for accessing KRA services.
        """

        # get ipaCert certificate
        with certdb.NSSDatabase(paths.HTTPD_ALIAS_DIR) as ipa_nssdb:
            cert_data = ipa_nssdb.get_cert("ipaCert")
        cert = x509.load_certificate(cert_data, x509.DER)

        # connect to KRA database
        server_id = installutils.realm_to_serverid(api.env.realm)
        dogtag_uri = "ldapi://%%2fvar%%2frun%%2fslapd-%s.socket" % server_id
        conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
        conn.connect(autobind=True)

        # create ipakra user with ipaCert certificate
        user_dn = DN(("uid", "ipakra"), ("ou", "people"), self.basedn)
        entry = conn.make_entry(
            user_dn,
            objectClass=["top", "person", "organizationalPerson", "inetOrgPerson", "cmsuser"],
            uid=["ipakra"],
            sn=["IPA KRA User"],
            cn=["IPA KRA User"],
            usertype=["undefined"],
            userCertificate=[cert_data],
            description=[
                "2;%s;%s;%s"
                % (
                    cert.serial_number,
                    DN(("CN", "Certificate Authority"), self.subject_base),
                    DN(("CN", "IPA RA"), self.subject_base),
                )
            ],
        )
        conn.add_entry(entry)

        # add ipakra user to Data Recovery Manager Agents group
        group_dn = DN(("cn", "Data Recovery Manager Agents"), ("ou", "groups"), self.basedn)
        conn.add_entry_to_group(user_dn, group_dn, "uniqueMember")

        conn.disconnect()
Exemple #52
0
    def track_server_cert(self, nickname, principal, password_file=None, command=None):
        """
        Tell certmonger to track the given certificate nickname.

        If command is not a full path then it is prefixed with
        /usr/lib[64]/ipa/certmonger.
        """
        if command is not None and not os.path.isabs(command):
            command = paths.CERTMONGER_COMMAND_TEMPLATE % (command)
        try:
            request_id = certmonger.start_tracking(nickname, self.secdir, password_file, command)
        except RuntimeError as e:
            root_logger.error("certmonger failed starting to track certificate: %s" % str(e))
            return

        cert = self.get_cert_from_db(nickname)
        cert_obj = x509.load_certificate(cert)
        subject = str(DN(cert_obj.subject))
        certmonger.add_principal(request_id, principal)
        certmonger.add_subject(request_id, subject)
Exemple #53
0
    def internal(self, algo, *args, **options):
        """
        Calls the internal counterpart of the command.
        """
        domain = self.api.env.domain

        # try call with cached transport certificate
        transport_cert = _transport_cert_cache.load_cert(domain)
        if transport_cert is not None:
            result = self._do_internal(algo, transport_cert, False, *args,
                                       **options)
            if result is not None:
                return result

        # retrieve transport certificate (cached by vaultconfig_show)
        response = self.api.Command.vaultconfig_show()
        transport_cert = x509.load_certificate(
            response['result']['transport_cert'], x509.DER)
        # call with the retrieved transport certificate
        return self._do_internal(algo, transport_cert, True, *args, **options)
Exemple #54
0
    def internal(self, algo, *args, **options):
        """
        Calls the internal counterpart of the command.
        """
        domain = self.api.env.domain

        # try call with cached transport certificate
        transport_cert = _transport_cert_cache.load_cert(domain)
        if transport_cert is not None:
            result = self._do_internal(algo, transport_cert, False,
                                       *args, **options)
            if result is not None:
                return result

        # retrieve transport certificate (cached by vaultconfig_show)
        response = self.api.Command.vaultconfig_show()
        transport_cert = x509.load_certificate(
            response['result']['transport_cert'], x509.DER)
        # call with the retrieved transport certificate
        return self._do_internal(algo, transport_cert, True,
                                 *args, **options)
Exemple #55
0
    def forward(self, *args, **options):

        file = options.get('transport_out')

        # don't send these parameters to server
        if 'transport_out' in options:
            del options['transport_out']

        response = super(vaultconfig_show, self).forward(*args, **options)

        # cache transport certificate
        transport_cert = x509.load_certificate(
                response['result']['transport_cert'], x509.DER)

        _transport_cert_cache.store_cert(
            self.api.env.domain, transport_cert
        )

        if file:
            with open(file, 'w') as f:
                f.write(response['result']['transport_cert'])

        return response
Exemple #56
0
def set_certificate_attrs(entry_attrs):
    """
    Set individual attributes from some values from a certificate.

    entry_attrs is a dict of an entry

    returns nothing
    """
    if not 'usercertificate' in entry_attrs:
        return
    if type(entry_attrs['usercertificate']) in (list, tuple):
        cert = entry_attrs['usercertificate'][0]
    else:
        cert = entry_attrs['usercertificate']
    cert = x509.normalize_certificate(cert)
    cert = x509.load_certificate(cert, datatype=x509.DER)
    entry_attrs['subject'] = unicode(cert.subject)
    entry_attrs['serial_number'] = unicode(cert.serial_number)
    entry_attrs['serial_number_hex'] = u'0x%X' % cert.serial_number
    entry_attrs['issuer'] = unicode(cert.issuer)
    entry_attrs['valid_not_before'] = unicode(cert.valid_not_before_str)
    entry_attrs['valid_not_after'] = unicode(cert.valid_not_after_str)
    entry_attrs['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
    entry_attrs['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
Exemple #57
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)
Exemple #58
0
    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")
Exemple #59
0
    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

        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
        )

        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, DN(old_cert_obj.subject))

        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:
            tmpdb.create_db()
            tmpdb.add_cert(old_cert_der, 'IPA CA', EXTERNAL_CA_TRUST_FLAGS)

            try:
                tmpdb.add_cert(new_cert_der, 'IPA CA', EXTERNAL_CA_TRUST_FLAGS)
            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)), EXTERNAL_CA_TRUST_FLAGS)

            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,
                    EMPTY_TRUST_FLAGS)

        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('dogtag-ipa-ca-renew-agent-reuse')

        print("CA certificate successfully renewed")