Fix build with DRWEB malware scanner
[users/jgh/exim.git] / doc / doc-txt / experimental-spec.txt
index d5140d58beb256030628460238862e770f2ec09b..2569ad3af2b76f7d0ea371a8b00703805932fed5 100644 (file)
@@ -292,10 +292,11 @@ These four steps are explained in more details below.
 
 
 
 
 
 
-SRS (Sender Rewriting Scheme) Support
+SRS (Sender Rewriting Scheme) Support (using libsrs_alt)
 --------------------------------------------------------------
 --------------------------------------------------------------
+See also below, for an alternative native support implementation.
 
 
-Exiscan  currently  includes SRS  support  via Miles  Wilton's
+Exim  currently  includes SRS  support  via 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.
 
@@ -312,6 +313,105 @@ EXPERIMENTAL_SRS=yes
 
 in your Local/Makefile.
 
 
 in your Local/Makefile.
 
+The following main-section options become available:
+       srs_config              string
+       srs_hashlength          int
+       srs_hashmin             int
+       srs_maxage              int
+       srs_secrets             string
+       srs_usehash             bool
+       srs_usetimestamp        bool
+
+The redirect router gains these options (all of type string, unset by default):
+       srs
+       srs_alias
+       srs_condition
+       srs_dbinsert
+       srs_dbselect
+
+The following variables become available:
+       $srs_db_address
+       $srs_db_key
+       $srs_orig_recipient
+       $srs_orig_sender
+       $srs_recipient
+       $srs_status
+
+The predefined feature-macro _HAVE_SRS will be present.
+Additional delivery log line elements, tagged with "SRS=" will show the srs sender.    
+For configuration information see https://github.com/Exim/exim/wiki/SRS .
+
+
+
+
+SRS (Sender Rewriting Scheme) Support (native)
+--------------------------------------------------------------
+This is less full-featured than the libsrs_alt version above.
+
+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>
+  
+  #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}}
+
+
 
 
 DCC Support
 
 
 DCC Support
