Exemple #1
0
static void
dkim_sign_callback (struct rspamd_task *task, void *unused)
{
	lua_State *L;
	struct rspamd_task **ptask;
	gboolean sign = FALSE;
	gint err_idx;
	GString *tb, *hdr;
	GError *err = NULL;
	const gchar *selector = NULL, *domain = NULL, *key = NULL;
	rspamd_dkim_sign_context_t *ctx;
	rspamd_dkim_sign_key_t *dkim_key;

	if (dkim_module_ctx->sign_condition_ref != -1) {
		sign = FALSE;
		L = task->cfg->lua_state;
		lua_pushcfunction (L, &rspamd_lua_traceback);
		err_idx = lua_gettop (L);

		lua_rawgeti (L, LUA_REGISTRYINDEX, dkim_module_ctx->sign_condition_ref);
		ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
		*ptask = task;
		rspamd_lua_setclass (L, "rspamd{task}", -1);

		if (lua_pcall (L, 1, 1, err_idx) != 0) {
			tb = lua_touserdata (L, -1);
			msg_err_task ("call to user extraction script failed: %v", tb);
			g_string_free (tb, TRUE);
		}
		else {
			if (lua_istable (L, -1)) {
				/*
				 * Get the following elements:
				 * - selector
				 * - domain
				 * - key
				 */
				if (!rspamd_lua_parse_table_arguments (L, -1, &err,
						"*key=S;*domain=S;*selector=S",
						&key, &domain, &selector)) {
					msg_err_task ("invalid return value from sign condition: %e",
							err);
					g_error_free (err);

					return;
				}

				dkim_key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash,
						key, time (NULL));

				if (dkim_key == NULL) {
					dkim_key = rspamd_dkim_sign_key_load (key, &err);

					if (dkim_key == NULL) {
						msg_err_task ("cannot load dkim key %s: %e",
								key, err);
						g_error_free (err);

						return;
					}

					rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
							g_strdup (key), dkim_key,
							time (NULL), 0);
				}

				ctx = rspamd_create_dkim_sign_context (task, dkim_key,
						DKIM_CANON_RELAXED, DKIM_CANON_RELAXED,
						dkim_module_ctx->sign_headers, &err);

				if (ctx == NULL) {
					msg_err_task ("cannot create sign context: %e",
							key, err);
					g_error_free (err);

					return;
				}

				hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, ctx);

				if (hdr) {
					rspamd_mempool_set_variable (task->task_pool, "dkim-signature",
							hdr, rspamd_gstring_free_hard);
				}

				sign = TRUE;
			}
			else {
				sign = FALSE;
			}
		}

		/* Result + error function */
		lua_settop (L, 0);

		if (!sign) {
			msg_debug_task ("skip signing as dkim condition callback returned"
					" false");
			return;
		}
	}
}
Exemple #2
0
static void
dkim_symbol_callback (struct rspamd_task *task, void *unused)
{
	GList *hlist;
	rspamd_dkim_context_t *ctx;
	rspamd_dkim_key_t *key;
	GError *err = NULL;
	struct raw_header *rh;
	struct dkim_check_result *res = NULL, *cur;
	guint checked = 0;
	/* First check if plugin should be enabled */
	if (task->user != NULL || rspamd_inet_address_is_local (task->from_addr)) {
		msg_info_task ("skip DKIM checks for local networks and authorized users");
		return;
	}
	/* Check whitelist */
	if (radix_find_compressed_addr (dkim_module_ctx->whitelist_ip,
			task->from_addr) != RADIX_NO_VALUE) {
		msg_info_task ("skip DKIM checks for whitelisted address");
		return;
	}

	/* Now check if a message has its signature */
	hlist = rspamd_message_get_header (task,
			DKIM_SIGNHEADER,
			FALSE);
	if (hlist != NULL) {
		msg_debug_task ("dkim signature found");

		while (hlist != NULL) {
			rh = (struct raw_header *)hlist->data;

			if (rh->decoded == NULL || rh->decoded[0] == '\0') {
				msg_info_task ("<%s> cannot load empty DKIM context",
						task->message_id);
				hlist = g_list_next (hlist);
				continue;
			}

			if (res == NULL) {
				res = rspamd_mempool_alloc0 (task->task_pool, sizeof (*res));
				res->prev = res;
				res->w = rspamd_session_get_watcher (task->s);
				cur = res;
			}
			else {
				cur = rspamd_mempool_alloc0 (task->task_pool, sizeof (*res));
			}

			cur->first = res;
			cur->res = -1;
			cur->task = task;
			cur->mult_allow = 1.0;
			cur->mult_deny = 1.0;

			ctx = rspamd_create_dkim_context (rh->decoded,
					task->task_pool,
					dkim_module_ctx->time_jitter,
					&err);
			if (ctx == NULL) {
				if (err != NULL) {
					msg_info_task ("<%s> cannot parse DKIM context: %e",
							task->message_id, err);
					g_error_free (err);
					err = NULL;
				}
				else {
					msg_info_task ("<%s> cannot parse DKIM context: "
							"unknown error",
							task->message_id);
				}

				hlist = g_list_next (hlist);
				continue;
			}
			else {
				/* Get key */

				cur->ctx = ctx;

				if (dkim_module_ctx->trusted_only &&
						(dkim_module_ctx->dkim_domains == NULL ||
								g_hash_table_lookup (dkim_module_ctx->dkim_domains,
										rspamd_dkim_get_domain (ctx)) == NULL)) {
					msg_debug_task ("skip dkim check for %s domain",
							rspamd_dkim_get_domain (ctx));
					hlist = g_list_next (hlist);

					continue;
				}

				key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash,
						rspamd_dkim_get_dns_key (ctx),
						task->tv.tv_sec);

				if (key != NULL) {
					cur->key = rspamd_dkim_key_ref (key);
					/* Release key when task is processed */
					rspamd_mempool_add_destructor (task->task_pool,
							dkim_module_key_dtor, cur->key);
				}
				else {
					rspamd_get_dkim_key (ctx,
							task,
							dkim_module_key_handler,
							cur);
				}
			}

			if (res != cur) {
				DL_APPEND (res, cur);
			}

			if (dkim_module_ctx->skip_multi) {
				if (hlist->next) {
					msg_info_task ("message has multiple signatures but we"
							" check only one as 'skip_multi' is set");
				}

				break;
			}

			checked ++;

			if (checked > dkim_module_ctx->max_sigs) {
				msg_info_task ("message has multiple signatures but we"
						" stopped after %d checked signatures as limit"
						" is reached", checked);
				break;
			}

			hlist = g_list_next (hlist);
		}
	}
	else {
		rspamd_task_insert_result (task,
				dkim_module_ctx->symbol_na,
				1.0,
				NULL);
	}

	if (res != NULL) {
		rspamd_session_watcher_push (task->s);
		dkim_module_check (res);
	}
}
Exemple #3
0
gint
lua_dkim_sign_handler (lua_State *L)
{
	struct rspamd_task *task = lua_check_task (L, 1);
	luaL_argcheck (L, lua_type (L, 2) == LUA_TTABLE, 2, "'table' expected");

	GError *err = NULL;
	GString *hdr;
	const gchar *selector = NULL, *domain = NULL, *key = NULL;
	rspamd_dkim_sign_context_t *ctx;
	rspamd_dkim_sign_key_t *dkim_key;
	/*
	 * Get the following elements:
	 * - selector
	 * - domain
	 * - key
	 */
	if (!rspamd_lua_parse_table_arguments (L, 2, &err,
			"*key=S;*domain=S;*selector=S",
			&key, &domain, &selector)) {
		msg_err_task ("invalid return value from sign condition: %e",
				err);
		g_error_free (err);

		lua_pushboolean (L, FALSE);
		return 1;
	}

	if (dkim_module_ctx->dkim_sign_hash == NULL) {
		dkim_module_ctx->dkim_sign_hash = rspamd_lru_hash_new (
				128,
				g_free, /* Keys are just C-strings */
				(GDestroyNotify)rspamd_dkim_sign_key_unref);
	}

	dkim_key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash,
			key, time (NULL));

	if (dkim_key == NULL) {
		dkim_key = rspamd_dkim_sign_key_load (key, &err);

		if (dkim_key == NULL) {
			msg_err_task ("cannot load dkim key %s: %e",
					key, err);
			g_error_free (err);

			lua_pushboolean (L, FALSE);
			return 1;
		}

		rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
				g_strdup (key), dkim_key,
				time (NULL), 0);
	}

	ctx = rspamd_create_dkim_sign_context (task, dkim_key,
			DKIM_CANON_RELAXED, DKIM_CANON_RELAXED,
			dkim_module_ctx->sign_headers, &err);

	if (ctx == NULL) {
		msg_err_task ("cannot create sign context: %e",
				err);
		g_error_free (err);

		lua_pushboolean (L, FALSE);
		return 1;
	}

	hdr = rspamd_dkim_sign (task, selector, domain, 0, 0, ctx);

	if (hdr) {
		rspamd_mempool_set_variable (task->task_pool, "dkim-signature",
				hdr, rspamd_gstring_free_hard);
		lua_pushboolean (L, TRUE);
		return 1;
	}

	lua_pushboolean (L, FALSE);
	return 1;
}
Exemple #4
0
static void
dkim_symbol_callback (struct rspamd_task *task, void *unused)
{
	GList *hlist;
	rspamd_dkim_context_t *ctx;
	rspamd_dkim_key_t *key;
	GError *err = NULL;
	struct raw_header *rh;
	struct dkim_check_result *res = NULL, *cur;
	/* First check if a message has its signature */

	hlist = rspamd_message_get_header (task,
			DKIM_SIGNHEADER,
			FALSE);
	if (hlist != NULL) {
		/* Check whitelist */
		msg_debug ("dkim signature found");
		if (radix_find_compressed_addr (dkim_module_ctx->whitelist_ip,
				task->from_addr) == RADIX_NO_VALUE) {
			/* Parse signature */
			msg_debug ("create dkim signature");

			while (hlist != NULL) {
				rh = (struct raw_header *)hlist->data;

				if (res == NULL) {
					res = rspamd_mempool_alloc0 (task->task_pool, sizeof (*res));
					res->prev = res;
					res->w = rspamd_session_get_watcher (task->s);
					cur = res;
				}
				else {
					cur = rspamd_mempool_alloc0 (task->task_pool, sizeof (*res));
				}

				cur->first = res;
				cur->res = -1;
				cur->task = task;
				cur->mult_allow = 1.0;
				cur->mult_deny = 1.0;

				ctx = rspamd_create_dkim_context (rh->decoded,
						task->task_pool,
						dkim_module_ctx->time_jitter,
						&err);
				if (ctx == NULL) {
					if (err != NULL) {
						msg_info ("<%s> cannot parse DKIM context: %s",
								task->message_id, err->message);
						g_error_free (err);
					}
					else {
						msg_info ("<%s> cannot parse DKIM context: unknown error",
								task->message_id);
					}

					hlist = g_list_next (hlist);
					continue;
				}
				else {
					/* Get key */

					cur->ctx = ctx;

					if (dkim_module_ctx->trusted_only &&
							(dkim_module_ctx->dkim_domains == NULL ||
									g_hash_table_lookup (dkim_module_ctx->dkim_domains,
											ctx->domain) == NULL)) {
						msg_debug ("skip dkim check for %s domain", ctx->domain);
						hlist = g_list_next (hlist);

						continue;
					}

					key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash,
							ctx->dns_key,
							task->tv.tv_sec);
					if (key != NULL) {
						debug_task ("found key for %s in cache", ctx->dns_key);
						cur->key = key;
					}
					else {
						debug_task ("request key for %s from DNS", ctx->dns_key);
						rspamd_get_dkim_key (ctx,
								task,
								dkim_module_key_handler,
								cur);
					}
				}

				if (res != cur) {
					DL_APPEND (res, cur);
				}

				hlist = g_list_next (hlist);
			}
		}
	}

	if (res != NULL) {
		rspamd_session_watcher_push (task->s);
		dkim_module_check (res);
	}
}
Exemple #5
0
static void
dkim_symbol_callback (struct rspamd_task *task, void *unused)
{
	GList *hlist;
	rspamd_dkim_context_t *ctx;
	rspamd_dkim_key_t *key;
	GError *err = NULL;
	struct raw_header *rh;
	/* First check if a message has its signature */

	hlist = message_get_header (task,
			DKIM_SIGNHEADER,
			FALSE);
	if (hlist != NULL) {
		/* Check whitelist */
		msg_debug ("dkim signature found");
		if (radix_find_compressed_addr (dkim_module_ctx->whitelist_ip,
				&task->from_addr) == RADIX_NO_VALUE) {
			/* Parse signature */
			msg_debug ("create dkim signature");
			/*
			 * Check only last signature as there is no way to check embeded signatures after
			 * resend or something like this
			 */
			if (dkim_module_ctx->skip_multi) {
				if (hlist->next != NULL) {
					msg_info (
						"<%s> skip dkim check as it has several dkim signatures",
						task->message_id);
					return;
				}
			}
			hlist = g_list_last (hlist);
			rh = (struct raw_header *)hlist->data;
			ctx = rspamd_create_dkim_context (rh->decoded,
					task->task_pool,
					dkim_module_ctx->time_jitter,
					&err);
			if (ctx == NULL) {
				msg_info ("cannot parse DKIM context: %s", err->message);
				g_error_free (err);
			}
			else {
				/* Get key */
				if (dkim_module_ctx->trusted_only &&
					(dkim_module_ctx->dkim_domains == NULL ||
					g_hash_table_lookup (dkim_module_ctx->dkim_domains,
					ctx->domain) == NULL)) {
					msg_debug ("skip dkim check for %s domain", ctx->domain);
					return;
				}
				key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash,
						ctx->dns_key,
						task->tv.tv_sec);
				if (key != NULL) {
					debug_task ("found key for %s in cache", ctx->dns_key);
					dkim_module_check (task, ctx, key);
				}
				else {
					debug_task ("request key for %s from DNS", ctx->dns_key);
					task->dns_requests++;
					rspamd_get_dkim_key (ctx,
						task->resolver,
						task->s,
						dkim_module_key_handler,
						task);
				}
			}
		}
	}
}