]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Add preprocessed settings to the config structure
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 14 Jun 2019 12:23:15 +0000 (13:23 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 14 Jun 2019 12:23:15 +0000 (13:23 +0100)
src/libserver/cfg_file.h
src/libserver/cfg_utils.c
src/libserver/protocol.c
src/libserver/rspamd_symcache.c
src/libserver/task.c
src/libserver/task.h
src/lua/lua_task.c

index b5780a599619823e2e1c514c4a36c224368d250c..dc11d7aab84773a6a64b7f202c588305619aed29 100644 (file)
@@ -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                                                                  */
@@ -715,6 +725,38 @@ gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
                struct rspamd_radix_map_helper **target,
                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
index 1c8b2ce5feb10000c67319d4e5353c8aea106d90..e32ca70201a447b612aac94c713969ee3463e6b1 100644 (file)
@@ -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);
+       }
+}
index 7d3ccb27de35393276b4b4f417618ea2f3610280..5cd0568daea9884569dc4ccbc2eab741f576f341 100644 (file)
@@ -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;
index 0340490052f4c0b7c8d10dc60b5a009445f84c81..22f4c3229093c3922d337442a8961a816c9d4d8f 100644 (file)
@@ -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;
                }
        }
index a7c1bc47814bb80ca41d0a084c2c052021d69aba..16b33294e59727b9e525e5ef65ad6bad86db02fc 100644 (file)
@@ -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);
                }
index 079e388df9ec06da95eab42b57581443c8b5bd30..263f067199dbc2c4e6a9f5d6395d9dfe37e65791 100644 (file)
@@ -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                                                         */
index 3218a958f5f43623de9464294a439d85e52c4ecc..f562d1ca6d92361c1b9d0419ae967436747e1397 100644 (file)
@@ -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);