ARC: add $arc_state, $arc_state_reason and add reason to authres string
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 13 Mar 2018 20:04:03 +0000 (20:04 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 13 Mar 2018 21:43:32 +0000 (21:43 +0000)
doc/doc-txt/experimental-spec.txt
src/src/acl.c
src/src/arc.c
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/smtp_in.c
test/confs/4560
test/log/4560
test/mail/4560.a

index 4ed6f25..839200c 100644 (file)
@@ -791,6 +791,8 @@ 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.
+
 Receive log lines for an ARC pass will be tagged "ARC".
 
 
index f0d78d3..f614116 100644 (file)
@@ -1698,7 +1698,8 @@ switch(vp->value)
     uschar * cond;
 
     if (!(arc_state = acl_verify_arc())) return DEFER;
-    DEBUG(D_acl) debug_printf_indent("ARC verify result %s\n", arc_state);
+    DEBUG(D_acl) debug_printf_indent("ARC verify result %s %s%s%s\n", arc_state,
+      arc_state_reason ? "(":"", arc_state_reason, arc_state_reason ? ")":"");
 
     if (!condlist) condlist = US"none:pass";
     while ((cond = string_nextinlist(&condlist, &csep, NULL, 0)))
index 28438e6..a749c78 100644 (file)
@@ -66,7 +66,7 @@ typedef struct arc_set {
   arc_line *           hdr_ams;
   arc_line *           hdr_as;
 
-  BOOL                 ams_verify_done;
+  const uschar *       ams_verify_done;
   BOOL                 ams_verify_passed;
 } arc_set;
 
@@ -495,7 +495,10 @@ for (h = header_list; h; h = h->next)
   rprev = r;
 
   if ((e = arc_try_header(ctx, h, FALSE)))
-    return e;
+    {
+    arc_state_reason = string_sprintf("collecting headers: %s", e);
+    return US"fail";
+    }
   }
 headers_rlist = r;
 
@@ -644,7 +647,7 @@ return pdkim_set_bodyhash(dkim_verify_ctx,
 and without a DKIM v= tag.
 */
 
-static uschar *
+static const uschar *
 arc_ams_verify(arc_ctx * ctx, arc_set * as)
 {
 arc_line * ams = as->hdr_ams;
@@ -656,7 +659,7 @@ ev_ctx vctx;
 int hashtype;
 const uschar * errstr;
 
-as->ams_verify_done = TRUE;
+as->ams_verify_done = US"in-progress";
 
 /* Check the AMS has all the required tags:
    "a="  algorithm
@@ -668,14 +671,20 @@ as->ams_verify_done = TRUE;
 */
 if (  !ams->a.data || !ams->b.data || !ams->bh.data || !ams->d.data
    || !ams->h.data || !ams->s.data)
+  {
+  as->ams_verify_done = arc_state_reason = US"required tag missing";
   return US"fail";
+  }
 
 
 /* The bodyhash should have been created earlier, and the dkim code should
 have managed calculating it during message input.  Find the reference to it. */
 
 if (!(b = arc_ams_setup_vfy_bodyhash(ams)))
+  {
+  as->ams_verify_done = arc_state_reason = US"internal hash setup error";
   return US"fail";
+  }
 
 DEBUG(D_acl)
   {
@@ -699,7 +708,7 @@ if (  !ams->bh.data
     pdkim_hexprint(sighash.data, sighash.len);
     debug_printf("ARC i=%d AMS Body hash did NOT match\n", as->instance);
     }
-  return US"body hash compare mismatch";
+  return as->ams_verify_done = arc_state_reason = US"AMS body hash miscompare";
   }
 
 DEBUG(D_acl) debug_printf("ARC i=%d AMS Body hash compared OK\n", as->instance);
@@ -707,7 +716,7 @@ DEBUG(D_acl) debug_printf("ARC i=%d AMS Body hash compared OK\n", as->instance);
 /* Get the public key from DNS */
 
 if (!(p = arc_line_to_pubkey(ams)))
-  return US"pubkey problem";
+  return as->ams_verify_done = arc_state_reason = US"pubkey problem";
 
 /* We know the b-tag blob is of a nul-term string, so safe as a string */
 pdkim_decode_base64(ams->b.data, &sighash);
@@ -719,6 +728,7 @@ arc_get_verify_hhash(ctx, ams, &hhash);
 if ((errstr = exim_dkim_verify_init(&p->key, KEYFMT_DER, &vctx)))
   {
   DEBUG(D_acl) debug_printf("ARC verify init: %s\n", errstr);
+  as->ams_verify_done = arc_state_reason = US"internal sigverify init error";
   return US"fail";
   }
 
@@ -728,7 +738,7 @@ if ((errstr = exim_dkim_verify(&vctx,
          pdkim_hashes[hashtype].exim_hashmethod, &hhash, &sighash)))
   {
   DEBUG(D_acl) debug_printf("ARC i=%d AMS verify %s\n", as->instance, errstr);
-  return US"ams sig verify fail";
+  return as->ams_verify_done = arc_state_reason = US"AMS sig nonverify";
   }
 
 DEBUG(D_acl) debug_printf("ARC i=%d AMS verify pass\n", as->instance);
@@ -761,8 +771,9 @@ for(inst = 0; as; as = as->next)
      || arc_cv_match(as->hdr_as, US"fail")
      )
     {
-    DEBUG(D_acl) debug_printf("ARC i=%d fail"
-      " (cv, sequence or missing header)\n", as->instance);
+    arc_state_reason = string_sprintf("i=%d fail"
+      " (cv, sequence or missing header)", as->instance);
+    DEBUG(D_acl) debug_printf("ARC %s\n", arc_state_reason);
     ret = US"fail";
     }
 
@@ -775,6 +786,7 @@ for(inst = 0; as; as = as->next)
       ams_fail_found = TRUE;
     else
       arc_oldest_pass = inst;
+  arc_state_reason = NULL;
   }
 
 arc_received = ctx->arcset_chain_last;
