From 8d8638b1a2c6dbd44298afcfa3cadaadb41fa6f7 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 29 May 2012 20:39:14 +0400 Subject: [PATCH] Make 'simple' dkim canonization working. --- CMakeLists.txt | 5 +++-- src/dkim.c | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d9ad74fe..3afda7769 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -885,9 +885,10 @@ SET(PLUGINSSRC src/plugins/surbl.c src/plugins/regexp.c src/plugins/chartable.c src/plugins/fuzzy_check.c - src/plugins/spf.c) + src/plugins/spf.c + src/plugins/dkim_check.c) -SET(MODULES_LIST surbl regexp chartable fuzzy_check spf) +SET(MODULES_LIST surbl regexp chartable fuzzy_check spf dkim) SET(WORKERS_LIST normal controller smtp smtp_proxy lmtp fuzzy keystorage) AddModules(MODULES_LIST WORKERS_LIST) diff --git a/src/dkim.c b/src/dkim.c index f50704722..20a52b0c6 100644 --- a/src/dkim.c +++ b/src/dkim.c @@ -191,6 +191,7 @@ rspamd_dkim_parse_hdrlist (rspamd_dkim_context_t* ctx, const gchar *param, gsize /* Insert new header to the list */ h = memory_pool_alloc (ctx->pool, p - c + 1); rspamd_strlcpy (h, c, p - c + 1); + g_strstrip (h); /* Check mandatory from */ if (!from_found && g_ascii_strcasecmp (h, "from") == 0) { from_found = TRUE; @@ -735,17 +736,21 @@ rspamd_dkim_canonize_body (rspamd_dkim_context_t *ctx, const gchar *start, const g_checksum_update (ctx->body_hash, CRLF, sizeof (CRLF) - 2); } else { + end --; while (end > start + 2) { if (*end == '\n' && *(end - 1) == '\r' && *(end - 2) == '\n') { end -= 2; } + else { + break; + } } if (end == start || end == start + 2) { /* Empty body */ g_checksum_update (ctx->body_hash, CRLF, sizeof (CRLF) - 2); } else { - g_checksum_update (ctx->body_hash, start, end - start); + g_checksum_update (ctx->body_hash, start, end - start + 1); } } return TRUE; @@ -764,16 +769,18 @@ rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, const gchar *begin, gu end = begin + len; p = begin; + c = begin; tag = TRUE; skip = FALSE; - while (p >= end) { + while (p < end) { if (tag && p[0] == 'b' && p[1] == '=') { /* Add to signature */ + msg_debug ("initial update hash with signature part: %*s", p - c + 2, c); g_checksum_update (ctx->headers_hash, c, p - c + 2); skip = TRUE; } - else if (skip && *p == ';') { + else if (skip && (*p == ';' || p == end - 1)) { skip = FALSE; c = p; } @@ -790,7 +797,10 @@ rspamd_dkim_signature_update (rspamd_dkim_context_t *ctx, const gchar *begin, gu while ((*p == '\r' || *p == '\n') && p > c) { p --; } - g_checksum_update (ctx->headers_hash, c, p - c); + if (p - c > 0) { + msg_debug ("final update hash with signature part: %*s", p - c, c); + g_checksum_update (ctx->headers_hash, c, p - c); + } } static gboolean @@ -811,7 +821,7 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea /* Compare state */ if (*p == ':') { /* Compare header's name with desired one */ - if (p - c - 1 == hlen) { + if (p - c == hlen) { if (g_ascii_strncasecmp (c, header_name, hlen) == 0) { /* Get value */ state = 2; @@ -837,7 +847,8 @@ rspamd_dkim_canonize_header_simple (rspamd_dkim_context_t *ctx, const gchar *hea /* c contains the beginning of header */ if (*p == '\n' && (!g_ascii_isspace (p[1]) || p[1] == '\0')) { if (!is_sign) { - g_checksum_update (ctx->headers_hash, c, p - c); + msg_debug ("update signature with header: %*s", p - c + 1, c); + g_checksum_update (ctx->headers_hash, c, p - c + 1); } else { rspamd_dkim_signature_update (ctx, c, p - c); @@ -943,6 +954,11 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct wo got_cr = TRUE; } } + else { + got_cr = FALSE; + got_crlf = FALSE; + } + p ++; } /* Start canonization of body part */ @@ -959,13 +975,13 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct wo body_end = end; } if (!rspamd_dkim_canonize_body (ctx, headers_end, body_end)) { - return DKIM_ERROR; + return DKIM_RECORD_ERROR; } /* Now canonize headers */ cur = ctx->hlist; while (cur) { if (!rspamd_dkim_canonize_header (ctx, task, cur->data, FALSE)) { - return DKIM_ERROR; + return DKIM_RECORD_ERROR; } cur = g_list_next (cur); } @@ -979,9 +995,11 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct wo /* Check bh field */ if (memcmp (ctx->bh, digest, dlen) != 0) { - return DKIM_ERROR; + msg_debug ("bh value missmatch"); + return DKIM_REJECT; } + g_checksum_get_digest (ctx->headers_hash, digest, &dlen); #ifdef HAVE_OPENSSL /* Check headers signature */ @@ -997,7 +1015,8 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct wo } if (RSA_verify (nid, digest, dlen, ctx->b, ctx->blen, key->key_rsa) != 1) { - res = DKIM_ERROR; + msg_debug ("rsa verify failed"); + res = DKIM_REJECT; } #endif return res; -- 2.39.5