From b326f3a87ad439673a1cb73037f411bb8ea25ff4 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 24 May 2022 20:27:38 +0100 Subject: [PATCH] TLS resumption: fix for PIPECONNECT When actively initiating a connection with PIPECONNECT, evaluate the EHLO response for possible lbserver indication when we do eventually reap that response, before acting on the STARTTLS response. --- src/src/structs.h | 1 + src/src/tls-gnu.c | 2 +- src/src/tls-openssl.c | 6 +++-- src/src/transports/smtp.c | 50 +++++++++++++++++++-------------------- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/src/structs.h b/src/src/structs.h index 3debd60f3..b38aa6a9d 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -834,6 +834,7 @@ typedef struct { int sock; /* used for a bound but not connected socket */ uschar * sending_ip_address; /* used for TLS resumption */ const uschar * host_lbserver; /* ditto, for server-behind LB */ + BOOL have_lbserver:1; /* host_lbserver is valid */ #ifdef SUPPORT_DANE BOOL dane:1; /* connection must do dane */ diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 5b4898014..fcb8f7ac4 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -3278,7 +3278,7 @@ tls_retrieve_session(tls_support * tlsp, gnutls_session_t session, { tlsp->resumption = RESUME_SUPPORTED; -if (continue_hostname) /* no host_lbserver available for tls_client_resmption_key() */ +if (!conn_args->have_lbserver) { DEBUG(D_tls) debug_printf("resumption not supported on continued-connection\n"); } else if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, conn_args->host) == OK) { diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 877069953..2b8a4e61c 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -4024,8 +4024,10 @@ if (ob->tls_alpn) #endif #ifndef DISABLE_TLS_RESUME -if (continue_hostname) /* no host_lbserver available for tls_client_resmption_key() */ - /*XXX another cmdline arg possibly, but use will be very low */ +/*XXX have_lbserver: another cmdline arg possibly, for continued-conn, but use +will be very low. */ + +if (!conn_args->have_lbserver) /* wanted for tls_client_resmption_key() */ { DEBUG(D_tls) debug_printf("resumption not supported on continued-connection\n"); } else if (verify_check_given_host(CUSS &ob->tls_resumption_hosts, host) == OK) tls_client_ctx_resume_prehandshake(exim_client_ctx, conn_args, tlsp, ob); diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 145907ca6..ad6d100a3 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -1004,6 +1004,28 @@ return authbits; +/* Grab a string differentiating server behind a loadbalancer, for TLS +resumption when such servers do not share a session-cache */ + +static void +ehlo_response_lbserver(smtp_context * sx, smtp_transport_options_block * ob) +{ +#if !defined(DISABLE_TLS) && !defined(DISABLE_TLS_RESUME) +const uschar * s; +uschar * save_item = iterate_item; + +if (sx->conn_args.have_lbserver) + return; +iterate_item = sx->buffer; +s = expand_cstring(ob->host_name_extract); +iterate_item = save_item; +sx->conn_args.host_lbserver = s && !*s ? NULL : s; +sx->conn_args.have_lbserver = TRUE; +#endif +} + + + /* Wait for and check responses for early-pipelining. Called from the lower-level smtp_read_response() function @@ -1040,6 +1062,8 @@ if (pending_BANNER) if (tls_out.active.sock >= 0) rc = DEFER; goto fail; } + /*XXX EXPERIMENTAL_ESMTP_LIMITS ? */ + ehlo_response_lbserver(sx, sx->conn_args.ob); } if (pending_EHLO) @@ -1880,28 +1904,6 @@ return checks; -/* Grab a string differentiating server behind a loadbalancer, for TLS -resumption when such servers do not share a session-cache */ - -static const uschar * -ehlo_response_lbserver(uschar * buffer, smtp_transport_options_block * ob) -{ -#if !defined(DISABLE_TLS) && !defined(DISABLE_TLS_RESUME) -/* want to make this a main-section option */ -const uschar * s; -uschar * save_item = iterate_item; - -iterate_item = buffer; -s = expand_cstring(ob->host_name_extract); -iterate_item = save_item; -return s && !*s ? NULL : s; -#else -return NULL; -#endif -} - - - /* Callback for emitting a BDAT data chunk header. If given a nonzero size, first flush any buffered SMTP commands @@ -2544,7 +2546,6 @@ goto SEND_QUIT; : 0 ) #endif -/*XXX RESUMP - sx->buffer has the EHLO-resp, but only if not early-pipe and not continued-connection */ ); #ifdef EXPERIMENTAL_ESMTP_LIMITS if (tls_out.active.sock >= 0 || !(sx->peer_offered & OPTION_TLS)) @@ -2567,7 +2568,7 @@ goto SEND_QUIT; } } #endif - sx->conn_args.host_lbserver = ehlo_response_lbserver(sx->buffer, ob); + ehlo_response_lbserver(sx, ob); } /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */ @@ -2670,7 +2671,6 @@ if ( smtp_peer_options & OPTION_TLS sx->early_pipe_active = FALSE; goto PIPE_CONNECT_RETRY; } - sx->conn_args.host_lbserver = ehlo_response_lbserver(sx->buffer, ob); } #endif -- 2.30.2