aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-06-14 13:23:15 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-06-14 13:23:15 +0100
commit4d32fb1b37d2ff46b4c6e1213a5bc163e3f2e96c (patch)
treeb24af7420652ebe418685907e60cecb7d381e293
parent0cbb51f4c06a63707f1e42646f032eb479b87b55 (diff)
downloadrspamd-4d32fb1b37d2ff46b4c6e1213a5bc163e3f2e96c.tar.gz
rspamd-4d32fb1b37d2ff46b4c6e1213a5bc163e3f2e96c.zip
[Project] Add preprocessed settings to the config structure
-rw-r--r--src/libserver/cfg_file.h42
-rw-r--r--src/libserver/cfg_utils.c112
-rw-r--r--src/libserver/protocol.c18
-rw-r--r--src/libserver/rspamd_symcache.c12
-rw-r--r--src/libserver/task.c4
-rw-r--r--src/libserver/task.h2
-rw-r--r--src/lua/lua_task.c4
7 files changed, 177 insertions, 17 deletions
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index b5780a599..dc11d7aab 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -302,6 +302,15 @@ struct rspamd_config_post_load_script {
struct rspamd_lang_detector;
+struct rspamd_config_settings_elt {
+ guint32 id;
+ const gchar *name;
+ ucl_object_t *symbols_enabled;
+ ucl_object_t *symbols_disabled;
+ struct rspamd_config_settings_elt *prev, *next;
+ ref_entry_t ref;
+};
+
/**
* Structure that stores all config data
*/
@@ -458,6 +467,7 @@ struct rspamd_config {
gchar *zstd_output_dictionary; /**< path to zstd output dictionary */
ucl_object_t *neighbours; /**< other servers in the cluster */
+ struct rspamd_config_settings_elt *setting_ids; /**< preprocessed settings ids */
struct rspamd_lang_detector *lang_det; /**< language detector */
ref_entry_t ref; /**< reference counter */
@@ -716,6 +726,38 @@ gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
GError **err);
/**
+ * Adds new settings id to be preprocessed
+ * @param cfg
+ * @param name
+ * @param symbols_enabled
+ * @param symbols_disabled
+ */
+void rspamd_config_register_settings_id (struct rspamd_config *cfg,
+ const gchar *name,
+ ucl_object_t *symbols_enabled,
+ ucl_object_t *symbols_disabled);
+
+/**
+ * Finds settings id element and obtain reference count (must be unrefed by callee)
+ * @param cfg
+ * @param id
+ * @return
+ */
+struct rspamd_config_settings_elt *rspamd_config_find_settings_id_ref (
+ struct rspamd_config *cfg,
+ guint32 id);
+
+/**
+ * Finds settings id element and obtain reference count (must be unrefed by callee)
+ * @param cfg
+ * @param id
+ * @return
+ */
+struct rspamd_config_settings_elt *rspamd_config_find_settings_name_ref (
+ struct rspamd_config *cfg,
+ const gchar *name, gsize namelen);
+
+/**
* Returns action object by name
* @param cfg
* @param name
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.c
index 1c8b2ce5f..e32ca7020 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.c
@@ -2334,3 +2334,115 @@ rspamd_actions_sort (struct rspamd_config *cfg)
{
HASH_SORT (cfg->actions, rspamd_actions_cmp);
}
+
+static void
+rspamd_config_settings_elt_dtor (struct rspamd_config_settings_elt *e)
+{
+ if (e->symbols_enabled) {
+ ucl_object_unref (e->symbols_enabled);
+ }
+ if (e->symbols_disabled) {
+ ucl_object_unref (e->symbols_disabled);
+ }
+}
+
+static inline guint32
+rspamd_config_name_to_id (const gchar *name, gsize namelen)
+{
+ guint64 h;
+
+ h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64,
+ name, strlen (name), 0x0);
+ /* Take the lower part of hash as LE number */
+ return ((guint32)GUINT64_TO_LE (h));
+}
+
+struct rspamd_config_settings_elt *
+rspamd_config_find_settings_id_ref (struct rspamd_config *cfg,
+ guint32 id)
+{
+ struct rspamd_config_settings_elt *cur;
+
+ DL_FOREACH (cfg->setting_ids, cur) {
+ if (cur->id == id) {
+ REF_RETAIN (cur);
+ return cur;
+ }
+ }
+
+ return NULL;
+}
+
+struct rspamd_config_settings_elt *rspamd_config_find_settings_name_ref (
+ struct rspamd_config *cfg,
+ const gchar *name, gsize namelen)
+{
+ guint32 id;
+
+ id = rspamd_config_name_to_id (name, namelen);
+
+ return rspamd_config_find_settings_id_ref (cfg, id);
+}
+
+void
+rspamd_config_register_settings_id (struct rspamd_config *cfg,
+ const gchar *name,
+ ucl_object_t *symbols_enabled,
+ ucl_object_t *symbols_disabled)
+{
+ struct rspamd_config_settings_elt *elt;
+ guint32 id;
+
+ id = rspamd_config_name_to_id (name, strlen (name));
+ elt = rspamd_config_find_settings_id_ref (cfg, id);
+
+ if (elt) {
+ /* Need to replace */
+ struct rspamd_config_settings_elt *nelt;
+
+ DL_DELETE (cfg->setting_ids, elt);
+
+ nelt = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*nelt));
+
+ nelt->id = id;
+ nelt->name = rspamd_mempool_strdup (cfg->cfg_pool, name);
+
+ if (symbols_enabled) {
+ nelt->symbols_enabled = ucl_object_ref (symbols_enabled);
+ }
+
+ if (symbols_disabled) {
+ nelt->symbols_disabled = ucl_object_ref (symbols_disabled);
+ }
+
+ REF_INIT_RETAIN (nelt, rspamd_config_settings_elt_dtor);
+ msg_info_config ("replace settings id %d (%s)", id, name);
+ DL_APPEND (cfg->setting_ids, nelt);
+
+ /*
+ * Need to unref old element twice as there are two reference holders:
+ * 1. Config structure as we call REF_INIT_RETAIN
+ * 2. rspamd_config_find_settings_id_ref also increases refcount
+ */
+ REF_RELEASE (elt);
+ REF_RELEASE (elt);
+ }
+ else {
+ elt = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*elt));
+
+ elt->id = id;
+ elt->name = rspamd_mempool_strdup (cfg->cfg_pool, name);
+
+ if (symbols_enabled) {
+ elt->symbols_enabled = ucl_object_ref (symbols_enabled);
+ }
+
+ if (symbols_disabled) {
+ elt->symbols_disabled = ucl_object_ref (symbols_disabled);
+ }
+
+ msg_info_config ("register new settings id %d (%s)", id, name);
+ REF_INIT_RETAIN (elt, rspamd_config_settings_elt_dtor);
+ DL_APPEND (cfg->setting_ids, elt);
+ }
+}
diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c
index 7d3ccb27d..5cd0568da 100644
--- a/src/libserver/protocol.c
+++ b/src/libserver/protocol.c
@@ -483,13 +483,14 @@ rspamd_protocol_handle_headers (struct rspamd_task *task,
task->subject = rspamd_mempool_ftokdup (task->task_pool, hv_tok);
}
IF_HEADER (SETTINGS_ID_HEADER) {
- guint64 h;
-
msg_debug_protocol ("read settings-id header, value: %V", hv);
- h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64,
- hv_tok->begin, hv_tok->len, 0x0);
- /* Take the lower part of hash as LE number */
- task->settings_id = (guint32)GUINT64_TO_LE (h);
+ task->settings_elt = rspamd_config_find_settings_name_ref (
+ task->cfg, hv_tok->begin, hv_tok->len);
+
+ if (task->settings_elt == NULL) {
+ msg_warn_protocol ("unknown settings id: %V",
+ hv);
+ }
}
break;
case 'u':
@@ -1702,10 +1703,9 @@ rspamd_protocol_write_log_pipe (struct rspamd_task *task)
ls = g_malloc0 (sz);
/* Handle settings id */
- sid = task->settings_id;
- if (sid) {
- ls->settings_id = sid;
+ if (task->settings_elt) {
+ ls->settings_id = task->settings_elt->id;
}
else {
ls->settings_id = 0;
diff --git a/src/libserver/rspamd_symcache.c b/src/libserver/rspamd_symcache.c
index 034049005..22f4c3229 100644
--- a/src/libserver/rspamd_symcache.c
+++ b/src/libserver/rspamd_symcache.c
@@ -1425,24 +1425,26 @@ static gboolean
rspamd_symcache_is_item_allowed (struct rspamd_task *task,
struct rspamd_symcache_item *item)
{
- if (task->settings_id != 0) {
+ if (task->settings_elt != 0) {
+ guint32 id = task->settings_elt->id;
+
if (item->forbidden_ids.st[0] != 0 &&
rspamd_symcache_check_id_list (&item->forbidden_ids,
- task->settings_id)) {
+ id)) {
msg_debug_cache_task ("deny execution of %s as it is forbidden for "
"settings id %d",
item->symbol,
- task->settings_id);
+ id);
return FALSE;
}
if (item->allowed_ids.st[0] != 0 &&
!rspamd_symcache_check_id_list (&item->allowed_ids,
- task->settings_id)) {
+ id)) {
msg_debug_cache_task ("deny execution of %s as it is not listed as allowed for "
"settings id %d",
item->symbol,
- task->settings_id);
+ id);
return FALSE;
}
}
diff --git a/src/libserver/task.c b/src/libserver/task.c
index a7c1bc478..16b33294e 100644
--- a/src/libserver/task.c
+++ b/src/libserver/task.c
@@ -313,6 +313,10 @@ rspamd_task_free (struct rspamd_task *task)
ucl_object_unref (task->settings);
}
+ if (task->settings_elt != NULL) {
+ REF_RELEASE (task->settings_elt);
+ }
+
if (task->client_addr) {
rspamd_inet_address_free (task->client_addr);
}
diff --git a/src/libserver/task.h b/src/libserver/task.h
index 079e388df..263f06719 100644
--- a/src/libserver/task.h
+++ b/src/libserver/task.h
@@ -206,7 +206,7 @@ struct rspamd_task {
gpointer checkpoint; /**< Opaque checkpoint data */
ucl_object_t *settings; /**< Settings applied to task */
guint32 processed_stages; /**< bits of stages that are processed */
- guint32 settings_id; /**< hashed settings id */
+ struct rspamd_config_settings_elt *settings_elt; /**< preprocessed settings id elt */
const gchar *classifier; /**< Classifier to learn (if needed) */
struct rspamd_lang_detector *lang_det; /**< Languages detector */
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c
index 3218a958f..f562d1ca6 100644
--- a/src/lua/lua_task.c
+++ b/src/lua/lua_task.c
@@ -4872,8 +4872,8 @@ lua_task_get_settings_id (lua_State *L)
if (task != NULL) {
- if (task->settings_id) {
- lua_pushnumber (L, task->settings_id);
+ if (task->settings_elt) {
+ lua_pushnumber (L, task->settings_elt->id);
}
else {
lua_pushnil (L);