@@ -785,7 +797,12 @@ if (ret)
 /* We can skip the latest-AMS validation, if we already did it. */
 
 as = ctx->arcset_chain_last;
-if (as->ams_verify_done ? !as->ams_verify_passed : !!arc_ams_verify(ctx, as))
+if (as->ams_verify_done && !as->ams_verify_passed)
+  {
+  arc_state_reason = as->ams_verify_done;
+  return US"fail";
+  }
+if (!!arc_ams_verify(ctx, as))
   return US"fail";
 
 return NULL;
@@ -822,7 +839,10 @@ DEBUG(D_acl) debug_printf("ARC: AS vfy i=%d\n", as->instance);
 if (  as->instance == 1 && !arc_cv_match(hdr_as, US"none")
    || arc_cv_match(hdr_as, US"none") && as->instance != 1
    )
+  {
+  arc_state_reason = US"seal cv state";
   return US"fail";
+  }
 
 /*
        3.  Initialize a hash function corresponding to the "a" tag of
@@ -835,6 +855,7 @@ if (!exim_sha_init(&hhash_ctx, pdkim_hashes[hashtype].exim_hashmethod))
   {
   DEBUG(D_acl)
       debug_printf("ARC: hash setup error, possibly nonhandled hashtype\n");
+  arc_state_reason = US"seal hash setup error";
   return US"fail";
   }
 
@@ -931,6 +952,7 @@ if ((errstr = exim_dkim_verify(&vctx,
   {
   DEBUG(D_acl)
     debug_printf("ARC i=%d AS headers verify: %s\n", as->instance, errstr);
+  arc_state_reason = US"seal sigverify init error";
   return US"fail";
   }
 
@@ -1690,7 +1712,10 @@ if (arc_state)
   if (arc_received_instance > 0)
     {
     g = string_append(g, 3, US" (i=",
-      string_sprintf("%d", arc_received_instance), US") header.s=");
+      string_sprintf("%d", arc_received_instance), US")");
+    if (arc_state_reason)
+      g = string_append(g, 3, US"(", arc_state_reason, US")");
+    g = string_catn(g, US" header.s=", 10);
     highest_ams = arc_received->hdr_ams;
     g = string_catn(g, highest_ams->s.data, highest_ams->s.len);
 
index 009049d..6f67ab1 100644 (file)
@@ -461,6 +461,10 @@ static var_entry var_table[] = {
   { "address_data",        vtype_stringptr,   &deliver_address_data },
   { "address_file",        vtype_stringptr,   &address_file },
   { "address_pipe",        vtype_stringptr,   &address_pipe },
+#ifdef EXPERIMENTAL_ARC
+  { "arc_state",           vtype_stringptr,   &arc_state },
+  { "arc_state_reason",    vtype_stringptr,   &arc_state_reason },
+#endif
   { "authenticated_fail_id",vtype_stringptr,  &authenticated_fail_id },
   { "authenticated_id",    vtype_stringptr,   &authenticated_id },
   { "authenticated_sender",vtype_stringptr,   &authenticated_sender },
index 1db5ece..e8faa9c 100644 (file)
@@ -427,6 +427,7 @@ struct arc_set *arc_received        = NULL;
 int     arc_received_instance  = 0;
 int     arc_oldest_pass                = 0;
 const uschar *arc_state                = NULL;
+const uschar *arc_state_reason = NULL;
 #endif
 
 uschar *authenticated_fail_id  = NULL;
index 03af195..63e0e42 100644 (file)
@@ -221,6 +221,7 @@ struct arc_set *arc_received;              /* highest ARC instance evaluation struct *
 extern int     arc_received_instance;  /* highest ARC instance number in headers */
 extern int     arc_oldest_pass;        /* lowest passing instance number in headers */
 extern const uschar *arc_state;               /* verification state */
