/* * Copyright 2023 Vsevolod Stakhov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file scan_result.h * Scan result holder */ #ifndef RSPAMD_SCAN_RESULT_H #define RSPAMD_SCAN_RESULT_H #include "config.h" #include "rspamd_symcache.h" #include "task.h" #ifdef __cplusplus extern "C" { #endif struct rspamd_task; struct rspamd_settings; struct rspamd_classifier_config; struct rspamd_symbol_option { gchar *option; gsize optlen; struct rspamd_symbol_option *prev, *next; }; enum rspamd_symbol_result_flags { RSPAMD_SYMBOL_RESULT_NORMAL = 0, RSPAMD_SYMBOL_RESULT_IGNORED = (1 << 0) }; struct kh_rspamd_options_hash_s; /** * Rspamd symbol */ struct rspamd_symbol_result { double score; /**< symbol's score */ struct kh_rspamd_options_hash_s *options; /**< list of symbol's options */ struct rspamd_symbol_option *opts_head; /**< head of linked list of options */ const gchar *name; struct rspamd_symbol *sym; /**< symbol configuration */ gssize opts_len; /**< total size of all options (negative if truncated option is added) */ guint nshots; int flags; struct rspamd_symbol_result *next; /**< for shadow results */ }; #define RSPAMD_PASSTHROUGH_NORMAL 1 #define RSPAMD_PASSTHROUGH_LOW 0 #define RSPAMD_PASSTHROUGH_HIGH 2 #define RSPAMD_PASSTHROUGH_CRITICAL 3 #define RSPAMD_PASSTHROUGH_LEAST (1u << 0u) #define RSPAMD_PASSTHROUGH_NO_SMTP_MESSAGE (1u << 1u) #define RSPAMD_PASSTHROUGH_PROCESS_ALL (1u << 2u) struct rspamd_passthrough_result { struct rspamd_action *action; guint priority; guint flags; double target_score; const gchar *message; const gchar *module; struct rspamd_passthrough_result *prev, *next; }; enum rspamd_action_config_flags { RSPAMD_ACTION_RESULT_DEFAULT = 0, RSPAMD_ACTION_RESULT_NO_THRESHOLD = (1u << 0u), RSPAMD_ACTION_RESULT_DISABLED = (1u << 1u), }; struct rspamd_action_config { gdouble cur_limit; int flags; struct rspamd_action *action; }; struct kh_rspamd_symbols_hash_s; struct kh_rspamd_symbols_group_hash_s; struct rspamd_scan_result { double score; /**< total score */ double grow_factor; /**< current grow factor */ struct rspamd_passthrough_result *passthrough_result; double positive_score; double negative_score; struct kh_rspamd_symbols_hash_s *symbols; /**< symbols of metric */ struct kh_rspamd_symbols_group_hash_s *sym_groups; /**< groups of symbols */ struct rspamd_action_config *actions_config; const gchar *name; /**< for named results, NULL is the default result */ struct rspamd_task *task; /**< back reference */ gint symbol_cbref; /**< lua function that defines if a symbol can be inserted, -1 if unused */ guint nactions; guint npositive; guint nnegative; guint nresults; /**< all results: positive, negative, passthrough etc */ guint nresults_postfilters; /**< how many results are there before postfilters stage */ struct rspamd_scan_result *prev, *next; /**< double linked list of results */ }; /** * Create or return existing result for the specified metric name * @param task task object * @return metric result or NULL if metric `name` has not been found */ struct rspamd_scan_result *rspamd_create_metric_result(struct rspamd_task *task, const gchar *name, gint lua_sym_cbref); /** * Find result with a specific name (NULL means the default result) * @param task * @param name * @return */ struct rspamd_scan_result *rspamd_find_metric_result(struct rspamd_task *task, const gchar *name); /** * Adds a new passthrough result to a task * @param task * @param action * @param priority * @param target_score * @param message * @param module */ bool rspamd_add_passthrough_result(struct rspamd_task *task, struct rspamd_action *action, guint priority, double target_score, const gchar *message, const gchar *module, guint flags, struct rspamd_scan_result *scan_result); enum rspamd_symbol_insert_flags { RSPAMD_SYMBOL_INSERT_DEFAULT = 0, RSPAMD_SYMBOL_INSERT_SINGLE = (1 << 0), RSPAMD_SYMBOL_INSERT_ENFORCE = (1 << 1), }; /** * Insert a result to task * @param task worker's task that present message from user * @param metric_name metric's name to which we need to insert result * @param symbol symbol to insert * @param weight numeric weight for symbol * @param opts list of symbol's options */ struct rspamd_symbol_result *rspamd_task_insert_result_full(struct rspamd_task *task, const gchar *symbol, double weight, const gchar *opts, enum rspamd_symbol_insert_flags flags, struct rspamd_scan_result *result); #define rspamd_task_insert_result_single(task, symbol, weight, opts) \ rspamd_task_insert_result_full((task), (symbol), (weight), (opts), RSPAMD_SYMBOL_INSERT_SINGLE, NULL) #define rspamd_task_insert_result(task, symbol, weight, opts) \ rspamd_task_insert_result_full((task), (symbol), (weight), (opts), RSPAMD_SYMBOL_INSERT_DEFAULT, NULL) /** * Removes a symbol from a specific symbol result * @param task * @param symbol * @param result * @return */ struct rspamd_symbol_result *rspamd_task_remove_symbol_result( struct rspamd_task *task, const gchar *symbol, struct rspamd_scan_result *result); /** * Adds new option to symbol * @param task * @param s * @param opt */ gboolean rspamd_task_add_result_option(struct rspamd_task *task, struct rspamd_symbol_result *s, const gchar *opt, gsize vlen); /** * Finds symbol result * @param task * @param sym * @return */ struct rspamd_symbol_result * rspamd_task_find_symbol_result(struct rspamd_task *task, const char *sym, struct rspamd_scan_result *result); /** * Compatibility function to iterate on symbols hash * @param task * @param func * @param ud */ void rspamd_task_symbol_result_foreach(struct rspamd_task *task, struct rspamd_scan_result *result, GHFunc func, gpointer ud); /** * Default consolidation function for metric, it get all symbols and multiply symbol * weight by some factor that is specified in config. Default factor is 1. * @param task worker's task that present message from user * @param metric_name name of metric * @return result metric weight */ double rspamd_factor_consolidation_func(struct rspamd_task *task, const gchar *metric_name, const gchar *unused); /** * Check thresholds and return action for a task * @param task * @return */ struct rspamd_action *rspamd_check_action_metric(struct rspamd_task *task, struct rspamd_passthrough_result **ppr, struct rspamd_scan_result *scan_result); struct rspamd_action_config *rspamd_find_action_config_for_action(struct rspamd_scan_result *scan_result, struct rspamd_action *act); #ifdef __cplusplus } #endif #endif