[exim-cvs] Introduce main config option allow_insecure_taint…

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Exim Git Commits Mailing List
Datum:  
To: exim-cvs
Betreff: [exim-cvs] Introduce main config option allow_insecure_tainted_data
Gitweb: https://git.exim.org/exim.git/commitdiff/f9a3fcddba223133019368e7cd6d51449fc54e7b
Commit:     f9a3fcddba223133019368e7cd6d51449fc54e7b
Parent:     1013a770f1be6eff05c4b835bb92b2c916fdd341
Author:     Heiko Schlittermann (HS12-RIPE) <hs@???>
AuthorDate: Thu Apr 1 22:44:31 2021 +0200
Committer:  Heiko Schlittermann (HS12-RIPE) <hs@???>
CommitDate: Thu Jun 24 21:43:03 2021 +0200


    Introduce main config option allow_insecure_tainted_data


    This option is deprecated already now.


    (cherry picked from commit ec06d64532e4952fc36429f73e0222d26997ef7c)
---
 src/src/EDITME            |  7 ++++++
 src/src/config.h.defaults |  2 ++
 src/src/functions.h       | 54 ++++++++++++++++++++++++++++++++++++-----------
 src/src/globals.c         | 10 +++++++++
 src/src/globals.h         |  4 ++++
 src/src/macros.h          |  3 +++
 src/src/readconf.c        |  3 +++
 7 files changed, 71 insertions(+), 12 deletions(-)


diff --git a/src/src/EDITME b/src/src/EDITME
index 8cd34e8..f4329fa 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -748,6 +748,13 @@ FIXED_NEVER_USERS=root

# WHITELIST_D_MACROS=TLS:SPOOL

+# The next setting enables a main config option
+# "allow_insecure_tainted_data" to turn taint failures into warnings.
+# Though this option is new, it is deprecated already now, and will be
+# ignored in future releases of Exim. It is meant as mitigation for
+# upgrading old (possibly insecure) configurations to more secure ones.
+ALLOW_INSECURE_TAINTED_DATA=yes
+
#------------------------------------------------------------------------------
# Exim has support for the AUTH (authentication) extension of the SMTP
# protocol, as defined by RFC 2554. If you don't know what SMTP authentication
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index e233fb3..877cc7b 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -17,6 +17,8 @@ Do not put spaces between # and the 'define'.
#define ALT_CONFIG_PREFIX
#define TRUSTED_CONFIG_LIST

+#define ALLOW_INSECURE_TAINTED_DATA
+
 #define APPENDFILE_MODE            0600
 #define APPENDFILE_DIRECTORY_MODE  0700
 #define APPENDFILE_LOCKFILE_MODE   0600
diff --git a/src/src/functions.h b/src/src/functions.h
index 4212c33..27c298c 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -1125,20 +1125,50 @@ if (f.running_in_test_harness && f.testsuite_delays) millisleep(millisec);


 /******************************************************************************/
 /* Taint-checked file opens */
+static inline uschar *
+is_tainted2(const void *p, int lflags, const uschar* fmt, ...)
+{
+va_list ap;
+uschar *msg;
+rmark mark;
+
+if (!is_tainted(p))
+  return NULL;
+
+mark = store_mark();
+va_start(ap, fmt);
+msg = string_from_gstring(string_vformat(NULL, SVFMT_TAINT_NOCHK|SVFMT_EXTEND, fmt, ap));
+va_end(ap);
+
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+if (allow_insecure_tainted_data)
+  {
+  if LOGGING(tainted) log_write(0, LOG_MAIN, "Warning: %s", msg);
+  store_reset(mark);
+  return NULL;
+  }
+#endif
+
+if (lflags) log_write(0, lflags, "%s", msg);
+return msg; /* no store_reset(), as the message might be used afterwards and Exim
+            is expected to exit anyway, so we do not care about the leaked
+            storage */
+}


 static inline int
 exim_open2(const char *pathname, int flags)
 {
-if (!is_tainted(pathname)) return open(pathname, flags);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+  return open(pathname, flags);
 errno = EACCES;
 return -1;
 }