+extern const uschar *arc_state_reason;
 #endif
 extern BOOL    allow_utf8_domains;     /* For experimenting */
 extern uschar *authenticated_fail_id;  /* ID that failed authentication */
index a229721..6cac7d2 100644 (file)
@@ -2009,6 +2009,9 @@ prdr_requested = FALSE;
 #ifdef SUPPORT_SPF
 spf_header_comment = spf_received = spf_result = spf_smtp_comment = NULL;
 #endif
+#ifdef EXPERIMENTAL_ARC
+arc_state = arc_state_reason = NULL;
+#endif
 #ifdef SUPPORT_I18N
 message_smtputf8 = FALSE;
 #endif
index 881b2d7..c986d5f 100644 (file)
@@ -23,6 +23,10 @@ check_data:
   warn !verify =       arc VALUE
        INSERT
 
+  warn logwrite =      arc_state: <$arc_state>
+       condition =     ${if def:arc_state_reason}
+       logwrite =      reason:    <$arc_state_reason>
+
 .ifdef OPTION
   accept
 .else
index 4339273..8876559 100644 (file)
@@ -1,8 +1,10 @@
 
 ******** 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: <none>
 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for za@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmaY-0005vi-00 arc_state: <pass>
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaY-0005vi-00"
 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
 1999-03-02 09:44:33 10HmaY-0005vi-00 => a <a@test.ex> R=d1 T=tfile
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 10HmaZ-0005vi-00 arc_state: <none>
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmbA-0005vi-00 arc_state: <pass>
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex
 1999-03-02 09:44:33 10HmaZ-0005vi-00 => za@test.ex <zza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbA-0005vi-00"
 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 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmbA-0005vi-00 => a@test.ex <za@test.ex> 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 10HmbB-0005vi-00 => a <a@test.ex> R=d1 T=tfile
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 10HmbC-0005vi-00 arc_state: <none>
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zmza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmbD-0005vi-00 arc_state: <pass>
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex
 1999-03-02 09:44:33 10HmbC-0005vi-00 => mza@test.ex <zmza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbD-0005vi-00"
 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 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex
 1999-03-02 09:44:33 10HmbD-0005vi-00 => za@test.ex <mza@test.ex> R=mlist T=tmlist 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmbE-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp 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 10HmbF-0005vi-00 => a <a@test.ex> R=d1 T=tfile
 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 10HmbG-0005vi-00 arc_state: <none>
 1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zzmza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmbH-0005vi-00 arc_state: <pass>
 1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for zmza@test.ex
 1999-03-02 09:44:33 10HmbG-0005vi-00 => zmza@test.ex <zzmza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbH-0005vi-00"
 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 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex
 1999-03-02 09:44:33 10HmbH-0005vi-00 => mza@test.ex <zmza@test.ex> 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: <fail>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 reason:    <AMS body hash miscompare>
 1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for za@test.ex
 1999-03-02 09:44:33 10HmbI-0005vi-00 => za@test.ex <mza@test.ex> R=mlist T=tmlist 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@test.ex
 1999-03-02 09:44:33 10HmbJ-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbK-0005vi-00"
 1999-03-02 09:44:33 10HmbJ-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbK-0005vi-00 => a <a@test.ex> R=d1 T=tfile
 1999-03-02 09:44:33 10HmbK-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
+1999-03-02 09:44:33 10HmbL-0005vi-00 arc_state: <none>
 1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
+1999-03-02 09:44:33 10HmbM-0005vi-00 arc_state: <pass>
 1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex
 1999-03-02 09:44:33 10HmbL-0005vi-00 => za@test.ex <zza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbM-0005vi-00"
 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 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmbM-0005vi-00 => a@test.ex <za@test.ex> 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 10HmbO-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 10HmbO-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 10HmbO-0005vi-00 arc_state: <fail>
