X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/94c1328507098238ae5ec784150c1ae58f3b3118..bd5b3f3c47654ba803f2a71daa4b739a2af39467:/src/src/tls-gnu.c diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 8cf28fca3..6de0f023a 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Copyright (c) Phil Pennock 2012 */ @@ -66,13 +66,17 @@ require current GnuTLS, then we'll drop support for the ancient libraries). #if GNUTLS_VERSION_NUMBER >= 0x030506 && !defined(DISABLE_OCSP) # define SUPPORT_SRV_OCSP_STACK #endif -#if GNUTLS_VERSION_NUMBER >= 0x030000 && defined(EXPERIMENTAL_DANE) -# define SUPPORT_DANE -# define DANESSL_USAGE_DANE_TA 2 -# define DANESSL_USAGE_DANE_EE 3 -#endif -#if GNUTLS_VERSION_NUMBER < 0x999999 && defined(EXPERIMENTAL_DANE) -# define GNUTLS_BROKEN_DANE_VALIDATION + +#ifdef SUPPORT_DANE +# if GNUTLS_VERSION_NUMBER >= 0x030000 +# define DANESSL_USAGE_DANE_TA 2 +# define DANESSL_USAGE_DANE_EE 3 +# else +# error GnuTLS version too early for DANE +# endif +# if GNUTLS_VERSION_NUMBER < 0x999999 +# define GNUTLS_BROKEN_DANE_VALIDATION +# endif #endif #ifndef DISABLE_OCSP @@ -1617,7 +1621,7 @@ else (needed for TA but not EE). */ if (usage == ((1<tlsp->peerdn = state->peerdn; return TRUE; +#ifdef SUPPORT_DANE tlsa_prob: *errstr = string_sprintf("TLSA record problem: %s", dane_strerror(rc)); +#endif + badcert: gnutls_alert_send(state->session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE); return FALSE; @@ -1913,12 +1920,10 @@ int rc; uschar * yield; exim_gnutls_state_st * state = gnutls_session_get_ptr(session); -cert_list = gnutls_certificate_get_peers(session, &cert_list_size); -if (cert_list) +if ((cert_list = gnutls_certificate_get_peers(session, &cert_list_size))) while (cert_list_size--) { - rc = import_cert(&cert_list[cert_list_size], &crt); - if (rc != GNUTLS_E_SUCCESS) + if ((rc = import_cert(&cert_list[cert_list_size], &crt)) != GNUTLS_E_SUCCESS) { DEBUG(D_tls) debug_printf("TLS: peer cert problem: depth %d: %s\n", cert_list_size, gnutls_strerror(rc)); @@ -2246,7 +2251,7 @@ int tls_client_start(int fd, host_item *host, address_item *addr ARG_UNUSED, transport_instance * tb, -#ifdef EXPERIMENTAL_DANE +#ifdef SUPPORT_DANE dns_answer * tlsa_dnsa, #endif uschar ** errstr) @@ -2361,10 +2366,8 @@ DEBUG(D_tls) debug_printf("about to gnutls_handshake\n"); sigalrm_seen = FALSE; alarm(ob->command_timeout); do - { rc = gnutls_handshake(state->session); - } while ((rc == GNUTLS_E_AGAIN) || - (rc == GNUTLS_E_INTERRUPTED && !sigalrm_seen)); +while (rc == GNUTLS_E_AGAIN || rc == GNUTLS_E_INTERRUPTED && !sigalrm_seen); alarm(0); if (rc != GNUTLS_E_SUCCESS) @@ -2437,12 +2440,15 @@ return OK; daemon, to shut down the TLS library, without actually doing a shutdown (which would tamper with the TLS session in the parent process). -Arguments: TRUE if gnutls_bye is to be called +Arguments: + shutdown 1 if TLS close-alert is to be sent, + 2 if also response to be waited for + Returns: nothing */ void -tls_close(BOOL is_server, BOOL shutdown) +tls_close(BOOL is_server, int shutdown) { exim_gnutls_state_st *state = is_server ? &state_server : &state_client; @@ -2450,8 +2456,12 @@ if (!state->tlsp || state->tlsp->active < 0) return; /* TLS was not active */ if (shutdown) { - DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS\n"); - gnutls_bye(state->session, GNUTLS_SHUT_WR); + DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS%s\n", + shutdown > 1 ? " (with response-wait)" : ""); + + alarm(2); + gnutls_bye(state->session, shutdown > 1 ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR); + alarm(0); } gnutls_deinit(state->session); @@ -2459,9 +2469,10 @@ gnutls_certificate_free_credentials(state->x509_cred); state->tlsp->active = -1; +if (state->xfer_buffer) store_free(state->xfer_buffer); memcpy(state, &exim_gnutls_state_init, sizeof(exim_gnutls_state_init)); -if ((state_server.session == NULL) && (state_client.session == NULL)) +if (!state_server.session && !state_client.session) { gnutls_global_deinit(); exim_gnutls_base_init_done = FALSE; @@ -2480,6 +2491,7 @@ ssize_t inbytes; DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%p, %p, %u)\n", state->session, state->xfer_buffer, ssl_xfer_buffer_size); +sigalrm_seen = FALSE; if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); inbytes = gnutls_record_recv(state->session, state->xfer_buffer, MIN(ssl_xfer_buffer_size, lim));