Browse Source

[Rework] Track maps origins

tags/2.7
Vsevolod Stakhov 3 years ago
parent
commit
f84b86d901

+ 1
- 1
src/controller.c View File

"Allow unauthenticated requests from these addresses", "Allow unauthenticated requests from these addresses",
&ctx->secure_map, &ctx->secure_map,
NULL, NULL,
worker);
worker, "controller secure ip");
} }


ctx->lang_det = ctx->cfg->lang_det; ctx->lang_det = ctx->cfg->lang_det;

+ 5
- 4
src/fuzzy_storage.c View File

if (ctx->update_map != NULL) { if (ctx->update_map != NULL) {
rspamd_config_radix_from_ucl (worker->srv->cfg, ctx->update_map, rspamd_config_radix_from_ucl (worker->srv->cfg, ctx->update_map,
"Allow fuzzy updates from specified addresses", "Allow fuzzy updates from specified addresses",
&ctx->update_ips, NULL, worker);
&ctx->update_ips, NULL, worker, "fuzzy update");
} }


if (ctx->skip_map != NULL) { if (ctx->skip_map != NULL) {
"Block fuzzy requests from the specific IPs", "Block fuzzy requests from the specific IPs",
&ctx->blocked_ips, &ctx->blocked_ips,
NULL, NULL,
worker);
worker, "fuzzy blocked");
} }


/* Create radix trees */ /* Create radix trees */
"Skip ratelimits from specific ip addresses/networks", "Skip ratelimits from specific ip addresses/networks",
&ctx->ratelimit_whitelist, &ctx->ratelimit_whitelist,
NULL, NULL,
worker);
worker, "fuzzy ratelimit whitelist");
} }


if (!isnan (ctx->delay) && ctx->delay_whitelist_map != NULL) { if (!isnan (ctx->delay) && ctx->delay_whitelist_map != NULL) {
rspamd_config_radix_from_ucl (worker->srv->cfg, ctx->delay_whitelist_map, rspamd_config_radix_from_ucl (worker->srv->cfg, ctx->delay_whitelist_map,
"Skip delay from the following ips", "Skip delay from the following ips",
&ctx->delay_whitelist, NULL, worker);
&ctx->delay_whitelist, NULL, worker,
"fuzzy delayed whitelist");
} }


/* Ratelimits */ /* Ratelimits */

+ 3
- 6
src/libserver/cfg_file.h View File

*/ */
struct rspamd_radix_map_helper; struct rspamd_radix_map_helper;


gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
const ucl_object_t *obj,
const gchar *description,
struct rspamd_radix_map_helper **target,
GError **err,
struct rspamd_worker *worker);
gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg, const ucl_object_t *obj, const gchar *description,
struct rspamd_radix_map_helper **target, GError **err,
struct rspamd_worker *worker, const gchar *map_name);


/** /**
* Adds new settings id to be preprocessed * Adds new settings id to be preprocessed

+ 9
- 10
src/libserver/cfg_utils.c View File

} }


gboolean gboolean
rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
const ucl_object_t *obj,
const gchar *description,
struct rspamd_radix_map_helper **target,
GError **err,
struct rspamd_worker *worker)
rspamd_config_radix_from_ucl (struct rspamd_config *cfg, const ucl_object_t *obj, const gchar *description,
struct rspamd_radix_map_helper **target, GError **err,
struct rspamd_worker *worker, const gchar *map_name)
{ {
ucl_type_t type; ucl_type_t type;
ucl_object_iter_t it = NULL; ucl_object_iter_t it = NULL;
else { else {
/* Just a list */ /* Just a list */
if (!*target) { if (!*target) {
*target = rspamd_map_helper_new_radix (NULL);
*target = rspamd_map_helper_new_radix (
rspamd_map_add_fake (cfg, description, map_name));
} }


rspamd_map_helper_insert_radix_resolve (*target, str, ""); rspamd_map_helper_insert_radix_resolve (*target, str, "");
str = ucl_object_tostring (cur); str = ucl_object_tostring (cur);


