]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Add some generic code to squeeze lua rules
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 15 Mar 2018 16:24:44 +0000 (16:24 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 15 Mar 2018 16:24:44 +0000 (16:24 +0000)
lualib/lua_squeeze_rules.lua [new file with mode: 0644]
lualib/lua_util.lua
rules/headers_checks.lua
rules/misc.lua
src/lua/lua_config.c

diff --git a/lualib/lua_squeeze_rules.lua b/lualib/lua_squeeze_rules.lua
new file mode 100644 (file)
index 0000000..d740e2e
--- /dev/null
@@ -0,0 +1,97 @@
+--[[
+Copyright (c) 2018, Vsevolod Stakhov <vsevolod@highsecure.ru>
+
+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.
+]]--
+
+local exports = {}
+local logger = require 'rspamd_logger'
+
+-- Squeezed rules part
+local squeezed_rules = {} -- plain vector of all rules squeezed
+local squeezed_symbols = {} -- indexed by name of symbol
+local squeezed_deps = {} -- squeezed deps
+local SN = 'lua_squeeze'
+local squeeze_function_id
+
+local function lua_squeeze_function(task)
+  if not squeezed_symbols then
+    for k,v in pairs(squeezed_symbols) do
+      if not squeezed_exceptions[k] then
+        logger.debugm(SN, task, 'added squeezed rule: %s', k)
+        table.insert(squeezed_rules, v)
+      else
+        logger.debugm(SN, task, 'skipped squeezed rule: %s', k)
+      end
+    end
+
+    squeezed_symbols = nil
+  end
+
+  for _,func in ipairs(squeezed_rules) do
+    local ret = func(task)
+
+    if ret then
+      -- Function has returned something, so it is rule, not a plugin
+      logger.errx(task, 'hui: %s', ret)
+    end
+  end
+end
+
+exports.squeeze_rule = function(s, func)
+  if s then
+    if not squeezed_symbols[s] then
+      squeezed_symbols[s] = {
+        cb = func,
+        order = 0,
+      }
+      logger.debugm(SN, rspamd_config, 'squeezed rule: %s', s)
+    else
+      logger.warnx(rspamd_config, 'duplicate symbol registered: %s, skip', s)
+    end
+  else
+    -- Unconditionally add function to the squeezed rules
+    logger.debugm(SN, rspamd_config, 'squeezed unnamed rule: %s', #squeezed_rules)
+    table.insert(squeezed_rules, func)
+  end
+
+  if not squeeze_function_id then
+    squeeze_function_id = rspamd_config:register_symbol{
+      type = 'callback',
+      callback = lua_squeeze_function,
+      name = 'LUA_SQUEEZE',
+      description = 'Meta rule for Lua rules that can be squeezed',
+      no_squeeze = true, -- to avoid infinite recursion
+    }
+  end
+
+  return squeeze_function_id
+end
+
+exports.squeeze_dependency = function(from, to)
+  logger.debugm(SN, rspamd_config, 'squeeze dep %s->%s', to, from)
+
+  if not squeezed_deps[to] then
+    squeezed_deps[to] = {}
+  end
+
+  if not squeezed_symbols[to][from] then
+    squeezed_symbols[to][from] = true
+  else
+    logger.warnx('duplicate dependency %s->%s', to, from)
+  end
+
+  return true
+end
+
+return exports
\ No newline at end of file
index d41d79fea4b490639e2eedae610923b265b4aff9..33d7e37144ab738f087f0cb1dd29ec494356ca6b 100644 (file)
@@ -22,6 +22,7 @@ limitations under the License.
 local exports = {}
 local lpeg = require 'lpeg'
 
+
 local split_grammar = {}
 local function rspamd_str_split(s, sep)
   local gr = split_grammar[sep]
index 334e0ab935d5860b4d3a56c30652bc2f7fcfc61b..00f2e505a8769fcdaea20a07160761dcd1e58b4a 100644 (file)
@@ -310,7 +310,7 @@ rspamd_config:register_symbol{
   group = 'headers',
 }
 
-rspamd_config:register_dependency(check_replyto_id, 'FROM_NAME_HAS_TITLE')
+rspamd_config:register_dependency('CHECK_REPLYTO', 'FROM_NAME_HAS_TITLE')
 
 local check_mime_id = rspamd_config:register_symbol{
   name = 'CHECK_MIME',
index 702431c1a14f9f025baec4cde300f7185a08a4df..2646e42d6fcc70b797653d6eb0677082be29b588 100644 (file)
@@ -338,8 +338,8 @@ local freemail_reply_neq_from_id = rspamd_config:register_symbol({
   score = 3.0,
   group = 'headers',
 })
-rspamd_config:register_dependency(freemail_reply_neq_from_id, 'FREEMAIL_REPLYTO')
-rspamd_config:register_dependency(freemail_reply_neq_from_id, 'FREEMAIL_FROM')
+rspamd_config:register_dependency('FREEMAIL_REPLYTO_NEQ_FROM_DOM', 'FREEMAIL_REPLYTO')
+rspamd_config:register_dependency('FREEMAIL_REPLYTO_NEQ_FROM_DOM', 'FREEMAIL_FROM')
 
 rspamd_config.OMOGRAPH_URL = {
   callback = function(task)
index b03c11910ca31f4e0117cfa45b75f0c776a94a82..d6a4ad550a1e7b6a0aaeffaa13c6e28f91558f3b 100644 (file)
@@ -1277,13 +1277,13 @@ rspamd_register_symbol_fromlua (lua_State *L,
 
        if (ref != -1) {
                /*
-                * We call for routine called lua_util.squeeze_rule if it exists
+                * We call for routine called lua_squeeze_rules.squeeze_rule if it exists
                 */
                lua_pushcfunction (L, &rspamd_lua_traceback);
                err_idx = lua_gettop (L);
 
                if (!no_squeeze && (type & (SYMBOL_TYPE_CALLBACK|SYMBOL_TYPE_NORMAL)) &&
-                               rspamd_lua_require_function (L, "lua_util", "squeeze_rule")) {
+                               rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_rule")) {
                        if (name) {
                                lua_pushstring (L, name);
                        }
@@ -1297,14 +1297,16 @@ rspamd_register_symbol_fromlua (lua_State *L,
                        /* Now call for squeeze function */
                        if (lua_pcall (L, 2, 1, err_idx) != 0) {
                                GString *tb = lua_touserdata (L, -1);
-                               msg_err_config ("call to finishing script failed: %v", tb);
+                               msg_err_config ("call to squeeze_rule failed: %v", tb);
 
                                if (tb) {
                                        g_string_free (tb, TRUE);
                                }
                        }
 
-                       if (!lua_toboolean (L, -1)) {
+                       ret = lua_tonumber (L, -1);
+
+                       if (ret == -1) {
                                /* Do direct registration */
                                cd = rspamd_mempool_alloc0 (cfg->cfg_pool,
                                                sizeof (struct lua_callback_data));
@@ -1324,6 +1326,9 @@ rspamd_register_symbol_fromlua (lua_State *L,
                                                cd,
                                                type,
                                                parent);
+                               rspamd_mempool_add_destructor (cfg->cfg_pool,
+                                               (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
+                                               cd);
                        }
                }
                else {
@@ -1345,6 +1350,9 @@ rspamd_register_symbol_fromlua (lua_State *L,
                                        cd,
                                        type,
                                        parent);
+                       rspamd_mempool_add_destructor (cfg->cfg_pool,
+                                       (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
+                                       cd);
                }
 
                /* Cleanup lua stack */
@@ -1360,10 +1368,6 @@ rspamd_register_symbol_fromlua (lua_State *L,
                                parent);
        }
 
-       rspamd_mempool_add_destructor (cfg->cfg_pool,
-                       (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
-                       cd);
-
        return ret;
 }
 
@@ -1812,12 +1816,52 @@ lua_config_register_callback_symbol_priority (lua_State * L)
        return 1;
 }
 
+static gboolean
+rspamd_lua_squeeze_dependency (lua_State *L, struct rspamd_config *cfg,
+               const gchar *name,
+               const gchar *from)
+{
+       gint err_idx;
+       gboolean ret = FALSE;
+
+       lua_pushcfunction (L, &rspamd_lua_traceback);
+       err_idx = lua_gettop (L);
+
+       if (rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_dependency")) {
+               lua_pushstring (L, name);
+
+               if (from) {
+                       lua_pushstring (L, from);
+               }
+               else {
+                       lua_pushnil (L);
+               }
+
+               if (lua_pcall (L, 2, 1, err_idx) != 0) {
+                       GString *tb = lua_touserdata (L, -1);
+                       msg_err_config ("call to squeeze_dependency script failed: %v", tb);
+
+                       if (tb) {
+                               g_string_free (tb, TRUE);
+                       }
+               }
+               else {
+                       ret = lua_toboolean (L, -1);
+               }
+       }
+
+       lua_settop (L, err_idx - 1);
+
+       return ret;
+}
+
 static gint
 lua_config_register_dependency (lua_State * L)
 {
        struct rspamd_config *cfg = lua_check_config (L, 1);
        const gchar *name = NULL, *from = NULL;
        gint id;
+       gboolean skip_squeeze = FALSE;
 
        if (cfg == NULL) {
                lua_error (L);
@@ -1828,16 +1872,36 @@ lua_config_register_dependency (lua_State * L)
                id = luaL_checknumber (L, 2);
                name = luaL_checkstring (L, 3);
 
+               if (lua_isboolean (L, 4)) {
+                       skip_squeeze = lua_toboolean (L, 4);
+               }
+
+               msg_warn_config ("calling for obsolete method to register deps for symbol %d->%s",
+                               id, name);
+
                if (id > 0 && name != NULL) {
-                       rspamd_symbols_cache_add_dependency (cfg->cache, id, name);
+
+                       if (skip_squeeze || !rspamd_lua_squeeze_dependency (L, cfg, name,
+                                       rspamd_symbols_cache_symbol_by_id (cfg->cache, id))) {
+                               rspamd_symbols_cache_add_dependency (cfg->cache, id, name);
+                       }
                }
        }
        else {
                from = luaL_checkstring (L,2);
                name = luaL_checkstring (L, 3);
 
+               if (lua_isboolean (L, 4)) {
+                       skip_squeeze = lua_toboolean (L, 4);
+               }
+
                if (from != NULL && name != NULL) {
-                       rspamd_symbols_cache_add_delayed_dependency (cfg->cache, from, name);
+
+                       if (skip_squeeze || !rspamd_lua_squeeze_dependency (L, cfg, name, from)) {
+                               rspamd_symbols_cache_add_delayed_dependency (cfg->cache, from,
+                                               name);
+                       }
+
                }
        }