+
 static inline int
 exim_open(const char *pathname, int flags, mode_t mode)
 {
-if (!is_tainted(pathname)) return open(pathname, flags, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+  return open(pathname, flags, mode);
 errno = EACCES;
 return -1;
 }
@@ -1146,16 +1176,16 @@ return -1;
 static inline int
 exim_openat(int dirfd, const char *pathname, int flags)
 {
-if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+  return openat(dirfd, pathname, flags);
 errno = EACCES;
 return -1;
 }
 static inline int
 exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
 {
-if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+  return openat(dirfd, pathname, flags, mode);
 errno = EACCES;
 return -1;
 }
@@ -1164,8 +1194,8 @@ return -1;
 static inline FILE *
 exim_fopen(const char *pathname, const char *mode)
 {
-if (!is_tainted(pathname)) return fopen(pathname, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+  return fopen(pathname, mode);
 errno = EACCES;
 return NULL;
 }
@@ -1173,8 +1203,8 @@ return NULL;
 static inline DIR *
 exim_opendir(const uschar * name)
 {
-if (!is_tainted(name)) return opendir(CCS name);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name);
+if (!is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name))
+  return opendir(CCS name);
 errno = EACCES;
 return NULL;
 }
diff --git a/src/src/globals.c b/src/src/globals.c
index e965860..9e68aac 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -98,6 +98,10 @@ int     sqlite_lock_timeout    = 5;
 BOOL    move_frozen_messages   = FALSE;
 #endif


+#ifdef ALLOW_INSECURE_TAINTED_DATA
+BOOL    allow_insecure_tainted_data = FALSE;
+#endif
+
 /* These variables are outside the #ifdef because it keeps the code less
 cluttered in several places (e.g. during logging) if we can always refer to
 them. Also, the tls_ variables are now always visible.  Note that these are
@@ -1055,6 +1059,9 @@ int     log_default[]          = { /* for initializing log_selector */
   Li_size_reject,
   Li_skip_delivery,
   Li_smtp_confirmation,
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+  Li_tainted,
+#endif
   Li_tls_certificate_verified,
   Li_tls_cipher,
   -1
@@ -1124,6 +1131,9 @@ bit_table log_options[]        = { /* must be in alphabetical order,
   BIT_TABLE(L, smtp_protocol_error),
   BIT_TABLE(L, smtp_syntax_error),
   BIT_TABLE(L, subject),
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+  BIT_TABLE(L, tainted),
+#endif
   BIT_TABLE(L, tls_certificate_verified),
   BIT_TABLE(L, tls_cipher),
   BIT_TABLE(L, tls_peerdn),
diff --git a/src/src/globals.h b/src/src/globals.h
index 937cce7..657e6c7 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -77,6 +77,10 @@ extern int     sqlite_lock_timeout;    /* Internal lock waiting timeout */
 extern BOOL    move_frozen_messages;   /* Get them out of the normal directory */
 #endif


+#ifdef ALLOW_INSECURE_TAINTED_DATA
+extern BOOL    allow_insecure_tainted_data;
+#endif
+
 /* These variables are outside the #ifdef because it keeps the code less
 cluttered in several places (e.g. during logging) if we can always refer to
 them. Also, the tls_ variables are now always visible. */
diff --git a/src/src/macros.h b/src/src/macros.h
index f8987d6..ccdcc45 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -491,6 +491,9 @@ enum logbit {
   Li_smtp_mailauth,
   Li_smtp_no_mail,
   Li_subject,
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+  Li_tainted,
+#endif
   Li_tls_certificate_verified,
   Li_tls_cipher,
   Li_tls_peerdn,
diff --git a/src/src/readconf.c b/src/src/readconf.c
index ae36fa0..34ebf87 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -68,6 +68,9 @@ static optionlist optionlist_config[] = {
   { "add_environment",          opt_stringptr,   {&add_environment} },
   { "admin_groups",             opt_gidlist,     {&admin_groups} },
   { "allow_domain_literals",    opt_bool,        {&allow_domain_literals} },
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+  { "allow_insecure_tainted_data", opt_bool,     {&allow_insecure_tainted_data} },
+#endif
   { "allow_mx_to_ip",           opt_bool,        {&allow_mx_to_ip} },
   { "allow_utf8_domains",       opt_bool,        {&allow_utf8_domains} },
   { "auth_advertise_hosts",     opt_stringptr,   {&auth_advertise_hosts} },