]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-ssl-iostream: openssl_cert_match_name() - add reason_r parameter
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 31 Oct 2017 22:12:24 +0000 (00:12 +0200)
committerTimo Sirainen <tss@dovecot.fi>
Mon, 6 Nov 2017 23:09:00 +0000 (01:09 +0200)
The returned string explains what exactly matched or why nothing matched.

src/lib-ssl-iostream/iostream-openssl-common.c
src/lib-ssl-iostream/iostream-openssl.c
src/lib-ssl-iostream/iostream-openssl.h
src/login-common/ssl-proxy-openssl.c

index ecc7294c40548e70927fd9c00ffdd846adf7b08a..6b6905329ab9e36970c3e74889922ee4d61b55ea 100644 (file)
@@ -154,7 +154,8 @@ static bool openssl_hostname_equals(const char *ssl_name, const char *host)
        return p != NULL && strcmp(ssl_name+2, p+1) == 0;
 }
 
-bool openssl_cert_match_name(SSL *ssl, const char *verify_name)
+bool openssl_cert_match_name(SSL *ssl, const char *verify_name,
+                            const char **reason_r)
 {
        X509 *cert;
        STACK_OF(GENERAL_NAME) *gnames;
@@ -165,6 +166,8 @@ bool openssl_cert_match_name(SSL *ssl, const char *verify_name)
        unsigned int i, count;
        bool ret;
 
+       *reason_r = NULL;
+
        cert = SSL_get_peer_certificate(ssl);
        i_assert(cert != NULL);
 
@@ -187,27 +190,44 @@ bool openssl_cert_match_name(SSL *ssl, const char *verify_name)
                if (gn->type == GEN_DNS) {
                        dns_names = TRUE;
                        dnsname = get_general_dns_name(gn);
-                       if (openssl_hostname_equals(dnsname, verify_name))
+                       if (openssl_hostname_equals(dnsname, verify_name)) {
+                               *reason_r = t_strdup_printf(
+                                       "Matches DNS name in SubjectAltNames: %s", dnsname);
                                break;
+                       }
                } else if (gn->type == GEN_IPADD) {
                        struct ip_addr ip_2;
                        i_zero(&ip_2);
                        dns_names = TRUE;
                        if (get_general_ip_addr(gn, &ip_2) == 0 &&
-                           net_ip_compare(&ip, &ip_2))
+                           net_ip_compare(&ip, &ip_2)) {
+                               *reason_r = t_strdup_printf(
+                                       "Matches IP in SubjectAltNames: %s", net_ip2addr(&ip_2));
                                break;
+                       }
                }
        }
        sk_GENERAL_NAME_pop_free(gnames, GENERAL_NAME_free);
 
        /* verify against CommonName only when there wasn't any DNS
           SubjectAltNames */
-       if (dns_names)
+       if (dns_names) {
+               i_assert(*reason_r != NULL);
                ret = i < count;
-       else if (openssl_hostname_equals(get_cname(cert), verify_name))
-               ret = TRUE;
-       else
-               ret = FALSE;
+       } else {
+               const char *cname = get_cname(cert);
+
+               if (openssl_hostname_equals(cname, verify_name)) {
+                       ret = TRUE;
+                       *reason_r = t_strdup_printf(
+                               "Matches to CommonName: %s", cname);
+               } else {
+                       *reason_r = t_strdup_printf(
+                               "No match to CommonName=%s or %u SubjectAltNames",
+                               cname, count);
+                       ret = FALSE;
+               }
+       }
        X509_free(cert);
        return ret;
 }
index 04156f96998d10e0ba8e2a0de308331d35632489..b242e2e61edc7ccf769d13ed51f89415389b170e 100644 (file)
@@ -591,10 +591,12 @@ static bool
 openssl_iostream_cert_match_name(struct ssl_iostream *ssl_io,
                                 const char *verify_name)
 {
+       const char *reason;
+
        if (!ssl_iostream_has_valid_client_cert(ssl_io))
                return FALSE;
 
-       return openssl_cert_match_name(ssl_io->ssl, verify_name);
+       return openssl_cert_match_name(ssl_io->ssl, verify_name, &reason);
 }
 
 static int openssl_iostream_handshake(struct ssl_iostream *ssl_io)
index 405dff15528bb4eeae8f7ed77d847a774533599c..d67de5207b0947b689999734c9dcc0b1619589c4 100644 (file)
@@ -82,7 +82,8 @@ void openssl_iostream_global_deinit(void);
 
 int openssl_iostream_load_key(const struct ssl_iostream_cert *set,
                              EVP_PKEY **pkey_r, const char **error_r);
-bool openssl_cert_match_name(SSL *ssl, const char *verify_name);
+bool openssl_cert_match_name(SSL *ssl, const char *verify_name,
+                            const char **reason_r);
 int openssl_get_protocol_options(const char *protocols);
 #define OPENSSL_ALL_PROTOCOL_OPTIONS \
        (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1)
index 7485a896f19235ea71f68cb46bb95102e219d0d0..b2432d9c63ccb8caf7e50aacb545e32fd4a2014e 100644 (file)
@@ -603,7 +603,9 @@ bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy)
 
 int ssl_proxy_cert_match_name(struct ssl_proxy *proxy, const char *verify_name)
 {
-       return openssl_cert_match_name(proxy->ssl, verify_name) ? 0 : -1;
+       const char *reason;
+
+       return openssl_cert_match_name(proxy->ssl, verify_name, &reason) ? 0 : -1;
 }
 
 const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy)