Skip to content

Commit

Permalink
lib-ssl-iostream: openssl_cert_match_name() - add reason_r parameter
Browse files Browse the repository at this point in the history
The returned string explains what exactly matched or why nothing matched.
  • Loading branch information
sirainen authored and Timo Sirainen committed Nov 6, 2017
1 parent 18344a6 commit bbafd34
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 11 deletions.
36 changes: 28 additions & 8 deletions src/lib-ssl-iostream/iostream-openssl-common.c
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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;
}
Expand Down
4 changes: 3 additions & 1 deletion src/lib-ssl-iostream/iostream-openssl.c
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion src/lib-ssl-iostream/iostream-openssl.h
Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/login-common/ssl-proxy-openssl.c
Expand Up @@ -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)
Expand Down

0 comments on commit bbafd34

Please sign in to comment.