diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-05-20 13:19:24 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-05-20 13:19:24 +0100 |
commit | 32428449bd7a6035cecaaf4a684df997f2a9dab7 (patch) | |
tree | a9ec2043f4675f0d01361ef54ad5387a8c1e0445 /src | |
parent | 6319622005f9da0cec9e255b8b8e4fe2721ced04 (diff) | |
download | rspamd-32428449bd7a6035cecaaf4a684df997f2a9dab7.tar.gz rspamd-32428449bd7a6035cecaaf4a684df997f2a9dab7.zip |
[Feature] Allow to have weak flags in fuzzy storage
Diffstat (limited to 'src')
-rw-r--r-- | src/fuzzy_storage.c | 58 | ||||
-rw-r--r-- | src/libserver/fuzzy_backend/fuzzy_backend_redis.c | 14 | ||||
-rw-r--r-- | src/libserver/fuzzy_wire.h | 3 |
3 files changed, 53 insertions, 22 deletions
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 8a7a3de4e..fe9160880 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -107,8 +107,7 @@ struct rspamd_leaky_bucket_elt { }; static const guint64 rspamd_fuzzy_storage_magic = 0x291a3253eb1b3ea5ULL; -KHASH_SET_INIT_INT(fuzzy_key_forbidden_ids); - +KHASH_SET_INIT_INT(fuzzy_key_ids_set); struct rspamd_fuzzy_storage_ctx { guint64 magic; @@ -171,7 +170,9 @@ struct rspamd_fuzzy_storage_ctx { gint lua_pre_handler_cbref; gint lua_post_handler_cbref; gint lua_blacklist_cbref; - khash_t(fuzzy_key_forbidden_ids) *default_forbidden_ids; + khash_t(fuzzy_key_ids_set) *default_forbidden_ids; + /* Ids that should not override other ids */ + khash_t(fuzzy_key_ids_set) *weak_ids; }; enum fuzzy_cmd_type { @@ -213,7 +214,7 @@ struct fuzzy_key { struct rspamd_cryptobox_pubkey *pk; struct fuzzy_key_stat *stat; khash_t(fuzzy_key_flag_stat) *flags_stat; - khash_t(fuzzy_key_forbidden_ids) *forbidden_ids; + khash_t(fuzzy_key_ids_set) *forbidden_ids; }; struct rspamd_updates_cbdata { @@ -449,7 +450,7 @@ fuzzy_key_dtor (gpointer p) } if (key->forbidden_ids) { - kh_destroy(fuzzy_key_forbidden_ids, key->forbidden_ids); + kh_destroy(fuzzy_key_ids_set, key->forbidden_ids); } g_free (key); @@ -812,7 +813,7 @@ rspamd_fuzzy_make_reply (struct rspamd_fuzzy_cmd *cmd, { khiter_t k; - k = kh_get(fuzzy_key_forbidden_ids, session->ctx->default_forbidden_ids, session->reply.rep.v1.flag); + k = kh_get(fuzzy_key_ids_set, session->ctx->default_forbidden_ids, session->reply.rep.v1.flag); if (k != kh_end(session->ctx->default_forbidden_ids)) { /* Hash is from a forbidden flag by default */ @@ -825,7 +826,7 @@ rspamd_fuzzy_make_reply (struct rspamd_fuzzy_cmd *cmd, if (session->reply.rep.v1.prob > 0 && session->key && session->key->forbidden_ids) { khiter_t k; - k = kh_get(fuzzy_key_forbidden_ids, session->key->forbidden_ids, session->reply.rep.v1.flag); + k = kh_get(fuzzy_key_ids_set, session->key->forbidden_ids, session->reply.rep.v1.flag); if (k != kh_end (session->key->forbidden_ids)) { /* Hash is from a forbidden flag for this key */ @@ -1320,6 +1321,11 @@ rspamd_fuzzy_process_command (struct fuzzy_session *session) } } + if (session->ctx->weak_ids && kh_get(fuzzy_key_ids_set, session->ctx->weak_ids, cmd->flag) != kh_end(session->ctx->weak_ids)) { + /* Flag command as weak */ + cmd->version |= RSPAMD_FUZZY_FLAG_WEAK; + } + if (session->worker->index == 0 || session->ctx->peer_fd == -1) { /* Just add to the queue */ up_cmd.is_shingle = is_shingle; @@ -1367,7 +1373,7 @@ rspamd_fuzzy_command_valid (struct rspamd_fuzzy_cmd *cmd, gint r) { enum rspamd_fuzzy_epoch ret = RSPAMD_FUZZY_EPOCH_MAX; - switch (cmd->version) { + switch (cmd->version & RSPAMD_FUZZY_VERSION_MASK) { case 4: if (cmd->shingles_count > 0) { if (r >= sizeof (struct rspamd_fuzzy_shingle_cmd)) { @@ -2281,16 +2287,16 @@ rspamd_fuzzy_storage_stat (struct rspamd_main *rspamd_main, } static gboolean - fuzzy_parse_forbidden_ids (rspamd_mempool_t *pool, +fuzzy_parse_ids (rspamd_mempool_t *pool, const ucl_object_t *obj, gpointer ud, struct rspamd_rcl_section *section, GError **err) { struct rspamd_rcl_struct_parser *pd = (struct rspamd_rcl_struct_parser *)ud; - struct rspamd_fuzzy_storage_ctx *ctx; + khash_t(fuzzy_key_ids_set) *target; - ctx = (struct rspamd_fuzzy_storage_ctx *)pd->user_struct; + target = (khash_t(fuzzy_key_ids_set) *)pd->user_struct; if (ucl_object_type (obj) == UCL_ARRAY) { const ucl_object_t *cur; @@ -2301,7 +2307,7 @@ static gboolean if (ucl_object_toint_safe (cur, &id)) { int r; - kh_put(fuzzy_key_forbidden_ids, ctx->default_forbidden_ids, id, &r); + kh_put(fuzzy_key_ids_set, target, id, &r); } else { return FALSE; @@ -2312,7 +2318,7 @@ static gboolean } else if (ucl_object_type (obj) == UCL_INT) { int r; - kh_put(fuzzy_key_forbidden_ids, ctx->default_forbidden_ids, ucl_object_toint (obj), &r); + kh_put(fuzzy_key_ids_set, target, ucl_object_toint (obj), &r); return TRUE; } @@ -2389,13 +2395,13 @@ fuzzy_parse_keypair (rspamd_mempool_t *pool, const ucl_object_t *forbidden_ids = ucl_object_lookup (extensions, "forbidden_ids"); if (forbidden_ids && ucl_object_type (forbidden_ids) == UCL_ARRAY) { - key->forbidden_ids = kh_init(fuzzy_key_forbidden_ids); + key->forbidden_ids = kh_init(fuzzy_key_ids_set); while ((cur = ucl_object_iterate (forbidden_ids, &it, true)) != NULL) { if (ucl_object_type(cur) == UCL_INT || ucl_object_type(cur) == UCL_FLOAT) { int id = ucl_object_toint(cur); int r; - kh_put(fuzzy_key_forbidden_ids, key->forbidden_ids, id, &r); + kh_put(fuzzy_key_ids_set, key->forbidden_ids, id, &r); } } } @@ -2462,7 +2468,8 @@ init_fuzzy (struct rspamd_config *cfg) ctx->leaky_bucket_burst = NAN; ctx->leaky_bucket_rate = NAN; ctx->delay = NAN; - ctx->default_forbidden_ids = kh_init(fuzzy_key_forbidden_ids); + ctx->default_forbidden_ids = kh_init(fuzzy_key_ids_set); + ctx->weak_ids = kh_init(fuzzy_key_ids_set); rspamd_rcl_register_worker_option (cfg, type, @@ -2535,13 +2542,22 @@ init_fuzzy (struct rspamd_config *cfg) rspamd_rcl_register_worker_option (cfg, type, "forbidden_ids", - fuzzy_parse_forbidden_ids, - ctx, + fuzzy_parse_ids, + ctx->default_forbidden_ids, 0, 0, "Deny specific flags by default"); rspamd_rcl_register_worker_option (cfg, + type, + "weak_ids", + fuzzy_parse_ids, + ctx->weak_ids, + 0, + 0, + "Treat these flags as weak (i.e. they do not overwrite strong flags)"); + + rspamd_rcl_register_worker_option (cfg, type, "keypair_cache_size", rspamd_rcl_parse_struct_integer, @@ -3019,7 +3035,11 @@ start_fuzzy (struct rspamd_worker *worker) } if (ctx->default_forbidden_ids) { - kh_destroy(fuzzy_key_forbidden_ids, ctx->default_forbidden_ids); + kh_destroy(fuzzy_key_ids_set, ctx->default_forbidden_ids); + } + + if (ctx->weak_ids) { + kh_destroy(fuzzy_key_ids_set, ctx->weak_ids); } REF_RELEASE (ctx->cfg); diff --git a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c index 0b7953bfe..390119fbc 100644 --- a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c +++ b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c @@ -1049,8 +1049,16 @@ rspamd_fuzzy_update_append_command (struct rspamd_fuzzy_backend *bk, g_string_append_len (key, cmd->digest, sizeof (cmd->digest)); value = g_string_sized_new (sizeof ("4294967296")); rspamd_printf_gstring (value, "%d", cmd->flag); - session->argv[cur_shift] = g_strdup ("HSET"); - session->argv_lens[cur_shift++] = sizeof ("HSET") - 1; + + if (cmd->version & RSPAMD_FUZZY_FLAG_WEAK) { + session->argv[cur_shift] = g_strdup ("HSETNX"); + session->argv_lens[cur_shift++] = sizeof ("HSETNX") - 1; + } + else { + session->argv[cur_shift] = g_strdup ("HSET"); + session->argv_lens[cur_shift++] = sizeof ("HSET") - 1; + } + session->argv[cur_shift] = key->str; session->argv_lens[cur_shift++] = key->len; session->argv[cur_shift] = g_strdup ("F"); @@ -1445,7 +1453,7 @@ rspamd_fuzzy_backend_update_redis (struct rspamd_fuzzy_backend *bk, /* * For each normal hash addition we do 3 redis commands: - * HSET <key> F <flag> + * HSET <key> F <flag> **OR** HSETNX <key> F <flag> when flag is weak * HINCRBY <key> V <weight> * EXPIRE <key> <expire> * INCR <prefix||fuzzy_count> diff --git a/src/libserver/fuzzy_wire.h b/src/libserver/fuzzy_wire.h index 8680e16fb..fd65ffb38 100644 --- a/src/libserver/fuzzy_wire.h +++ b/src/libserver/fuzzy_wire.h @@ -13,6 +13,9 @@ extern "C" { #define RSPAMD_FUZZY_VERSION 4 #define RSPAMD_FUZZY_KEYLEN 8 +#define RSPAMD_FUZZY_FLAG_WEAK (1u << 7u) +/* Use lower 4 bits for the version */ +#define RSPAMD_FUZZY_VERSION_MASK 0x0fu /* Commands for fuzzy storage */ #define FUZZY_CHECK 0 #define FUZZY_WRITE 1 |