DMARC: add variables for spf/dkim alignment results. Bug 3119
authorJeremy Harris <jgh146exb@wizmail.org>
Fri, 25 Oct 2024 13:21:23 +0000 (14:21 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Fri, 25 Oct 2024 13:32:27 +0000 (14:32 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/expand.c
src/src/miscmods/dmarc.c
test/confs/4650
test/log/4650

index 3da27cdea67e53842a79c010f764b6df97576499..661421be1ba1b9de7238a05cbbe78c0450f42fa5 100644 (file)
@@ -12714,7 +12714,9 @@ When a message has been received this variable contains
 a colon-separated list of signer domains and identities for the message.
 For details see section &<<SECDKIMVFY>>&.
 
 a colon-separated list of signer domains and identities for the message.
 For details see section &<<SECDKIMVFY>>&.
 
-.vitem &$dmarc_domain_policy$& &&&
+.vitem &$dmarc_alignment_spf$& &&&
+       &$dmarc_alignment_dkim$& &&&
+       &$dmarc_domain_policy$& &&&
        &$dmarc_status$& &&&
        &$dmarc_status_text$& &&&
        &$dmarc_used_domains$&
        &$dmarc_status$& &&&
        &$dmarc_status_text$& &&&
        &$dmarc_used_domains$&
@@ -42951,6 +42953,18 @@ The domain which DMARC used to look up the DMARC policy record.
 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.
 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.
+
+.new
+.vitem &$dmarc_alignment_spf$&
+.vindex &$dmarc_alignment_spf$&
+The result of the SPF alignment portion of the test status;
+"yes" or "no".
+
+.vitem &$dmarc_alignment_dkim$&
+.vindex &$dmarc_alignment_dkim$&
+The result of the DKIM alignment portion of the test status;
+"yes" or "no".
+.wen
 .endlist
 
 .subsection Logging SSECDMARCLOGGING
 .endlist
 
 .subsection Logging SSECDMARCLOGGING
index 86c5dad83e2c27d2fcc5641d1368e3d5109212c4..27508be8d138dcd14abe3ea00ff0180a580eed88 100644 (file)
@@ -24,6 +24,8 @@ Version 4.98
  6. A transport "socks_proxy" may expand to an empty string, specifying no
     proxying.
 
  6. A transport "socks_proxy" may expand to an empty string, specifying no
     proxying.
 
+ 7. Variables $dmarc_alignment_spf and $dmarc_alignment_dkim.
+
 Version 4.98
 ------------
  1. The dkim_status ACL condition may now be used in data ACLs
 Version 4.98
 ------------
  1. The dkim_status ACL condition may now be used in data ACLs
index bb51bf10ca0a6fb6573f51f5f52cb17a4b5e8626..ebfd4d44a72836235018c1a6f4e6ed52dc102c3d 100644 (file)
@@ -514,6 +514,8 @@ static var_entry var_table[] = {
   { "dkim_verify_status",  vtype_module,       US"dkim" },
 #endif
 #ifdef SUPPORT_DMARC
   { "dkim_verify_status",  vtype_module,       US"dkim" },
 #endif
 #ifdef SUPPORT_DMARC
+  { "dmarc_alignment_dkim",vtype_module,       US"dmarc" },
+  { "dmarc_alignment_spf", vtype_module,       US"dmarc" },
   { "dmarc_domain_policy", vtype_module,       US"dmarc" },
   { "dmarc_status",        vtype_module,       US"dmarc" },
   { "dmarc_status_text",   vtype_module,       US"dmarc" },
   { "dmarc_domain_policy", vtype_module,       US"dmarc" },
   { "dmarc_status",        vtype_module,       US"dmarc" },
   { "dmarc_status_text",   vtype_module,       US"dmarc" },
index 9741a3a45f0956d743ae18f9ee6f42486bd39717..c16a7108ce7c11720b3bf756c04cc4946671c625 100644 (file)
@@ -57,6 +57,8 @@ static dmarc_exim_p dmarc_policy_description[] = {
 
 
 /* $variables */
 
 
 /* $variables */
+BOOL    dmarc_alignment_dkim    = FALSE; /* Subtest result */
+BOOL    dmarc_alignment_spf     = FALSE; /* Subtest result */
 uschar * dmarc_domain_policy     = NULL; /* Declared policy of used domain */
 uschar * dmarc_status            = NULL; /* One word value */
 uschar * dmarc_status_text       = NULL; /* Human readable value */
 uschar * dmarc_domain_policy     = NULL; /* Declared policy of used domain */
 uschar * dmarc_status            = NULL; /* One word value */
 uschar * dmarc_status_text       = NULL; /* Human readable value */
@@ -435,6 +437,8 @@ uschar * rr;
 BOOL has_dmarc_record = TRUE;
 u_char ** ruf; /* forensic report addressees, if called for */
 
 BOOL has_dmarc_record = TRUE;
 u_char ** ruf; /* forensic report addressees, if called for */
 
+dmarc_alignment_spf = dmarc_alignment_dkim = FALSE;
+
 /* ACLs have "control=dmarc_disable_verify" */
 if (f.dmarc_disable_verify)
   return OK;
 /* ACLs have "control=dmarc_disable_verify" */
 if (f.dmarc_disable_verify)
   return OK;
@@ -716,11 +720,14 @@ The EDITME provides a DMARC_API variable */
 
   if (has_dmarc_record)
     {
 
   if (has_dmarc_record)
     {
+    dmarc_alignment_spf = sa == DMARC_POLICY_SPF_ALIGNMENT_PASS;
+    dmarc_alignment_dkim = da == DMARC_POLICY_DKIM_ALIGNMENT_PASS;
+
     log_write(0, LOG_MAIN, "DMARC results: spf_domain=%s dmarc_domain=%s "
                           "spf_align=%s dkim_align=%s enforcement='%s'",
                           spf_sender_domain, dmarc_used_domain,
     log_write(0, LOG_MAIN, "DMARC results: spf_domain=%s dmarc_domain=%s "
                           "spf_align=%s dkim_align=%s enforcement='%s'",
                           spf_sender_domain, dmarc_used_domain,
-                          sa==DMARC_POLICY_SPF_ALIGNMENT_PASS  ?"yes":"no",
-                          da==DMARC_POLICY_DKIM_ALIGNMENT_PASS ?"yes":"no",
+                          dmarc_alignment_spf  ? "yes" : "no",
+                          dmarc_alignment_dkim ? "yes" : "no",
                           dmarc_status_text);
     history_file_status = dmarc_write_history_file(dkim_history_buffer);
     /* Now get the forensic reporting addresses, if any */
                           dmarc_status_text);
     history_file_status = dmarc_write_history_file(dkim_history_buffer);
     /* Now get the forensic reporting addresses, if any */
@@ -796,11 +803,13 @@ by moan_send_message. We do not document it as a config-visible $variable.
 We could provide it via a function but there's little advantage. */
 
 static var_entry dmarc_variables[] = {
 We could provide it via a function but there's little advantage. */
 
 static var_entry dmarc_variables[] = {
-  { "dmarc_domain_policy", vtype_stringptr,   &dmarc_domain_policy },
-  { "dmarc_forensic_sender", vtype_stringptr, &dmarc_forensic_sender },
-  { "dmarc_status",        vtype_stringptr,   &dmarc_status },
-  { "dmarc_status_text",   vtype_stringptr,   &dmarc_status_text },
-  { "dmarc_used_domain",   vtype_stringptr,   &dmarc_used_domain },
+  { "dmarc_alignment_dkim",    vtype_bool,             &dmarc_alignment_dkim },
+  { "dmarc_alignment_spf",     vtype_bool,             &dmarc_alignment_spf },
+  { "dmarc_domain_policy",     vtype_stringptr,        &dmarc_domain_policy },
+  { "dmarc_forensic_sender",   vtype_stringptr,        &dmarc_forensic_sender},
+  { "dmarc_status",            vtype_stringptr,        &dmarc_status },
+  { "dmarc_status_text",       vtype_stringptr,        &dmarc_status_text },
+  { "dmarc_used_domain",       vtype_stringptr,        &dmarc_used_domain },
 };
 
 misc_module_info dmarc_module_info =
 };
 
 misc_module_info dmarc_module_info =
index d6a637adb3844d8e37ff7a219c957861204945ab..c0b73d425d4d2a831019c0725c6eb3d374e20d50 100644 (file)
@@ -36,6 +36,8 @@ check_data:
                logwrite =      dmarc_status_text <$dmarc_status_text>
                logwrite =      dmarc_used_domain <$dmarc_used_domain>
                logwrite =      dmarc_domain_policy <$dmarc_domain_policy>
                logwrite =      dmarc_status_text <$dmarc_status_text>
                logwrite =      dmarc_used_domain <$dmarc_used_domain>
                logwrite =      dmarc_domain_policy <$dmarc_domain_policy>
+               logwrite =      dmarc_alignment_spf <$dmarc_alignment_spf>
+               logwrite =      dmarc_alignment_dkim <$dmarc_alignment_dkim>
                logwrite =      ${authresults {$primary_hostname}}
 
 # End
                logwrite =      ${authresults {$primary_hostname}}
 
 # End
index f9c6bd38faee9f0ae1cd33a2179d52c963a3500c..f5f4e0a6dd27fbbc71cb7db07102be0b4b25245d 100644 (file)
@@ -6,6 +6,8 @@
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_status_text <None, Accept>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_used_domain <test.ex>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_domain_policy <none>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_status_text <None, Accept>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_used_domain <test.ex>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_domain_policy <none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_alignment_spf <no>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_alignment_dkim <no>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 Authentication-Results: myhost.test.ex;\n  spf=none smtp.mailfrom=test.ex;\n       dmarc=none header.from=test.ex
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= a@test.ex H=(testclient) [ip4.ip4.ip4.ip4] P=smtp S=sss
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 DMARC results: spf_domain=bloggs.com dmarc_domain=test.ex spf_align=no dkim_align=yes enforcement='Accept'
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 Authentication-Results: myhost.test.ex;\n  spf=none smtp.mailfrom=test.ex;\n       dmarc=none header.from=test.ex
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= a@test.ex H=(testclient) [ip4.ip4.ip4.ip4] P=smtp S=sss
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 DMARC results: spf_domain=bloggs.com dmarc_domain=test.ex spf_align=no dkim_align=yes enforcement='Accept'
@@ -13,5 +15,7 @@
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_status_text <Accept>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_used_domain <test.ex>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_domain_policy <none>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_status_text <Accept>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_used_domain <test.ex>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_domain_policy <none>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_alignment_spf <no>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_alignment_dkim <yes>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 Authentication-Results: myhost.test.ex;\n  spf=none smtp.mailfrom=bloggs.com;\n    dkim=pass header.d=test.ex header.s=sel header.a=rsa-sha1;\n    dmarc=pass header.from=test.ex
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 <= CALLER@bloggs.com H=(testclient) [ip4.ip4.ip4.ip4] P=smtp S=sss DKIM=test.ex id=qwerty1234@disco-zombie.net
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 Authentication-Results: myhost.test.ex;\n  spf=none smtp.mailfrom=bloggs.com;\n    dkim=pass header.d=test.ex header.s=sel header.a=rsa-sha1;\n    dmarc=pass header.from=test.ex
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 <= CALLER@bloggs.com H=(testclient) [ip4.ip4.ip4.ip4] P=smtp S=sss DKIM=test.ex id=qwerty1234@disco-zombie.net