diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-01-13 14:22:04 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-01-13 14:22:04 +0000 |
commit | 60107a1f7d79df078c8528618c026858092d2d46 (patch) | |
tree | 36ced99f94959ab7a3c72823a6faad750bc5dcbd | |
parent | 776a0273b5dc02498fcc24373bdb76ae608219fa (diff) | |
download | rspamd-60107a1f7d79df078c8528618c026858092d2d46.tar.gz rspamd-60107a1f7d79df078c8528618c026858092d2d46.zip |
[Project] Add concept of flexible actions
-rw-r--r-- | src/controller.c | 6 | ||||
-rw-r--r-- | src/libmime/filter.c | 2 | ||||
-rw-r--r-- | src/libserver/cfg_file.h | 40 | ||||
-rw-r--r-- | src/libserver/cfg_utils.c | 87 | ||||
-rw-r--r-- | src/lua/lua_config.c | 8 |
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); } } |