Specific check for null pointer
[exim.git] / src / src / smtp_out.c
index f103c2752ebd76c23dbec4e704ea6be2e4525a78..fc1e6cecd8d62cec0b7cfff53a10d15abc44ce4a 100644 (file)
@@ -3,7 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* A number of functions for driving outgoing SMTP calls. */
@@ -27,7 +27,7 @@ Arguments:
                which case the function does nothing
   host_af    AF_INET or AF_INET6 for the outgoing IP address
   addr       the mail address being handled (for setting errors)
-  interface  point this to the interface
+  interface  point this to the interface if there is one defined
   msg        to add to any error message
 
 Returns:     TRUE on success, FALSE on failure, with error message
@@ -53,11 +53,8 @@ if (!(expint = expand_string(istring)))
   return FALSE;
   }
 
-if (is_tainted(expint))
+if (is_tainted2(expint, LOG_MAIN|LOG_PANIC, "Tainted value '%s' from '%s' for interface", expint, istring))
   {
-  log_write(0, LOG_MAIN|LOG_PANIC,
-    "attempt to use tainted value '%s' from '%s' for interface",
-    expint, istring);
   addr->transport_return = PANIC;
   addr->message = string_sprintf("failed to expand \"interface\" "
       "option for %s: configuration error", msg);
@@ -67,11 +64,10 @@ if (is_tainted(expint))
 Uskip_whitespace(&expint);
 if (!*expint) return TRUE;
 
-/* we just tested to ensure no taint, so big_buffer is ok */
-while ((iface = string_nextinlist(&expint, &sep, big_buffer,
-          big_buffer_size)))
+while ((iface = string_nextinlist(&expint, &sep, NULL, 0)))
   {
-  if (string_is_ip_address(iface, NULL) == 0)
+  int if_af = string_is_ip_address(iface, NULL);
+  if (if_af == 0)
     {
     addr->transport_return = PANIC;
     addr->message = string_sprintf("\"%s\" is not a valid IP "
@@ -80,11 +76,11 @@ while ((iface = string_nextinlist(&expint, &sep, big_buffer,
     return FALSE;
     }
 
-  if (((Ustrchr(iface, ':') == NULL)? AF_INET:AF_INET6) == host_af)
+  if ((if_af == 4 ? AF_INET : AF_INET6) == host_af)
     break;
   }
 
-if (iface) *interface = string_copy(iface);
+*interface = iface;
 return TRUE;
 }
 
@@ -154,9 +150,16 @@ return TRUE;
 
 
 #ifdef TCP_FASTOPEN
+/* Try to record if TFO was attmepted and if it was successfully used.  */
+
 static void
 tfo_out_check(int sock)
 {
+static BOOL done_once = FALSE;
+
+if (done_once) return;
+done_once = TRUE;
+
 # ifdef __FreeBSD__
 struct tcp_info tinfo;
 socklen_t len = sizeof(tinfo);
@@ -280,7 +283,7 @@ const blob * fastopen_blob = NULL;
 #ifndef DISABLE_EVENT
 deliver_host_address = host->address;
 deliver_host_port = port;
-if (event_raise(tb->event_action, US"tcp:connect", NULL)) return -1;
+if (event_raise(tb->event_action, US"tcp:connect", NULL, &errno)) return -1;
 #endif
 
 if ((sock = ip_socket(SOCK_STREAM, host_af)) < 0) return -1;
@@ -472,7 +475,7 @@ if (ob->socks_proxy)
   {
   int sock = socks_sock_connect(sc->host, sc->host_af, port, sc->interface,
                                sc->tblock, ob->connect_timeout);
-  
+
   if (sock >= 0)
     {
     if (early_data && early_data->data && early_data->len)
@@ -521,13 +524,21 @@ flush_buffer(smtp_outblock * outblock, int mode)
 int rc;
 int n = outblock->ptr - outblock->buffer;
 BOOL more = mode == SCMD_MORE;
+client_conn_ctx * cctx;
 
 HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
   more ? " (more expected)" : "");
 
+if (!(cctx = outblock->cctx))
+  {
+  log_write(0, LOG_MAIN|LOG_PANIC, "null conn-context pointer");
+  errno = 0;
+  return FALSE;
+  }
+
 #ifndef DISABLE_TLS
-if (outblock->cctx->tls_ctx)
-  rc = tls_write(outblock->cctx->tls_ctx, outblock->buffer, n, more);
+if (cctx->tls_ctx)             /*XXX have seen a null cctx here, rvfy sending QUIT, hence check above */
+  rc = tls_write(cctx->tls_ctx, outblock->buffer, n, more);
 else
 #endif
 
@@ -541,7 +552,7 @@ else
     requirement: TFO with data can, in rare cases, replay the data to the
     receiver. */
 
-    if (  (outblock->cctx->sock = smtp_connect(outblock->conn_args, &early_data))
+    if (  (cctx->sock = smtp_connect(outblock->conn_args, &early_data))
        < 0)
       return FALSE;
     outblock->conn_args = NULL;
@@ -549,7 +560,7 @@ else
     }
   else
     {
-    rc = send(outblock->cctx->sock, outblock->buffer, n,
+    rc = send(cctx->sock, outblock->buffer, n,
 #ifdef MSG_MORE
              more ? MSG_MORE : 0
 #else
@@ -564,7 +575,7 @@ else
     https://bugzilla.redhat.com/show_bug.cgi?id=1803806 */
 
     if (!more)
-      setsockopt(outblock->cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
+      setsockopt(cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
 #endif
     }
   }
@@ -860,7 +871,7 @@ for (;;)
   }
 
 #ifdef TCP_FASTOPEN
-  tfo_out_check(sx->cctx.sock);
+tfo_out_check(sx->cctx.sock);
 #endif
 
 /* Return a value that depends on the SMTP return code. On some systems a