Cutthrough: support a transport dkim_domain that expands to empty master
authorJeremy Harris <jgh146exb@wizmail.org>
Wed, 18 Dec 2024 14:12:12 +0000 (14:12 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Wed, 18 Dec 2024 14:12:12 +0000 (14:12 +0000)
doc/doc-docbook/spec.xfpt
src/Makefile
src/src/expand.c
src/src/functions.h
src/src/verify.c

index 31aafa4beeda259ffb6f0942d035637d7fbc5001..d4e0d6d4f2fb7b19bafc9746c9652d4a73cab3fd 100644 (file)
 . --- 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
 &<indexterm role="concept">&
@@ -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
index a6e0de9f452062056da658fe7e78716db0ab71a6..5e82de27120790b3b5f91d0f79d2c4aa65c83e7d 100644 (file)
@@ -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" > $@
index b290720aa924548dcc2f775dd27743e0aa15a2e3..31420d59fcaf49f3b399b82caeb58f52fba09f91 100644 (file)
@@ -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;
+}
 
 
 
index ee6b1ff2d24e46ec448a5d2ac13af36135271c9b..21c3eecb6b56261e879474a2721cb29e75b4c633 100644 (file)
@@ -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 * );
index b48d17ee5b6c40b0d4e3e7a86921e2ec26336046..cfd4eadc93fd802ccf3aeb9e53944ccc840fabd5 100644 (file)
@@ -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");