Merge branch 'hs/taintwarn'
[exim.git] / src / src / transports / autoreply.c
index 666591b6029cc79645156659e5761465e64b5c9d..80c7c0db0c655306709facc766c9070b5dabadcf 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -16,44 +17,27 @@ order (note that "_" comes before the lower case letters). Those starting
 with "*" are not settable by the user but are used by the option-reading
 software for alternative value types. Some options are publicly visible and so
 are stored in the driver instance block. These are flagged with opt_public. */
+#define LOFF(field) OPT_OFF(autoreply_transport_options_block, field)
 
 optionlist autoreply_transport_options[] = {
-  { "bcc",               opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, bcc) },
-  { "cc",                opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, cc) },
-  { "file",              opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, file) },
-  { "file_expand",     opt_bool,
-      (void *)offsetof(autoreply_transport_options_block, file_expand) },
-  { "file_optional",     opt_bool,
-      (void *)offsetof(autoreply_transport_options_block, file_optional) },
-  { "from",              opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, from) },
-  { "headers",           opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, headers) },
-  { "log",               opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, logfile) },
-  { "mode",              opt_octint,
-      (void *)offsetof(autoreply_transport_options_block, mode) },
-  { "never_mail",        opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, never_mail) },
-  { "once",              opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, oncelog) },
-  { "once_file_size",    opt_int,
-      (void *)offsetof(autoreply_transport_options_block, once_file_size) },
-  { "once_repeat",       opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, once_repeat) },
-  { "reply_to",          opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, reply_to) },
-  { "return_message",    opt_bool,
-      (void *)offsetof(autoreply_transport_options_block, return_message) },
-  { "subject",           opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, subject) },
-  { "text",              opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, text) },
-  { "to",                opt_stringptr,
-      (void *)offsetof(autoreply_transport_options_block, to) },
+  { "bcc",               opt_stringptr,        LOFF(bcc) },
+  { "cc",                opt_stringptr,        LOFF(cc) },
+  { "file",              opt_stringptr,        LOFF(file) },
+  { "file_expand",     opt_bool,       LOFF(file_expand) },
+  { "file_optional",     opt_bool,     LOFF(file_optional) },
+  { "from",              opt_stringptr,        LOFF(from) },
+  { "headers",           opt_stringptr,        LOFF(headers) },
+  { "log",               opt_stringptr,        LOFF(logfile) },
+  { "mode",              opt_octint,   LOFF(mode) },
+  { "never_mail",        opt_stringptr,        LOFF(never_mail) },
+  { "once",              opt_stringptr,        LOFF(oncelog) },
+  { "once_file_size",    opt_int,      LOFF(once_file_size) },
+  { "once_repeat",       opt_stringptr,        LOFF(once_repeat) },
+  { "reply_to",          opt_stringptr,        LOFF(reply_to) },
+  { "return_message",    opt_bool,     LOFF(return_message) },
+  { "subject",           opt_stringptr,        LOFF(subject) },
+  { "text",              opt_stringptr,        LOFF(text) },
+  { "to",                opt_stringptr,        LOFF(to) },
 };
 
 /* Size of the options list. An extern variable has to be used so that its
@@ -219,7 +203,7 @@ while (*s != 0)
   /* If there is some kind of syntax error, just give up on this header
   line. */
 
-  if (next == NULL) break;
+  if (!next) break;
 
   /* See if the address is on the never_mail list */
 
@@ -420,14 +404,15 @@ recipient cache. */
 
 if (oncelog && *oncelog && to)
   {
+  uschar *m;
   time_t then = 0;
 
-  if (is_tainted(oncelog))
+  if ((m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
+      " not permitted", oncelog, tblock->name)))
     {
     addr->transport_return = DEFER;
     addr->basic_errno = EACCES;
-    addr->message = string_sprintf("Tainted '%s' (once file for %s transport)"
-      " not permitted", oncelog, tblock->name);
+    addr->message = m;
     goto END_OFF;
     }
 
@@ -490,10 +475,10 @@ if (oncelog && *oncelog && to)
   else
     {
     EXIM_DATUM key_datum, result_datum;
-    uschar * dirname = string_copy(oncelog);
-    uschar * s;
+    uschar * dirname, * s;
 
-    if ((s = Ustrrchr(dirname, '/'))) *s = '\0';
+    dirname = (s = Ustrrchr(oncelog, '/'))
+      ? string_copyn(oncelog, s - oncelog) : NULL;
     EXIM_DBOPEN(oncelog, dirname, O_RDWR|O_CREAT, ob->mode, &dbm_file);
     if (!dbm_file)
       {
@@ -531,13 +516,14 @@ if (oncelog && *oncelog && to)
 
   if (then != 0 && (once_repeat_sec <= 0 || now - then < once_repeat_sec))
     {
+    uschar *m;
     int log_fd;
-    if (is_tainted(logfile))
+    if ((m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
+       " not permitted", logfile, tblock->name)))
       {
       addr->transport_return = DEFER;
       addr->basic_errno = EACCES;
-      addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)"
-       " not permitted", logfile, tblock->name);
+      addr->message = m;
       goto END_OFF;
       }
 
@@ -564,12 +550,13 @@ if (oncelog && *oncelog && to)
 /* We are going to send a message. Ensure any requested file is available. */
 if (file)
   {
-  if (is_tainted(file))
+  uschar *m;
+  if ((m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
+      " not permitted", file, tblock->name)))
     {
     addr->transport_return = DEFER;
     addr->basic_errno = EACCES;
-    addr->message = string_sprintf("Tainted '%s' (file for %s transport)"
-      " not permitted", file, tblock->name);
+    addr->message = m;
     return FALSE;
     }
   if (!(ff = Ufopen(file, "rb")) && !ob->file_optional)
@@ -584,12 +571,10 @@ if (file)
 
 /* Make a subprocess to send the message */
 
-pid = child_open_exim(&fd);
-
-/* Creation of child failed; defer this delivery. */
-
-if (pid < 0)
+if ((pid = child_open_exim(&fd, US"autoreply")) < 0)
   {
+  /* Creation of child failed; defer this delivery. */
+
   addr->transport_return = DEFER;
   addr->basic_errno = errno;
   addr->message = string_sprintf("Failed to create child process to send "