+1999-03-02 09:44:33 10HmbO-0005vi-00 reason:    <AMS body hash miscompare>
 1999-03-02 09:44:33 10HmbO-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for za@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 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 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for a@test.ex
 1999-03-02 09:44:33 10HmbO-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbP-0005vi-00"
 1999-03-02 09:44:33 10HmbO-0005vi-00 Completed
 1999-03-02 09:44:33 End queue run: pid=pppp
 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 10HmbQ-0005vi-00 H=(xxx) [127.0.0.1] Warning: ARC-FAIL
+1999-03-02 09:44:33 10HmbQ-0005vi-00 arc_state: <none>
 1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for a@test.ex
index 7a068d2..9ddcd2a 100644 (file)
@@ -171,12 +171,12 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
        id 10HmbK-0005vi-00
        for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=3; cv=fail; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
-        b=TSTRZa5Pb1FTxQ2M5heDeAZTQ6mg/qETgzXrxUA9Aa9GkofMft7JnWyPuM5ZZm9f0BWydQUD24
-         omdjyXmK78wyfDoSDS1Zzau16bByabyDgb7tF3K5qMYTNEosX0aJskb6h/NqBRd5RMlhyt3OOK
-         zGEfd5TI5pS16ghs9I6oB88=;
+        b=uamKZbfYVEc5YSkTjyr588o4KIEF8g6bZ1RzC46wkJifmP0pML666Vvc0lTSsf5MmMcBLl+fTV
+         kVUTGZYjjRU1eTVNShszYPk5LBUPH2nY8h1th4PFsHNxLRzP4sSOEGc4yZjYsG8zYkDGgEPzLH
+         Uw0J+Oa0vRcx2ZW+jZrrd5U=;
 ARC-Authentication-Results: i=3; test.ex;
        iprev=pass (localhost);
-       arc=fail (i=2) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1
+       arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1
 ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
        bh=31zA4VNQZ2yhHUh+7vWASIL9kKqo6pSym1QghgPyUkM=;
        h=Subject;
@@ -185,7 +185,7 @@ ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
          DsScgtJ2MqYbikFuA0LxRIA=;
 Authentication-Results: test.ex;
        iprev=pass (localhost);
-       arc=fail (i=2) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1
+       arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 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@bloggs.com>)
@@ -300,14 +300,14 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
        id 10HmbP-0005vi-00
        for a@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=2; cv=fail; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
-        b=kyA9Jr7oTw0RjbIMJuRSDVS34QV/o7rR2vk8j9OoOrJCc4SGYoFdnwOPuZ0xnJ7PC6VBYqFuaF
-         0roSJ1UkJk7NJLjfw4UXF1gF01z+EBahwpYpLE1K7+wuejYBiu83ksxeNbMaejGCZGXRgTrx4N
-         r8h8iR9p7dSbp6/B7CxxoSg=;
+        b=MQwdR5nlxQNXdo/J3hK8voFybIpzoj3/32eQHLm8rJ0zOfAiJEOB4TKsvhRvn+ErtTRzoQsCrk
+         aY4hSDnUsxPbgawzMeC3QpidYlXOyfNrS6B4wBoaRM2pbAIZytVT0MjZu9g+qrUnv2cOsveQI3
+         ApDVpyZaYfDdcepyBOm5//4=;
 ARC-Authentication-Results: i=2; test.ex;
        dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256;
        dkim=fail (body hash mismatch; body probably modified in transit)
                 header.d=convivian.com header.s=default header.a=rsa-sha256;
-       arc=fail (i=1) header.s=default arc.oldest-pass=0 smtp.client-ip=127.0.0.1
+       arc=fail (i=1)(AMS body hash miscompare) header.s=default arc.oldest-pass=0 smtp.client-ip=127.0.0.1
 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
        bh=DXU/xKzzQYeoYB254nZ0AzNm7z2YZ//FpTnhgIjPyt8=;
        h=Sender:Content-Type:Reply-To:From:List-Subscribe:List-Help:List-Post:
@@ -320,7 +320,7 @@ Authentication-Results: test.ex;
        dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256;
        dkim=fail (body hash mismatch; body probably modified in transit)
                 header.d=convivian.com header.s=default header.a=rsa-sha256;
-       arc=fail (i=1) header.s=default arc.oldest-pass=0 smtp.client-ip=127.0.0.1
+       arc=fail (i=1)(AMS body hash miscompare) header.s=default arc.oldest-pass=0 smtp.client-ip=127.0.0.1
 Received: from [127.0.0.1] (helo=xxx)
        by test.ex with smtp (Exim x.yz)
        (envelope-from <CALLER@bloggs.com>)