commit 96986ba: [Project] More steps to flexible actions
Vsevolod Stakhov
vsevolod at highsecure.ru
Mon Jan 14 18:00:05 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-01-14 09:47:05 +0000
URL: https://github.com/rspamd/rspamd/commit/96986ba7f75858395a35c87305427b16eca96547
[Project] More steps to flexible actions
---
src/libserver/cfg_file.h | 13 ++++-
src/libserver/cfg_utils.c | 135 ++++++++++++++++++++++++++++++++++++----------
src/lua/lua_config.c | 43 ++++++++++++---
3 files changed, 152 insertions(+), 39 deletions(-)
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index 22b154943..3a8094585 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -29,7 +29,6 @@
#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
@@ -280,6 +279,7 @@ enum rspamd_action_flags {
RSPAMD_ACTION_HAM = (1u << 2),
};
+struct UT_hash_handle;
/**
* Action config definition
*/
@@ -290,7 +290,7 @@ struct rspamd_action {
gint lua_handler_ref; /* If special handling is needed */
gdouble threshold;
gchar *name;
- UT_hash_handle hh; /* Index by name */
+ struct UT_hash_handle hh; /* Index by name */
};
struct rspamd_config_post_load_script {
@@ -699,6 +699,15 @@ gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
struct rspamd_radix_map_helper **target,
GError **err);
+/**
+ * Returns action object by name
+ * @param cfg
+ * @param name
+ * @return
+ */
+struct rspamd_action * rspamd_config_get_action (struct rspamd_config *cfg,
+ const gchar *name);
+
#define msg_err_config(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
cfg->cfg_pool->tag.tagname, cfg->checksum, \
G_STRFUNC, \
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index 170595fb6..5e3193cba 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -17,6 +17,8 @@
#include "cfg_file.h"
#include "rspamd.h"
+#include "../../contrib/mumhash/mum.h"
+#define HASH_CASELESS
#include "uthash_strcase.h"
#include "filter.h"
#include "lua/lua_common.h"
@@ -1038,12 +1040,6 @@ rspamd_config_init_metric (struct rspamd_config *cfg)
cfg->symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
cfg->groups = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
- cfg->actions[i].score = NAN;
- cfg->actions[i].action = i;
- cfg->actions[i].priority = 0;
- }
-
cfg->subject = SPAM_SUBJECT;
rspamd_mempool_add_destructor (cfg->cfg_pool,
(rspamd_mempool_destruct_t) g_hash_table_unref,
@@ -1912,6 +1908,72 @@ rspamd_config_is_module_enabled (struct rspamd_config *cfg,
return TRUE;
}
+static gboolean
+rspamd_config_action_from_ucl (struct rspamd_config *cfg,
+ struct rspamd_action *act,
+ const ucl_object_t *obj,
+ guint priority)
+{
+ const ucl_object_t *elt;
+ gdouble threshold = NAN;
+ guint flags = 0, std_act;
+
+ elt = ucl_object_lookup_any (obj, "score", "threshold", NULL);
+
+ if (elt) {
+ threshold = ucl_object_todouble (elt);
+ }
+
+ elt = ucl_object_lookup_any (obj, "flags");
+
+ if (elt && ucl_object_type (elt) == UCL_ARRAY) {
+ const ucl_object_t *cur;
+ ucl_object_iter_t it = NULL;
+
+ while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
+ if (ucl_object_type (cur) == UCL_STRING) {
+ const gchar *fl_str = ucl_object_tostring (cur);
+
+ if (g_ascii_strcasecmp (fl_str, "no_threshold") == 0) {
+ flags |= RSPAMD_ACTION_NO_THRESHOLD;
+ }
+ else if (g_ascii_strcasecmp (fl_str, "threshold_only") == 0) {
+ flags |= RSPAMD_ACTION_THRESHOLD_ONLY;
+ }
+ else if (g_ascii_strcasecmp (fl_str, "ham") == 0) {
+ flags |= RSPAMD_ACTION_HAM;
+ }
+ else {
+ msg_warn_config ("unknown action flag: %s", fl_str);
+ }
+ }
+ }
+ }
+
+ /* TODO: add lua references support */
+
+ if (isnan (threshold) && !(flags & RSPAMD_ACTION_NO_THRESHOLD)) {
+ msg_err_config ("action %s has no threshold being set and it is not"
+ " a no threshold action", act->name);
+
+ return FALSE;
+ }
+
+ act->threshold = threshold;
+ act->flags = flags;
+
+ if (rspamd_action_from_str (act->name, &std_act)) {
+ act->action = std_act;
+ }
+ else {
+ act->action = METRIC_ACTION_CUSTOM;
+ }
+
+ rspamd_actions_sort (cfg);
+
+ return TRUE;
+}
+
gboolean
rspamd_config_set_action_score (struct rspamd_config *cfg,
const gchar *action_name,
@@ -1919,52 +1981,67 @@ rspamd_config_set_action_score (struct rspamd_config *cfg,
{
struct rspamd_action *act;
const ucl_object_t *elt;
+ guint priority = ucl_object_get_priority (obj);
g_assert (cfg != NULL);
g_assert (action_name != NULL);
+ elt = ucl_object_lookup (obj, "priority");
+
+ if (elt) {
+ priority = ucl_object_toint (elt);
+ }
+
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->threshold)) {
- act->score = score;
- act->priority = priority;
- }
- else {
- if (act->priority > priority) {
+ if (act->priority <= priority) {
+ /* We can replace data */
msg_info_config ("action %s has been already registered with "
- "priority %ud, do not override (new priority: %ud)",
+ "priority %ud, override it with new priority: %ud, "
+ "old score: %.2f, new score: %.2f",
action_name,
act->priority,
- priority);
- return FALSE;
+ priority,
+ act->threshold,
+ ucl_object_todouble (
+ ucl_object_lookup_any (obj, "score", "threshold", NULL)));
+ return rspamd_config_action_from_ucl (cfg, act, obj, priority);
}
else {
msg_info_config ("action %s has been already registered with "
- "priority %ud, override it with new priority: %ud, "
- "old score: %.2f, new score: %.2f",
+ "priority %ud, do not override (new priority: %ud)",
action_name,
act->priority,
- priority,
- act->threshold,
- score);
+ priority);
+ }
+ }
+ else {
+ /* Add new element */
+ act = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*act));
+ act->name = rspamd_mempool_strdup (cfg->cfg_pool, action_name);
- act->score = score;
- act->priority = priority;
+ if (rspamd_config_action_from_ucl (cfg, act, obj, priority)) {
+ HASH_ADD_STR (cfg->actions, name, act);
+ }
+ else {
+ return FALSE;
}
}
return TRUE;
}
+struct rspamd_action *
+rspamd_config_get_action (struct rspamd_config *cfg, const gchar *name)
+{
+ struct rspamd_action *res = NULL;
+
+ HASH_FIND_STR (cfg->actions, name, res);
+
+ return res;
+}
gboolean
rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index 513c2da93..0b9811272 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -2127,9 +2127,10 @@ lua_config_set_metric_action (lua_State * L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *name = NULL;
- double weight;
+ double threshold = NAN;
GError *err = NULL;
gdouble priority = 0.0;
+ ucl_object_t *obj_tbl = NULL;
if (cfg) {
@@ -2137,7 +2138,7 @@ lua_config_set_metric_action (lua_State * L)
if (!rspamd_lua_parse_table_arguments (L, 2, &err,
"*action=S;score=N;"
"priority=N",
- &name, &weight,
+ &name, &threshold,
&priority)) {
msg_err_config ("bad arguments: %e", err);
g_error_free (err);
@@ -2145,12 +2146,36 @@ lua_config_set_metric_action (lua_State * L)
return 0;
}
}
+ else if (lua_type (L, 2) == LUA_TSTRING && lua_type (L, 3) == LUA_TTABLE) {
+ name = lua_tostring (L, 2);
+ obj_tbl = ucl_object_lua_import (L, 3);
+
+ if (obj_tbl) {
+ if (name) {
+ rspamd_config_set_action_score (cfg, name, obj_tbl);
+ ucl_object_unref (obj_tbl);
+ }
+ else {
+ ucl_object_unref (obj_tbl);
+ return luaL_error (L, "invalid first argument, action name expected");
+ }
+ }
+ else {
+ return luaL_error (L, "invalid second argument, table expected");
+ }
+ }
else {
return luaL_error (L, "invalid arguments, table expected");
}
- if (name != NULL && weight != 0) {
- rspamd_config_set_action_score (cfg, name, weight, (guint)priority);
+ if (name != NULL && !isnan (threshold) && threshold != 0) {
+ obj_tbl = ucl_object_typed_new (UCL_OBJECT);
+ ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (threshold),
+ "score", 0, false);
+ ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (priority),
+ "priority", 0, false);
+ rspamd_config_set_action_score (cfg, name, obj_tbl);
+ ucl_object_unref (obj_tbl);
}
}
else {
@@ -2166,12 +2191,14 @@ lua_config_get_metric_action (lua_State * L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *act_name = luaL_checkstring (L, 2);
- gint act = 0;
+ struct rspamd_action *act;
if (cfg && act_name) {
- if (rspamd_action_from_str (act_name, &act)) {
- if (!isnan (cfg->actions[act].threshold)) {
- lua_pushnumber (L, cfg->actions[act].threshold);
+ act = rspamd_config_get_action (cfg, act_name);
+
+ if (act) {
+ if (!isnan (act->threshold)) {
+ lua_pushnumber (L, act->threshold);
}
else {
lua_pushnil (L);
More information about the Commits
mailing list