From: Timo Sirainen Date: Tue, 31 Oct 2017 22:18:23 +0000 (+0200) Subject: lib-ssl-iostream: ssl_iostream_cert_match_name() - add reason_r parameter X-Git-Tag: 2.3.0.rc1~525 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6315f87da1b28578d2deb4d51aa624dc178efb0a;p=thirdparty%2Fdovecot%2Fcore.git lib-ssl-iostream: ssl_iostream_cert_match_name() - add reason_r parameter The callers were also changed to add the reason to error messages. --- diff --git a/src/lib-ssl-iostream/iostream-openssl.c b/src/lib-ssl-iostream/iostream-openssl.c index b242e2e61e..221ae0acd6 100644 --- a/src/lib-ssl-iostream/iostream-openssl.c +++ b/src/lib-ssl-iostream/iostream-openssl.c @@ -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; } } diff --git a/src/lib-ssl-iostream/iostream-ssl-private.h b/src/lib-ssl-iostream/iostream-ssl-private.h index 2242f63609..b5f16112e7 100644 --- a/src/lib-ssl-iostream/iostream-ssl-private.h +++ b/src/lib-ssl-iostream/iostream-ssl-private.h @@ -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); diff --git a/src/lib-ssl-iostream/iostream-ssl.c b/src/lib-ssl-iostream/iostream-ssl.c index f23819d37f..6656698c80 100644 --- a/src/lib-ssl-iostream/iostream-ssl.c +++ b/src/lib-ssl-iostream/iostream-ssl.c @@ -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; diff --git a/src/lib-ssl-iostream/iostream-ssl.h b/src/lib-ssl-iostream/iostream-ssl.h index f3e5fef6b9..86c569a5a7 100644 --- a/src/lib-ssl-iostream/iostream-ssl.h +++ b/src/lib-ssl-iostream/iostream-ssl.h @@ -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);