summaryrefslogtreecommitdiffstats
path: root/src/libserver
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2022-04-24 11:59:00 +0100
committerVsevolod Stakhov <vsevolod@rspamd.com>2022-04-24 11:59:00 +0100
commit97a66ce053d9ac770960408fb06d0816128b83e8 (patch)
tree44bb4627af1f3a2fd612f4aa8e319996c6babf74 /src/libserver
parent2d2260268a4200d5207f78c06c953a34f381df10 (diff)
downloadrspamd-97a66ce053d9ac770960408fb06d0816128b83e8.tar.gz
rspamd-97a66ce053d9ac770960408fb06d0816128b83e8.zip
[Project] Implement some conditions checks
Diffstat (limited to 'src/libserver')
-rw-r--r--src/libserver/symcache/symcache_id_list.hxx28
-rw-r--r--src/libserver/symcache/symcache_item.cxx135
-rw-r--r--src/libserver/symcache/symcache_item.hxx30
-rw-r--r--src/libserver/symcache/symcache_runtime.cxx7
4 files changed, 182 insertions, 18 deletions
diff --git a/src/libserver/symcache/symcache_id_list.hxx b/src/libserver/symcache/symcache_id_list.hxx
index b42cb9183..444ac2079 100644
--- a/src/libserver/symcache/symcache_id_list.hxx
+++ b/src/libserver/symcache/symcache_id_list.hxx
@@ -20,7 +20,7 @@
#include <cstdint>
#include <cstring> // for memset
-#include <algorithm> // for sort
+#include <algorithm> // for sort/bsearch
#include "config.h"
#include "libutil/mem_pool.h"
@@ -43,7 +43,9 @@ struct id_list {
} data;
id_list() = default;
- auto reset() {
+
+ auto reset()
+ {
std::memset(&data, 0, sizeof(data));
}
@@ -121,7 +123,8 @@ struct id_list {
}
}
- auto set_ids(const std::uint32_t *ids, std::size_t nids, rspamd_mempool_t *pool) -> void {
+ auto set_ids(const std::uint32_t *ids, std::size_t nids, rspamd_mempool_t *pool) -> void
+ {
if (nids <= G_N_ELEMENTS(data.st)) {
/* Use static version */
reset();
@@ -145,6 +148,25 @@ struct id_list {
std::sort(data.dyn.n, data.dyn.n + data.dyn.len);
}
}
+
+ auto check_id(unsigned int id) const -> bool
+ {
+ if (data.dyn.e == -1) {
+ return std::binary_search(data.dyn.n, data.dyn.n + data.dyn.len, id);
+ }
+ else {
+ for (auto elt: data.st) {
+ if (elt == id) {
+ return true;
+ }
+ else if (elt == 0) {
+ return false;
+ }
+ }
+ }
+
+ return false;
+ }
};
static_assert(std::is_trivial_v<id_list>);
diff --git a/src/libserver/symcache/symcache_item.cxx b/src/libserver/symcache/symcache_item.cxx
index 0ca080ac0..99e3cfb5d 100644
--- a/src/libserver/symcache/symcache_item.cxx
+++ b/src/libserver/symcache/symcache_item.cxx
@@ -17,6 +17,8 @@
#include "symcache_internal.hxx"
#include "symcache_item.hxx"
#include "fmt/core.h"
+#include "libserver/task.h"
+#include "lua/lua_common.h"
namespace rspamd::symcache {
@@ -205,7 +207,7 @@ auto cache_item::update_counters_check_peak(lua_State *L,
auto cache_item::get_type_str() const -> const char *
{
- switch(type) {
+ switch (type) {
case symcache_item_type::CONNFILTER:
return "connfilter";
case symcache_item_type::FILTER:
@@ -227,6 +229,100 @@ auto cache_item::get_type_str() const -> const char *
RSPAMD_UNREACHABLE;
}
+auto cache_item::is_item_allowed(struct rspamd_task *task, bool exec_only) -> bool
+{
+ const auto *what = "execution";
+
+ if (!exec_only) {
+ what = "symbol insertion";
+ }
+
+ /* Static checks */
+ if (!enabled ||
+ (RSPAMD_TASK_IS_EMPTY(task) && !(flags & SYMBOL_TYPE_EMPTY)) ||
+ (flags & SYMBOL_TYPE_MIME_ONLY && !RSPAMD_TASK_IS_MIME(task))) {
+
+ if (!enabled) {
+ msg_debug_cache_task("skipping %s of %s as it is permanently disabled",
+ what, symbol.c_str());
+
+ return false;
+ }
+ else {
+ /*
+ * If we check merely execution (not insertion), then we disallow
+ * mime symbols for non mime tasks and vice versa
+ */
+ if (exec_only) {
+ msg_debug_cache_task("skipping check of %s as it cannot be "
+ "executed for this task type",
+ symbol.c_str());
+
+ return FALSE;
+ }
+ }
+ }
+
+ /* Settings checks */
+ if (task->settings_elt != nullptr) {
+ if (forbidden_ids.check_id(task->settings_elt->id)) {
+ msg_debug_cache_task ("deny %s of %s as it is forbidden for "
+ "settings id %ud",
+ what,
+ symbol.c_str(),
+ task->settings_elt->id);
+
+ return false;
+ }
+
+ if (!(flags & SYMBOL_TYPE_EXPLICIT_DISABLE)) {
+ if (allowed_ids.check_id(task->settings_elt->id)) {
+
+ if (task->settings_elt->policy == RSPAMD_SETTINGS_POLICY_IMPLICIT_ALLOW) {
+ msg_debug_cache_task("allow execution of %s settings id %ud "
+ "allows implicit execution of the symbols;",
+ symbol.c_str(),
+ id);
+
+ return true;
+ }
+
+ if (exec_only) {
+ /*
+ * Special case if any of our virtual children are enabled
+ */
+ if (exec_only_ids.check_id(task->settings_elt->id)) {
+ return true;
+ }
+ }
+
+ msg_debug_cache_task ("deny %s of %s as it is not listed "
+ "as allowed for settings id %ud",
+ what,
+ symbol.c_str(),
+ task->settings_elt->id);
+ return false;
+ }
+ }
+ else {
+ msg_debug_cache_task ("allow %s of %s for "
+ "settings id %ud as it can be only disabled explicitly",
+ what,
+ symbol.c_str(),
+ task->settings_elt->id);
+ }
+ }
+ else if (flags & SYMBOL_TYPE_EXPLICIT_ENABLE) {
+ msg_debug_cache_task ("deny %s of %s as it must be explicitly enabled",
+ what,
+ symbol.c_str());
+ return false;
+ }
+
+ /* Allow all symbols with no settings id */
+ return true;
+}
+
auto virtual_item::get_parent(const symcache &cache) const -> const cache_item *
{
if (parent) {
@@ -331,4 +427,41 @@ bool operator<(symcache_item_type lhs, symcache_item_type rhs)
return ret;
}
+item_condition::~item_condition()
+{
+ if (cb != -1 && L != nullptr) {
+ luaL_unref(L, LUA_REGISTRYINDEX, cb);
+ }
+}
+
+auto item_condition::check(std::string_view sym_name, struct rspamd_task *task) const -> bool
+{
+ if (cb != -1 && L != nullptr) {
+ auto ret = false;
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, cb);
+
+ lua_pushcfunction (L, &rspamd_lua_traceback);
+ auto err_idx = lua_gettop(L);
+
+ auto **ptask = (struct rspamd_task **) lua_newuserdata(L, sizeof(struct rspamd_task *));
+ rspamd_lua_setclass(L, "rspamd{task}", -1);
+ *ptask = task;
+
+ if (lua_pcall(L, 1, 1, err_idx) != 0) {
+ msg_info_task("call to condition for %s failed: %s",
+ sym_name.data(), lua_tostring(L, -1));
+ }
+ else {
+ ret = lua_toboolean(L, -1);
+ }
+
+ lua_settop(L, err_idx - 1);
+
+ return ret;
+ }
+
+ return true;
+}
+
}
diff --git a/src/libserver/symcache/symcache_item.hxx b/src/libserver/symcache/symcache_item.hxx
index 18a46d317..484065cc2 100644
--- a/src/libserver/symcache/symcache_item.hxx
+++ b/src/libserver/symcache/symcache_item.hxx
@@ -25,12 +25,12 @@
#include <string_view>
#include <memory>
#include <variant>
+#include <algorithm>
#include "rspamd_symcache.h"
#include "symcache_id_list.hxx"
#include "contrib/expected/expected.hpp"
#include "contrib/libev/ev.h"
-#include "lua/lua_common.h"
namespace rspamd::symcache {
@@ -67,16 +67,10 @@ private:
lua_State *L;
int cb;
public:
- item_condition(lua_State *_L, int _cb) : L(_L), cb(_cb)
- {
- }
+ item_condition(lua_State *_L, int _cb) : L(_L), cb(_cb) {}
+ virtual ~item_condition();
- virtual ~item_condition()
- {
- if (cb != -1 && L != nullptr) {
- luaL_unref(L, LUA_REGISTRYINDEX, cb);
- }
- }
+ auto check(std::string_view sym_name, struct rspamd_task *task) const -> bool;
};
class normal_item {
@@ -98,6 +92,11 @@ public:
{
// TODO
}
+
+ auto check_conditions(std::string_view sym_name, struct rspamd_task *task) -> bool {
+ return std::all_of(std::begin(conditions), std::end(conditions),
+ [&](const auto &cond) { return cond.check(sym_name, task); });
+ }
};
class virtual_item {
@@ -288,10 +287,21 @@ public:
double cur_time,
double last_resort) -> bool;
+ /**
+ * Increase frequency for a symbol
+ */
auto inc_frequency() -> void {
g_atomic_int_inc(&st->hits);
}
+ /**
+ * Check if an item is allowed to be executed not checking item conditions
+ * @param task
+ * @param exec_only
+ * @return
+ */
+ auto is_item_allowed(struct rspamd_task *task, bool exec_only) -> bool;
+
private:
/**
* Constructor for a normal symbols with callback
diff --git a/src/libserver/symcache/symcache_runtime.cxx b/src/libserver/symcache/symcache_runtime.cxx
index c86f79087..74dd4a183 100644
--- a/src/libserver/symcache/symcache_runtime.cxx
+++ b/src/libserver/symcache/symcache_runtime.cxx
@@ -18,6 +18,7 @@
#include "symcache_item.hxx"
#include "symcache_runtime.hxx"
#include "libutil/cxx/util.hxx"
+#include "libserver/task.h"
namespace rspamd::symcache {
@@ -31,13 +32,11 @@ constexpr static const auto PROFILE_PROBABILITY = 0.01;
auto
symcache_runtime::create_savepoint(struct rspamd_task *task, symcache &cache) -> symcache_runtime *
{
- struct symcache_runtime *checkpoint;
-
cache.maybe_resort();
auto &&cur_order = cache.get_cache_order();
- checkpoint = (struct symcache_runtime *) rspamd_mempool_alloc0 (task->task_pool,
- sizeof(*checkpoint) +
+ auto *checkpoint = (symcache_runtime *) rspamd_mempool_alloc0 (task->task_pool,
+ sizeof(symcache_runtime) +
sizeof(struct cache_dynamic_item) * cur_order->size());
checkpoint->order = cache.get_cache_order();