summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2021-02-06 22:01:23 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2021-02-06 22:01:23 +0000
commitcdb37db5c0ff060de7edfc94e830cab6b7f7c084 (patch)
treef3a9c97551e40a7efbe24cb627f25d7313218fa5
parentc4e2500b1d629e640a40f15889c5dc39ca3d116b (diff)
downloadexim4-cdb37db5c0ff060de7edfc94e830cab6b7f7c084.tar.gz
Fix handling of server which follows a RCPT 452 with a 250. Bug 26092
(cherry picked from commit d6870e76cf0b838eab1929e5d5afb486c4e7b448)
-rw-r--r--doc/doc-txt/ChangeLog5
-rw-r--r--src/src/transports/smtp.c11
2 files changed, 12 insertions, 4 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index c9ad2e259..f687f73f5 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -148,6 +148,11 @@ JH/41 Fix daemon SIGHUP on FreeBSD. Previously, a named socket for IPC was
This affected any platform not supporting "abstract" Unix-domain
sockets (i.e. not Linux).
+JH/42 Bug 2692: Harden against a peer which reneges on a 452 "too many
+ recipients" response to RCPT in a later response, with a 250. The
+ previous coding assumed this would not happen, and under PIPELINING
+ would result in both lost and duplicate recipients for a message.
+
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index b0dedfa8c..0c87027f5 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1087,7 +1087,7 @@ if (sx->pending_MAIL)
{
DEBUG(D_transport) debug_printf("%s expect mail\n", __FUNCTION__);
count--;
- sx->pending_MAIL = FALSE;
+ sx->pending_MAIL = sx->RCPT_452 = FALSE;
if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
'2', ob->command_timeout))
{
@@ -1227,7 +1227,7 @@ while (count-- > 0)
if (addr->more_errno >> 8 == 52 && yield & 3)
{
- if (!sx->RCPT_452)
+ if (!sx->RCPT_452) /* initialised at MAIL-ack above */
{
DEBUG(D_transport)
debug_printf("%s: seen first 452 too-many-rcpts\n", __FUNCTION__);
@@ -1274,6 +1274,8 @@ while (count-- > 0)
}
}
}
+ if (count && !(addr = addr->next))
+ return -2;
} /* Loop for next RCPT response */
/* Update where to start at for the next block of responses, unless we
@@ -3922,9 +3924,10 @@ else
}
/* Process all transported addresses - for LMTP or PRDR, read a status for
- each one. */
+ each one. We used to drop out at first_addr, until someone returned a 452
+ followed by a 250... and we screwed up the accepted addresses. */
- for (address_item * addr = addrlist; addr != sx->first_addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
{
if (addr->transport_return != PENDING_OK) continue;