commit 2903234: [CritFix] Arc: Fix ARC validation for chains of signatures
Vsevolod Stakhov
vsevolod at highsecure.ru
Tue Sep 8 14:35:12 UTC 2020
Author: Vsevolod Stakhov
Date: 2020-09-08 15:29:00 +0100
URL: https://github.com/rspamd/rspamd/commit/2903234da6d2be2f4782fdcadcc958f0f30a7c47 (HEAD -> master)
[CritFix] Arc: Fix ARC validation for chains of signatures
---
src/libserver/dkim.c | 92 ++++++++++++++++++++++++++++++++++------------------
1 file changed, 60 insertions(+), 32 deletions(-)
diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c
index cc7818330..a37f1c036 100644
--- a/src/libserver/dkim.c
+++ b/src/libserver/dkim.c
@@ -173,7 +173,7 @@ struct rspamd_dkim_sign_context_s {
struct rspamd_dkim_header {
const gchar *name;
- guint count;
+ gint count;
};
/* Parser of dkim params */
@@ -722,7 +722,7 @@ rspamd_dkim_add_arc_seal_headers (rspamd_mempool_t *pool,
struct rspamd_dkim_common_ctx *ctx)
{
struct rspamd_dkim_header *hdr;
- guint count = ctx->idx, i;
+ gint count = ctx->idx, i;
ctx->hlist = g_ptr_array_sized_new (count * 3 - 1);
@@ -730,20 +730,20 @@ rspamd_dkim_add_arc_seal_headers (rspamd_mempool_t *pool,
/* Authentication results */
hdr = rspamd_mempool_alloc (pool, sizeof (*hdr));
hdr->name = RSPAMD_DKIM_ARC_AUTHHEADER;
- hdr->count = i;
+ hdr->count = -(i + 1);
g_ptr_array_add (ctx->hlist, hdr);
/* Arc signature */
hdr = rspamd_mempool_alloc (pool, sizeof (*hdr));
hdr->name = RSPAMD_DKIM_ARC_SIGNHEADER;
- hdr->count = i;
+ hdr->count = -(i + 1);
g_ptr_array_add (ctx->hlist, hdr);
/* Arc seal (except last one) */
if (i != count - 1) {
hdr = rspamd_mempool_alloc (pool, sizeof (*hdr));
hdr->name = RSPAMD_DKIM_ARC_SEALHEADER;
- hdr->count = i;
+ hdr->count = (-i + 1);
g_ptr_array_add (ctx->hlist, hdr);
}
}
@@ -2240,52 +2240,80 @@ static gboolean
rspamd_dkim_canonize_header (struct rspamd_dkim_common_ctx *ctx,
struct rspamd_task *task,
const gchar *header_name,
- guint count,
+ gint count,
const gchar *dkim_header,
const gchar *dkim_domain)
{
struct rspamd_mime_header *rh, *cur, *sel = NULL;
gint hdr_cnt = 0;
+ bool use_idx = false;
+
+ if (count < 0) {
+ use_idx = true;
+ count = -(count); /* use i= in header content as it is arc stuff */
+ }
if (dkim_header == NULL) {
rh = rspamd_message_get_header_array (task, header_name);
if (rh) {
/* Check uniqueness of the header but we count from the bottom to top */
- for (cur = rh->prev; ; cur = cur->prev) {
- if (hdr_cnt == count) {
- sel = cur;
- }
+ if (!use_idx) {
+ for (cur = rh->prev;; cur = cur->prev) {
+ if (hdr_cnt == count) {
+ sel = cur;
+ }
- hdr_cnt ++;
+ hdr_cnt++;
- if (cur == rh) {
- /* Cycle */
- break;
+ if (cur == rh) {
+ /* Cycle */
+ break;
+ }
}
- }
- if ((rh->flags & RSPAMD_HEADER_UNIQUE) && hdr_cnt > 1) {
- guint64 random_cookie = ottery_rand_uint64 ();
+ if ((rh->flags & RSPAMD_HEADER_UNIQUE) && hdr_cnt > 1) {
+ guint64 random_cookie = ottery_rand_uint64 ();
- msg_warn_dkim ("header %s is intended to be unique by"
- " email standards, but we have %d headers of this"
- " type, artificially break DKIM check", header_name,
- hdr_cnt);
- rspamd_dkim_hash_update (ctx->headers_hash,
- (const gchar *)&random_cookie,
- sizeof (random_cookie));
- ctx->headers_canonicalised += sizeof (random_cookie);
+ msg_warn_dkim ("header %s is intended to be unique by"
+ " email standards, but we have %d headers of this"
+ " type, artificially break DKIM check", header_name,
+ hdr_cnt);
+ rspamd_dkim_hash_update (ctx->headers_hash,
+ (const gchar *)&random_cookie,
+ sizeof (random_cookie));
+ ctx->headers_canonicalised += sizeof (random_cookie);
- return FALSE;
+ return FALSE;
+ }
+
+ if (hdr_cnt <= count) {
+ /*
+ * If DKIM has less headers requested than there are in a
+ * message, then it's fine, it allows adding extra headers
+ */
+ return TRUE;
+ }
}
+ else {
+ gchar idx_buf[16];
+ gint id_len;
- if (hdr_cnt <= count) {
- /*
- * If DKIM has less headers requested than there are in a
- * message, then it's fine, it allows adding extra headers
- */
- return TRUE;
+ id_len = rspamd_snprintf (idx_buf, sizeof (idx_buf), "i=%d;",
+ count);
+
+ for (cur = rh->prev;; cur = cur->prev) {
+ if (cur->decoded &&
+ rspamd_substring_search (cur->decoded, strlen (cur->decoded),
+ idx_buf, id_len) != -1) {
+ sel = cur;
+ break;
+ }
+ }
+
+ if (sel == NULL) {
+ return FALSE;
+ }
}
/* Selected header must be non-null if previous condition is false */
More information about the Commits
mailing list