SPDX: license tags (mostly by guesswork)
[exim.git] / src / src / lookups / readsock.c
index c2088b7a5e2d13593d65c1e21291b10dd3e7703d..7c7b9cfa89dd11c6d83b78e1e9090f2084a2336d 100644 (file)
@@ -2,8 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2021 - 2022 */
 /* Copyright (c) Jeremy Harris 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-only */
 
 #include "../exim.h"
 #include "lf_functions.h"
@@ -13,8 +15,6 @@ static int
 internal_readsock_open(client_conn_ctx * cctx, const uschar * sspec,
   int timeout, BOOL do_tls, uschar ** errmsg)
 {
-int sep = ',';
-uschar * ele;
 const uschar * server_name;
 host_item host;
 
@@ -97,7 +97,7 @@ else
 
   sigalrm_seen = FALSE;
   ALARM(timeout);
-  rc = connect(cctx->sock, (struct sockaddr *)(&sockun), sizeof(sockun));
+  rc = connect(cctx->sock, (struct sockaddr *) &sockun, sizeof(sockun));
   ALARM_CLR(0);
   if (sigalrm_seen)
     {
@@ -117,10 +117,20 @@ 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};
+  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));
+    goto bad;
+    }
+
   if (!tls_client_start(cctx, &conn_args, NULL, &tls_dummy, &errstr))
     {
     *errmsg = string_sprintf("TLS connect failed: %s", errstr);
@@ -151,7 +161,7 @@ that connection cacheing at the framework layer works. */
 static void *
 readsock_open(const uschar * filename, uschar ** errmsg)
 {
-client_conn_ctx * cctx = store_get(sizeof(*cctx), FALSE);
+client_conn_ctx * cctx = store_get(sizeof(*cctx), GET_UNTAINTED);
 cctx->sock = -1;
 cctx->tls_ctx = NULL;
 DEBUG(D_lookup) debug_printf_indent("readsock: allocated context\n");
@@ -182,11 +192,12 @@ struct {
 } lf = {.do_shutdown = TRUE};
 uschar * eol = NULL;
 int timeout = 5;
-FILE * fp;
 gstring * yield;
 int ret = DEFER;
 
-DEBUG(D_lookup) debug_printf_indent("readsock: file=\"%s\" key=\"%s\" len=%d opts=\"%s\"\n", filename, keystring, length, opts);
+DEBUG(D_lookup)
+  debug_printf_indent("readsock: file=\"%s\" key=\"%s\" len=%d opts=\"%s\"\n",
+    filename, keystring, length, opts);
 
 /* Parse options */
 
@@ -200,7 +211,7 @@ if (opts) for (uschar * s; s = string_nextinlist(&opts, &sep, NULL, 0); )
     lf.do_tls = TRUE;
 #endif
   else if (Ustrncmp(s, "eol=", 4) == 0)
-    eol = s + 4;
+    eol = string_unprinting(s + 4);
   else if (Ustrcmp(s, "cache=yes") == 0)
     lf.cache = TRUE;
   else if (Ustrcmp(s, "send=no") == 0)
@@ -248,16 +259,28 @@ that reads a file can be used.  If we're using a stdio buffered read,
 and might need later write ops on the socket, the stdio must be in
 writable mode or the underlying socket goes non-writable. */
 
-if (!cctx->tls_ctx)
-  fp = fdopen(cctx->sock, lf.do_shutdown ? "rb" : "wb");
-
 sigalrm_seen = FALSE;
-ALARM(timeout);
-yield =
-#ifndef DISABLE_TLS
-  cctx->tls_ctx ? cat_file_tls(cctx->tls_ctx, NULL, eol) :
+#ifdef DISABLE_TLS
+if (TRUE)
+#else
+if (!cctx->tls_ctx)
 #endif
-                 cat_file(fp, NULL, eol);
+  {
+  FILE * fp = fdopen(cctx->sock, "rb");
+  if (!fp)
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC, "readsock fdopen: %s\n", strerror(errno));
+    goto out;
+    }
+  ALARM(timeout);
+  yield = cat_file(fp, NULL, eol);
+  }
+else
+  {
+  ALARM(timeout);
+  yield = cat_file_tls(cctx->tls_ctx, NULL, eol);
+  }
+
 ALARM_CLR(0);
 
 if (sigalrm_seen)