[exim-cvs] ARC: add $arc_domains variable, for verify pass

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] ARC: add $arc_domains variable, for verify pass
Gitweb: https://git.exim.org/exim.git/commitdiff/9cffa4367b034b97a01fb3a0cf8095d8f56fa56a
Commit:     9cffa4367b034b97a01fb3a0cf8095d8f56fa56a
Parent:     ef262e3170d26e4203fbf259180a34b1c0228a32
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Tue Apr 24 22:46:11 2018 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Tue Apr 24 22:46:11 2018 +0100


    ARC: add $arc_domains variable, for verify pass
---
 doc/doc-txt/experimental-spec.txt |  6 +++-
 src/src/arc.c                     | 30 +++++++++++++++++---
 src/src/expand.c                  |  9 +++---
 src/src/functions.h               |  1 +
 test/confs/4560                   |  1 +
 test/confs/4562                   |  1 +
 test/log/4560                     | 21 ++++++++++++++
 test/log/4561                     | 11 +++++++
 test/mail/4561.a                  | 35 +++++++++++++++++++++++
 test/mail/4562.a                  | 60 +++++++++++++++++++++++++++++++++++++++
 10 files changed, 166 insertions(+), 9 deletions(-)


diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index 5c82311..8454308 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -793,7 +793,11 @@ standard header.
     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 two new variables: $arc_state and $arc_state_reason.
+There are three new variables: $arc_state, $arc_state_reason, $arc_domains:
+
+  $arc_state        One of pass, fail, none
+  $arc_state_reason    (if fail, why)
+  $arc_domains        (if pass) colon-sep list of ARC chain domains


Receive log lines for an ARC pass will be tagged "ARC".

diff --git a/src/src/arc.c b/src/src/arc.c
index 53d06de..7ad00fc 100644
--- a/src/src/arc.c
+++ b/src/src/arc.c
@@ -93,6 +93,7 @@ static time_t now;
static time_t expire;
static hdr_rlist * headers_rlist;
static arc_ctx arc_sign_ctx = { NULL };
+static arc_ctx arc_verify_ctx = { NULL };


