Gitweb:
https://git.exim.org/exim.git/commitdiff/6fdf76d0eae42ce4507fe317f095572100c5d6b8
Commit: 6fdf76d0eae42ce4507fe317f095572100c5d6b8
Parent: 8ff2ba119ba654e9238f157f94bf10ed640ed877
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Mon Mar 13 00:43:01 2023 +0000
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Mon Mar 13 15:41:09 2023 +0000
SNI for ${readsocket }
---
doc/doc-docbook/spec.xfpt | 5 ++++
doc/doc-txt/NewStuff | 2 ++
src/src/functions.h | 2 ++
src/src/lookups/readsock.c | 31 ++++++------------------
src/src/tls.c | 51 ++++++++++++++++++++++++++++++++++++++++
test/confs/1149 | 2 ++
test/log/1149 | 1 +
test/scripts/1100-Basic-TLS/1149 | 1 +
test/stdout/1149 | 1 +
9 files changed, 72 insertions(+), 24 deletions(-)
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 0ba62ce5e..bdc0eb30e 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -10495,6 +10495,11 @@ Defines whether or not a write-shutdown is done on the connection after
sending the request. Values are &"yes"& (the default) or &"no"&
(preferred, eg. by some webservers).
+.next
+&*sni*&
+Controls the use of Server Name Identification on the connection.
+Any nonempty value will be the SNI sent; TLS will be forced.
+
.next
&*tls*&
Controls the use of TLS on the connection.
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index d12246e03..84db8ea58 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -29,6 +29,8 @@ Version 4.97
10. A commandline option to print just the message IDs of the queue
+ 11. An option for the ${readsocket } expansion to set an SNI for TLS.
+
Version 4.96
------------
diff --git a/src/src/functions.h b/src/src/functions.h
index 5fbb426ec..896122a69 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -54,6 +54,8 @@ extern uschar * tls_cert_fprt_sha256(void *);
extern void tls_clean_env(void);
extern BOOL tls_client_start(client_conn_ctx *, smtp_connect_args *,
void *, tls_support *, uschar **);
+extern BOOL tls_client_adjunct_start(host_item *, client_conn_ctx *,
+ const uschar *, uschar **);
extern void tls_client_creds_reload(BOOL);
extern void tls_close(void *, int);
diff --git a/src/src/lookups/readsock.c b/src/src/lookups/readsock.c
index b1ea42c7f..a3f87108a 100644
--- a/src/src/lookups/readsock.c
+++ b/src/src/lookups/readsock.c
@@ -13,7 +13,7 @@
static int
internal_readsock_open(client_conn_ctx * cctx, const uschar * sspec,
- int timeout, BOOL do_tls, uschar ** errmsg)
+ int timeout, uschar * do_tls, uschar ** errmsg)
{
const uschar * server_name;
host_item host;
@@ -116,27 +116,8 @@ else
#ifndef DISABLE_TLS
if (do_tls)
- {
- union sockaddr_46 interface_sock;
- EXIM_SOCKLEN_T size = sizeof(interface_sock);
- smtp_connect_args conn_args = {.host = &host };
- tls_support tls_dummy = { .sni = NULL };
- uschar * errstr;
-
- if (getsockname(cctx->sock, (struct sockaddr *) &interface_sock, &size) == 0)
- conn_args.sending_ip_address = host_ntoa(-1, &interface_sock, NULL, NULL);
- else
- {
- *errmsg = string_sprintf("getsockname failed: %s", strerror(errno));
+ if (!tls_client_adjunct_start(&host, cctx, do_tls, errmsg))
goto bad;
- }
-
- if (!tls_client_start(cctx, &conn_args, NULL, &tls_dummy, &errstr))
- {
- *errmsg = string_sprintf("TLS connect failed: %s", errstr);
- goto bad;
- }
- }
#endif
DEBUG(D_expand|D_lookup) debug_printf_indent(" connected to socket %s\n", sspec);
@@ -187,8 +168,8 @@ client_conn_ctx * cctx = handle;
int sep = ',';
struct {
BOOL do_shutdown:1;
- BOOL do_tls:1;
BOOL cache:1;
+ uschar * do_tls; /* NULL, empty-string, or SNI */
} lf = {.do_shutdown = TRUE};
uschar * eol = NULL;
int timeout = 5;
@@ -207,8 +188,10 @@ if (opts) for (uschar * s; s = string_nextinlist(&opts, &sep, NULL, 0); )
else if (Ustrncmp(s, "shutdown=", 9) == 0)
lf.do_shutdown = Ustrcmp(s + 9, "no") != 0;
#ifndef DISABLE_TLS
- else if (Ustrncmp(s, "tls=", 4) == 0 && Ustrcmp(s + 4, US"no") != 0)
- lf.do_tls = TRUE;
+ else if (Ustrncmp(s, "tls=", 4) == 0 && Ustrcmp(s + 4, US"no") != 0 && !lf.do_tls)
+ lf.do_tls = US"";
+ else if (Ustrncmp(s, "sni=", 4) == 0)
+ lf.do_tls = s + 4;
#endif
else if (Ustrncmp(s, "eol=", 4) == 0)
eol = string_unprinting(s + 4);
diff --git a/src/src/tls.c b/src/src/tls.c
index ba7c2de38..825313a9a 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -852,6 +852,57 @@ DEBUG(D_tls) debug_printf("TLS: resume session index %s\n", tlsp->resume_index);
#endif
}
+
+
+/* Start TLS as a client for an ajunct connection, eg. readsocket
+Return boolean success.
+*/
+
+BOOL
+tls_client_adjunct_start(host_item * host, client_conn_ctx * cctx,
+ const uschar * sni, uschar ** errmsg)
+{
+union sockaddr_46 interface_sock;
+EXIM_SOCKLEN_T size = sizeof(interface_sock);
+smtp_connect_args conn_args = {.host = host };
+tls_support tls_dummy = { .sni = NULL };
+uschar * errstr;
+
+if (getsockname(cctx->sock, (struct sockaddr *) &interface_sock, &size) == 0)
+ conn_args.sending_ip_address = host_ntoa(-1, &interface_sock, NULL, NULL);
+else
+ {
+ *errmsg = string_sprintf("getsockname failed: %s", strerror(errno));
+ return FALSE;
+ }
+
+/* To handle SNI we need to emulate more of a real transport because the
+base tls code assumes that is where the SNI string lives. */
+
+if (*sni)
+ {
+ transport_instance * tb;
+ smtp_transport_options_block * ob;
+
+ conn_args.tblock = tb = store_get(sizeof(*tb), GET_UNTAINTED);
+ memset(tb, 0, sizeof(*tb));
+
+ tb->options_block = ob = store_get(sizeof(*ob), GET_UNTAINTED);
+ memcpy(ob, &smtp_transport_option_defaults, sizeof(*ob));
+
+ ob->tls_sni = sni;
+ }
+
+if (!tls_client_start(cctx, &conn_args, NULL, &tls_dummy, &errstr))
+ {
+ *errmsg = string_sprintf("TLS connect failed: %s", errstr);
+ return FALSE;
+ }
+return TRUE;
+}
+
+
+
#endif /*!DISABLE_TLS*/
#endif /*!MACRO_PREDEF*/
diff --git a/test/confs/1149 b/test/confs/1149
index 737753109..dfe5b33cb 100644
--- a/test/confs/1149
+++ b/test/confs/1149
@@ -13,4 +13,6 @@ tls_advertise_hosts = *
tls_certificate = DIR/aux-fixed/cert1
tls_privatekey = DIR/aux-fixed/cert1
+acl_smtp_helo = accept logwrite = HELO <$sender_helo_name> SNI <$tls_in_sni>
+
# End
diff --git a/test/log/1149 b/test/log/1149
index bc6ac7f77..efcef1b23 100644
--- a/test/log/1149
+++ b/test/log/1149
@@ -1,3 +1,4 @@
******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=p1234, no queue runs, listening for SMTPS on port PORT_D
+1999-03-02 09:44:33 HELO <tester> SNI <fubar>
diff --git a/test/scripts/1100-Basic-TLS/1149 b/test/scripts/1100-Basic-TLS/1149
index 501a9c9da..29702b049 100644
--- a/test/scripts/1100-Basic-TLS/1149
+++ b/test/scripts/1100-Basic-TLS/1149
@@ -8,6 +8,7 @@ exim -DSERVER=server -tls-on-connect -bd -oX PORT_D
millisleep 500
exim -be
1 >>${readsocket{inet:thisloop:PORT_D}{QUIT\n}{2s:tls=yes}}<<
+2 >>${readsocket{inet:thisloop:PORT_D}{EHLO tester\n}{1s:tls=yes:sni=fubar}}<<
****
millisleep 500
#
diff --git a/test/stdout/1149 b/test/stdout/1149
index a3eab5117..c67e31cfe 100644
--- a/test/stdout/1149
+++ b/test/stdout/1149
@@ -1,4 +1,5 @@
> 1 >>220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
221 myhost.test.ex closing connection
<<
+> Failed: socket read timed out
>