X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftls-gnu.c;h=826a3fdc555ee51bd0736fa8289a5575e13e6bef;hb=7832b9aa09dc312a137a1a56924d270085fad39e;hp=f18c244eeba90e8ddee00ff7578f61bdd5d41acb;hpb=97277c1f835e749bf06aea2e16922fc234470034;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index f18c244ee..826a3fdc5 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -167,7 +167,7 @@ Some of these correspond to variables in globals.c; those variables will be set to point to content in one of these instances, as appropriate for the stage of the process lifetime. -Not handled here: global tls_channelbinding_b64. +Not handled here: global tlsp->tls_channelbinding. */ typedef struct exim_gnutls_state { @@ -177,10 +177,17 @@ typedef struct exim_gnutls_state { enum peer_verify_requirement verify_requirement; int fd_in; int fd_out; - BOOL peer_cert_verified; - BOOL peer_dane_verified; - BOOL trigger_sni_changes; - BOOL have_set_peerdn; + + BOOL peer_cert_verified:1; + BOOL peer_dane_verified:1; + BOOL trigger_sni_changes:1; + BOOL have_set_peerdn:1; + BOOL xfer_eof:1; /*XXX never gets set! */ + BOOL xfer_error:1; +#ifdef SUPPORT_CORK + BOOL corked:1; +#endif + const struct host_item *host; /* NULL if server */ gnutls_x509_crt_t peercert; uschar *peerdn; @@ -213,8 +220,6 @@ typedef struct exim_gnutls_state { uschar *xfer_buffer; int xfer_buffer_lwm; int xfer_buffer_hwm; - BOOL xfer_eof; /*XXX never gets set! */ - BOOL xfer_error; } exim_gnutls_state_st; static const exim_gnutls_state_st exim_gnutls_state_init = { @@ -479,7 +484,8 @@ Sets: tls_active fd tls_bits strength indicator tls_certificate_verified bool indicator - tls_channelbinding_b64 for some SASL mechanisms + tls_channelbinding for some SASL mechanisms + tls_ver a string tls_cipher a string tls_peercert pointer to library internal tls_peerdn a string @@ -510,10 +516,10 @@ tlsp->certificate_verified = state->peer_cert_verified; tlsp->dane_verified = state->peer_dane_verified; #endif -/* note that tls_channelbinding_b64 is not saved to the spool file, since it's +/* note that tls_channelbinding is not saved to the spool file, since it's only available for use for authenticators while this TLS session is running. */ -tls_channelbinding_b64 = NULL; +tlsp->channelbinding = NULL; #ifdef HAVE_GNUTLS_SESSION_CHANNEL_BINDING channel.data = NULL; channel.size = 0; @@ -521,11 +527,15 @@ if ((rc = gnutls_session_channel_binding(state->session, GNUTLS_CB_TLS_UNIQUE, & { 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. */ + old_pool = store_pool; store_pool = POOL_PERM; - tls_channelbinding_b64 = b64encode(CUS channel.data, (int)channel.size); + 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"); + DEBUG(D_tls) debug_printf("Have channel bindings cached for possible auth usage\n"); } #endif @@ -1766,11 +1776,17 @@ old_pool = store_pool; /* debug_printf("peer_status: gnutls_session_get_desc %s\n", s); */ for (s++; (c = *s) && c != ')'; s++) g = string_catn(g, s, 1); + + tlsp->ver = string_copyn(g->s, g->ptr); + for (uschar * p = US tlsp->ver; *p; p++) + if (*p == '-') { *p = '\0'; break; } /* TLS1.0-PKIX -> TLS1.0 */ + g = string_catn(g, US":", 1); if (*s) s++; /* now on _ between groups */ while ((c = *s)) { - for (*++s && ++s; (c = *s) && c != ')'; s++) g = string_catn(g, c == '-' ? US"_" : s, 1); + for (*++s && ++s; (c = *s) && c != ')'; s++) + g = string_catn(g, c == '-' ? US"_" : s, 1); /* now on ) closing group */ if ((c = *s) && *++s == '-') g = string_catn(g, US"__", 2); /* now on _ between groups */ @@ -1790,6 +1806,8 @@ old_pool = store_pool; releases did return "TLS 1.0"; play it safe, just in case. */ for (uschar * p = state->ciphersuite; *p; p++) if (isspace(*p)) *p = '-'; + tlsp->ver = string_copyn(state->ciphersuite, + Ustrchr(state->ciphersuite, ':') - state->ciphersuite); #endif /* debug_printf("peer_status: ciphersuite %s\n", state->ciphersuite); */ @@ -1926,7 +1944,7 @@ else const char ** dd; int * ddl; - for(nrec = 0; state->dane_data_len[nrec]; ) nrec++; + for (nrec = 0; state->dane_data_len[nrec]; ) nrec++; nrec++; dd = store_get(nrec * sizeof(uschar *), FALSE); @@ -2289,11 +2307,12 @@ if (TRUE) } else debug_printf("To get keying info for TLS1.3 is hard:\n" - " set environment variable SSLKEYLOGFILE to a filename writable by uid exim\n" - " add SSLKEYLOGFILE to keep_environment in the exim config\n" - " run exim as root\n" - " if using sudo, add SSLKEYLOGFILE to env_keep in /etc/sudoers\n" - " (works for TLS1.2 also, and saves cut-paste into file)" + " Set environment variable SSLKEYLOGFILE to a filename relative to the spool directory,\n" + " and make sure it is writable by the Exim runtime user.\n" + " Add SSLKEYLOGFILE to keep_environment in the exim config.\n" + " Start Exim as root.\n" + " If using sudo, add SSLKEYLOGFILE to env_keep in /etc/sudoers\n" + " (works for TLS1.2 also, and saves cut-paste into file).\n" " Trying to use add_environment for this will not work\n"); #endif } @@ -2398,9 +2417,20 @@ and sent an SMTP response. */ DEBUG(D_tls) debug_printf("initialising GnuTLS as a server\n"); -if ((rc = tls_init(NULL, tls_certificate, tls_privatekey, - NULL, tls_verify_certificates, tls_crl, - require_ciphers, &state, &tls_in, errstr)) != OK) return rc; + { +#ifdef MEASURE_TIMING + struct timeval t0; + gettimeofday(&t0, NULL); +#endif + + if ((rc = tls_init(NULL, tls_certificate, tls_privatekey, + NULL, tls_verify_certificates, tls_crl, + require_ciphers, &state, &tls_in, errstr)) != OK) return rc; + +#ifdef MEASURE_TIMING + report_time_since(&t0, US"server tls_init (delta)"); +#endif + } #ifdef EXPERIMENTAL_TLS_RESUME tls_server_resume_prehandshake(state); @@ -2505,6 +2535,11 @@ if (rc != GNUTLS_E_SUCCESS) return FAIL; } +#ifdef GNUTLS_SFLAGS_EXT_MASTER_SECRET +if (gnutls_session_get_flags(state->session) & GNUTLS_SFLAGS_EXT_MASTER_SECRET) + tls_in.ext_master_secret = TRUE; +#endif + #ifdef EXPERIMENTAL_TLS_RESUME tls_server_resume_posthandshake(state); #endif @@ -2834,10 +2869,21 @@ if (conn_args->dane && ob->dane_require_tls_ciphers) if (!cipher_list) cipher_list = ob->tls_require_ciphers; -if (tls_init(host, ob->tls_certificate, ob->tls_privatekey, - ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl, - cipher_list, &state, tlsp, errstr) != OK) - return FALSE; + { +#ifdef MEASURE_TIMING + struct timeval t0; + gettimeofday(&t0, NULL); +#endif + + if (tls_init(host, ob->tls_certificate, ob->tls_privatekey, + ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl, + cipher_list, &state, tlsp, errstr) != OK) + return FALSE; + +#ifdef MEASURE_TIMING + report_time_since(&t0, US"client tls_init (delta)"); +#endif + } { int dh_min_bits = ob->tls_dh_min_bits; @@ -2963,6 +3009,11 @@ if (!verify_certificate(state, errstr)) return FALSE; } +#ifdef GNUTLS_SFLAGS_EXT_MASTER_SECRET +if (gnutls_session_get_flags(state->session) & GNUTLS_SFLAGS_EXT_MASTER_SECRET) + tlsp->ext_master_secret = TRUE; +#endif + #ifndef DISABLE_OCSP if (request_ocsp) { @@ -3075,7 +3126,7 @@ gnutls_certificate_free_credentials(state->x509_cred); tlsp->active.sock = -1; tlsp->active.tls_ctx = NULL; /* Leave bits, peercert, cipher, peerdn, certificate_verified set, for logging */ -tls_channelbinding_b64 = NULL; +tlsp->channelbinding = NULL; if (state->xfer_buffer) store_free(state->xfer_buffer); @@ -3289,6 +3340,9 @@ Arguments: len number of bytes more more data expected soon +Calling with len zero and more unset will flush buffered writes. The buff +argument can be null for that case. + Returns: the number of bytes after a successful write, -1 after a failed write */ @@ -3300,9 +3354,8 @@ ssize_t outbytes; size_t left = len; exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server; #ifdef SUPPORT_CORK -static BOOL corked = FALSE; -if (more && !corked) gnutls_record_cork(state->session); +if (more && !state->corked) gnutls_record_cork(state->session); #endif DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__, @@ -3310,8 +3363,8 @@ DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__, while (left > 0) { - DEBUG(D_tls) debug_printf("gnutls_record_send(SSL, %p, " SIZE_T_FMT ")\n", - buff, left); + DEBUG(D_tls) debug_printf("gnutls_record_send(%p, %p, " SIZE_T_FMT ")\n", + state->session, buff, left); do outbytes = gnutls_record_send(state->session, buff, left); @@ -3343,10 +3396,10 @@ if (len > INT_MAX) } #ifdef SUPPORT_CORK -if (more != corked) +if (more != state->corked) { if (!more) (void) gnutls_record_uncork(state->session, 0); - corked = more; + state->corked = more; } #endif