]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-ssl-iostream: ssl_iostream_cert_match_name() - add reason_r parameter
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 31 Oct 2017 22:18:23 +0000 (00:18 +0200)
committerTimo Sirainen <tss@dovecot.fi>
Mon, 6 Nov 2017 23:09:00 +0000 (01:09 +0200)
The callers were also changed to add the reason to error messages.

src/lib-ssl-iostream/iostream-openssl.c
src/lib-ssl-iostream/iostream-ssl-private.h
src/lib-ssl-iostream/iostream-ssl.c
src/lib-ssl-iostream/iostream-ssl.h

index b242e2e61edc7ccf769d13ed51f89415389b170e..221ae0acd66d14e49ccfc8dcc08817018c367de9 100644 (file)
@@ -589,19 +589,19 @@ int openssl_iostream_handle_error(struct ssl_iostream *ssl_io, int ret,
 
 static bool
 openssl_iostream_cert_match_name(struct ssl_iostream *ssl_io,
-                                const char *verify_name)
+                                const char *verify_name, const char **reason_r)
 {
-       const char *reason;
-
-       if (!ssl_iostream_has_valid_client_cert(ssl_io))
+       if (!ssl_iostream_has_valid_client_cert(ssl_io)) {
+               *reason_r = "Invalid certificate";
                return FALSE;
+       }
 
-       return openssl_cert_match_name(ssl_io->ssl, verify_name, &reason);
+       return openssl_cert_match_name(ssl_io->ssl, verify_name, reason_r);
 }
 
 static int openssl_iostream_handshake(struct ssl_iostream *ssl_io)
 {
-       const char *error = NULL;
+       const char *reason, *error = NULL;
        int ret;
 
        i_assert(!ssl_io->handshaked);
@@ -631,10 +631,10 @@ static int openssl_iostream_handshake(struct ssl_iostream *ssl_io)
                        ssl_io->handshake_failed = TRUE;
                }
        } else if (ssl_io->connected_host != NULL && !ssl_io->handshake_failed) {
-               if (!ssl_iostream_cert_match_name(ssl_io, ssl_io->connected_host)) {
+               if (!ssl_iostream_cert_match_name(ssl_io, ssl_io->connected_host, &reason)) {
                        openssl_iostream_set_error(ssl_io, t_strdup_printf(
-                               "SSL certificate doesn't match expected host name %s",
-                               ssl_io->connected_host));
+                               "SSL certificate doesn't match expected host name %s: %s",
+                               ssl_io->connected_host, reason));
                        ssl_io->handshake_failed = TRUE;
                }
        }
index 2242f63609aab9584841d5527c9801297e1f2957..b5f16112e7d7688848f336856fa2b2cbbafbbaf1 100644 (file)
@@ -30,7 +30,8 @@ struct iostream_ssl_vfuncs {
        bool (*has_handshake_failed)(const struct ssl_iostream *ssl_io);
        bool (*has_valid_client_cert)(const struct ssl_iostream *ssl_io);
        bool (*has_broken_client_cert)(struct ssl_iostream *ssl_io);
-       bool (*cert_match_name)(struct ssl_iostream *ssl_io, const char *name);
+       bool (*cert_match_name)(struct ssl_iostream *ssl_io, const char *name,
+                               const char **reason_r);
        const char *(*get_peer_name)(struct ssl_iostream *ssl_io);
        const char *(*get_server_name)(struct ssl_iostream *ssl_io);
        const char *(*get_compression)(struct ssl_iostream *ssl_io);
index f23819d37f3e16c720967370b071af56e80826b3..6656698c8012e73e1670c666070874a7f22c1dea 100644 (file)
@@ -187,14 +187,17 @@ bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io)
        return ssl_vfuncs->has_broken_client_cert(ssl_io);
 }
 
-bool ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name)
+bool ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name,
+                                 const char **reason_r)
 {
-       return ssl_vfuncs->cert_match_name(ssl_io, name);
+       return ssl_vfuncs->cert_match_name(ssl_io, name, reason_r);
 }
 
 int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io,
                                     const char *host, const char **error_r)
 {
+       const char *reason;
+
        if (!ssl_iostream_has_valid_client_cert(ssl_io)) {
                if (!ssl_iostream_has_broken_client_cert(ssl_io))
                        *error_r = "SSL certificate not received";
@@ -204,10 +207,10 @@ int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io,
                                *error_r = "Received invalid SSL certificate";
                }
                return -1;
-       } else if (!ssl_iostream_cert_match_name(ssl_io, host)) {
+       } else if (!ssl_iostream_cert_match_name(ssl_io, host, &reason)) {
                *error_r = t_strdup_printf(
-                       "SSL certificate doesn't match expected host name %s",
-                       host);
+                       "SSL certificate doesn't match expected host name %s: %s",
+                       host, reason);
                return -1;
        }
        return 0;
index f3e5fef6b9c1f09979a6be1d71eeac8a7ff335e8..86c569a5a7d6e7c18f9613987d461730c5341078 100644 (file)
@@ -80,8 +80,13 @@ bool ssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io);
 bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io);
 int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io,
                                     const char *host, const char **error_r);
-/* Returns TRUE if the given name matches the SSL stream's certificate. */
-bool ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name);
+/* Returns TRUE if the given name matches the SSL stream's certificate.
+   The returned reason is a human-readable string explaining what exactly
+   matched the name, or why nothing matched. Note that this function works
+   only if the certificate was valid - using it when certificate is invalid
+   will always return FALSE before even checking the hostname. */
+bool ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name,
+                                 const char **reason_r);
 const char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io);
 const char *ssl_iostream_get_compression(struct ssl_iostream *ssl_io);
 const char *ssl_iostream_get_server_name(struct ssl_iostream *ssl_io);