From 1eccaa59eb366c180c36af219a142d8f934f73b0 Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Tue, 10 Oct 2006 15:36:50 +0000 Subject: Sort out group syntax problems, particularly with verify=header_sender. --- src/src/parse.c | 15 ++++++---- src/src/receive.c | 13 ++++---- src/src/sieve.c | 4 ++- src/src/verify.c | 88 ++++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 81 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/src/parse.c b/src/src/parse.c index a0366431e..0c1b9fe8f 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/parse.c,v 1.9 2006/03/08 11:13:07 ph10 Exp $ */ +/* $Cambridge: exim/src/src/parse.c,v 1.10 2006/10/10 15:36:50 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -597,10 +597,15 @@ which may appear in certain headers. If the flag parse_allow_group is set TRUE and parse_found_group is FALSE when this function is called, an address which is the start of a group (i.e. preceded by a phrase and a colon) is recognized; the phrase is ignored and the flag parse_found_group is set. If -this flag is TRUE at the end of an address, then if an extraneous semicolon is -found, it is ignored and the flag is cleared. This logic is used only when -scanning through addresses in headers, either to fulfil the -t option or for -rewriting or checking header syntax. +this flag is TRUE at the end of an address, and if an extraneous semicolon is +found, it is ignored and the flag is cleared. + +This logic is used only when scanning through addresses in headers, either to +fulfil the -t option, or for rewriting, or for checking header syntax. Because +the group "state" has to be remembered between multiple calls of this function, +the variables parse_{allow,found}_group are global. It is important to ensure +that they are reset to FALSE at the end of scanning a header's list of +addresses. Arguments: mailbox points to the RFC822 mailbox diff --git a/src/src/receive.c b/src/src/receive.c index 797444ca1..73675bee2 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.29 2006/09/25 10:14:20 ph10 Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.30 2006/10/10 15:36:50 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -2051,8 +2051,6 @@ if (extract_recip) recipients_count = recipients_list_max = 0; } - parse_allow_group = TRUE; /* Allow address group syntax */ - /* Now scan the headers */ for (h = header_list->next; h != NULL; h = h->next) @@ -2063,6 +2061,8 @@ if (extract_recip) uschar *s = Ustrchr(h->text, ':') + 1; while (isspace(*s)) s++; + parse_allow_group = TRUE; /* Allow address group syntax */ + while (*s != 0) { uschar *ss = parse_find_address_end(s, FALSE); @@ -2127,7 +2127,10 @@ if (extract_recip) s = ss + (*ss? 1:0); while (isspace(*s)) s++; - } + } /* Next address */ + + parse_allow_group = FALSE; /* Reset group syntax flags */ + parse_found_group = FALSE; /* If this was the bcc: header, mark it "old", which means it will be kept on the spool, but not transmitted as part of the @@ -2137,8 +2140,6 @@ if (extract_recip) } /* For appropriate header line */ } /* For each header line */ - parse_allow_group = FALSE; /* Reset group syntax flags */ - parse_found_group = FALSE; } /* Now build the unique message id. This has changed several times over the diff --git a/src/src/sieve.c b/src/src/sieve.c index 425a0b9e0..549dba197 100644 --- a/src/src/sieve.c +++ b/src/src/sieve.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/sieve.c,v 1.22 2006/09/05 14:05:43 ph10 Exp $ */ +/* $Cambridge: exim/src/src/sieve.c,v 1.23 2006/10/10 15:36:50 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -1826,6 +1826,8 @@ if (parse_identifier(filter,CUS "address")) if (saveend == 0) break; header_value = end_addr + 1; } + parse_allow_group = FALSE; + parse_found_group = FALSE; } } return 1; diff --git a/src/src/verify.c b/src/src/verify.c index 4f0da9bbd..5b635989e 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/verify.c,v 1.42 2006/10/09 14:36:25 ph10 Exp $ */ +/* $Cambridge: exim/src/src/verify.c,v 1.43 2006/10/10 15:36:50 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -1451,8 +1451,9 @@ verify_check_headers(uschar **msgptr) { header_line *h; uschar *colon, *s; +int yield = OK; -for (h = header_list; h != NULL; h = h->next) +for (h = header_list; h != NULL && yield == OK; h = h->next) { if (h->type != htype_from && h->type != htype_reply_to && @@ -1466,9 +1467,10 @@ for (h = header_list; h != NULL; h = h->next) s = colon + 1; while (isspace(*s)) s++; - parse_allow_group = TRUE; /* Allow group syntax */ + /* Loop for multiple addresses in the header, enabling group syntax. Note + that we have to reset this after the header has been scanned. */ - /* Loop for multiple addresses in the header */ + parse_allow_group = TRUE; while (*s != 0) { @@ -1478,7 +1480,7 @@ for (h = header_list; h != NULL; h = h->next) int start, end, domain; /* Temporarily terminate the string at this point, and extract the - operative address within. */ + operative address within, allowing group syntax. */ *ss = 0; recipient = parse_extract_address(s,&errmess,&start,&end,&domain,FALSE); @@ -1534,7 +1536,8 @@ for (h = header_list; h != NULL; h = h->next) string_sprintf("%s: failing address in \"%.*s:\" header %s: %.*s", errmess, tt - h->text, h->text, verb, len, s)); - return FAIL; + yield = FAIL; + break; /* Out of address loop */ } /* Advance to the next address */ @@ -1542,9 +1545,12 @@ for (h = header_list; h != NULL; h = h->next) s = ss + (terminator? 1:0); while (isspace(*s)) s++; } /* Next address */ - } /* Next header */ -return OK; + parse_allow_group = FALSE; + parse_found_group = FALSE; + } /* Next header unless yield has been set FALSE */ + +return yield; } @@ -1587,9 +1593,10 @@ for (i = 0; i < recipients_count; i++) s = colon + 1; while (isspace(*s)) s++; - parse_allow_group = TRUE; /* Allow group syntax */ + /* Loop for multiple addresses in the header, enabling group syntax. Note + that we have to reset this after the header has been scanned. */ - /* Loop for multiple addresses in the header */ + parse_allow_group = TRUE; while (*s != 0) { @@ -1599,7 +1606,7 @@ for (i = 0; i < recipients_count; i++) int start, end, domain; /* Temporarily terminate the string at this point, and extract the - operative address within. */ + operative address within, allowing group syntax. */ *ss = 0; recipient = parse_extract_address(s,&errmess,&start,&end,&domain,FALSE); @@ -1623,6 +1630,9 @@ for (i = 0; i < recipients_count; i++) s = ss + (terminator? 1:0); while (isspace(*s)) s++; } /* Next address */ + + parse_allow_group = FALSE; + parse_found_group = FALSE; } /* Next header (if found is false) */ if (!found) return FAIL; @@ -1705,13 +1715,14 @@ verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr, uschar *pm_mailfrom, int options, int *verrno) { static int header_types[] = { htype_sender, htype_reply_to, htype_from }; +BOOL done = FALSE; int yield = FAIL; int i; -for (i = 0; i < 3; i++) +for (i = 0; i < 3 && !done; i++) { header_line *h; - for (h = header_list; h != NULL; h = h->next) + for (h = header_list; h != NULL && !done; h = h->next) { int terminator, new_ok; uschar *s, *ss, *endname; @@ -1719,6 +1730,11 @@ for (i = 0; i < 3; i++) if (h->type != header_types[i]) continue; s = endname = Ustrchr(h->text, ':') + 1; + /* Scan the addresses in the header, enabling group syntax. Note that we + have to reset this after the header has been scanned. */ + + parse_allow_group = TRUE; + while (*s != 0) { address_item *vaddr; @@ -1761,11 +1777,21 @@ for (i = 0; i < 3; i++) else { int start, end, domain; - uschar *address = parse_extract_address(s, log_msgptr, &start, - &end, &domain, FALSE); + uschar *address = parse_extract_address(s, log_msgptr, &start, &end, + &domain, FALSE); *ss = terminator; + /* If we found an empty address, just carry on with the next one, but + kill the message. */ + + if (address == NULL && Ustrcmp(*log_msgptr, "empty address") == 0) + { + *log_msgptr = NULL; + s = ss; + continue; + } + /* If verification failed because of a syntax error, fail this function, and ensure that the failing address gets added to the error message. */ @@ -1773,14 +1799,13 @@ for (i = 0; i < 3; i++) if (address == NULL) { new_ok = FAIL; - if (*log_msgptr != NULL) - { - while (ss > s && isspace(ss[-1])) ss--; - *log_msgptr = string_sprintf("syntax error in '%.*s' header when " - "scanning for sender: %s in \"%.*s\"", - endname - h->text, h->text, *log_msgptr, ss - s, s); - return FAIL; - } + while (ss > s && isspace(ss[-1])) ss--; + *log_msgptr = string_sprintf("syntax error in '%.*s' header when " + "scanning for sender: %s in \"%.*s\"", + endname - h->text, h->text, *log_msgptr, ss - s, s); + yield = FAIL; + done = TRUE; + break; } /* Else go ahead with the sender verification. But it isn't *the* @@ -1814,15 +1839,24 @@ for (i = 0; i < 3; i++) /* Success or defer */ - if (new_ok == OK) return OK; + if (new_ok == OK) + { + yield = OK; + done = TRUE; + break; + } + if (new_ok == DEFER) yield = DEFER; /* Move on to any more addresses in the header */ s = ss; - } - } - } + } /* Next address */ + + parse_allow_group = FALSE; + parse_found_group = FALSE; + } /* Next header, unless done */ + } /* Next header type unless done */ if (yield == FAIL && *log_msgptr == NULL) *log_msgptr = US"there is no valid sender in any header line"; -- cgit v1.2.3