SPDX: license tags (mostly by guesswork)
[exim.git] / src / src / rewrite.c
index 6a6da47dfa0c70d4e3265fb85a033efe5a4f0a23..040525ec52a542b95e9bc569b5697bf420d08346 100644 (file)
@@ -2,8 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2021 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-only */
 
 /* Functions concerned with rewriting headers */
 
@@ -135,7 +137,8 @@ for (rewrite_rule * rule = rewrite_rules;
 
   if (flag & rewrite_smtp)
     {
-    uschar *key = expand_string(rule->key);
+    BOOL textonly_re;
+    const uschar * key = expand_string_2(rule->key, &textonly_re);
     if (!key)
       {
       if (!f.expand_string_forcedfail)
@@ -143,7 +146,8 @@ for (rewrite_rule * rule = rewrite_rules;
           "checking for SMTP rewriting: %s", rule->key, expand_string_message);
       continue;
       }
-    if (match_check_string(subject, key, 0, TRUE, FALSE, FALSE, NULL) != OK)
+    if (match_check_string(subject, key, 0,
+      textonly_re ? MCS_CACHEABLE | MCS_PARTIAL : MCS_PARTIAL, NULL) != OK)
       continue;
     new = expand_string(rule->replacement);
     }
@@ -453,7 +457,7 @@ uschar *s = Ustrchr(h->text, ':') + 1;
 while (isspace(*s)) s++;
 
 DEBUG(D_rewrite)
-  debug_printf("rewrite_one_header: type=%c:\n  %s", h->type, h->text);
+  debug_printf_indent("rewrite_one_header: type=%c:\n  %s", h->type, h->text);
 
 f.parse_allow_group = TRUE;     /* Allow group syntax */
 
@@ -483,7 +487,7 @@ while (*s)
   recipient = parse_extract_address(s, &errmess, &start, &end, &domain, FALSE);
   *ss = terminator;
   sprev = s;
-  s = ss + (terminator ? 1 :0);
+  s = ss + (terminator ? 1 : 0);
   while (isspace(*s)) s++;
 
   /* There isn't much we can do for syntactic disasters at this stage.
@@ -492,30 +496,16 @@ while (*s)
   empty address, overlong addres. Sometimes the result matters, sometimes not.
   It seems this function is called for *any* header we see. */
 
-
   if (!recipient)
     {
-#if 0
-    /* FIXME:
-    This was(!) an attempt tho handle empty rewrits, but seemingly it
-    needs more effort to decide if the returned empty address matters.
-    Now this will now break test 471 again.
-
-    471 fails now because it uses an overlong address, for wich parse_extract_address()
-    returns an empty address (which was not expected).
-
-    Checking the output and exit if rewrite_rules or routed_old are present
-    isn't a good idea either: It's enough to have *any* rewrite rule
-    in the configuration plus "To: undisclosed recpients:;" to exit(), which
-    is not what we want.
-    */
-
-    if (rewrite_rules || routed_old)
-      {
+    /* Log unparesable addresses in the header. Slightly ugly because a
+    null output from the extract can also result from a header without an
+    address, "To: undisclosed recpients:;" being the classic case. Ignore
+    this one and carry on. */
+
+    if ((rewrite_rules || routed_old) && Ustrcmp(errmess, "empty address") != 0)
       log_write(0, LOG_MAIN, "rewrite: %s", errmess);
-      exim_exit(EXIT_FAILURE);
-      }
-#endif
+
     loop_reset_point = store_reset(loop_reset_point);
     continue;
     }
@@ -615,7 +605,7 @@ while (*s)
     int oldlen = end - start;
 
     header_line * prev = newh ? newh : h;
-    uschar * newt = store_get_perm(prev->slen - oldlen + newlen + 4, TRUE);
+    uschar * newt = store_get_perm(prev->slen - oldlen + newlen + 4, GET_TAINTED);
     uschar * newtstart = newt;
 
     int type = prev->type;
@@ -679,7 +669,7 @@ while (*s)
 
     store_reset(function_reset_point);
     function_reset_point = store_mark();
-    newh = store_get(sizeof(header_line), FALSE);
+    newh = store_get(sizeof(header_line), GET_UNTAINTED);
     newh->type = type;
     newh->slen = slen;
     newh->text = string_copyn(newtstart, slen);