if (!*target) { if (!*target) {
*target = rspamd_map_helper_new_radix (NULL);
*target = rspamd_map_helper_new_radix (
rspamd_map_add_fake (cfg, description, map_name));
} }


rspamd_map_helper_insert_radix_resolve (*target, str, ""); rspamd_map_helper_insert_radix_resolve (*target, str, "");
if (cfg->local_addrs) { if (cfg->local_addrs) {
rspamd_config_radix_from_ucl (cfg, cfg->local_addrs, rspamd_config_radix_from_ucl (cfg, cfg->local_addrs,
"Local addresses", "Local addresses",
(struct rspamd_radix_map_helper **)ctx->local_addrs,
(struct rspamd_radix_map_helper **) ctx->local_addrs,
NULL, NULL,
NULL);
NULL, "local addresses");
} }


rspamd_free_zstd_dictionary (ctx->in_dict); rspamd_free_zstd_dictionary (ctx->in_dict);

+ 1
- 1
src/libserver/logger/logger.c View File

"IP addresses for which debug logs are enabled", "IP addresses for which debug logs are enabled",
&logger->debug_ip, &logger->debug_ip,
NULL, NULL,
NULL);
NULL, "debug ip");
} }


if (cfg->log_encryption_key) { if (cfg->log_encryption_key) {

+ 20
- 0
src/libserver/maps/map.c View File

return map; return map;
} }


struct rspamd_map *
rspamd_map_add_fake (struct rspamd_config *cfg,
const gchar *description,
const gchar *name)
{
struct rspamd_map *map;

map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct rspamd_map));
map->cfg = cfg;
map->id = rspamd_random_uint64_fast ();
map->name = rspamd_mempool_strdup (cfg->cfg_pool, name);
map->user_data = (void **)↦ /* to prevent null pointer dereferencing */

if (description != NULL) {
map->description = rspamd_mempool_strdup (cfg->cfg_pool, description);
}

return map;
}

static inline void static inline void
rspamd_map_add_backend (struct rspamd_map *map, struct rspamd_map_backend *bk) rspamd_map_add_backend (struct rspamd_map *map, struct rspamd_map_backend *bk)
{ {

+ 11
- 0
src/libserver/maps/map.h View File

struct rspamd_worker *worker, struct rspamd_worker *worker,
int flags); int flags);


/**
* Adds a fake map structure (for logging purposes mainly)
* @param cfg
* @param description
* @return
*/
struct rspamd_map *rspamd_map_add_fake (struct rspamd_config *cfg,
const gchar *description,
const gchar *name);


enum rspamd_map_watch_type { enum rspamd_map_watch_type {
RSPAMD_MAP_WATCH_MIN = 9, RSPAMD_MAP_WATCH_MIN = 9,
RSPAMD_MAP_WATCH_PRIMARY_CONTROLLER, RSPAMD_MAP_WATCH_PRIMARY_CONTROLLER,

+ 36
- 4
src/libserver/maps/map_helpers.c View File

rspamd_mempool_t *pool; rspamd_mempool_t *pool;
khash_t(rspamd_map_hash) *htb; khash_t(rspamd_map_hash) *htb;
radix_compressed_t *trie; radix_compressed_t *trie;
struct rspamd_map *map;
rspamd_cryptobox_fast_hash_state_t hst; rspamd_cryptobox_fast_hash_state_t hst;
}; };


struct rspamd_hash_map_helper { struct rspamd_hash_map_helper {
rspamd_mempool_t *pool; rspamd_mempool_t *pool;
khash_t(rspamd_map_hash) *htb; khash_t(rspamd_map_hash) *htb;
struct rspamd_map *map;
rspamd_cryptobox_fast_hash_state_t hst; rspamd_cryptobox_fast_hash_state_t hst;
}; };


struct rspamd_cdb_map_helper { struct rspamd_cdb_map_helper {
GQueue cdbs; GQueue cdbs;
struct rspamd_map *map;
rspamd_cryptobox_fast_hash_state_t hst; rspamd_cryptobox_fast_hash_state_t hst;
gsize total_size; gsize total_size;
}; };
gconstpointer nk; gconstpointer nk;
rspamd_ftok_t tok; rspamd_ftok_t tok;
gint res; gint res;
struct rspamd_map *map;


