summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2018-03-13 20:04:03 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2018-03-13 21:43:32 +0000
commit93c931f83dfa0c448fbb4be09afe1d9fc753fe18 (patch)
treeb7804bdc0c5ec40db639ee0688c8a7849a4f0f70 /src
parent4b4856ff163c6fd31f07511fd1f5c5d9ffc57f53 (diff)
ARC: add $arc_state, $arc_state_reason and add reason to authres string
Diffstat (limited to 'src')
-rw-r--r--src/src/acl.c3
-rw-r--r--src/src/arc.c47
-rw-r--r--src/src/expand.c4
-rw-r--r--src/src/globals.c1
-rw-r--r--src/src/globals.h1
-rw-r--r--src/src/smtp_in.c3
6 files changed, 47 insertions, 12 deletions
diff --git a/src/src/acl.c b/src/src/acl.c
index f0d78d3ef..f6141165c 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -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)))
diff --git a/src/src/arc.c b/src/src/arc.c
index 28438e65e..a749c78ef 100644
--- a/src/src/arc.c
+++ b/src/src/arc.c
@@ -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);
diff --git a/src/src/expand.c b/src/src/expand.c
index 009049db4..6f67ab138 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -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 },
diff --git a/src/src/globals.c b/src/src/globals.c
index 1db5ece32..e8faa9c02 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -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;
diff --git a/src/src/globals.h b/src/src/globals.h
index 03af195f9..63e0e424c 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -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 */
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index a229721cf..6cac7d2e2 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -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