1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2015 */
6 /* See the file NOTICE for conditions of use and distribution. */
9 /* Code for mail filtering functions. */
14 /* Command arguments and left/right points in conditions can contain different
15 types of data, depending on the particular command or condition. Originally,
16 (void *) was used as "any old type", with casts, but this gives trouble and
17 warnings in some environments. So now it is done "properly", with a union. We
18 need to declare the structures first because some of them are recursive. */
21 struct condition_block;
24 struct string_item *a;
26 struct condition_block *c;
32 /* Local structures used in this module */
34 typedef struct filter_cmd {
35 struct filter_cmd *next;
39 union argtypes args[1];
42 typedef struct condition_block {
43 struct condition_block *parent;
50 /* Miscellaneous other declarations */
52 static uschar **error_pointer;
53 static uschar *log_filename;
54 static int filter_options;
55 static int line_number;
56 static int expect_endif;
57 static int had_else_endif;
60 static int output_indent;
61 static BOOL filter_delivered;
62 static BOOL finish_obeyed;
63 static BOOL seen_force;
64 static BOOL seen_value;
65 static BOOL noerror_force;
67 enum { had_neither, had_else, had_elif, had_endif };
69 static BOOL read_command_list(uschar **, filter_cmd ***, BOOL);
72 /* The string arguments for the mail command. The header line ones (that are
73 permitted to include \n followed by white space) first, and then the body text
74 one (it can have \n anywhere). Then the file names and once_repeat, which may
77 static const char *mailargs[] = { /* "to" must be first, and */
78 "to", /* "cc" and "bcc" must follow */
84 "extra_headers", /* miscellaneous added header lines */
92 /* The count of string arguments */
94 #define MAILARGS_STRING_COUNT (sizeof(mailargs)/sizeof(uschar *))
96 /* The count of string arguments that are actually passed over as strings
97 (once_repeat is converted to an int). */
99 #define mailargs_string_passed (MAILARGS_STRING_COUNT - 1)
101 /* This defines the offsets for the arguments; first the string ones, and
102 then the non-string ones. The order must be as above. */
104 enum { mailarg_index_to,
108 mailarg_index_reply_to,
109 mailarg_index_subject,
110 mailarg_index_headers, /* misc headers must be last */
111 mailarg_index_text, /* text is first after headers */
112 mailarg_index_file, /* between text and expand are filenames */
115 mailarg_index_once_repeat, /* a time string */
116 mailarg_index_expand, /* first non-string argument */
117 mailarg_index_return,
118 mailargs_total /* total number of arguments */
121 /* Offsets in the data structure for the string arguments (note that
122 once_repeat isn't a string argument at this point.) */
124 static int reply_offsets[] = { /* must be in same order as above */
125 offsetof(reply_item, to),
126 offsetof(reply_item, cc),
127 offsetof(reply_item, bcc),
128 offsetof(reply_item, from),
129 offsetof(reply_item, reply_to),
130 offsetof(reply_item, subject),
131 offsetof(reply_item, headers),
132 offsetof(reply_item, text),
133 offsetof(reply_item, file),
134 offsetof(reply_item, logfile),
135 offsetof(reply_item, oncelog),
138 /* Condition identities and names, with negated versions for some
141 enum { cond_and, cond_or, cond_personal, cond_begins, cond_BEGINS,
142 cond_ends, cond_ENDS, cond_is, cond_IS, cond_matches,
143 cond_MATCHES, cond_contains, cond_CONTAINS, cond_delivered,
144 cond_above, cond_below, cond_errormsg, cond_firsttime,
145 cond_manualthaw, cond_foranyaddress };
147 static const char *cond_names[] = {
148 "and", "or", "personal",
149 "begins", "BEGINS", "ends", "ENDS",
150 "is", "IS", "matches", "MATCHES", "contains",
151 "CONTAINS", "delivered", "above", "below", "error_message",
152 "first_delivery", "manually_thawed", "foranyaddress" };
154 static const char *cond_not_names[] = {
155 "", "", "not personal",
156 "does not begin", "does not BEGIN",
157 "does not end", "does not END",
158 "is not", "IS not", "does not match",
159 "does not MATCH", "does not contain", "does not CONTAIN",
160 "not delivered", "not above", "not below", "not error_message",
161 "not first_delivery", "not manually_thawed", "not foranyaddress" };
163 /* Tables of binary condition words and their corresponding types. Not easy
164 to amalgamate with the above because of the different variants. */
166 static const char *cond_words[] = {
188 static int cond_word_count = (sizeof(cond_words)/sizeof(uschar *));
190 static int cond_types[] = { cond_BEGINS, cond_BEGINS, cond_CONTAINS,
191 cond_CONTAINS, cond_ENDS, cond_ENDS, cond_IS, cond_MATCHES, cond_MATCHES,
192 cond_above, cond_begins, cond_begins, cond_below, cond_contains,
193 cond_contains, cond_ends, cond_ends, cond_is, cond_matches, cond_matches };
195 /* Command identities: must be kept in step with the list of command words
196 and the list of expanded argument counts which follow. */
198 enum { add_command, defer_command, deliver_command, elif_command, else_command,
199 endif_command, finish_command, fail_command, freeze_command,
200 headers_command, if_command, logfile_command, logwrite_command,
201 mail_command, noerror_command, pipe_command, save_command, seen_command,
202 testprint_command, unseen_command, vacation_command };
204 static const char *command_list[] = {
205 "add", "defer", "deliver", "elif", "else", "endif", "finish",
206 "fail", "freeze", "headers", "if", "logfile", "logwrite", "mail",
207 "noerror", "pipe", "save", "seen", "testprint", "unseen", "vacation"
210 static int command_list_count = sizeof(command_list)/sizeof(uschar *);
212 /* This table contains the number of expanded arguments in the bottom 4 bits.
213 If the top bit is set, it means that the default for the command is "seen". */
215 static uschar command_exparg_count[] = {
229 MAILARGS_STRING_COUNT, /* mail */
236 MAILARGS_STRING_COUNT /* vacation */
241 /*************************************************
242 * Find next significant uschar *
243 *************************************************/
245 /* Function to skip over white space and, optionally, comments.
248 ptr pointer to next character
249 comment_allowed if TRUE, comments (# to \n) are skipped
251 Returns: pointer to next non-whitespace character
255 nextsigchar(uschar *ptr, BOOL comment_allowed)
259 while (isspace(*ptr))
261 if (*ptr == '\n') line_number++;
264 if (comment_allowed && *ptr == '#')
266 while (*(++ptr) != '\n' && *ptr != 0);
276 /*************************************************
278 *************************************************/
280 /* The terminator is white space unless bracket is TRUE, in which
281 case ( and ) terminate.
284 ptr pointer to next character
285 buffer where to put the word
287 bracket if TRUE, terminate on ( and ) as well as space
289 Returns: pointer to the next significant character after the word
293 nextword(uschar *ptr, uschar *buffer, int size, BOOL bracket)
296 while (*ptr != 0 && !isspace(*ptr) &&
297 (!bracket || (*ptr != '(' && *ptr != ')')))
299 if (bp - buffer < size - 1) *bp++ = *ptr++; else
301 *error_pointer = string_sprintf("word is too long in line %d of "
302 "filter file (max = %d chars)", line_number, size);
307 return nextsigchar(ptr, TRUE);
312 /*************************************************
314 *************************************************/
316 /* Might be a word, or might be a quoted string; in the latter case
320 ptr pointer to next character
321 buffer where to put the item
323 bracket if TRUE, terminate non-quoted on ( and ) as well as space
325 Returns: the next significant character after the item
329 nextitem(uschar *ptr, uschar *buffer, int size, BOOL bracket)
332 if (*ptr != '\"') return nextword(ptr, buffer, size, bracket);
334 while (*(++ptr) != 0 && *ptr != '\"' && *ptr != '\n')
336 if (bp - buffer >= size - 1)
338 *error_pointer = string_sprintf("string is too long in line %d of "
339 "filter file (max = %d chars)", line_number, size);
343 if (*ptr != '\\') *bp++ = *ptr; else
345 if (isspace(ptr[1])) /* \<whitespace>NL<whitespace> ignored */
348 while (*p != '\n' && isspace(*p)) p++;
353 while (ptr[1] != '\n' && isspace(ptr[1])) ptr++;
358 *bp++ = string_interpret_escape(CUSS &ptr);
362 if (*ptr == '\"') ptr++;
363 else if (*error_pointer == NULL)
364 *error_pointer = string_sprintf("quote missing at end of string "
365 "in line %d", line_number);
368 return nextsigchar(ptr, TRUE);
374 /*************************************************
375 * Convert a string + K|M to a number *
376 *************************************************/
380 s points to text string
381 OK set TRUE if a valid number was read
383 Returns: the number, or 0 on error (with *OK FALSE)
387 get_number(uschar *s, BOOL *ok)
391 if (sscanf(CS s, "%i%n", &value, &count) != 1) return 0;
392 if (tolower(s[count]) == 'k') { value *= 1024; count++; }
393 if (tolower(s[count]) == 'm') { value *= 1024*1024; count++; }
394 while (isspace((s[count]))) count++;
395 if (s[count] != 0) return 0;
402 /*************************************************
403 * Read one condition *
404 *************************************************/
406 /* A complete condition must be terminated by "then"; bracketed internal
407 conditions must be terminated by a closing bracket. They are read by calling
408 this function recursively.
411 ptr points to start of condition
412 condition_block where to hang the created condition block
413 toplevel TRUE when called at the top level
415 Returns: points to next character after "then"
419 read_condition(uschar *ptr, condition_block **cond, BOOL toplevel)
423 condition_block *current_parent = NULL;
424 condition_block **current = cond;
428 /* Loop to read next condition */
434 /* reaching the end of the input is an error. */
438 *error_pointer = string_sprintf("\"then\" missing at end of filter file");
442 /* Opening bracket at the start of a condition introduces a nested
443 condition, which must be terminated by a closing bracket. */
447 ptr = read_condition(nextsigchar(ptr+1, TRUE), &c, FALSE);
448 if (*error_pointer != NULL) break;
451 *error_pointer = string_sprintf("expected \")\" in line %d of "
452 "filter file", line_number);
457 c->testfor = !c->testfor;
460 ptr = nextsigchar(ptr+1, TRUE);
464 /* Closing bracket at the start of a condition is an error. Give an
465 explicit message, as otherwise "unknown condition" would be confusing. */
467 else if (*ptr == ')')
469 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
470 "filter file", line_number);
474 /* Otherwise we expect a word or a string. */
478 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
479 if (*error_pointer != NULL) break;
481 /* "Then" at the start of a condition is an error */
483 if (Ustrcmp(buffer, "then") == 0)
485 *error_pointer = string_sprintf("unexpected \"then\" near line %d of "
486 "filter file", line_number);
490 /* "Not" at the start of a condition negates the testing condition. */
492 if (Ustrcmp(buffer, "not") == 0)
498 /* Build a condition block from the specific word. */
500 c = store_get(sizeof(condition_block));
501 c->left.u = c->right.u = NULL;
502 c->testfor = testfor;
505 /* Check for conditions that start with a keyword */
507 if (Ustrcmp(buffer, "delivered") == 0) c->type = cond_delivered;
508 else if (Ustrcmp(buffer, "error_message") == 0) c->type = cond_errormsg;
509 else if (Ustrcmp(buffer, "first_delivery") == 0) c->type = cond_firsttime;
510 else if (Ustrcmp(buffer, "manually_thawed") == 0) c->type = cond_manualthaw;
512 /* Personal can be followed by any number of aliases */
514 else if (Ustrcmp(buffer, "personal") == 0)
516 c->type = cond_personal;
520 uschar *saveptr = ptr;
521 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
522 if (*error_pointer) break;
523 if (Ustrcmp(buffer, "alias") != 0)
528 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
529 if (*error_pointer) break;
530 aa = store_get(sizeof(string_item));
531 aa->text = string_copy(buffer);
532 aa->next = c->left.a;
537 /* Foranyaddress must be followed by a string and a condition enclosed
538 in parentheses, which is handled as a subcondition. */
540 else if (Ustrcmp(buffer, "foranyaddress") == 0)
542 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
543 if (*error_pointer) break;
546 *error_pointer = string_sprintf("\"(\" expected after \"foranyaddress\" "
547 "near line %d of filter file", line_number);
551 c->type = cond_foranyaddress;
552 c->left.u = string_copy(buffer);
554 ptr = read_condition(nextsigchar(ptr+1, TRUE), &(c->right.c), FALSE);
555 if (*error_pointer) break;
558 *error_pointer = string_sprintf("expected \")\" in line %d of "
559 "filter file", line_number);
562 ptr = nextsigchar(ptr+1, TRUE);
565 /* If it's not a word we recognize, then it must be the lefthand
566 operand of one of the comparison words. */
571 uschar *isptr = NULL;
573 c->left.u = string_copy(buffer);
574 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
575 if (*error_pointer) break;
577 /* Handle "does|is [not]", preserving the pointer after "is" in
578 case it isn't that, but the form "is <string>". */
580 if (strcmpic(buffer, US"does") == 0 || strcmpic(buffer, US"is") == 0)
582 if (buffer[0] == 'i') { c->type = cond_is; isptr = ptr; }
583 if (buffer[0] == 'I') { c->type = cond_IS; isptr = ptr; }
585 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
586 if (*error_pointer) break;
587 if (strcmpic(buffer, US"not") == 0)
589 c->testfor = !c->testfor;
590 if (isptr) isptr = ptr;
591 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
592 if (*error_pointer) break;
596 for (i = 0; i < cond_word_count; i++)
598 if (Ustrcmp(buffer, cond_words[i]) == 0)
600 c->type = cond_types[i];
605 /* If an unknown word follows "is" or "is not"
606 it's actually the argument. Reset to read it. */
608 if (i >= cond_word_count)
612 *error_pointer = string_sprintf("unrecognized condition word \"%s\" "
613 "near line %d of filter file", buffer, line_number);
619 /* Get the RH argument. */
621 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
622 if (*error_pointer) break;
623 c->right.u = string_copy(buffer);
627 /* We have read some new condition and set it up in the condition block
628 c; point the current pointer at it, and then deal with what follows. */
632 /* Closing bracket terminates if this is a lower-level condition. Otherwise
638 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
639 "filter file", line_number);
643 /* Opening bracket following a condition is an error; give an explicit
644 message to make it clearer what is wrong. */
646 else if (*ptr == '(')
648 *error_pointer = string_sprintf("unexpected \"(\" in line %d of "
649 "filter file", line_number);
653 /* Otherwise the next thing must be one of the words "and", "or" or "then" */
657 uschar *saveptr = ptr;
658 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
659 if (*error_pointer) break;
661 /* "Then" terminates a toplevel condition; otherwise a closing bracket
662 has been omitted. Put a string terminator at the start of "then" so
663 that reflecting the condition can be done when testing. */
665 if (Ustrcmp(buffer, "then") == 0)
667 if (toplevel) *saveptr = 0;
668 else *error_pointer = string_sprintf("missing \")\" at end of "
669 "condition near line %d of filter file", line_number);
673 /* "And" causes a new condition block to replace the one we have
674 just read, which becomes the left sub-condition. The current pointer
675 is reset to the pointer for the right sub-condition. We have to keep
676 track of the tree of sequential "ands", so as to traverse back up it
677 if an "or" is met. */
679 else if (Ustrcmp(buffer, "and") == 0)
681 condition_block *andc = store_get(sizeof(condition_block));
682 andc->parent = current_parent;
683 andc->type = cond_and;
684 andc->testfor = TRUE;
686 andc->right.u = NULL; /* insurance */
688 current = &(andc->right.c);
689 current_parent = andc;
692 /* "Or" is similar, but has to be done a bit more carefully to
693 ensure that "and" is more binding. If there's a parent set, we
694 are following a sequence of "and"s and must track back to their
697 else if (Ustrcmp(buffer, "or") == 0)
699 condition_block *orc = store_get(sizeof(condition_block));
700 condition_block *or_parent = NULL;
704 while (current_parent->parent &&
705 current_parent->parent->type == cond_and)
706 current_parent = current_parent->parent;
708 /* If the parent has a parent, it must be an "or" parent. */
710 if (current_parent->parent)
711 or_parent = current_parent->parent;
714 orc->parent = or_parent;
715 if (!or_parent) *cond = orc;
716 else or_parent->right.c = orc;
719 orc->left.c = (current_parent == NULL)? c : current_parent;
720 orc->right.c = NULL; /* insurance */
721 current = &(orc->right.c);
722 current_parent = orc;
725 /* Otherwise there is a disaster */
729 *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
730 "expected near line %d of filter file, but found \"%s\"",
731 toplevel? "then" : ")", line_number, buffer);
737 return nextsigchar(ptr, TRUE);
742 /*************************************************
743 * Ouput the current indent *
744 *************************************************/
750 for (i = 0; i < output_indent; i++) debug_printf(" ");
755 /*************************************************
756 * Condition printer: for debugging *
757 *************************************************/
761 c the block at the top of the tree
762 toplevel TRUE at toplevel - stops overall brackets
768 print_condition(condition_block *c, BOOL toplevel)
770 const char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
777 case cond_manualthaw:
778 debug_printf("%s", name);
793 debug_printf("%s %s %s", c->left.u, name, c->right.u);
797 if (!c->testfor) debug_printf("not (");
798 print_condition(c->left.c, FALSE);
799 debug_printf(" %s ", cond_names[c->type]);
800 print_condition(c->right.c, FALSE);
801 if (!c->testfor) debug_printf(")");
805 if (!c->testfor) debug_printf("not (");
806 else if (!toplevel) debug_printf("(");
807 print_condition(c->left.c, FALSE);
808 debug_printf(" %s ", cond_names[c->type]);
809 print_condition(c->right.c, FALSE);
810 if (!toplevel || !c->testfor) debug_printf(")");
813 case cond_foranyaddress:
814 debug_printf("%s %s (", name, c->left.u);
815 print_condition(c->right.c, FALSE);
824 /*************************************************
825 * Read one filtering command *
826 *************************************************/
830 pptr points to pointer to first character of command; the pointer
831 is updated to point after the last character read
832 lastcmdptr points to pointer to pointer to last command; used for hanging
833 on the newly read command
835 Returns: TRUE if command successfully read, else FALSE
839 read_command(uschar **pptr, filter_cmd ***lastcmdptr)
841 int command, i, cmd_bit;
842 filter_cmd *new, **newlastcmdptr;
844 BOOL was_seen_or_unseen = FALSE;
845 BOOL was_noerror = FALSE;
851 /* Read the next word and find which command it is. Command words are normally
852 terminated by white space, but there are two exceptions, which are the "if" and
853 "elif" commands. We must allow for them to be terminated by an opening bracket,
854 as brackets are allowed in conditions and users will expect not to require
857 if (Ustrncmp(ptr, "if(", 3) == 0)
859 Ustrcpy(buffer, "if");
862 else if (Ustrncmp(ptr, "elif(", 5) == 0)
864 Ustrcpy(buffer, "elif");
869 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
870 if (*error_pointer != NULL) return FALSE;
873 for (command = 0; command < command_list_count; command++)
874 if (Ustrcmp(buffer, command_list[command]) == 0) break;
876 /* Handle the individual commands */
880 /* Add takes two arguments, separated by the word "to". Headers has two
881 arguments, but the first must be "add", "remove", or "charset", and it gets
882 stored in the second argument slot. Neither may be preceded by seen, unseen
886 case headers_command:
887 if (seen_force || noerror_force)
889 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
890 "found before an \"%s\" command near line %d",
891 command_list[command], line_number);
896 /* Logwrite, logfile, pipe, and testprint all take a single argument, save
897 and logfile can have an option second argument for the mode, and deliver can
898 have "errors_to <address>" in a system filter, or in a user filter if the
899 address is the current one. */
901 case deliver_command:
902 case logfile_command:
903 case logwrite_command:
906 case testprint_command:
908 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
910 *error_pointer = string_sprintf("\"%s\" requires an argument "
911 "near line %d of filter file", command_list[command], line_number);
913 if (*error_pointer != NULL) yield = FALSE; else
915 union argtypes argument, second_argument;
917 argument.u = second_argument.u = NULL;
919 if (command == add_command)
921 argument.u = string_copy(buffer);
922 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
923 if (*buffer == 0 || Ustrcmp(buffer, "to") != 0)
924 *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
925 "near line %d of filter file", line_number);
928 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
930 *error_pointer = string_sprintf("value missing after \"to\" "
931 "near line %d of filter file", line_number);
932 else second_argument.u = string_copy(buffer);
936 else if (command == headers_command)
938 if (Ustrcmp(buffer, "add") == 0)
939 second_argument.b = TRUE;
941 if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
943 if (Ustrcmp(buffer, "charset") == 0)
944 second_argument.b = TRUE_UNSET;
947 *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
948 "expected after \"headers\" near line %d of filter file",
953 if (!system_filtering && second_argument.b != TRUE_UNSET)
955 *error_pointer = string_sprintf("header addition and removal is "
956 "available only in system filters: near line %d of filter file",
964 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
966 *error_pointer = string_sprintf("value missing after \"add\", "
967 "\"remove\", or \"charset\" near line %d of filter file",
969 else argument.u = string_copy(buffer);
973 /* The argument for the logwrite command must end in a newline, and the save
974 and logfile commands can have an optional mode argument. The deliver
975 command can have an optional "errors_to <address>" for a system filter,
976 or for a user filter if the address is the user's address. Accept the
977 syntax here - the check is later. */
981 if (command == logwrite_command)
983 int len = Ustrlen(buffer);
984 if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, "\n");
987 argument.u = string_copy(buffer);
989 if (command == save_command || command == logfile_command)
993 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
994 second_argument.i = (int)Ustrtol(buffer, NULL, 8);
996 else second_argument.i = -1;
999 else if (command == deliver_command)
1001 uschar *save_ptr = ptr;
1002 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1003 if (Ustrcmp(buffer, "errors_to") == 0)
1005 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1006 second_argument.u = string_copy(buffer);
1008 else ptr = save_ptr;
1012 /* Set up the command block. Seen defaults TRUE for delivery commands,
1013 FALSE for logging commands, and it doesn't matter for testprint, as
1014 that doesn't change the "delivered" status. */
1016 if (*error_pointer != NULL) yield = FALSE; else
1018 new = store_get(sizeof(filter_cmd) + sizeof(union argtypes));
1021 *lastcmdptr = &(new->next);
1022 new->command = command;
1023 new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1024 new->noerror = noerror_force;
1025 new->args[0] = argument;
1026 new->args[1] = second_argument;
1032 /* Elif, else and endif just set a flag if expected. */
1037 if (seen_force || noerror_force)
1039 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1040 "near line %d is not followed by a command", line_number);
1044 if (expect_endif > 0)
1045 had_else_endif = (command == elif_command)? had_elif :
1046 (command == else_command)? had_else : had_endif;
1049 *error_pointer = string_sprintf("unexpected \"%s\" command near "
1050 "line %d of filter file", buffer, line_number);
1056 /* Defer, freeze, and fail are available only if permitted. */
1059 cmd_bit = RDO_DEFER;
1060 goto DEFER_FREEZE_FAIL;
1064 goto DEFER_FREEZE_FAIL;
1066 case freeze_command:
1067 cmd_bit = RDO_FREEZE;
1070 if ((filter_options & cmd_bit) == 0)
1072 *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1073 "near line %d of filter file", buffer, line_number);
1078 /* A text message can be provided after the "text" keyword, or
1079 as a string in quotes. */
1082 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1083 if (*saveptr != '\"' && (*buffer == 0 || Ustrcmp(buffer, "text") != 0))
1090 if (*saveptr != '\"')
1091 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1092 fmsg = string_copy(buffer);
1095 /* Drop through and treat as "finish", but never set "seen". */
1099 /* Finish has no arguments; fmsg defaults to NULL */
1101 case finish_command:
1102 new = store_get(sizeof(filter_cmd));
1105 *lastcmdptr = &(new->next);
1106 new->command = command;
1107 new->seen = seen_force? seen_value : FALSE;
1108 new->args[0].u = fmsg;
1112 /* Seen, unseen, and noerror are not allowed before if, which takes a
1113 condition argument and then and else sub-commands. */
1116 if (seen_force || noerror_force)
1118 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1119 "found before an \"if\" command near line %d",
1124 /* Set up the command block for if */
1126 new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1129 *lastcmdptr = &(new->next);
1130 new->command = command;
1132 new->args[0].u = NULL;
1133 new->args[1].u = new->args[2].u = NULL;
1134 new->args[3].u = ptr;
1136 /* Read the condition */
1138 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1139 if (*error_pointer != NULL) { yield = FALSE; break; }
1141 /* Read the commands to be obeyed if the condition is true */
1143 newlastcmdptr = &(new->args[1].f);
1144 if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1146 /* If commands were successfully read, handle the various possible
1147 terminators. There may be a number of successive "elif" sections. */
1151 while (had_else_endif == had_elif)
1153 filter_cmd *newnew =
1154 store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1155 new->args[2].f = newnew;
1158 new->command = command;
1160 new->args[0].u = NULL;
1161 new->args[1].u = new->args[2].u = NULL;
1162 new->args[3].u = ptr;
1164 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1165 if (*error_pointer != NULL) { yield = FALSE; break; }
1166 newlastcmdptr = &(new->args[1].f);
1167 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1171 if (yield == FALSE) break;
1173 /* Handle termination by "else", possibly following one or more
1174 "elsif" sections. */
1176 if (had_else_endif == had_else)
1178 newlastcmdptr = &(new->args[2].f);
1179 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1181 else if (had_else_endif != had_endif)
1183 *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1184 "filter file", line_number);
1189 /* Otherwise the terminator was "endif" - this is checked by
1190 read_command_list(). The pointer is already set to NULL. */
1193 /* Reset the terminator flag. */
1195 had_else_endif = had_neither;
1199 /* The mail & vacation commands have a whole slew of keyworded arguments.
1200 The final argument values are the file expand and return message booleans,
1201 whose offsets are defined in mailarg_index_{expand,return}. Although they
1202 are logically booleans, because they are stored in a uschar * value, we use
1203 NULL and not FALSE, to keep 64-bit compilers happy. */
1206 case vacation_command:
1207 new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes));
1209 new->command = command;
1210 new->seen = seen_force? seen_value : FALSE;
1211 new->noerror = noerror_force;
1212 for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1214 /* Read keyword/value pairs until we hit one that isn't. The data
1215 must contain only printing chars plus tab, though the "text" value
1216 can also contain newlines. The "file" keyword can be preceded by the
1217 word "expand", and "return message" has no data. */
1221 uschar *saveptr = ptr;
1222 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1223 if (*error_pointer != NULL)
1229 /* Ensure "return" is followed by "message"; that's a complete option */
1231 if (Ustrcmp(buffer, "return") == 0)
1233 new->args[mailarg_index_return].u = US""; /* not NULL => TRUE */
1234 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1235 if (Ustrcmp(buffer, "message") != 0)
1237 *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1238 " near line %d of filter file", line_number);
1245 /* Ensure "expand" is followed by "file", then fall through to process the
1248 if (Ustrcmp(buffer, "expand") == 0)
1250 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1251 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1252 if (Ustrcmp(buffer, "file") != 0)
1254 *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1255 " near line %d of filter file", line_number);
1261 /* Scan for the keyword */
1263 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1264 if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1266 /* Not found keyword; assume end of this command */
1268 if (i >= MAILARGS_STRING_COUNT)
1274 /* Found keyword, read the data item */
1276 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1277 if (*error_pointer != NULL)
1282 else new->args[i].u = string_copy(buffer);
1285 /* If this is the vacation command, apply some default settings to
1286 some of the arguments. */
1288 if (command == vacation_command)
1290 if (new->args[mailarg_index_file].u == NULL)
1292 new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1293 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1295 if (new->args[mailarg_index_log].u == NULL)
1296 new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1297 if (new->args[mailarg_index_once].u == NULL)
1298 new->args[mailarg_index_once].u = string_copy(US".vacation");
1299 if (new->args[mailarg_index_once_repeat].u == NULL)
1300 new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1301 if (new->args[mailarg_index_subject].u == NULL)
1302 new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1305 /* Join the address on to the chain of generated addresses */
1308 *lastcmdptr = &(new->next);
1312 /* Seen and unseen just set flags */
1315 case unseen_command:
1318 *error_pointer = string_sprintf("\"seen\" or \"unseen\" "
1319 "near line %d is not followed by a command", line_number);
1324 *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1325 "near line %d", line_number);
1328 seen_value = (command == seen_command);
1330 was_seen_or_unseen = TRUE;
1334 /* So does noerror */
1336 case noerror_command:
1339 *error_pointer = string_sprintf("\"noerror\" "
1340 "near line %d is not followed by a command", line_number);
1343 noerror_force = TRUE;
1351 *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1352 "near line %d of filter file", buffer, line_number);
1357 if (!was_seen_or_unseen && !was_noerror)
1360 noerror_force = FALSE;
1369 /*************************************************
1370 * Read a list of commands *
1371 *************************************************/
1373 /* If condional is TRUE, the list must be terminated
1374 by the words "else" or "endif".
1377 pptr points to pointer to next character; the pointer is updated
1378 lastcmdptr points to pointer to pointer to previously-read command; used
1379 for hanging on the new command
1380 conditional TRUE if this command is the subject of a condition
1382 Returns: TRUE on success
1386 read_command_list(uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1388 if (conditional) expect_endif++;
1389 had_else_endif = had_neither;
1390 while (**pptr != 0 && had_else_endif == had_neither)
1392 if (!read_command(pptr, lastcmdptr)) return FALSE;
1393 *pptr = nextsigchar(*pptr, TRUE);
1398 if (had_else_endif == had_neither)
1400 *error_pointer = US"\"endif\" missing at end of filter file";
1410 /*************************************************
1411 * Test a condition *
1412 *************************************************/
1416 c points to the condition block; c->testfor indicated whether
1417 it's a positive or negative condition
1418 toplevel TRUE if called from "if" directly; FALSE otherwise
1420 Returns: TRUE if the condition is met
1424 test_condition(condition_block *c, BOOL toplevel)
1428 uschar *exp[2], *p, *pp;
1429 const uschar *regcomp_error = NULL;
1430 int regcomp_error_offset;
1434 if (c == NULL) return TRUE; /* does this ever occur? */
1439 yield = test_condition(c->left.c, FALSE) &&
1440 *error_pointer == NULL &&
1441 test_condition(c->right.c, FALSE);
1445 yield = test_condition(c->left.c, FALSE) ||
1446 (*error_pointer == NULL &&
1447 test_condition(c->right.c, FALSE));
1450 /* The personal test is meaningless in a system filter. The tests are now in
1451 a separate function (so Sieve can use them). However, an Exim filter does not
1452 scan Cc: (hence the FALSE argument). */
1455 yield = system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1458 case cond_delivered:
1459 yield = filter_delivered;
1462 /* Only TRUE if a message is actually being processed; FALSE for address
1463 testing and verification. */
1466 yield = message_id[0] != 0 &&
1467 (sender_address == NULL || sender_address[0] == 0);
1470 /* Only FALSE if a message is actually being processed; TRUE for address
1471 and filter testing and verification. */
1473 case cond_firsttime:
1474 yield = filter_test != FTEST_NONE || message_id[0] == 0 || deliver_firsttime;
1477 /* Only TRUE if a message is actually being processed; FALSE for address
1478 testing and verification. */
1480 case cond_manualthaw:
1481 yield = message_id[0] != 0 && deliver_manual_thaw;
1484 /* The foranyaddress condition loops through a list of addresses */
1486 case cond_foranyaddress:
1488 pp = expand_string(p);
1491 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1492 "filter file: %s", p, expand_string_message);
1497 parse_allow_group = TRUE; /* Allow group syntax */
1502 int start, end, domain;
1505 p = parse_find_address_end(pp, FALSE);
1509 filter_thisaddress =
1510 parse_extract_address(pp, &error, &start, &end, &domain, FALSE);
1513 if (filter_thisaddress != NULL)
1515 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1516 (debug_selector & D_filter) != 0)
1519 debug_printf("Extracted address %s\n", filter_thisaddress);
1521 yield = test_condition(c->right.c, FALSE);
1525 if (saveend == 0) break;
1529 parse_allow_group = FALSE; /* Reset group syntax flags */
1530 parse_found_group = FALSE;
1533 /* All other conditions have left and right values that need expanding;
1534 on error, it doesn't matter what value is returned. */
1538 for (i = 0; i < 2; i++)
1540 exp[i] = expand_string(p);
1543 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1544 "filter file: %s", p, expand_string_message);
1550 /* Inner switch for the different cases */
1555 yield = strcmpic(exp[0], exp[1]) == 0;
1559 yield = Ustrcmp(exp[0], exp[1]) == 0;
1563 yield = strstric(exp[0], exp[1], FALSE) != NULL;
1567 yield = Ustrstr(exp[0], exp[1]) != NULL;
1571 yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1575 yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1581 int len = Ustrlen(exp[1]);
1582 uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1583 yield = (s < exp[0])? FALSE :
1584 ((c->type == cond_ends)? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1590 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1591 (debug_selector & D_filter) != 0)
1593 debug_printf("Match expanded arguments:\n");
1594 debug_printf(" Subject = %s\n", exp[0]);
1595 debug_printf(" Pattern = %s\n", exp[1]);
1598 re = pcre_compile(CS exp[1],
1599 PCRE_COPT | ((c->type == cond_matches)? PCRE_CASELESS : 0),
1600 (const char **)®comp_error, ®comp_error_offset, NULL);
1604 *error_pointer = string_sprintf("error while compiling "
1605 "regular expression \"%s\": %s at offset %d",
1606 exp[1], regcomp_error, regcomp_error_offset);
1610 yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1613 /* For above and below, convert the strings to numbers */
1617 for (i = 0; i < 2; i++)
1619 val[i] = get_number(exp[i], &yield);
1622 *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1627 yield = (c->type == cond_above)? (val[0] > val[1]) : (val[0] < val[1]);
1633 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1634 (debug_selector & D_filter) != 0)
1637 debug_printf("%sondition is %s: ",
1638 toplevel? "C" : "Sub-c",
1639 (yield == c->testfor)? "true" : "false");
1640 print_condition(c, TRUE);
1644 return yield == c->testfor;
1649 /*************************************************
1650 * Interpret chain of commands *
1651 *************************************************/
1653 /* In testing state, just say what would be done rather than doing it. The
1654 testprint command just expands and outputs its argument in testing state, and
1655 does nothing otherwise.
1658 commands points to chain of commands to interpret
1659 generated where to hang newly-generated addresses
1661 Returns: FF_DELIVERED success, a significant action was taken
1662 FF_NOTDELIVERED success, no significant action
1663 FF_DEFER defer requested
1664 FF_FAIL fail requested
1665 FF_FREEZE freeze requested
1666 FF_ERROR there was a problem
1670 interpret_commands(filter_cmd *commands, address_item **generated)
1675 BOOL condition_value;
1677 while (commands != NULL)
1680 uschar *fmsg, *ff_name;
1681 uschar *expargs[MAILARGS_STRING_COUNT];
1685 /* Expand the relevant number of arguments for the command that are
1688 for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1690 uschar *ss = commands->args[i].u;
1697 expargs[i] = expand_string(ss);
1698 if (expargs[i] == NULL)
1700 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1701 "%s command: %s", ss, command_list[commands->command],
1702 expand_string_message);
1708 /* Now switch for each command, setting the "delivered" flag if any of them
1711 if (commands->seen) filter_delivered = TRUE;
1713 switch(commands->command)
1716 for (i = 0; i < 2; i++)
1718 uschar *ss = expargs[i];
1721 if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1723 *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1724 "command", expargs[i]);
1728 /* Allow for "--" at the start of the value (from -$n0) for example */
1729 if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1731 n[i] = (int)Ustrtol(ss, &end, 0);
1734 *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1740 filter_n[n[1]] += n[0];
1741 if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
1744 /* A deliver command's argument must be a valid address. Its optional
1745 second argument (system filter only) must also be a valid address. */
1747 case deliver_command:
1748 for (i = 0; i < 2; i++)
1753 int start, end, domain;
1755 uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1758 expargs[i] = ((filter_options & RDO_REWRITE) != 0)?
1759 rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1760 rewrite_existflags) :
1761 rewrite_address_qualify(ss, TRUE);
1764 *error_pointer = string_sprintf("malformed address \"%s\" in "
1765 "filter file: %s", s, error);
1771 /* Stick the errors address into a simple variable, as it will
1772 be referenced a few times. Check that the caller is permitted to
1777 if (s != NULL && !system_filtering)
1779 uschar *ownaddress = expand_string(US"$local_part@$domain");
1780 if (strcmpic(ownaddress, s) != 0)
1782 *error_pointer = US"errors_to must point to the caller's address";
1787 /* Test case: report what would happen */
1789 if (filter_test != FTEST_NONE)
1792 printf("%seliver message to: %s%s%s%s\n",
1793 (commands->seen)? "D" : "Unseen d",
1795 commands->noerror? " (noerror)" : "",
1796 (s != NULL)? " errors_to " : "",
1797 (s != NULL)? s : US"");
1804 DEBUG(D_filter) debug_printf("Filter: %sdeliver message to: %s%s%s%s\n",
1805 (commands->seen)? "" : "unseen ",
1807 commands->noerror? " (noerror)" : "",
1808 (s != NULL)? " errors_to " : "",
1809 (s != NULL)? s : US"");
1811 /* Create the new address and add it to the chain, setting the
1812 af_ignore_error flag if necessary, and the errors address, which can be
1813 set in a system filter and to the local address in user filters. */
1815 addr = deliver_make_addr(expargs[0], TRUE); /* TRUE => copy s */
1816 addr->prop.errors_address = (s == NULL)?
1817 s : string_copy(s); /* Default is NULL */
1818 if (commands->noerror) setflag(addr, af_ignore_error);
1819 addr->next = *generated;
1826 mode = commands->args[1].i;
1828 /* Test case: report what would happen */
1830 if (filter_test != FTEST_NONE)
1834 printf("%save message to: %s%s\n", (commands->seen)?
1835 "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1837 printf("%save message to: %s %04o%s\n", (commands->seen)?
1838 "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1841 /* Real case: Ensure save argument starts with / if there is a home
1842 directory to prepend. */
1846 if (s[0] != '/' && (filter_options & RDO_PREPEND_HOME) != 0 &&
1847 deliver_home != NULL && deliver_home[0] != 0)
1848 s = string_sprintf("%s/%s", deliver_home, s);
1849 DEBUG(D_filter) debug_printf("Filter: %ssave message to: %s%s\n",
1850 (commands->seen)? "" : "unseen ", s,
1851 commands->noerror? " (noerror)" : "");
1853 /* Create the new address and add it to the chain, setting the
1854 af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1857 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1858 setflag(addr, af_pfr|af_file);
1859 if (commands->noerror) setflag(addr, af_ignore_error);
1861 addr->next = *generated;
1867 s = string_copy(commands->args[0].u);
1868 if (filter_test != FTEST_NONE)
1871 printf("%sipe message to: %s%s\n", (commands->seen)?
1872 "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1874 else /* Ensure pipe command starts with | */
1876 DEBUG(D_filter) debug_printf("Filter: %spipe message to: %s%s\n",
1877 (commands->seen)? "" : "unseen ", s,
1878 commands->noerror? " (noerror)" : "");
1879 if (s[0] != '|') s = string_sprintf("|%s", s);
1881 /* Create the new address and add it to the chain, setting the
1882 af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1883 each command argument is expanded in the transport after the command
1884 has been split up into separate arguments. */
1886 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1887 setflag(addr, af_pfr|af_expand_pipe);
1888 if (commands->noerror) setflag(addr, af_ignore_error);
1889 addr->next = *generated;
1892 /* If there are any numeric variables in existence (e.g. after a regex
1893 condition), or if $thisaddress is set, take a copy for use in the
1894 expansion. Note that we can't pass NULL for filter_thisaddress, because
1895 NULL terminates the list. */
1897 if (expand_nmax >= 0 || filter_thisaddress != NULL)
1900 int ecount = (expand_nmax >= 0)? expand_nmax : -1;
1901 uschar **ss = store_get(sizeof(uschar *) * (ecount + 3));
1902 addr->pipe_expandn = ss;
1903 if (filter_thisaddress == NULL) filter_thisaddress = US"";
1904 *ss++ = string_copy(filter_thisaddress);
1905 for (i = 0; i <= expand_nmax; i++)
1906 *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1912 /* Set up the file name and mode, and close any previously open
1915 case logfile_command:
1916 log_mode = commands->args[1].i;
1917 if (log_mode == -1) log_mode = 0600;
1920 (void)close(log_fd);
1923 log_filename = expargs[0];
1924 if (filter_test != FTEST_NONE)
1927 printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1931 case logwrite_command:
1934 if (filter_test != FTEST_NONE)
1937 printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1938 string_printing(s));
1941 /* Attempt to write to a log file only if configured as permissible.
1942 Logging may be forcibly skipped for verifying or testing. */
1944 else if ((filter_options & RDO_LOG) != 0) /* Locked out */
1947 debug_printf("filter log command aborted: euid=%ld\n",
1948 (long int)geteuid());
1949 *error_pointer = US"logwrite command forbidden";
1952 else if ((filter_options & RDO_REALLOG) != 0)
1955 DEBUG(D_filter) debug_printf("writing filter log as euid %ld\n",
1956 (long int)geteuid());
1959 if (log_filename == NULL)
1961 *error_pointer = US"attempt to obey \"logwrite\" command "
1962 "without a previous \"logfile\"";
1965 log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1968 *error_pointer = string_open_failed(errno, "filter log file \"%s\"",
1974 if (write(log_fd, s, len) != len)
1976 *error_pointer = string_sprintf("write error on file \"%s\": %s",
1977 log_filename, strerror(errno));
1983 DEBUG(D_filter) debug_printf("skipping logwrite (verifying or testing)\n");
1987 /* Header addition and removal is available only in the system filter. The
1988 command is rejected at parse time otherwise. However "headers charset" is
1989 always permitted. */
1991 case headers_command:
1993 int subtype = commands->args[1].i;
1996 if (filter_test != FTEST_NONE)
1997 printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
1998 (subtype == FALSE)? "remove" : "charset", string_printing(s));
2000 if (subtype == TRUE)
2002 while (isspace(*s)) s++;
2005 header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')?
2007 header_last->type = header_checkname(header_last, FALSE);
2008 if (header_last->type >= 'a') header_last->type = htype_other;
2012 else if (subtype == FALSE)
2016 const uschar *list = s;
2018 while ((ss = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
2020 header_remove(0, ss);
2023 /* This setting lasts only while the filter is running; on exit, the
2024 variable is reset to the previous value. */
2026 else headers_charset = s;
2030 /* Defer, freeze, and fail are available only when explicitly permitted.
2031 These commands are rejected at parse time otherwise. The message can get
2032 very long by the inclusion of message headers; truncate if it is, and also
2033 ensure printing characters so as not to mess up log files. */
2036 ff_name = US"defer";
2038 goto DEFERFREEZEFAIL;
2043 goto DEFERFREEZEFAIL;
2045 case freeze_command:
2046 ff_name = US"freeze";
2051 if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, " ... (truncated)");
2052 fmsg = US string_printing(fmsg);
2053 *error_pointer = fmsg;
2055 if (filter_test != FTEST_NONE)
2058 printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2060 else DEBUG(D_filter) debug_printf("Filter: %s \"%s\"\n", ff_name, fmsg);
2063 case finish_command:
2064 if (filter_test != FTEST_NONE)
2067 printf("%sinish\n", (commands->seen)? "Seen f" : "F");
2071 DEBUG(D_filter) debug_printf("Filter: %sfinish\n",
2072 (commands->seen)? " Seen " : "");
2074 finish_obeyed = TRUE;
2075 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2079 uschar *save_address = filter_thisaddress;
2080 int ok = FF_DELIVERED;
2081 condition_value = test_condition(commands->args[0].c, TRUE);
2082 if (*error_pointer != NULL) ok = FF_ERROR; else
2085 ok = interpret_commands(commands->args[condition_value? 1:2].f,
2089 filter_thisaddress = save_address;
2090 if (finish_obeyed || (ok != FF_DELIVERED && ok != FF_NOTDELIVERED))
2096 /* To try to catch runaway loops, do not generate mail if the
2097 return path is unset or if a non-trusted user supplied -f <>
2098 as the return path. */
2101 case vacation_command:
2102 if (return_path == NULL || return_path[0] == 0)
2104 if (filter_test != FTEST_NONE)
2105 printf("%s command ignored because return_path is empty\n",
2106 command_list[commands->command]);
2107 else DEBUG(D_filter) debug_printf("%s command ignored because return_path "
2108 "is empty\n", command_list[commands->command]);
2112 /* Check the contents of the strings. The type of string can be deduced
2113 from the value of i.
2115 . If i is equal to mailarg_index_text it's a text string for the body,
2116 where anything goes.
2118 . If i is > mailarg_index_text, we are dealing with a file name, which
2119 cannot contain non-printing characters.
2121 . If i is less than mailarg_index_headers we are dealing with something
2122 that will go in a single message header line, where newlines must be
2123 followed by white space.
2125 . If i is equal to mailarg_index_headers, we have a string that contains
2126 one or more headers. Newlines that are not followed by white space must
2127 be followed by a header name.
2130 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
2133 uschar *s = expargs[i];
2135 if (s == NULL) continue;
2137 if (i != mailarg_index_text) for (p = s; *p != 0; p++)
2140 if (i > mailarg_index_text)
2142 if (!mac_isprint(c))
2144 *error_pointer = string_sprintf("non-printing character in \"%s\" "
2145 "in %s command", string_printing(s),
2146 command_list[commands->command]);
2151 /* i < mailarg_index_text */
2153 else if (c == '\n' && !isspace(p[1]))
2155 if (i < mailarg_index_headers)
2157 *error_pointer = string_sprintf("\\n not followed by space in "
2158 "\"%.1024s\" in %s command", string_printing(s),
2159 command_list[commands->command]);
2163 /* Check for the start of a new header line within the string */
2168 for (pp = p + 1;; pp++)
2171 if (c == ':' && pp != p + 1) break;
2172 if (c == 0 || c == ':' || isspace(*pp))
2174 *error_pointer = string_sprintf("\\n not followed by space or "
2175 "valid header name in \"%.1024s\" in %s command",
2176 string_printing(s), command_list[commands->command]);
2183 } /* Loop to scan the string */
2185 /* The string is OK */
2187 commands->args[i].u = s;
2190 /* Proceed with mail or vacation command */
2192 if (filter_test != FTEST_NONE)
2194 uschar *to = commands->args[mailarg_index_to].u;
2196 printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2197 (to == NULL)? US"<default>" : to,
2198 (commands->command == vacation_command)? " (vacation)" : "",
2199 (commands->noerror)? " (noerror)" : "");
2200 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2202 uschar *arg = commands->args[i].u;
2205 int len = Ustrlen(mailargs[i]);
2206 int indent = (debug_selector != 0)? output_indent : 0;
2207 while (len++ < 7 + indent) printf(" ");
2208 printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2209 (commands->args[mailarg_index_expand].u != NULL &&
2210 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2213 if (commands->args[mailarg_index_return].u != NULL)
2214 printf("Return original message\n");
2219 uschar *log_addr = NULL;
2220 uschar *to = commands->args[mailarg_index_to].u;
2225 if (to == NULL) to = expand_string(US"$reply_address");
2226 while (isspace(*to)) to++;
2228 for (tt = to; *tt != 0; tt++) /* Get rid of newlines */
2229 if (*tt == '\n') *tt = ' ';
2233 debug_printf("Filter: %smail to: %s%s%s\n",
2234 (commands->seen)? "seen " : "",
2236 (commands->command == vacation_command)? " (vacation)" : "",
2237 (commands->noerror)? " (noerror)" : "");
2238 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2240 uschar *arg = commands->args[i].u;
2243 int len = Ustrlen(mailargs[i]);
2244 while (len++ < 15) debug_printf(" ");
2245 debug_printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2246 (commands->args[mailarg_index_expand].u != NULL &&
2247 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2252 /* Create the "address" for the autoreply. This is used only for logging,
2253 as the actual recipients are extracted from the To: line by -t. We use the
2254 same logic here to extract the working addresses (there may be more than
2255 one). Just in case there are a vast number of addresses, stop when the
2256 string gets too long. */
2261 uschar *ss = parse_find_address_end(tt, FALSE);
2262 uschar *recipient, *errmess;
2263 int start, end, domain;
2267 recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
2271 /* Ignore empty addresses and errors; an error will occur later if
2272 there's something really bad. */
2274 if (recipient != NULL)
2276 log_addr = string_catn(log_addr, &size, &ptr,
2277 log_addr ? US"," : US">", 1);
2278 log_addr = string_cat(log_addr, &size, &ptr, recipient);
2285 log_addr = string_catn(log_addr, &size, &ptr, US", ...", 5);
2289 /* Move on past this address */
2291 tt = ss + (*ss? 1:0);
2292 while (isspace(*tt)) tt++;
2295 if (log_addr == NULL)
2297 log_addr = string_sprintf(">**bad-reply**");
2298 badflag = af_bad_reply;
2300 else log_addr[ptr] = 0;
2302 addr = deliver_make_addr(log_addr, FALSE);
2303 setflag(addr, (af_pfr|badflag));
2304 if (commands->noerror) setflag(addr, af_ignore_error);
2305 addr->next = *generated;
2307 addr->reply = store_get(sizeof(reply_item));
2308 addr->reply->from = NULL;
2309 addr->reply->to = string_copy(to);
2310 addr->reply->file_expand =
2311 commands->args[mailarg_index_expand].u != NULL;
2312 addr->reply->expand_forbid = expand_forbid;
2313 addr->reply->return_message =
2314 commands->args[mailarg_index_return].u != NULL;
2315 addr->reply->once_repeat = 0;
2317 if (commands->args[mailarg_index_once_repeat].u != NULL)
2319 addr->reply->once_repeat =
2320 readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2322 if (addr->reply->once_repeat < 0)
2324 *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2325 "in mail or vacation command: %s",
2326 commands->args[mailarg_index_once_repeat]);
2331 /* Set up all the remaining string arguments (those other than "to") */
2333 for (i = 1; i < mailargs_string_passed; i++)
2335 uschar *ss = commands->args[i].u;
2336 *((uschar **)(((uschar *)(addr->reply)) + reply_offsets[i])) =
2337 (ss == NULL)? NULL : string_copy(ss);
2342 case testprint_command:
2343 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2345 const uschar *s = string_printing(expargs[0]);
2346 if (filter_test == FTEST_NONE)
2347 debug_printf("Filter: testprint: %s\n", s);
2349 printf("Testprint: %s\n", s);
2353 commands = commands->next;
2356 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2361 /*************************************************
2362 * Test for a personal message *
2363 *************************************************/
2365 /* This function is global so that it can also be called from the code that
2366 implements Sieve filters.
2369 aliases a chain of aliases
2370 scan_cc TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2372 Returns: TRUE if the message is deemed to be personal
2376 filter_personal(string_item *aliases, BOOL scan_cc)
2378 uschar *self, *self_from, *self_to;
2379 uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL;
2380 void *reset_point = store_get(0);
2386 /* If any header line in the message is a defined "List-" header field, it is
2387 not a personal message. We used to check for any header line that started with
2388 "List-", but this was tightened up for release 4.54. The check is now for
2389 "List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
2390 Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
2391 defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
2392 contain any value other than "no", the message is not personal (RFC 3834).
2393 Previously the test was for "auto-". */
2395 for (h = header_list; h != NULL; h = h->next)
2398 if (h->type == htype_old) continue;
2400 if (strncmpic(h->text, US"List-", 5) == 0)
2403 if (strncmpic(s, US"Id:", 3) == 0 ||
2404 strncmpic(s, US"Help:", 5) == 0 ||
2405 strncmpic(s, US"Subscribe:", 10) == 0 ||
2406 strncmpic(s, US"Unsubscribe:", 12) == 0 ||
2407 strncmpic(s, US"Post:", 5) == 0 ||
2408 strncmpic(s, US"Owner:", 6) == 0 ||
2409 strncmpic(s, US"Archive:", 8) == 0)
2413 else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
2416 while (isspace(*s)) s++;
2417 if (strncmpic(s, US"no", 2) != 0) return FALSE;
2419 while (isspace(*s)) s++;
2420 if (*s != 0) return FALSE;
2424 /* Set up "my" address */
2426 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2427 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2428 global_rewrite_rules);
2429 self_to = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2430 global_rewrite_rules);
2433 if (self_from == NULL) self_from = self;
2434 if (self_to == NULL) self_to = self;
2436 /* If there's a prefix or suffix set, we must include the prefixed/
2437 suffixed version of the local part in the tests. */
2439 if (deliver_localpart_prefix != NULL || deliver_localpart_suffix != NULL)
2441 psself = string_sprintf("%s%s%s@%s",
2442 (deliver_localpart_prefix == NULL)? US"" : deliver_localpart_prefix,
2444 (deliver_localpart_suffix == NULL)? US"" : deliver_localpart_suffix,
2446 psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2447 global_rewrite_rules);
2448 psself_to = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2449 global_rewrite_rules);
2450 if (psself_from == NULL) psself_from = psself;
2451 if (psself_to == NULL) psself_to = psself;
2456 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2460 header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2464 header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2467 header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2473 header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2474 "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2475 "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2477 header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2479 (sender_address == NULL || sender_address[0] != 0);
2481 store_reset(reset_point);
2487 /*************************************************
2488 * Interpret a mail filter file *
2489 *************************************************/
2493 filter points to the entire file, read into store as a single string
2494 options controls whether various special things are allowed, and requests
2496 generated where to hang newly-generated addresses
2497 error where to pass back an error text
2499 Returns: FF_DELIVERED success, a significant action was taken
2500 FF_NOTDELIVERED success, no significant action
2501 FF_DEFER defer requested
2502 FF_FAIL fail requested
2503 FF_FREEZE freeze requested
2504 FF_ERROR there was a problem
2508 filter_interpret(uschar *filter, int options, address_item **generated,
2512 int yield = FF_ERROR;
2513 uschar *ptr = filter;
2514 uschar *save_headers_charset = headers_charset;
2515 filter_cmd *commands = NULL;
2516 filter_cmd **lastcmdptr = &commands;
2518 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2520 /* Initialize "not in an if command", set the global flag that is always TRUE
2521 while filtering, and zero the variables. */
2525 filter_running = TRUE;
2526 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2528 /* To save having to pass certain values about all the time, make them static.
2529 Also initialize the line number, for error messages, and the log file
2532 filter_options = options;
2533 filter_delivered = FALSE;
2534 finish_obeyed = FALSE;
2535 error_pointer = error;
2536 *error_pointer = NULL;
2540 log_filename = NULL;
2542 /* Scan filter file for syntax and build up an interpretation thereof, and
2543 interpret the compiled commands, and if testing, say whether we ended up
2544 delivered or not, unless something went wrong. */
2547 ptr = nextsigchar(ptr, TRUE);
2549 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2550 yield = interpret_commands(commands, generated);
2552 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2558 s = US"Filtering ended by \"defer\".";
2562 s = US"Filtering ended by \"freeze\".";
2566 s = US"Filtering ended by \"fail\".";
2570 s = US"Filtering set up at least one significant delivery "
2571 "or other action.\n"
2572 "No other deliveries will occur.";
2575 case FF_NOTDELIVERED:
2576 s = US"Filtering did not set up a significant delivery.\n"
2577 "Normal delivery will occur.";
2581 s = string_sprintf("Filter error: %s", *error);
2585 if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2586 else debug_printf("%s\n", s);
2589 /* Close the log file if it was opened, and kill off any numerical variables
2590 before returning. Reset the header decoding charset. */
2592 if (log_fd >= 0) (void)close(log_fd);
2594 filter_running = FALSE;
2595 headers_charset = save_headers_charset;
2597 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2602 /* End of filter.c */