@@ -390,227 +490,6 @@ Use a reasonable IP. eg. one the sending cluster actually uses.
 
 
 
 
 
 
-DMARC Support
---------------------------------------------------------------
-
-DMARC combines feedback from SPF, DKIM, and header From: in order
-to attempt to provide better indicators of the authenticity of an
-email.  This document does not explain the fundamentals, you
-should read and understand how it works by visiting the website at
-http://www.dmarc.org/.
-
-DMARC support is added via the libopendmarc library.  Visit:
-
-  http://sourceforge.net/projects/opendmarc/
-
-to obtain a copy, or find it in your favorite rpm package
-repository.  If building from source, this description assumes
-that headers will be in /usr/local/include, and that the libraries
-are in /usr/local/lib.
-
-1. To compile Exim with DMARC support, you must first enable SPF.
-Please read the Local/Makefile comments on enabling the SUPPORT_SPF
-feature.  You must also have DKIM support, so you cannot set the
-DISABLE_DKIM feature.  Once both of those conditions have been met
-you can enable DMARC in Local/Makefile:
-
-EXPERIMENTAL_DMARC=yes
-LDFLAGS += -lopendmarc
-# CFLAGS += -I/usr/local/include
-# LDFLAGS += -L/usr/local/lib
-
-The first line sets the feature to include the correct code, and
-the second line says to link the libopendmarc libraries into the
-exim binary.  The commented out lines should be uncommented if you
-built opendmarc from source and installed in the default location.
-Adjust the paths if you installed them elsewhere, but you do not
-need to uncomment them if an rpm (or you) installed them in the
-package controlled locations (/usr/include and /usr/lib).
-
-
-2. Use the following global settings to configure DMARC:
-
-Optional:
-dmarc_tld_file      Defines the location of a text file of valid
-                    top level domains the opendmarc library uses
-                    during domain parsing. Maintained by Mozilla,
-                    the most current version can be downloaded
-                    from a link at http://publicsuffix.org/list/.
-                    If unset, "/etc/exim/opendmarc.tlds" (hardcoded)
-                    is used.
-
-Optional:
-dmarc_history_file  Defines the location of a file to log results
-                    of dmarc verification on inbound emails. The
-                    contents are importable by the opendmarc tools
-                    which will manage the data, send out DMARC
-                    reports, and expire the data. Make sure the
-                    directory of this file is writable by the user
-                    exim runs as.
-
-dmarc_forensic_sender The email address to use when sending a
-                    forensic report detailing alignment failures
-                    if a sender domain's dmarc record specifies it
-                    and you have configured Exim to send them.
-                    Default: do-not-reply@$default_hostname
-
-
-3. By default, the DMARC processing will run for any remote,
-non-authenticated user.  It makes sense to only verify DMARC
-status of messages coming from remote, untrusted sources.  You can
-use standard conditions such as hosts, senders, etc, to decide that
-DMARC verification should *not* be performed for them and disable
-DMARC with a control setting:
-
-  control = dmarc_disable_verify
-
-A DMARC record can also specify a "forensic address", which gives
-exim an email address to submit reports about failed alignment.
-Exim does not do this by default because in certain conditions it
-results in unintended information leakage (what lists a user might
-be subscribed to, etc).  You must configure exim to submit forensic
-reports to the owner of the domain.  If the DMARC record contains a
-forensic address and you specify the control statement below, then
-exim will send these forensic emails.  It's also advised that you
-configure a dmarc_forensic_sender because the default sender address
-construction might be inadequate.
-
-  control = dmarc_enable_forensic
-
-(AGAIN: You can choose not to send these forensic reports by simply
-not putting the dmarc_enable_forensic control line at any point in
-your exim config.  If you don't tell it to send them, it will not
-send them.)
-
-There are no options to either control.  Both must appear before
-the DATA acl.
-
-
-4. You can now run DMARC checks in incoming SMTP by using the
-"dmarc_status" ACL condition in the DATA ACL.  You are required to
-call the spf condition first in the ACLs, then the "dmarc_status"
-condition.  Putting this condition in the ACLs is required in order
-for a DMARC check to actually occur.  All of the variables are set
-up before the DATA ACL, but there is no actual DMARC check that
-occurs until a "dmarc_status" condition is encountered in the ACLs.
-
-The dmarc_status condition takes a list of strings on its
-right-hand side.  These strings describe recommended action based
-on the DMARC check.  To understand what the policy recommendations
-mean, refer to the DMARC website above.  Valid strings are:
-
-  o accept      The DMARC check passed and the library recommends
-                accepting the email.
-  o reject      The DMARC check failed and the library recommends
-                rejecting the email.
-  o quarantine  The DMARC check failed and the library recommends
-                keeping it for further inspection.
-  o none        The DMARC check passed and the library recommends
-                no specific action, neutral.
-  o norecord    No policy section in the DMARC record for this
-                sender domain.
-  o nofrom      Unable to determine the domain of the sender.
-  o temperror   Library error or dns error.
-  o off         The DMARC check was disabled for this email.
-
-You can prefix each string with an exclamation mark to invert its
-meaning, for example "!accept" will match all results but
-"accept".  The string list is evaluated left-to-right in a
-short-circuit fashion.  When a string matches the outcome of the
-DMARC check, the condition succeeds.  If none of the listed
-strings matches the outcome of the DMARC check, the condition
-fails.
-
-Of course, you can also use any other lookup method that Exim
-supports, including LDAP, Postgres, MySQL, etc, as long as the
-result is a list of colon-separated strings.
-
-Several expansion variables are set before the DATA ACL is
-processed, and you can use them in this ACL.  The following
-expansion variables are available:
-
-  o $dmarc_status
-    This is a one word status indicating what the DMARC library
-    thinks of the email.  It is a combination of the results of
-    DMARC record lookup and the SPF/DKIM/DMARC processing results
-    (if a DMARC record was found).  The actual policy declared
-    in the DMARC record is in a separate expansion variable.
-
-  o $dmarc_status_text
-    This is a slightly longer, human readable status.
-
-  o $dmarc_used_domain
-    This is the domain which DMARC used to look up the DMARC
-    policy record.
-
-  o $dmarc_domain_policy
-    This is the policy declared in the DMARC record.  Valid values
-    are "none", "reject" and "quarantine".  It is blank when there
-    is any error, including no DMARC record.
-
-  o $dmarc_ar_header
-    This is the entire Authentication-Results header which you can
-    add using an add_header modifier.
-
-
-5. How to enable DMARC advanced operation:
-By default, Exim's DMARC configuration is intended to be
-non-intrusive and conservative.  To facilitate this, Exim will not
-create any type of logging files without explicit configuration by
-you, the admin.  Nor will Exim send out any emails/reports about
-DMARC issues without explicit configuration by you, the admin (other
-than typical bounce messages that may come about due to ACL
-processing or failure delivery issues).
-
-In order to log statistics suitable to be imported by the opendmarc
-tools, you need to:
-a. Configure the global setting dmarc_history_file.
-b. Configure cron jobs to call the appropriate opendmarc history
-   import scripts and truncating the dmarc_history_file.
-
-In order to send forensic reports, you need to:
-a. Configure the global setting dmarc_forensic_sender.
-b. Configure, somewhere before the DATA ACL, the control option to
-   enable sending DMARC forensic reports.
-
-
-6. Example usage:
-(RCPT ACL)
-  warn    domains        = +local_domains
-          hosts          = +local_hosts
-          control        = dmarc_disable_verify
-
-  warn    !domains       = +screwed_up_dmarc_records
-          control        = dmarc_enable_forensic
-
-  warn    condition      = (lookup if destined to mailing list)
-          set acl_m_mailing_list = 1
-
-(DATA ACL)
-  warn    dmarc_status   = accept : none : off
-          !authenticated = *
-          log_message    = DMARC DEBUG: $dmarc_status $dmarc_used_domain
-          add_header     = $dmarc_ar_header
-
-  warn    dmarc_status   = !accept
-          !authenticated = *
-          log_message    = DMARC DEBUG: '$dmarc_status' for $dmarc_used_domain
-
-  warn    dmarc_status   = quarantine
-          !authenticated = *
-          set $acl_m_quarantine = 1
-          # Do something in a transport with this flag variable
-
-  deny    condition      = ${if eq{$dmarc_domain_policy}{reject}}
-          condition      = ${if eq{$acl_m_mailing_list}{1}}
-          message        = Messages from $dmarc_used_domain break mailing lists
-
-  deny    dmarc_status   = reject
-          !authenticated = *
-          message        = Message from $dmarc_used_domain failed sender's DMARC policy, REJECT
-
-
-
 DSN extra information
 ---------------------
 If compiled with EXPERIMENTAL_DSN_INFO extra information will be added
 DSN extra information
 ---------------------
 If compiled with EXPERIMENTAL_DSN_INFO extra information will be added
