Merge branch 'debian'
[hcoop/debian/exim4.git] / debian / patches / 84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch
diff --git a/debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch b/debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch
new file mode 100644 (file)
index 0000000..0d44293
--- /dev/null
@@ -0,0 +1,135 @@
+From 1663ab541b37675dec5bcf235605568ff36ac65a Mon Sep 17 00:00:00 2001
+From: Qualys Security Advisory <qsa@qualys.com>
+Date: Sun, 21 Feb 2021 22:36:10 -0800
+Subject: [PATCH 22/29] CVE-2020-28019: Failure to reset function pointer after
+ BDAT error
+
+Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy
+Harris's commits aa171254 and 9aceb5c2.
+---
+ src/globals.c |  1 +
+ src/globals.h |  1 +
+ src/smtp_in.c | 55 +++++++++++++++++++++++++++++++++++++++--------
+ 3 files changed, 48 insertions(+), 9 deletions(-)
+
+diff --git a/src/globals.c b/src/globals.c
+index b3362a34c..894b8487b 100644
+--- a/src/globals.c
++++ b/src/globals.c
+@@ -247,6 +247,7 @@ struct global_flags f =
+       .authentication_local   = FALSE,
+       .background_daemon      = TRUE,
++      .bdat_readers_wanted    = FALSE,
+       .chunking_offered       = FALSE,
+       .config_changed         = FALSE,
+diff --git a/src/globals.h b/src/globals.h
+index f71f104e2..58f7ae55f 100644
+--- a/src/globals.h
++++ b/src/globals.h
+@@ -173,6 +173,7 @@ extern struct global_flags {
+  BOOL   authentication_local          :1; /* TRUE if non-smtp (implicit authentication) */
+  BOOL   background_daemon             :1; /* Set FALSE to keep in foreground */
++ BOOL   bdat_readers_wanted           :1; /* BDAT-handling to be pushed on readfunc stack */
+  BOOL   chunking_offered              :1;
+  BOOL   config_changed                        :1; /* True if -C used */
+diff --git a/src/smtp_in.c b/src/smtp_in.c
+index 1a5fbfea3..016c44c0f 100644
+--- a/src/smtp_in.c
++++ b/src/smtp_in.c
+@@ -602,6 +602,10 @@ if (n > 0)
+ #endif
+ }
++/* Forward declarations */
++static inline void bdat_push_receive_functions(void);
++static inline void bdat_pop_receive_functions(void);
++
+ /* Get a byte from the smtp input, in CHUNKING mode.  Handle ack of the
+ previous BDAT chunk and getting new ones when we run out.  Uses the
+@@ -634,9 +638,7 @@ for(;;)
+   if (chunking_data_left > 0)
+     return lwr_receive_getc(chunking_data_left--);
+-  receive_getc = lwr_receive_getc;
+-  receive_getbuf = lwr_receive_getbuf;
+-  receive_ungetc = lwr_receive_ungetc;
++  bdat_pop_receive_functions();
+ #ifndef DISABLE_DKIM
+   dkim_save = dkim_collect_input;
+   dkim_collect_input = 0;
+@@ -740,9 +742,7 @@ next_cmd:
+         goto repeat_until_rset;
+         }
+-      receive_getc = bdat_getc;
+-      receive_getbuf = bdat_getbuf;   /* r~getbuf is never actually used */
+-      receive_ungetc = bdat_ungetc;
++      bdat_push_receive_functions();
+ #ifndef DISABLE_DKIM
+       dkim_collect_input = dkim_save;
+ #endif
+@@ -775,9 +775,7 @@ while (chunking_data_left)
+   if (!bdat_getbuf(&n)) break;
+   }
+-receive_getc = lwr_receive_getc;
+-receive_getbuf = lwr_receive_getbuf;
+-receive_ungetc = lwr_receive_ungetc;
++bdat_pop_receive_functions();
+ if (chunking_state != CHUNKING_LAST)
+   {
+@@ -787,6 +785,45 @@ if (chunking_state != CHUNKING_LAST)
+ }
++static inline void
++bdat_push_receive_functions(void)
++{
++/* push the current receive_* function on the "stack", and
++replace them by bdat_getc(), which in turn will use the lwr_receive_*
++functions to do the dirty work. */
++if (lwr_receive_getc == NULL)
++  {
++  lwr_receive_getc = receive_getc;
++  lwr_receive_getbuf = receive_getbuf;
++  lwr_receive_ungetc = receive_ungetc;
++  }
++else
++  {
++  DEBUG(D_receive) debug_printf("chunking double-push receive functions\n");
++  }
++
++receive_getc = bdat_getc;
++receive_getbuf = bdat_getbuf;
++receive_ungetc = bdat_ungetc;
++}
++
++static inline void
++bdat_pop_receive_functions(void)
++{
++if (lwr_receive_getc == NULL)
++  {
++  DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
++  return;
++  }
++
++receive_getc = lwr_receive_getc;
++receive_getbuf = lwr_receive_getbuf;
++receive_ungetc = lwr_receive_ungetc;
++
++lwr_receive_getc = NULL;
++lwr_receive_getbuf = NULL;
++lwr_receive_ungetc = NULL;
++}
+ /*************************************************
+-- 
+2.30.2
+