summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2022-04-15 10:36:56 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2022-04-15 11:22:04 +0100
commitec2a355fdc961aba7ace27c624c01accd58dc1ed (patch)
treef9641fcbe830c2c3c231fc833b7c9baded9bc4b3 /src
parentfa714063ea46ef6dd92dbef3525781d85513394b (diff)
downloadexim4-ec2a355fdc961aba7ace27c624c01accd58dc1ed.tar.gz
TLS resumption: support Outlook hosts-behind-loadbalancer
Diffstat (limited to 'src')
-rw-r--r--src/src/structs.h4
-rw-r--r--src/src/tls.c9
-rw-r--r--src/src/transports/smtp.c52
-rw-r--r--src/src/transports/smtp.h3
4 files changed, 56 insertions, 12 deletions
diff --git a/src/src/structs.h b/src/src/structs.h
index 9bf3aebe2..087683c49 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -830,8 +830,10 @@ typedef struct {
host_item * host;
int host_af;
uschar * interface;
- uschar * sending_ip_address; /* used for TLS resumption */
+
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 */
#ifdef SUPPORT_DANE
BOOL dane:1; /* connection must do dane */
diff --git a/src/src/tls.c b/src/src/tls.c
index c9bc556fc..e80dd9aaf 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -804,16 +804,19 @@ hctx * h = &tlsp->resume_hctx;
blob b;
gstring * g;
+DEBUG(D_tls) if (conn_args->host_lbserver)
+ debug_printf("TLS: lbserver '%s'\n", conn_args->host_lbserver);
+
#ifdef EXIM_HAVE_SHA2
exim_sha_init(h, HASH_SHA2_256);
#else
exim_sha_init(h, HASH_SHA1);
#endif
-
-// TODO: word from server EHLO resp /* how, fer gossakes? Add item to conn_args or tls_support? */
-
+exim_sha_update_string(h, conn_args->host_lbserver);
+#ifdef SUPPORT_DANE
if (conn_args->dane)
exim_sha_update(h, CUS &conn_args->tlsa_dnsa, sizeof(dns_answer));
+#endif
exim_sha_update_string(h, conn_args->host->address);
exim_sha_update(h, CUS &conn_args->host->port, sizeof(conn_args->host->port));
exim_sha_update_string(h, conn_args->sending_ip_address);
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index f9e319c79..e2368da13 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -64,6 +64,9 @@ optionlist smtp_transport_options[] = {
{ "final_timeout", opt_time, LOFF(final_timeout) },
{ "gethostbyname", opt_bool, LOFF(gethostbyname) },
{ "helo_data", opt_stringptr, LOFF(helo_data) },
+#if !defined(DISABLE_TLS) && !defined(DISABLE_TLS_RESUME)
+ { "host_name_extract", opt_stringptr, LOFF(host_name_extract) },
+# endif
{ "hosts", opt_stringptr, LOFF(hosts) },
{ "hosts_avoid_esmtp", opt_stringptr, LOFF(hosts_avoid_esmtp) },
{ "hosts_avoid_pipelining", opt_stringptr, LOFF(hosts_avoid_pipelining) },
@@ -199,6 +202,9 @@ smtp_transport_options_block smtp_transport_option_defaults = {
.tls_tempfail_tryclear = TRUE,
.tls_try_verify_hosts = US"*",
.tls_verify_cert_hostnames = US"*",
+# ifndef DISABLE_TLS_RESUME
+ .host_name_extract = US"${if and {{match{$host}{.outlook.com\\$}} {match{$item}{\\N^250-([\\w.]+)\\s\\N}}} {$1}}",
+# endif
#endif
#ifdef SUPPORT_I18N
.utf8_downconvert = US"-1",
@@ -1066,6 +1072,7 @@ if (pending_EHLO)
if (tls_out.active.sock >= 0 || !(peer_offered & OPTION_TLS))
ehlo_response_limits_read(sx);
#endif
+/*XXX RESUMP - EHLO-resp avail here int sx->buffer */
if ( peer_offered != sx->peer_offered
|| (authbits = study_ehlo_auths(sx)) != *ap)
{
@@ -1874,6 +1881,28 @@ 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
@@ -2516,6 +2545,8 @@ goto SEND_QUIT;
: 0
)
#endif
+/*XXX RESUMP - sx->buffer has the EHLO-resp, but only if not early-pipe and not continued-connection */
+/* maybe disable resump on cont? */
);
#ifdef EXPERIMENTAL_ESMTP_LIMITS
if (tls_out.active.sock >= 0 || !(sx->peer_offered & OPTION_TLS))
@@ -2538,6 +2569,7 @@ goto SEND_QUIT;
}
}
#endif
+ sx->conn_args.host_lbserver = ehlo_response_lbserver(sx->buffer, ob);
}
/* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
@@ -2629,14 +2661,19 @@ if ( smtp_peer_options & OPTION_TLS
the response for the STARTTLS we just sent alone. On fail, assume wrong
cached capability and retry with the pipelining disabled. */
- if (sx->early_pipe_active && sync_responses(sx, 2, 0) != 0)
+ if (sx->early_pipe_active)
{
- HDEBUG(D_transport)
- debug_printf("failed reaping pipelined cmd responses\n");
- close(sx->cctx.sock);
- sx->cctx.sock = -1;
- sx->early_pipe_active = FALSE;
- goto PIPE_CONNECT_RETRY;
+ if (sync_responses(sx, 2, 0) != 0)
+ {
+ HDEBUG(D_transport)
+ debug_printf("failed reaping pipelined cmd responses\n");
+ close(sx->cctx.sock);
+ sx->cctx.sock = -1;
+ sx->early_pipe_active = FALSE;
+ goto PIPE_CONNECT_RETRY;
+ }
+/*XXX RESUMP - does this leave the EHLO-resp anywhere? Yes, sx->buffer */
+ sx->conn_args.host_lbserver = ehlo_response_lbserver(sx->buffer, ob);
}
#endif
@@ -2666,6 +2703,7 @@ if ( smtp_peer_options & OPTION_TLS
TLS_NEGOTIATE:
{
sx->conn_args.sending_ip_address = sending_ip_address;
+ /*XXX RESUMP want LB-server info here */
if (!tls_client_start(&sx->cctx, &sx->conn_args, sx->addrlist, &tls_out, &tls_errstr))
{
/* TLS negotiation failed; give an error. From outside, this function may
diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h
index 2ed6cfd51..8dbd1fcf3 100644
--- a/src/src/transports/smtp.h
+++ b/src/src/transports/smtp.h
@@ -83,7 +83,7 @@ typedef struct {
int size_addition;
int hosts_max_try;
int hosts_max_try_hardlimit;
- int message_linelength_limit;
+ int message_linelength_limit;
BOOL address_retry_include_sender;
BOOL allow_localhost;
BOOL authenticated_sender_force;
@@ -108,6 +108,7 @@ typedef struct {
uschar *tls_privatekey;
uschar *tls_require_ciphers;
# ifndef DISABLE_TLS_RESUME
+ uschar *host_name_extract;
uschar *tls_resumption_hosts;
# endif
const uschar *tls_sni;