map = r->map;
vlen = strlen (value); vlen = strlen (value);
val = rspamd_mempool_alloc0 (r->pool, sizeof (*val) + val = rspamd_mempool_alloc0 (r->pool, sizeof (*val) +
vlen + 1); vlen + 1);
tok.begin = nk; tok.begin = nk;
k = kh_put (rspamd_map_hash, r->htb, tok, &res); k = kh_put (rspamd_map_hash, r->htb, tok, &res);
} }
else {
msg_warn_map ("duplicate radix entry found for map %s: %s (old value: %s, new: %s)",
map->name, key, kh_value (r->htb, k), val);
}


nk = kh_key (r->htb, k).begin; nk = kh_key (r->htb, k).begin;
val->key = nk; val->key = nk;
kh_value (r->htb, k) = val; kh_value (r->htb, k) = val;
rspamd_radix_add_iplist (key, ",", r->trie, val, FALSE);
rspamd_radix_add_iplist (key, ",", r->trie, val, FALSE,
r->map->name);
rspamd_cryptobox_fast_hash_update (&r->hst, nk, tok.len); rspamd_cryptobox_fast_hash_update (&r->hst, nk, tok.len);
} }


gconstpointer nk; gconstpointer nk;
rspamd_ftok_t tok; rspamd_ftok_t tok;
gint res; gint res;
struct rspamd_map *map;


map = r->map;
vlen = strlen (value); vlen = strlen (value);
val = rspamd_mempool_alloc0 (r->pool, sizeof (*val) + val = rspamd_mempool_alloc0 (r->pool, sizeof (*val) +
vlen + 1); vlen + 1);
tok.begin = nk; tok.begin = nk;
k = kh_put (rspamd_map_hash, r->htb, tok, &res); k = kh_put (rspamd_map_hash, r->htb, tok, &res);
} }
else {
msg_warn_map ("duplicate radix entry found for map %s: %s (old value: %s, new: %s)",
map->name, key, kh_value (r->htb, k), val);
}


nk = kh_key (r->htb, k).begin; nk = kh_key (r->htb, k).begin;
val->key = nk; val->key = nk;
kh_value (r->htb, k) = val; kh_value (r->htb, k) = val;
rspamd_radix_add_iplist (key, ",", r->trie, val, TRUE);
rspamd_radix_add_iplist (key, ",", r->trie, val, TRUE,
r->map->name);
rspamd_cryptobox_fast_hash_update (&r->hst, nk, tok.len); rspamd_cryptobox_fast_hash_update (&r->hst, nk, tok.len);
} }


gsize vlen; gsize vlen;
gint r; gint r;
rspamd_ftok_t tok; rspamd_ftok_t tok;
struct rspamd_map *map;


tok.begin = key; tok.begin = key;
tok.len = strlen (key); tok.len = strlen (key);
map = ht->map;


k = kh_get (rspamd_map_hash, ht->htb, tok); k = kh_get (rspamd_map_hash, ht->htb, tok);
vlen = strlen (value); vlen = strlen (value);
/* Same element, skip */ /* Same element, skip */
return; return;
} }
else {
msg_warn_map ("duplicate hash entry found for map %s: %s (old value: %s, new: %s)",
map->name, key, kh_value (ht->htb, k), val);
}
} }


/* Null termination due to alloc0 */ /* Null termination due to alloc0 */
vlen = strlen (value); vlen = strlen (value);
val = rspamd_mempool_alloc0 (re_map->pool, sizeof (*val) + val = rspamd_mempool_alloc0 (re_map->pool, sizeof (*val) +
vlen + 1); vlen + 1);
memcpy (val->value, value, vlen);
memcpy (val->value, value, vlen); /* Null terminated due to alloc0 previously */
tok.begin = key; tok.begin = key;
tok.len = strlen (key); tok.len = strlen (key);


