def get_san_from_cert(CERT_FILE):
    cert = _load_certificate(CERT_FILE)
    e = cert.get_extension(2)
    for i in range(cert.get_extension_count()):
        logging.debug(cert.get_extension(i).get_short_name())
        if cert.get_extension(i).get_short_name().decode() == "subjectAltName":
            e = cert.get_extension(i)
            break
    raw_alt_names = e.get_data()
    decoded_alt_names, _ = asn1_decoder(raw_alt_names,
                                        asn1Spec=SubjectAltName())
    py_alt_names = nat_encoder(decoded_alt_names)
    logging.debug(py_alt_names)
    ip_sub_alt_name = []
    dns_sub_alt_name = []
    for element in py_alt_names:
        if element.keys() == OrderedDict([('iPAddress', '_')]).keys():
            ip_sub_alt_name.append(
                str(ipaddress.IPv4Address(element['iPAddress'])))
        elif element.keys() == OrderedDict([('dNSName', '_')]).keys():
            dns_sub_alt_name.append(element['dNSName'].decode("utf-8"))
        else:
            logging.error("Bad AltName Key")
    logging.debug(ip_sub_alt_name)
    logging.debug(dns_sub_alt_name)
    san = {"dns": dns_sub_alt_name, "ip": ip_sub_alt_name}
    logging.debug(san)
    return san
Exemplo n.º 2
0
def extract_names(raw_cert):
    results = {
        'CN': set(),
        'DNS': set(),
        'SRV': set(),
        'URI': set(),
        'XMPPAddr': set()
    }

    cert = decoder.decode(raw_cert, asn1Spec=Certificate())[0]
    tbs = cert.getComponentByName('tbsCertificate')
    subject = tbs.getComponentByName('subject')
    extensions = tbs.getComponentByName('extensions') or []

    # Extract the CommonName(s) from the cert.
    for rdnss in subject:
        for rdns in rdnss:
            for name in rdns:
                oid = name.getComponentByName('type')
                value = name.getComponentByName('value')

                if oid != COMMON_NAME:
                    continue

                value = decoder.decode(value, asn1Spec=DirectoryString())[0]
                value = decode_str(value.getComponent())
                results['CN'].add(value)

    # Extract the Subject Alternate Names (DNS, SRV, URI, XMPPAddr)
    for extension in extensions:
        oid = extension.getComponentByName('extnID')
        if oid != SUBJECT_ALT_NAME:
            continue

        value = decoder.decode(extension.getComponentByName('extnValue'),
                               asn1Spec=OctetString())[0]
        sa_names = decoder.decode(value, asn1Spec=SubjectAltName())[0]
        for name in sa_names:
            name_type = name.getName()
            if name_type == 'dNSName':
                results['DNS'].add(decode_str(name.getComponent()))
            if name_type == 'uniformResourceIdentifier':
                value = decode_str(name.getComponent())
                if value.startswith('xmpp:'):
                    results['URI'].add(value[5:])
            elif name_type == 'otherName':
                name = name.getComponent()

                oid = name.getComponentByName('type-id')
                value = name.getComponentByName('value')

                if oid == XMPP_ADDR:
                    value = decoder.decode(value, asn1Spec=UTF8String())[0]
                    results['XMPPAddr'].add(decode_str(value))
                elif oid == SRV_NAME:
                    value = decoder.decode(value, asn1Spec=IA5String())[0]
                    results['SRV'].add(decode_str(value))

    return results
Exemplo n.º 3
0
def chain_subject_names(chain):
    names = {
        name for field, name in chain[0].get_subject().get_components() if field == "CN"
    }
    for i in range(chain[0].get_extension_count()):
        ext = chain[0].get_extension(i)
        if ext.get_short_name() == "subjectAltName":
            value, substrate = der_decoder.decode(
                ext.get_data(), asn1Spec=SubjectAltName()
            )
            assert substrate == b""
            for component in value:
                if component.getName() == "dNSName":
                    names.add(str(component.getComponent()))
    return names
Exemplo n.º 4
0
    def __extract_san(self, x509):
        domain = set()

        if isinstance(x509, OpenSSL.crypto.X509):
            extensions = [
                x509.get_extension(i)
                for i in range(x509.get_extension_count())
            ]
        else:
            extensions = x509.get_extensions()

        for extension in extensions:
            if extension.get_short_name() == b"subjectAltName":
                san = extension.get_data()
                san = decoder.decode(san, asn1Spec=SubjectAltName())

                for name in san:
                    if isinstance(name, SubjectAltName):
                        for entry in range(len(name)):
                            component = name.getComponentByPosition(entry)
                            domain.add(str(component.getComponent()))
        return domain
Exemplo n.º 5
0
def fnmt_data_from_pem(pem):
    '''
    given an FNMT PEM certificate, returns the relevant data from it:
    returns nif, full_name, email

    The certificate might not contain an email - in that case it will return
    None for the email.

    If there's any error processing the certificate, it will throw an exception
    '''

    import OpenSSL
    from pyasn1.type.base import AbstractConstructedAsn1Item
    from pyasn1.type.char import IA5String
    from pyasn1.codec.der.decoder import decode
    from pyasn1_modules.rfc2459 import SubjectAltName, AttributeTypeAndValue, GeneralName

    cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem)

    # sanity check
    components = cert.get_subject().get_components()
    assert components[0][0].lower() == 'c'
    assert components[0][1].lower() == 'es'

    assert components[1][0].lower() == 'o'
    assert components[1][1].lower() == 'fnmt'

    assert components[2][0].lower() == 'ou'
    assert components[2][1].lower() == 'fnmt clase 2 ca'

    assert components[4][0].lower() == 'cn'

    def visit_asn(data, item):
        '''
        visits asn items locating and saving relevant data
        '''
        if isinstance(item, IA5String):
            data['email'] = str(item).lower()
        elif isinstance(item, AttributeTypeAndValue):
            item_type = str(item[0])
            if item_type == '1.3.6.1.4.1.5734.1.1':
                data['name'] = str(decode(item[1])[0])
            elif item_type == '1.3.6.1.4.1.5734.1.2':
                data['surname1'] = str(decode(item[1])[0])
            elif item_type == '1.3.6.1.4.1.5734.1.3':
                data['surname2'] = str(decode(item[1])[0])
            elif item_type == '1.3.6.1.4.1.5734.1.4':
                data['nif'] = str(decode(item[1])[0])
        elif isinstance(item, AbstractConstructedAsn1Item) or isinstance(
                item, tuple):
            for child_item in item:
                visit_asn(data, child_item)

    # find subjectAltName, which should contain user's email address
    for i in xrange(cert.get_extension_count()):
        ext = cert.get_extension(i)
        if ext.get_short_name() == 'subjectAltName':
            alt_name = decode(ext.get_data(), asn1Spec=SubjectAltName())

            data = dict()
            visit_asn(data, alt_name)

            # check that everything was found
            assert data.has_key('nif')
            assert data.has_key('surname1')
            assert data.has_key('surname2')
            assert data.has_key('name')
            # email might not be found

            full_name = "%s %s %s" % (data['name'], data['surname1'],
                                      data['surname2'])
            full_name = " ".join(
                [i.capitalize() for i in full_name.split(" ")])
            # we can only store 30 chars in
            # django.contrib.auth.models.User.first_name field anyway
            full_name = full_name[:30]

            return data['nif'], full_name, data.get('email', None)

    raise Exception("subjectAltName not found in the certificate")