]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Finish rework of passthrough actions
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 11 Oct 2018 14:35:07 +0000 (15:35 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 11 Oct 2018 14:35:07 +0000 (15:35 +0100)
src/libmime/filter.c
src/libmime/filter.h
src/libmime/message.c
src/lua/lua_task.c

index cdbfdcfbf9adbac14ca7063265a9981c67945e1d..c06df1b773fcb50505cb8ab55db49dd8660fd822 100644 (file)
@@ -60,6 +60,7 @@ rspamd_create_metric_result (struct rspamd_task *task)
        metric_res->sym_groups = kh_init (rspamd_symbols_group_hash);
        metric_res->grow_factor = 0;
        metric_res->score = 0;
+       metric_res->passthrough_result = NULL;
 
        /* Optimize allocation */
        kh_resize (rspamd_symbols_group_hash, metric_res->sym_groups, 4);
@@ -82,6 +83,49 @@ rspamd_create_metric_result (struct rspamd_task *task)
        return metric_res;
 }
 
+static inline int
+rspamd_pr_sort (const struct rspamd_passthrough_result *pra,
+                               const struct rspamd_passthrough_result *prb)
+{
+       return prb->priority - pra->priority;
+}
+
+void
+rspamd_add_passthrough_result (struct rspamd_task *task,
+                                                                       enum rspamd_action_type action,
+                                                                       guint priority,
+                                                                       double target_score,
+                                                                       const gchar *message,
+                                                                       const gchar *module)
+{
+       struct rspamd_metric_result *metric_res;
+       struct rspamd_passthrough_result *pr;
+
+       metric_res = task->result;
+
+       pr = rspamd_mempool_alloc (task->task_pool, sizeof (*pr));
+       pr->action = action;
+       pr->priority = priority;
+       pr->message = message;
+       pr->module = module;
+       pr->target_score = target_score;
+
+       DL_APPEND (metric_res->passthrough_result, pr);
+       DL_SORT (metric_res->passthrough_result, rspamd_pr_sort);
+
+       if (!isnan (target_score)) {
+               msg_info_task ("<%s>: set pre-result to %s (%.2f): '%s' from %s(%d)",
+                               task->message_id, rspamd_action_to_str (action), target_score,
+                               message, module, priority);
+       }
+
+       else {
+               msg_info_task ("<%s>: set pre-result to %s (no score): '%s' from %s(%d)",
+                               task->message_id, rspamd_action_to_str (action),
+                               message, module, priority);
+       }
+}
+
 static inline gdouble
 rspamd_check_group_score (struct rspamd_task *task,
                const gchar *symbol,
@@ -417,12 +461,13 @@ enum rspamd_action_type
 rspamd_check_action_metric (struct rspamd_task *task, struct rspamd_metric_result *mres)
 {
        struct rspamd_action *action, *selected_action = NULL;
+       struct rspamd_passthrough_result *pr;
        double max_score = -(G_MAXDOUBLE), sc;
        int i;
        gboolean set_action = FALSE;
 
        /* We are not certain about the results during processing */
-       if (task->pre_result.action == METRIC_ACTION_MAX) {
+       if (task->result->passthrough_result == NULL) {
                for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
                        action = &task->cfg->actions[i];
                        sc = mres->actions_limits[i];
@@ -442,26 +487,33 @@ rspamd_check_action_metric (struct rspamd_task *task, struct rspamd_metric_resul
                }
        }
        else {
+               /* Peek the highest priority result */
+               pr = task->result->passthrough_result;
                sc = NAN;
 
-               for (i = task->pre_result.action; i < METRIC_ACTION_MAX; i ++) {
-                       selected_action = &task->cfg->actions[i];
-                       sc = mres->actions_limits[i];
+               if (isnan (pr->target_score)) {
+                       for (i = pr->action; i < METRIC_ACTION_MAX; i++) {
+                               selected_action = &task->cfg->actions[i];
+                               sc = mres->actions_limits[i];
 
-                       if (isnan (sc)) {
-                               if (i == task->pre_result.action) {
-                                       /* No scores defined, just avoid NaN */
-                                       sc = 0;
+                               if (isnan (sc)) {
+                                       if (i == pr->action) {
+                                               /* No scores defined, just avoid NaN */
+                                               sc = 0;
+                                               break;
+                                       }
+                               }
+                               else {
                                        break;
                                }
                        }
-                       else {
-                               break;
-                       }
+               }
+               else {
+                       sc = pr->target_score;
                }
 
                if (!isnan (sc)) {
-                       if (task->pre_result.action == METRIC_ACTION_NOACTION) {
+                       if (pr->action == METRIC_ACTION_NOACTION) {
                                mres->score = MIN (sc, mres->score);
                        }
                        else {
index 9137258f57a17d07a694e3afd0cec69cfde4b9f9..fdd0f8dc94c14557b2fc366a9d392d831333f0dd 100644 (file)
@@ -58,10 +58,25 @@ KHASH_INIT (rspamd_symbols_group_hash,
                1,
                rspamd_ptr_hash_func,
                rspamd_ptr_equal_func);
+
+#define RSPAMD_PASSTHROUGH_NORMAL 1
+#define RSPAMD_PASSTHROUGH_LOW 0
+#define RSPAMD_PASSTHROUGH_HIGH 2
+#define RSPAMD_PASSTHROUGH_CRITICAL 3
+
+struct rspamd_passthrough_result {
+       enum rspamd_action_type action;
+       guint priority;
+       double target_score;
+       const gchar *message;
+       const gchar *module;
+       struct rspamd_passthrough_result *prev, *next;
+};
+
 struct rspamd_metric_result {
        double score;                                                                   /**< total score                                                        */
        double grow_factor;                                                             /**< current grow factor                                        */
-
+       struct rspamd_passthrough_result *passthrough_result;
        khash_t(rspamd_symbols_hash) *symbols;                  /**< symbols of metric                                          */
        khash_t(rspamd_symbols_group_hash) *sym_groups; /**< groups of symbols                                          */
        gdouble actions_limits[METRIC_ACTION_MAX];              /**< set of actions for this metric                     */
@@ -74,6 +89,22 @@ struct rspamd_metric_result {
  */
 struct rspamd_metric_result * rspamd_create_metric_result (struct rspamd_task *task);
 
+/**
+ * Adds a new passthrough result to a task
+ * @param task
+ * @param action
+ * @param priority
+ * @param target_score
+ * @param message
+ * @param module
+ */
+void rspamd_add_passthrough_result (struct rspamd_task *task,
+                                                                       enum rspamd_action_type action,
+                                                                       guint priority,
+                                                                       double target_score,
+                                                                       const gchar *message,
+                                                                       const gchar *module);
+
 enum rspamd_symbol_insert_flags {
        RSPAMD_SYMBOL_INSERT_DEFAULT = 0,
        RSPAMD_SYMBOL_INSERT_SINGLE = (1 << 0),
index 4206211c14389d3f92641baece8835e1bce33375..43158d083cd6b9b24268f88c8e7e44990468224f 100644 (file)
@@ -32,6 +32,8 @@
 #include "libstemmer.h"
 #endif
 
+#include <math.h>
+
 #define GTUBE_SYMBOL "GTUBE"
 
 #define SET_PART_RAW(part) ((part)->flags &= ~RSPAMD_MIME_TEXT_PART_FLAG_UTF)
@@ -854,22 +856,18 @@ rspamd_message_process_text_part_maybe (struct rspamd_task *task,
 
        act = rspamd_check_gtube (task, text_part);
        if (act != METRIC_ACTION_NOACTION) {
-               struct rspamd_metric_result *mres;
-
-               mres = task->result;
+               struct rspamd_metric_result *mres = task->result;
+               gdouble score = NAN;
 
-               if (mres != NULL) {
-                       if (act == METRIC_ACTION_REJECT) {
-                               mres->score = rspamd_task_get_required_score (task, mres);
-                       }
-                       else {
-                               mres->score = mres->actions_limits[act];
-                       }
+               if (act == METRIC_ACTION_REJECT) {
+                       score = rspamd_task_get_required_score (task, mres);
+               }
+               else {
+                       score = mres->actions_limits[act];
                }
 
-               task->result = mres;
-               task->pre_result.action = act;
-               task->pre_result.str = "Gtube pattern";
+               rspamd_add_passthrough_result (task, act, RSPAMD_PASSTHROUGH_CRITICAL,
+                               score, "Gtube pattern", "GTUBE");
 
                if (ucl_object_lookup (task->messages, "smtp_message") == NULL) {
                        ucl_object_replace_key (task->messages,
index 7f2711e196255cb8179924d4dfb7b04769c27977..a6b32b089e68b58c40d833cadf856126b2ae9077 100644 (file)
@@ -1567,8 +1567,10 @@ lua_task_set_pre_result (lua_State * L)
 {
        LUA_TRACE_POINT;
        struct rspamd_task *task = lua_check_task (L, 1);
-       gchar *action_str;
+       const gchar *message = NULL, *module = NULL;
+       gdouble score = NAN;
        gint action = METRIC_ACTION_MAX;
+       guint priority = RSPAMD_PASSTHROUGH_NORMAL;
 
        if (task != NULL) {
 
@@ -1584,26 +1586,38 @@ lua_task_set_pre_result (lua_State * L)
                        rspamd_action_from_str (lua_tostring (L, 2), &action);
                }
 
-               if (action < METRIC_ACTION_MAX && action >= METRIC_ACTION_REJECT) {
-                       /* We also need to set the default metric to that result */
+               if (lua_type (L, 3) == LUA_TSTRING) {
+                       message = lua_tostring (L, 3);
 
-                       task->pre_result.action = action;
+                       /* Keep compatibility here :( */
+                       ucl_object_replace_key (task->messages,
+                                       ucl_object_fromstring (message), "smtp_message", 0,
+                                       false);
+               }
+               else {
+                       message = "unknown reason";
+               }
 
-                       if (lua_gettop (L) >= 3) {
-                               action_str = rspamd_mempool_strdup (task->task_pool,
-                                               luaL_checkstring (L, 3));
-                               task->pre_result.str = action_str;
-                               ucl_object_replace_key (task->messages,
-                                               ucl_object_fromstring (action_str), "smtp_message", 0,
-                                               false);
-                       }
-                       else {
-                               task->pre_result.str = "unknown";
-                       }
+               if (lua_type (L, 4) == LUA_TSTRING) {
+                       module = lua_tostring (L, 4);
+               }
+               else {
+                       module = "Unknown lua";
+               }
+
+               if (lua_type (L, 5) == LUA_TNUMBER) {
+                       score = lua_tonumber (L, 5);
+               }
+
+               if (lua_type (L, 6) == LUA_TNUMBER) {
+                       priority = lua_tonumber (L, 5);
+               }
+
+               if (action < METRIC_ACTION_MAX && action >= METRIC_ACTION_REJECT) {
 
-                       msg_info_task ("<%s>: set pre-result to %s: '%s'",
-                                               task->message_id, rspamd_action_to_str (action),
-                                               task->pre_result.str);
+                       rspamd_add_passthrough_result (task, action, priority,
+                                       score, rspamd_mempool_strdup (task->task_pool, message),
+                                       rspamd_mempool_strdup (task->task_pool, module));
 
                        /* Don't classify or filter message if pre-filter sets results */
                        task->processed_stages |= (RSPAMD_TASK_STAGE_FILTERS |
@@ -1629,7 +1643,7 @@ lua_task_has_pre_result (lua_State * L)
        struct rspamd_task *task = lua_check_task (L, 1);
 
        if (task) {
-               lua_pushboolean (L, task->pre_result.action != METRIC_ACTION_MAX);
+               lua_pushboolean (L, task->result->passthrough_result != NULL);
        }
        else {
                return luaL_error (L, "invalid arguments");