83 votes

Comment vérifier les noms alternatifs des sujets d'un certificat SSL/TLS ?

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

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 !

150voto

JoeSlav Points 1077

Pour obtenir les Subject Alternative Names (SAN) d'un certificat, utilisez la commande suivante :

openssl s_client -connect website.com:443 </dev/null 2>/dev/null | 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

Ensuite, le tuyau ( | ) dans cette commande :

openssl x509 -noout -text

Il prend le fichier de certificat et en sort tous les détails juteux. La fonction -noout l'empêche de produire le fichier de certificat (encodé en base64) lui-même, ce dont nous n'avons pas besoin. L'option -text lui indique d'afficher les détails du certificat sous forme de texte.

Normalement, il y a beaucoup de données de sortie (signature, émetteur, extensions, etc.) dont nous ne nous soucions pas, alors nous mettons en place un tuyau que en un simple grep :

grep DNS:

Étant donné que les entrées du SAN commencent par DNS: ne renvoie que les lignes qui contiennent cette information, en éliminant toutes les autres informations et en nous laissant l'information souhaitée.

Vous remarquerez que la commande ne se termine pas proprement ; openssl s_client agit en fait comme un client et laisse la connexion ouverte, en attente d'une entrée. Si vous voulez qu'il quitte immédiatement (par exemple pour analyser la sortie dans un shell script), pipez simplement echo en son sein :

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

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

Pour cela, vous n'avez pas besoin de l'option openssl s_client commande. Il suffit d'ajouter -in MyCertificate.crt sur le openssl x509 et une fois de plus, passer par grep, par exemple :

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

6voto

dAm2K Points 3283

Il est également possible d'utiliser la fonctionnalité openssl intégrée :

openssl s_client -connect website.com:443 </dev/null | openssl x509 -noout -ext subjectAltName

3voto

jww Points 9514

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

Il peut y avoir plusieurs SAN dans un certificat X509. Ce qui suit est tiré du wiki OpenSSL à l'adresse suivante Client SSL/TLS . Il passe en 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 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);

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X