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--)
else if (one->port != two->port)
return FALSE;
- /* Hosts matched */
+#ifdef SUPPORT_DANE
+ /* DNSSEC equality */
+ if (one->dnssec != two->dnssec) return FALSE;
+#endif
+ /* Hosts matched */
one = one->next;
two = two->next;
}
if (LOGGING(outgoing_port))
g = string_fmt_append(g, ":%d", h->port);
+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);
+
#ifdef SUPPORT_SOCKS
if (LOGGING(proxy) && proxy_local_address)
{
if (addr->host_used)
{
g = d_hostlog(g, addr);
- 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
deliver_host_address = addr->host_used->address;
/* Time on queue and actual time taken to deliver */
if (LOGGING(queue_time))
- g = string_append(g, 2, US" QT=",
- string_timesince(&received_time));
+ g = string_append(g, 2, US" QT=", string_timesince(
+ LOGGING(queue_time_exclusive) ? &received_time_complete : &received_time));
if (LOGGING(deliver_time))
g = string_append(g, 2, US" DT=", string_timediff(&addr->delivery_time));
g = string_fmt_append(g, " defer (%d)", addr->basic_errno);
if (addr->basic_errno > 0)
- g = string_append(g, 2, US": ",
- US strerror(addr->basic_errno));
+ g = string_append(g, 2, US": ", US strerror(addr->basic_errno));
if (addr->host_used)
- {
- g = string_append(g, 5,
- US" H=", addr->host_used->name,
- US" [", addr->host_used->address, US"]");
- if (LOGGING(outgoing_port))
- {
- int port = addr->host_used->port;
- g = string_fmt_append(g, ":%d", port == PORT_NONE ? 25 : port);
- }
- }
+ g = d_hostlog(g, addr);
if (LOGGING(deliver_time))
g = string_append(g, 2, US" DT=", string_timediff(&addr->delivery_time));
(void)close(addr->return_file);
}
+/* Check if the transport notifed continue-conn status explicitly, and
+update our knowlege. */
+
+if (testflag(addr, af_new_conn)) continue_sequence = 1;
+else if (testflag(addr, af_cont_conn)) continue_sequence++;
+
/* The success case happens only after delivery by a transport. */
if (result == OK)
/* 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.
deliveries (e.g. to pipes) can take a substantial time. */
if (!(dbm_file = dbfn_open(US"retry", O_RDONLY, &dbblock, FALSE, TRUE)))
- {
DEBUG(D_deliver|D_retry|D_hints_lookup)
debug_printf("no retry data available\n");
- }
addr2 = addr;
addr3 = NULL;
uschar *pattern;
uschar patbuf[256];
+/*XXX The list is used before expansion. Not sure how that ties up with the docs */
while ( *aptr
&& (pattern = string_nextinlist(&listptr, &sep, patbuf, sizeof(patbuf)))
)
switch (*subid)
{
- #ifdef SUPPORT_SOCKS
+ case 3: /* explicit notification of continued-connection (non)use;
+ overrides caller's knowlege. */
+ if (*ptr & BIT(1)) setflag(addr, af_new_conn);
+ else if (*ptr & BIT(2)) setflag(addr, af_cont_conn);
+ break;
+
+#ifdef SUPPORT_SOCKS
case '2': /* proxy information; must arrive before A0 and applies to that addr XXX oops*/
proxy_session = TRUE; /*XXX should this be cleared somewhere? */
if (*ptr == 0)
ptr += sizeof(proxy_local_port);
}
break;
- #endif
+#endif
- #ifdef EXPERIMENTAL_DSN_INFO
+#ifdef EXPERIMENTAL_DSN_INFO
case '1': /* must arrive before A0, and applies to that addr */
/* Two strings: smtp_greeting and helo_response */
addr->smtp_greeting = string_copy(ptr);
addr->helo_response = string_copy(ptr);
while(*ptr++);
break;
- #endif
+#endif
case '0':
DEBUG(D_deliver) debug_printf("A0 %s tret %d\n", addr->address, *ptr);
rmt_dlv_checked_write(fd, 'R', '0', big_buffer, ptr - big_buffer);
}
+ if (testflag(addr, af_new_conn) || testflag(addr, af_cont_conn))
+ {
+ DEBUG(D_deliver) debug_printf("%scontinued-connection\n",
+ testflag(addr, af_new_conn) ? "non-" : "");
+ big_buffer[0] = testflag(addr, af_new_conn) ? BIT(1) : BIT(2);
+ rmt_dlv_checked_write(fd, 'A', '3', big_buffer, 1);
+ }
+
#ifdef SUPPORT_SOCKS
if (LOGGING(proxy) && proxy_session)
{
if (!s || !*s)
log_write(0, LOG_MAIN|LOG_PANIC,
"Failed to expand %s: '%s'\n", varname, filename);
-else if (*s != '/' || is_tainted(s))
- log_write(0, LOG_MAIN|LOG_PANIC,
- "%s is not %s after expansion: '%s'\n",
- varname, *s == '/' ? "untainted" : "absolute", s);
+else if (*s != '/')
+ log_write(0, LOG_MAIN|LOG_PANIC, "%s is not absolute after expansion: '%s'\n",
+ varname, s);
+else if (is_tainted2(s, LOG_MAIN|LOG_PANIC, "Tainted %s after expansion: '%s'\n", varname, s))
+ ;
else if (!(fp = Ufopen(s, "rb")))
log_write(0, LOG_MAIN|LOG_PANIC, "Failed to open %s for %s "
"message texts: %s", s, reason, strerror(errno));
if (!tmp)
p->message = string_sprintf("failed to expand \"%s\" as a "
"system filter transport name", tpname);
- if (is_tainted(tmp))
- p->message = string_sprintf("attempt to used tainted value '%s' for"
- "transport '%s' as a system filter", tmp, tpname);
+ { uschar *m;
+ if ((m = is_tainted2(tmp, 0, "Tainted values '%s' " "for transport '%s' as a system filter", tmp, tpname)))
+ p->message = m;
+ }
tpname = tmp;
}
else
addr_route = addr->next;
deliver_domain = addr->domain; /* set $domain */
- if ((rc = match_isinlist(addr->domain, (const uschar **)&queue_domains, 0,
+ if ((rc = match_isinlist(addr->domain, CUSS &queue_domains, 0,
&domainlist_anchor, addr->domain_cache, MCL_DOMAIN, TRUE, NULL))
!= OK)
if (rc == DEFER)
/* 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;
+ address_item * addr = addr_defer;
while (addr->next) addr = addr->next;
addr->next = addr_local;
}
/* If this was a first delivery attempt, unset the first time flag, and
ensure that the spool gets updated. */
- if (f.deliver_firsttime)
+ if (f.deliver_firsttime && !f.queue_2stage)
{
f.deliver_firsttime = FALSE;
update_spool = TRUE;
}
-uschar *
-deliver_get_sender_address (uschar * id)
-{
-int rc;
-uschar * new_sender_address,
- * save_sender_address;
-BOOL save_qr = f.queue_running;
-uschar * spoolname;
-
-/* make spool_open_datafile non-noisy on fail */
-
-f.queue_running = TRUE;
-
-/* Side effect: message_subdir is set for the (possibly split) spool directory */
-
-deliver_datafile = spool_open_datafile(id);
-f.queue_running = save_qr;
-if (deliver_datafile < 0)
- return NULL;
-
-/* Save and restore the global sender_address. I'm not sure if we should
-not save/restore all the other global variables too, because
-spool_read_header() may change all of them. But OTOH, when this
-deliver_get_sender_address() gets called, the current message is done
-already and nobody needs the globals anymore. (HS12, 2015-08-21) */
-
-spoolname = string_sprintf("%s-H", id);
-save_sender_address = sender_address;
-
-rc = spool_read_header(spoolname, TRUE, TRUE);
-
-new_sender_address = sender_address;
-sender_address = save_sender_address;
-
-if (rc != spool_read_OK)
- return NULL;
-
-assert(new_sender_address);
-
-(void)close(deliver_datafile);
-deliver_datafile = -1;
-
-return new_sender_address;
-}
-
+/* Called from a commandline, or from the daemon, to do a delivery.
+We need to regain privs; do this by exec of the exim binary. */
void
delivery_re_exec(int exec_type)