diff options
author | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-14 21:28:19 +0200 |
---|---|---|
committer | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-14 21:28:19 +0200 |
commit | 1087d4df2a7342d2832ba3bab1843bf4a3040775 (patch) | |
tree | 96cd6ea198cc542f29c0660d5e5f7083af84d711 /src/ssl_verify.c |
Diffstat (limited to 'src/ssl_verify.c')
-rw-r--r-- | src/ssl_verify.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/ssl_verify.c b/src/ssl_verify.c new file mode 100644 index 0000000..474c45b --- /dev/null +++ b/src/ssl_verify.c @@ -0,0 +1,63 @@ +/** + @file ssl_verify.c + @author web, feh -- parts of code borrowed from Pavel Shramov; tx Peter Conrad + @brief Compares 'hostname' against SubAltName DNS:hostname + DN: /CN=hostname +*/ +#include "ucspissl.h" +#include "case.h" +#include "str.h" + +int ssl_verify(SSL *ssl,const char *hostname,stralloc *dnsout) +{ + X509 *cert; + STACK_OF(GENERAL_NAME) *extensions; + const GENERAL_NAME *ext; + char buf[SSL_NAME_LEN]; + char *dnsname = 0; + int i; + int num; + int len; + int dname = 0; + +#if (OPENSSL_VERSION_NUMBER > 0x30100000L) + cert = SSL_get1_peer_certificate(ssl); +#else + cert = SSL_get_peer_certificate(ssl); +#endif + if (!cert) return -1; + + if (SSL_get_verify_result(ssl) != X509_V_OK) return -2; + + if (hostname) { + if (!stralloc_copys(dnsout,"")) return 1; + extensions = X509_get_ext_d2i(cert,NID_subject_alt_name,0,0); + num = sk_GENERAL_NAME_num(extensions); /* num = 0, if no SAN extensions */ + + for (i = 0; i < num; ++i) { + ext = sk_GENERAL_NAME_value(extensions,i); + if (ext->type == GEN_DNS) { + if (ASN1_STRING_type(ext->d.dNSName) != V_ASN1_IA5STRING) continue; +#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L)) + dnsname = (char *)ASN1_STRING_data(ext->d.dNSName); +#else + dnsname = (char *)ASN1_STRING_get0_data(ext->d.dNSName); +#endif + len = ASN1_STRING_length(ext->d.dNSName); + if (len != str_len(dnsname)) continue; + if (!stralloc_copyb(dnsout,dnsname,len)) return 1; + if (case_diffs((char *)hostname,dnsname) == 0) return 0; + dname = 1; + } + } + + if (!dname) { + X509_NAME_get_text_by_NID(X509_get_subject_name(cert),NID_commonName,buf,sizeof(buf)); + buf[SSL_NAME_LEN - 1] = 0; + if (!stralloc_copyb(dnsout,buf,str_len(buf))) return 1; + if (case_diffs((char *)hostname,buf) == 0) return 0; + } + + return -3; + } + return 0; +} |