tok.begin = nk; tok.begin = nk;
k = kh_put (rspamd_map_hash, re_map->htb, tok, &r); k = kh_put (rspamd_map_hash, re_map->htb, tok, &r);
} }
else {
msg_warn_map ("duplicate re found for map %s: %s (old value: %s, new: %s)",
map->name, key, kh_value (re_map->htb, k)->value, val);
}


nk = kh_key (re_map->htb, k).begin; nk = kh_key (re_map->htb, k).begin;
val->key = nk; val->key = nk;
htb = rspamd_mempool_alloc0 (pool, sizeof (*htb)); htb = rspamd_mempool_alloc0 (pool, sizeof (*htb));
htb->htb = kh_init (rspamd_map_hash); htb->htb = kh_init (rspamd_map_hash);
htb->pool = pool; htb->pool = pool;
htb->map = map;
rspamd_cryptobox_fast_hash_init (&htb->hst, map_hash_seed); rspamd_cryptobox_fast_hash_init (&htb->hst, map_hash_seed);


return htb; return htb;
{ {
struct rspamd_radix_map_helper *r; struct rspamd_radix_map_helper *r;
rspamd_mempool_t *pool; rspamd_mempool_t *pool;
const gchar *name = "unnamed";


if (map) { if (map) {
pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
map->tag, 0); map->tag, 0);
name = map->name;
} }
else { else {
pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
} }


r = rspamd_mempool_alloc0 (pool, sizeof (*r)); r = rspamd_mempool_alloc0 (pool, sizeof (*r));
r->trie = radix_create_compressed_with_pool (pool);
r->trie = radix_create_compressed_with_pool (pool, name);
r->htb = kh_init (rspamd_map_hash); r->htb = kh_init (rspamd_map_hash);
r->pool = pool; r->pool = pool;
r->map = map;
rspamd_cryptobox_fast_hash_init (&r->hst, map_hash_seed); rspamd_cryptobox_fast_hash_init (&r->hst, map_hash_seed);


return r; return r;


n = g_malloc0 (sizeof (*n)); n = g_malloc0 (sizeof (*n));
n->cdbs = (GQueue)G_QUEUE_INIT; n->cdbs = (GQueue)G_QUEUE_INIT;
n->map = map;


rspamd_cryptobox_fast_hash_init (&n->hst, map_hash_seed); rspamd_cryptobox_fast_hash_init (&n->hst, map_hash_seed);



+ 2
- 2
src/libserver/monitored.c View File

if (elt) { if (elt) {
if (ucl_object_type (elt) == UCL_STRING) { if (ucl_object_type (elt) == UCL_STRING) {
radix_add_generic_iplist (ucl_object_tostring (elt), radix_add_generic_iplist (ucl_object_tostring (elt),
&conf->expected, FALSE);
&conf->expected, FALSE, NULL);
} }
else if (ucl_object_type (elt) == UCL_ARRAY) { else if (ucl_object_type (elt) == UCL_ARRAY) {
const ucl_object_t *cur; const ucl_object_t *cur;


while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) { while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
radix_add_generic_iplist (ucl_object_tostring (elt), radix_add_generic_iplist (ucl_object_tostring (elt),
&conf->expected, FALSE);
&conf->expected, FALSE, NULL);
} }
} }
} }

+ 25
- 15
src/libutil/radix.c View File

