summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQualys Security Advisory <qsa@qualys.com>2021-02-21 19:11:55 -0800
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2021-04-28 00:40:53 +0200
commit611143d73ce446cb34c44e3dac2c7f321acaa225 (patch)
tree0df31352ef68af2fb9e4dd522a0a0f9666b3f4a0
parentb7ee9ba69039aca48704decc1c13b2618a8d96bc (diff)
downloadexim4-611143d73ce446cb34c44e3dac2c7f321acaa225.tar.gz
CVE-2020-28023: Out-of-bounds read in smtp_setup_msg()
Extracted from Jeremy Harris's commit afaf5a50.
-rw-r--r--src/src/acl.c3
-rw-r--r--src/src/macros.h1
-rw-r--r--src/src/smtp_in.c4
3 files changed, 5 insertions, 3 deletions
diff --git a/src/src/acl.c b/src/src/acl.c
index 9fe9e5145..7061230b4 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -4473,7 +4473,8 @@ switch (where)
/* Drop cutthrough conns, and drop heldopen verify conns if
the previous was not DATA */
{
- uschar prev = smtp_connection_had[smtp_ch_index-2];
+ uschar prev =
+ smtp_connection_had[SMTP_HBUFF_PREV(SMTP_HBUFF_PREV(smtp_ch_index))];
BOOL dropverify = !(prev == SCH_DATA || prev == SCH_BDAT);
cancel_cutthrough_connection(dropverify, US"quit or conndrop");
diff --git a/src/src/macros.h b/src/src/macros.h
index f83ba1933..b2f86ed53 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -150,6 +150,7 @@ enough to hold all the headers from a normal kind of message. */
/* The size of the circular buffer that remembers recent SMTP commands */
#define SMTP_HBUFF_SIZE 20
+#define SMTP_HBUFF_PREV(n) ((n) ? (n)-1 : SMTP_HBUFF_SIZE-1)
/* The initial size of a big buffer for use in various places. It gets put
into big_buffer_size and in some circumstances increased. It should be at least
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 258ec03e4..e57059a51 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -5364,10 +5364,10 @@ while (done <= 0)
}
if (f.smtp_in_pipelining_advertised && last_was_rcpt)
smtp_printf("503 Valid RCPT command must precede %s\r\n", FALSE,
- smtp_names[smtp_connection_had[smtp_ch_index-1]]);
+ smtp_names[smtp_connection_had[SMTP_HBUFF_PREV(smtp_ch_index)]]);
else
done = synprot_error(L_smtp_protocol_error, 503, NULL,
- smtp_connection_had[smtp_ch_index-1] == SCH_DATA
+ smtp_connection_had[SMTP_HBUFF_PREV(smtp_ch_index)] == SCH_DATA
? US"valid RCPT command must precede DATA"
: US"valid RCPT command must precede BDAT");