Commit | Line | Data |
---|---|---|
0c0c20aa AM |
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 | |
5 | BDAT error | |
6 | ||
7 | Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy | |
8 | Harris's commits aa171254 and 9aceb5c2. | |
9 | --- | |
10 | src/globals.c | 1 + | |
11 | src/globals.h | 1 + | |
12 | src/smtp_in.c | 55 +++++++++++++++++++++++++++++++++++++++-------- | |
13 | 3 files changed, 48 insertions(+), 9 deletions(-) | |
14 | ||
15 | diff --git a/src/globals.c b/src/globals.c | |
16 | index b3362a34c..894b8487b 100644 | |
17 | --- a/src/globals.c | |
18 | +++ b/src/globals.c | |
19 | @@ -247,6 +247,7 @@ struct global_flags f = | |
20 | .authentication_local = FALSE, | |
21 | ||
22 | .background_daemon = TRUE, | |
23 | + .bdat_readers_wanted = FALSE, | |
24 | ||
25 | .chunking_offered = FALSE, | |
26 | .config_changed = FALSE, | |
27 | diff --git a/src/globals.h b/src/globals.h | |
28 | index f71f104e2..58f7ae55f 100644 | |
29 | --- a/src/globals.h | |
30 | +++ b/src/globals.h | |
31 | @@ -173,6 +173,7 @@ extern struct global_flags { | |
32 | BOOL authentication_local :1; /* TRUE if non-smtp (implicit authentication) */ | |
33 | ||
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 */ | |
36 | ||
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 | |
41 | --- a/src/smtp_in.c | |
42 | +++ b/src/smtp_in.c | |
43 | @@ -602,6 +602,10 @@ if (n > 0) | |
44 | #endif | |
45 | } | |
46 | ||
47 | +/* Forward declarations */ | |
48 | +static inline void bdat_push_receive_functions(void); | |
49 | +static inline void bdat_pop_receive_functions(void); | |
50 | + | |
51 | ||
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--); | |
57 | ||
58 | - receive_getc = lwr_receive_getc; | |
59 | - receive_getbuf = lwr_receive_getbuf; | |
60 | - receive_ungetc = lwr_receive_ungetc; | |
61 | + bdat_pop_receive_functions(); | |
62 | #ifndef DISABLE_DKIM | |
63 | dkim_save = dkim_collect_input; | |
64 | dkim_collect_input = 0; | |
65 | @@ -740,9 +742,7 @@ next_cmd: | |
66 | goto repeat_until_rset; | |
67 | } | |
68 | ||
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(); | |
73 | #ifndef DISABLE_DKIM | |
74 | dkim_collect_input = dkim_save; | |
75 | #endif | |
76 | @@ -775,9 +775,7 @@ while (chunking_data_left) | |
77 | if (!bdat_getbuf(&n)) break; | |
78 | } | |
79 | ||
80 | -receive_getc = lwr_receive_getc; | |
81 | -receive_getbuf = lwr_receive_getbuf; | |
82 | -receive_ungetc = lwr_receive_ungetc; | |
83 | +bdat_pop_receive_functions(); | |
84 | ||
85 | if (chunking_state != CHUNKING_LAST) | |
86 | { | |
87 | @@ -787,6 +785,45 @@ if (chunking_state != CHUNKING_LAST) | |
88 | } | |
89 | ||
90 | ||
91 | +static inline void | |
92 | +bdat_push_receive_functions(void) | |
93 | +{ | |
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) | |
98 | + { | |
99 | + lwr_receive_getc = receive_getc; | |
100 | + lwr_receive_getbuf = receive_getbuf; | |
101 | + lwr_receive_ungetc = receive_ungetc; | |
102 | + } | |
103 | +else | |
104 | + { | |
105 | + DEBUG(D_receive) debug_printf("chunking double-push receive functions\n"); | |
106 | + } | |
107 | + | |
108 | +receive_getc = bdat_getc; | |
109 | +receive_getbuf = bdat_getbuf; | |
110 | +receive_ungetc = bdat_ungetc; | |
111 | +} | |
112 | + | |
113 | +static inline void | |
114 | +bdat_pop_receive_functions(void) | |
115 | +{ | |
116 | +if (lwr_receive_getc == NULL) | |
117 | + { | |
118 | + DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n"); | |
119 | + return; | |
120 | + } | |
121 | + | |
122 | +receive_getc = lwr_receive_getc; | |
123 | +receive_getbuf = lwr_receive_getbuf; | |
124 | +receive_ungetc = lwr_receive_ungetc; | |
125 | + | |
126 | +lwr_receive_getc = NULL; | |
127 | +lwr_receive_getbuf = NULL; | |
128 | +lwr_receive_ungetc = NULL; | |
129 | +} | |
130 | ||
131 | ||
132 | /************************************************* | |
133 | -- | |
134 | 2.30.2 | |
135 |