summaryrefslogtreecommitdiff
path: root/src/ssl_verify.c
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-07-14 21:28:19 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-07-14 21:28:19 +0200
commit1087d4df2a7342d2832ba3bab1843bf4a3040775 (patch)
tree96cd6ea198cc542f29c0660d5e5f7083af84d711 /src/ssl_verify.c
add version 0.12.10HEADmaster
Diffstat (limited to 'src/ssl_verify.c')
-rw-r--r--src/ssl_verify.c63
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;
+}