struct radix_tree_compressed { struct radix_tree_compressed {
rspamd_mempool_t *pool; rspamd_mempool_t *pool;
struct btrie *tree; struct btrie *tree;
const gchar *name;
size_t size; size_t size;
guint duplicates; guint duplicates;
gboolean own_pool; gboolean own_pool;
g_assert (tree != NULL); g_assert (tree != NULL);
g_assert (keybits >= masklen); g_assert (keybits >= masklen);


msg_debug_radix ("want insert value %p with mask %z, key: %*xs",
(gpointer)value, keybits - masklen, (int)keylen, key);
msg_debug_radix ("%s: want insert value %p with mask %z, key: %*xs",
tree->name, (gpointer)value, keybits - masklen, (int)keylen, key);


old = radix_find_compressed (tree, key, keylen); old = radix_find_compressed (tree, key, keylen);


tree->duplicates++; tree->duplicates++;


if (tree->duplicates == max_duplicates) { if (tree->duplicates == max_duplicates) {
msg_err_radix ("maximum duplicates limit reached: %d, "
"suppress further errors", max_duplicates);
msg_err_radix ("%s: maximum duplicates limit reached: %d, "
"suppress further errors", tree->name, max_duplicates);
} }
else if (tree->duplicates < max_duplicates) { else if (tree->duplicates < max_duplicates) {
memset (ip_str, 0, sizeof (ip_str)); memset (ip_str, 0, sizeof (ip_str));


if (keybits == 32) { if (keybits == 32) {
msg_err_radix ("cannot insert %p, key: %s/%d, duplicate value",
msg_err_radix ("%s: cannot insert %p, key: %s/%d, duplicate value",
tree->name,
(gpointer) value, (gpointer) value,
inet_ntop (AF_INET, key, ip_str, sizeof (ip_str) - 1), inet_ntop (AF_INET, key, ip_str, sizeof (ip_str) - 1),
(gint) (keybits - masklen)); (gint) (keybits - masklen));
} else if (keybits == 128) { } else if (keybits == 128) {
msg_err_radix ("cannot insert %p, key: [%s]/%d, duplicate value",
msg_err_radix ("%s: cannot insert %p, key: [%s]/%d, duplicate value",
tree->name,
(gpointer) value, (gpointer) value,
inet_ntop (AF_INET6, key, ip_str, sizeof (ip_str) - 1), inet_ntop (AF_INET6, key, ip_str, sizeof (ip_str) - 1),
(gint) (keybits - masklen)); (gint) (keybits - masklen));
} else { } else {
msg_err_radix ("cannot insert %p with mask %z, key: %*xs, duplicate value",
(gpointer) value, keybits - masklen, (int) keylen, key);
msg_err_radix ("%s: cannot insert %p with mask %z, key: %*xs, duplicate value",
tree->name,
(gpointer) value,
keybits - masklen,
(int) keylen, key);
} }
} }
} }




radix_compressed_t * radix_compressed_t *
radix_create_compressed (void)
radix_create_compressed (const gchar *tree_name)
{ {
radix_compressed_t *tree; radix_compressed_t *tree;


tree->duplicates = 0; tree->duplicates = 0;
tree->tree = btrie_init (tree->pool); tree->tree = btrie_init (tree->pool);
tree->own_pool = TRUE; tree->own_pool = TRUE;
tree->name = tree_name;


return tree; return tree;
} }


radix_compressed_t * radix_compressed_t *
radix_create_compressed_with_pool (rspamd_mempool_t *pool)
radix_create_compressed_with_pool (rspamd_mempool_t *pool, const gchar *tree_name)
{ {
radix_compressed_t *tree; radix_compressed_t *tree;


tree->duplicates = 0; tree->duplicates = 0;
tree->tree = btrie_init (tree->pool); tree->tree = btrie_init (tree->pool);
tree->own_pool = FALSE; tree->own_pool = FALSE;
tree->name = tree_name;


return tree; return tree;
} }


