From 44fd00e6d02859d6068fce899429aaa17a23ce9c Mon Sep 17 00:00:00 2001 From: Joel Pelaez Jorge Date: Sun, 3 Aug 2025 19:54:55 -0500 Subject: [PATCH] feat: check hostname against the certificate SAN and CN This change allows check target domain name againts the certificate Subject Alternate Names (SAN) and Subject CommonName (CN). This feature is implemented using X509_check_host OpenSSL method. The translations files are updated by a new error string added. --- src/en.po | 34 ++++++++++++++++++++-------------- src/es.po | 34 ++++++++++++++++++++-------------- src/fr.po | 37 ++++++++++++++++++++++--------------- src/sslcheck.c | 18 ++++++++++++++++++ src/sslcheck.pot | 31 ++++++++++++++++++------------- 5 files changed, 98 insertions(+), 56 deletions(-) diff --git a/src/en.po b/src/en.po index 574b81c..0e577c4 100644 --- a/src/en.po +++ b/src/en.po @@ -16,70 +16,76 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: sslcheck.c:58 sslcheck.c:64 +#: sslcheck.c:59 sslcheck.c:65 #, c-format msgid "SSLCHECK %s (%s, %s)\n" msgstr "SSLCHECK %s (%s, %s)\n" -#: sslcheck.c:66 +#: sslcheck.c:67 #, c-format msgid "" "sslcheck prints domain and remainder of days until cert " "expires\n" msgstr "" -"sslcheck prints domain and remainder of days until cert expires\n" +"sslcheck prints domain and remainder of days until cert " +"expires\n" -#: sslcheck.c:67 +#: sslcheck.c:68 #, c-format msgid "-s --short prints only the days\n" msgstr "-s --short prints only the days\n" -#: sslcheck.c:68 +#: sslcheck.c:69 #, c-format msgid "-j --json prints output as JSON\n" msgstr "-j --json prints output as JSON\n" -#: sslcheck.c:69 +#: sslcheck.c:70 #, c-format msgid "-p --port use custom port instead of 443\n" msgstr "-p --port use custom port instead of 443\n" -#: sslcheck.c:70 +#: sslcheck.c:71 #, c-format msgid "-h --help prints this menu\n" msgstr "-h --help prints this menu\n" -#: sslcheck.c:71 +#: sslcheck.c:72 #, c-format msgid "-v --version prints version\n" msgstr "-v --version prints version\n" -#: sslcheck.c:138 +#: sslcheck.c:150 #, c-format msgid "Error creating SSL context\n" msgstr "Error creating SSL context\n" -#: sslcheck.c:153 +#: sslcheck.c:165 #, c-format msgid "Error getting SSL object\n" msgstr "Error getting SSL object\n" -#: sslcheck.c:166 +#: sslcheck.c:178 #, c-format msgid "Error connecting to %s\n" msgstr "Error connecting to %s\n" -#: sslcheck.c:177 +#: sslcheck.c:189 #, c-format msgid "No certificate found for %s\n" msgstr "No certificate found for %s\n" -#: sslcheck.c:188 +#: sslcheck.c:212 #, c-format msgid "Could not calculate certificate expiration\n" msgstr "Could not calculate certificate expiration\n" -#: sslcheck.c:195 +#: sslcheck.c:219 #, c-format msgid "Domain: %s | Days until Certification expires: %d\n" msgstr "Domain: %s | Days until Certification expires: %d\n" + +#: sslcheck.c:201 +#, c-format +msgid "Certificate doesn't match with hostname\n" +msgstr "Certificate doesn't match with hostname\n" diff --git a/src/es.po b/src/es.po index 31fb98b..96cd95a 100644 --- a/src/es.po +++ b/src/es.po @@ -16,70 +16,76 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: sslcheck.c:58 sslcheck.c:64 +#: sslcheck.c:59 sslcheck.c:65 #, c-format msgid "SSLCHECK %s (%s, %s)\n" msgstr "SSLCHECK %s (%s, %s)\n" -#: sslcheck.c:66 +#: sslcheck.c:67 #, c-format msgid "" "sslcheck prints domain and remainder of days until cert " "expires\n" msgstr "" -"sslcheck muestra el dominio y los días restantes hasta que expire el certificado\n" +"sslcheck muestra el dominio y los días restantes hasta que " +"expire el certificado\n" -#: sslcheck.c:67 +#: sslcheck.c:68 #, c-format msgid "-s --short prints only the days\n" msgstr "-s --short muestra solo los días\n" -#: sslcheck.c:68 +#: sslcheck.c:69 #, c-format msgid "-j --json prints output as JSON\n" msgstr "-j --json muestra la salida en formato JSON\n" -#: sslcheck.c:69 +#: sslcheck.c:70 #, c-format msgid "-p --port use custom port instead of 443\n" msgstr "-p --port usa un puerto distinto al 443\n" -#: sslcheck.c:70 +#: sslcheck.c:71 #, c-format msgid "-h --help prints this menu\n" msgstr "-h --help muestra este menú\n" -#: sslcheck.c:71 +#: sslcheck.c:72 #, c-format msgid "-v --version prints version\n" msgstr "-v --version muestra la versión\n" -#: sslcheck.c:138 +#: sslcheck.c:150 #, c-format msgid "Error creating SSL context\n" msgstr "Error creando el contexto SSL\n" -#: sslcheck.c:153 +#: sslcheck.c:165 #, c-format msgid "Error getting SSL object\n" msgstr "Error obteniendo el objeto SSL\n" -#: sslcheck.c:166 +#: sslcheck.c:178 #, c-format msgid "Error connecting to %s\n" msgstr "Error al conectar a %s\n" -#: sslcheck.c:177 +#: sslcheck.c:189 #, c-format msgid "No certificate found for %s\n" msgstr "No se encontró certificado para %s\n" -#: sslcheck.c:188 +#: sslcheck.c:212 #, c-format msgid "Could not calculate certificate expiration\n" msgstr "No se pudo calcular la expiración del certificado\n" -#: sslcheck.c:195 +#: sslcheck.c:219 #, c-format msgid "Domain: %s | Days until Certification expires: %d\n" msgstr "Dominio: %s | Días hasta que vence el certificado: %d\n" + +#: sslcheck.c:201 +#, c-format +msgid "Certificate doesn't match with hostname\n" +msgstr "El certificado no coincide con el nombre del host\n" diff --git a/src/fr.po b/src/fr.po index 6ea0a66..957a731 100644 --- a/src/fr.po +++ b/src/fr.po @@ -16,70 +16,77 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: sslcheck.c:58 sslcheck.c:64 +#: sslcheck.c:59 sslcheck.c:65 #, c-format msgid "SSLCHECK %s (%s, %s)\n" msgstr "SSLCHECK %s (%s, %s)\n" -#: sslcheck.c:66 +#: sslcheck.c:67 #, c-format msgid "" "sslcheck prints domain and remainder of days until cert " "expires\n" msgstr "" -"sslcheck affiche le domaine et le nombre de jours restants avant l'expiration du certificat\n" +"sslcheck affiche le domaine et le nombre de jours restants " +"avant l'expiration du certificat\n" -#: sslcheck.c:67 +#: sslcheck.c:68 #, c-format msgid "-s --short prints only the days\n" msgstr "-s --short affiche uniquement le nombre de jours\n" -#: sslcheck.c:68 +#: sslcheck.c:69 #, c-format msgid "-j --json prints output as JSON\n" msgstr "-j --json affiche la sortie au format JSON\n" -#: sslcheck.c:69 +#: sslcheck.c:70 #, c-format msgid "-p --port use custom port instead of 443\n" -msgstr "-p --port utilise un port personnalisé à la place de 443\n" +msgstr "" +"-p --port utilise un port personnalisé à la place de 443\n" -#: sslcheck.c:70 +#: sslcheck.c:71 #, c-format msgid "-h --help prints this menu\n" msgstr "-h --help affiche ce menu\n" -#: sslcheck.c:71 +#: sslcheck.c:72 #, c-format msgid "-v --version prints version\n" msgstr "-v --version affiche la version\n" -#: sslcheck.c:138 +#: sslcheck.c:150 #, c-format msgid "Error creating SSL context\n" msgstr "Erreur lors de la création du contexte SSL\n" -#: sslcheck.c:153 +#: sslcheck.c:165 #, c-format msgid "Error getting SSL object\n" msgstr "Erreur lors de l'obtention de l'objet SSL\n" -#: sslcheck.c:166 +#: sslcheck.c:178 #, c-format msgid "Error connecting to %s\n" msgstr "Erreur de connexion à %s\n" -#: sslcheck.c:177 +#: sslcheck.c:189 #, c-format msgid "No certificate found for %s\n" msgstr "Aucun certificat trouvé pour %s\n" -#: sslcheck.c:188 +#: sslcheck.c:212 #, c-format msgid "Could not calculate certificate expiration\n" msgstr "Impossible de calculer l'expiration du certificat\n" -#: sslcheck.c:195 +#: sslcheck.c:219 #, c-format msgid "Domain: %s | Days until Certification expires: %d\n" msgstr "Domaine: %s | Jours restants avant expiration du certificat: %d\n" + +#: sslcheck.c:201 +#, c-format +msgid "Certificate doesn't match with hostname\n" +msgstr "Le certificat ne correspond pas au nom d'hôte\n" diff --git a/src/sslcheck.c b/src/sslcheck.c index 5fdd973..ded95fe 100644 --- a/src/sslcheck.c +++ b/src/sslcheck.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "sslcheck.h" @@ -83,6 +84,11 @@ int days_until_expiration(X509 *cert) { return days; } +// Valida si el dominio solicitado se encuentra en el certificado +int hostname_in_certificate(X509 *cert, const char *hostname) { + return X509_check_host(cert, hostname, 0, 0, NULL); +} + int main(int argc, char **argv) { setlocale(LC_ALL, ""); bindtextdomain("sslcheck", LOCALE_PATH); @@ -186,6 +192,18 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + int valid_name = hostname_in_certificate(cert, hostname); + if (!valid_name) { + if (json_output) { + printf("{\"domain\": \"%s\", \"days\": null}\n", hostname); + } + else + fprintf(stderr, _("Certificate doesn't match with hostname\n")); + BIO_free_all(bio); + SSL_CTX_free(ctx); + return EXIT_FAILURE; + } + int days = days_until_expiration(cert); if (days < 0) { if (json_output) diff --git a/src/sslcheck.pot b/src/sslcheck.pot index 0eca454..53d4a56 100644 --- a/src/sslcheck.pot +++ b/src/sslcheck.pot @@ -17,69 +17,74 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: sslcheck.c:58 sslcheck.c:64 +#: sslcheck.c:59 sslcheck.c:65 #, c-format msgid "SSLCHECK %s (%s, %s)\n" msgstr "" -#: sslcheck.c:66 +#: sslcheck.c:67 #, c-format msgid "" "sslcheck prints domain and remainder of days until cert " "expires\n" msgstr "" -#: sslcheck.c:67 +#: sslcheck.c:68 #, c-format msgid "-s --short prints only the days\n" msgstr "" -#: sslcheck.c:68 +#: sslcheck.c:69 #, c-format msgid "-j --json prints output as JSON\n" msgstr "" -#: sslcheck.c:69 +#: sslcheck.c:70 #, c-format msgid "-p --port use custom port instead of 443\n" msgstr "" -#: sslcheck.c:70 +#: sslcheck.c:71 #, c-format msgid "-h --help prints this menu\n" msgstr "" -#: sslcheck.c:71 +#: sslcheck.c:72 #, c-format msgid "-v --version prints version\n" msgstr "" -#: sslcheck.c:138 +#: sslcheck.c:150 #, c-format msgid "Error creating SSL context\n" msgstr "" -#: sslcheck.c:153 +#: sslcheck.c:165 #, c-format msgid "Error getting SSL object\n" msgstr "" -#: sslcheck.c:166 +#: sslcheck.c:178 #, c-format msgid "Error connecting to %s\n" msgstr "" -#: sslcheck.c:177 +#: sslcheck.c:189 #, c-format msgid "No certificate found for %s\n" msgstr "" -#: sslcheck.c:188 +#: sslcheck.c:212 #, c-format msgid "Could not calculate certificate expiration\n" msgstr "" -#: sslcheck.c:195 +#: sslcheck.c:219 #, c-format msgid "Domain: %s | Days until Certification expires: %d\n" msgstr "" + +#: sslcheck.c:201 +#, c-format +msgid "Certificate doesn't match with hostname\n" +msgstr ""