aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-01-13 14:22:04 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-01-13 14:22:04 +0000
commit60107a1f7d79df078c8528618c026858092d2d46 (patch)
tree36ced99f94959ab7a3c72823a6faad750bc5dcbd
parent776a0273b5dc02498fcc24373bdb76ae608219fa (diff)
downloadrspamd-60107a1f7d79df078c8528618c026858092d2d46.tar.gz
rspamd-60107a1f7d79df078c8528618c026858092d2d46.zip
[Project] Add concept of flexible actions
-rw-r--r--src/controller.c6
-rw-r--r--src/libmime/filter.c2
-rw-r--r--src/libserver/cfg_file.h40
-rw-r--r--src/libserver/cfg_utils.c87
-rw-r--r--src/lua/lua_config.c8
5 files changed, 111 insertions, 32 deletions
diff --git a/src/controller.c b/src/controller.c
index b8eface74..ee7e80e20 100644
--- a/src/controller.c
+++ b/src/controller.c
@@ -882,7 +882,7 @@ rspamd_controller_handle_actions (struct rspamd_http_connection_entry *conn_ent,
ucl_object_fromstring (rspamd_action_to_str (
act->action)), "action", 0, false);
ucl_object_insert_key (obj, ucl_object_fromdouble (
- act->score), "value", 0, false);
+ act->threshold), "value", 0, false);
ucl_array_append (top, obj);
}
@@ -2238,8 +2238,8 @@ rspamd_controller_handle_saveactions (
score = ucl_object_todouble (cur);
}
- if ((isnan (session->cfg->actions[act].score) != isnan (score)) ||
- (session->cfg->actions[act].score != score)) {
+ if ((isnan (session->cfg->actions[act].threshold) != isnan (score)) ||
+ (session->cfg->actions[act].threshold != score)) {
add_dynamic_action (ctx->cfg, DEFAULT_METRIC, act, score);
added ++;
}
diff --git a/src/libmime/filter.c b/src/libmime/filter.c
index 94c9ac223..2bda47fe7 100644
--- a/src/libmime/filter.c
+++ b/src/libmime/filter.c
@@ -71,7 +71,7 @@ rspamd_create_metric_result (struct rspamd_task *task)
if (task->cfg) {
for (i = 0; i < METRIC_ACTION_MAX; i++) {
- metric_res->actions_limits[i] = task->cfg->actions[i].score;
+ metric_res->actions_limits[i] = task->cfg->actions[i].threshold;
}
}
else {
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index 6d6ed6f62..22b154943 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -29,6 +29,7 @@
#include "libutil/radix.h"
#include "monitored.h"
#include "redis_pool.h"
+#include "contrib/uthash/uthash.h"
#define DEFAULT_BIND_PORT 11333
#define DEFAULT_CONTROL_PORT 11334
@@ -115,7 +116,7 @@ struct rspamd_symbols_group {
#define RSPAMD_SYMBOL_FLAG_UNGROUPPED (1 << 3)
/**
- * Symbol definition
+ * Symbol config definition
*/
struct rspamd_symbol {
gchar *name;
@@ -258,6 +259,9 @@ struct rspamd_log_format {
struct rspamd_log_format *prev, *next;
};
+/**
+ * Standard actions
+ */
enum rspamd_action_type {
METRIC_ACTION_REJECT = 0,
METRIC_ACTION_SOFT_REJECT,
@@ -265,13 +269,28 @@ enum rspamd_action_type {
METRIC_ACTION_ADD_HEADER,
METRIC_ACTION_GREYLIST,
METRIC_ACTION_NOACTION,
- METRIC_ACTION_MAX
+ METRIC_ACTION_MAX,
+ METRIC_ACTION_CUSTOM = 999,
+};
+
+enum rspamd_action_flags {
+ RSPAMD_ACTION_NORMAL = 0,
+ RSPAMD_ACTION_NO_THRESHOLD = (1u << 0),
+ RSPAMD_ACTION_THRESHOLD_ONLY = (1u << 1),
+ RSPAMD_ACTION_HAM = (1u << 2),
};
+/**
+ * Action config definition
+ */
struct rspamd_action {
enum rspamd_action_type action;
- gdouble score;
+ enum rspamd_action_flags flags;
guint priority;
+ gint lua_handler_ref; /* If special handling is needed */
+ gdouble threshold;
+ gchar *name;
+ UT_hash_handle hh; /* Index by name */
};
struct rspamd_config_post_load_script {
@@ -300,8 +319,8 @@ struct rspamd_config {
gdouble grow_factor; /**< grow factor for metric */
GHashTable *symbols; /**< weights of symbols in metric */
const gchar *subject; /**< subject rewrite string */
- GHashTable * groups; /**< groups of symbols */
- struct rspamd_action actions[METRIC_ACTION_MAX]; /**< all actions of the metric */
+ GHashTable * groups; /**< groups of symbols */
+ struct rspamd_action *actions; /**< all actions of the metric */
gboolean raw_mode; /**< work in raw mode instead of utf one */
gboolean one_shot_mode; /**< rules add only one symbol */
@@ -626,14 +645,12 @@ gboolean rspamd_config_add_symbol_group (struct rspamd_config *cfg,
* @param cfg config file
* @param metric metric name (or NULL for default metric)
* @param action_name symbolic name of action
- * @param score score limit
- * @param priority priority for action
+ * @param obj data to set for action
* @return TRUE if symbol has been inserted or FALSE if action already exists with higher priority
*/
gboolean rspamd_config_set_action_score (struct rspamd_config *cfg,
const gchar *action_name,
- gdouble score,
- guint priority);
+ const ucl_object_t *obj);
/**
* Checks if a specified C or lua module is enabled or disabled in the config.
@@ -662,6 +679,11 @@ gboolean rspamd_action_from_str (const gchar *data, gint *result);
const gchar * rspamd_action_to_str (enum rspamd_action_type action);
const gchar * rspamd_action_to_str_alt (enum rspamd_action_type action);
+/*
+ * Resort all actions (needed to operate with thresholds)
+ */
+void rspamd_actions_sort (struct rspamd_config *cfg);
+
/**
* Parse radix tree or radix map from ucl object
* @param cfg configuration object
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index a15bb9b8a..170595fb6 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -133,6 +133,29 @@ rspamd_config_new (enum rspamd_config_init_flags flags)
/* 16 sockets per DNS server */
cfg->dns_io_per_server = 16;
+ /* Add all internal actions to keep compatibility */
+ for (int i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) {
+ struct rspamd_action *action;
+
+ action = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*action));
+ action->threshold = NAN;
+ action->name = rspamd_mempool_strdup (cfg->cfg_pool,
+ rspamd_action_to_str (i));
+ action->action = i;
+
+ if (i == METRIC_ACTION_SOFT_REJECT) {
+ action->flags |= RSPAMD_ACTION_NO_THRESHOLD;
+ }
+ else if (i == METRIC_ACTION_GREYLIST) {
+ action->flags |= RSPAMD_ACTION_THRESHOLD_ONLY;
+ }
+ else if (i == METRIC_ACTION_NOACTION) {
+ action->flags |= RSPAMD_ACTION_HAM;
+ }
+
+ HASH_ADD_STR (cfg->actions, name, action);
+ }
+
/* Disable timeout */
cfg->task_timeout = DEFAULT_TASK_TIMEOUT;
@@ -265,6 +288,8 @@ rspamd_config_free (struct rspamd_config *cfg)
rspamd_monitored_ctx_destroy (cfg->monitored_ctx);
}
+ HASH_CLEAR (hh, cfg->actions);
+
rspamd_mempool_delete (cfg->cfg_pool);
if (cfg->checksum) {
@@ -828,17 +853,17 @@ rspamd_config_post_load (struct rspamd_config *cfg,
struct rspamd_worker_conf *wcf;
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) {
- if (!isnan (prev_score) && !isnan (cfg->actions[i].score)) {
- if (prev_score <= isnan (cfg->actions[i].score)) {
+ if (!isnan (prev_score) && !isnan (cfg->actions[i].threshold)) {
+ if (prev_score <= isnan (cfg->actions[i].threshold)) {
msg_warn_config ("incorrect metrics scores: action %s"
" has lower score: %.2f than action %s: %.2f",
rspamd_action_to_str (prev_act), prev_score,
- rspamd_action_to_str (i), cfg->actions[i].score);
+ rspamd_action_to_str (i), cfg->actions[i].threshold);
ret = FALSE;
}
}
- if (!isnan (cfg->actions[i].score)) {
+ if (!isnan (cfg->actions[i].threshold)) {
prev_score = cfg->actions[i].score;
prev_act = i;
}
@@ -1890,25 +1915,26 @@ rspamd_config_is_module_enabled (struct rspamd_config *cfg,
gboolean
rspamd_config_set_action_score (struct rspamd_config *cfg,
const gchar *action_name,
- gdouble score,
- guint priority)
+ const ucl_object_t *obj)
{
struct rspamd_action *act;
- gint act_num;
+ const ucl_object_t *elt;
g_assert (cfg != NULL);
g_assert (action_name != NULL);
- if (!rspamd_action_from_str (action_name, &act_num)) {
- msg_err_config ("invalid action name: %s", action_name);
- return FALSE;
- }
-
- g_assert (act_num >= METRIC_ACTION_REJECT && act_num < METRIC_ACTION_MAX);
+ HASH_FIND_STR (cfg->actions, action_name, act);
+ if (act) {
+ /* Existing element */
+ }
+ else {
+ /* Add new element */
+ act = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*act));
+ }
act = &cfg->actions[act_num];
- if (isnan (act->score)) {
+ if (isnan (act->threshold)) {
act->score = score;
act->priority = priority;
}
@@ -1928,7 +1954,7 @@ rspamd_config_set_action_score (struct rspamd_config *cfg,
action_name,
act->priority,
priority,
- act->score,
+ act->threshold,
score);
act->score = score;
@@ -2119,3 +2145,34 @@ rspamd_action_to_str_alt (enum rspamd_action_type action)
return "unknown action";
}
+
+static int
+rspamd_actions_cmp (const struct rspamd_action *a1, const struct rspamd_action *a2)
+{
+ if (!isnan (a1->threshold) && !isnan (a2->threshold)) {
+ if (a1->threshold < a2->threshold) {
+ return -1;
+ }
+ else if (a1->threshold > a2->threshold) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (isnan (a1->threshold) && isnan (a2->threshold)) {
+ return 0;
+ }
+ else if (isnan (a1->threshold)) {
+ return 1;
+ }
+ else {
+ return -1;
+ }
+}
+
+void
+rspamd_actions_sort (struct rspamd_config *cfg)
+{
+ HASH_SORT (cfg->actions, rspamd_actions_cmp);
+}
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index 31d4af79b..513c2da93 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -2170,8 +2170,8 @@ lua_config_get_metric_action (lua_State * L)
if (cfg && act_name) {
if (rspamd_action_from_str (act_name, &act)) {
- if (!isnan (cfg->actions[act].score)) {
- lua_pushnumber (L, cfg->actions[act].score);
+ if (!isnan (cfg->actions[act].threshold)) {
+ lua_pushnumber (L, cfg->actions[act].threshold);
}
else {
lua_pushnil (L);
@@ -2199,9 +2199,9 @@ lua_config_get_all_actions (lua_State * L)
lua_newtable (L);
for (act = METRIC_ACTION_REJECT; act < METRIC_ACTION_MAX; act ++) {
- if (!isnan (cfg->actions[act].score)) {
+ if (!isnan (cfg->actions[act].threshold)) {
lua_pushstring (L, rspamd_action_to_str (act));
- lua_pushnumber (L, cfg->actions[act].score);
+ lua_pushnumber (L, cfg->actions[act].threshold);
lua_settable (L, -3);
}
}