From: Timo Sirainen Date: Tue, 31 Oct 2017 22:12:24 +0000 (+0200) Subject: lib-ssl-iostream: openssl_cert_match_name() - add reason_r parameter X-Git-Tag: 2.3.0.rc1~526 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bbafd34da224c399700956db6819643e1d3b3ce7;p=thirdparty%2Fdovecot%2Fcore.git lib-ssl-iostream: openssl_cert_match_name() - add reason_r parameter The returned string explains what exactly matched or why nothing matched. --- diff --git a/src/lib-ssl-iostream/iostream-openssl-common.c b/src/lib-ssl-iostream/iostream-openssl-common.c index ecc7294c40..6b6905329a 100644 --- a/src/lib-ssl-iostream/iostream-openssl-common.c +++ b/src/lib-ssl-iostream/iostream-openssl-common.c @@ -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; } diff --git a/src/lib-ssl-iostream/iostream-openssl.c b/src/lib-ssl-iostream/iostream-openssl.c index 04156f9699..b242e2e61e 100644 --- a/src/lib-ssl-iostream/iostream-openssl.c +++ b/src/lib-ssl-iostream/iostream-openssl.c @@ -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) diff --git a/src/lib-ssl-iostream/iostream-openssl.h b/src/lib-ssl-iostream/iostream-openssl.h index 405dff1552..d67de5207b 100644 --- a/src/lib-ssl-iostream/iostream-openssl.h +++ b/src/lib-ssl-iostream/iostream-openssl.h @@ -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) diff --git a/src/login-common/ssl-proxy-openssl.c b/src/login-common/ssl-proxy-openssl.c index 7485a896f1..b2432d9c63 100644 --- a/src/login-common/ssl-proxy-openssl.c +++ b/src/login-common/ssl-proxy-openssl.c @@ -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)