# endif /* AVOID_GNUTLS_PKCS11 */
#endif
+#if GNUTLS_VERSION_NUMBER >= 0x030404
+# define HAVE_GNUTLS_PRF_RFC5705
+#endif
static void
extract_exim_vars_from_tls_state(exim_gnutls_state_st * state)
{
-#ifdef HAVE_GNUTLS_SESSION_CHANNEL_BINDING
-int old_pool;
-int rc;
-gnutls_datum_t channel;
-#endif
tls_support * tlsp = state->tlsp;
tlsp->active.sock = state->fd_out;
tlsp->channelbinding = NULL;
#ifdef HAVE_GNUTLS_SESSION_CHANNEL_BINDING
-channel.data = NULL;
-channel.size = 0;
-if ((rc = gnutls_session_channel_binding(state->session, GNUTLS_CB_TLS_UNIQUE, &channel)))
- { DEBUG(D_tls) debug_printf("Channel binding error: %s\n", gnutls_strerror(rc)); }
-else
{
- /* Declare the taintedness of the binding info. On server, untainted; on
- client, tainted - being the Finish msg from the server. */
+ gnutls_datum_t channel = {.data = NULL, .size = 0};
+ uschar * buf;
+ int rc;
- old_pool = store_pool;
- store_pool = POOL_PERM;
- tlsp->channelbinding = b64encode_taint(CUS channel.data, (int)channel.size,
- !!state->host);
- store_pool = old_pool;
- DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n");
+# ifdef HAVE_GNUTLS_PRF_RFC5705
+ if (gnutls_protocol_get_version(state->session) >= GNUTLS_TLS1_3)
+ {
+ buf = store_get(32, !!state->host);
+ rc = gnutls_prf_rfc5705(state->session,
+ (size_t)24, "EXPORTER-Channel-Binding", (size_t)0, "",
+ 32, CS buf);
+ channel.data = buf;
+ channel.size = 32;
+ }
+ else
+# endif
+ rc = gnutls_session_channel_binding(state->session, GNUTLS_CB_TLS_UNIQUE, &channel);
+
+ if (rc)
+ { DEBUG(D_tls) debug_printf("extracting channel binding: %s\n", gnutls_strerror(rc)); }
+ else
+ {
+ int old_pool = store_pool;
+ /* Declare the taintedness of the binding info. On server, untainted; on
+ client, tainted - being the Finish msg from the server. */
+
+ store_pool = POOL_PERM;
+ tlsp->channelbinding = b64encode_taint(CUS channel.data, (int)channel.size,
+ !!state->host);
+ store_pool = old_pool;
+ DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n");
+ }
}
#endif
state->tlsp->peercert = crt;
if ((yield = event_raise(state->event_action,
- US"tls:cert", string_sprintf("%d", cert_list_size))))
+ US"tls:cert", string_sprintf("%d", cert_list_size), &errno)))
{
log_write(0, LOG_MAIN,
"SSL verify denied by event-action: depth=%d: %s",
if (sigalrm_seen)
{
tls_error(US"gnutls_handshake", US"timed out", NULL, errstr);
- (void) event_raise(event_action, US"tls:fail:connect", *errstr);
+ (void) event_raise(event_action, US"tls:fail:connect", *errstr, NULL);
gnutls_db_remove_session(state->session);
}
else
{
tls_error_gnu(state, US"gnutls_handshake", rc, errstr);
- (void) event_raise(event_action, US"tls:fail:connect", *errstr);
+ (void) event_raise(event_action, US"tls:fail:connect", *errstr, NULL);
(void) gnutls_alert_send_appropriate(state->session, rc);
gnutls_deinit(state->session);
gnutls_certificate_free_credentials(state->lib_state.x509_cred);
tls_write(ct_ctx, NULL, 0, FALSE); /* flush write buffer */
+#ifdef EXIM_TCP_CORK
+ if (do_shutdown > 1)
+ (void) setsockopt(tlsp->active.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &off, sizeof(off));
+#endif
+
ALARM(2);
gnutls_bye(state->session, do_shutdown > 1 ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
ALARM_CLR(0);
/* See a description in tls-openssl.c for an explanation of why this exists.
-Arguments: a FILE* to print the results to
-Returns: nothing
+Arguments: string to append to
+Returns: string
*/
-void
-tls_version_report(FILE *f)
+gstring *
+tls_version_report(gstring * g)
{
-fprintf(f, "Library version: GnuTLS: Compile: %s\n"
- " Runtime: %s\n",
- LIBGNUTLS_VERSION,
- gnutls_check_version(NULL));
+return string_fmt_append(g,
+ "Library version: GnuTLS: Compile: %s\n"
+ " Runtime: %s\n",
+ LIBGNUTLS_VERSION,
+ gnutls_check_version(NULL));
}
#endif /*!MACRO_PREDEF*/