示例#1
0
def _get_crl_dp(certificate):
    if lib.OPENSSL_VERSION_NUMBER >= 0x10001000:
        lib.X509_check_ca(certificate)
    dps = lib.X509_get_ext_d2i(certificate, lib.NID_crl_distribution_points,
                               ffi.NULL, ffi.NULL)
    if dps is ffi.NULL:
        return None

    lst = []
    count = lib.sk_DIST_POINT_num(dps)
    for i in range(count):
        dp = lib.sk_DIST_POINT_value(dps, i)
        if not dp.distpoint:
            return None
        gns = dp.distpoint.name.fullname

        jcount = lib.sk_GENERAL_NAME_num(gns)
        for j in range(jcount):
            gn = lib.sk_GENERAL_NAME_value(gns, j)
            if gn.type != lib.GEN_URI:
                continue

            uri = gn.d.uniformResourceIdentifier
            ouri = _str_with_len(uri.data, uri.length)
            lst.append(ouri)

    if lib.OPENSSL_VERSION_NUMBER < 0x10001000:
        lib.sk_DIST_POINT_free(dps)

    if len(lst) == 0: return None
    return tuple(lst)
示例#2
0
def _get_peer_alt_names(certificate):
    # this code follows the procedure outlined in
    # OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print()
    # function to extract the STACK_OF(GENERAL_NAME),
    # then iterates through the stack to add the
    # names.
    peer_alt_names = []

    if certificate == ffi.NULL:
        return None

    # get a memory buffer
    biobuf = lib.BIO_new(lib.BIO_s_mem())

    i = -1
    while True:
        i = lib.X509_get_ext_by_NID(certificate, lib.NID_subject_alt_name, i)
        if i < 0:
            break

        # now decode the altName
        ext = lib.X509_get_ext(certificate, i)
        method = lib.X509V3_EXT_get(ext)
        if method is ffi.NULL:
            raise ssl_error("No method for internalizing subjectAltName!")

        ext_data = lib.X509_EXTENSION_get_data(ext)
        ext_data_len = ext_data.length
        ext_data_value = ffi.new("unsigned char**", ffi.NULL)
        ext_data_value[0] = ext_data.data

        if method.it != ffi.NULL:
            names = lib.ASN1_item_d2i(ffi.NULL, ext_data_value, ext_data_len,
                                      lib.ASN1_ITEM_ptr(method.it))
        else:
            names = method.d2i(ffi.NULL, ext_data_value, ext_data_len)

        names = ffi.cast("GENERAL_NAMES*", names)
        count = lib.sk_GENERAL_NAME_num(names)
        for j in range(count):
            # get a rendering of each name in the set of names
            name = lib.sk_GENERAL_NAME_value(names, j)
            _type = name.type
            if _type == lib.GEN_DIRNAME:
                # we special-case DirName as a tuple of
                # tuples of attributes
                v = _create_tuple_for_X509_NAME(name.d.dirn)
                peer_alt_names.append(("DirName", v))
            # GENERAL_NAME_print() doesn't handle NULL bytes in ASN1_string
            # correctly, CVE-2013-4238
            elif _type == lib.GEN_EMAIL:
                v = _string_from_asn1(name.d.rfc822Name)
                peer_alt_names.append(("email", v))
            elif _type == lib.GEN_DNS:
                v = _string_from_asn1(name.d.dNSName)
                peer_alt_names.append(("DNS", v))
            elif _type == lib.GEN_URI:
                v = _string_from_asn1(name.d.uniformResourceIdentifier)
                peer_alt_names.append(("URI", v))
            elif _type == lib.GEN_RID:
                v = "Registered ID"
                buf = ffi.new("char[2048]")

                length = lib.OBJ_obj2txt(buf, 2047, name.d.rid, 0)
                if length < 0:
                    # TODO _setSSLError(NULL, 0, __FILE__, __LINE__);
                    raise NotImplementedError
                elif length >= 2048:
                    v = "<INVALID>"
                else:
                    v = _str_with_len(buf, length)
                peer_alt_names.append(("Registered ID", v))
            else:
                # for everything else, we use the OpenSSL print form
                if _type not in (lib.GEN_OTHERNAME, lib.GEN_X400, \
                                 lib.GEN_EDIPARTY, lib.GEN_IPADD, lib.GEN_RID):
                    warnings.warn("Unknown general type %d" % _type,
                                  RuntimeWarning)
                    continue
                lib.BIO_reset(biobuf)
                lib.GENERAL_NAME_print(biobuf, name)
                v = _bio_get_str(biobuf)
                idx = v.find(":")
                if idx == -1:
                    raise ValueError("Invalid value %s", v)
                peer_alt_names.append((v[:idx], v[idx + 1:]))

        free_func_addr = ffi.addressof(lib, "GENERAL_NAME_free")
        lib.sk_GENERAL_NAME_pop_free(names, free_func_addr)
    lib.BIO_free(biobuf)
    if peer_alt_names is not None:
        return tuple(peer_alt_names)
    return peer_alt_names