From 2acd1e740c9e2797adc10516fe95a177be38e741 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Fri, 25 Oct 2024 14:21:23 +0100 Subject: [PATCH 1/1] DMARC: add variables for spf/dkim alignment results. Bug 3119 --- doc/doc-docbook/spec.xfpt | 16 +++++++++++++++- doc/doc-txt/NewStuff | 2 ++ src/src/expand.c | 2 ++ src/src/miscmods/dmarc.c | 23 ++++++++++++++++------- test/confs/4650 | 2 ++ test/log/4650 | 4 ++++ 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 3da27cdea..661421be1 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -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 &<>&. -.vitem &$dmarc_domain_policy$& &&& +.vitem &$dmarc_alignment_spf$& &&& + &$dmarc_alignment_dkim$& &&& + &$dmarc_domain_policy$& &&& &$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. + +.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 diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 86c5dad83..27508be8d 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -24,6 +24,8 @@ Version 4.98 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 diff --git a/src/src/expand.c b/src/src/expand.c index bb51bf10c..ebfd4d44a 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -514,6 +514,8 @@ static var_entry var_table[] = { { "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" }, diff --git a/src/src/miscmods/dmarc.c b/src/src/miscmods/dmarc.c index 9741a3a45..c16a7108c 100644 --- a/src/src/miscmods/dmarc.c +++ b/src/src/miscmods/dmarc.c @@ -57,6 +57,8 @@ static dmarc_exim_p dmarc_policy_description[] = { /* $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 */ @@ -435,6 +437,8 @@ uschar * rr; 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; @@ -716,11 +720,14 @@ The EDITME provides a DMARC_API variable */ 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, - 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 */ @@ -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[] = { - { "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 = diff --git a/test/confs/4650 b/test/confs/4650 index d6a637adb..c0b73d425 100644 --- a/test/confs/4650 +++ b/test/confs/4650 @@ -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_alignment_spf <$dmarc_alignment_spf> + logwrite = dmarc_alignment_dkim <$dmarc_alignment_dkim> logwrite = ${authresults {$primary_hostname}} # End diff --git a/test/log/4650 b/test/log/4650 index f9c6bd38f..f5f4e0a6d 100644 --- a/test/log/4650 +++ b/test/log/4650 @@ -6,6 +6,8 @@ 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_status_text 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_used_domain 1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_domain_policy +1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_alignment_spf +1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_alignment_dkim 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 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_used_domain 1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_domain_policy +1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_alignment_spf +1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_alignment_dkim 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 -- 2.30.2