示例#1
0
/*
Function:
CheckX509Hostname

Used by System.Net.Security's Unix CertModule to identify if the certificate presented by
the server is applicable to the hostname requested.

Return values:
1 if the hostname is a match
0 if the hostname is not a match
Any negative number indicates an error in the arguments.
*/
extern int32_t CryptoNative_CheckX509Hostname(X509* x509, const char* hostname, int32_t cchHostname)
{
    if (!x509)
        return -2;
    if (cchHostname > 0 && !hostname)
        return -3;
    if (cchHostname < 0)
        return -4;

    int subjectNid = NID_commonName;
    int sanGenType = GEN_DNS;
    GENERAL_NAMES* san = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
    char readSubject = 1;
    int success = 0;

    // RFC2818 says that if ANY dNSName alternative name field is present then
    // we should ignore the subject common name.

    if (san)
    {
        int i;
        int count = sk_GENERAL_NAME_num(san);

        for (i = 0; i < count; ++i)
        {
            GENERAL_NAME* sanEntry = sk_GENERAL_NAME_value(san, i);

            if (sanEntry->type != sanGenType)
            {
                continue;
            }

            readSubject = 0;

            if (CheckX509HostnameMatch(sanEntry->d.dNSName, hostname, cchHostname, 1))
            {
                success = 1;
                break;
            }
        }

        GENERAL_NAMES_free(san);
    }

    if (readSubject && !success)
    {
        // This is a shared/interor pointer, do not free!
        X509_NAME* subject = X509_get_subject_name(x509);

        if (subject)
        {
            int i = -1;

            while ((i = X509_NAME_get_index_by_NID(subject, subjectNid, i)) >= 0)
            {
                // Shared/interior pointers, do not free!
                X509_NAME_ENTRY* nameEnt = X509_NAME_get_entry(subject, i);
                ASN1_STRING* cn = X509_NAME_ENTRY_get_data(nameEnt);

                if (CheckX509HostnameMatch(cn, hostname, cchHostname, 0))
                {
                    success = 1;
                    break;
                }
            }
        }
    }

    return success;
}
示例#2
0
/*
Function:
CheckX509IpAddress

Used by System.Net.Security's Unix CertModule to identify if the certificate presented by
the server is applicable to the hostname (an IP address) requested.

Return values:
1 if the hostname is a match
0 if the hostname is not a match
Any negative number indicates an error in the arguments.
*/
extern int32_t CryptoNative_CheckX509IpAddress(
    X509* x509, const uint8_t* addressBytes, int32_t addressBytesLen, const char* hostname, int32_t cchHostname)
{
    if (!x509)
        return -2;
    if (cchHostname > 0 && !hostname)
        return -3;
    if (cchHostname < 0)
        return -4;
    if (addressBytesLen < 0)
        return -5;
    if (!addressBytes)
        return -6;

    int subjectNid = NID_commonName;
    int sanGenType = GEN_IPADD;
    GENERAL_NAMES* san = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
    int success = 0;

    if (san)
    {
        int i;
        int count = sk_GENERAL_NAME_num(san);

        for (i = 0; i < count; ++i)
        {
            GENERAL_NAME* sanEntry = sk_GENERAL_NAME_value(san, i);
            ASN1_OCTET_STRING* ipAddr;

            if (sanEntry->type != sanGenType)
            {
                continue;
            }

            ipAddr = sanEntry->d.iPAddress;

            if (!ipAddr || !ipAddr->data || ipAddr->length != addressBytesLen)
            {
                continue;
            }

            if (!memcmp(addressBytes, ipAddr->data, (size_t)addressBytesLen))
            {
                success = 1;
                break;
            }
        }

        GENERAL_NAMES_free(san);
    }

    if (!success)
    {
        // This is a shared/interor pointer, do not free!
        X509_NAME* subject = X509_get_subject_name(x509);

        if (subject)
        {
            int i = -1;

            while ((i = X509_NAME_get_index_by_NID(subject, subjectNid, i)) >= 0)
            {
                // Shared/interior pointers, do not free!
                X509_NAME_ENTRY* nameEnt = X509_NAME_get_entry(subject, i);
                ASN1_STRING* cn = X509_NAME_ENTRY_get_data(nameEnt);

                if (CheckX509HostnameMatch(cn, hostname, cchHostname, 0))
                {
                    success = 1;
                    break;
                }
            }
        }
    }

    return success;
}
示例#3
0
文件: apibridge.c 项目: dotnet/corefx
int32_t local_X509_check_host(X509* x509, const char* name, size_t namelen, unsigned int flags, char** peername)
{
    assert(peername == NULL);
    assert(flags == X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
    (void)flags;
    (void)peername;

    GENERAL_NAMES* san = (GENERAL_NAMES*)(X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL));
    int readSubject = 1;
    int success = 0;

    // RFC2818 says that if ANY dNSName alternative name field is present then
    // we should ignore the subject common name.

    if (san != NULL)
    {
        int count = sk_GENERAL_NAME_num(san);

        for (int i = 0; i < count; ++i)
        {
            GENERAL_NAME* sanEntry = sk_GENERAL_NAME_value(san, i);

            if (sanEntry->type != GEN_DNS)
            {
                continue;
            }

            readSubject = 0;

            // A GEN_DNS name is supposed to be a V_ASN1_IA5STRING.
            // If it isn't, we don't know how to read it.
            if (CheckX509HostnameMatch(sanEntry->d.dNSName, name, (int)namelen, V_ASN1_IA5STRING))
            {
                success = 1;
                break;
            }
        }

        GENERAL_NAMES_free(san);
    }

    if (readSubject)
    {
        assert(success == 0);

        // This is a shared/interor pointer, do not free!
        X509_NAME* subject = X509_get_subject_name(x509);

        if (subject != NULL)
        {
            int i = -1;

            while ((i = X509_NAME_get_index_by_NID(subject, NID_commonName, i)) >= 0)
            {
                // Shared/interior pointers, do not free!
                X509_NAME_ENTRY* nameEnt = X509_NAME_get_entry(subject, i);
                ASN1_STRING* cn = X509_NAME_ENTRY_get_data(nameEnt);

                // For compatibility with previous .NET Core builds, allow any type of
                // string for CN, provided it ended up with a single-byte encoding (otherwise
                // strncasecmp simply won't match).
                if (CheckX509HostnameMatch(cn, name, (int)namelen, cn->type))
                {
                    success = 1;
                    break;
                }
            }
        }
    }

    return success;
}