web-dev-qa-db-fra.com

Comment vérifier les autres noms de sujet pour un certificat SSL / TLS?

Existe-t-il un moyen de vérifier par programme les noms alternatifs de sujet d'un certificat SSL SAN SSL?

En utilisant, par exemple, la commande suivante, je peux obtenir de nombreuses informations mais pas tous les SAN:

openssl s_client -connect www.website.com:443 

Merci beaucoup!

51
JoeSlav

Pour obtenir les noms alternatifs de sujet (SAN) pour un certificat, utilisez la commande suivante:

openssl s_client -connect website.com:443 | openssl x509 -noout -text | grep DNS:

Tout d'abord, cette commande se connecte au site que nous voulons (website.com, port 443 pour SSL):

openssl s_client -connect website.com:443

Puis pipe (|) que dans cette commande:

openssl x509 -noout -text

Cela prend le fichier de certificat et génère tous ses détails juteux. Le -noout flag l'empêche de sortir le fichier de certificat (encodé en base64) lui-même, dont nous n'avons pas besoin. Le -text flag lui indique de sortir les détails du certificat sous forme de texte.

Normalement, il y a beaucoup de sorties (signature, émetteur, extensions, etc.) dont nous ne nous soucions pas, alors nous redirige que dans un simple grep:

grep DNS:

Étant donné que les entrées SAN commencent par DNS: cela ne renvoie que les lignes qui contiennent cela, supprimant toutes les autres informations et nous laissant les informations souhaitées.

Vous pouvez noter que la commande ne se ferme pas proprement; openssl s_client agit en fait comme un client et laisse la connexion ouverte, en attente de saisie. Si vous voulez qu'il se ferme immédiatement (par exemple pour analyser la sortie dans un script Shell), il suffit de diriger echo dedans:

echo | openssl s_client -connect website.com:443 | openssl x509 -noout -text | grep DNS:

Comment puis-je obtenir le SAN directement à partir d'un fichier?

Pour cela, vous n'avez pas besoin du openssl s_client commande. Ajoutez simplement -in MyCertificate.crt sur le openssl x509 commande et rediriger à travers grep, par exemple:

openssl x509 -noout -text -in MyCertificate.crt | grep DNS:
85
JoeSlav

Existe-t-il un moyen de vérifier par programme les noms alternatifs d'un certificat SSL SAN SSL?

Il peut y avoir plusieurs SAN dans un certificat X509. Ce qui suit provient du wiki OpenSSL à SSL/TLS Client . Il boucle sur les noms et les imprime.

Vous obtenez le X509* à partir d'une fonction comme SSL_get_peer_certificate à partir d'une connexion TLS, d2i_X509 de mémoire ou PEM_read_bio_X509 à partir du système de fichiers.

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: <not available>\n", label);

}
2
jww