summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2014-11-08 13:24:21 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2014-11-08 20:06:57 +0000
commitaa2a70baf1a7ae2d6c579094a188c1d30d3d5fd5 (patch)
treed297637678bfb66b4ce95ad8b3e4ac6a8bdef4f8 /src
parenta320fabd09f43c02c869c90a5a5a70a49dd77f89 (diff)
Fix smtp transport certificate-verification option matching to use correct host
Fix certificate name verification done with tls_try_verify_hosts Affected tls_verify_hosts, tls_try_verify_hosts, tls_verify_cert_hostnames.
Diffstat (limited to 'src')
-rw-r--r--src/src/tls-gnu.c72
-rw-r--r--src/src/tls-openssl.c39
2 files changed, 60 insertions, 51 deletions
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index 093b3a375..9d72ebc66 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -75,11 +75,7 @@ Changes:
/* Values for verify_requirement */
enum peer_verify_requirement
- { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED
-#ifdef EXPERIMENTAL_CERTNAMES
- ,VERIFY_WITHHOST
-#endif
- };
+ { VERIFY_NONE, VERIFY_OPTIONAL, VERIFY_REQUIRED };
/* This holds most state for server or client; with this, we can set up an
outbound TLS-enabled connection in an ACL callout, while not stomping all
@@ -1390,7 +1386,7 @@ if (rc < 0 ||
else
{
#ifdef EXPERIMENTAL_CERTNAMES
- if (state->verify_requirement == VERIFY_WITHHOST)
+ if (state->exp_tls_verify_cert_hostnames)
{
int sep = 0;
uschar * list = state->exp_tls_verify_cert_hostnames;
@@ -1402,9 +1398,13 @@ else
{
DEBUG(D_tls)
debug_printf("TLS certificate verification failed: cert name mismatch\n");
- gnutls_alert_send(state->session,
- GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE);
- return FALSE;
+ if (state->verify_requirement >= VERIFY_REQUIRED)
+ {
+ gnutls_alert_send(state->session,
+ GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE);
+ return FALSE;
+ }
+ return TRUE;
}
}
#endif
@@ -1771,6 +1771,23 @@ return OK;
+#ifdef EXPERIMENTAL_CERTNAMES
+static void
+tls_client_setup_hostname_checks(host_item * host, exim_gnutls_state_st * state,
+ smtp_transport_options_block * ob)
+{
+if (verify_check_this_host(&ob->tls_verify_cert_hostnames, NULL,
+ host->name, host->address, NULL) == OK)
+ {
+ state->exp_tls_verify_cert_hostnames = host->name;
+ DEBUG(D_tls)
+ debug_printf("TLS: server cert verification includes hostname: \"%s\".\n",
+ state->exp_tls_verify_cert_hostnames);
+ }
+}
+#endif
+
+
/*************************************************
* Start a TLS session in a client *
*************************************************/
@@ -1837,35 +1854,28 @@ if ((rc = tls_init(host, ob->tls_certificate, ob->tls_privatekey,
set but both tls_verify_hosts and tls_try_verify_hosts are unset. Check only
the specified host patterns if one of them is defined */
-if (( state->exp_tls_verify_certificates
- && !ob->tls_verify_hosts
- && !ob->tls_try_verify_hosts
- )
- ||
- verify_check_host(&ob->tls_verify_hosts) == OK
+if ( ( state->exp_tls_verify_certificates
+ && !ob->tls_verify_hosts
+ && !ob->tls_try_verify_hosts
+ )
+ || verify_check_this_host(&ob->tls_verify_hosts, NULL,
+ host->name, host->address, NULL) == OK
)
{
#ifdef EXPERIMENTAL_CERTNAMES
- if (verify_check_host(&ob->tls_verify_cert_hostnames) == OK)
- {
- DEBUG(D_tls)
- debug_printf("TLS: server cert incl. hostname verification required.\n");
- state->verify_requirement = VERIFY_WITHHOST;
- state->exp_tls_verify_cert_hostnames = host->name;
- DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n",
- state->exp_tls_verify_cert_hostnames);
- }
- else
+ tls_client_setup_hostname_checks(host, state, ob);
#endif
- {
- DEBUG(D_tls)
- debug_printf("TLS: server certificate verification required.\n");
- state->verify_requirement = VERIFY_REQUIRED;
- }
+ DEBUG(D_tls)
+ debug_printf("TLS: server certificate verification required.\n");
+ state->verify_requirement = VERIFY_REQUIRED;
gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUIRE);
}
-else if (verify_check_host(&ob->tls_try_verify_hosts) == OK)
+else if (verify_check_this_host(&ob->tls_try_verify_hosts, NULL,
+ host->name, host->address, NULL) == OK)
{
+#ifdef EXPERIMENTAL_CERTNAMES
+ tls_client_setup_hostname_checks(host, state, ob);
+#endif
DEBUG(D_tls)
debug_printf("TLS: server certificate verification optional.\n");
state->verify_requirement = VERIFY_OPTIONAL;
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 628860044..b1094b1c2 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1683,31 +1683,30 @@ int rc;
set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only
the specified host patterns if one of them is defined */
-if ((!ob->tls_verify_hosts && !ob->tls_try_verify_hosts) ||
- (verify_check_host(&ob->tls_verify_hosts) == OK))
- {
- if ((rc = setup_certs(ctx, ob->tls_verify_certificates,
- ob->tls_crl, host, FALSE, verify_callback_client)) != OK)
- return rc;
+if ( (!ob->tls_verify_hosts && !ob->tls_try_verify_hosts)
+ || (verify_check_this_host(&ob->tls_verify_hosts, NULL,
+ host->name, host->address, NULL) == OK)
+ )
client_verify_optional = FALSE;
+else if (verify_check_this_host(&ob->tls_try_verify_hosts, NULL,
+ host->name, host->address, NULL) == OK)
+ client_verify_optional = TRUE;
+else
+ return OK;
+
+if ((rc = setup_certs(ctx, ob->tls_verify_certificates,
+ ob->tls_crl, host, client_verify_optional, verify_callback_client)) != OK)
+ return rc;
#ifdef EXPERIMENTAL_CERTNAMES
- if (verify_check_host(&ob->tls_verify_cert_hostnames) == OK)
- {
- cbinfo->verify_cert_hostnames = host->name;
- DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n",
- cbinfo->verify_cert_hostnames);
- }
-#endif
- }
-else if (verify_check_host(&ob->tls_try_verify_hosts) == OK)
+if (verify_check_this_host(&ob->tls_verify_cert_hostnames, NULL,
+ host->name, host->address, NULL) == OK)
{
- if ((rc = setup_certs(ctx, ob->tls_verify_certificates,
- ob->tls_crl, host, TRUE, verify_callback_client)) != OK)
- return rc;
- client_verify_optional = TRUE;
+ cbinfo->verify_cert_hostnames = host->name;
+ DEBUG(D_tls) debug_printf("Cert hostname to check: \"%s\"\n",
+ cbinfo->verify_cert_hostnames);
}
-
+#endif
return OK;
}