From 40feafaedc29f38400e27a81ebc88f1e188dc648 Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Thu, 23 Jan 2020 19:09:07 +0100 Subject: [PATCH 1/3] Make expand_string process whole list, not each element If the whole list is expanded before the list is split, it enables inclusion of expandos that themselves are lists. The original behaviour would result in such expandos to be treated as one header instead of the list it should have been. --- src/src/transport.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/src/transport.c b/src/src/transport.c index ed3dcf0af7..4dead8f9b8 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -727,16 +727,17 @@ for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old) { int sep = ':'; /* This is specified as a colon-separated list */ uschar *s, *ss; + /* expand the list first, so we can include expandos that return lists too */ + if (i == 0) + if (!(list = expand_string(list)) && !f.expand_string_forcedfail) + { + errno = ERRNO_CHHEADER_FAIL; + return FALSE; + } while ((s = string_nextinlist(&list, &sep, NULL, 0))) { int len; - if (i == 0) - if (!(s = expand_string(s)) && !f.expand_string_forcedfail) - { - errno = ERRNO_CHHEADER_FAIL; - return FALSE; - } len = s ? Ustrlen(s) : 0; if (strncmpic(h->text, s, len) != 0) continue; ss = h->text + len; From d056a6947e71ed903ef7ff9159553a7cec3d6ff2 Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Thu, 23 Jan 2020 19:13:39 +0100 Subject: [PATCH 2/3] Implement use of * as a suffix in headers_remove The ability to use * as a suffix in removal of headers fixes https://bugs.exim.org/show_bug.cgi?id=159 If one of the headers to remove ends in *, the header checked is removed if it matches the prefix (header without the *) --- src/src/transport.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/src/transport.c b/src/src/transport.c index 4dead8f9b8..0ce5e8b326 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -739,10 +739,17 @@ for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old) int len; len = s ? Ustrlen(s) : 0; - if (strncmpic(h->text, s, len) != 0) continue; - ss = h->text + len; - while (*ss == ' ' || *ss == '\t') ss++; - if (*ss == ':') break; + if (len && s[len-1] == '*') + { + if (strncmpic(h->text, s, len-1) == 0) break; + } + else + { + if (strncmpic(h->text, s, len) != 0) continue; + ss = h->text + len; + while (*ss == ' ' || *ss == '\t') ss++; + if (*ss == ':') break; + } } if (s) { include_header = FALSE; break; } } From 84bcb93d1ec195cf7931c70e782e716d3210ef0e Mon Sep 17 00:00:00 2001 From: Peder Stray Date: Thu, 23 Jan 2020 19:29:32 +0100 Subject: [PATCH 3/3] Update relevant parts of documentation for headers_remove fix --- doc/doc-docbook/spec.xfpt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index ed00537775..53fc7dc807 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -8119,9 +8119,6 @@ domain, host, address and local part lists. .cindex "expansion" "of lists" Each list is expanded as a single string before it is used. -&'Exception: the router headers_remove option, where list-item -splitting is done before string-expansion.'& - The result of expansion must be a list, possibly containing empty items, which is split up into separate items for matching. By default, colon is the separator character, @@ -18647,7 +18644,8 @@ avoided. The &%repeat_use%& option of the &%redirect%& router may be of help. This option specifies a list of text headers, colon-separated (by default, changeable in the usual way &<>&), that is associated with any addresses that are accepted by the router. -Each item is separately expanded, at routing time. However, this +The whole list is expanded before splitting, at routing time. If an item +ends in *, it will match any header with the same prefix. However, this option has no effect when an address is just being verified. The way in which the text is used to remove header lines at transport time is described in section &<>&. Header lines are not actually removed until