#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, \
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;
gint8 *b;
gint8 *bh;
gchar *dns_key;
+ enum rspamd_arc_seal_cv cv;
const gchar *dkim_header;
};
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[] = {
[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 ()
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)
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,
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;
* @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)
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;
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;
}
}
-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;
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);
}
#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 */
* @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);