BOOL peer_dane_verified;
BOOL trigger_sni_changes;
BOOL have_set_peerdn;
- const struct host_item *host;
+ const struct host_item *host; /* NULL if server */
gnutls_x509_crt_t peercert;
uschar *peerdn;
uschar *ciphersuite;
if (state->verify_requirement == VERIFY_NONE)
return TRUE;
+DEBUG(D_tls) debug_printf("TLS: checking peer certificate\n");
*errstr = NULL;
if ((rc = peer_status(state, errstr)) != OK)
else
{
- if (state->exp_tls_verify_cert_hostnames)
+ /* Client side, check the server's certificate name versus the name on the
+ A-record for the connection we made. What to do for server side - what name
+ to use for client? We document that there is no such checking for server
+ side. */
+
+ if ( state->exp_tls_verify_cert_hostnames
+ && !gnutls_x509_crt_check_hostname(state->tlsp->peercert,
+ CS state->exp_tls_verify_cert_hostnames)
+ )
{
- int sep = 0;
- const uschar * list = state->exp_tls_verify_cert_hostnames;
- uschar * name;
- while ((name = string_nextinlist(&list, &sep, NULL, 0)))
- if (gnutls_x509_crt_check_hostname(state->tlsp->peercert, CS name))
- break;
- if (!name)
- {
- DEBUG(D_tls)
- debug_printf("TLS certificate verification failed: cert name mismatch\n");
- if (state->verify_requirement >= VERIFY_REQUIRED)
- goto badcert;
- return TRUE;
- }
+ DEBUG(D_tls)
+ debug_printf("TLS certificate verification failed: cert name mismatch\n");
+ if (state->verify_requirement >= VERIFY_REQUIRED)
+ goto badcert;
+ return TRUE;
}
+
state->peer_cert_verified = TRUE;
DEBUG(D_tls) debug_printf("TLS certificate verified: peerdn=\"%s\"\n",
state->peerdn ? state->peerdn : US"<unset>");
}
/* Now negotiate the TLS session. We put our own timer on it, since it seems
-that the GnuTLS library doesn't. */
+that the GnuTLS library doesn't.
+From 3.1.0 there is gnutls_handshake_set_timeout() - but it requires you
+to set (and clear down afterwards) up a pull-timeout callback function that does
+a select, so we're no better off unless avoiding signals becomes an issue. */
gnutls_transport_set_ptr2(state->session,
(gnutls_transport_ptr_t)(long) fileno(smtp_in),
tls_client_setup_hostname_checks(host_item * host, exim_gnutls_state_st * state,
smtp_transport_options_block * ob)
{
-if (verify_check_given_host(&ob->tls_verify_cert_hostnames, host) == OK)
+if (verify_check_given_host(CUSS &ob->tls_verify_cert_hostnames, host) == OK)
{
state->exp_tls_verify_cert_hostnames =
#ifdef SUPPORT_I18N
for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS), i = 0;
rr;
rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
- ) if (rr->type == T_TLSA)
+ ) if (rr->type == T_TLSA && rr->size > 3)
{
const uschar * p = rr->data;
uint8_t usage = p[0], sel = p[1], type = p[2];
#ifndef DISABLE_OCSP
BOOL require_ocsp =
- verify_check_given_host(&ob->hosts_require_ocsp, host) == OK;
+ verify_check_given_host(CUSS &ob->hosts_require_ocsp, host) == OK;
BOOL request_ocsp = require_ocsp ? TRUE
- : verify_check_given_host(&ob->hosts_request_ocsp, host) == OK;
+ : verify_check_given_host(CUSS &ob->hosts_request_ocsp, host) == OK;
#endif
DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", fd);
&& !ob->tls_verify_hosts
&& (!ob->tls_try_verify_hosts || !*ob->tls_try_verify_hosts)
)
- || verify_check_given_host(&ob->tls_verify_hosts, host) == OK
+ || verify_check_given_host(CUSS &ob->tls_verify_hosts, host) == OK
)
{
tls_client_setup_hostname_checks(host, state, ob);
state->verify_requirement = VERIFY_REQUIRED;
gnutls_certificate_server_set_request(state->session, GNUTLS_CERT_REQUIRE);
}
-else if (verify_check_given_host(&ob->tls_try_verify_hosts, host) == OK)
+else if (verify_check_given_host(CUSS &ob->tls_try_verify_hosts, host) == OK)
{
tls_client_setup_hostname_checks(host, state, ob);
DEBUG(D_tls)
else if (inbytes < 0)
{
+debug_printf("%s: err from gnutls_record_recv(\n", __FUNCTION__);
record_io_error(state, (int) inbytes, US"recv", NULL);
state->xfer_error = TRUE;
return FALSE;
{
DEBUG(D_tls) debug_printf("Got TLS_EOF\n");
}
-else record_io_error(state, (int)inbytes, US"recv", NULL);
+else
+{
+debug_printf("%s: err from gnutls_record_recv(\n", __FUNCTION__);
+record_io_error(state, (int)inbytes, US"recv", NULL);
+}
return -1;
}
DEBUG(D_tls) debug_printf("outbytes=" SSIZE_T_FMT "\n", outbytes);
if (outbytes < 0)
{
+ DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__);
record_io_error(state, outbytes, US"send", NULL);
return -1;
}