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