@@ -707,6 +586,8 @@ an external directory retaining the exim spool format.
 
 The spool files can then be processed by external processes and then
 requeued into exim spool directories for final delivery.
 
 The spool files can then be processed by external processes and then
 requeued into exim spool directories for final delivery.
+However, note carefully the warnings in the main documentation on
+qpool file formats.
 
 The motivation/inspiration for the transport is to allow external
 processes to access email queued by exim and have access to all the
 
 The motivation/inspiration for the transport is to allow external
 processes to access email queued by exim and have access to all the
@@ -723,7 +604,7 @@ the queuefile driver.
 The transport only takes one option:
 
 * directory - This is used to specify the directory messages should be
 The transport only takes one option:
 
 * directory - This is used to specify the directory messages should be
-copied to
+copied to.  Expanded.
 
 The generic transport options (body_only, current_directory, disable_logging,
 debug_print, delivery_date_add, envelope_to_add, event_action, group,
 
 The generic transport options (body_only, current_directory, disable_logging,
 debug_print, delivery_date_add, envelope_to_add, event_action, group,
@@ -756,6 +637,177 @@ to your Local/Makefile. (Re-)build/install exim. exim -d should show
 Experimental_QUEUEFILE in the line "Support for:".
 
 
 Experimental_QUEUEFILE in the line "Support for:".
 
 
+ARC support
+-----------
+Specification: https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-11
+Note that this is not an RFC yet, so may change.
+
+[RFC 8617 was published 2019/06.  Draft 11 was 2018/01.  A review of the
+changes has not yet been done]
+
+ARC is intended to support the utility of SPF and DKIM in the presence of
+intermediaries in the transmission path - forwarders and mailinglists -
+by establishing a cryptographically-signed chain in headers.
+
+Normally one would only bother doing ARC-signing when functioning as
+an intermediary.  One might do verify for local destinations.
+
+ARC uses the notion of a "ADministrative Management Domain" (ADMD).
+Described in RFC 5598 (section 2.3), this is essentially a set of
+mail-handling systems that mail transits that are all under the control
+of one organisation.  A label should be chosen to identify the ADMD.
+Messages should be ARC-verified on entry to the ADMD, and ARC-signed on exit
+from it.
+
+
+Building with ARC Support
+--
+Enable using EXPERIMENTAL_ARC=yes in your Local/Makefile.
+You must also have DKIM present (not disabled), and you very likely
+want to have SPF enabled.
+
+
+Verification
+--
+An ACL condition is provided to perform the "verifier actions" detailed
+in section 6 of the above specification.  It may be called from the DATA ACL
+and succeeds if the result matches any of a given list.
+It also records the highest ARC instance number (the chain size)
+and verification result for later use in creating an Authentication-Results:
+standard header.
+
+  verify = arc/<acceptable_list>   none:fail:pass
+
+  add_header = :at_start:${authresults {<admd-identifier>}}
+
+       Note that it would be wise to strip incoming messages of A-R headers
+       that claim to be from our own <admd-identifier>.
+
+There are four new variables:
+
+  $arc_state           One of pass, fail, none
+  $arc_state_reason    (if fail, why)
+  $arc_domains         colon-sep list of ARC chain domains, in chain order.
+                       problematic elements may have empty list elements
+  $arc_oldest_pass     lowest passing instance number of chain
+
+Example:
+  logwrite = oldest-p-ams: <${reduce {$lh_ARC-Authentication-Results:} \
+                               {} \
+                               {${if = {$arc_oldest_pass} \
+                                       {${extract {i}{${extract {1}{;}{$item}}}}} \
+                                       {$item} {$value}}} \
+                           }>
+
+Receive log lines for an ARC pass will be tagged "ARC".
+
+
+Signing
+--
+arc_sign = <admd-identifier> : <selector> : <privkey> [ : <options> ]
+An option on the smtp transport, which constructs and prepends to the message
+an ARC set of headers.  The textually-first Authentication-Results: header
+is used as a basis (you must have added one on entry to the ADMD).
+Expanded as a whole; if unset, empty or forced-failure then no signing is done.
+If it is set, all of the first three elements must be non-empty.
+
+The fourth element is optional, and if present consists of a comma-separated list
+of options.  The options implemented are
+
+  timestamps           Add a t= tag to the generated AMS and AS headers, with the
+                       current time.
+  expire[=<val>]       Add an x= tag to the generated AMS header, with an expiry time.
+                       If the value <val> is an plain number it is used unchanged.
+                       If it starts with a '+' then the following number is added
+                       to the current time, as an offset in seconds.
+                       If a value is not given it defaults to a one month offset.
+
+[As of writing, gmail insist that a t= tag on the AS is mandatory]
+
+Caveats:
+ * There must be an Authentication-Results header, presumably added by an ACL
+   while receiving the message, for the same ADMD, for arc_sign to succeed.
+   This requires careful coordination between inbound and outbound logic.
+
+   Only one A-R header is taken account of.  This is a limitation versus
+   the ARC spec (which says that all A-R headers from within the ADMD must
+   be used).
+
+ * If passing a message to another system, such as a mailing-list manager
+   (MLM), between receipt and sending, be wary of manipulations to headers made
+   by the MLM.
+   + For instance, Mailman with REMOVE_DKIM_HEADERS==3 might improve
+     deliverability in a pre-ARC world, but that option also renames the
+     Authentication-Results header, which breaks signing.
+
+ * Even if you use multiple DKIM keys for different domains, the ARC concept
+   should try to stick to one ADMD, so pick a primary domain and use that for
+   AR headers and outbound signing.
+
+Signing is not compatible with cutthrough delivery; any (before expansion)
+value set for the option will result in cutthrough delivery not being
+used via the transport in question.
+
+
+
+
+TLS Session Resumption
+----------------------
+TLS Session Resumption for TLS 1.2 and TLS 1.3 connections can be used (defined
+in RFC 5077 for 1.2).  The support for this can be included by building with
+EXPERIMENTAL_TLS_RESUME defined.  This requires GnuTLS 3.6.3 or OpenSSL 1.1.1
+(or later).
+
+Session resumption (this is the "stateless" variant) involves the server sending
+a "session ticket" to the client on one connection, which can be stored by the
+client and used for a later session.  The ticket contains sufficient state for
+the server to reconstruct the TLS session, avoiding some expensive crypto
+calculation and one full packet roundtrip time.
+
+Operational cost/benefit:
+ The extra data being transmitted costs a minor amount, and the client has
+ extra costs in storing and retrieving the data.
+
+ In the Exim/Gnutls implementation the extra cost on an initial connection
+ which is TLS1.2 over a loopback path is about 6ms on 2017-laptop class hardware.
+ The saved cost on a subsequent connection is about 4ms; three or more
+ connections become a net win.  On longer network paths, two or more
+ connections will have an average lower startup time thanks to the one
+ saved packet roundtrip.  TLS1.3 will save the crypto cpu costs but not any
+ packet roundtrips.
+
+ Since a new hints DB is used, the hints DB maintenance should be updated
+ to additionally handle "tls".
+
+Security aspects:
+ The session ticket is encrypted, but is obviously an additional security
+ vulnarability surface.  An attacker able to decrypt it would have access
+ all connections using the resumed session.
+ The session ticket encryption key is not committed to storage by the server
+ and is rotated regularly (OpenSSL: 1hr, and one previous key is used for
+ overlap; GnuTLS 6hr but does not specify any overlap).
+ Tickets have limited lifetime (2hr, and new ones issued after 1hr under
+ OpenSSL.  GnuTLS 2hr, appears to not do overlap).
+
+ There is a question-mark over the security of the Diffie-Helman parameters
+ used for session negotiation. TBD.  q-value; cf bug 1895
+
+Observability:
+ New log_selector "tls_resumption", appends an asterisk to the tls_cipher "X="
+ element.
+
+ Variables $tls_{in,out}_resumption have bits 0-4 indicating respectively
+ support built, client requested ticket, client offered session,
+ server issued ticket, resume used.  A suitable decode list is provided
+ in the builtin macro _RESUME_DECODE for ${listextract {}{}}.
+
+Issues:
+ In a resumed session:
+  $tls_{in,out}_cipher will have values different to the original (under GnuTLS)
+  $tls_{in,out}_ocsp will be "not requested" or "no response", and
+   hosts_require_ocsp will fail
+
+
 --------------------------------------------------------------
 End of file
 --------------------------------------------------------------
 --------------------------------------------------------------
 End of file
 --------------------------------------------------------------