/******************************************************************************/
@@ -998,9 +999,10 @@ Return: The ARC state, or NULL on error.
const uschar *
acl_verify_arc(void)
{
-arc_ctx ctx = { NULL };
const uschar * res;

+memset(&arc_verify_ctx, 0, sizeof(arc_verify_ctx));
+
 if (!dkim_verify_ctx)
   {
   DEBUG(D_acl) debug_printf("ARC: no DKIM verify context\n");
@@ -1014,7 +1016,7 @@ https://tools.ietf.org/html/draft-ietf-dmarc-arc-protocol-10#section-6
        none, the ARC state is "none" and the algorithm stops here.
 */


-if ((res = arc_vfy_collect_hdrs(&ctx)))
+if ((res = arc_vfy_collect_hdrs(&arc_verify_ctx)))
goto out;

 /* 2.  If the form of any ARC set is invalid (e.g., does not contain
@@ -1032,7 +1034,7 @@ if ((res = arc_vfy_collect_hdrs(&ctx)))
        then the chain state is "fail" and the algorithm stops here.
 */


-if ((res = arc_headers_check(&ctx)))
+if ((res = arc_headers_check(&arc_verify_ctx)))
goto out;

 /* 4.  For each ARC-Seal from the "N"th instance to the first, apply the
@@ -1074,7 +1076,7 @@ if ((res = arc_headers_check(&ctx)))
        the algorithm is complete.
 */


-if ((res = arc_verify_seals(&ctx)))
+if ((res = arc_verify_seals(&arc_verify_ctx)))
goto out;

res = US"pass";
@@ -1772,6 +1774,26 @@ return is_vfy ? arc_header_vfy_feed(g) : arc_header_sign_feed(g);

/******************************************************************************/

+/* Construct the list of domains from the ARC chain after validation */
+
+uschar *
+fn_arc_domains(void)
+{
+arc_set * as;
+gstring * g = NULL;
+
+if (!arc_state || Ustrcmp(arc_state, "pass") != 0)
+ return US"";
+
+for(as = arc_verify_ctx.arcset_chain; as; as = as->next)
+ {
+ blob * d = &as->hdr_as->d;
+ g = string_append_listele_n(g, ':', d->data, d->len);
+ }
+return g ? g->s : US"";
+}
+
+
/* Construct an Authenticate-Results header portion, for the ARC module */

 gstring *
diff --git a/src/src/expand.c b/src/src/expand.c
index 25ae559..42a5a5d 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -462,6 +462,7 @@ static var_entry var_table[] = {
   { "address_file",        vtype_stringptr,   &address_file },
   { "address_pipe",        vtype_stringptr,   &address_pipe },
 #ifdef EXPERIMENTAL_ARC
+  { "arc_domains",         vtype_string_func, &fn_arc_domains },
   { "arc_state",           vtype_stringptr,   &arc_state },
   { "arc_state_reason",    vtype_stringptr,   &arc_state_reason },
 #endif
@@ -1934,13 +1935,13 @@ switch (vp->type)
   case vtype_reply:                          /* Get reply address */
     s = find_header(US"reply-to:", exists_only, newsize, TRUE,
       headers_charset);
-    if (s != NULL) while (isspace(*s)) s++;
-    if (s == NULL || *s == 0)
+    if (s) while (isspace(*s)) s++;
+    if (!s || !*s)
       {
       *newsize = 0;                            /* For the *s==0 case */
       s = find_header(US"from:", exists_only, newsize, TRUE, headers_charset);
       }
-    if (s != NULL)
+    if (s)
       {
       uschar *t;
       while (isspace(*s)) s++;
@@ -1948,7 +1949,7 @@ switch (vp->type)
       while (t > s && isspace(t[-1])) t--;
       *t = 0;
       }
-    return (s == NULL)? US"" : s;
+    return s ? s : US"";


   case vtype_string_func:
     {
diff --git a/src/src/functions.h b/src/src/functions.h
index 5f9deab..3432d78 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -95,6 +95,7 @@ extern const uschar *arc_header_feed(gstring *, BOOL);
 extern gstring *arc_sign(const uschar *, gstring *, uschar **);
 extern void     arc_sign_init(void);
 extern const uschar *acl_verify_arc(void);
+extern uschar * fn_arc_domains(void);
 #endif


 extern void    assert_no_variables(void *, int, const char *, int);
diff --git a/test/confs/4560 b/test/confs/4560
index c986d5f..10ead1c 100644
--- a/test/confs/4560
+++ b/test/confs/4560
@@ -24,6 +24,7 @@ check_data:
     INSERT


   warn    logwrite =    arc_state: <$arc_state>
+    logwrite =    domains:   <$arc_domains>
     condition =    ${if def:arc_state_reason}
     logwrite =    reason:    <$arc_state_reason>


diff --git a/test/confs/4562 b/test/confs/4562
index 7adcd54..bc7415c 100644
--- a/test/confs/4562
+++ b/test/confs/4562
@@ -26,6 +26,7 @@ check_data:
   warn    logwrite =    arc_state: <$arc_state>
     condition =    ${if def:arc_state_reason}
     logwrite =    reason:    <$arc_state_reason>
+    logwrite =    domains:   <$arc_domains>


 .ifdef OPTION
   accept
diff --git a/test/log/4560 b/test/log/4560
index a897380..2e8d6dc 100644
--- a/test/log/4560
+++ b/test/log/4560
@@ -2,15 +2,18 @@
 ******** SERVER ********
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmaX-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss ARC id=qwerty1234@??? for a@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmaX-0005vi-00 => a <a@???> R=d1 T=tfile
 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 10HmaY-0005vi-00 arc_state: <none>
+1999-03-02 09:44:33 10HmaY-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for za@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmaZ-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmaY-0005vi-00 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaZ-0005vi-00"
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
@@ -20,15 +23,18 @@
 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 10HmbA-0005vi-00 arc_state: <none>
+1999-03-02 09:44:33 10HmbA-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zza@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbB-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbB-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@???
 1999-03-02 09:44:33 10HmbA-0005vi-00 => za@??? <zza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbB-0005vi-00"
 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbC-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbC-0005vi-00 domains:   <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmbB-0005vi-00 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbC-0005vi-00"
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
@@ -38,21 +44,25 @@
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 10HmbD-0005vi-00 arc_state: <none>
+1999-03-02 09:44:33 10HmbD-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zmza@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbE-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbE-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@???
 1999-03-02 09:44:33 10HmbD-0005vi-00 => mza@??? <zmza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbE-0005vi-00"
 1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbF-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbF-0005vi-00 domains:   <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@???
 1999-03-02 09:44:33 10HmbE-0005vi-00 => za@??? <mza@???> R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbF-0005vi-00"
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbG-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbG-0005vi-00 domains:   <test.ex:test.ex:test.ex>
 1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmbF-0005vi-00 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbG-0005vi-00"
 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
@@ -62,21 +72,25 @@
 1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 10HmbH-0005vi-00 arc_state: <none>
+1999-03-02 09:44:33 10HmbH-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zzmza@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbI-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbI-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for zmza@???
 1999-03-02 09:44:33 10HmbH-0005vi-00 => zmza@??? <zzmza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbI-0005vi-00"
 1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbJ-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 domains:   <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@???
 1999-03-02 09:44:33 10HmbI-0005vi-00 => mza@??? <zmza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbJ-0005vi-00"
 1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbK-0005vi-00 arc_state: <fail>
+1999-03-02 09:44:33 10HmbK-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbK-0005vi-00 reason:    <AMS body hash miscompare>
 1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for za@???
 1999-03-02 09:44:33 10HmbJ-0005vi-00 => za@??? <mza@???> R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbK-0005vi-00"
@@ -84,6 +98,7 @@
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbL-0005vi-00 arc_state: <fail>
+1999-03-02 09:44:33 10HmbL-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbL-0005vi-00 reason:    <i=3 (cv, sequence or missing header)>
 1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@???
 1999-03-02 09:44:33 10HmbK-0005vi-00 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-0005vi-00"
@@ -94,15 +109,18 @@
 1999-03-02 09:44:33 10HmbL-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 10HmbM-0005vi-00 arc_state: <none>
+1999-03-02 09:44:33 10HmbM-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zza@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbN-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbN-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@???
 1999-03-02 09:44:33 10HmbM-0005vi-00 => za@??? <zza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbN-0005vi-00"
 1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbO-0005vi-00 arc_state: <pass>
+1999-03-02 09:44:33 10HmbO-0005vi-00 domains:   <test.ex>
 1999-03-02 09:44:33 10HmbO-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmbN-0005vi-00 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbO-0005vi-00"
 1999-03-02 09:44:33 10HmbN-0005vi-00 Completed
@@ -114,12 +132,14 @@
 1999-03-02 09:44:33 10HmbP-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded]
 1999-03-02 09:44:33 10HmbP-0005vi-00 DKIM: d=convivian.com s=default c=simple/simple a=rsa-sha256 b=1024 t=1517535248 [verification failed - body hash mismatch (body probably modified in transit)]
 1999-03-02 09:44:33 10HmbP-0005vi-00 arc_state: <fail>
+1999-03-02 09:44:33 10HmbP-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbP-0005vi-00 reason:    <AMS body hash miscompare>
 1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@??? for za@???
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded]
 1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=convivian.com s=default c=simple/simple a=rsa-sha256 b=1024 t=1517535248 [verification failed - body hash mismatch (body probably modified in transit)]
 1999-03-02 09:44:33 10HmbQ-0005vi-00 arc_state: <fail>
+1999-03-02 09:44:33 10HmbQ-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbQ-0005vi-00 reason:    <i=2 (cv, sequence or missing header)>
 1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@??? for a@???
 1999-03-02 09:44:33 10HmbP-0005vi-00 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbQ-0005vi-00"
@@ -132,4 +152,5 @@
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmbR-0005vi-00 H=(xxx) [127.0.0.1] Warning: ARC-FAIL
 1999-03-02 09:44:33 10HmbR-0005vi-00 arc_state: <none>
+1999-03-02 09:44:33 10HmbR-0005vi-00 domains:   <>
 1999-03-02 09:44:33 10HmbR-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for a@???
diff --git a/test/log/4561 b/test/log/4561
new file mode 100644
index 0000000..07c8ed1
--- /dev/null
+++ b/test/log/4561
@@ -0,0 +1,11 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaX-0005vi-00 arc_state: <fail>
+1999-03-02 09:44:33 10HmaX-0005vi-00 domains:   <>
+1999-03-02 09:44:33 10HmaX-0005vi-00 reason:    <i=2 (cv, sequence or missing header)>
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss id=3885245d-3bae-66a2-7a1e-0dbceae2fb50@??? for a@???
+1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaX-0005vi-00 => a <a@???> R=d1 T=tfile
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp
diff --git a/test/mail/4561.a b/test/mail/4561.a
new file mode 100644
index 0000000..55f5673
--- /dev/null
+++ b/test/mail/4561.a
@@ -0,0 +1,35 @@
+From CALLER@??? Tue Mar 02 09:44:33 1999
+Authentication-Results: test.ex;
+    arc=fail (i=2 (cv, sequence or missing header))
+Received: from [127.0.0.1] (helo=xxx)
+    by test.ex with smtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaX-0005vi-00
+    for a@???; Tue, 2 Mar 1999 09:44:33 +0000
+ARC-Seal: i=2; cv=none; a=rsa-sha256; d=test.ex; s=r201803;
+      b=HxjMzNcj7OX+I9Vr1Xr14AGgAci/CI8JxspaeoNT7TBsiOAtZ+YDBBSqXe6fqX3mHQEwpnXrdz
+       PCMIU1SF3ZiBtqWaLBPhStfuNQl5cw+TWXC60rOwCD2bxuBqubM/3AZLMPzIpm62MUYUUGaxwi
+       +LssT4F237WN88Lu4g5vqi8=;
+ARC-Authentication-Results: i=2; test.ex;
+     iprev=fail;
+     auth=pass (PLAIN) smtp.auth=fred@???
+ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=r201803;
+     bh=52LTOZoDLUGP5RZMMrrjLkwTKuJ59wx4n3rL9RKBtgg=;
+     h=Content-Transfer-Encoding:Content-Type:MIME-Version:Date:Message-ID:Subject:
+       From:To:Content-Transfer-Encoding:Content-Type:MIME-Version:Date:Message-ID:
+       Subject:From:To;
+     b=LYAs/k3m790qXfftAVQxqHFCUkqcavgcpKnbEje3MgCmpCiYzeeusloVSjyFx6Mdo0XkN0GSZb
+       HXOCRGaJVnpU9V1QzdIqvz/I7DAyWl53XsKxl9YhsuaeuMMgPpqWpYkp0mOIo3Mtg+VdbF2DKd
+       O8BRJnqfkZkGUqMUJzdaYMU=;
+Authentication-Results: test.ex;
+     iprev=fail;
+     auth=pass (PLAIN) smtp.auth=fred@???
+Received: from [127.0.0.1]
+To: a@???
+From: Jeremy Harris <b@???>
+Subject: another test
+Message-ID: <3885245d-3bae-66a2-7a1e-0dbceae2fb50@???>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+This is a simple test.
+
diff --git a/test/mail/4562.a b/test/mail/4562.a
new file mode 100644
index 0000000..c0e9341
--- /dev/null
+++ b/test/mail/4562.a
@@ -0,0 +1,60 @@
+From CALLER@??? Tue Mar 02 09:44:33 1999
+Authentication-Results: test.ex;
+    iprev=pass (localhost) smtp.client-ip=127.0.0.1;
+    dkim=pass header.d=test.ex header.s=sel header.a=rsa-sha256;
+    dkim=fail (body hash mismatch; body probably modified in transit)
+         header.d=example.com header.s=sel header.a=rsa-sha256;
+    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1
+Received: from localhost ([127.0.0.1] helo=test.ex)
+    by test.ex with esmtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaY-0005vi-00
+    for a@???; Tue, 2 Mar 1999 09:44:33 +0000
+ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
+     b=1J94ImExSjtnwHY/c/aN3BX/xlnQfi6CPdGQvbeSdsbCCEtOqK9547tA54tYFh8beeVECAR0xu
+      9fCSAjZ/0WM7mrxKNMbWkoHNoejUhNkcxJOtFmiS/0JKPQGk8HTE7FHLbogUQvEJoVBBnqo6xW
+      nFtzlI3JfLnWvB3FQ316xLs=;
+ARC-Authentication-Results: i=1; test.ex;
+    dkim=fail (body hash mismatch; body probably modified in transit)
+         header.d=example.com header.s=sel header.a=rsa-sha256;
+    arc=none
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
+    bh=3UbbJTudPxmejzh7U1Zg33U3QT+16kfV2eOTvMeiEis=;
+    h=Subject:Message-ID:Date:To:From:DKIM-Signature:DKIM-Signature;
+    b=cOGacpDRcKUs8d6NK5vfwKQ9OJ3QbHRjxkBgZr2goYGe4M+9/tWjxgbwrpFGkgqqqVE1iHxp73
+      XiycAmipwr0J+Hu1PjkqIXLIY+LsCY+Oq/g1roC2VnphFpfQjaelQQxAIk8RSvmhvIN0WWZG5V
+      UYCQCkQeY+URg26dYoPZRoY=;
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex;
+    s=sel; h=Subject:Message-ID:Date:To:From:Sender:Reply-To:Cc:MIME-Version:
+    Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description:
+    Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
+    In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
+    List-Post:List-Owner:List-Archive;
+    bh=3UbbJTudPxmejzh7U1Zg33U3QT+16kfV2eOTvMeiEis=; b=kN1wFOnQGZMmJkwnBgDwrqe3xg
+    +YlqMcd3tS2KBPcnA71tzAKBiX+QMrcIkp9PgEiJkHOCbM44SEoW/GT/aN0FqeGUuIoZ22nNc9wJq
+    9u4dqiZV6L0EFx0+BmAcKN/Ban7hsQASjP8USIMomgaG9ymJhrkOoDcQhkQTBriYt91c=;
+Authentication-Results: test.ex;
+    dkim=fail (body hash mismatch; body probably modified in transit)
+         header.d=example.com header.s=sel header.a=rsa-sha256;
+    arc=none
+Received: from [127.0.0.1] (helo=xxx)
+    by test.ex with smtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaX-0005vi-00
+    for za@???; Tue, 2 Mar 1999 09:44:33 +0000
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+    d=example.com; s=sel; h=List-Archive;
+     bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=; b=uslVEq1LzHDR2ACoSTiErsGhe
+    GcuqL5no/4XYjsEJOIXkKFp4FFTj7QTcblHqyqsjgd5Dgs7zuFV4U3lwU9jSZtqJNQI+BtYZ5dS48
+    sjr9PbLiguw8rAv5eDXBQKi5XcNCnZlUnWEjl10OXEgJZ9UXdKToWHpSfWEw1nFvOlKAfPBfkznnA
+    EOQXSTJOTanLpr7EZ4Yw5LWE+9BWJfnl6snn6W0mmJl4tbfEXEV1ZzOxdQF1rwjJqmojoCG36Z+v5
+    sWKswl7HgSlKo2GKgxh9zIIhoxg5+7zfmHdKUQ2/6zuR8nqjDAjl3bSdOMgZVM0L6G6EMxQP6Sj6f
+    oEr6ePt9A==;
+From: mrgus@???
+To: bakawolf@???
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+Message-ID: <qwerty1234@???>
+Subject: simple test
+
+This is a simple test.
+