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)
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
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])
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))
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
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()))
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)
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) )
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
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)
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)
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()))
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))
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
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
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
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)
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
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))
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
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)
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'
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
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
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
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
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
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'
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
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
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
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
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))
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)
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
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()
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)
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)
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)
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)
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()
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)
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)
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
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])
def import_files(self, files, db_password_filename, import_keys=False, key_password=None, key_nickname=None): """ Import certificates and a single private key from multiple files The files may be in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and raw private key and PKCS#12 formats. :param files: Names of files to import :param db_password_filename: Name of file containing the database password :param import_keys: Whether to import private keys :param key_password: Password to decrypt private keys :param key_nickname: Nickname of the private key to import from PKCS#12 files """ key_file = None extracted_key = None extracted_certs = '' for filename in files: try: with open(filename, 'rb') as f: data = f.read() except IOError as e: raise RuntimeError( "Failed to open %s: %s" % (filename, e.strerror)) # Try to parse the file as PEM file matches = list(re.finditer( r'-----BEGIN (.+?)-----(.*?)-----END \1-----', data, re.DOTALL)) if matches: loaded = False for match in matches: body = match.group() label = match.group(1) line = len(data[:match.start() + 1].splitlines()) if label in ('CERTIFICATE', 'X509 CERTIFICATE', 'X.509 CERTIFICATE'): try: x509.load_certificate(match.group(2)) except NSPRError as e: if label != 'CERTIFICATE': root_logger.warning( "Skipping certificate in %s at line %s: %s", filename, line, e) continue else: extracted_certs += body + '\n' loaded = True continue if label in ('PKCS7', 'PKCS #7 SIGNED DATA', 'CERTIFICATE'): args = [ paths.OPENSSL, 'pkcs7', '-print_certs', ] try: result = ipautil.run( args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: if label == 'CERTIFICATE': root_logger.warning( "Skipping certificate in %s at line %s: %s", filename, line, e) else: root_logger.warning( "Skipping PKCS#7 in %s at line %s: %s", filename, line, e) continue else: extracted_certs += result.output + '\n' loaded = True continue if label in ('PRIVATE KEY', 'ENCRYPTED PRIVATE KEY', 'RSA PRIVATE KEY', 'DSA PRIVATE KEY', 'EC PRIVATE KEY'): if not import_keys: continue if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) args = [ paths.OPENSSL, 'pkcs8', '-topk8', '-passout', 'file:' + db_password_filename, ] if ((label != 'PRIVATE KEY' and key_password) or label == 'ENCRYPTED PRIVATE KEY'): key_pwdfile = ipautil.write_tmp_file(key_password) args += [ '-passin', 'file:' + key_pwdfile.name, ] try: result = ipautil.run( args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: root_logger.warning( "Skipping private key in %s at line %s: %s", filename, line, e) continue else: extracted_key = result.output key_file = filename loaded = True continue if loaded: continue raise RuntimeError("Failed to load %s" % filename) # Try to load the file as DER certificate try: x509.load_certificate(data, x509.DER) except NSPRError: pass else: data = x509.make_pem(base64.b64encode(data)) extracted_certs += data + '\n' continue # Try to import the file as PKCS#12 file if import_keys: try: self.import_pkcs12( filename, db_password_filename, key_password) except RuntimeError: pass else: if key_file: raise RuntimeError( "Can't load private key from both %s and %s" % (key_file, filename)) key_file = filename server_certs = self.find_server_certs() if key_nickname: for nickname, trust_flags in server_certs: if nickname == key_nickname: break else: raise RuntimeError( "Server certificate \"%s\" not found in %s" % (key_nickname, filename)) else: if len(server_certs) > 1: raise RuntimeError( "%s server certificates found in %s, " "expecting only one" % (len(server_certs), filename)) continue raise RuntimeError("Failed to load %s" % filename) if import_keys and not key_file: raise RuntimeError( "No server certificates found in %s" % (', '.join(files))) nss_certs = x509.load_certificate_list(extracted_certs) nss_cert = None for nss_cert in nss_certs: nickname = str(nss_cert.subject) self.add_cert(nss_cert.der_data, nickname, ',,') del nss_certs, nss_cert if extracted_key: in_file = ipautil.write_tmp_file(extracted_certs + extracted_key) out_file = tempfile.NamedTemporaryFile() out_password = ipautil.ipa_generate_password() out_pwdfile = ipautil.write_tmp_file(out_password) args = [ paths.OPENSSL, 'pkcs12', '-export', '-in', in_file.name, '-out', out_file.name, '-passin', 'file:' + db_password_filename, '-passout', 'file:' + out_pwdfile.name, ] try: ipautil.run(args) except ipautil.CalledProcessError as e: raise RuntimeError( "No matching certificate found for private key from %s" % key_file) self.import_pkcs12(out_file.name, db_password_filename, out_password)
def 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")
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")