Update upgrade notes and source about use of seteuid()
[exim.git] / src / src / deliver.c
index 85b061b303559810500a27e6927e9b41ca49b99b..f5f065e63b32962731c846c317200ffb65412c04 100644 (file)
@@ -334,7 +334,7 @@ static int
 open_msglog_file(uschar *filename, int mode, uschar **error)
 {
 if (Ustrstr(filename, US"/../"))
-  log_write(0, LOG_MAIN|LOG_PANIC,
+  log_write(0, LOG_MAIN|LOG_PANIC_DIE,
     "Attempt to open msglog file path with upward-traversal: '%s'\n", filename);
 
 for (int i = 2; i > 0; i--)
@@ -460,6 +460,9 @@ TRUE if the lists refer to the same hosts in the same order, except that
 This enables Exim to use a single SMTP transaction for sending to two entirely
 different domains that happen to end up pointing at the same hosts.
 
+We do not try to batch up different A-record host names that refer to the
+same IP.
+
 Arguments:
   one       points to the first host list
   two       points to the second host list
@@ -1192,7 +1195,7 @@ else
   if (addr->host_used)
     {
     g = d_hostlog(g, addr);
-    if (continue_sequence > 1)
+    if (continue_sequence > 1)         /*XXX this is wrong for a dropped proxyconn.  Would have to pass back from transport */
       g = string_catn(g, US"*", 1);
 
 #ifndef DISABLE_EVENT
@@ -2093,9 +2096,9 @@ return FALSE;
 
 /* Each local delivery is performed in a separate process which sets its
 uid and gid as specified. This is a safer way than simply changing and
-restoring using seteuid(); there is a body of opinion that seteuid() cannot be
-used safely. From release 4, Exim no longer makes any use of it. Besides, not
-all systems have seteuid().
+restoring using seteuid(); there is a body of opinion that seteuid()
+cannot be used safely. From release 4, Exim no longer makes any use of
+it for delivery. Besides, not all systems have seteuid().
 
 If the uid/gid are specified in the transport_instance, they are used; the
 transport initialization must ensure that either both or neither are set.
@@ -4272,6 +4275,10 @@ for (int delivery_count = 0; addr_remote; delivery_count++)
       }
     }
 
+/*XXX need to defeat this when DANE is used - but we don't know that yet.
+So look out for the place it gets used.
+*/
+
   /* Get the flag which specifies whether the transport can handle different
   domains that nevertheless resolve to the same set of hosts. If it needs
   expanding, get variables set: $address_data, $domain_data, $localpart_data,
@@ -4350,6 +4357,11 @@ for (int delivery_count = 0; addr_remote; delivery_count++)
   /************************************************************************/
 
 
+/*XXX don't know yet if DANE will be used.  So tpt will have to
+check at the point if gets next addr from list, and skip/defer any
+nonmatch domains
+*/
+
   /* Pick off all addresses which have the same transport, errors address,
   destination, and extra headers. In some cases they point to the same host
   list, but we also need to check for identical host lists generated from
@@ -4496,6 +4508,7 @@ for (int delivery_count = 0; addr_remote; delivery_count++)
   if (continue_transport)
     {
     BOOL ok = Ustrcmp(continue_transport, tp->name) == 0;
+/*XXX do we need to check for a DANEd conn vs. a change of domain? */
 
     /* If the transport is about to override the host list do not check
     it here but take the cost of running the transport process to discover
@@ -5380,7 +5393,8 @@ Returns:       nothing
 static void
 print_dsn_diagnostic_code(const address_item *addr, FILE *f)
 {
-uschar *s = testflag(addr, af_pass_message) ? addr->message : NULL;
+uschar * s = testflag(addr, af_pass_message) ? addr->message : NULL;
+unsigned cnt;
 
 /* af_pass_message and addr->message set ? print remote host answer */
 if (s)
@@ -5392,19 +5406,32 @@ if (s)
   if (!(s = Ustrstr(addr->message, ": ")))
     return;                            /* not found, bail out */
   s += 2;  /* skip ": " */
-  fprintf(f, "Diagnostic-Code: smtp; ");
+  cnt = fprintf(f, "Diagnostic-Code: smtp; ");
   }
 /* no message available. do nothing */
 else return;
 
 while (*s)
+  {
+  if (cnt > 950)       /* RFC line length limit: 998 */
+    {
+    DEBUG(D_deliver) debug_printf("print_dsn_diagnostic_code() truncated line\n");
+    fputs("[truncated]", f);
+    break;
+    }
+
   if (*s == '\\' && s[1] == 'n')
     {
     fputs("\n ", f);    /* as defined in RFC 3461 */
     s += 2;
+    cnt += 2;
     }
   else
+    {
     fputc(*s++, f);
+    cnt++;
+    }
+  }
 
 fputc('\n', f);
 }
@@ -7052,10 +7079,20 @@ if (  mua_wrapper
 
 
 /* If this is a run to continue deliveries to an external channel that is
-already set up, defer any local deliveries. */
+already set up, defer any local deliveries.
 
-if (continue_transport)
+jgh 2020/12/20: I don't see why; locals should be quick.
+The defer goes back to version 1.62 in 1997.  A local being still deliverable
+during a continued run might result from something like a defer during the
+original delivery, eg. in a DB lookup.  Unlikely but possible.
+
+To avoid delaying a local when combined with a callout-hold for a remote
+delivery, test continue_sequence rather than continue_transport. */
+
+if (continue_sequence > 1 && addr_local)
   {
+  DEBUG(D_deliver|D_retry|D_route)
+    debug_printf("deferring local deliveries due to continued-transport\n");
   if (addr_defer)
     {
     address_item *addr = addr_defer;
@@ -7831,11 +7868,11 @@ wording. */
            fprintf(fp, "Remote-MTA: X-ip; [%s]%s\n", hu->address, p);
            }
          if ((s = addr->smtp_greeting) && *s)
-           fprintf(fp, "X-Remote-MTA-smtp-greeting: X-str; %s\n", s);
+           fprintf(fp, "X-Remote-MTA-smtp-greeting: X-str; %.900s\n", s);
          if ((s = addr->helo_response) && *s)
-           fprintf(fp, "X-Remote-MTA-helo-response: X-str; %s\n", s);
+           fprintf(fp, "X-Remote-MTA-helo-response: X-str; %.900s\n", s);
          if ((s = addr->message) && *s)
-           fprintf(fp, "X-Exim-Diagnostic: X-str; %s\n", s);
+           fprintf(fp, "X-Exim-Diagnostic: X-str; %.900s\n", s);
          }
 #endif
          print_dsn_diagnostic_code(addr, fp);