From: Vsevolod Stakhov Date: Thu, 25 May 2017 13:05:12 +0000 (+0100) Subject: [Minor] Parse CV results from Arc-Seal X-Git-Tag: 1.6.0~136 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8824596a69479b2d6031a20c8afa1c2aa18b36b6;p=rspamd.git [Minor] Parse CV results from Arc-Seal --- diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index b7d3f8ea1..6e72c58b2 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -36,28 +36,33 @@ #define DKIM_CANON_DEFAULT DKIM_CANON_SIMPLE /* Params */ -#define DKIM_PARAM_UNKNOWN (-1) /* unknown */ -#define DKIM_PARAM_SIGNATURE 0 /* b */ -#define DKIM_PARAM_SIGNALG 1 /* a */ -#define DKIM_PARAM_DOMAIN 2 /* d */ -#define DKIM_PARAM_CANONALG 3 /* c */ -#define DKIM_PARAM_QUERYMETHOD 4 /* q */ -#define DKIM_PARAM_SELECTOR 5 /* s */ -#define DKIM_PARAM_HDRLIST 6 /* h */ -#define DKIM_PARAM_VERSION 7 /* v */ -#define DKIM_PARAM_IDENTITY 8 /* i */ -#define DKIM_PARAM_TIMESTAMP 9 /* t */ -#define DKIM_PARAM_EXPIRATION 10 /* x */ -#define DKIM_PARAM_COPIEDHDRS 11 /* z */ -#define DKIM_PARAM_BODYHASH 12 /* bh */ -#define DKIM_PARAM_BODYLENGTH 13 /* l */ -#define DKIM_PARAM_IDX 14 /* i */ +enum rspamd_dkim_param_type { + DKIM_PARAM_UNKNOWN = -1, + DKIM_PARAM_SIGNATURE = 0, + DKIM_PARAM_SIGNALG, + DKIM_PARAM_DOMAIN, + DKIM_PARAM_CANONALG, + DKIM_PARAM_QUERYMETHOD, + DKIM_PARAM_SELECTOR, + DKIM_PARAM_HDRLIST, + DKIM_PARAM_VERSION, + DKIM_PARAM_IDENTITY, + DKIM_PARAM_TIMESTAMP, + DKIM_PARAM_EXPIRATION, + DKIM_PARAM_COPIEDHDRS, + DKIM_PARAM_BODYHASH, + DKIM_PARAM_BODYLENGTH, + DKIM_PARAM_IDX, + DKIM_PARAM_CV +}; /* Signature methods */ -#define DKIM_SIGN_UNKNOWN (-2) /* unknown method */ -#define DKIM_SIGN_DEFAULT (-1) /* use internal default */ -#define DKIM_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */ -#define DKIM_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */ +enum rspamd_sign_type { + DKIM_SIGN_UNKNOWN = -2, + DKIM_SIGN_RSASHA1 = 0, + DKIM_SIGN_RSASHA256 +}; + #define RSPAMD_DKIM_MAX_ARC_IDX 10 #define msg_err_dkim(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \ @@ -89,6 +94,14 @@ struct rspamd_dkim_common_ctx { guint idx; }; +enum rspamd_arc_seal_cv { + RSPAMD_ARC_UNKNOWN = 0, + RSPAMD_ARC_NONE, + RSPAMD_ARC_INVALID, + RSPAMD_ARC_FAIL, + RSPAMD_ARC_PASS +}; + struct rspamd_dkim_context_s { struct rspamd_dkim_common_ctx common; rspamd_mempool_t *pool; @@ -103,6 +116,7 @@ struct rspamd_dkim_context_s { gint8 *b; gint8 *bh; gchar *dns_key; + enum rspamd_arc_seal_cv cv; const gchar *dkim_header; }; @@ -195,6 +209,10 @@ static gboolean rspamd_dkim_parse_idx (rspamd_dkim_context_t * ctx, const gchar *param, gsize len, GError **err); +static gboolean rspamd_dkim_parse_cv (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err); static const dkim_parse_param_f parser_funcs[] = { @@ -213,6 +231,7 @@ static const dkim_parse_param_f parser_funcs[] = { [DKIM_PARAM_BODYHASH] = rspamd_dkim_parse_bodyhash, [DKIM_PARAM_BODYLENGTH] = rspamd_dkim_parse_bodylength, [DKIM_PARAM_IDX] = rspamd_dkim_parse_idx, + [DKIM_PARAM_CV] = rspamd_dkim_parse_cv, }; #define DKIM_ERROR dkim_error_quark () @@ -575,6 +594,40 @@ rspamd_dkim_parse_idx (rspamd_dkim_context_t * ctx, return TRUE; } +static gboolean +rspamd_dkim_parse_cv (rspamd_dkim_context_t * ctx, + const gchar *param, + gsize len, + GError **err) +{ + + /* Only check header */ + if (len == 4 && memcmp (param, "fail", len) == 0) { + ctx->cv = RSPAMD_ARC_FAIL; + return TRUE; + } + else if (len == 4 && memcmp (param, "pass", len) == 0) { + ctx->cv = RSPAMD_ARC_PASS; + return TRUE; + } + else if (len == 4 && memcmp (param, "none", len) == 0) { + ctx->cv = RSPAMD_ARC_NONE; + return TRUE; + } + else if (len == 7 && memcmp (param, "invalid", len) == 0) { + ctx->cv = RSPAMD_ARC_INVALID; + return TRUE; + } + + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "invalid arc seal verification result"); + + return FALSE; +} + + static void rspamd_dkim_add_arc_seal_headers (rspamd_mempool_t *pool, struct rspamd_dkim_common_ctx *ctx) @@ -796,6 +849,19 @@ rspamd_create_dkim_context (const gchar *sig, param = DKIM_PARAM_BODYHASH; } } + else if (tag[0] == 'c' && tag[1] == 'v') { + if (type != RSPAMD_DKIM_ARC_SEAL) { + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "cv tag is valid for ARC-Seal only"); + state = DKIM_STATE_ERROR; + break; + } + else { + param = DKIM_PARAM_CV; + } + } else { g_set_error (err, DKIM_ERROR, @@ -976,6 +1042,16 @@ rspamd_create_dkim_context (const gchar *sig, return NULL; } + if (ctx->common.type != RSPAMD_DKIM_ARC_SEAL) { + if (ctx->cv == RSPAMD_ARC_UNKNOWN) { + g_set_error (err, + DKIM_ERROR, + DKIM_SIGERROR_UNKNOWN, + "cv parameter missing or invalid for ARC"); + return NULL; + } + } + /* Now create dns key to request further */ taglen = strlen (ctx->domain) + strlen (ctx->selector) + sizeof (DKIM_DNSKEYNAME) + 2; @@ -1923,7 +1999,7 @@ rspamd_dkim_canonize_header (struct rspamd_dkim_common_ctx *ctx, * @param task task to check * @return */ -gint +enum rspamd_dkim_check_result rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct rspamd_task *task) @@ -1932,7 +2008,7 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, guchar raw_digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX *cpy_ctx; gsize dlen; - gint res = DKIM_CONTINUE; + enum rspamd_dkim_check_result res = DKIM_CONTINUE; guint i; struct rspamd_dkim_header *dh; gint nid; @@ -2062,6 +2138,21 @@ rspamd_dkim_check (rspamd_dkim_context_t *ctx, res = DKIM_REJECT; } + if (ctx->common.type == RSPAMD_DKIM_ARC_SEAL && res == DKIM_CONTINUE) { + switch (ctx->cv) { + case RSPAMD_ARC_INVALID: + msg_info_dkim ("arc seal is invalid i=%d", ctx->common.idx); + res = DKIM_PERM_ERROR; + break; + case RSPAMD_ARC_FAIL: + msg_info_dkim ("arc seal failed i=%d", ctx->common.idx); + res = DKIM_REJECT; + break; + default: + break; + } + } + return res; } @@ -2348,12 +2439,10 @@ rspamd_create_dkim_sign_context (struct rspamd_task *task, } -GString* -rspamd_dkim_sign (struct rspamd_task *task, - const gchar *selector, const gchar *domain, - time_t expire, gsize len, - guint idx, - rspamd_dkim_sign_context_t *ctx) +GString * +rspamd_dkim_sign (struct rspamd_task *task, const gchar *selector, + const gchar *domain, time_t expire, gsize len, guint idx, + const gchar *arc_cv, rspamd_dkim_sign_context_t *ctx) { GString *hdr; struct rspamd_dkim_header *dh; @@ -2407,8 +2496,9 @@ rspamd_dkim_sign (struct rspamd_task *task, domain, selector); } else { - /* Shouldn't be called for arc seal */ - rspamd_printf_gstring (hdr, "i=%d; a=rsa-sha256; c=%s/%s; d=%s; s=%s; ", + g_assert (arc_cv != NULL); + rspamd_printf_gstring (hdr, "i=%d; a=rsa-sha256; c=%s/%s; d=%s; s=%s; cv=%s; ", + arc_cv, idx, domain, selector); } diff --git a/src/libserver/dkim.h b/src/libserver/dkim.h index 0a7eec21c..2a8b0e0b5 100644 --- a/src/libserver/dkim.h +++ b/src/libserver/dkim.h @@ -81,12 +81,14 @@ #define DKIM_SIGERROR_EMPTY_V 45 /* v= tag empty */ /* Check results */ -#define DKIM_CONTINUE 0 /* continue */ -#define DKIM_REJECT 1 /* reject */ -#define DKIM_TRYAGAIN 2 /* try again later */ -#define DKIM_NOTFOUND 3 /* requested record not found */ -#define DKIM_RECORD_ERROR 4 /* error requesting record */ -#define DKIM_PERM_ERROR 5 /* permanent error */ +enum rspamd_dkim_check_result { + DKIM_CONTINUE = 0, + DKIM_REJECT, + DKIM_TRYAGAIN, + DKIM_NOTFOUND, + DKIM_RECORD_ERROR, + DKIM_PERM_ERROR, +}; #define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */ #define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */ @@ -189,15 +191,13 @@ gboolean rspamd_get_dkim_key (rspamd_dkim_context_t *ctx, * @param task task to check * @return */ -gint rspamd_dkim_check (rspamd_dkim_context_t *ctx, +enum rspamd_dkim_check_result rspamd_dkim_check (rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key, struct rspamd_task *task); -GString* rspamd_dkim_sign (struct rspamd_task *task, - const gchar *selector, const gchar *domain, - time_t expire, gsize len, - guint idx, - rspamd_dkim_sign_context_t *ctx); +GString *rspamd_dkim_sign (struct rspamd_task *task, const gchar *selector, + const gchar *domain, time_t expire, gsize len, guint idx, + const gchar *arc_cv, rspamd_dkim_sign_context_t *ctx); rspamd_dkim_key_t * rspamd_dkim_key_ref (rspamd_dkim_key_t *k); void rspamd_dkim_key_unref (rspamd_dkim_key_t *k); diff --git a/src/plugins/dkim_check.c b/src/plugins/dkim_check.c index e5c775959..effced5e2 100644 --- a/src/plugins/dkim_check.c +++ b/src/plugins/dkim_check.c @@ -681,7 +681,7 @@ lua_dkim_sign_handler (lua_State *L) return 1; } - hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, 0, ctx); + hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, 0, NULL, ctx); if (hdr) { @@ -1185,7 +1185,8 @@ dkim_sign_callback (struct rspamd_task *task, void *unused) return; } - hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, 0, ctx); + hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, 0, NULL, + ctx); if (hdr) { rspamd_mempool_set_variable (task->task_pool,