b56b593b85656cf8df721772a961198f71bf3acd
[exim.git] / src / src / filter.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2023 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10
11 /* Code for mail filtering functions. */
12
13 #include "exim.h"
14
15
16 /* Command arguments and left/right points in conditions can contain different
17 types of data, depending on the particular command or condition. Originally,
18 (void *) was used as "any old type", with casts, but this gives trouble and
19 warnings in some environments. So now it is done "properly", with a union. We
20 need to declare the structures first because some of them are recursive. */
21
22 struct filter_cmd;
23 struct condition_block;
24
25 union argtypes {
26   struct string_item     *a;
27   BOOL                    b;
28   struct condition_block *c;
29   struct filter_cmd      *f;
30   int                     i;
31   const uschar            *u;
32 };
33
34 /* Local structures used in this module */
35
36 typedef struct filter_cmd {
37   struct filter_cmd *next;
38   int command;
39   BOOL seen;
40   BOOL noerror;
41   union argtypes args[1];
42 } filter_cmd;
43
44 typedef struct condition_block {
45   struct condition_block *parent;
46   int type;
47   BOOL testfor;
48   union argtypes left;
49   union argtypes right;
50 } condition_block;
51
52 /* Miscellaneous other declarations */
53
54 static uschar **error_pointer;
55 static const uschar *log_filename;
56 static int  filter_options;
57 static int  line_number;
58 static int  expect_endif;
59 static int  had_else_endif;
60 static int  log_fd;
61 static int  log_mode;
62 static int  output_indent;
63 static BOOL filter_delivered;
64 static BOOL finish_obeyed;
65 static BOOL seen_force;
66 static BOOL seen_value;
67 static BOOL noerror_force;
68
69 enum { had_neither, had_else, had_elif, had_endif };
70
71 static BOOL read_command_list(const uschar **, filter_cmd ***, BOOL);
72
73
74 /* The string arguments for the mail command. The header line ones (that are
75 permitted to include \n followed by white space) first, and then the body text
76 one (it can have \n anywhere). Then the file names and once_repeat, which may
77 not contain \n. */
78
79 static const char *mailargs[] = {  /* "to" must be first, and */
80   "to",                            /* "cc" and "bcc" must follow */
81   "cc",
82   "bcc",
83   "from",
84   "reply_to",
85   "subject",
86   "extra_headers",           /* miscellaneous added header lines */
87   "text",
88   "file",
89   "log",
90   "once",
91   "once_repeat"
92 };
93
94 /* The count of string arguments */
95
96 #define MAILARGS_STRING_COUNT (nelem(mailargs))
97
98 /* The count of string arguments that are actually passed over as strings
99 (once_repeat is converted to an int). */
100
101 #define mailargs_string_passed (MAILARGS_STRING_COUNT - 1)
102
103 /* This defines the offsets for the arguments; first the string ones, and
104 then the non-string ones. The order must be as above. */
105
106 enum { mailarg_index_to,
107        mailarg_index_cc,
108        mailarg_index_bcc,
109        mailarg_index_from,
110        mailarg_index_reply_to,
111        mailarg_index_subject,
112        mailarg_index_headers,      /* misc headers must be last */
113        mailarg_index_text,         /* text is first after headers */
114        mailarg_index_file,         /* between text and expand are filenames */
115        mailarg_index_log,
116        mailarg_index_once,
117        mailarg_index_once_repeat,  /* a time string */
118        mailarg_index_expand,       /* first non-string argument */
119        mailarg_index_return,
120        mailargs_total              /* total number of arguments */
121        };
122
123 /* Offsets in the data structure for the string arguments (note that
124 once_repeat isn't a string argument at this point.) */
125
126 static int reply_offsets[] = {  /* must be in same order as above */
127   offsetof(reply_item, to),
128   offsetof(reply_item, cc),
129   offsetof(reply_item, bcc),
130   offsetof(reply_item, from),
131   offsetof(reply_item, reply_to),
132   offsetof(reply_item, subject),
133   offsetof(reply_item, headers),
134   offsetof(reply_item, text),
135   offsetof(reply_item, file),
136   offsetof(reply_item, logfile),
137   offsetof(reply_item, oncelog),
138 };
139
140 /* Condition identities and names, with negated versions for some
141 of them. */
142
143 enum { cond_and, cond_or, cond_personal, cond_begins, cond_BEGINS,
144        cond_ends, cond_ENDS, cond_is, cond_IS, cond_matches,
145        cond_MATCHES, cond_contains, cond_CONTAINS, cond_delivered,
146        cond_above, cond_below, cond_errormsg, cond_firsttime,
147        cond_manualthaw, cond_foranyaddress };
148
149 static const char *cond_names[] = {
150   "and", "or", "personal",
151   "begins", "BEGINS", "ends", "ENDS",
152   "is", "IS", "matches", "MATCHES", "contains",
153   "CONTAINS", "delivered", "above", "below", "error_message",
154   "first_delivery", "manually_thawed", "foranyaddress" };
155
156 static const char *cond_not_names[] = {
157   "", "", "not personal",
158   "does not begin", "does not BEGIN",
159   "does not end", "does not END",
160   "is not", "IS not", "does not match",
161   "does not MATCH", "does not contain", "does not CONTAIN",
162   "not delivered", "not above", "not below", "not error_message",
163   "not first_delivery", "not manually_thawed", "not foranyaddress" };
164
165 /* Tables of binary condition words and their corresponding types. Not easy
166 to amalgamate with the above because of the different variants. */
167
168 static const char *cond_words[] = {
169    "BEGIN",
170    "BEGINS",
171    "CONTAIN",
172    "CONTAINS",
173    "END",
174    "ENDS",
175    "IS",
176    "MATCH",
177    "MATCHES",
178    "above",
179    "begin",
180    "begins",
181    "below",
182    "contain",
183    "contains",
184    "end",
185    "ends",
186    "is",
187    "match",
188    "matches"};
189
190 static int cond_word_count = nelem(cond_words);
191
192 static int cond_types[] = { cond_BEGINS, cond_BEGINS, cond_CONTAINS,
193   cond_CONTAINS, cond_ENDS, cond_ENDS, cond_IS, cond_MATCHES, cond_MATCHES,
194   cond_above, cond_begins, cond_begins, cond_below, cond_contains,
195   cond_contains, cond_ends, cond_ends, cond_is, cond_matches, cond_matches };
196
197 /* Command identities */
198
199 enum { add_command, defer_command, deliver_command, elif_command, else_command,
200        endif_command, finish_command, fail_command, freeze_command,
201        headers_command, if_command, logfile_command, logwrite_command,
202        mail_command, noerror_command, pipe_command, save_command, seen_command,
203        testprint_command, unseen_command, vacation_command };
204
205 static const char * command_list[] = {
206   [add_command] =       "add",
207   [defer_command] =     "defer",
208   [deliver_command] =   "deliver",
209   [elif_command] =      "elif",
210   [else_command] =      "else",
211   [endif_command] =     "endif",
212   [finish_command] =    "finish",
213   [fail_command] =      "fail",
214   [freeze_command] =    "freeze",
215   [headers_command] =   "headers",
216   [if_command] =        "if",
217   [logfile_command] =   "logfile",
218   [logwrite_command] =  "logwrite",
219   [mail_command] =      "mail",
220   [noerror_command] =   "noerror",
221   [pipe_command] =      "pipe",
222   [save_command] =      "save",
223   [seen_command] =      "seen",
224   [testprint_command] = "testprint",
225   [unseen_command] =    "unseen",
226   [vacation_command] =  "vacation"
227 };
228
229 static int command_list_count = nelem(command_list);
230
231 /* This table contains the number of expanded arguments in the bottom 4 bits.
232 If the top bit is set, it means that the default for the command is "seen". */
233
234 static uschar command_exparg_count[] = {
235   [add_command] =       2,
236   [defer_command] =     1,
237   [deliver_command] =   128+2,
238   [elif_command] =      0,
239   [else_command] =      0,
240   [endif_command] =     0,
241   [finish_command] =    0,
242   [fail_command] =      1,
243   [freeze_command] =    1,
244   [headers_command] =   1,
245   [if_command] =        0,
246   [logfile_command] =   1,
247   [logwrite_command] =  1,
248   [mail_command] =      MAILARGS_STRING_COUNT,
249   [noerror_command] =   0,
250   [pipe_command] =      128+0,
251   [save_command] =      128+1,
252   [seen_command] =      0,
253   [testprint_command] = 1,
254   [unseen_command] =    0,
255   [vacation_command] =  MAILARGS_STRING_COUNT
256 };
257
258
259
260 /*************************************************
261 *          Find next significant uschar            *
262 *************************************************/
263
264 /* Function to skip over white space and, optionally, comments.
265
266 Arguments:
267   ptr              pointer to next character
268   comment_allowed  if TRUE, comments (# to \n) are skipped
269
270 Returns:           pointer to next non-whitespace character
271 */
272
273 static const uschar *
274 nextsigchar(const uschar *ptr, BOOL comment_allowed)
275 {
276 for (;;)
277   {
278   while (isspace(*ptr))
279     {
280     if (*ptr == '\n') line_number++;
281     ptr++;
282     }
283   if (comment_allowed && *ptr == '#')
284     {
285     while (*(++ptr) != '\n' && *ptr != 0);
286     continue;
287     }
288   else break;
289   }
290 return ptr;
291 }
292
293
294
295 /*************************************************
296 *                Read one word                   *
297 *************************************************/
298
299 /* The terminator is white space unless bracket is TRUE, in which
300 case ( and ) terminate.
301
302 Arguments
303   ptr       pointer to next character
304   buffer    where to put the word
305   size      size of buffer
306   bracket   if TRUE, terminate on ( and ) as well as space
307
308 Returns:    pointer to the next significant character after the word
309 */
310
311 static const uschar *
312 nextword(const uschar *ptr, uschar *buffer, int size, BOOL bracket)
313 {
314 uschar *bp = buffer;
315 while (*ptr != 0 && !isspace(*ptr) &&
316        (!bracket || (*ptr != '(' && *ptr != ')')))
317   {
318   if (bp - buffer < size - 1) *bp++ = *ptr++; else
319     {
320     *error_pointer = string_sprintf("word is too long in line %d of "
321       "filter file (max = %d chars)", line_number, size);
322     break;
323     }
324   }
325 *bp = 0;
326 return nextsigchar(ptr, TRUE);
327 }
328
329
330
331 /*************************************************
332 *                Read one item                   *
333 *************************************************/
334
335 /* Might be a word, or might be a quoted string; in the latter case
336 do the escape stuff.
337
338 Arguments:
339   ptr        pointer to next character
340   buffer     where to put the item
341   size       size of buffer
342   bracket    if TRUE, terminate non-quoted on ( and ) as well as space
343
344 Returns:     the next significant character after the item
345 */
346
347 static const uschar *
348 nextitem(const uschar *ptr, uschar *buffer, int size, BOOL bracket)
349 {
350 uschar *bp = buffer;
351 if (*ptr != '\"') return nextword(ptr, buffer, size, bracket);
352
353 while (*++ptr && *ptr != '\"' && *ptr != '\n')
354   {
355   if (bp - buffer >= size - 1)
356     {
357     *error_pointer = string_sprintf("string is too long in line %d of "
358       "filter file (max = %d chars)", line_number, size);
359     break;
360     }
361
362   if (*ptr != '\\') *bp++ = *ptr; else
363     {
364     if (isspace(ptr[1]))    /* \<whitespace>NL<whitespace> ignored */
365       {
366       const uschar *p = ptr + 1;
367       while (*p != '\n' && isspace(*p)) p++;
368       if (*p == '\n')
369         {
370         line_number++;
371         ptr = p;
372         while (ptr[1] != '\n' && isspace(ptr[1])) ptr++;
373         continue;
374         }
375       }
376
377     *bp++ = string_interpret_escape(CUSS &ptr);
378     }
379   }
380
381 if (*ptr == '\"') ptr++;
382   else if (*error_pointer == NULL)
383     *error_pointer = string_sprintf("quote missing at end of string "
384       "in line %d", line_number);
385
386 *bp = 0;
387 return nextsigchar(ptr, TRUE);
388 }
389
390
391
392
393 /*************************************************
394 *          Convert a string + K|M to a number    *
395 *************************************************/
396
397 /*
398 Arguments:
399   s        points to text string
400   OK       set TRUE if a valid number was read
401
402 Returns:   the number, or 0 on error (with *OK FALSE)
403 */
404
405 static int
406 get_number(const uschar *s, BOOL *ok)
407 {
408 int value, count;
409 *ok = FALSE;
410 if (sscanf(CS s, "%i%n", &value, &count) != 1) return 0;
411 if (tolower(s[count]) == 'k') { value *= 1024; count++; }
412 if (tolower(s[count]) == 'm') { value *= 1024*1024; count++; }
413 while (isspace((s[count]))) count++;
414 if (s[count] != 0) return 0;
415 *ok = TRUE;
416 return value;
417 }
418
419
420
421 /*************************************************
422 *            Read one condition                  *
423 *************************************************/
424
425 /* A complete condition must be terminated by "then"; bracketed internal
426 conditions must be terminated by a closing bracket. They are read by calling
427 this function recursively.
428
429 Arguments:
430   ptr             points to start of condition
431   condition_block where to hang the created condition block
432   toplevel        TRUE when called at the top level
433
434 Returns:          points to next character after "then"
435 */
436
437 static const uschar *
438 read_condition(const uschar *ptr, condition_block **cond, BOOL toplevel)
439 {
440 uschar buffer[1024];
441 BOOL testfor = TRUE;
442 condition_block *current_parent = NULL;
443 condition_block **current = cond;
444
445 *current = NULL;
446
447 /* Loop to read next condition */
448
449 for (;;)
450   {
451   condition_block *c;
452
453   /* reaching the end of the input is an error. */
454
455   if (!*ptr)
456     {
457     *error_pointer = US"\"then\" missing at end of filter file";
458     break;
459     }
460
461   /* Opening bracket at the start of a condition introduces a nested
462   condition, which must be terminated by a closing bracket. */
463
464   if (*ptr == '(')
465     {
466     ptr = read_condition(nextsigchar(ptr+1, TRUE), &c, FALSE);
467     if (*error_pointer != NULL) break;
468     if (*ptr != ')')
469       {
470       *error_pointer = string_sprintf("expected \")\" in line %d of "
471         "filter file", line_number);
472       break;
473       }
474     if (!testfor)
475       {
476       c->testfor = !c->testfor;
477       testfor = TRUE;
478       }
479     ptr = nextsigchar(ptr+1, TRUE);
480     }
481
482
483   /* Closing bracket at the start of a condition is an error. Give an
484   explicit message, as otherwise "unknown condition" would be confusing. */
485
486   else if (*ptr == ')')
487     {
488     *error_pointer = string_sprintf("unexpected \")\" in line %d of "
489       "filter file", line_number);
490     break;
491     }
492
493   /* Otherwise we expect a word or a string. */
494
495   else
496     {
497     ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
498     if (*error_pointer) break;
499
500     /* "Then" at the start of a condition is an error */
501
502     if (Ustrcmp(buffer, "then") == 0)
503       {
504       *error_pointer = string_sprintf("unexpected \"then\" near line %d of "
505         "filter file", line_number);
506       break;
507       }
508
509     /* "Not" at the start of a condition negates the testing condition. */
510
511     if (Ustrcmp(buffer, "not") == 0)
512       {
513       testfor = !testfor;
514       continue;
515       }
516
517     /* Build a condition block from the specific word. */
518
519     c = store_get(sizeof(condition_block), GET_UNTAINTED);
520     c->left.u = c->right.u = NULL;
521     c->testfor = testfor;
522     testfor = TRUE;
523
524     /* Check for conditions that start with a keyword */
525
526     if (Ustrcmp(buffer, "delivered") == 0) c->type = cond_delivered;
527     else if (Ustrcmp(buffer, "error_message") == 0) c->type = cond_errormsg;
528     else if (Ustrcmp(buffer, "first_delivery") == 0) c->type = cond_firsttime;
529     else if (Ustrcmp(buffer, "manually_thawed") == 0) c->type = cond_manualthaw;
530
531     /* Personal can be followed by any number of aliases */
532
533     else if (Ustrcmp(buffer, "personal") == 0)
534       {
535       c->type = cond_personal;
536       for (;;)
537         {
538         string_item *aa;
539         const uschar * saveptr = ptr;
540         ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
541         if (*error_pointer) break;
542         if (Ustrcmp(buffer, "alias") != 0)
543           {
544           ptr = saveptr;
545           break;
546           }
547         ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
548         if (*error_pointer) break;
549         aa = store_get(sizeof(string_item), GET_UNTAINTED);
550         aa->text = string_copy(buffer);
551         aa->next = c->left.a;
552         c->left.a = aa;
553         }
554       }
555
556     /* Foranyaddress must be followed by a string and a condition enclosed
557     in parentheses, which is handled as a subcondition. */
558
559     else if (Ustrcmp(buffer, "foranyaddress") == 0)
560       {
561       ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
562       if (*error_pointer) break;
563       if (*ptr != '(')
564         {
565         *error_pointer = string_sprintf("\"(\" expected after \"foranyaddress\" "
566           "near line %d of filter file", line_number);
567         break;
568         }
569
570       c->type = cond_foranyaddress;
571       c->left.u = string_copy(buffer);
572
573       ptr = read_condition(nextsigchar(ptr+1, TRUE), &(c->right.c), FALSE);
574       if (*error_pointer) break;
575       if (*ptr != ')')
576         {
577         *error_pointer = string_sprintf("expected \")\" in line %d of "
578           "filter file", line_number);
579         break;
580         }
581       ptr = nextsigchar(ptr+1, TRUE);
582       }
583
584     /* If it's not a word we recognize, then it must be the lefthand
585     operand of one of the comparison words. */
586
587     else
588       {
589       int i;
590       const uschar *isptr = NULL;
591
592       c->left.u = string_copy(buffer);
593       ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
594       if (*error_pointer) break;
595
596       /* Handle "does|is [not]", preserving the pointer after "is" in
597       case it isn't that, but the form "is <string>". */
598
599       if (strcmpic(buffer, US"does") == 0 || strcmpic(buffer, US"is") == 0)
600         {
601         if (buffer[0] == 'i') { c->type = cond_is; isptr = ptr; }
602         if (buffer[0] == 'I') { c->type = cond_IS; isptr = ptr; }
603
604         ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
605         if (*error_pointer) break;
606         if (strcmpic(buffer, US"not") == 0)
607           {
608           c->testfor = !c->testfor;
609           if (isptr) isptr = ptr;
610           ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
611           if (*error_pointer) break;
612           }
613         }
614
615       for (i = 0; i < cond_word_count; i++)
616         {
617         if (Ustrcmp(buffer, cond_words[i]) == 0)
618           {
619           c->type = cond_types[i];
620           break;
621           }
622         }
623
624       /* If an unknown word follows "is" or "is not"
625       it's actually the argument. Reset to read it. */
626
627       if (i >= cond_word_count)
628         {
629         if (!isptr)
630           {
631           *error_pointer = string_sprintf("unrecognized condition word \"%s\" "
632             "near line %d of filter file", buffer, line_number);
633           break;
634           }
635         ptr = isptr;
636         }
637
638       /* Get the RH argument. */
639
640       ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
641       if (*error_pointer) break;
642       c->right.u = string_copy(buffer);
643       }
644     }
645
646   /* We have read some new condition and set it up in the condition block
647   c; point the current pointer at it, and then deal with what follows. */
648
649   *current = c;
650
651   /* Closing bracket terminates if this is a lower-level condition. Otherwise
652   it is unexpected. */
653
654   if (*ptr == ')')
655     {
656     if (toplevel)
657       *error_pointer = string_sprintf("unexpected \")\" in line %d of "
658         "filter file", line_number);
659     break;
660     }
661
662   /* Opening bracket following a condition is an error; give an explicit
663   message to make it clearer what is wrong. */
664
665   else if (*ptr == '(')
666     {
667     *error_pointer = string_sprintf("unexpected \"(\" in line %d of "
668       "filter file", line_number);
669     break;
670     }
671
672   /* Otherwise the next thing must be one of the words "and", "or" or "then" */
673
674   else
675     {
676 //    const uschar *saveptr = ptr;
677     ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
678     if (*error_pointer) break;
679
680     /* "Then" terminates a toplevel condition; otherwise a closing bracket
681     has been omitted. Put a string terminator at the start of "then" so
682     that reflecting the condition can be done when testing. */
683     /*XXX This stops us doing a constification job in this file, unfortunately.
684     Comment it out and see if anything breaks.
685     With one addition down at DEFERFREEZEFAIL it passes the testsuite. */
686
687     if (Ustrcmp(buffer, "then") == 0)
688       {
689 //      if (toplevel) *saveptr = 0;
690 //      else
691       if (!toplevel)
692         *error_pointer = string_sprintf("missing \")\" at end of "
693           "condition near line %d of filter file", line_number);
694       break;
695       }
696
697     /* "And" causes a new condition block to replace the one we have
698     just read, which becomes the left sub-condition. The current pointer
699     is reset to the pointer for the right sub-condition. We have to keep
700     track of the tree of sequential "ands", so as to traverse back up it
701     if an "or" is met. */
702
703     else if (Ustrcmp(buffer, "and") == 0)
704       {
705       condition_block * andc = store_get(sizeof(condition_block), GET_UNTAINTED);
706       andc->parent = current_parent;
707       andc->type = cond_and;
708       andc->testfor = TRUE;
709       andc->left.c = c;
710       andc->right.u = NULL;    /* insurance */
711       *current = andc;
712       current = &(andc->right.c);
713       current_parent = andc;
714       }
715
716     /* "Or" is similar, but has to be done a bit more carefully to
717     ensure that "and" is more binding. If there's a parent set, we
718     are following a sequence of "and"s and must track back to their
719     start. */
720
721     else if (Ustrcmp(buffer, "or") == 0)
722       {
723       condition_block * orc = store_get(sizeof(condition_block), GET_UNTAINTED);
724       condition_block * or_parent = NULL;
725
726       if (current_parent)
727         {
728         while (current_parent->parent &&
729                current_parent->parent->type == cond_and)
730           current_parent = current_parent->parent;
731
732         /* If the parent has a parent, it must be an "or" parent. */
733
734         if (current_parent->parent)
735           or_parent = current_parent->parent;
736         }
737
738       orc->parent = or_parent;
739       if (!or_parent) *cond = orc;
740       else or_parent->right.c = orc;
741       orc->type = cond_or;
742       orc->testfor = TRUE;
743       orc->left.c = (current_parent == NULL)? c : current_parent;
744       orc->right.c = NULL;   /* insurance */
745       current = &(orc->right.c);
746       current_parent = orc;
747       }
748
749     /* Otherwise there is a disaster */
750
751     else
752       {
753       *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
754         "expected near line %d of filter file, but found \"%s\"",
755           toplevel? "then" : ")", line_number, buffer);
756       break;
757       }
758     }
759   }
760
761 return nextsigchar(ptr, TRUE);
762 }
763
764
765
766 /*************************************************
767 *             Output the current indent          *
768 *************************************************/
769
770 static void
771 indent(void)
772 {
773 int i;
774 for (i = 0; i < output_indent; i++) debug_printf(" ");
775 }
776
777
778
779 /*************************************************
780 *          Condition printer: for debugging      *
781 *************************************************/
782
783 /*
784 Arguments:
785   c           the block at the top of the tree
786   toplevel    TRUE at toplevel - stops overall brackets
787
788 Returns:      nothing
789 */
790
791 static void
792 print_condition(condition_block *c, BOOL toplevel)
793 {
794 const char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
795 switch(c->type)
796   {
797   case cond_personal:
798   case cond_delivered:
799   case cond_errormsg:
800   case cond_firsttime:
801   case cond_manualthaw:
802   debug_printf("%s", name);
803   break;
804
805   case cond_is:
806   case cond_IS:
807   case cond_matches:
808   case cond_MATCHES:
809   case cond_contains:
810   case cond_CONTAINS:
811   case cond_begins:
812   case cond_BEGINS:
813   case cond_ends:
814   case cond_ENDS:
815   case cond_above:
816   case cond_below:
817   debug_printf("%s %s %s", c->left.u, name, c->right.u);
818   break;
819
820   case cond_and:
821   if (!c->testfor) debug_printf("not (");
822   print_condition(c->left.c, FALSE);
823   debug_printf(" %s ", cond_names[c->type]);
824   print_condition(c->right.c, FALSE);
825   if (!c->testfor) debug_printf(")");
826   break;
827
828   case cond_or:
829   if (!c->testfor) debug_printf("not (");
830   else if (!toplevel) debug_printf("(");
831   print_condition(c->left.c, FALSE);
832   debug_printf(" %s ", cond_names[c->type]);
833   print_condition(c->right.c, FALSE);
834   if (!toplevel || !c->testfor) debug_printf(")");
835   break;
836
837   case cond_foranyaddress:
838   debug_printf("%s %s (", name, c->left.u);
839   print_condition(c->right.c, FALSE);
840   debug_printf(")");
841   break;
842   }
843 }
844
845
846
847
848 /*************************************************
849 *            Read one filtering command          *
850 *************************************************/
851
852 /*
853 Arguments:
854    pptr        points to pointer to first character of command; the pointer
855                  is updated to point after the last character read
856    lastcmdptr  points to pointer to pointer to last command; used for hanging
857                  on the newly read command
858
859 Returns:       TRUE if command successfully read, else FALSE
860 */
861
862 static BOOL
863 read_command(const uschar **pptr, filter_cmd ***lastcmdptr)
864 {
865 int command, i, cmd_bit;
866 filter_cmd *new, **newlastcmdptr;
867 BOOL yield = TRUE;
868 BOOL was_seen_or_unseen = FALSE;
869 BOOL was_noerror = FALSE;
870 uschar buffer[1024];
871 const uschar *ptr = *pptr;
872 const uschar *saveptr;
873 uschar *fmsg = NULL;
874
875 /* Read the next word and find which command it is. Command words are normally
876 terminated by white space, but there are two exceptions, which are the "if" and
877 "elif" commands. We must allow for them to be terminated by an opening bracket,
878 as brackets are allowed in conditions and users will expect not to require
879 white space here. */
880
881 *buffer = '\0'; /* compiler quietening */
882
883 if (Ustrncmp(ptr, "if(", 3) == 0)
884   {
885   Ustrcpy(buffer, US"if");
886   ptr += 2;
887   }
888 else if (Ustrncmp(ptr, "elif(", 5) == 0)
889   {
890   Ustrcpy(buffer, US"elif");
891   ptr += 4;
892   }
893 else
894   {
895   ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
896   if (*error_pointer) return FALSE;
897   }
898
899 for (command = 0; command < command_list_count; command++)
900   if (Ustrcmp(buffer, command_list[command]) == 0) break;
901
902 /* Handle the individual commands */
903
904 switch (command)
905   {
906   /* Add takes two arguments, separated by the word "to". Headers has two
907   arguments, but the first must be "add", "remove", or "charset", and it gets
908   stored in the second argument slot. Neither may be preceded by seen, unseen
909   or noerror. */
910
911   case add_command:
912   case headers_command:
913   if (seen_force || noerror_force)
914     {
915     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
916       "found before an \"%s\" command near line %d",
917         command_list[command], line_number);
918     yield = FALSE;
919     }
920   /* Fall through */
921
922   /* Logwrite, logfile, pipe, and testprint all take a single argument, save
923   and logfile can have an option second argument for the mode, and deliver can
924   have "errors_to <address>" in a system filter, or in a user filter if the
925   address is the current one. */
926
927   case deliver_command:
928   case logfile_command:
929   case logwrite_command:
930   case pipe_command:
931   case save_command:
932   case testprint_command:
933
934   ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
935   if (!*buffer)
936     *error_pointer = string_sprintf("\"%s\" requires an argument "
937       "near line %d of filter file", command_list[command], line_number);
938
939   if (*error_pointer) yield = FALSE; else
940     {
941     union argtypes argument, second_argument;
942
943     argument.u = second_argument.u = NULL;
944
945     if (command == add_command)
946       {
947       argument.u = string_copy(buffer);
948       ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
949       if (!*buffer || Ustrcmp(buffer, "to") != 0)
950         *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
951           "near line %d of filter file", line_number);
952       else
953         {
954         ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
955         if (!*buffer)
956           *error_pointer = string_sprintf("value missing after \"to\" "
957             "near line %d of filter file", line_number);
958         else second_argument.u = string_copy(buffer);
959         }
960       }
961
962     else if (command == headers_command)
963       {
964       if (Ustrcmp(buffer, "add") == 0)
965         second_argument.b = TRUE;
966       else
967         if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
968       else
969         if (Ustrcmp(buffer, "charset") == 0)
970           second_argument.b = TRUE_UNSET;
971       else
972         {
973         *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
974           "expected after \"headers\" near line %d of filter file",
975             line_number);
976         yield = FALSE;
977         }
978
979       if (!f.system_filtering && second_argument.b != TRUE_UNSET)
980         {
981         *error_pointer = string_sprintf("header addition and removal is "
982           "available only in system filters: near line %d of filter file",
983           line_number);
984         yield = FALSE;
985         break;
986         }
987
988       if (yield)
989         {
990         ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
991         if (!*buffer)
992           *error_pointer = string_sprintf("value missing after \"add\", "
993             "\"remove\", or \"charset\" near line %d of filter file",
994               line_number);
995         else argument.u = string_copy(buffer);
996         }
997       }
998
999     /* The argument for the logwrite command must end in a newline, and the save
1000     and logfile commands can have an optional mode argument. The deliver
1001     command can have an optional "errors_to <address>" for a system filter,
1002     or for a user filter if the address is the user's address. Accept the
1003     syntax here - the check is later. */
1004
1005     else
1006       {
1007       if (command == logwrite_command)
1008         {
1009         int len = Ustrlen(buffer);
1010         if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, US"\n");
1011         }
1012
1013       argument.u = string_copy(buffer);
1014
1015       if (command == save_command || command == logfile_command)
1016         {
1017         if (isdigit(*ptr))
1018           {
1019           ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1020           second_argument.i = (int)Ustrtol(buffer, NULL, 8);
1021           }
1022         else second_argument.i = -1;
1023         }
1024
1025       else if (command == deliver_command)
1026         {
1027         const uschar *save_ptr = ptr;
1028         ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1029         if (Ustrcmp(buffer, "errors_to") == 0)
1030           {
1031           ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1032           second_argument.u = string_copy(buffer);
1033           }
1034         else ptr = save_ptr;
1035         }
1036       }
1037
1038     /* Set up the command block. Seen defaults TRUE for delivery commands,
1039     FALSE for logging commands, and it doesn't matter for testprint, as
1040     that doesn't change the "delivered" status. */
1041
1042     if (*error_pointer) yield = FALSE;
1043     else
1044       {
1045       new = store_get(sizeof(filter_cmd) + sizeof(union argtypes), GET_UNTAINTED);
1046       new->next = NULL;
1047       **lastcmdptr = new;
1048       *lastcmdptr = &(new->next);
1049       new->command = command;
1050       new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1051       new->noerror = noerror_force;
1052       new->args[0] = argument;
1053       new->args[1] = second_argument;
1054       }
1055     }
1056   break;
1057
1058
1059   /* Elif, else and endif just set a flag if expected. */
1060
1061   case elif_command:
1062   case else_command:
1063   case endif_command:
1064   if (seen_force || noerror_force)
1065     {
1066     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1067       "near line %d is not followed by a command", line_number);
1068     yield = FALSE;
1069     }
1070
1071   if (expect_endif > 0)
1072     had_else_endif = (command == elif_command)? had_elif :
1073                      (command == else_command)? had_else : had_endif;
1074   else
1075     {
1076     *error_pointer = string_sprintf("unexpected \"%s\" command near "
1077       "line %d of filter file", buffer, line_number);
1078     yield = FALSE;
1079     }
1080   break;
1081
1082
1083   /* Defer, freeze, and fail are available only if permitted. */
1084
1085   case defer_command:
1086   cmd_bit = RDO_DEFER;
1087   goto DEFER_FREEZE_FAIL;
1088
1089   case fail_command:
1090   cmd_bit = RDO_FAIL;
1091   goto DEFER_FREEZE_FAIL;
1092
1093   case freeze_command:
1094   cmd_bit = RDO_FREEZE;
1095
1096   DEFER_FREEZE_FAIL:
1097   if ((filter_options & cmd_bit) == 0)
1098     {
1099     *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1100       "near line %d of filter file", buffer, line_number);
1101     yield = FALSE;
1102     break;
1103     }
1104
1105   /* A text message can be provided after the "text" keyword, or
1106   as a string in quotes. */
1107
1108   saveptr = ptr;
1109   ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1110   if (*saveptr != '\"' && (!*buffer || Ustrcmp(buffer, "text") != 0))
1111     {
1112     ptr = saveptr;
1113     fmsg = US"";
1114     }
1115   else
1116     {
1117     if (*saveptr != '\"')
1118       ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1119     fmsg = string_copy(buffer);
1120     }
1121
1122   /* Drop through and treat as "finish", but never set "seen". */
1123
1124   seen_value = FALSE;
1125
1126   /* Finish has no arguments; fmsg defaults to NULL */
1127
1128   case finish_command:
1129   new = store_get(sizeof(filter_cmd), GET_UNTAINTED);
1130   new->next = NULL;
1131   **lastcmdptr = new;
1132   *lastcmdptr = &(new->next);
1133   new->command = command;
1134   new->seen = seen_force ? seen_value : FALSE;
1135   new->args[0].u = fmsg;
1136   break;
1137
1138
1139   /* Seen, unseen, and noerror are not allowed before if, which takes a
1140   condition argument and then and else sub-commands. */
1141
1142   case if_command:
1143   if (seen_force || noerror_force)
1144     {
1145     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1146       "found before an \"if\" command near line %d",
1147         line_number);
1148     yield = FALSE;
1149     }
1150
1151   /* Set up the command block for if */
1152
1153   new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes), GET_UNTAINTED);
1154   new->next = NULL;
1155   **lastcmdptr = new;
1156   *lastcmdptr = &new->next;
1157   new->command = command;
1158   new->seen = FALSE;
1159   new->args[0].u = NULL;
1160   new->args[1].u = new->args[2].u = NULL;
1161   new->args[3].u = ptr;
1162
1163   /* Read the condition */
1164
1165   ptr = read_condition(ptr, &new->args[0].c, TRUE);
1166   if (*error_pointer) { yield = FALSE; break; }
1167
1168   /* Read the commands to be obeyed if the condition is true */
1169
1170   newlastcmdptr = &(new->args[1].f);
1171   if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1172
1173   /* If commands were successfully read, handle the various possible
1174   terminators. There may be a number of successive "elif" sections. */
1175
1176   else
1177     {
1178     while (had_else_endif == had_elif)
1179       {
1180       filter_cmd *newnew =
1181         store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes), GET_UNTAINTED);
1182       new->args[2].f = newnew;
1183       new = newnew;
1184       new->next = NULL;
1185       new->command = command;
1186       new->seen = FALSE;
1187       new->args[0].u = NULL;
1188       new->args[1].u = new->args[2].u = NULL;
1189       new->args[3].u = ptr;
1190
1191       ptr = read_condition(ptr, &new->args[0].c, TRUE);
1192       if (*error_pointer) { yield = FALSE; break; }
1193       newlastcmdptr = &(new->args[1].f);
1194       if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1195         yield = FALSE;
1196       }
1197
1198     if (yield == FALSE) break;
1199
1200     /* Handle termination by "else", possibly following one or more
1201     "elsif" sections. */
1202
1203     if (had_else_endif == had_else)
1204       {
1205       newlastcmdptr = &(new->args[2].f);
1206       if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1207         yield = FALSE;
1208       else if (had_else_endif != had_endif)
1209         {
1210         *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1211           "filter file", line_number);
1212         yield = FALSE;
1213         }
1214       }
1215
1216     /* Otherwise the terminator was "endif" - this is checked by
1217     read_command_list(). The pointer is already set to NULL. */
1218     }
1219
1220   /* Reset the terminator flag. */
1221
1222   had_else_endif = had_neither;
1223   break;
1224
1225
1226   /* The mail & vacation commands have a whole slew of keyworded arguments.
1227   The final argument values are the file expand and return message booleans,
1228   whose offsets are defined in mailarg_index_{expand,return}. Although they
1229   are logically booleans, because they are stored in a uschar * value, we use
1230   NULL and not FALSE, to keep 64-bit compilers happy. */
1231
1232   case mail_command:
1233   case vacation_command:
1234   new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes), GET_UNTAINTED);
1235   new->next = NULL;
1236   new->command = command;
1237   new->seen = seen_force ? seen_value : FALSE;
1238   new->noerror = noerror_force;
1239   for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1240
1241   /* Read keyword/value pairs until we hit one that isn't. The data
1242   must contain only printing chars plus tab, though the "text" value
1243   can also contain newlines. The "file" keyword can be preceded by the
1244   word "expand", and "return message" has no data. */
1245
1246   for (;;)
1247     {
1248     const uschar *saveptr = ptr;
1249     ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1250     if (*error_pointer)
1251       { yield = FALSE; break; }
1252
1253     /* Ensure "return" is followed by "message"; that's a complete option */
1254
1255     if (Ustrcmp(buffer, "return") == 0)
1256       {
1257       new->args[mailarg_index_return].u = US"";  /* not NULL => TRUE */
1258       ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1259       if (Ustrcmp(buffer, "message") != 0)
1260         {
1261         *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1262           " near line %d of filter file", line_number);
1263         yield = FALSE;
1264         break;
1265         }
1266       continue;
1267       }
1268
1269     /* Ensure "expand" is followed by "file", then fall through to process the
1270     file keyword. */
1271
1272     if (Ustrcmp(buffer, "expand") == 0)
1273       {
1274       new->args[mailarg_index_expand].u = US"";  /* not NULL => TRUE */
1275       ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1276       if (Ustrcmp(buffer, "file") != 0)
1277         {
1278         *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1279           " near line %d of filter file", line_number);
1280         yield = FALSE;
1281         break;
1282         }
1283       }
1284
1285     /* Scan for the keyword */
1286
1287     for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1288       if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1289
1290     /* Not found keyword; assume end of this command */
1291
1292     if (i >= MAILARGS_STRING_COUNT)
1293       {
1294       ptr = saveptr;
1295       break;
1296       }
1297
1298     /* Found keyword, read the data item */
1299
1300     ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1301     if (*error_pointer)
1302       { yield = FALSE; break; }
1303     else new->args[i].u = string_copy(buffer);
1304     }
1305
1306   /* If this is the vacation command, apply some default settings to
1307   some of the arguments. */
1308
1309   if (command == vacation_command)
1310     {
1311     if (!new->args[mailarg_index_file].u)
1312       {
1313       new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1314       new->args[mailarg_index_expand].u = US"";   /* not NULL => TRUE */
1315       }
1316     if (!new->args[mailarg_index_log].u)
1317       new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1318     if (!new->args[mailarg_index_once].u)
1319       new->args[mailarg_index_once].u = string_copy(US".vacation");
1320     if (!new->args[mailarg_index_once_repeat].u)
1321       new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1322     if (!new->args[mailarg_index_subject].u)
1323       new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1324     }
1325
1326   /* Join the address on to the chain of generated addresses */
1327
1328   **lastcmdptr = new;
1329   *lastcmdptr = &(new->next);
1330   break;
1331
1332
1333   /* Seen and unseen just set flags */
1334
1335   case seen_command:
1336   case unseen_command:
1337   if (!*ptr)
1338     {
1339     *error_pointer = string_sprintf("\"seen\" or \"unseen\" "
1340       "near line %d is not followed by a command", line_number);
1341     yield = FALSE;
1342     }
1343   if (seen_force)
1344     {
1345     *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1346       "near line %d", line_number);
1347     yield = FALSE;
1348     }
1349   seen_value = (command == seen_command);
1350   seen_force = TRUE;
1351   was_seen_or_unseen = TRUE;
1352   break;
1353
1354
1355   /* So does noerror */
1356
1357   case noerror_command:
1358   if (!*ptr)
1359     {
1360     *error_pointer = string_sprintf("\"noerror\" "
1361       "near line %d is not followed by a command", line_number);
1362     yield = FALSE;
1363     }
1364   noerror_force = TRUE;
1365   was_noerror = TRUE;
1366   break;
1367
1368
1369   /* Oops */
1370
1371   default:
1372   *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1373     "near line %d of filter file", buffer, line_number);
1374   yield = FALSE;
1375   break;
1376   }
1377
1378 if (!was_seen_or_unseen && !was_noerror)
1379   {
1380   seen_force = FALSE;
1381   noerror_force = FALSE;
1382   }
1383
1384 *pptr = ptr;
1385 return yield;
1386 }
1387
1388
1389
1390 /*************************************************
1391 *              Read a list of commands           *
1392 *************************************************/
1393
1394 /* If conditional is TRUE, the list must be terminated
1395 by the words "else" or "endif".
1396
1397 Arguments:
1398   pptr        points to pointer to next character; the pointer is updated
1399   lastcmdptr  points to pointer to pointer to previously-read command; used
1400                 for hanging on the new command
1401   conditional TRUE if this command is the subject of a condition
1402
1403 Returns:      TRUE on success
1404 */
1405
1406 static BOOL
1407 read_command_list(const uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1408 {
1409 if (conditional) expect_endif++;
1410 had_else_endif = had_neither;
1411 while (**pptr && had_else_endif == had_neither)
1412   {
1413   if (!read_command(pptr, lastcmdptr)) return FALSE;
1414   *pptr = nextsigchar(*pptr, TRUE);
1415   }
1416 if (conditional)
1417   {
1418   expect_endif--;
1419   if (had_else_endif == had_neither)
1420     {
1421     *error_pointer = US"\"endif\" missing at end of filter file";
1422     return FALSE;
1423     }
1424   }
1425 return TRUE;
1426 }
1427
1428
1429
1430
1431 /*************************************************
1432 *             Test a condition                   *
1433 *************************************************/
1434
1435 /*
1436 Arguments:
1437   c              points to the condition block; c->testfor indicated whether
1438                    it's a positive or negative condition
1439   toplevel       TRUE if called from "if" directly; FALSE otherwise
1440
1441 Returns:         TRUE if the condition is met
1442 */
1443
1444 static BOOL
1445 test_condition(condition_block * c, BOOL toplevel)
1446 {
1447 BOOL yield = FALSE, textonly_re;
1448 const uschar * exp[2], * p, * pp;
1449 int val[2];
1450
1451 if (!c) return TRUE;  /* does this ever occur? */
1452
1453 switch (c->type)
1454   {
1455   case cond_and:
1456     yield = test_condition(c->left.c, FALSE) &&
1457             *error_pointer == NULL &&
1458             test_condition(c->right.c, FALSE);
1459     break;
1460
1461   case cond_or:
1462     yield = test_condition(c->left.c, FALSE) ||
1463             (*error_pointer == NULL &&
1464             test_condition(c->right.c, FALSE));
1465     break;
1466
1467     /* The personal test is meaningless in a system filter. The tests are now in
1468     a separate function (so Sieve can use them). However, an Exim filter does not
1469     scan Cc: (hence the FALSE argument). */
1470
1471   case cond_personal:
1472     yield = f.system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1473     break;
1474
1475   case cond_delivered:
1476     yield = filter_delivered;
1477     break;
1478
1479     /* Only TRUE if a message is actually being processed; FALSE for address
1480     testing and verification. */
1481
1482   case cond_errormsg:
1483     yield = message_id[0] && (!sender_address || !*sender_address);
1484     break;
1485
1486     /* Only FALSE if a message is actually being processed; TRUE for address
1487     and filter testing and verification. */
1488
1489   case cond_firsttime:
1490     yield = filter_test != FTEST_NONE || !message_id[0] || f.deliver_firsttime;
1491     break;
1492
1493     /* Only TRUE if a message is actually being processed; FALSE for address
1494     testing and verification. */
1495
1496   case cond_manualthaw:
1497     yield = message_id[0] && f.deliver_manual_thaw;
1498     break;
1499
1500     /* The foranyaddress condition loops through a list of addresses */
1501
1502   case cond_foranyaddress:
1503     p = c->left.u;
1504     if (!(pp = expand_cstring(p)))
1505       {
1506       *error_pointer = string_sprintf("failed to expand \"%s\" in "
1507         "filter file: %s", p, expand_string_message);
1508       return FALSE;
1509       }
1510
1511     yield = FALSE;
1512     f.parse_allow_group = TRUE;     /* Allow group syntax */
1513
1514     while (*pp)
1515       {
1516       uschar *error;
1517       int start, end, domain;
1518       uschar * s;
1519
1520       p = parse_find_address_end(pp, FALSE);
1521       s = string_copyn(pp, p - pp);
1522
1523       filter_thisaddress =
1524         parse_extract_address(s, &error, &start, &end, &domain, FALSE);
1525
1526       if (filter_thisaddress)
1527         {
1528         if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1529             (debug_selector & D_filter) != 0)
1530           {
1531           indent();
1532           debug_printf_indent("Extracted address %s\n", filter_thisaddress);
1533           }
1534         yield = test_condition(c->right.c, FALSE);
1535         }
1536
1537       if (yield) break;
1538       if (!*p) break;
1539       pp = p + 1;
1540       }
1541
1542     f.parse_allow_group = FALSE;      /* Reset group syntax flags */
1543     f.parse_found_group = FALSE;
1544     break;
1545
1546     /* All other conditions have left and right values that need expanding;
1547     on error, it doesn't matter what value is returned. */
1548
1549     default:
1550     p = c->left.u;
1551     for (int i = 0; i < 2; i++)
1552       {
1553       if (!(exp[i] = expand_string_2(p, &textonly_re)))
1554         {
1555         *error_pointer = string_sprintf("failed to expand \"%s\" in "
1556           "filter file: %s", p, expand_string_message);
1557         return FALSE;
1558         }
1559       p = c->right.u;
1560       }
1561
1562     /* Inner switch for the different cases */
1563
1564     switch(c->type)
1565       {
1566       case cond_is:
1567         yield = strcmpic(exp[0], exp[1]) == 0;
1568         break;
1569
1570       case cond_IS:
1571         yield = Ustrcmp(exp[0], exp[1]) == 0;
1572         break;
1573
1574       case cond_contains:
1575         yield = strstric_c(exp[0], exp[1], FALSE) != NULL;
1576         break;
1577
1578       case cond_CONTAINS:
1579         yield = Ustrstr(exp[0], exp[1]) != NULL;
1580         break;
1581
1582       case cond_begins:
1583         yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1584         break;
1585
1586       case cond_BEGINS:
1587         yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1588         break;
1589
1590       case cond_ends:
1591       case cond_ENDS:
1592         {
1593         int len = Ustrlen(exp[1]);
1594         const uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1595         yield = s < exp[0]
1596           ? FALSE
1597           : (c->type == cond_ends ? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1598         break;
1599         }
1600
1601       case cond_matches:
1602       case cond_MATCHES:
1603         {
1604         const pcre2_code * re;
1605         mcs_flags flags = textonly_re ? MCS_CACHEABLE : MCS_NOFLAGS;
1606
1607         if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1608             (debug_selector & D_filter) != 0)
1609           {
1610           debug_printf_indent("Match expanded arguments:\n");
1611           debug_printf_indent("  Subject = %s\n", exp[0]);
1612           debug_printf_indent("  Pattern = %s\n", exp[1]);
1613           }
1614
1615         if (c->type == cond_matches) flags |= MCS_CASELESS;
1616         if (!(re = regex_compile(exp[1], flags, error_pointer, pcre_gen_cmp_ctx)))
1617           return FALSE;
1618
1619         yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1620         break;
1621         }
1622
1623       /* For above and below, convert the strings to numbers */
1624
1625       case cond_above:
1626       case cond_below:
1627         for (int i = 0; i < 2; i++)
1628           {
1629           val[i] = get_number(exp[i], &yield);
1630           if (!yield)
1631             {
1632             *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1633               exp[i]);
1634             return FALSE;
1635             }
1636           }
1637         yield = c->type == cond_above ? (val[0] > val[1]) : (val[0] < val[1]);
1638         break;
1639       }
1640     break;
1641   }
1642
1643 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1644     (debug_selector & D_filter) != 0)
1645   {
1646   indent();
1647   debug_printf_indent("%sondition is %s: ",
1648     toplevel? "C" : "Sub-c",
1649     (yield == c->testfor)? "true" : "false");
1650   print_condition(c, TRUE);
1651   debug_printf_indent("\n");
1652   }
1653
1654 return yield == c->testfor;
1655 }
1656
1657
1658
1659 /*************************************************
1660 *          Interpret chain of commands           *
1661 *************************************************/
1662
1663 /* In testing state, just say what would be done rather than doing it. The
1664 testprint command just expands and outputs its argument in testing state, and
1665 does nothing otherwise.
1666
1667 Arguments:
1668   commands    points to chain of commands to interpret
1669   generated   where to hang newly-generated addresses
1670
1671 Returns:      FF_DELIVERED     success, a significant action was taken
1672               FF_NOTDELIVERED  success, no significant action
1673               FF_DEFER         defer requested
1674               FF_FAIL          fail requested
1675               FF_FREEZE        freeze requested
1676               FF_ERROR         there was a problem
1677 */
1678
1679 static int
1680 interpret_commands(filter_cmd *commands, address_item **generated)
1681 {
1682 const uschar *s;
1683 int mode;
1684 address_item *addr;
1685 BOOL condition_value;
1686
1687 while (commands)
1688   {
1689   int ff_ret;
1690   uschar *fmsg, *ff_name;
1691   const uschar *expargs[MAILARGS_STRING_COUNT];
1692
1693   int i, n[2];
1694
1695   /* Expand the relevant number of arguments for the command that are
1696   not NULL. */
1697
1698   for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1699     {
1700     const uschar *ss = commands->args[i].u;
1701     if (!ss)
1702       expargs[i] = NULL;
1703     else if (!(expargs[i] = expand_cstring(ss)))
1704       {
1705       *error_pointer = string_sprintf("failed to expand \"%s\" in "
1706         "%s command: %s", ss, command_list[commands->command],
1707         expand_string_message);
1708       return FF_ERROR;
1709       }
1710     }
1711
1712   /* Now switch for each command, setting the "delivered" flag if any of them
1713   have "seen" set. */
1714
1715   if (commands->seen) filter_delivered = TRUE;
1716
1717   switch(commands->command)
1718     {
1719     case add_command:
1720       for (i = 0; i < 2; i++)
1721         {
1722         const uschar *ss = expargs[i];
1723         uschar *end;
1724
1725         if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1726           {
1727           *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1728             "command", expargs[i]);
1729           return FF_ERROR;
1730           }
1731
1732         /* Allow for "--" at the start of the value (from -$n0) for example */
1733         if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1734
1735         n[i] = (int)Ustrtol(ss, &end, 0);
1736         if (*end != 0)
1737           {
1738           *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1739             "command", ss);
1740           return FF_ERROR;
1741           }
1742         }
1743
1744       filter_n[n[1]] += n[0];
1745       if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
1746       break;
1747
1748       /* A deliver command's argument must be a valid address. Its optional
1749       second argument (system filter only) must also be a valid address. */
1750
1751     case deliver_command:
1752       for (i = 0; i < 2; i++)
1753         {
1754         s = expargs[i];
1755         if (s != NULL)
1756           {
1757           int start, end, domain;
1758           uschar *error;
1759           uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1760             FALSE);
1761           if (ss)
1762             expargs[i] = filter_options & RDO_REWRITE
1763               ? rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1764                                 rewrite_existflags)
1765               : rewrite_address_qualify(ss, TRUE);
1766           else
1767             {
1768             *error_pointer = string_sprintf("malformed address \"%s\" in "
1769               "filter file: %s", s, error);
1770             return FF_ERROR;
1771             }
1772           }
1773         }
1774
1775       /* Stick the errors address into a simple variable, as it will
1776       be referenced a few times. Check that the caller is permitted to
1777       specify it. */
1778
1779       s = expargs[1];
1780
1781       if (s != NULL && !f.system_filtering)
1782         {
1783         uschar *ownaddress = expand_string(US"$local_part@$domain");
1784         if (strcmpic(ownaddress, s) != 0)
1785           {
1786           *error_pointer = US"errors_to must point to the caller's address";
1787           return FF_ERROR;
1788           }
1789         }
1790
1791       /* Test case: report what would happen */
1792
1793       if (filter_test != FTEST_NONE)
1794         {
1795         indent();
1796         printf("%seliver message to: %s%s%s%s\n",
1797           (commands->seen)? "D" : "Unseen d",
1798           expargs[0],
1799           commands->noerror? " (noerror)" : "",
1800           (s != NULL)? " errors_to " : "",
1801           (s != NULL)? s : US"");
1802         }
1803
1804       /* Real case. */
1805
1806       else
1807         {
1808         DEBUG(D_filter) debug_printf_indent("Filter: %sdeliver message to: %s%s%s%s\n",
1809           (commands->seen)? "" : "unseen ",
1810           expargs[0],
1811           commands->noerror? " (noerror)" : "",
1812           (s != NULL)? " errors_to " : "",
1813           (s != NULL)? s : US"");
1814
1815         /* Create the new address and add it to the chain, setting the
1816         af_ignore_error flag if necessary, and the errors address, which can be
1817         set in a system filter and to the local address in user filters. */
1818
1819         addr = deliver_make_addr(US expargs[0], TRUE);  /* TRUE => copy s, so deconst ok */
1820         addr->prop.errors_address = !s ? NULL : string_copy(s); /* Default is NULL */
1821         if (commands->noerror) addr->prop.ignore_error = TRUE;
1822         addr->next = *generated;
1823         *generated = addr;
1824         }
1825       break;
1826
1827     case save_command:
1828       s = expargs[0];
1829       mode = commands->args[1].i;
1830
1831       /* Test case: report what would happen */
1832
1833       if (filter_test != FTEST_NONE)
1834         {
1835         indent();
1836         if (mode < 0)
1837           printf("%save message to: %s%s\n", (commands->seen)?
1838             "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1839         else
1840           printf("%save message to: %s %04o%s\n", (commands->seen)?
1841             "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1842         }
1843
1844       /* Real case: Ensure save argument starts with / if there is a home
1845       directory to prepend. */
1846
1847       else
1848         {
1849         if (s[0] != '/' && (filter_options & RDO_PREPEND_HOME) != 0 &&
1850             deliver_home != NULL && deliver_home[0] != 0)
1851           s = string_sprintf("%s/%s", deliver_home, s);
1852         DEBUG(D_filter) debug_printf_indent("Filter: %ssave message to: %s%s\n",
1853           (commands->seen)? "" : "unseen ", s,
1854           commands->noerror? " (noerror)" : "");
1855
1856         /* Create the new address and add it to the chain, setting the
1857         af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1858         mode value. */
1859
1860         addr = deliver_make_addr(US s, TRUE);  /* TRUE => copy s, so deconst ok */
1861         setflag(addr, af_pfr);
1862         setflag(addr, af_file);
1863         if (commands->noerror) addr->prop.ignore_error = TRUE;
1864         addr->mode = mode;
1865         addr->next = *generated;
1866         *generated = addr;
1867         }
1868       break;
1869
1870     case pipe_command:
1871       s = string_copy(commands->args[0].u);
1872       if (filter_test != FTEST_NONE)
1873         {
1874         indent();
1875         printf("%sipe message to: %s%s\n", (commands->seen)?
1876           "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1877         }
1878       else /* Ensure pipe command starts with | */
1879         {
1880         DEBUG(D_filter) debug_printf_indent("Filter: %spipe message to: %s%s\n",
1881           commands->seen ? "" : "unseen ", s,
1882           commands->noerror ? " (noerror)" : "");
1883         if (s[0] != '|') s = string_sprintf("|%s", s);
1884
1885         /* Create the new address and add it to the chain, setting the
1886         af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1887         each command argument is expanded in the transport after the command
1888         has been split up into separate arguments. */
1889
1890         addr = deliver_make_addr(US s, TRUE);  /* TRUE => copy s, so deconst ok */
1891         setflag(addr, af_pfr);
1892         setflag(addr, af_expand_pipe);
1893         if (commands->noerror) addr->prop.ignore_error = TRUE;
1894         addr->next = *generated;
1895         *generated = addr;
1896
1897         /* If there are any numeric variables in existence (e.g. after a regex
1898         condition), or if $thisaddress is set, take a copy for use in the
1899         expansion. Note that we can't pass NULL for filter_thisaddress, because
1900         NULL terminates the list. */
1901
1902         if (expand_nmax >= 0 || filter_thisaddress != NULL)
1903           {
1904           int ecount = expand_nmax >= 0 ? expand_nmax : -1;
1905           uschar ** ss = store_get(sizeof(uschar *) * (ecount + 3), GET_UNTAINTED);
1906
1907           addr->pipe_expandn = ss;
1908           if (!filter_thisaddress) filter_thisaddress = US"";
1909           *ss++ = string_copy(filter_thisaddress);
1910           for (int i = 0; i <= expand_nmax; i++)
1911             *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1912           *ss = NULL;
1913           }
1914         }
1915       break;
1916
1917       /* Set up the file name and mode, and close any previously open
1918       file. */
1919
1920     case logfile_command:
1921       log_mode = commands->args[1].i;
1922       if (log_mode == -1) log_mode = 0600;
1923       if (log_fd >= 0)
1924         {
1925         (void)close(log_fd);
1926         log_fd = -1;
1927         }
1928       log_filename = expargs[0];
1929       if (filter_test != FTEST_NONE)
1930         {
1931         indent();
1932         printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1933         }
1934       break;
1935
1936     case logwrite_command:
1937       s = expargs[0];
1938
1939       if (filter_test != FTEST_NONE)
1940         {
1941         indent();
1942         printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1943           string_printing(s));
1944         }
1945
1946       /* Attempt to write to a log file only if configured as permissible.
1947       Logging may be forcibly skipped for verifying or testing. */
1948
1949       else if ((filter_options & RDO_LOG) != 0)   /* Locked out */
1950         {
1951         DEBUG(D_filter)
1952           debug_printf_indent("filter log command aborted: euid=%ld\n",
1953           (long int)geteuid());
1954         *error_pointer = US"logwrite command forbidden";
1955         return FF_ERROR;
1956         }
1957       else if ((filter_options & RDO_REALLOG) != 0)
1958         {
1959         int len;
1960         DEBUG(D_filter) debug_printf_indent("writing filter log as euid %ld\n",
1961           (long int)geteuid());
1962         if (log_fd < 0)
1963           {
1964           if (!log_filename)
1965             {
1966             *error_pointer = US"attempt to obey \"logwrite\" command "
1967               "without a previous \"logfile\"";
1968             return FF_ERROR;
1969             }
1970           log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1971           if (log_fd < 0)
1972             {
1973             *error_pointer = string_open_failed("filter log file \"%s\"",
1974               log_filename);
1975             return FF_ERROR;
1976             }
1977           }
1978         len = Ustrlen(s);
1979         if (write(log_fd, s, len) != len)
1980           {
1981           *error_pointer = string_sprintf("write error on file \"%s\": %s",
1982             log_filename, strerror(errno));
1983           return FF_ERROR;
1984           }
1985         }
1986       else
1987         DEBUG(D_filter)
1988           debug_printf_indent("skipping logwrite (verifying or testing)\n");
1989       break;
1990
1991       /* Header addition and removal is available only in the system filter. The
1992       command is rejected at parse time otherwise. However "headers charset" is
1993       always permitted. */
1994
1995     case headers_command:
1996         {
1997         int subtype = commands->args[1].i;
1998         s = expargs[0];
1999
2000         if (filter_test != FTEST_NONE)
2001           printf("Headers %s \"%s\"\n",
2002             subtype == TRUE ? "add"
2003             : subtype == FALSE ? "remove"
2004             : "charset",
2005             string_printing(s));
2006
2007         if (subtype == TRUE)
2008           {
2009           while (isspace(*s)) s++;
2010           if (*s)
2011             {
2012             header_add(htype_other, "%s%s", s,
2013               s[Ustrlen(s)-1] == '\n' ? "" : "\n");
2014             header_last->type = header_checkname(header_last, FALSE);
2015             if (header_last->type >= 'a') header_last->type = htype_other;
2016             }
2017           }
2018
2019         else if (subtype == FALSE)
2020           {
2021           int sep = 0;
2022           const uschar * list = s;
2023
2024           for (uschar * ss; ss = string_nextinlist(&list, &sep, NULL, 0); )
2025             header_remove(0, ss);
2026           }
2027
2028         /* This setting lasts only while the filter is running; on exit, the
2029         variable is reset to the previous value. */
2030
2031         else headers_charset = s;
2032         }
2033       break;
2034
2035       /* Defer, freeze, and fail are available only when explicitly permitted.
2036       These commands are rejected at parse time otherwise. The message can get
2037       very long by the inclusion of message headers; truncate if it is, and also
2038       ensure printing characters so as not to mess up log files. */
2039
2040     case defer_command:
2041       ff_name = US"defer";
2042       ff_ret = FF_DEFER;
2043       goto DEFERFREEZEFAIL;
2044
2045     case fail_command:
2046       ff_name = US"fail";
2047       ff_ret = FF_FAIL;
2048       goto DEFERFREEZEFAIL;
2049
2050     case freeze_command:
2051       ff_name = US"freeze";
2052       ff_ret = FF_FREEZE;
2053
2054     DEFERFREEZEFAIL:
2055       *error_pointer = fmsg = US string_printing(Ustrlen(expargs[0]) > 1024
2056         ? string_sprintf("%.1000s ... (truncated)", expargs[0])
2057         : string_copy(expargs[0]));
2058       for(uschar * s = fmsg; *s; s++)
2059         if (!s[1] && *s == '\n') { *s = '\0'; break; }  /* drop trailing newline */
2060
2061       if (filter_test != FTEST_NONE)
2062         {
2063         indent();
2064         printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2065         }
2066       else
2067         DEBUG(D_filter) debug_printf_indent("Filter: %s \"%s\"\n", ff_name, fmsg);
2068       return ff_ret;
2069
2070     case finish_command:
2071       if (filter_test != FTEST_NONE)
2072         {
2073         indent();
2074         printf("%sinish\n", (commands->seen)? "Seen f" : "F");
2075         }
2076       else
2077         DEBUG(D_filter) debug_printf_indent("Filter: %sfinish\n",
2078           commands->seen ? " Seen " : "");
2079       finish_obeyed = TRUE;
2080       return filter_delivered ? FF_DELIVERED : FF_NOTDELIVERED;
2081
2082     case if_command:
2083         {
2084         uschar *save_address = filter_thisaddress;
2085         int ok = FF_DELIVERED;
2086         condition_value = test_condition(commands->args[0].c, TRUE);
2087         if (*error_pointer)
2088           ok = FF_ERROR;
2089         else
2090           {
2091           output_indent += 2;
2092           ok = interpret_commands(commands->args[condition_value? 1:2].f,
2093             generated);
2094           output_indent -= 2;
2095           }
2096         filter_thisaddress = save_address;
2097         if (finish_obeyed  ||  ok != FF_DELIVERED && ok != FF_NOTDELIVERED)
2098           return ok;
2099         }
2100       break;
2101
2102
2103       /* To try to catch runaway loops, do not generate mail if the
2104       return path is unset or if a non-trusted user supplied -f <>
2105       as the return path. */
2106
2107     case mail_command:
2108     case vacation_command:
2109         if (!return_path || !*return_path)
2110           {
2111           if (filter_test != FTEST_NONE)
2112             printf("%s command ignored because return_path is empty\n",
2113               command_list[commands->command]);
2114           else DEBUG(D_filter) debug_printf_indent("%s command ignored because return_path "
2115             "is empty\n", command_list[commands->command]);
2116           break;
2117           }
2118
2119         /* Check the contents of the strings. The type of string can be deduced
2120         from the value of i.
2121
2122         . If i is equal to mailarg_index_text it's a text string for the body,
2123           where anything goes.
2124
2125         . If i is > mailarg_index_text, we are dealing with a file name, which
2126           cannot contain non-printing characters.
2127
2128         . If i is less than mailarg_index_headers we are dealing with something
2129           that will go in a single message header line, where newlines must be
2130           followed by white space.
2131
2132         . If i is equal to mailarg_index_headers, we have a string that contains
2133           one or more headers. Newlines that are not followed by white space must
2134           be followed by a header name.
2135         */
2136
2137         for (i = 0; i < MAILARGS_STRING_COUNT; i++)
2138           {
2139           const uschar *s = expargs[i];
2140
2141           if (!s) continue;
2142
2143           if (i != mailarg_index_text) for (const uschar * p = s; *p; p++)
2144             {
2145             int c = *p;
2146             if (i > mailarg_index_text)
2147               {
2148               if (!mac_isprint(c))
2149                 {
2150                 *error_pointer = string_sprintf("non-printing character in \"%s\" "
2151                   "in %s command", string_printing(s),
2152                   command_list[commands->command]);
2153                 return FF_ERROR;
2154                 }
2155               }
2156
2157             /* i < mailarg_index_text */
2158
2159             else if (c == '\n' && !isspace(p[1]))
2160               {
2161               if (i < mailarg_index_headers)
2162                 {
2163                 *error_pointer = string_sprintf("\\n not followed by space in "
2164                   "\"%.1024s\" in %s command", string_printing(s),
2165                   command_list[commands->command]);
2166                 return FF_ERROR;
2167                 }
2168
2169               /* Check for the start of a new header line within the string */
2170
2171               else
2172                 {
2173                 const uschar *pp;
2174                 for (pp = p + 1;; pp++)
2175                   {
2176                   c = *pp;
2177                   if (c == ':' && pp != p + 1) break;
2178                   if (!c || c == ':' || isspace(c))
2179                     {
2180                     *error_pointer = string_sprintf("\\n not followed by space or "
2181                       "valid header name in \"%.1024s\" in %s command",
2182                       string_printing(s), command_list[commands->command]);
2183                     return FF_ERROR;
2184                     }
2185                   }
2186                 p = pp;
2187                 }
2188               }
2189             }       /* Loop to scan the string */
2190
2191           /* The string is OK */
2192
2193           commands->args[i].u = s;
2194           }
2195
2196         /* Proceed with mail or vacation command */
2197
2198         if (filter_test != FTEST_NONE)
2199           {
2200           const uschar *to = commands->args[mailarg_index_to].u;
2201           indent();
2202           printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2203             to ? to : US"<default>",
2204             commands->command == vacation_command ? " (vacation)" : "",
2205             commands->noerror ? " (noerror)" : "");
2206           for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2207             {
2208             const uschar *arg = commands->args[i].u;
2209             if (arg)
2210               {
2211               int len = Ustrlen(mailargs[i]);
2212               int indent = (debug_selector != 0)? output_indent : 0;
2213               while (len++ < 7 + indent) printf(" ");
2214               printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2215                 (commands->args[mailarg_index_expand].u != NULL &&
2216                   Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2217               }
2218             }
2219           if (commands->args[mailarg_index_return].u)
2220             printf("Return original message\n");
2221           }
2222         else
2223           {
2224           const uschar *tt;
2225           const uschar *to = commands->args[mailarg_index_to].u;
2226           gstring * log_addr = NULL;
2227
2228           if (!to) to = expand_string(US"$reply_address");
2229           while (isspace(*to)) to++;
2230
2231           for (tt = to; *tt; tt++)     /* Get rid of newlines */
2232             if (*tt == '\n')
2233               {
2234               uschar * s = string_copy(to);
2235               for (uschar * ss = s; *ss; ss++)
2236                 if (*ss == '\n') *ss = ' ';
2237               to = s;
2238               break;
2239               }
2240
2241           DEBUG(D_filter)
2242             {
2243             debug_printf_indent("Filter: %smail to: %s%s%s\n",
2244               commands->seen ? "seen " : "",
2245               to,
2246               commands->command == vacation_command ? " (vacation)" : "",
2247               commands->noerror ? " (noerror)" : "");
2248             for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2249               {
2250               const uschar *arg = commands->args[i].u;
2251               if (arg)
2252                 {
2253                 int len = Ustrlen(mailargs[i]);
2254                 while (len++ < 15) debug_printf_indent(" ");
2255                 debug_printf_indent("%s: %s%s\n", mailargs[i], string_printing(arg),
2256                   (commands->args[mailarg_index_expand].u != NULL &&
2257                     Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2258                 }
2259               }
2260             }
2261
2262           /* Create the "address" for the autoreply. This is used only for logging,
2263           as the actual recipients are extracted from the To: line by -t. We use the
2264           same logic here to extract the working addresses (there may be more than
2265           one). Just in case there are a vast number of addresses, stop when the
2266           string gets too long. */
2267
2268           tt = to;
2269           while (*tt)
2270             {
2271             uschar *ss = parse_find_address_end(tt, FALSE);
2272             uschar *recipient, *errmess;
2273             int start, end, domain;
2274             int temp = *ss;
2275
2276             *ss = 0;
2277             recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
2278               FALSE);
2279             *ss = temp;
2280
2281             /* Ignore empty addresses and errors; an error will occur later if
2282             there's something really bad. */
2283
2284             if (recipient)
2285               {
2286               log_addr = string_catn(log_addr, log_addr ? US"," : US">", 1);
2287               log_addr = string_cat (log_addr, recipient);
2288               }
2289
2290             /* Check size */
2291
2292             if (log_addr && log_addr->ptr > 256)
2293               {
2294               log_addr = string_catn(log_addr, US", ...", 5);
2295               break;
2296               }
2297
2298             /* Move on past this address */
2299
2300             tt = ss + (*ss ? 1 : 0);
2301             while (isspace(*tt)) tt++;
2302             }
2303
2304           if (log_addr)
2305             addr = deliver_make_addr(string_from_gstring(log_addr), FALSE);
2306           else
2307             {
2308             addr = deliver_make_addr(US ">**bad-reply**", FALSE);
2309             setflag(addr, af_bad_reply);
2310             }
2311
2312           setflag(addr, af_pfr);
2313           if (commands->noerror) addr->prop.ignore_error = TRUE;
2314           addr->next = *generated;
2315           *generated = addr;
2316
2317           addr->reply = store_get(sizeof(reply_item), GET_UNTAINTED);
2318           addr->reply->from = NULL;
2319           addr->reply->to = string_copy(to);
2320           addr->reply->file_expand =
2321             commands->args[mailarg_index_expand].u != NULL;
2322           addr->reply->expand_forbid = expand_forbid;
2323           addr->reply->return_message =
2324             commands->args[mailarg_index_return].u != NULL;
2325           addr->reply->once_repeat = 0;
2326
2327           if (commands->args[mailarg_index_once_repeat].u != NULL)
2328             {
2329             addr->reply->once_repeat =
2330               readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2331                 FALSE);
2332             if (addr->reply->once_repeat < 0)
2333               {
2334               *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2335                 "in mail or vacation command: %s",
2336                 commands->args[mailarg_index_once_repeat].u);
2337               return FF_ERROR;
2338               }
2339             }
2340
2341           /* Set up all the remaining string arguments (those other than "to") */
2342
2343           for (i = 1; i < mailargs_string_passed; i++)
2344             {
2345             const uschar *ss = commands->args[i].u;
2346             *(USS((US addr->reply) + reply_offsets[i])) =
2347               ss ? string_copy(ss) : NULL;
2348             }
2349           }
2350         break;
2351
2352     case testprint_command:
2353         if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2354           {
2355           const uschar *s = string_printing(expargs[0]);
2356           if (filter_test == FTEST_NONE)
2357             debug_printf_indent("Filter: testprint: %s\n", s);
2358           else
2359             printf("Testprint: %s\n", s);
2360           }
2361     }
2362
2363   commands = commands->next;
2364   }
2365
2366 return filter_delivered ? FF_DELIVERED : FF_NOTDELIVERED;
2367 }
2368
2369
2370
2371 /*************************************************
2372 *        Test for a personal message             *
2373 *************************************************/
2374
2375 /* This function is global so that it can also be called from the code that
2376 implements Sieve filters.
2377
2378 Arguments:
2379   aliases    a chain of aliases
2380   scan_cc    TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2381
2382 Returns:     TRUE if the message is deemed to be personal
2383 */
2384
2385 BOOL
2386 filter_personal(string_item *aliases, BOOL scan_cc)
2387 {
2388 const uschar *self, *self_from, *self_to;
2389 uschar *psself = NULL;
2390 const uschar *psself_from = NULL, *psself_to = NULL;
2391 rmark reset_point = store_mark();
2392 BOOL yield;
2393 header_line *h;
2394 int to_count = 2;
2395 int from_count = 9;
2396
2397 /* If any header line in the message is a defined "List-" header field, it is
2398 not a personal message. We used to check for any header line that started with
2399 "List-", but this was tightened up for release 4.54. The check is now for
2400 "List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
2401 Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
2402 defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
2403 contain any value other than "no", the message is not personal (RFC 3834).
2404 Previously the test was for "auto-". */
2405
2406 for (h = header_list; h; h = h->next)
2407   {
2408   if (h->type == htype_old) continue;
2409
2410   if (strncmpic(h->text, US"List-", 5) == 0)
2411     {
2412     uschar * s = h->text + 5;
2413     if (strncmpic(s, US"Id:", 3) == 0 ||
2414         strncmpic(s, US"Help:", 5) == 0 ||
2415         strncmpic(s, US"Subscribe:", 10) == 0 ||
2416         strncmpic(s, US"Unsubscribe:", 12) == 0 ||
2417         strncmpic(s, US"Post:", 5) == 0 ||
2418         strncmpic(s, US"Owner:", 6) == 0 ||
2419         strncmpic(s, US"Archive:", 8) == 0)
2420       return FALSE;
2421     }
2422
2423   else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
2424     {
2425     uschar * s = h->text + 15;
2426     Uskip_whitespace(&s);
2427     if (strncmpic(s, US"no", 2) != 0) return FALSE;
2428     s += 2;
2429     Uskip_whitespace(&s);
2430     if (*s) return FALSE;
2431     }
2432   }
2433
2434 /* Set up "my" address */
2435
2436 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2437 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2438   global_rewrite_rules);
2439 self_to   = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2440   global_rewrite_rules);
2441
2442
2443 if (!self_from) self_from = self;
2444 if (self_to) self_to = self;
2445
2446 /* If there's a prefix or suffix set, we must include the prefixed/
2447 suffixed version of the local part in the tests. */
2448
2449 if (deliver_localpart_prefix || deliver_localpart_suffix)
2450   {
2451   psself = string_sprintf("%s%s%s@%s",
2452     deliver_localpart_prefix ? deliver_localpart_prefix : US"",
2453     deliver_localpart,
2454     deliver_localpart_suffix ? deliver_localpart_suffix : US"",
2455     deliver_domain);
2456   psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2457     global_rewrite_rules);
2458   psself_to   = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2459     global_rewrite_rules);
2460   if (psself_from == NULL) psself_from = psself;
2461   if (psself_to == NULL) psself_to = psself;
2462   to_count += 2;
2463   from_count += 2;
2464   }
2465
2466 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2467
2468 yield =
2469   (
2470   header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2471                psself_to) ||
2472     (scan_cc &&
2473        (
2474        header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2475                              psself, psself_to)
2476        ||
2477        header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2478                               psself, psself_to)
2479        )
2480     )
2481   ) &&
2482
2483   header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2484     "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2485     "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2486
2487   header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2488
2489   (sender_address == NULL || sender_address[0] != 0);
2490
2491 store_reset(reset_point);
2492 return yield;
2493 }
2494
2495
2496
2497 /*************************************************
2498 *            Interpret a mail filter file        *
2499 *************************************************/
2500
2501 /*
2502 Arguments:
2503   filter      points to the entire file, read into store as a single string
2504   options     controls whether various special things are allowed, and requests
2505               special actions
2506   generated   where to hang newly-generated addresses
2507   error       where to pass back an error text
2508
2509 Returns:      FF_DELIVERED     success, a significant action was taken
2510               FF_NOTDELIVERED  success, no significant action
2511               FF_DEFER         defer requested
2512               FF_FAIL          fail requested
2513               FF_FREEZE        freeze requested
2514               FF_ERROR         there was a problem
2515 */
2516
2517 int
2518 filter_interpret(const uschar *filter, int options, address_item **generated,
2519   uschar **error)
2520 {
2521 int i;
2522 int yield = FF_ERROR;
2523 const uschar *ptr = filter;
2524 const uschar *save_headers_charset = headers_charset;
2525 filter_cmd *commands = NULL;
2526 filter_cmd **lastcmdptr = &commands;
2527
2528 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2529 acl_level++;
2530
2531 /* Initialize "not in an if command", set the global flag that is always TRUE
2532 while filtering, and zero the variables. */
2533
2534 expect_endif = 0;
2535 output_indent = 0;
2536 f.filter_running = TRUE;
2537 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2538
2539 /* To save having to pass certain values about all the time, make them static.
2540 Also initialize the line number, for error messages, and the log file
2541 variables. */
2542
2543 filter_options = options;
2544 filter_delivered = FALSE;
2545 finish_obeyed = FALSE;
2546 error_pointer = error;
2547 *error_pointer = NULL;
2548 line_number = 1;
2549 log_fd = -1;
2550 log_mode = 0600;
2551 log_filename = NULL;
2552
2553 /* Scan filter file for syntax and build up an interpretation thereof, and
2554 interpret the compiled commands, and if testing, say whether we ended up
2555 delivered or not, unless something went wrong. */
2556
2557 seen_force = FALSE;
2558 ptr = nextsigchar(ptr, TRUE);
2559
2560 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2561   yield = interpret_commands(commands, generated);
2562
2563 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2564   {
2565   uschar *s = US"";
2566   switch(yield)
2567     {
2568     case FF_DEFER:
2569       s = US"Filtering ended by \"defer\".";
2570       break;
2571
2572     case FF_FREEZE:
2573       s = US"Filtering ended by \"freeze\".";
2574       break;
2575
2576     case FF_FAIL:
2577       s = US"Filtering ended by \"fail\".";
2578       break;
2579
2580     case FF_DELIVERED:
2581       s = US"Filtering set up at least one significant delivery "
2582              "or other action.\n"
2583              "No other deliveries will occur.";
2584       break;
2585
2586     case FF_NOTDELIVERED:
2587       s = US"Filtering did not set up a significant delivery.\n"
2588              "Normal delivery will occur.";
2589       break;
2590
2591     case FF_ERROR:
2592       s = string_sprintf("Filter error: %s", *error);
2593       break;
2594     }
2595
2596   if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2597     else debug_printf_indent("%s\n", s);
2598   }
2599
2600 /* Close the log file if it was opened, and kill off any numerical variables
2601 before returning. Reset the header decoding charset. */
2602
2603 if (log_fd >= 0) (void)close(log_fd);
2604 expand_nmax = -1;
2605 f.filter_running = FALSE;
2606 headers_charset = save_headers_charset;
2607
2608 acl_level--;
2609 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2610 return yield;
2611 }
2612
2613
2614 /* End of filter.c */