]> git.netwichtig.de Git - user/henk/code/exim.git/blobdiff - src/src/sieve.c
Split out separate fn for success-DSN send
[user/henk/code/exim.git] / src / src / sieve.c
index 18aa3e609ead7f995d2bcde2bbd63473d0379e79..4793d5756c9a1a6f451a4e8d916b1b8d097d6b95 100644 (file)
@@ -2,9 +2,11 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) Michael Haardt 2003 - 2015
- * Copyright (c) The Exim Maintainers 2016 - 2020
+/*
+ * Copyright (c) The Exim Maintainers 2016 - 2022
+ * Copyright (c) Michael Haardt 2003 - 2015
  * See the file NOTICE for conditions of use and distribution.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 /* This code was contributed by Michael Haardt. */
@@ -54,7 +56,7 @@
 
 struct Sieve
   {
-  uschar *filter;
+  const uschar *filter;
   const uschar *pc;
   int line;
   const uschar *errmsg;
@@ -71,7 +73,7 @@ struct Sieve
   int require_enotify;
   struct Notification *notified;
 #endif
-  uschar *enotify_mailto_owner;
+  const uschar *enotify_mailto_owner;
 #ifdef SUBADDRESS
   int require_subaddress;
 #endif
@@ -79,7 +81,7 @@ struct Sieve
   int require_vacation;
   int vacation_ran;
 #endif
-  uschar *vacation_directory;
+  const uschar *vacation_directory;
   const uschar *subaddress;
   const uschar *useraddress;
   int require_copy;
@@ -245,7 +247,7 @@ for (int pass = 0; pass <= 1; pass++)
     dst->length=0;
   else
     {
-    dst->character = store_get(dst->length+1, is_tainted(src->character)); /* plus one for \0 */
+    dst->character = store_get(dst->length+1, src->character); /* plus one for \0 */
     new=dst->character;
     }
   for (const uschar * start = src->character, * end = start + src->length;
@@ -437,23 +439,22 @@ if (*uri && *uri!='?')
       {
       gstring * g = string_catn(NULL, start, uri-start);
 
-      to.character = string_from_gstring(g);
-      to.length = g->ptr;
+      to.length = len_string_from_gstring(g, &to.character);
       if (uri_decode(&to)==-1)
         {
         filter->errmsg=US"Invalid URI encoding";
         return -1;
         }
-      new=store_get(sizeof(string_item), FALSE);
-      new->text = store_get(to.length+1, is_tainted(to.character));
+      new = store_get(sizeof(string_item), GET_UNTAINTED);
+      new->text = store_get(to.length+1, to.character);
       if (to.length) memcpy(new->text, to.character, to.length);
-      new->text[to.length]='\0';
-      new->next=*recipient;
-      *recipient=new;
+      new->text[to.length] = '\0';
+      new->next = *recipient;
+      *recipient = new;
       }
     else
       {
-      filter->errmsg=US"Missing addr-spec in URI";
+      filter->errmsg = US"Missing addr-spec in URI";
       return -1;
       }
     if (*uri=='%') uri+=3;
@@ -470,8 +471,7 @@ if (*uri=='?')
       {
       gstring * g = string_catn(NULL, start, uri-start);
 
-      hname.character = string_from_gstring(g);
-      hname.length = g->ptr;
+      hname.length = len_string_from_gstring(g, &hname.character);
       if (uri_decode(&hname)==-1)
         {
         filter->errmsg=US"Invalid URI encoding";
@@ -492,8 +492,7 @@ if (*uri=='?')
       {
       gstring * g = string_catn(NULL, start, uri-start);
 
-      hname.character = string_from_gstring(g);
-      hname.length = g->ptr;
+      hname.length = len_string_from_gstring(g, &hname.character);
       if (uri_decode(&hvalue)==-1)
         {
         filter->errmsg=US"Invalid URI encoding";
@@ -502,8 +501,8 @@ if (*uri=='?')
       }
     if (hname.length==2 && strcmpic(hname.character, US"to")==0)
       {
-      new=store_get(sizeof(string_item), FALSE);
-      new->text = store_get(hvalue.length+1, is_tainted(hvalue.character));
+      new=store_get(sizeof(string_item), GET_UNTAINTED);
+      new->text = store_get(hvalue.length+1, hvalue.character);
       if (hvalue.length) memcpy(new->text, hvalue.character, hvalue.length);
       new->text[hvalue.length]='\0';
       new->next=*recipient;
@@ -539,8 +538,7 @@ if (*uri=='?')
         g = string_catn(g, hvalue.character, hvalue.length);
         g = string_catn(g, CUS "\n", 1);
 
-       header->character = string_from_gstring(g);
-       header->length = g->ptr;
+       hname.length = len_string_from_gstring(g, &hname.character);
         }
       }
     if (*uri=='&') ++uri;
@@ -1480,10 +1478,7 @@ if (*filter->pc=='"') /* quoted string */
       ++filter->pc;
 
       if (g)
-       {
-       data->character = string_from_gstring(g);
-       data->length = g->ptr;
-       }
+       data->length = len_string_from_gstring(g, &data->character);
       else
        data->character = US"\0";
       /* that way, there will be at least one character allocated */
@@ -1567,10 +1562,7 @@ else if (Ustrncmp(filter->pc,CUS "text:",5)==0) /* multiline string */
 #endif
         {
        if (g)
-         {
-         data->character = string_from_gstring(g);
-         data->length = g->ptr;
-         }
+         data->length = len_string_from_gstring(g, &data->character);
        else
          data->character = US"\0";
        /* that way, there will be at least one character allocated */
@@ -1729,7 +1721,7 @@ if (*filter->pc=='[') /* string list */
       struct String *new;
 
       dataCapacity = dataCapacity ? dataCapacity * 2 : 4;
-      new = store_get(sizeof(struct String) * dataCapacity, FALSE);
+      new = store_get(sizeof(struct String) * dataCapacity, GET_UNTAINTED);
 
       if (d) memcpy(new,d,sizeof(struct String)*dataLength);
       d = new;
@@ -1767,7 +1759,7 @@ if (*filter->pc=='[') /* string list */
   }
 else /* single string */
   {
-  if (!(d=store_get(sizeof(struct String)*2, FALSE)))
+  if (!(d=store_get(sizeof(struct String)*2, GET_UNTAINTED)))
     return -1;
 
   m=parse_string(filter,&d[0]);
@@ -3073,7 +3065,7 @@ while (*filter->pc)
         if (!already)
           /* New notification, process it */
           {
-          struct Notification * sent = store_get(sizeof(struct Notification), FALSE);
+          struct Notification * sent = store_get(sizeof(struct Notification), GET_UNTAINTED);
           sent->method=method;
           sent->importance=importance;
           sent->message=message;
@@ -3087,31 +3079,25 @@ while (*filter->pc)
             if ((pid = child_open_exim2(&fd, envelope_from, envelope_from,
                        US"sieve-notify")) >= 1)
               {
-              FILE *f;
-              uschar *buffer;
-              int buffer_capacity;
+              FILE * f = fdopen(fd, "wb");
 
-              f = fdopen(fd, "wb");
               fprintf(f,"From: %s\n", from.length == -1
                ? expand_string(US"$local_part_prefix$local_part$local_part_suffix@$domain")
                : from.character);
               for (string_item * p = recipient; p; p=p->next)
-               fprintf(f,"To: %s\n",p->text);
-              fprintf(f,"Auto-Submitted: auto-notified; %s\n",filter->enotify_mailto_owner);
-              if (header.length>0) fprintf(f,"%s",header.character);
+               fprintf(f, "To: %s\n",p->text);
+              fprintf(f, "Auto-Submitted: auto-notified; %s\n", filter->enotify_mailto_owner);
+              if (header.length > 0) fprintf(f, "%s", header.character);
               if (message.length==-1)
                 {
                 message.character=US"Notification";
                 message.length=Ustrlen(message.character);
                 }
-              /* Allocation is larger than necessary, but enough even for split MIME words */
-              buffer_capacity = 32 + 4*message.length;
-              buffer=store_get(buffer_capacity, TRUE);
               if (message.length != -1)
                fprintf(f, "Subject: %s\n", parse_quote_2047(message.character,
-                 message.length, US"utf-8", buffer, buffer_capacity, TRUE));
+                 message.length, US"utf-8", TRUE));
               fprintf(f,"\n");
-              if (body.length>0) fprintf(f,"%s\n",body.character);
+              if (body.length > 0) fprintf(f, "%s\n", body.character);
               fflush(f);
               (void)fclose(f);
               (void)child_close(pid, 0);
@@ -3218,9 +3204,9 @@ while (*filter->pc)
           }
         for (struct String * a = addresses; a->length != -1; ++a)
           {
-          string_item * new = store_get(sizeof(string_item), FALSE);
+          string_item * new = store_get(sizeof(string_item), GET_UNTAINTED);
 
-          new->text = store_get(a->length+1, is_tainted(a->character));
+          new->text = store_get(a->length+1, a->character);
           if (a->length) memcpy(new->text,a->character,a->length);
           new->text[a->length]='\0';
           new->next=aliases;
@@ -3263,8 +3249,6 @@ while (*filter->pc)
     if (exec)
       {
       address_item *addr;
-      uschar *buffer;
-      int buffer_capacity;
       md5 base;
       uschar digest[16];
       uschar hexdigest[33];
@@ -3309,7 +3293,7 @@ while (*filter->pc)
 
           if (subject.length==-1)
             {
-            uschar *subject_def;
+            uschar * subject_def;
 
             subject_def = expand_string(US"${if def:header_subject {true}{false}}");
             if (subject_def && Ustrcmp(subject_def,"true")==0)
@@ -3318,13 +3302,12 @@ while (*filter->pc)
 
               expand_header(&subject,&str_subject);
               g = string_catn(g, subject.character, subject.length);
-             subject.character = string_from_gstring(g);
-              subject.length = g->ptr;
+             subject.length = len_string_from_gstring(g, &subject.character);
               }
             else
               {
-              subject.character=US"Automated reply";
-              subject.length=Ustrlen(subject.character);
+              subject.character = US"Automated reply";
+              subject.length = Ustrlen(subject.character);
               }
             }
 
@@ -3335,18 +3318,15 @@ while (*filter->pc)
           addr->prop.ignore_error = TRUE;
           addr->next = *generated;
           *generated = addr;
-          addr->reply = store_get(sizeof(reply_item), FALSE);
+          addr->reply = store_get(sizeof(reply_item), GET_UNTAINTED);
           memset(addr->reply,0,sizeof(reply_item)); /* XXX */
           addr->reply->to = string_copy(sender_address);
           if (from.length==-1)
             addr->reply->from = expand_string(US"$local_part@$domain");
           else
             addr->reply->from = from.character;
-          /* Allocation is larger than necessary, but enough even for split MIME words */
-          buffer_capacity=32+4*subject.length;
-          buffer = store_get(buffer_capacity, is_tainted(subject.character));
          /* deconst cast safe as we pass in a non-const item */
-          addr->reply->subject = US parse_quote_2047(subject.character, subject.length, US"utf-8", buffer, buffer_capacity, TRUE);
+          addr->reply->subject = US parse_quote_2047(subject.character, subject.length, US"utf-8", TRUE);
           addr->reply->oncelog = string_from_gstring(once);
           addr->reply->once_repeat=days*86400;
 
@@ -3436,7 +3416,7 @@ filter->require_iascii_numeric=0;
 
 if (parse_white(filter)==-1) return -1;
 
-if (exec && filter->vacation_directory != NULL && filter_test == FTEST_NONE)
+if (exec && filter->vacation_directory && filter_test == FTEST_NONE)
   {
   DIR *oncelogdir;
   struct dirent *oncelog;
@@ -3459,8 +3439,8 @@ if (exec && filter->vacation_directory != NULL && filter_test == FTEST_NONE)
     while ((oncelog = readdir(oncelogdir)))
       if (strlen(oncelog->d_name)==32)
         {
-        uschar *s = string_sprintf("%s/%s",filter->vacation_directory,oncelog->d_name);
-        if (Ustat(s,&properties)==0 && (properties.st_mtime+VACATION_MAX_DAYS*86400)<now)
+        uschar *s = string_sprintf("%s/%s", filter->vacation_directory, oncelog->d_name);
+        if (Ustat(s,&properties) == 0 && properties.st_mtime+VACATION_MAX_DAYS*86400 < now)
           Uunlink(s);
         }
     closedir(oncelogdir);
@@ -3495,7 +3475,7 @@ while (parse_identifier(filter,CUS "require"))
 #ifdef ENOTIFY
     else if (eq_octet(check,&str_enotify,0))
       {
-      if (filter->enotify_mailto_owner == NULL)
+      if (!filter->enotify_mailto_owner)
         {
         filter->errmsg=CUS "enotify disabled";
         return -1;
@@ -3509,7 +3489,7 @@ while (parse_identifier(filter,CUS "require"))
 #ifdef VACATION
     else if (eq_octet(check,&str_vacation,0))
       {
-      if (filter_test == FTEST_NONE && filter->vacation_directory == NULL)
+      if (filter_test == FTEST_NONE && !filter->vacation_directory)
         {
         filter->errmsg=CUS "vacation disabled";
         return -1;
@@ -3565,44 +3545,36 @@ Returns:      FF_DELIVERED     success, a significant action was taken
 */
 
 int
-sieve_interpret(uschar *filter, int options, uschar *vacation_directory,
-  uschar *enotify_mailto_owner, uschar *useraddress, uschar *subaddress,
-  address_item **generated, uschar **error)
+sieve_interpret(const uschar * filter, int options,
+  const uschar * vacation_directory, const uschar * enotify_mailto_owner,
+  const uschar * useraddress, const uschar * subaddress,
+  address_item ** generated, uschar ** error)
 {
 struct Sieve sieve;
 int r;
-uschar *msg;
-
-options = options; /* Keep picky compilers happy */
-error = error;
+uschar * msg;
 
 DEBUG(D_route) debug_printf("Sieve: start of processing\n");
 sieve.filter = filter;
 
 if (!vacation_directory)
   sieve.vacation_directory = NULL;
-else
+else if (!(sieve.vacation_directory = expand_cstring(vacation_directory)))
   {
-  if (!(sieve.vacation_directory = expand_string(vacation_directory)))
-    {
-    *error = string_sprintf("failed to expand \"%s\" "
-      "(sieve_vacation_directory): %s", vacation_directory,
-      expand_string_message);
-    return FF_ERROR;
-    }
+  *error = string_sprintf("failed to expand \"%s\" "
+    "(sieve_vacation_directory): %s", vacation_directory,
+    expand_string_message);
+  return FF_ERROR;
   }
 
 if (!enotify_mailto_owner)
   sieve.enotify_mailto_owner = NULL;
-else
+else if (!(sieve.enotify_mailto_owner = expand_cstring(enotify_mailto_owner)))
   {
-  if (!(sieve.enotify_mailto_owner = expand_string(enotify_mailto_owner)))
-    {
-    *error = string_sprintf("failed to expand \"%s\" "
-      "(sieve_enotify_mailto_owner): %s", enotify_mailto_owner,
-      expand_string_message);
-    return FF_ERROR;
-    }
+  *error = string_sprintf("failed to expand \"%s\" "
+    "(sieve_enotify_mailto_owner): %s", enotify_mailto_owner,
+    expand_string_message);
+  return FF_ERROR;
   }
 
 sieve.useraddress = useraddress
@@ -3610,14 +3582,13 @@ sieve.useraddress = useraddress
 sieve.subaddress = subaddress;
 
 #ifdef COMPILE_SYNTAX_CHECKER
-if (parse_start(&sieve,0,generated)==1)
+if (parse_start(&sieve, 0, generated) == 1)
 #else
-if (parse_start(&sieve,1,generated)==1)
+if (parse_start(&sieve, 1, generated) == 1)
 #endif
-  {
   if (sieve.keep)
     {
-    add_addr(generated,US"inbox",1,0,0,0);
+    add_addr(generated, US"inbox", 1, 0, 0, 0);
     msg = US"Implicit keep";
     r = FF_DELIVERED;
     }
@@ -3626,7 +3597,6 @@ if (parse_start(&sieve,1,generated)==1)
     msg = US"No implicit keep";
     r = FF_DELIVERED;
     }
-  }
 else
   {
   msg = string_sprintf("Sieve error: %s in line %d",sieve.errmsg,sieve.line);