Browse Source

[Minor] Parse CV results from Arc-Seal

tags/1.6.0
Vsevolod Stakhov 7 years ago
parent
commit
8824596a69
3 changed files with 135 additions and 44 deletions
  1. 120
    30
      src/libserver/dkim.c
  2. 12
    12
      src/libserver/dkim.h
  3. 3
    2
      src/plugins/dkim_check.c

+ 120
- 30
src/libserver/dkim.c View File

@@ -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);
}

+ 12
- 12
src/libserver/dkim.h View File

@@ -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);

+ 3
- 2
src/plugins/dkim_check.c View File

@@ -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,

Loading…
Cancel
Save