Move the native SRS implementation from Experimental to mainline
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 9 May 2020 20:04:49 +0000 (21:04 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 9 May 2020 22:30:19 +0000 (23:30 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
doc/doc-txt/experimental-spec.txt
src/src/EDITME
src/src/config.h.defaults
src/src/exim.c
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/macro_predef.c
test/scripts/4620-SRS/REQUIRES

index f1940bb1ef31b9057c177f7130b13dca5aa79f13..748f81cc0f2be4400cc7d95ecaa52408a78afa7a 100644 (file)
@@ -10597,6 +10597,14 @@ ${sort {${lookup dnsdb{>:,,mx=example.com}}} {<} {${listextract{1}{<,$item}}}}
 will sort an MX lookup into priority order.
 
 
 will sort an MX lookup into priority order.
 
 
+
+.new
+.vitem &*${srs_encode&~{*&<&'secret'&>&*}{*&<&'return&~path'&>&*}{*&<&'original&~domain'&>&*}}*&
+SRS encoding.  See SECT &<<SECTSRS>>& for details.
+.wen
+
+
+
 .vitem &*${substr{*&<&'string1'&>&*}{*&<&'string2'&>&*}{*&<&'string3'&>&*}}*&
 .cindex "&%substr%& expansion item"
 .cindex "substring extraction"
 .vitem &*${substr{*&<&'string1'&>&*}{*&<&'string2'&>&*}{*&<&'string3'&>&*}}*&
 .cindex "&%substr%& expansion item"
 .cindex "substring extraction"
@@ -11659,6 +11667,13 @@ includes the case of letters, whereas for &%gti%& the comparison is
 case-independent.
 Case and collation order are defined per the system C locale.
 
 case-independent.
 Case and collation order are defined per the system C locale.
 
+
+.new
+.vitem &*inbound_srs&~{*&<&'local&~part'&>&*}{*&<&'secret'&>&*}*&
+SRS decode.  See SECT &<<SECTSRS>>& for details.
+.wen
+
+
 .vitem &*inlist&~{*&<&'string1'&>&*}{*&<&'string2'&>&*}*& &&&
        &*inlisti&~{*&<&'string1'&>&*}{*&<&'string2'&>&*}*&
 .cindex "string" "comparison"
 .vitem &*inlist&~{*&<&'string1'&>&*}{*&<&'string2'&>&*}*& &&&
        &*inlisti&~{*&<&'string1'&>&*}{*&<&'string2'&>&*}*&
 .cindex "string" "comparison"
@@ -41078,6 +41093,108 @@ The lookup will return the same result strings as can appear in
 
 
 
 
 
 
+.section "SRS (Sender Rewriting Scheme)" SECTSRS
+.cindex SRS "sender rewriting scheme"
+
+.new
+SRS can be used to modify sender addresses when forwarding so that
+SPF verification does not object to them.
+It operates by encoding the original envelope sender in a new
+sender local part and using a domain run by the forwarding site
+as the new domain for the sender.  Any DSN message should be returned
+to this new sender at the forwarding site, which can extract the
+original sender from the coded local part and forward the DSN to
+the originator.
+
+This is a way of avoiding the breakage that SPF does to forwarding.
+The constructed local-part will be longer than the original,
+leading to possible problems with very long addresses.
+The changing of the sender address also hinders the tracing of mail
+problems.
+
+Exim can be built to include native SRS support.  To do this
+SUPPORT_SRS=yes must be defined in &_Local/Makefile_&.
+If this has been done, the macros _HAVE_SRS and _HAVE_NATIVE_SRS
+will be defined.
+The support is limited to SRS0-encoding; SRS1 is not supported.
+
+.cindex SRS excoding
+To encode an address use this expansion item:
+.vlist
+.vitem &*${srs_encode&~{*&<&'secret'&>&*}{*&<&'return&~path'&>&*}{*&<&'original&~domain'&>&*}}*&
+.cindex "&%srs_encode%& expansion item"
+.cindex SRS "expansion item"
+The first argument should be a secret known and used by all systems
+handling the recipient domain for the original message.
+There is no need to periodically change this key; a timestamp is also
+encoded.
+The second argument should be given as the envelope sender address before this
+encoding operation.
+The third argument should be the recipient domain of the message when
+it arrived at this system.
+.endlist
+
+.cindex SRS decoding
+To decode an address use this expansion condition:
+.vlist
+.vitem &*inbound_srs&~{*&<&'local&~part'&>&*}{*&<&'secret'&>&*}*&
+The first argument should be the recipient local prt as is was received.
+The second argument is the site secret.
+
+If the messages is not for an SRS-encoded recipient the condition will
+return false.  If it is, the condition will return true and the variable
+&$srs_recipient$& will be set to the decoded (original) value.
+.endlist
+
+Example usage:
+.code
+  #macro
+  SRS_SECRET = <pick something unique for your site for this. Use on all MXs.>
+  
+  #routers
+
+  outbound:
+    driver =    dnslookup
+    # if outbound, and forwarding has been done, use an alternate transport
+    domains =   ! +my_domains
+    transport = ${if eq {$local_part@$domain} \
+                        {$original_local_part@$original_domain} \
+                     {remote_smtp} {remote_forwarded_smtp}}
+  
+  inbound_srs:
+    driver =    redirect
+    senders =   :
+    domains =   +my_domains
+    # detect inbound bounces which are SRS'd, and decode them
+    condition = ${if inbound_srs {$local_part} {SRS_SECRET}}
+    data =      $srs_recipient
+  
+  inbound_srs_failure:
+    driver =    redirect
+    senders =   :
+    domains =   +my_domains
+    # detect inbound bounces which look SRS'd but are invalid
+    condition = ${if inbound_srs {$local_part} {}}
+    allow_fail
+    data =      :fail: Invalid SRS recipient address
+
+  #... further routers here
+
+  
+  # transport; should look like the non-forward outbound
+  # one, plus the max_rcpt and return_path options
+  remote_forwarded_smtp:
+    driver =              smtp
+    # modify the envelope from, for mails that we forward
+    max_rcpt =            1
+    return_path =         ${srs_encode {SRS_SECRET} {$return_path} {$original_domain}}
+.endd
+
+
+.wen
+
+
+
 .section DMARC SECDMARC
 .cindex DMARC verification
 
 .section DMARC SECDMARC
 .cindex DMARC verification
 
index 7f8f628f9b26627ac49bc558c582d923d8b67496..53d7b5c9a11af01fa5dba60e725b0e3cea6dfc46 100644 (file)
@@ -12,6 +12,9 @@ Version 4.95
  1. The fast-ramp two phase queue run support, previously experimental, is
     now supported by default.
 
  1. The fast-ramp two phase queue run support, previously experimental, is
     now supported by default.
 
+ 2. The native SRS support, previously experimental, is now supported. It is
+    not built unless specified in the Local/Makefile.
+
 
 Version 4.94
 ------------
 
 Version 4.94
 ------------
index 68d04cce76ec0f4af213192978dcbb4c58ae6fef..2b6d01f33107e874ede74321374aa98b95714160 100644 (file)
@@ -292,81 +292,11 @@ These four steps are explained in more details below.
 
 
 
 
 
 
-SRS (Sender Rewriting Scheme) Support (native)
---------------------------------------------------------------
-This is less full-featured than the libsrs_alt version below.
-
-The Exim build needs to be done with this in Local/Makefile:
-EXPERIMENTAL_SRS_NATIVE=yes
-
-The following are provided:
-- an expansion item "srs_encode"
-  This takes three arguments:
-  - a site SRS secret
-  - the return_path
-  - the pre-forwarding domain
-
-- an expansion condition "inbound_srs"
-  This takes two arguments: the local_part to check, and a site SRS secret.
-  If the secret is zero-length, only the pattern of the local_part is checked.
-  The $srs_recipient variable is set as a side-effect.
-
-- an expansion variable $srs_recipient
-  This gets the original return_path encoded in the SRS'd local_part
-
-- predefined macros _HAVE_SRS and _HAVE_NATIVE_SRS
-
-Sample usage:
-
-  #macro
-  SRS_SECRET = <pick something unique for your site for this. Use on all MXs.>
-  
-  #routers
-
-  outbound:
-    driver =    dnslookup
-    # if outbound, and forwarding has been done, use an alternate transport
-    domains =   ! +my_domains
-    transport = ${if eq {$local_part@$domain} \
-                        {$original_local_part@$original_domain} \
-                     {remote_smtp} {remote_forwarded_smtp}}
-  
-  inbound_srs:
-    driver =    redirect
-    senders =   :
-    domains =   +my_domains
-    # detect inbound bounces which are SRS'd, and decode them
-    condition = ${if inbound_srs {$local_part} {SRS_SECRET}}
-    data =      $srs_recipient
-  
-  inbound_srs_failure:
-    driver =    redirect
-    senders =   :
-    domains =   +my_domains
-    # detect inbound bounces which look SRS'd but are invalid
-    condition = ${if inbound_srs {$local_part} {}}
-    allow_fail
-    data =      :fail: Invalid SRS recipient address
-
-  #... further routers here
-
-  
-  # transport; should look like the non-forward outbound
-  # one, plus the max_rcpt and return_path options
-  remote_forwarded_smtp:
-    driver =              smtp
-    # modify the envelope from, for mails that we forward
-    max_rcpt =            1
-    return_path =         ${srs_encode {SRS_SECRET} {$return_path} {$original_domain}}
-
-
-
-
 SRS (Sender Rewriting Scheme) Support (using libsrs_alt)
 --------------------------------------------------------------
 SRS (Sender Rewriting Scheme) Support (using libsrs_alt)
 --------------------------------------------------------------
-See also above, for an alternative native support implementation.
+See also the main docs, for an alternative native support implementation.
 
 
-Exim  currently  includes SRS  support  via Miles  Wilton's
+Exim can be built with SRS support using Miles  Wilton's
 libsrs_alt library. The current version of the supported
 library is 0.5, there are reports of 1.0 working.
 
 libsrs_alt library. The current version of the supported
 library is 0.5, there are reports of 1.0 working.
 
@@ -383,6 +313,10 @@ EXPERIMENTAL_SRS_ALT=yes
 
 in your Local/Makefile.
 
 
 in your Local/Makefile.
 
+The built-in support, included by SUPPORT_SRS,
+shuold *not* be enabled if you wish to use the libsrs_alt
+version.
+
 The following main-section options become available:
        srs_config              string
        srs_hashlength          int
 The following main-section options become available:
        srs_config              string
        srs_hashlength          int
index 340d30d76281d23ba5a65b3dd66f8e3e13198270..cf671afd1bc982897cdfb3f42344142635c04083 100644 (file)
@@ -572,6 +572,10 @@ DISABLE_MAL_MKS=yes
 # Uncomment the following to remove the fast-ramp two-phase-queue-run support
 # DISABLE_QUEUE_RAMP=yes
 
 # Uncomment the following to remove the fast-ramp two-phase-queue-run support
 # DISABLE_QUEUE_RAMP=yes
 
+# Uncomment the following lines to add SRS (Sender Rewriting Scheme) support
+# using only native facilities.  See EXPERIMENTAL_SRS_ALT for an alternative.
+# SUPPORT_SRS=yes
+
 
 #------------------------------------------------------------------------------
 # Compiling Exim with experimental features. These are documented in
 
 #------------------------------------------------------------------------------
 # Compiling Exim with experimental features. These are documented in
@@ -584,10 +588,6 @@ DISABLE_MAL_MKS=yes
 
 # EXPERIMENTAL_DCC=yes
 
 
 # EXPERIMENTAL_DCC=yes
 
-# Uncomment the following lines to add SRS (Sender rewriting scheme) support
-# using only native facilities.
-# EXPERIMENTAL_SRS_NATIVE=yes
-
 # Uncomment the following lines to add SRS (Sender rewriting scheme) support
 # using the implementation in linbsrs_alt.
 # You need to have libsrs_alt installed on your system (srs.mirtol.com).
 # Uncomment the following lines to add SRS (Sender rewriting scheme) support
 # using the implementation in linbsrs_alt.
 # You need to have libsrs_alt installed on your system (srs.mirtol.com).
index 5347f7a8e8a48b536d0976bc36613040a92f3f84..a91c3c3aaba2a98b2d62f335d3f633d1bbbc0fe8 100644 (file)
@@ -157,6 +157,7 @@ Do not put spaces between # and the 'define'.
 #define SUPPORT_PROXY
 #define SUPPORT_SOCKS
 #define SUPPORT_SPF
 #define SUPPORT_PROXY
 #define SUPPORT_SOCKS
 #define SUPPORT_SPF
+#define SUPPORT_SRS
 #define SUPPORT_TRANSLATE_IP_ADDRESS
 
 #define SYSLOG_LOG_PID
 #define SUPPORT_TRANSLATE_IP_ADDRESS
 
 #define SYSLOG_LOG_PID
@@ -205,7 +206,6 @@ Do not put spaces between # and the 'define'.
 #define EXPERIMENTAL_LMDB
 #define EXPERIMENTAL_QUEUEFILE
 #define EXPERIMENTAL_SRS_ALT
 #define EXPERIMENTAL_LMDB
 #define EXPERIMENTAL_QUEUEFILE
 #define EXPERIMENTAL_SRS_ALT
-#define EXPERIMENTAL_SRS_NATIVE
 #define EXPERIMENTAL_TLS_RESUME
 
 
 #define EXPERIMENTAL_TLS_RESUME
 
 
index cd6d253231b21a37aba0d44e31ba26360de5e215..ab2d673dd1eae08468395ef72f4577e34c6c9377 100644 (file)
@@ -979,6 +979,9 @@ g = string_cat(NULL, US"Support for:");
 #ifdef SUPPORT_SPF
   g = string_cat(g, US" SPF");
 #endif
 #ifdef SUPPORT_SPF
   g = string_cat(g, US" SPF");
 #endif
+#if defined(SUPPORT_SRS)
+  g = string_cat(g, US" SRS");
+#endif
 #ifdef TCP_FASTOPEN
   tcp_init();
   if (f.tcp_fastopen_ok) g = string_cat(g, US" TCP_Fast_Open");
 #ifdef TCP_FASTOPEN
   tcp_init();
   if (f.tcp_fastopen_ok) g = string_cat(g, US" TCP_Fast_Open");
@@ -1001,7 +1004,7 @@ g = string_cat(NULL, US"Support for:");
 #ifdef EXPERIMENTAL_QUEUEFILE
   g = string_cat(g, US" Experimental_QUEUEFILE");
 #endif
 #ifdef EXPERIMENTAL_QUEUEFILE
   g = string_cat(g, US" Experimental_QUEUEFILE");
 #endif
-#if defined(EXPERIMENTAL_SRS_ALT) || defined(EXPERIMENTAL_SRS_NATIVE)
+#if defined(EXPERIMENTAL_SRS_ALT)
   g = string_cat(g, US" Experimental_SRS");
 #endif
 #ifdef EXPERIMENTAL_TLS_RESUME
   g = string_cat(g, US" Experimental_SRS");
 #endif
 #ifdef EXPERIMENTAL_TLS_RESUME
index 95b5d02e1b32a7c7608499d00d54ddf16dc33afe..4abde0af62fe89d5ccf973a118d462795befd881 100644 (file)
@@ -131,7 +131,7 @@ static uschar *item_table[] = {
   US"run",
   US"sg",
   US"sort",
   US"run",
   US"sg",
   US"sort",
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
   US"srs_encode",
 #endif
   US"substr",
   US"srs_encode",
 #endif
   US"substr",
@@ -166,7 +166,7 @@ enum {
   EITEM_RUN,
   EITEM_SG,
   EITEM_SORT,
   EITEM_RUN,
   EITEM_SG,
   EITEM_SORT,
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
   EITEM_SRS_ENCODE,
 #endif
   EITEM_SUBSTR,
   EITEM_SRS_ENCODE,
 #endif
   EITEM_SUBSTR,
@@ -334,7 +334,7 @@ static uschar *cond_table[] = {
   US"gei",
   US"gt",
   US"gti",
   US"gei",
   US"gt",
   US"gti",
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
   US"inbound_srs",
 #endif
   US"inlist",
   US"inbound_srs",
 #endif
   US"inlist",
@@ -387,7 +387,7 @@ enum {
   ECOND_STR_GEI,
   ECOND_STR_GT,
   ECOND_STR_GTI,
   ECOND_STR_GEI,
   ECOND_STR_GT,
   ECOND_STR_GTI,
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
   ECOND_INBOUND_SRS,
 #endif
   ECOND_INLIST,
   ECOND_INBOUND_SRS,
 #endif
   ECOND_INLIST,
@@ -758,7 +758,7 @@ static var_entry var_table[] = {
   { "srs_orig_recipient",  vtype_stringptr,   &srs_orig_recipient },
   { "srs_orig_sender",     vtype_stringptr,   &srs_orig_sender },
 #endif
   { "srs_orig_recipient",  vtype_stringptr,   &srs_orig_recipient },
   { "srs_orig_sender",     vtype_stringptr,   &srs_orig_sender },
 #endif
-#if defined(EXPERIMENTAL_SRS_ALT) || defined(EXPERIMENTAL_SRS_NATIVE)
+#if defined(EXPERIMENTAL_SRS_ALT) || defined(SUPPORT_SRS)
   { "srs_recipient",       vtype_stringptr,   &srs_recipient },
 #endif
 #ifdef EXPERIMENTAL_SRS_ALT
   { "srs_recipient",       vtype_stringptr,   &srs_recipient },
 #endif
 #ifdef EXPERIMENTAL_SRS_ALT
@@ -2438,7 +2438,7 @@ else
 
 
 
 
 
 
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
 /* Do an hmac_md5.  The result is _not_ nul-terminated, and is sized as
 the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
 
 /* Do an hmac_md5.  The result is _not_ nul-terminated, and is sized as
 the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
 
@@ -2513,7 +2513,7 @@ for (int i = 0, j = len; i < MD5_HASHLEN; i++)
   }
 return;
 }
   }
 return;
 }
-#endif /*EXPERIMENTAL_SRS_NATIVE*/
+#endif /*SUPPORT_SRS*/
 
 
 /*************************************************
 
 
 /*************************************************
@@ -3443,7 +3443,7 @@ switch(cond_type = identify_operator(&s, &opname))
     return s;
     }
 
     return s;
     }
 
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
   case ECOND_INBOUND_SRS:
     /* ${if inbound_srs {local_part}{secret}  {yes}{no}} */
     {
   case ECOND_INBOUND_SRS:
     /* ${if inbound_srs {local_part}{secret}  {yes}{no}} */
     {
@@ -3535,7 +3535,7 @@ srs_result:
     if (yield) *yield = (boolvalue == testfor);
     return s;
     }
     if (yield) *yield = (boolvalue == testfor);
     return s;
     }
-#endif /*EXPERIMENTAL_SRS_NATIVE*/
+#endif /*SUPPORT_SRS*/
 
   /* Unknown condition */
 
 
   /* Unknown condition */
 
@@ -6783,7 +6783,7 @@ while (*s != 0)
       continue;
       }
 
       continue;
       }
 
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
     case EITEM_SRS_ENCODE:
       /* ${srs_encode {secret} {return_path} {orig_domain}} */
       {
     case EITEM_SRS_ENCODE:
       /* ${srs_encode {secret} {return_path} {orig_domain}} */
       {
@@ -6837,7 +6837,7 @@ while (*s != 0)
       yield = string_cat(yield, sub[2]);
       continue;
       }
       yield = string_cat(yield, sub[2]);
       continue;
       }
-#endif /*EXPERIMENTAL_SRS_NATIVE*/
+#endif /*SUPPORT_SRS*/
     }  /* EITEM_* switch */
 
   /* Control reaches here if the name is not recognized as one of the more
     }  /* EITEM_* switch */
 
   /* Control reaches here if the name is not recognized as one of the more
index 880db98f47971e68ab76b87b093052f3d03b635b..5610549816e1ee008465aebb237a84c0dba07503 100644 (file)
@@ -1517,7 +1517,7 @@ uschar *srs_recipient          = NULL;
 uschar *srs_secrets            = NULL;
 uschar *srs_status             = NULL;
 #endif
 uschar *srs_secrets            = NULL;
 uschar *srs_status             = NULL;
 #endif
-#ifdef EXPERIMENTAL_SRS_ALT
+#ifdef SUPPORT_SRS
 uschar *srs_recipient          = NULL;
 #endif
 int     string_datestamp_offset= -1;
 uschar *srs_recipient          = NULL;
 #endif
 int     string_datestamp_offset= -1;
index 3b9e6fb40838b077c86c8ddc0effb828f3383837..fffe744414ada46b570b7476a5b0f0b4089de7ee 100644 (file)
@@ -1002,7 +1002,7 @@ extern uschar *srs_status;             /* SRS staus */
 extern BOOL    srs_usehash;            /* SRS use hash flag */
 extern BOOL    srs_usetimestamp;       /* SRS use timestamp flag */
 #endif
 extern BOOL    srs_usehash;            /* SRS use hash flag */
 extern BOOL    srs_usetimestamp;       /* SRS use timestamp flag */
 #endif
-#ifdef EXPERIMENTAL_SRS_NATIVE
+#ifdef SUPPORT_SRS
 extern uschar *srs_recipient;          /* SRS recipient */
 #endif
 extern BOOL    strict_acl_vars;        /* ACL variables have to be set before being used */
 extern uschar *srs_recipient;          /* SRS recipient */
 #endif
 extern BOOL    strict_acl_vars;        /* ACL variables have to be set before being used */
index 17aad2e4ba9d585cc904bd75e07a30f51aa15279..f6cfcb14ca3acad05b5581d2735ef6902da54ebe 100644 (file)
@@ -174,6 +174,9 @@ due to conflicts with other common macros. */
 #ifdef SUPPORT_SOCKS
   builtin_macro_create(US"_HAVE_SOCKS");
 #endif
 #ifdef SUPPORT_SOCKS
   builtin_macro_create(US"_HAVE_SOCKS");
 #endif
+#if defined(SUPPORT_SRS)
+  builtin_macro_create(US"_HAVE_NATIVE_SRS");  /* beware clash with _HAVE_SRS */
+#endif
 #ifdef TCP_FASTOPEN
   builtin_macro_create(US"_HAVE_TCP_FASTOPEN");
 #endif
 #ifdef TCP_FASTOPEN
   builtin_macro_create(US"_HAVE_TCP_FASTOPEN");
 #endif
@@ -183,12 +186,9 @@ due to conflicts with other common macros. */
 #ifdef SUPPORT_SPF
   builtin_macro_create(US"_HAVE_SPF");
 #endif
 #ifdef SUPPORT_SPF
   builtin_macro_create(US"_HAVE_SPF");
 #endif
-#if defined(EXPERIMENTAL_SRS_ALT) || defined(EXPERIMENTAL_SRS_NATIVE)
+#if defined(EXPERIMENTAL_SRS_ALT) || defined(SUPPORT_SRS)
   builtin_macro_create(US"_HAVE_SRS");
 #endif
   builtin_macro_create(US"_HAVE_SRS");
 #endif
-#if defined(EXPERIMENTAL_SRS_NATIVE)
-  builtin_macro_create(US"_HAVE_NATIVE_SRS");  /* beware clash with _HAVE_SRS */
-#endif
 #ifdef EXPERIMENTAL_ARC
   builtin_macro_create(US"_HAVE_ARC");
 #endif
 #ifdef EXPERIMENTAL_ARC
   builtin_macro_create(US"_HAVE_ARC");
 #endif
index 7286713d681ae2df5948ee87cddfea6734643e8f..a32fd44f6c1535e6e068c93368e7ecc479b70247 100644 (file)
@@ -1,2 +1,2 @@
-support Experimental_SRS
+support SRS
 feature _HAVE_NATIVE_SRS
 feature _HAVE_NATIVE_SRS