How to Check Subject Alternative Names for a SSL/TLS Certificate?

后端 未结 4 1484
北海茫月
北海茫月 2020-12-12 16:27

Is there a way to programmatically check the Subject Alternative Names of a SAN SSL cert?

Using, for instance, the following command I can get many info but not all

4条回答
  •  情深已故
    2020-12-12 16:46

    Is there a way to programmatically check the Alternative Names of a SAN SSL cert?

    There could be multiple SANs in a X509 certificate. The following is from the OpenSSL wiki at SSL/TLS Client. It loops over the names and prints them.

    You get the X509* from a function like SSL_get_peer_certificate from a TLS connection, d2i_X509 from memory or PEM_read_bio_X509 from the filesystem.

    void print_san_name(const char* label, X509* const cert)
    {
        int success = 0;
        GENERAL_NAMES* names = NULL;
        unsigned char* utf8 = NULL;
    
        do
        {
            if(!cert) break; /* failed */
    
            names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
            if(!names) break;
    
            int i = 0, count = sk_GENERAL_NAME_num(names);
            if(!count) break; /* failed */
    
            for( i = 0; i < count; ++i )
            {
                GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
                if(!entry) continue;
    
                if(GEN_DNS == entry->type)
                {
                    int len1 = 0, len2 = -1;
    
                    len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
                    if(utf8) {
                        len2 = (int)strlen((const char*)utf8);
                    }
    
                    if(len1 != len2) {
                        fprintf(stderr, "  Strlen and ASN1_STRING size do not match (embedded null?): %d vs %d\n", len2, len1);
                    }
    
                    /* If there's a problem with string lengths, then     */
                    /* we skip the candidate and move on to the next.     */
                    /* Another policy would be to fails since it probably */
                    /* indicates the client is under attack.              */
                    if(utf8 && len1 && len2 && (len1 == len2)) {
                        fprintf(stdout, "  %s: %s\n", label, utf8);
                        success = 1;
                    }
    
                    if(utf8) {
                        OPENSSL_free(utf8), utf8 = NULL;
                    }
                }
                else
                {
                    fprintf(stderr, "  Unknown GENERAL_NAME type: %d\n", entry->type);
                }
            }
    
        } while (0);
    
        if(names)
            GENERAL_NAMES_free(names);
    
        if(utf8)
            OPENSSL_free(utf8);
    
        if(!success)
            fprintf(stdout, "  %s: \n", label);
    
    }
    

提交回复
热议问题