1 From 1663ab541b37675dec5bcf235605568ff36ac65a Mon Sep 17 00:00:00 2001
2 From: Qualys Security Advisory <qsa@qualys.com>
3 Date: Sun, 21 Feb 2021 22:36:10 -0800
4 Subject: [PATCH 22/29] CVE-2020-28019: Failure to reset function pointer after
7 Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy
8 Harris's commits aa171254 and 9aceb5c2.
12 src/smtp_in.c | 55 +++++++++++++++++++++++++++++++++++++++--------
13 3 files changed, 48 insertions(+), 9 deletions(-)
15 diff --git a/src/globals.c b/src/globals.c
16 index b3362a34c..894b8487b 100644
19 @@ -247,6 +247,7 @@ struct global_flags f =
20 .authentication_local = FALSE,
22 .background_daemon = TRUE,
23 + .bdat_readers_wanted = FALSE,
25 .chunking_offered = FALSE,
26 .config_changed = FALSE,
27 diff --git a/src/globals.h b/src/globals.h
28 index f71f104e2..58f7ae55f 100644
31 @@ -173,6 +173,7 @@ extern struct global_flags {
32 BOOL authentication_local :1; /* TRUE if non-smtp (implicit authentication) */
34 BOOL background_daemon :1; /* Set FALSE to keep in foreground */
35 + BOOL bdat_readers_wanted :1; /* BDAT-handling to be pushed on readfunc stack */
37 BOOL chunking_offered :1;
38 BOOL config_changed :1; /* True if -C used */
39 diff --git a/src/smtp_in.c b/src/smtp_in.c
40 index 1a5fbfea3..016c44c0f 100644
43 @@ -602,6 +602,10 @@ if (n > 0)
47 +/* Forward declarations */
48 +static inline void bdat_push_receive_functions(void);
49 +static inline void bdat_pop_receive_functions(void);
52 /* Get a byte from the smtp input, in CHUNKING mode. Handle ack of the
53 previous BDAT chunk and getting new ones when we run out. Uses the
54 @@ -634,9 +638,7 @@ for(;;)
55 if (chunking_data_left > 0)
56 return lwr_receive_getc(chunking_data_left--);
58 - receive_getc = lwr_receive_getc;
59 - receive_getbuf = lwr_receive_getbuf;
60 - receive_ungetc = lwr_receive_ungetc;
61 + bdat_pop_receive_functions();
63 dkim_save = dkim_collect_input;
64 dkim_collect_input = 0;
65 @@ -740,9 +742,7 @@ next_cmd:
66 goto repeat_until_rset;
69 - receive_getc = bdat_getc;
70 - receive_getbuf = bdat_getbuf; /* r~getbuf is never actually used */
71 - receive_ungetc = bdat_ungetc;
72 + bdat_push_receive_functions();
74 dkim_collect_input = dkim_save;
76 @@ -775,9 +775,7 @@ while (chunking_data_left)
77 if (!bdat_getbuf(&n)) break;
80 -receive_getc = lwr_receive_getc;
81 -receive_getbuf = lwr_receive_getbuf;
82 -receive_ungetc = lwr_receive_ungetc;
83 +bdat_pop_receive_functions();
85 if (chunking_state != CHUNKING_LAST)
87 @@ -787,6 +785,45 @@ if (chunking_state != CHUNKING_LAST)
92 +bdat_push_receive_functions(void)
94 +/* push the current receive_* function on the "stack", and
95 +replace them by bdat_getc(), which in turn will use the lwr_receive_*
96 +functions to do the dirty work. */
97 +if (lwr_receive_getc == NULL)
99 + lwr_receive_getc = receive_getc;
100 + lwr_receive_getbuf = receive_getbuf;
101 + lwr_receive_ungetc = receive_ungetc;
105 + DEBUG(D_receive) debug_printf("chunking double-push receive functions\n");
108 +receive_getc = bdat_getc;
109 +receive_getbuf = bdat_getbuf;
110 +receive_ungetc = bdat_ungetc;
114 +bdat_pop_receive_functions(void)
116 +if (lwr_receive_getc == NULL)
118 + DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
122 +receive_getc = lwr_receive_getc;
123 +receive_getbuf = lwr_receive_getbuf;
124 +receive_ungetc = lwr_receive_ungetc;
126 +lwr_receive_getc = NULL;
127 +lwr_receive_getbuf = NULL;
128 +lwr_receive_ungetc = NULL;
132 /*************************************************