From 1efe178fac47bb1fa7dbacc46c1871553b7e85a4 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 18 Dec 2024 14:12:12 +0000 Subject: [PATCH 1/1] Cutthrough: support a transport dkim_domain that expands to empty --- doc/doc-docbook/spec.xfpt | 4 ++++ src/Makefile | 9 +++++++-- src/src/expand.c | 33 ++++++++++++++++++++++++++------- src/src/functions.h | 1 + src/src/verify.c | 12 +++++++----- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 31aafa4be..d4e0d6d4f 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -170,6 +170,8 @@ . --- ID that ties them together. . --- The index entry points to the most-recent chapter head, section or subsection . --- head, or list-item. +. ---- It'd be a lot nicer to point to the precise word-location; a chapter +. ---- can be pretty big. .macro cindex && @@ -1269,6 +1271,8 @@ one of the checks to be performed in an ACL for incoming messages, on both sender and recipient addresses, and it can be tested using the &%-bv%& and &%-bvs%& command line options. +.cindex router "verify mode" +.cindex "verify mode" routers When an address is being verified, the routers are run in &"verify mode"&. This does not affect the way the routers work, but it is a state that can be detected. By this means, a router can be skipped or made to behave differently diff --git a/src/Makefile b/src/Makefile index a6e0de9f4..5e82de271 100644 --- a/src/Makefile +++ b/src/Makefile @@ -102,12 +102,17 @@ clean_exim:; cd build-$(buildname); \ done; \ $(RM_COMMAND) -fr dynmodules -clean: clean_exim +clean-doc: FRC + cd ../doc/doc-docbook; \ + $(RM_COMMAND) {filter,spec}*.{pdf,ps,txt,html,xml} + +clean: clean_exim clean_doc @echo ""; echo '*** "make clean" just removes all .o and .a files' @echo '*** Use "make makefile" to force a rebuild of the makefile' @echo "" -distclean:; $(RM_COMMAND) -rf build-* cscope* +distclean: clean_doc + $(RM_COMMAND) -rf build-* cscope* cscope.files: FRC echo "-q" > $@ diff --git a/src/src/expand.c b/src/src/expand.c index b290720aa..31420d59f 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -4601,13 +4601,14 @@ and, given the acl condition, ${if }. This is an unfortunate consequence of string expansion becoming too powerful. Arguments: - string the string to be expanded + s the string to be expanded flags brace_ends expansion is to stop at } honour_dollar TRUE if $ is to be expanded, FALSE if it's just another character skipping TRUE for recursive calls when the value isn't actually going to be used (to allow for optimisation) + exists_only return as soon as we have a char, for optimisation left if not NULL, a pointer to the first character after the expansion is placed here (typically used with brace_ends) resetok_p if not NULL, pointer to flag - write FALSE if unsafe to reset @@ -4621,13 +4622,13 @@ Returns: NULL if expansion fails: */ static uschar * -expand_string_internal(const uschar * string, esi_flags flags, const uschar ** left, +expand_string_internal(const uschar * s, esi_flags flags, const uschar ** left, BOOL *resetok_p, BOOL * textonly_p) { rmark reset_point = store_mark(); -gstring * yield = string_get(Ustrlen(string) + 64); +gstring * yield = NULL; int item_type; -const uschar * s = string; +const uschar * orig_string = s; const uschar * save_expand_nstring[EXPAND_MAXN+1]; int save_expand_nlength[EXPAND_MAXN+1]; BOOL resetok = TRUE, first = TRUE, textonly = TRUE; @@ -4636,7 +4637,7 @@ expand_level++; f.expand_string_forcedfail = FALSE; expand_string_message = US""; -if (is_tainted(string)) +if (is_tainted(s)) { expand_string_message = string_sprintf("attempt to expand tainted string '%s'", s); @@ -4644,10 +4645,17 @@ if (is_tainted(string)) goto EXPAND_FAILED; } + { + int len = Ustrlen(s); + if (len) yield = string_get(len + 64); + } + while (*s) { uschar name[256]; + if (flags & ESI_EXISTS_ONLY && gstring_length(yield) > 0) break; + DEBUG(D_expand) { debug_printf_indent("%V%V%s: %W\n", @@ -8491,7 +8499,7 @@ left != NULL, return a pointer to the terminator. */ BOOL tainted = is_tainted(res); debug_printf_indent("%Vexpanded: %.*W\n", "K---", - (int)(s - string), string); + (int)(s - orig_string), orig_string); debug_printf_indent("%Vresult: ", flags & ESI_SKIPPING ? "K-----" : "\\_____"); if (*res || !(flags & ESI_SKIPPING)) @@ -8533,7 +8541,7 @@ EXPAND_FAILED: if (left) *left = s; DEBUG(D_expand) { - debug_printf_indent("%Vfailed to expand: %s\n", "K", string); + debug_printf_indent("%Vfailed to expand: %s\n", "K", orig_string); debug_printf_indent("%Verror message: %s\n", f.expand_string_forcedfail ? "K---" : "\\___", expand_string_message); if (f.expand_string_forcedfail) @@ -8584,6 +8592,17 @@ expand_string(uschar * string) { return US expand_string_2(CUS string, NULL); } +/* Just return whether the string is non-empty after expansion */ + +BOOL +expand_string_nonempty(const uschar * string) +{ +const uschar * s; +if (!string) return FALSE; +s = expand_string_internal(string, ESI_HONOR_DOLLAR | ESI_EXISTS_ONLY, + NULL, NULL, NULL); +return s && *s; +} diff --git a/src/src/functions.h b/src/src/functions.h index ee6b1ff2d..21c3eecb6 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -235,6 +235,7 @@ extern uschar *expand_file_big_buffer(const uschar *); extern uschar *expand_string(uschar *); /* public, cannot make const */ extern const uschar *expand_string_2(const uschar *, BOOL *); extern const uschar *expand_cstring(const uschar *); /* ... so use this one */ +extern BOOL expand_string_nonempty(const uschar *); extern uschar *expand_getkeyed(const uschar *, const uschar *); extern uschar *expand_hide_passwords(uschar * ); diff --git a/src/src/verify.c b/src/src/verify.c index b48d17ee5..cfd4eadc9 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -1115,22 +1115,24 @@ no_conn: if (cutthrough.delivery) { - if (addr->transport->filter_command) + if (expand_string_nonempty(addr->transport->filter_command)) { cutthrough.delivery= FALSE; HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n"); } #ifndef DISABLE_DKIM - /* DKIM signing needs to add a header after seeing the whole body, so we cannot just copy - body bytes to the outbound as they are received, which is the intent of cutthrough. */ - if (ob->dkim.dkim_domain) + /* DKIM signing needs to add a header after seeing the whole body, so we + cannot just copy body bytes to the outbound as they are received, which is + the intent of cutthrough. */ + if (expand_string_nonempty(ob->dkim.dkim_domain)) { cutthrough.delivery= FALSE; HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n"); } #endif #ifdef EXPERIMENTAL_ARC - if (ob->arc_sign) + /* ARC has the same issue as DKIM above */ + if (expand_string_nonempty(ob->arc_sign)) { cutthrough.delivery= FALSE; HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of ARC signing\n"); -- 2.30.2