preallocate store for config
[users/jgh/exim.git] / src / src / smtp_out.c
index 8a4dace7e7f324f8589228035ac750f5422f4599..ece79de10a52e22b9ee692cdaaef96eb897b923b 100644 (file)
@@ -52,6 +52,17 @@ if (!(expint = expand_string(istring)))
   return FALSE;
   }
 
+if (is_tainted(expint))
+  {
+  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);
+  return FALSE;
+  }
+
 while (isspace(*expint)) expint++;
 if (*expint == 0) return TRUE;
 
@@ -296,7 +307,7 @@ if (save_errno != 0)
   {
   HDEBUG(D_transport|D_acl|D_v)
     {
-    debug_printf_indent("failed: %s", CUstrerror(save_errno));
+    debug_printf_indent(" failed: %s", CUstrerror(save_errno));
     if (save_errno == ETIMEDOUT)
       debug_printf(" (timeout=%s)", readconf_printtime(timeout));
     debug_printf("\n");
@@ -313,7 +324,7 @@ else
   union sockaddr_46 interface_sock;
   EXIM_SOCKLEN_T size = sizeof(interface_sock);
 
-  HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("connected\n");
+  HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" connected\n");
   if (getsockname(sock, (struct sockaddr *)(&interface_sock), &size) == 0)
     sending_ip_address = host_ntoa(-1, &interface_sock, NULL, &sending_port);
   else
@@ -444,7 +455,7 @@ BOOL more = mode == SCMD_MORE;
 HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
   more ? " (more expected)" : "");
 
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
 if (outblock->cctx->tls_ctx)
   rc = tls_write(outblock->cctx->tls_ctx, outblock->buffer, n, more);
 else
@@ -521,8 +532,14 @@ if (format)
   gstring gs = { .size = big_buffer_size, .ptr = 0, .s = big_buffer };
   va_list ap;
 
+  /* Use taint-unchecked routines for writing into big_buffer, trusting that
+  we'll never expand the results.  Actually, the error-message use - leaving
+  the results in big_buffer for potential later use - is uncomfortably distant.
+  XXX Would be better to assume all smtp commands are short, use normal pool
+  alloc rather than big_buffer, and another global for the data-for-error. */
+
   va_start(ap, format);
-  if (!string_vformat(&gs, FALSE, CS format, ap))
+  if (!string_vformat(&gs, SVFMT_TAINT_NOCHK, CS format, ap))
     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
       "SMTP");
   va_end(ap);
@@ -538,7 +555,7 @@ if (format)
     if (!flush_buffer(outblock, SCMD_FLUSH)) return -1;
     }
 
-  Ustrncpy(CS outblock->ptr, gs.s, gs.ptr);
+  Ustrncpy(outblock->ptr, gs.s, gs.ptr);
   outblock->ptr += gs.ptr;
   outblock->cmd_count++;
   gs.ptr -= 2; string_from_gstring(&gs); /* remove \r\n for error message */
@@ -589,14 +606,14 @@ Arguments:
   inblock   the SMTP input block (contains holding buffer, socket, etc.)
   buffer    where to put the line
   size      space available for the line
-  timeout   the timeout to use when reading a packet
+  timelimit deadline for reading the lime, seconds past epoch
 
 Returns:    length of a line that has been put in the buffer
             -1 otherwise, with errno set
 */
 
 static int
-read_response_line(smtp_inblock *inblock, uschar *buffer, int size, int timeout)
+read_response_line(smtp_inblock *inblock, uschar *buffer, int size, time_t timelimit)
 {
 uschar *p = buffer;
 uschar *ptr = inblock->ptr;
@@ -639,9 +656,9 @@ for (;;)
 
   /* Need to read a new input packet. */
 
-  if((rc = ip_recv(cctx, inblock->buffer, inblock->buffersize, timeout)) <= 0)
+  if((rc = ip_recv(cctx, inblock->buffer, inblock->buffersize, timelimit)) <= 0)
     {
-    DEBUG(D_deliver|D_transport|D_acl)
+    DEBUG(D_deliver|D_transport|D_acl|D_v)
       debug_printf_indent(errno ? "  SMTP(%s)<<\n" : "  SMTP(closed)<<\n",
        strerror(errno));
     break;
@@ -690,22 +707,28 @@ Returns:    TRUE if a valid, non-error response was received; else FALSE
 /*XXX could move to smtp transport; no other users */
 
 BOOL
-smtp_read_response(void * sx0, uschar *buffer, int size, int okdigit,
+smtp_read_response(void * sx0, uschar * buffer, int size, int okdigit,
    int timeout)
 {
 smtp_context * sx = sx0;
-uschar *ptr = buffer;
+uschar * ptr = buffer;
 int count = 0;
+time_t timelimit = time(NULL) + timeout;
 
 errno = 0;  /* Ensure errno starts out zero */
 
-#ifdef EXPERIMENTAL_PIPE_CONNECT
+#ifdef SUPPORT_PIPE_CONNECT
 if (sx->pending_BANNER || sx->pending_EHLO)
-  if (smtp_reap_early_pipe(sx, &count) != OK)
+  {
+  int rc;
+  if ((rc = smtp_reap_early_pipe(sx, &count)) != OK)
     {
     DEBUG(D_transport) debug_printf("failed reaping pipelined cmd responsess\n");
+    buffer[0] = '\0';
+    if (rc == DEFER) errno = ERRNO_TLSFAILURE;
     return FALSE;
     }
+  }
 #endif
 
 /* This is a loop to read and concatenate the lines that make up a multi-line
@@ -713,7 +736,7 @@ response. */
 
 for (;;)
   {
-  if ((count = read_response_line(&sx->inblock, ptr, size, timeout)) < 0)
+  if ((count = read_response_line(&sx->inblock, ptr, size, timelimit)) < 0)
     return FALSE;
 
   HDEBUG(D_transport|D_acl|D_v)