gint gint
rspamd_radix_add_iplist (const gchar *list, const gchar *separators, rspamd_radix_add_iplist (const gchar *list, const gchar *separators,
radix_compressed_t *tree, gconstpointer value, gboolean resolve)
radix_compressed_t *tree, gconstpointer value,
gboolean resolve, const gchar *tree_name)
{ {
gchar *token, *ipnet, *err_str, **strv, **cur, *brace; gchar *token, *ipnet, *err_str, **strv, **cur, *brace;
union { union {
k = strtoul (ipnet, &err_str, 10); k = strtoul (ipnet, &err_str, 10);
if (errno != 0) { if (errno != 0) {
msg_warn_radix ( msg_warn_radix (
"invalid netmask, error detected on symbol: %s, error: %s",
"%s: invalid netmask, error detected on symbol: %s, error: %s",
tree_name,
err_str, err_str,
strerror (errno)); strerror (errno));
k = G_MAXINT; k = G_MAXINT;


gboolean gboolean
radix_add_generic_iplist (const gchar *ip_list, radix_compressed_t **tree, radix_add_generic_iplist (const gchar *ip_list, radix_compressed_t **tree,
gboolean resolve)
gboolean resolve, const gchar *tree_name)
{ {
static const char fill_ptr[] = "1"; static const char fill_ptr[] = "1";


if (*tree == NULL) { if (*tree == NULL) {
*tree = radix_create_compressed ();
*tree = radix_create_compressed (tree_name);
} }


return (rspamd_radix_add_iplist (ip_list, ",; ", *tree, return (rspamd_radix_add_iplist (ip_list, ",; ", *tree,
fill_ptr, resolve) > 0);
fill_ptr, resolve, tree_name) > 0);
} }





+ 9
- 5
src/libutil/radix.h View File

* Create new radix trie * Create new radix trie
* @return * @return
*/ */
radix_compressed_t *radix_create_compressed (void);
radix_compressed_t *radix_create_compressed (const gchar *tree_name);


radix_compressed_t *radix_create_compressed_with_pool (rspamd_mempool_t *pool);
radix_compressed_t *radix_create_compressed_with_pool (rspamd_mempool_t *pool, const gchar *tree_name);


/** /**
* Insert list of ip addresses and masks to the radix tree * Insert list of ip addresses and masks to the radix tree
* @return number of elements inserted * @return number of elements inserted
*/ */
gint rspamd_radix_add_iplist (const gchar *list, const gchar *separators, gint rspamd_radix_add_iplist (const gchar *list, const gchar *separators,
radix_compressed_t *tree, gconstpointer value, gboolean resolve);
radix_compressed_t *tree, gconstpointer value,
gboolean resolve, const gchar *tree_name);


/** /**
* Generic version of @see rspamd_radix_add_iplist. This function creates tree * Generic version of @see rspamd_radix_add_iplist. This function creates tree
* if `tree` is NULL. * if `tree` is NULL.
*/ */
gboolean radix_add_generic_iplist (const gchar *ip_list,
radix_compressed_t **tree, gboolean resolve);
gboolean
radix_add_generic_iplist (const gchar *ip_list,
radix_compressed_t **tree,
gboolean resolve,
const gchar *tree_name);


/** /**
* Returns number of elements in the tree * Returns number of elements in the tree

+ 1
- 1
src/plugins/dkim_check.c View File

rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) { rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) {


rspamd_config_radix_from_ucl (cfg, value, "DKIM whitelist", rspamd_config_radix_from_ucl (cfg, value, "DKIM whitelist",
&dkim_module_ctx->whitelist_ip, NULL, NULL);
&dkim_module_ctx->whitelist_ip, NULL, NULL, "dkim whitelist");
} }


if ((value = if ((value =

+ 1
- 1
src/plugins/fuzzy_check.c View File

rspamd_config_radix_from_ucl (cfg, value, "Fuzzy whitelist", rspamd_config_radix_from_ucl (cfg, value, "Fuzzy whitelist",
&fuzzy_module_ctx->whitelist, &fuzzy_module_ctx->whitelist,
NULL, NULL,
NULL);
NULL, "fuzzy ip whitelist");
} }
else { else {
fuzzy_module_ctx->whitelist = NULL; fuzzy_module_ctx->whitelist = NULL;

+ 2
- 2
test/rspamd_radix_test.c View File

static void static void
rspamd_radix_test_vec (void) rspamd_radix_test_vec (void)
{ {
radix_compressed_t *tree = radix_create_compressed ();
radix_compressed_t *tree = radix_create_compressed (NULL);
struct _tv *t = &test_vec[0]; struct _tv *t = &test_vec[0];
struct in_addr ina; struct in_addr ina;
struct in6_addr in6a; struct in6_addr in6a;
{ {
struct btrie *btrie; struct btrie *btrie;
rspamd_mempool_t *pool; rspamd_mempool_t *pool;
radix_compressed_t *comp_tree = radix_create_compressed ();
radix_compressed_t *comp_tree = radix_create_compressed (NULL);
struct { struct {
guint32 addr; guint32 addr;
guint32 mask; guint32 mask;

Loading…
Cancel
Save