1 /* $Cambridge: exim/src/src/filter.c,v 1.14 2007/01/08 10:50:18 ph10 Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
7 /* Copyright (c) University of Cambridge 1995 - 2007 */
8 /* See the file NOTICE for conditions of use and distribution. */
11 /* Code for mail filtering functions. */
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. */
23 struct condition_block;
26 struct string_item *a;
28 struct condition_block *c;
34 /* Local structures used in this module */
36 typedef struct filter_cmd {
37 struct filter_cmd *next;
41 union argtypes args[1];
44 typedef struct condition_block {
45 struct condition_block *parent;
52 /* Miscellaneous other declarations */
54 static uschar **error_pointer;
55 static uschar *log_filename;
56 static int filter_options;
57 static int line_number;
58 static int expect_endif;
59 static int had_else_endif;
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;
69 enum { had_neither, had_else, had_elif, had_endif };
71 static BOOL read_command_list(uschar **, filter_cmd ***, BOOL);
74 /* The string arguments for the mail command. The header line ones (that are
75 permitted to include \n followed by white space) first, and then the body text
76 one (it can have \n anywhere). Then the file names and once_repeat, which may
79 static char *mailargs[] = { /* "to" must be first, and */
80 "to", /* "cc" and "bcc" must follow */
86 "extra_headers", /* miscellaneous added header lines */
94 /* The count of string arguments */
96 #define MAILARGS_STRING_COUNT (sizeof(mailargs)/sizeof(uschar *))
98 /* The count of string arguments that are actually passed over as strings
99 (once_repeat is converted to an int). */
101 #define mailargs_string_passed (MAILARGS_STRING_COUNT - 1)
103 /* This defines the offsets for the arguments; first the string ones, and
104 then the non-string ones. The order must be as above. */
106 enum { mailarg_index_to,
110 mailarg_index_reply_to,
111 mailarg_index_subject,
112 mailarg_index_headers, /* misc headers must be last */
113 mailarg_index_text, /* text is first after headers */
114 mailarg_index_file, /* between text and expand are filenames */
117 mailarg_index_once_repeat, /* a time string */
118 mailarg_index_expand, /* first non-string argument */
119 mailarg_index_return,
120 mailargs_total /* total number of arguments */
123 /* Offsets in the data structure for the string arguments (note that
124 once_repeat isn't a string argument at this point.) */
126 static int reply_offsets[] = { /* must be in same order as above */
127 offsetof(reply_item, to),
128 offsetof(reply_item, cc),
129 offsetof(reply_item, bcc),
130 offsetof(reply_item, from),
131 offsetof(reply_item, reply_to),
132 offsetof(reply_item, subject),
133 offsetof(reply_item, headers),
134 offsetof(reply_item, text),
135 offsetof(reply_item, file),
136 offsetof(reply_item, logfile),
137 offsetof(reply_item, oncelog),
140 /* Condition identities and names, with negated versions for some
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 };
149 static char *cond_names[] = {
150 "and", "or", "personal",
151 "begins", "BEGINS", "ends", "ENDS",
152 "is", "IS", "matches", "MATCHES", "contains",
153 "CONTAINS", "delivered", "above", "below", "error_message",
154 "first_delivery", "manually_thawed", "foranyaddress" };
156 static char *cond_not_names[] = {
157 "", "", "not personal",
158 "does not begin", "does not BEGIN",
159 "does not end", "does not END",
160 "is not", "IS not", "does not match",
161 "does not MATCH", "does not contain", "does not CONTAIN",
162 "not delivered", "not above", "not below", "not error_message",
163 "not first_delivery", "not manually_thawed", "not foranyaddress" };
165 /* Tables of binary condition words and their corresponding types. Not easy
166 to amalgamate with the above because of the different variants. */
168 static char *cond_words[] = {
190 static int cond_word_count = (sizeof(cond_words)/sizeof(uschar *));
192 static int cond_types[] = { cond_BEGINS, cond_BEGINS, cond_CONTAINS,
193 cond_CONTAINS, cond_ENDS, cond_ENDS, cond_IS, cond_MATCHES, cond_MATCHES,
194 cond_above, cond_begins, cond_begins, cond_below, cond_contains,
195 cond_contains, cond_ends, cond_ends, cond_is, cond_matches, cond_matches };
197 /* Command identities: must be kept in step with the list of command words
198 and the list of expanded argument counts which follow. */
200 enum { add_command, defer_command, deliver_command, elif_command, else_command,
201 endif_command, finish_command, fail_command, freeze_command,
202 headers_command, if_command, logfile_command, logwrite_command,
203 mail_command, noerror_command, pipe_command, save_command, seen_command,
204 testprint_command, unseen_command, vacation_command };
206 static char *command_list[] = {
207 "add", "defer", "deliver", "elif", "else", "endif", "finish",
208 "fail", "freeze", "headers", "if", "logfile", "logwrite", "mail",
209 "noerror", "pipe", "save", "seen", "testprint", "unseen", "vacation"
212 static int command_list_count = sizeof(command_list)/sizeof(uschar *);
214 /* This table contains the number of expanded arguments in the bottom 4 bits.
215 If the top bit is set, it means that the default for the command is "seen". */
217 static uschar command_exparg_count[] = {
231 MAILARGS_STRING_COUNT, /* mail */
238 MAILARGS_STRING_COUNT /* vacation */
243 /*************************************************
244 * Find next significant uschar *
245 *************************************************/
247 /* Function to skip over white space and, optionally, comments.
250 ptr pointer to next character
251 comment_allowed if TRUE, comments (# to \n) are skipped
253 Returns: pointer to next non-whitespace character
257 nextsigchar(uschar *ptr, BOOL comment_allowed)
261 while (isspace(*ptr))
263 if (*ptr == '\n') line_number++;
266 if (comment_allowed && *ptr == '#')
268 while (*(++ptr) != '\n' && *ptr != 0);
278 /*************************************************
280 *************************************************/
282 /* The terminator is white space unless bracket is TRUE, in which
283 case ( and ) terminate.
286 ptr pointer to next character
287 buffer where to put the word
289 bracket if TRUE, terminate on ( and ) as well as space
291 Returns: pointer to the next significant character after the word
295 nextword(uschar *ptr, uschar *buffer, int size, BOOL bracket)
298 while (*ptr != 0 && !isspace(*ptr) &&
299 (!bracket || (*ptr != '(' && *ptr != ')')))
301 if (bp - buffer < size - 1) *bp++ = *ptr++; else
303 *error_pointer = string_sprintf("word is too long in line %d of "
304 "filter file (max = %d chars)", line_number, size);
309 return nextsigchar(ptr, TRUE);
314 /*************************************************
316 *************************************************/
318 /* Might be a word, or might be a quoted string; in the latter case
322 ptr pointer to next character
323 buffer where to put the item
325 bracket if TRUE, terminate non-quoted on ( and ) as well as space
327 Returns: the next significant character after the item
331 nextitem(uschar *ptr, uschar *buffer, int size, BOOL bracket)
334 if (*ptr != '\"') return nextword(ptr, buffer, size, bracket);
336 while (*(++ptr) != 0 && *ptr != '\"' && *ptr != '\n')
338 if (bp - buffer >= size - 1)
340 *error_pointer = string_sprintf("string is too long in line %d of "
341 "filter file (max = %d chars)", line_number, size);
345 if (*ptr != '\\') *bp++ = *ptr; else
347 if (isspace(ptr[1])) /* \<whitespace>NL<whitespace> ignored */
350 while (*p != '\n' && isspace(*p)) p++;
355 while (ptr[1] != '\n' && isspace(ptr[1])) ptr++;
360 *bp++ = string_interpret_escape(&ptr);
364 if (*ptr == '\"') ptr++;
365 else if (*error_pointer == NULL)
366 *error_pointer = string_sprintf("quote missing at end of string "
367 "in line %d", line_number);
370 return nextsigchar(ptr, TRUE);
376 /*************************************************
377 * Convert a string + K|M to a number *
378 *************************************************/
382 s points to text string
383 OK set TRUE if a valid number was read
385 Returns: the number, or 0 on error (with *OK FALSE)
389 get_number(uschar *s, BOOL *ok)
393 if (sscanf(CS s, "%i%n", &value, &count) != 1) return 0;
394 if (tolower(s[count]) == 'k') { value *= 1024; count++; }
395 if (tolower(s[count]) == 'm') { value *= 1024*1024; count++; }
396 while (isspace((s[count]))) count++;
397 if (s[count] != 0) return 0;
404 /*************************************************
405 * Read one condition *
406 *************************************************/
408 /* A complete condition must be terminated by "then"; bracketed internal
409 conditions must be terminated by a closing bracket. They are read by calling
410 this function recursively.
413 ptr points to start of condition
414 condition_block where to hang the created condition block
415 toplevel TRUE when called at the top level
417 Returns: points to next character after "then"
421 read_condition(uschar *ptr, condition_block **cond, BOOL toplevel)
425 condition_block *current_parent = NULL;
426 condition_block **current = cond;
430 /* Loop to read next condition */
436 /* reaching the end of the input is an error. */
440 *error_pointer = string_sprintf("\"then\" missing at end of filter file");
444 /* Opening bracket at the start of a condition introduces a nested
445 condition, which must be terminated by a closing bracket. */
449 ptr = read_condition(nextsigchar(ptr+1, TRUE), &c, FALSE);
450 if (*error_pointer != NULL) break;
453 *error_pointer = string_sprintf("expected \")\" in line %d of "
454 "filter file", line_number);
459 c->testfor = !c->testfor;
462 ptr = nextsigchar(ptr+1, TRUE);
466 /* Closing bracket at the start of a condition is an error. Give an
467 explicit message, as otherwise "unknown condition" would be confusing. */
469 else if (*ptr == ')')
471 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
472 "filter file", line_number);
476 /* Otherwise we expect a word or a string. */
480 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
481 if (*error_pointer != NULL) break;
483 /* "Then" at the start of a condition is an error */
485 if (Ustrcmp(buffer, "then") == 0)
487 *error_pointer = string_sprintf("unexpected \"then\" near line %d of "
488 "filter file", line_number);
492 /* "Not" at the start of a condition negates the testing condition. */
494 if (Ustrcmp(buffer, "not") == 0)
500 /* Build a condition block from the specific word. */
502 c = store_get(sizeof(condition_block));
503 c->left.u = c->right.u = NULL;
504 c->testfor = testfor;
507 /* Check for conditions that start with a keyword */
509 if (Ustrcmp(buffer, "delivered") == 0) c->type = cond_delivered;
510 else if (Ustrcmp(buffer, "error_message") == 0) c->type = cond_errormsg;
511 else if (Ustrcmp(buffer, "first_delivery") == 0) c->type = cond_firsttime;
512 else if (Ustrcmp(buffer, "manually_thawed") == 0) c->type = cond_manualthaw;
514 /* Personal can be followed by any number of aliases */
516 else if (Ustrcmp(buffer, "personal") == 0)
518 c->type = cond_personal;
522 uschar *saveptr = ptr;
523 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
524 if (*error_pointer != NULL) break;
525 if (Ustrcmp(buffer, "alias") != 0)
530 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
531 if (*error_pointer != NULL) break;
532 aa = store_get(sizeof(string_item));
533 aa->text = string_copy(buffer);
534 aa->next = c->left.a;
539 /* Foranyaddress must be followed by a string and a condition enclosed
540 in parentheses, which is handled as a subcondition. */
542 else if (Ustrcmp(buffer, "foranyaddress") == 0)
544 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
545 if (*error_pointer != NULL) break;
548 *error_pointer = string_sprintf("\"(\" expected after \"foranyaddress\" "
549 "near line %d of filter file", line_number);
553 c->type = cond_foranyaddress;
554 c->left.u = string_copy(buffer);
556 ptr = read_condition(nextsigchar(ptr+1, TRUE), &(c->right.c), FALSE);
557 if (*error_pointer != NULL) break;
560 *error_pointer = string_sprintf("expected \")\" in line %d of "
561 "filter file", line_number);
566 c->testfor = !c->testfor;
569 ptr = nextsigchar(ptr+1, TRUE);
572 /* If it's not a word we recognize, then it must be the lefthand
573 operand of one of the comparison words. */
578 uschar *isptr = NULL;
580 c->left.u = string_copy(buffer);
581 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
582 if (*error_pointer != NULL) break;
584 /* Handle "does|is [not]", preserving the pointer after "is" in
585 case it isn't that, but the form "is <string>". */
587 if (strcmpic(buffer, US"does") == 0 || strcmpic(buffer, US"is") == 0)
589 if (buffer[0] == 'i') { c->type = cond_is; isptr = ptr; }
590 if (buffer[0] == 'I') { c->type = cond_IS; isptr = ptr; }
592 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
593 if (*error_pointer != NULL) break;
594 if (strcmpic(buffer, US"not") == 0)
596 c->testfor = !c->testfor;
597 if (isptr != NULL) isptr = ptr;
598 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
599 if (*error_pointer != NULL) break;
603 for (i = 0; i < cond_word_count; i++)
605 if (Ustrcmp(buffer, cond_words[i]) == 0)
607 c->type = cond_types[i];
612 /* If an unknown word follows "is" or "is not"
613 it's actually the argument. Reset to read it. */
615 if (i >= cond_word_count)
623 *error_pointer = string_sprintf("unrecognized condition word \"%s\" "
624 "near line %d of filter file", buffer, line_number);
629 /* Get the RH argument. */
631 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
632 if (*error_pointer != NULL) break;
633 c->right.u = string_copy(buffer);
637 /* We have read some new condition and set it up in the condition block
638 c; point the current pointer at it, and then deal with what follows. */
642 /* Closing bracket terminates if this is a lower-level condition. Otherwise
648 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
649 "filter file", line_number);
653 /* Opening bracket following a condition is an error; give an explicit
654 message to make it clearer what is wrong. */
656 else if (*ptr == '(')
658 *error_pointer = string_sprintf("unexpected \"(\" in line %d of "
659 "filter file", line_number);
663 /* Otherwise the next thing must be one of the words "and", "or" or "then" */
667 uschar *saveptr = ptr;
668 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
669 if (*error_pointer != NULL) break;
671 /* "Then" terminates a toplevel condition; otherwise a closing bracket
672 has been omitted. Put a string terminator at the start of "then" so
673 that reflecting the condition can be done when testing. */
675 if (Ustrcmp(buffer, "then") == 0)
677 if (toplevel) *saveptr = 0;
678 else *error_pointer = string_sprintf("missing \")\" at end of "
679 "condition near line %d of filter file", line_number);
683 /* "And" causes a new condition block to replace the one we have
684 just read, which becomes the left sub-condition. The current pointer
685 is reset to the pointer for the right sub-condition. We have to keep
686 track of the tree of sequential "ands", so as to traverse back up it
687 if an "or" is met. */
689 else if (Ustrcmp(buffer, "and") == 0)
691 condition_block *andc = store_get(sizeof(condition_block));
692 andc->parent = current_parent;
693 andc->type = cond_and;
694 andc->testfor = TRUE;
696 andc->right.u = NULL; /* insurance */
698 current = &(andc->right.c);
699 current_parent = andc;
702 /* "Or" is similar, but has to be done a bit more carefully to
703 ensure that "and" is more binding. If there's a parent set, we
704 are following a sequence of "and"s and must track back to their
707 else if (Ustrcmp(buffer, "or") == 0)
709 condition_block *orc = store_get(sizeof(condition_block));
710 condition_block *or_parent = NULL;
712 if (current_parent != NULL)
714 while (current_parent->parent != NULL &&
715 current_parent->parent->type == cond_and)
716 current_parent = current_parent->parent;
718 /* If the parent has a parent, it must be an "or" parent. */
720 if (current_parent->parent != NULL)
721 or_parent = current_parent->parent;
724 orc->parent = or_parent;
725 if (or_parent == NULL) *cond = orc; else
726 or_parent->right.c = orc;
729 orc->left.c = (current_parent == NULL)? c : current_parent;
730 orc->right.c = NULL; /* insurance */
731 current = &(orc->right.c);
732 current_parent = orc;
735 /* Otherwise there is a disaster */
739 *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
740 "expected near line %d of filter file, but found \"%s\"",
741 toplevel? "then" : ")", line_number, buffer);
747 return nextsigchar(ptr, TRUE);
752 /*************************************************
753 * Ouput the current indent *
754 *************************************************/
760 for (i = 0; i < output_indent; i++) debug_printf(" ");
765 /*************************************************
766 * Condition printer: for debugging *
767 *************************************************/
771 c the block at the top of the tree
772 toplevel TRUE at toplevel - stops overall brackets
778 print_condition(condition_block *c, BOOL toplevel)
780 char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
787 case cond_manualthaw:
788 debug_printf("%s", name);
803 debug_printf("%s %s %s", c->left.u, (char *)name, c->right.u);
807 if (!c->testfor) debug_printf("not (");
808 print_condition(c->left.c, FALSE);
809 debug_printf(" %s ", cond_names[c->type]);
810 print_condition(c->right.c, FALSE);
811 if (!c->testfor) debug_printf(")");
815 if (!c->testfor) debug_printf("not (");
816 else if (!toplevel) debug_printf("(");
817 print_condition(c->left.c, FALSE);
818 debug_printf(" %s ", cond_names[c->type]);
819 print_condition(c->right.c, FALSE);
820 if (!toplevel || !c->testfor) debug_printf(")");
823 case cond_foranyaddress:
824 debug_printf("%s %s (", name, c->left.u);
825 print_condition(c->right.c, FALSE);
834 /*************************************************
835 * Read one filtering command *
836 *************************************************/
840 pptr points to pointer to first character of command; the pointer
841 is updated to point after the last character read
842 lastcmdptr points to pointer to pointer to last command; used for hanging
843 on the newly read command
845 Returns: TRUE if command successfully read, else FALSE
849 read_command(uschar **pptr, filter_cmd ***lastcmdptr)
851 int command, i, cmd_bit;
852 filter_cmd *new, **newlastcmdptr;
854 BOOL was_seen_or_unseen = FALSE;
855 BOOL was_noerror = FALSE;
861 /* Read the next word and find which command it is. Command words are normally
862 terminated by white space, but there are two exceptions, which are the "if" and
863 "elif" commands. We must allow for them to be terminated by an opening bracket,
864 as brackets are allowed in conditions and users will expect not to require
867 if (Ustrncmp(ptr, "if(", 3) == 0)
869 Ustrcpy(buffer, "if");
872 else if (Ustrncmp(ptr, "elif(", 5) == 0)
874 Ustrcpy(buffer, "elif");
879 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
880 if (*error_pointer != NULL) return FALSE;
883 for (command = 0; command < command_list_count; command++)
884 if (Ustrcmp(buffer, command_list[command]) == 0) break;
886 /* Handle the individual commands */
890 /* Add takes two arguments, separated by the word "to". Headers has two
891 arguments, but the first must be "add", "remove", or "charset", and it gets
892 stored in the second argument slot. Neither may be preceded by seen, unseen
896 case headers_command:
897 if (seen_force || noerror_force)
899 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
900 "found before an \"%s\" command near line %d",
901 command_list[command], line_number);
906 /* Logwrite, logfile, pipe, and testprint all take a single argument, save
907 and logfile can have an option second argument for the mode, and deliver can
908 have "errors_to <address>" in a system filter, or in a user filter if the
909 address is the current one. */
911 case deliver_command:
912 case logfile_command:
913 case logwrite_command:
916 case testprint_command:
918 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
920 *error_pointer = string_sprintf("\"%s\" requires an argument "
921 "near line %d of filter file", command_list[command], line_number);
923 if (*error_pointer != NULL) yield = FALSE; else
925 union argtypes argument, second_argument;
927 argument.u = second_argument.u = NULL;
929 if (command == add_command)
931 argument.u = string_copy(buffer);
932 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
933 if (*buffer == 0 || Ustrcmp(buffer, "to") != 0)
934 *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
935 "near line %d of filter file", line_number);
938 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
940 *error_pointer = string_sprintf("value missing after \"to\" "
941 "near line %d of filter file", line_number);
942 else second_argument.u = string_copy(buffer);
946 else if (command == headers_command)
948 if (Ustrcmp(buffer, "add") == 0)
949 second_argument.b = TRUE;
951 if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
953 if (Ustrcmp(buffer, "charset") == 0)
954 second_argument.b = TRUE_UNSET;
957 *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
958 "expected after \"headers\" near line %d of filter file",
963 if (!system_filtering && second_argument.b != TRUE_UNSET)
965 *error_pointer = string_sprintf("header addition and removal is "
966 "available only in system filters: near line %d of filter file",
974 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
976 *error_pointer = string_sprintf("value missing after \"add\", "
977 "\"remove\", or \"charset\" near line %d of filter file",
979 else argument.u = string_copy(buffer);
983 /* The argument for the logwrite command must end in a newline, and the save
984 and logfile commands can have an optional mode argument. The deliver
985 command can have an optional "errors_to <address>" for a system filter,
986 or for a user filter if the address is the user's address. Accept the
987 syntax here - the check is later. */
991 if (command == logwrite_command)
993 int len = Ustrlen(buffer);
994 if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, "\n");
997 argument.u = string_copy(buffer);
999 if (command == save_command || command == logfile_command)
1003 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1004 second_argument.i = (int)Ustrtol(buffer, NULL, 8);
1006 else second_argument.i = -1;
1009 else if (command == deliver_command)
1011 uschar *save_ptr = ptr;
1012 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1013 if (Ustrcmp(buffer, "errors_to") == 0)
1015 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1016 second_argument.u = string_copy(buffer);
1018 else ptr = save_ptr;
1022 /* Set up the command block. Seen defaults TRUE for delivery commands,
1023 FALSE for logging commands, and it doesn't matter for testprint, as
1024 that doesn't change the "delivered" status. */
1026 if (*error_pointer != NULL) yield = FALSE; else
1028 new = store_get(sizeof(filter_cmd) + sizeof(union argtypes));
1031 *lastcmdptr = &(new->next);
1032 new->command = command;
1033 new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1034 new->noerror = noerror_force;
1035 new->args[0] = argument;
1036 new->args[1] = second_argument;
1042 /* Elif, else and endif just set a flag if expected. */
1047 if (seen_force || noerror_force)
1049 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1050 "near line %d is not followed by a command", line_number);
1054 if (expect_endif > 0)
1055 had_else_endif = (command == elif_command)? had_elif :
1056 (command == else_command)? had_else : had_endif;
1059 *error_pointer = string_sprintf("unexpected \"%s\" command near "
1060 "line %d of filter file", buffer, line_number);
1066 /* Defer, freeze, and fail are available only if permitted. */
1069 cmd_bit = RDO_DEFER;
1070 goto DEFER_FREEZE_FAIL;
1074 goto DEFER_FREEZE_FAIL;
1076 case freeze_command:
1077 cmd_bit = RDO_FREEZE;
1080 if ((filter_options & cmd_bit) == 0)
1082 *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1083 "near line %d of filter file", buffer, line_number);
1088 /* A text message can be provided after the "text" keyword, or
1089 as a string in quotes. */
1092 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1093 if (*saveptr != '\"' && (*buffer == 0 || Ustrcmp(buffer, "text") != 0))
1100 if (*saveptr != '\"')
1101 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1102 fmsg = string_copy(buffer);
1105 /* Drop through and treat as "finish", but never set "seen". */
1109 /* Finish has no arguments; fmsg defaults to NULL */
1111 case finish_command:
1112 new = store_get(sizeof(filter_cmd));
1115 *lastcmdptr = &(new->next);
1116 new->command = command;
1117 new->seen = seen_force? seen_value : FALSE;
1118 new->args[0].u = fmsg;
1122 /* Seen, unseen, and noerror are not allowed before if, which takes a
1123 condition argument and then and else sub-commands. */
1126 if (seen_force || noerror_force)
1128 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1129 "found before an \"if\" command near line %d",
1134 /* Set up the command block for if */
1136 new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1139 *lastcmdptr = &(new->next);
1140 new->command = command;
1142 new->args[0].u = NULL;
1143 new->args[1].u = new->args[2].u = NULL;
1144 new->args[3].u = ptr;
1146 /* Read the condition */
1148 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1149 if (*error_pointer != NULL) { yield = FALSE; break; }
1151 /* Read the commands to be obeyed if the condition is true */
1153 newlastcmdptr = &(new->args[1].f);
1154 if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1156 /* If commands were successfully read, handle the various possible
1157 terminators. There may be a number of successive "elif" sections. */
1161 while (had_else_endif == had_elif)
1163 filter_cmd *newnew =
1164 store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1165 new->args[2].f = newnew;
1168 new->command = command;
1170 new->args[0].u = NULL;
1171 new->args[1].u = new->args[2].u = NULL;
1172 new->args[3].u = ptr;
1174 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1175 if (*error_pointer != NULL) { yield = FALSE; break; }
1176 newlastcmdptr = &(new->args[1].f);
1177 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1181 if (yield == FALSE) break;
1183 /* Handle termination by "else", possibly following one or more
1184 "elsif" sections. */
1186 if (had_else_endif == had_else)
1188 newlastcmdptr = &(new->args[2].f);
1189 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1191 else if (had_else_endif != had_endif)
1193 *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1194 "filter file", line_number);
1199 /* Otherwise the terminator was "endif" - this is checked by
1200 read_command_list(). The pointer is already set to NULL. */
1203 /* Reset the terminator flag. */
1205 had_else_endif = had_neither;
1209 /* The mail & vacation commands have a whole slew of keyworded arguments.
1210 The final argument values are the file expand and return message booleans,
1211 whose offsets are defined in mailarg_index_{expand,return}. Although they
1212 are logically booleans, because they are stored in a uschar * value, we use
1213 NULL and not FALSE, to keep 64-bit compilers happy. */
1216 case vacation_command:
1217 new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes));
1219 new->command = command;
1220 new->seen = seen_force? seen_value : FALSE;
1221 new->noerror = noerror_force;
1222 for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1224 /* Read keyword/value pairs until we hit one that isn't. The data
1225 must contain only printing chars plus tab, though the "text" value
1226 can also contain newlines. The "file" keyword can be preceded by the
1227 word "expand", and "return message" has no data. */
1231 uschar *saveptr = ptr;
1232 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1233 if (*error_pointer != NULL)
1239 /* Ensure "return" is followed by "message"; that's a complete option */
1241 if (Ustrcmp(buffer, "return") == 0)
1243 new->args[mailarg_index_return].u = US""; /* not NULL => TRUE */
1244 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1245 if (Ustrcmp(buffer, "message") != 0)
1247 *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1248 " near line %d of filter file", line_number);
1255 /* Ensure "expand" is followed by "file", then fall through to process the
1258 if (Ustrcmp(buffer, "expand") == 0)
1260 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1261 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1262 if (Ustrcmp(buffer, "file") != 0)
1264 *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1265 " near line %d of filter file", line_number);
1271 /* Scan for the keyword */
1273 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1274 if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1276 /* Not found keyword; assume end of this command */
1278 if (i >= MAILARGS_STRING_COUNT)
1284 /* Found keyword, read the data item */
1286 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1287 if (*error_pointer != NULL)
1292 else new->args[i].u = string_copy(buffer);
1295 /* If this is the vacation command, apply some default settings to
1296 some of the arguments. */
1298 if (command == vacation_command)
1300 if (new->args[mailarg_index_file].u == NULL)
1302 new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1303 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1305 if (new->args[mailarg_index_log].u == NULL)
1306 new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1307 if (new->args[mailarg_index_once].u == NULL)
1308 new->args[mailarg_index_once].u = string_copy(US".vacation");
1309 if (new->args[mailarg_index_once_repeat].u == NULL)
1310 new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1311 if (new->args[mailarg_index_subject].u == NULL)
1312 new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1315 /* Join the address on to the chain of generated addresses */
1318 *lastcmdptr = &(new->next);
1322 /* Seen and unseen just set flags */
1325 case unseen_command:
1328 *error_pointer = string_sprintf("\"seen\" or \"unseen\" "
1329 "near line %d is not followed by a command", line_number);
1334 *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1335 "near line %d", line_number);
1338 seen_value = (command == seen_command);
1340 was_seen_or_unseen = TRUE;
1344 /* So does noerror */
1346 case noerror_command:
1349 *error_pointer = string_sprintf("\"noerror\" "
1350 "near line %d is not followed by a command", line_number);
1353 noerror_force = TRUE;
1361 *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1362 "near line %d of filter file", buffer, line_number);
1367 if (!was_seen_or_unseen && !was_noerror)
1370 noerror_force = FALSE;
1379 /*************************************************
1380 * Read a list of commands *
1381 *************************************************/
1383 /* If condional is TRUE, the list must be terminated
1384 by the words "else" or "endif".
1387 pptr points to pointer to next character; the pointer is updated
1388 lastcmdptr points to pointer to pointer to previously-read command; used
1389 for hanging on the new command
1390 conditional TRUE if this command is the subject of a condition
1392 Returns: TRUE on success
1396 read_command_list(uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1398 if (conditional) expect_endif++;
1399 had_else_endif = had_neither;
1400 while (**pptr != 0 && had_else_endif == had_neither)
1402 if (!read_command(pptr, lastcmdptr)) return FALSE;
1403 *pptr = nextsigchar(*pptr, TRUE);
1408 if (had_else_endif == had_neither)
1410 *error_pointer = US"\"endif\" missing at end of filter file";
1420 /*************************************************
1421 * Test a condition *
1422 *************************************************/
1426 c points to the condition block; c->testfor indicated whether
1427 it's a positive or negative condition
1428 toplevel TRUE if called from "if" directly; FALSE otherwise
1430 Returns: TRUE if the condition is met
1434 test_condition(condition_block *c, BOOL toplevel)
1438 uschar *exp[2], *p, *pp;
1439 const uschar *regcomp_error = NULL;
1440 int regcomp_error_offset;
1444 if (c == NULL) return TRUE; /* does this ever occur? */
1449 yield = test_condition(c->left.c, FALSE) &&
1450 *error_pointer == NULL &&
1451 test_condition(c->right.c, FALSE);
1455 yield = test_condition(c->left.c, FALSE) ||
1456 (*error_pointer == NULL &&
1457 test_condition(c->right.c, FALSE));
1460 /* The personal test is meaningless in a system filter. The tests are now in
1461 a separate function (so Sieve can use them). However, an Exim filter does not
1462 scan Cc: (hence the FALSE argument). */
1465 yield = system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1468 case cond_delivered:
1469 yield = filter_delivered;
1472 /* Only TRUE if a message is actually being processed; FALSE for address
1473 testing and verification. */
1476 yield = message_id[0] != 0 &&
1477 (sender_address == NULL || sender_address[0] == 0);
1480 /* Only FALSE if a message is actually being processed; TRUE for address
1481 and filter testing and verification. */
1483 case cond_firsttime:
1484 yield = filter_test != FTEST_NONE || message_id[0] == 0 || deliver_firsttime;
1487 /* Only TRUE if a message is actually being processed; FALSE for address
1488 testing and verification. */
1490 case cond_manualthaw:
1491 yield = message_id[0] != 0 && deliver_manual_thaw;
1494 /* The foranyaddress condition loops through a list of addresses */
1496 case cond_foranyaddress:
1498 pp = expand_string(p);
1501 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1502 "filter file: %s", p, expand_string_message);
1507 parse_allow_group = TRUE; /* Allow group syntax */
1512 int start, end, domain;
1515 p = parse_find_address_end(pp, FALSE);
1519 filter_thisaddress =
1520 parse_extract_address(pp, &error, &start, &end, &domain, FALSE);
1523 if (filter_thisaddress != NULL)
1525 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1526 (debug_selector & D_filter) != 0)
1529 debug_printf("Extracted address %s\n", filter_thisaddress);
1531 yield = test_condition(c->right.c, FALSE);
1535 if (saveend == 0) break;
1539 parse_allow_group = FALSE; /* Reset group syntax flags */
1540 parse_found_group = FALSE;
1543 /* All other conditions have left and right values that need expanding;
1544 on error, it doesn't matter what value is returned. */
1548 for (i = 0; i < 2; i++)
1550 exp[i] = expand_string(p);
1553 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1554 "filter file: %s", p, expand_string_message);
1560 /* Inner switch for the different cases */
1565 yield = strcmpic(exp[0], exp[1]) == 0;
1569 yield = Ustrcmp(exp[0], exp[1]) == 0;
1573 yield = strstric(exp[0], exp[1], FALSE) != NULL;
1577 yield = Ustrstr(exp[0], exp[1]) != NULL;
1581 yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1585 yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1591 int len = Ustrlen(exp[1]);
1592 uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1593 yield = (s < exp[0])? FALSE :
1594 ((c->type == cond_ends)? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1600 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1601 (debug_selector & D_filter) != 0)
1603 debug_printf("Match expanded arguments:\n");
1604 debug_printf(" Subject = %s\n", exp[0]);
1605 debug_printf(" Pattern = %s\n", exp[1]);
1608 re = pcre_compile(CS exp[1],
1609 PCRE_COPT | ((c->type == cond_matches)? PCRE_CASELESS : 0),
1610 (const char **)®comp_error, ®comp_error_offset, NULL);
1614 *error_pointer = string_sprintf("error while compiling "
1615 "regular expression \"%s\": %s at offset %d",
1616 exp[1], regcomp_error, regcomp_error_offset);
1620 yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1623 /* For above and below, convert the strings to numbers */
1627 for (i = 0; i < 2; i++)
1629 val[i] = get_number(exp[i], &yield);
1632 *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1637 yield = (c->type == cond_above)? (val[0] > val[1]) : (val[0] < val[1]);
1643 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1644 (debug_selector & D_filter) != 0)
1647 debug_printf("%sondition is %s: ",
1648 toplevel? "C" : "Sub-c",
1649 (yield == c->testfor)? "true" : "false");
1650 print_condition(c, TRUE);
1654 return yield == c->testfor;
1659 /*************************************************
1660 * Interpret chain of commands *
1661 *************************************************/
1663 /* In testing state, just say what would be done rather than doing it. The
1664 testprint command just expands and outputs its argument in testing state, and
1665 does nothing otherwise.
1668 commands points to chain of commands to interpret
1669 generated where to hang newly-generated addresses
1671 Returns: FF_DELIVERED success, a significant action was taken
1672 FF_NOTDELIVERED success, no significant action
1673 FF_DEFER defer requested
1674 FF_FAIL fail requested
1675 FF_FREEZE freeze requested
1676 FF_ERROR there was a problem
1680 interpret_commands(filter_cmd *commands, address_item **generated)
1685 BOOL condition_value;
1687 while (commands != NULL)
1690 uschar *fmsg, *ff_name;
1691 uschar *expargs[MAILARGS_STRING_COUNT];
1695 /* Expand the relevant number of arguments for the command that are
1698 for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1700 uschar *ss = commands->args[i].u;
1707 expargs[i] = expand_string(ss);
1708 if (expargs[i] == NULL)
1710 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1711 "%s command: %s", ss, command_list[commands->command],
1712 expand_string_message);
1718 /* Now switch for each command, setting the "delivered" flag if any of them
1721 if (commands->seen) filter_delivered = TRUE;
1723 switch(commands->command)
1726 for (i = 0; i < 2; i++)
1728 uschar *ss = expargs[i];
1731 if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1733 *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1734 "command", expargs[i]);
1738 /* Allow for "--" at the start of the value (from -$n0) for example */
1739 if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1741 n[i] = (int)Ustrtol(ss, &end, 0);
1744 *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1750 filter_n[n[1]] += n[0];
1751 if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
1754 /* A deliver command's argument must be a valid address. Its optional
1755 second argument (system filter only) must also be a valid address. */
1757 case deliver_command:
1758 for (i = 0; i < 2; i++)
1763 int start, end, domain;
1765 uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1768 expargs[i] = ((filter_options & RDO_REWRITE) != 0)?
1769 rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1770 rewrite_existflags) :
1771 rewrite_address_qualify(ss, TRUE);
1774 *error_pointer = string_sprintf("malformed address \"%s\" in "
1775 "filter file: %s", s, error);
1781 /* Stick the errors address into a simple variable, as it will
1782 be referenced a few times. Check that the caller is permitted to
1787 if (s != NULL && !system_filtering)
1789 uschar *ownaddress = expand_string(US"$local_part@$domain");
1790 if (strcmpic(ownaddress, s) != 0)
1792 *error_pointer = US"errors_to must point to the caller's address";
1797 /* Test case: report what would happen */
1799 if (filter_test != FTEST_NONE)
1802 printf("%seliver message to: %s%s%s%s\n",
1803 (commands->seen)? "D" : "Unseen d",
1805 commands->noerror? " (noerror)" : "",
1806 (s != NULL)? " errors_to " : "",
1807 (s != NULL)? s : US"");
1814 DEBUG(D_filter) debug_printf("Filter: %sdeliver message to: %s%s%s%s\n",
1815 (commands->seen)? "" : "unseen ",
1817 commands->noerror? " (noerror)" : "",
1818 (s != NULL)? " errors_to " : "",
1819 (s != NULL)? s : US"");
1821 /* Create the new address and add it to the chain, setting the
1822 af_ignore_error flag if necessary, and the errors address, which can be
1823 set in a system filter and to the local address in user filters. */
1825 addr = deliver_make_addr(expargs[0], TRUE); /* TRUE => copy s */
1826 addr->p.errors_address = (s == NULL)?
1827 s : string_copy(s); /* Default is NULL */
1828 if (commands->noerror) setflag(addr, af_ignore_error);
1829 addr->next = *generated;
1836 mode = commands->args[1].i;
1838 /* Test case: report what would happen */
1840 if (filter_test != FTEST_NONE)
1844 printf("%save message to: %s%s\n", (commands->seen)?
1845 "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1847 printf("%save message to: %s %04o%s\n", (commands->seen)?
1848 "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1851 /* Real case: Ensure save argument starts with / if there is a home
1852 directory to prepend. */
1856 if (s[0] != '/' && (filter_options & RDO_PREPEND_HOME) != 0 &&
1857 deliver_home != NULL && deliver_home[0] != 0)
1858 s = string_sprintf("%s/%s", deliver_home, s);
1859 DEBUG(D_filter) debug_printf("Filter: %ssave message to: %s%s\n",
1860 (commands->seen)? "" : "unseen ", s,
1861 commands->noerror? " (noerror)" : "");
1863 /* Create the new address and add it to the chain, setting the
1864 af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1867 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1868 setflag(addr, af_pfr|af_file);
1869 if (commands->noerror) setflag(addr, af_ignore_error);
1871 addr->next = *generated;
1877 s = string_copy(commands->args[0].u);
1878 if (filter_test != FTEST_NONE)
1881 printf("%sipe message to: %s%s\n", (commands->seen)?
1882 "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1884 else /* Ensure pipe command starts with | */
1886 DEBUG(D_filter) debug_printf("Filter: %spipe message to: %s%s\n",
1887 (commands->seen)? "" : "unseen ", s,
1888 commands->noerror? " (noerror)" : "");
1889 if (s[0] != '|') s = string_sprintf("|%s", s);
1891 /* Create the new address and add it to the chain, setting the
1892 af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1893 each command argument is expanded in the transport after the command
1894 has been split up into separate arguments. */
1896 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1897 setflag(addr, af_pfr|af_expand_pipe);
1898 if (commands->noerror) setflag(addr, af_ignore_error);
1899 addr->next = *generated;
1902 /* If there are any numeric variables in existence (e.g. after a regex
1903 condition), or if $thisaddress is set, take a copy for use in the
1904 expansion. Note that we can't pass NULL for filter_thisaddress, because
1905 NULL terminates the list. */
1907 if (expand_nmax >= 0 || filter_thisaddress != NULL)
1910 int ecount = (expand_nmax >= 0)? expand_nmax : -1;
1911 uschar **ss = store_get(sizeof(uschar *) * (ecount + 3));
1912 addr->pipe_expandn = ss;
1913 if (filter_thisaddress == NULL) filter_thisaddress = US"";
1914 *ss++ = string_copy(filter_thisaddress);
1915 for (i = 0; i <= expand_nmax; i++)
1916 *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1922 /* Set up the file name and mode, and close any previously open
1925 case logfile_command:
1926 log_mode = commands->args[1].i;
1927 if (log_mode == -1) log_mode = 0600;
1930 (void)close(log_fd);
1933 log_filename = expargs[0];
1934 if (filter_test != FTEST_NONE)
1937 printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1941 case logwrite_command:
1944 if (filter_test != FTEST_NONE)
1947 printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1948 string_printing(s));
1951 /* Attempt to write to a log file only if configured as permissible.
1952 Logging may be forcibly skipped for verifying or testing. */
1954 else if ((filter_options & RDO_LOG) != 0) /* Locked out */
1957 debug_printf("filter log command aborted: euid=%ld\n",
1958 (long int)geteuid());
1959 *error_pointer = US"logwrite command forbidden";
1962 else if ((filter_options & RDO_REALLOG) != 0)
1965 DEBUG(D_filter) debug_printf("writing filter log as euid %ld\n",
1966 (long int)geteuid());
1969 if (log_filename == NULL)
1971 *error_pointer = US"attempt to obey \"logwrite\" command "
1972 "without a previous \"logfile\"";
1975 log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1978 *error_pointer = string_open_failed(errno, "filter log file \"%s\"",
1984 if (write(log_fd, s, len) != len)
1986 *error_pointer = string_sprintf("write error on file \"%s\": %s",
1987 log_filename, strerror(errno));
1993 DEBUG(D_filter) debug_printf("skipping logwrite (verifying or testing)\n");
1997 /* Header addition and removal is available only in the system filter. The
1998 command is rejected at parse time otherwise. However "headers charset" is
1999 always permitted. */
2001 case headers_command:
2003 int subtype = commands->args[1].i;
2006 if (filter_test != FTEST_NONE)
2007 printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
2008 (subtype == FALSE)? "remove" : "charset", string_printing(s));
2010 if (subtype == TRUE)
2012 while (isspace(*s)) s++;
2015 header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')?
2017 header_last->type = header_checkname(header_last, FALSE);
2018 if (header_last->type >= 'a') header_last->type = htype_other;
2022 else if (subtype == FALSE)
2028 while ((ss = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
2030 header_remove(0, ss);
2033 /* This setting lasts only while the filter is running; on exit, the
2034 variable is reset to the previous value. */
2036 else headers_charset = s;
2040 /* Defer, freeze, and fail are available only when explicitly permitted.
2041 These commands are rejected at parse time otherwise. The message can get
2042 very long by the inclusion of message headers; truncate if it is, and also
2043 ensure printing characters so as not to mess up log files. */
2046 ff_name = US"defer";
2048 goto DEFERFREEZEFAIL;
2053 goto DEFERFREEZEFAIL;
2055 case freeze_command:
2056 ff_name = US"freeze";
2061 if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, " ... (truncated)");
2062 fmsg = string_printing(fmsg);
2063 *error_pointer = fmsg;
2065 if (filter_test != FTEST_NONE)
2068 printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2070 else DEBUG(D_filter) debug_printf("Filter: %s \"%s\"\n", ff_name, fmsg);
2073 case finish_command:
2074 if (filter_test != FTEST_NONE)
2077 printf("%sinish\n", (commands->seen)? "Seen f" : "F");
2081 DEBUG(D_filter) debug_printf("Filter: %sfinish\n",
2082 (commands->seen)? " Seen " : "");
2084 finish_obeyed = TRUE;
2085 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2089 uschar *save_address = filter_thisaddress;
2090 int ok = FF_DELIVERED;
2091 condition_value = test_condition(commands->args[0].c, TRUE);
2092 if (*error_pointer != NULL) ok = FF_ERROR; else
2095 ok = interpret_commands(commands->args[condition_value? 1:2].f,
2099 filter_thisaddress = save_address;
2100 if (finish_obeyed || (ok != FF_DELIVERED && ok != FF_NOTDELIVERED))
2106 /* To try to catch runaway loops, do not generate mail if the
2107 return path is unset or if a non-trusted user supplied -f <>
2108 as the return path. */
2111 case vacation_command:
2112 if (return_path == NULL || return_path[0] == 0)
2114 if (filter_test != FTEST_NONE)
2115 printf("%s command ignored because return_path is empty\n",
2116 command_list[commands->command]);
2117 else DEBUG(D_filter) debug_printf("%s command ignored because return_path "
2118 "is empty\n", command_list[commands->command]);
2122 /* Check the contents of the strings. The type of string can be deduced
2123 from the value of i.
2125 . If i is equal to mailarg_index_text it's a text string for the body,
2126 where anything goes.
2128 . If i is > mailarg_index_text, we are dealing with a file name, which
2129 cannot contain non-printing characters.
2131 . If i is less than mailarg_index_headers we are dealing with something
2132 that will go in a single message header line, where newlines must be
2133 followed by white space.
2135 . If i is equal to mailarg_index_headers, we have a string that contains
2136 one or more headers. Newlines that are not followed by white space must
2137 be followed by a header name.
2140 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
2143 uschar *s = expargs[i];
2145 if (s == NULL) continue;
2147 if (i != mailarg_index_text) for (p = s; *p != 0; p++)
2150 if (i > mailarg_index_text)
2152 if (!mac_isprint(c))
2154 *error_pointer = string_sprintf("non-printing character in \"%s\" "
2155 "in %s command", string_printing(s),
2156 command_list[commands->command]);
2161 /* i < mailarg_index_text */
2163 else if (c == '\n' && !isspace(p[1]))
2165 if (i < mailarg_index_headers)
2167 *error_pointer = string_sprintf("\\n not followed by space in "
2168 "\"%.1024s\" in %s command", string_printing(s),
2169 command_list[commands->command]);
2173 /* Check for the start of a new header line within the string */
2178 for (pp = p + 1;; pp++)
2181 if (c == ':' && pp != p + 1) break;
2182 if (c == 0 || c == ':' || isspace(*pp))
2184 *error_pointer = string_sprintf("\\n not followed by space or "
2185 "valid header name in \"%.1024s\" in %s command",
2186 string_printing(s), command_list[commands->command]);
2193 } /* Loop to scan the string */
2195 /* The string is OK */
2197 commands->args[i].u = s;
2200 /* Proceed with mail or vacation command */
2202 if (filter_test != FTEST_NONE)
2204 uschar *to = commands->args[mailarg_index_to].u;
2206 printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2207 (to == NULL)? US"<default>" : to,
2208 (commands->command == vacation_command)? " (vacation)" : "",
2209 (commands->noerror)? " (noerror)" : "");
2210 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2212 uschar *arg = commands->args[i].u;
2215 int len = Ustrlen(mailargs[i]);
2216 int indent = (debug_selector != 0)? output_indent : 0;
2217 while (len++ < 7 + indent) printf(" ");
2218 printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2219 (commands->args[mailarg_index_expand].u != NULL &&
2220 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2223 if (commands->args[mailarg_index_return].u != NULL)
2224 printf("Return original message\n");
2229 uschar *log_addr = NULL;
2230 uschar *to = commands->args[mailarg_index_to].u;
2235 if (to == NULL) to = expand_string(US"$reply_address");
2236 while (isspace(*to)) to++;
2238 for (tt = to; *tt != 0; tt++) /* Get rid of newlines */
2239 if (*tt == '\n') *tt = ' ';
2243 debug_printf("Filter: %smail to: %s%s%s\n",
2244 (commands->seen)? "seen " : "",
2246 (commands->command == vacation_command)? " (vacation)" : "",
2247 (commands->noerror)? " (noerror)" : "");
2248 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2250 uschar *arg = commands->args[i].u;
2253 int len = Ustrlen(mailargs[i]);
2254 while (len++ < 15) debug_printf(" ");
2255 debug_printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2256 (commands->args[mailarg_index_expand].u != NULL &&
2257 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2262 /* Create the "address" for the autoreply. This is used only for logging,
2263 as the actual recipients are extracted from the To: line by -t. We use the
2264 same logic here to extract the working addresses (there may be more than
2265 one). Just in case there are a vast number of addresses, stop when the
2266 string gets too long. */
2271 uschar *ss = parse_find_address_end(tt, FALSE);
2272 uschar *recipient, *errmess;
2273 int start, end, domain;
2277 recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
2281 /* Ignore empty addresses and errors; an error will occur later if
2282 there's something really bad. */
2284 if (recipient != NULL)
2286 log_addr = string_cat(log_addr, &size, &ptr,
2287 (log_addr == NULL)? US">" : US",", 1);
2288 log_addr = string_cat(log_addr, &size, &ptr, recipient,
2289 Ustrlen(recipient));
2296 log_addr = string_cat(log_addr, &size, &ptr, US", ...", 5);
2300 /* Move on past this address */
2302 tt = ss + (*ss? 1:0);
2303 while (isspace(*tt)) tt++;
2306 if (log_addr == NULL)
2308 log_addr = string_sprintf(">**bad-reply**");
2309 badflag = af_bad_reply;
2311 else log_addr[ptr] = 0;
2313 addr = deliver_make_addr(log_addr, FALSE);
2314 setflag(addr, (af_pfr|badflag));
2315 if (commands->noerror) setflag(addr, af_ignore_error);
2316 addr->next = *generated;
2318 addr->reply = store_get(sizeof(reply_item));
2319 addr->reply->from = NULL;
2320 addr->reply->to = string_copy(to);
2321 addr->reply->file_expand =
2322 commands->args[mailarg_index_expand].u != NULL;
2323 addr->reply->expand_forbid = expand_forbid;
2324 addr->reply->return_message =
2325 commands->args[mailarg_index_return].u != NULL;
2326 addr->reply->once_repeat = 0;
2328 if (commands->args[mailarg_index_once_repeat].u != NULL)
2330 addr->reply->once_repeat =
2331 readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2333 if (addr->reply->once_repeat < 0)
2335 *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2336 "in mail or vacation command: %s",
2337 commands->args[mailarg_index_once_repeat]);
2342 /* Set up all the remaining string arguments (those other than "to") */
2344 for (i = 1; i < mailargs_string_passed; i++)
2346 uschar *ss = commands->args[i].u;
2347 *((uschar **)(((uschar *)(addr->reply)) + reply_offsets[i])) =
2348 (ss == NULL)? NULL : string_copy(ss);
2353 case testprint_command:
2354 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2356 uschar *s = string_printing(expargs[0]);
2357 if (filter_test == FTEST_NONE)
2358 debug_printf("Filter: testprint: %s\n", s);
2360 printf("Testprint: %s\n", s);
2364 commands = commands->next;
2367 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2372 /*************************************************
2373 * Test for a personal message *
2374 *************************************************/
2376 /* This function is global so that it can also be called from the code that
2377 implements Sieve filters.
2380 aliases a chain of aliases
2381 scan_cc TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2383 Returns: TRUE if the message is deemed to be personal
2387 filter_personal(string_item *aliases, BOOL scan_cc)
2389 uschar *self, *self_from, *self_to;
2390 uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL;
2391 void *reset_point = store_get(0);
2397 /* If any header line in the message is a defined "List-" header field, it is
2398 not a personal message. We used to check for any header line that started with
2399 "List-", but this was tightened up for release 4.54. The check is now for
2400 "List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
2401 Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
2402 defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
2403 contain any value other than "no", the message is not personal (RFC 3834).
2404 Previously the test was for "auto-". */
2406 for (h = header_list; h != NULL; h = h->next)
2409 if (h->type == htype_old) continue;
2411 if (strncmpic(h->text, US"List-", 5) == 0)
2414 if (strncmpic(s, US"Id:", 3) == 0 ||
2415 strncmpic(s, US"Help:", 5) == 0 ||
2416 strncmpic(s, US"Subscribe:", 10) == 0 ||
2417 strncmpic(s, US"Unsubscribe:", 12) == 0 ||
2418 strncmpic(s, US"Post:", 5) == 0 ||
2419 strncmpic(s, US"Owner:", 6) == 0 ||
2420 strncmpic(s, US"Archive:", 8) == 0)
2424 else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
2427 while (isspace(*s)) s++;
2428 if (strncmpic(s, US"no", 2) != 0) return FALSE;
2430 while (isspace(*s)) s++;
2431 if (*s != 0) return FALSE;
2435 /* Set up "my" address */
2437 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2438 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2439 global_rewrite_rules);
2440 self_to = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2441 global_rewrite_rules);
2444 if (self_from == NULL) self_from = self;
2445 if (self_to == NULL) self_to = self;
2447 /* If there's a prefix or suffix set, we must include the prefixed/
2448 suffixed version of the local part in the tests. */
2450 if (deliver_localpart_prefix != NULL || deliver_localpart_suffix != NULL)
2452 psself = string_sprintf("%s%s%s@%s",
2453 (deliver_localpart_prefix == NULL)? US"" : deliver_localpart_prefix,
2455 (deliver_localpart_suffix == NULL)? US"" : deliver_localpart_suffix,
2457 psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2458 global_rewrite_rules);
2459 psself_to = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2460 global_rewrite_rules);
2461 if (psself_from == NULL) psself_from = psself;
2462 if (psself_to == NULL) psself_to = psself;
2467 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2471 header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2475 header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2478 header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2484 header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2485 "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2486 "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2488 header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2490 (sender_address == NULL || sender_address[0] != 0);
2492 store_reset(reset_point);
2498 /*************************************************
2499 * Interpret a mail filter file *
2500 *************************************************/
2504 filter points to the entire file, read into store as a single string
2505 options controls whether various special things are allowed, and requests
2507 generated where to hang newly-generated addresses
2508 error where to pass back an error text
2510 Returns: FF_DELIVERED success, a significant action was taken
2511 FF_NOTDELIVERED success, no significant action
2512 FF_DEFER defer requested
2513 FF_FAIL fail requested
2514 FF_FREEZE freeze requested
2515 FF_ERROR there was a problem
2519 filter_interpret(uschar *filter, int options, address_item **generated,
2523 int yield = FF_ERROR;
2524 uschar *ptr = filter;
2525 uschar *save_headers_charset = headers_charset;
2526 filter_cmd *commands = NULL;
2527 filter_cmd **lastcmdptr = &commands;
2529 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2531 /* Initialize "not in an if command", set the global flag that is always TRUE
2532 while filtering, and zero the variables. */
2536 filter_running = TRUE;
2537 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2539 /* To save having to pass certain values about all the time, make them static.
2540 Also initialize the line number, for error messages, and the log file
2543 filter_options = options;
2544 filter_delivered = FALSE;
2545 finish_obeyed = FALSE;
2546 error_pointer = error;
2547 *error_pointer = NULL;
2551 log_filename = NULL;
2553 /* Scan filter file for syntax and build up an interpretation thereof, and
2554 interpret the compiled commands, and if testing, say whether we ended up
2555 delivered or not, unless something went wrong. */
2558 ptr = nextsigchar(ptr, TRUE);
2560 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2561 yield = interpret_commands(commands, generated);
2563 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2569 s = US"Filtering ended by \"defer\".";
2573 s = US"Filtering ended by \"freeze\".";
2577 s = US"Filtering ended by \"fail\".";
2581 s = US"Filtering set up at least one significant delivery "
2582 "or other action.\n"
2583 "No other deliveries will occur.";
2586 case FF_NOTDELIVERED:
2587 s = US"Filtering did not set up a significant delivery.\n"
2588 "Normal delivery will occur.";
2592 s = string_sprintf("Filter error: %s", *error);
2596 if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2597 else debug_printf("%s\n", s);
2600 /* Close the log file if it was opened, and kill off any numerical variables
2601 before returning. Reset the header decoding charset. */
2603 if (log_fd >= 0) (void)close(log_fd);
2605 filter_running = FALSE;
2606 headers_charset = save_headers_charset;
2608 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2613 /* End of filter.c */