summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-docbook/spec.xfpt249
-rw-r--r--doc/doc-txt/ChangeLog2
-rw-r--r--doc/doc-txt/OptionLists.txt6
-rw-r--r--doc/doc-txt/experimental-spec.txt233
-rw-r--r--src/src/EDITME2
-rw-r--r--src/src/acl.c24
-rw-r--r--src/src/config.h.defaults4
-rw-r--r--src/src/dmarc.c6
-rw-r--r--src/src/dmarc.h4
-rw-r--r--src/src/exim.c6
-rw-r--r--src/src/exim.h2
-rw-r--r--src/src/expand.c4
-rw-r--r--src/src/functions.h2
-rw-r--r--src/src/globals.c4
-rw-r--r--src/src/globals.h4
-rw-r--r--src/src/macro_predef.c6
-rw-r--r--src/src/macros.h2
-rw-r--r--src/src/moan.c8
-rw-r--r--src/src/readconf.c2
-rw-r--r--src/src/receive.c17
-rw-r--r--src/src/smtp_in.c2
-rw-r--r--test/scripts/4650-DMARC/REQUIRES2
22 files changed, 301 insertions, 290 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 00ff91d85..c2adc9ea6 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -12079,6 +12079,15 @@ contain the trailing slash. If &$config_file$& does not contain a slash,
.vindex "&$config_file$&"
The name of the main configuration file Exim is using.
+.new
+.vitem &$dmarc_domain_policy$& &&&
+ &$dmarc_status$& &&&
+ &$dmarc_status_text$& &&&
+ &$dmarc_used_domains$&
+Results of DMARC verification.
+For details see section &<<SECDMARC>>&.
+.wen
+
.vitem &$dkim_verify_status$&
Results of DKIM verification.
For details see section &<<SECDKIMVFY>>&.
@@ -39752,11 +39761,11 @@ There is no dot-stuffing (and no dot-termination).
. ////////////////////////////////////////////////////////////////////////////
. ////////////////////////////////////////////////////////////////////////////
-.chapter "DKIM and SPF" "CHAPdkim" &&&
- "DKIM and SPF Support"
-.cindex "DKIM"
+.chapter "DKIM, SPF and DMARC" "CHAPdkim" &&&
+ "DKIM, SPF and DMARC Support"
.section "DKIM (DomainKeys Identified Mail)" SECDKIM
+.cindex "DKIM"
DKIM is a mechanism by which messages sent by some entity can be provably
linked to a domain which that entity controls. It permits reputation to
@@ -40446,6 +40455,240 @@ The lookup will return the same result strings as can appear in
+
+.new
+.section DMARC SECDMARC
+.cindex DMARC verification
+
+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
+&url(http://www.dmarc.org/).
+
+If Exim is built with DMARC support,
+the libopendmarc library is used.
+
+For building Exim yourself, obtain the library from
+&url(http://sourceforge.net/projects/opendmarc/)
+to obtain a copy, or find it in your favorite rpm package
+repository. You will need to attend to the local/Makefile feature
+SUPPORT_DMARC and the associated LDFLAGS addition.
+This description assumes
+that headers will be in /usr/local/include, and that the libraries
+are in /usr/local/lib.
+
+. subsection
+
+There are three main-configuration options:
+.cindex DMARC "configuration options"
+
+The &%dmarc_tld_file%& option
+.oindex &%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 &url(http://publicsuffix.org/list/).
+See also util/renew-opendmarc-tlds.sh script.
+The default for the option is currently
+/etc/exim/opendmarc.tlds
+
+The &%dmarc_history_file%& option, if set
+.oindex &%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.
+The default is unset.
+
+The &%dmarc_forensic_sender%& option
+.oindex &%dmarc_forensic_sender%&
+defines an alternate 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.
+If set, this is expanded and used for the
+From: header line; the address is extracted
+from it and used for the envelope from.
+If not set (the default), the From: header is expanded from
+the dsn_from option, and <> is used for the
+envelope from.
+
+. I wish we had subsections...
+
+.cindex DMARC controls
+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:
+.code
+ control = dmarc_disable_verify
+.endd
+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.
+.code
+ control = dmarc_enable_forensic
+.endd
+(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.
+
+. subsection
+
+DMARC checks cam be run on incoming SMTP messages 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:
+.display
+&'accept '& The DMARC check passed and the library recommends accepting the email.
+&'reject '& The DMARC check failed and the library recommends rejecting the email.
+&'quarantine '& The DMARC check failed and the library recommends keeping it for further inspection.
+&'none '& The DMARC check passed and the library recommends no specific action, neutral.
+&'norecord '& No policy section in the DMARC record for this sender domain.
+&'nofrom '& Unable to determine the domain of the sender.
+&'temperror '& Library error or dns error.
+&'off '& The DMARC check was disabled for this email.
+.endd
+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.
+
+Performing the check sets up information used by the
+&%authresults%& expansion item.
+
+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:
+
+&$dmarc_status$&
+.vindex &$dmarc_status$&
+.cindex DMARC result
+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.
+
+&$dmarc_status_text$&
+.vindex &$dmarc_status_text$&
+is a slightly longer, human readable status.
+
+&$dmarc_used_domain$&
+.vindex &$dmarc_used_domain$&
+is the domain which DMARC used to look up the DMARC policy record.
+
+&$dmarc_domain_policy$&
+.vindex &$dmarc_domain_policy$&
+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.
+
+. subsection
+
+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:
+.ilist
+Configure the global setting dmarc_history_file
+.next
+Configure cron jobs to call the appropriate opendmarc history
+import scripts and truncating the dmarc_history_file
+.endlist
+
+In order to send forensic reports, you need to:
+.ilist
+Configure the global setting dmarc_forensic_sender
+.next
+Configure, somewhere before the DATA ACL, the control option to
+enable sending DMARC forensic reports
+.endlist
+
+. subsection
+
+Example usage:
+.code
+(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
+
+ 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
+
+ warn add_header = :at_start:${authresults {$primary_hostname}}
+.endd
+
+.wen
+
+
+
+
. ////////////////////////////////////////////////////////////////////////////
. ////////////////////////////////////////////////////////////////////////////
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 22a38981b..293ff201a 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -183,6 +183,8 @@ JH/38 Bug 1395: Teach the DNS negative-cache about TTL value from the SOA in
HS/05 Handle trailing backslash gracefully. (CVE-2019-15846)
+JH/39 Promote DMARC support to mainline.
+
Exim version 4.92
-----------------
diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt
index abc09ece1..1618e4279 100644
--- a/doc/doc-txt/OptionLists.txt
+++ b/doc/doc-txt/OptionLists.txt
@@ -182,9 +182,9 @@ directory_transport string* unset redirect
disable_ipv6 boolean false main 4.61
disable_logging boolean false routers 4.11
false transports 4.11
-dmarc_forensic_sender string unset main 4.82 if experimental_dmarc
-dmarc_history_file string unset main 4.82 if experimental_dmarc
-dmarc_tld_file string unset main 4.82 if experimental_dmarc
+dmarc_forensic_sender string unset main 4.82 if experimental_dmarc, 4.93 mainline
+dmarc_history_file string unset main 4.82 if experimental_dmarc, 4.93 mainline
+dmarc_tld_file string unset main 4.82 if experimental_dmarc, 4.93 mainline
dns_again_means_nonexist domain list unset main 1.89
dns_check_names_pattern string + main 2.11
dns_cname_loops integer 0 main 4.92 Set to 9 for older behaviour
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index f748f6146..2b77d2647 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -390,239 +390,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 options to configure DMARC:
-
-Required:
-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/.
- See also util/renew-opendmarc-tlds.sh script.
- The default for the option is currently
- /etc/exim/opendmarc.tlds
-
-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 Alternate 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.
-
- If set, this is expanded and used for the
- From: header line; the address is extracted
- from it and used for the envelope from.
- If not set, the From: header is expanded from
- the dsn_from option, and <> is used for the
- envelope from.
-
- Default: unset.
-
-
-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.
-
-Performing the check sets up information used by the
-${authresults } expansion item.
-
-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.
-
-A now-redundant variable $dmarc_ar_header has now been withdrawn.
-Use the ${authresults } expansion instead.
-
-
-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
-
- 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
-
- warn add_header = :at_start:${authresults {$primary_hostname}}
-
-
-
DSN extra information
---------------------
If compiled with EXPERIMENTAL_DSN_INFO extra information will be added
diff --git a/src/src/EDITME b/src/src/EDITME
index 37e43ac39..965f058bb 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -589,7 +589,7 @@ DISABLE_MAL_MKS=yes
# Uncomment the following line to add DMARC checking capability, implemented
# using libopendmarc libraries. You must have SPF and DKIM support enabled also.
-# EXPERIMENTAL_DMARC=yes
+# SUPPORT_DMARC=yes
# CFLAGS += -I/usr/local/include
# LDFLAGS += -lopendmarc
# Uncomment the following if you need to change the default. You can
diff --git a/src/src/acl.c b/src/src/acl.c
index 5f0a7864b..8e34513d0 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -70,7 +70,7 @@ enum { ACLC_ACL,
ACLC_DKIM_SIGNER,
ACLC_DKIM_STATUS,
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
ACLC_DMARC_STATUS,
#endif
ACLC_DNSLISTS,
@@ -192,7 +192,7 @@ static condition_def conditions[] = {
[ACLC_DKIM_SIGNER] = { US"dkim_signers", TRUE, FALSE, (unsigned int) ~ACL_BIT_DKIM },
[ACLC_DKIM_STATUS] = { US"dkim_status", TRUE, FALSE, (unsigned int) ~ACL_BIT_DKIM },
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
[ACLC_DMARC_STATUS] = { US"dmarc_status", TRUE, FALSE, (unsigned int) ~ACL_BIT_DATA },
#endif
@@ -346,7 +346,7 @@ enum {
#ifndef DISABLE_DKIM
CONTROL_DKIM_VERIFY,
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
CONTROL_DMARC_VERIFY,
CONTROL_DMARC_FORENSIC,
#endif
@@ -417,7 +417,7 @@ static control_def controls_list[] = {
},
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
[CONTROL_DMARC_VERIFY] =
{ US"dmarc_disable_verify", FALSE,
ACL_BIT_DATA | ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START
@@ -3029,18 +3029,18 @@ for (; cb; cb = cb->next)
break;
#endif
- #ifndef DISABLE_DKIM
+#ifndef DISABLE_DKIM
case CONTROL_DKIM_VERIFY:
f.dkim_disable_verify = TRUE;
- #ifdef EXPERIMENTAL_DMARC
+# ifdef SUPPORT_DMARC
/* Since DKIM was blocked, skip DMARC too */
f.dmarc_disable_verify = TRUE;
f.dmarc_enable_forensic = FALSE;
- #endif
+# endif
break;
- #endif
+#endif
- #ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
case CONTROL_DMARC_VERIFY:
f.dmarc_disable_verify = TRUE;
break;
@@ -3048,7 +3048,7 @@ for (; cb; cb = cb->next)
case CONTROL_DMARC_FORENSIC:
f.dmarc_enable_forensic = TRUE;
break;
- #endif
+#endif
case CONTROL_DSCP:
if (*p == '/')
@@ -3442,7 +3442,7 @@ for (; cb; cb = cb->next)
break;
#endif
- #ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
case ACLC_DMARC_STATUS:
if (!f.dmarc_has_been_checked)
dmarc_process();
@@ -3452,7 +3452,7 @@ for (; cb; cb = cb->next)
rc = match_isinlist(dmarc_exim_expand_query(DMARC_VERIFY_STATUS),
&arg,0,NULL,NULL,MCL_STRING,TRUE,NULL);
break;
- #endif
+#endif
case ACLC_DNSLISTS:
rc = verify_check_dnsbl(where, &arg, log_msgptr);
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 17239bb85..b94b36866 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -143,6 +143,8 @@ Do not put spaces between # and the 'define'.
#define SUPPORT_CRYPTEQ
#define SUPPORT_DANE
+#define SUPPORT_DMARC
+#define DMARC_TLD_FILE "/etc/exim/opendmarc.tlds"
#define SUPPORT_I18N
#define SUPPORT_I18N_2008
#define SUPPORT_MAILDIR
@@ -199,8 +201,6 @@ Do not put spaces between # and the 'define'.
#define EXPERIMENTAL_BRIGHTMAIL
#define EXPERIMENTAL_DCC
#define EXPERIMENTAL_DSN_INFO
-#define EXPERIMENTAL_DMARC
-#define DMARC_TLD_FILE "/etc/exim/opendmarc.tlds"
#define EXPERIMENTAL_LMDB
#define EXPERIMENTAL_QUEUEFILE
#define EXPERIMENTAL_SRS
diff --git a/src/src/dmarc.c b/src/src/dmarc.c
index 0644563d0..2e43f846d 100644
--- a/src/src/dmarc.c
+++ b/src/src/dmarc.c
@@ -1,7 +1,7 @@
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Experimental DMARC support.
+/* DMARC support.
Copyright (c) Todd Lyons <tlyons@exim.org> 2012 - 2014
Copyright (c) The Exim Maintainers 2019
License: GPL */
@@ -12,7 +12,7 @@
/* Code for calling dmarc checks via libopendmarc. Called from acl.c. */
#include "exim.h"
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
# if !defined SUPPORT_SPF
# error SPF must also be enabled for DMARC
# elif defined DISABLE_DKIM
@@ -635,6 +635,6 @@ return g;
}
# endif /* SUPPORT_SPF */
-#endif /* EXPERIMENTAL_DMARC */
+#endif /* SUPPORT_DMARC */
/* vi: aw ai sw=2
*/
diff --git a/src/src/dmarc.h b/src/src/dmarc.h
index 3a3bc6d13..c94d939cc 100644
--- a/src/src/dmarc.h
+++ b/src/src/dmarc.h
@@ -9,7 +9,7 @@
/* Portions Copyright (c) 2012, 2013, The Trusted Domain Project;
All rights reserved, licensed for use per LICENSE.opendmarc. */
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
# include "opendmarc/dmarc.h"
# ifdef SUPPORT_SPF
@@ -58,4 +58,4 @@ static int dmarc_write_history_file();
#define ARES_RESULT_UNKNOWN 11
#define ARES_RESULT_DISCARD 12
-#endif /* EXPERIMENTAL_DMARC */
+#endif /* SUPPORT_DMARC */
diff --git a/src/src/exim.c b/src/src/exim.c
index f163b1249..388743f8d 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -916,6 +916,9 @@ fprintf(fp, "Support for:");
#ifdef SUPPORT_SPF
fprintf(fp, " SPF");
#endif
+#ifdef SUPPORT_DMARC
+ fprintf(fp, " DMARC");
+#endif
#ifdef TCP_FASTOPEN
deliver_init();
if (f.tcp_fastopen_ok) fprintf(fp, " TCP_Fast_Open");
@@ -938,9 +941,6 @@ fprintf(fp, "Support for:");
#ifdef EXPERIMENTAL_DCC
fprintf(fp, " Experimental_DCC");
#endif
-#ifdef EXPERIMENTAL_DMARC
- fprintf(fp, " Experimental_DMARC");
-#endif
#ifdef EXPERIMENTAL_DSN_INFO
fprintf(fp, " Experimental_DSN_info");
#endif
diff --git a/src/src/exim.h b/src/src/exim.h
index 263c00321..2cc2621c4 100644
--- a/src/src/exim.h
+++ b/src/src/exim.h
@@ -499,7 +499,7 @@ config.h, mytypes.h, and store.h, so we don't need to mention them explicitly.
#ifndef DISABLE_DKIM
# include "dkim.h"
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
# include "dmarc.h"
# include <opendmarc/dmarc.h>
#endif
diff --git a/src/src/expand.c b/src/src/expand.c
index f38d7a492..d2ccddc73 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -530,7 +530,7 @@ static var_entry var_table[] = {
{ "dkim_verify_reason", vtype_stringptr, &dkim_verify_reason },
{ "dkim_verify_status", vtype_stringptr, &dkim_verify_status },
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
{ "dmarc_domain_policy", vtype_stringptr, &dmarc_domain_policy },
{ "dmarc_status", vtype_stringptr, &dmarc_status },
{ "dmarc_status_text", vtype_stringptr, &dmarc_status_text },
@@ -4390,7 +4390,7 @@ while (*s != 0)
#ifndef DISABLE_DKIM
yield = authres_dkim(yield);
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
yield = authres_dmarc(yield);
#endif
#ifdef EXPERIMENTAL_ARC
diff --git a/src/src/functions.h b/src/src/functions.h
index 4a44096ea..0cd0a0d18 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -124,7 +124,7 @@ extern gstring *authres_arc(gstring *);
#ifndef DISABLE_DKIM
extern gstring *authres_dkim(gstring *);
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
extern gstring *authres_dmarc(gstring *);
#endif
extern gstring *authres_smtpauth(gstring *);
diff --git a/src/src/globals.c b/src/src/globals.c
index 61a9c9796..ad6b38ec5 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -239,7 +239,7 @@ struct global_flags f =
#ifndef DISABLE_DKIM
.dkim_disable_verify = FALSE,
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
.dmarc_has_been_checked = FALSE,
.dmarc_disable_verify = FALSE,
.dmarc_enable_forensic = FALSE,
@@ -838,7 +838,7 @@ uschar *dkim_verify_signers = US"$dkim_signers";
uschar *dkim_verify_status = NULL;
uschar *dkim_verify_reason = NULL;
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
uschar *dmarc_domain_policy = NULL;
uschar *dmarc_forensic_sender = NULL;
uschar *dmarc_history_file = NULL;
diff --git a/src/src/globals.h b/src/src/globals.h
index 4ab43ca65..533def981 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -199,7 +199,7 @@ extern struct global_flags {
#ifndef DISABLE_DKIM
BOOL dkim_disable_verify :1; /* Set via ACL control statement. When set, DKIM verification is disabled for the current message */
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
BOOL dmarc_has_been_checked :1; /* Global variable to check if test has been called yet */
BOOL dmarc_disable_verify :1; /* Set via ACL control statement. When set, DMARC verification is disabled for the current message */
BOOL dmarc_enable_forensic :1; /* Set via ACL control statement. When set, DMARC forensic reports are enabled for the current message */
@@ -511,7 +511,7 @@ extern uschar *dkim_verify_signers; /* Colon-separated list of domains for ea
extern uschar *dkim_verify_status; /* result for this signature */
extern uschar *dkim_verify_reason; /* result for this signature */
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
extern uschar *dmarc_domain_policy; /* Expansion for declared policy of used domain */
extern uschar *dmarc_forensic_sender; /* Set sender address for forensic reports */
extern uschar *dmarc_history_file; /* Expansion variable, file to store dmarc results */
diff --git a/src/src/macro_predef.c b/src/src/macro_predef.c
index fce981996..e96fef938 100644
--- a/src/src/macro_predef.c
+++ b/src/src/macro_predef.c
@@ -146,6 +146,9 @@ due to conflicts with other common macros. */
#ifndef DISABLE_DKIM
builtin_macro_create(US"_HAVE_DKIM");
#endif
+#ifdef SUPPORT_DMARC
+ builtin_macro_create(US"_HAVE_DMARC");
+#endif
#ifndef DISABLE_DNSSEC
builtin_macro_create(US"_HAVE_DNSSEC");
#endif
@@ -194,9 +197,6 @@ due to conflicts with other common macros. */
#ifdef EXPERIMENTAL_DCC
builtin_macro_create(US"_HAVE_DCC");
#endif
-#ifdef EXPERIMENTAL_DMARC
- builtin_macro_create(US"_HAVE_DMARC");
-#endif
#ifdef EXPERIMENTAL_DSN_INFO
builtin_macro_create(US"_HAVE_DSN_INFO");
#endif
diff --git a/src/src/macros.h b/src/src/macros.h
index a94a71f7e..e36c09c47 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -238,7 +238,7 @@ enum {
ERRMESS_TOOMANYRECIP, /* Too many recipients */
ERRMESS_LOCAL_SCAN, /* Rejected by local scan */
ERRMESS_LOCAL_ACL /* Rejected by non-SMTP ACL */
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
,ERRMESS_DMARC_FORENSIC /* DMARC Forensic Report */
#endif
};
diff --git a/src/src/moan.c b/src/src/moan.c
index fea3683ba..f6cda37f2 100644
--- a/src/src/moan.c
+++ b/src/src/moan.c
@@ -73,7 +73,7 @@ int size_limit = bounce_return_size_limit;
FILE * fp;
int pid;
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
uschar * s, * s2;
/* For DMARC if there is a specific sender set, expand the variable for the
@@ -111,7 +111,7 @@ fp = fdopen(fd, "wb");
if (errors_reply_to) fprintf(fp, "Reply-To: %s\n", errors_reply_to);
fprintf(fp, "Auto-Submitted: auto-replied\n");
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
if (s)
fprintf(fp, "From: %s\n", s);
else
@@ -228,7 +228,7 @@ switch(ident)
fprintf(fp, "\n");
break;
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
case ERRMESS_DMARC_FORENSIC:
bounce_return_message = TRUE;
bounce_return_body = FALSE;
@@ -339,7 +339,7 @@ if (bounce_return_message)
fputs(CS buf, fp);
}
}
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
/* Overkill, but use exact test in case future code gets inserted */
else if (bounce_return_body && message_file == NULL)
{
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 16f4a8abe..2f78cd746 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -122,7 +122,7 @@ static optionlist optionlist_config[] = {
{ "dkim_verify_minimal", opt_bool, &dkim_verify_minimal },
{ "dkim_verify_signers", opt_stringptr, &dkim_verify_signers },
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
{ "dmarc_forensic_sender", opt_stringptr, &dmarc_forensic_sender },
{ "dmarc_history_file", opt_stringptr, &dmarc_history_file },
{ "dmarc_tld_file", opt_stringptr, &dmarc_tld_file },
diff --git a/src/src/receive.c b/src/src/receive.c
index ada3ca519..31e3f7cbb 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -14,9 +14,9 @@
extern int dcc_ok;
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
# include "dmarc.h"
-#endif /* EXPERIMENTAL_DMARC */
+#endif
/*************************************************
* Local static variables *
@@ -1703,9 +1703,9 @@ header_line *msgid_header = NULL;
header_line *received_header;
BOOL msgid_header_newly_created = FALSE;
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
int dmarc_up = 0;
-#endif /* EXPERIMENTAL_DMARC */
+#endif
/* Variables for use when building the Received: header. */
@@ -1767,9 +1767,8 @@ if (smtp_input && !smtp_batched_input && !f.dkim_disable_verify)
dkim_exim_verify_init(chunking_state <= CHUNKING_OFFERED);
#endif
-#ifdef EXPERIMENTAL_DMARC
-/* initialize libopendmarc */
-dmarc_up = dmarc_init();
+#ifdef SUPPORT_DMARC
+dmarc_up = dmarc_init(); /* initialize libopendmarc */
#endif
/* Remember the time of reception. Exim uses time+pid for uniqueness of message
@@ -3499,9 +3498,9 @@ else
goto TIDYUP;
#endif /* WITH_CONTENT_SCAN */
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
dmarc_up = dmarc_store_data(from_header);
-#endif /* EXPERIMENTAL_DMARC */
+#endif
#ifndef DISABLE_PRDR
if (prdr_requested && recipients_count > 1 && acl_smtp_data_prdr)
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 257c33de1..671798641 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -2075,7 +2075,7 @@ dkim_collect_input = 0;
dkim_verify_overall = dkim_verify_status = dkim_verify_reason = NULL;
dkim_key_length = 0;
#endif
-#ifdef EXPERIMENTAL_DMARC
+#ifdef SUPPORT_DMARC
f.dmarc_has_been_checked = f.dmarc_disable_verify = f.dmarc_enable_forensic = FALSE;
dmarc_domain_policy = dmarc_status = dmarc_status_text =
dmarc_used_domain = NULL;
diff --git a/test/scripts/4650-DMARC/REQUIRES b/test/scripts/4650-DMARC/REQUIRES
index bb17aff6c..fe9e7b342 100644
--- a/test/scripts/4650-DMARC/REQUIRES
+++ b/test/scripts/4650-DMARC/REQUIRES
@@ -1 +1 @@
-support Experimental_DMARC
+support DMARC