Browse Source

[Feature] Support modern style SURBL configuration

tags/1.4.0
Vsevolod Stakhov 7 years ago
parent
commit
33eb7e3b2a
1 changed files with 196 additions and 181 deletions
  1. 196
    181
      src/plugins/surbl.c

+ 196
- 181
src/plugins/surbl.c View File

@@ -461,17 +461,196 @@ register_bit_symbols (struct rspamd_config *cfg, struct suffix_item *suffix,
}
}

static gint
surbl_module_parse_rule (const ucl_object_t* value, struct rspamd_config* cfg,
ucl_object_t* monitored_opts)
{
const ucl_object_t* cur_rule;
const ucl_object_t* cur;
gint cb_id;
gint nrules = 0;
struct suffix_item* new_suffix;
const gchar* ip_val;
struct surbl_bit_item* new_bit;

LL_FOREACH(value, cur_rule) {
cur = ucl_object_lookup (cur_rule, "suffix");
if (cur == NULL) {
msg_err_config("surbl rule must have explicit symbol "
"definition");
continue;
}

new_suffix = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool,
sizeof(struct suffix_item));
new_suffix->magic = rspamd_surbl_cb_magic;
new_suffix->suffix = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool, ucl_obj_tostring (cur));
new_suffix->options = 0;
new_suffix->bits = g_array_new (FALSE, FALSE,
sizeof(struct surbl_bit_item));
rspamd_mempool_add_destructor(surbl_module_ctx->surbl_pool,
(rspamd_mempool_destruct_t )rspamd_array_free_hard,
new_suffix->bits);

cur = ucl_object_lookup (cur_rule, "symbol");
if (cur == NULL) {
if (ucl_object_key (value)) {
new_suffix->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_object_key (value));
}
else {
msg_warn_config(
"surbl rule for suffix %s lacks symbol, using %s as symbol",
new_suffix->suffix, DEFAULT_SURBL_SYMBOL);
new_suffix->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool, DEFAULT_SURBL_SYMBOL);
}
}
else {
new_suffix->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool, ucl_obj_tostring (cur));
}

cur = ucl_object_lookup (cur_rule, "options");
if (cur != NULL && cur->type == UCL_STRING) {
if (strstr(ucl_obj_tostring(cur), "noip") != NULL) {
new_suffix->options |= SURBL_OPTION_NOIP;
}
}

cur = ucl_object_lookup (cur_rule, "no_ip");
if (cur != NULL && cur->type == UCL_BOOLEAN) {
if (ucl_object_toboolean(cur)) {
new_suffix->options |= SURBL_OPTION_NOIP;
}
}

cur = ucl_object_lookup (cur_rule, "resolve_ip");
if (cur != NULL && cur->type == UCL_BOOLEAN) {
if (ucl_object_toboolean(cur)) {
new_suffix->options |= SURBL_OPTION_RESOLVEIP;
}
}

cur = ucl_object_lookup (cur_rule, "images");
if (cur != NULL && cur->type == UCL_BOOLEAN) {
if (ucl_object_toboolean (cur)) {
new_suffix->options |= SURBL_OPTION_CHECKIMAGES;
}
}

if ((new_suffix->options & (SURBL_OPTION_RESOLVEIP | SURBL_OPTION_NOIP))
== (SURBL_OPTION_NOIP | SURBL_OPTION_RESOLVEIP)) {
/* Mutually exclusive options */
msg_err_config("options noip and resolve_ip are "
"mutually exclusive for suffix %s", new_suffix->suffix);
}

cb_id = rspamd_symbols_cache_add_symbol (cfg->cache, "SURBL_CALLBACK",
0, surbl_test_url, new_suffix, SYMBOL_TYPE_CALLBACK, -1);
nrules++;
new_suffix->callback_id = cb_id;
cur = ucl_object_lookup (cur_rule, "bits");

if (cur != NULL && cur->type == UCL_OBJECT) {
ucl_object_iter_t it = NULL;
const ucl_object_t* cur_bit;
guint32 bit;

while ((cur_bit = ucl_object_iterate (cur, &it, true)) != NULL) {
if (ucl_object_key (cur_bit) != NULL
&& cur_bit->type == UCL_INT) {
gchar* p;
bit = ucl_obj_toint (cur_bit);
new_bit = rspamd_mempool_alloc (
surbl_module_ctx->surbl_pool,
sizeof(struct surbl_bit_item));
new_bit->bit = bit;
new_bit->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_object_key (cur_bit));
/* Convert to uppercase */
p = new_bit->symbol;
while (*p) {
*p = g_ascii_toupper (*p);
p++;
}
msg_debug_config("add new bit suffix: %d with symbol: %s",
(gint )new_bit->bit, new_bit->symbol);
g_array_append_val(new_suffix->bits, *new_bit);
}
}
}

cur = ucl_object_lookup(cur_rule, "ips");
if (cur != NULL && cur->type == UCL_OBJECT) {
ucl_object_iter_t it = NULL;
const ucl_object_t* cur_bit;
guint32 bit;

new_suffix->ips = g_hash_table_new (g_int_hash, g_int_equal);
rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool,
(rspamd_mempool_destruct_t )g_hash_table_unref,
new_suffix->ips);

while ((cur_bit = ucl_object_iterate (cur, &it, true)) != NULL) {
if (ucl_object_key (cur_bit) != NULL) {
gchar* p;
ip_val = ucl_obj_tostring (cur_bit);
new_bit = rspamd_mempool_alloc (
surbl_module_ctx->surbl_pool,
sizeof(struct surbl_bit_item));
if (inet_pton (AF_INET, ip_val, &bit) != 1) {
msg_err_config("cannot parse ip %s: %s", ip_val,
strerror (errno));
continue;
}
new_bit->bit = bit;
new_bit->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_object_key (cur_bit));
/* Convert to uppercase */
p = new_bit->symbol;
while (*p) {
*p = g_ascii_toupper (*p);
p++;
}
msg_debug_config ("add new IP suffix: %d with symbol: %s",
(gint )new_bit->bit, new_bit->symbol);
g_hash_table_insert (new_suffix->ips, &new_bit->bit,
new_bit);
}
}
}

if (new_suffix->symbol) {
/* Register just a symbol itself */
rspamd_symbols_cache_add_symbol (cfg->cache,
new_suffix->symbol, 0,
NULL, NULL, SYMBOL_TYPE_VIRTUAL, cb_id);
nrules++;
}

new_suffix->m = rspamd_monitored_create (cfg->monitored_ctx,
new_suffix->suffix, RSPAMD_MONITORED_DNS,
RSPAMD_MONITORED_DEFAULT, monitored_opts);
surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes,
new_suffix);
}

return nrules;
}

gint
surbl_module_config (struct rspamd_config *cfg)
{
GList *cur_opt;
struct suffix_item *new_suffix, *cur_suffix = NULL;
struct surbl_bit_item *new_bit;
const ucl_object_t *value, *cur, *cur_rule, *cur_bit;
ucl_object_iter_t it = NULL;
const gchar *redir_val, *ip_val;
guint32 bit;
gint cb_id, nrules = 0;
struct suffix_item *cur_suffix = NULL;
const ucl_object_t *value, *cur;
const gchar *redir_val;
gint nrules = 0;
ucl_object_t *monitored_opts;

if (!rspamd_config_is_module_enabled (cfg, "surbl")) {
@@ -582,182 +761,18 @@ surbl_module_config (struct rspamd_config *cfg)

value = rspamd_config_get_module_opt (cfg, "surbl", "rule");
if (value != NULL && value->type == UCL_OBJECT) {
LL_FOREACH (value, cur_rule)
{
cur = ucl_obj_get_key (cur_rule, "suffix");
if (cur == NULL) {
msg_err_config ("surbl rule must have explicit symbol "
"definition");
continue;
}

new_suffix = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool,
sizeof (struct suffix_item));
new_suffix->magic = rspamd_surbl_cb_magic;
new_suffix->suffix = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_obj_tostring (cur));
new_suffix->options = 0;
new_suffix->bits = g_array_new (FALSE, FALSE,
sizeof (struct surbl_bit_item));
rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool,
(rspamd_mempool_destruct_t)rspamd_array_free_hard,
new_suffix->bits);

cur = ucl_obj_get_key (cur_rule, "symbol");
if (cur == NULL) {
msg_warn_config (
"surbl rule for suffix %s lacks symbol, using %s as symbol",
new_suffix->suffix,
DEFAULT_SURBL_SYMBOL);
new_suffix->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
DEFAULT_SURBL_SYMBOL);
}
else {
new_suffix->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_obj_tostring (cur));
}

cur = ucl_obj_get_key (cur_rule, "options");
if (cur != NULL && cur->type == UCL_STRING) {
if (strstr (ucl_obj_tostring (cur), "noip") != NULL) {
new_suffix->options |= SURBL_OPTION_NOIP;
}
}

cur = ucl_obj_get_key (cur_rule, "no_ip");
if (cur != NULL && cur->type == UCL_BOOLEAN) {
if (ucl_object_toboolean (cur)) {
new_suffix->options |= SURBL_OPTION_NOIP;
}
}

cur = ucl_obj_get_key (cur_rule, "resolve_ip");
if (cur != NULL && cur->type == UCL_BOOLEAN) {
if (ucl_object_toboolean (cur)) {
new_suffix->options |= SURBL_OPTION_RESOLVEIP;
}
}

cur = ucl_obj_get_key (cur_rule, "images");
if (cur != NULL && cur->type == UCL_BOOLEAN) {
if (ucl_object_toboolean (cur)) {
new_suffix->options |= SURBL_OPTION_CHECKIMAGES;
}
}
ucl_object_iter_t it = NULL;
const ucl_object_t *cur_value;

if ((new_suffix->options & (SURBL_OPTION_RESOLVEIP|SURBL_OPTION_NOIP)) ==
(SURBL_OPTION_NOIP|SURBL_OPTION_RESOLVEIP)) {
/* Mutually exclusive options */
msg_err_config ("options noip and resolve_ip are "
"mutually exclusive for suffix %s", new_suffix->suffix);
}

cb_id = rspamd_symbols_cache_add_symbol (cfg->cache,
"SURBL_CALLBACK",
0,
surbl_test_url,
new_suffix,
SYMBOL_TYPE_CALLBACK,
-1);
nrules++;
new_suffix->callback_id = cb_id;

cur = ucl_obj_get_key (cur_rule, "bits");
if (cur != NULL && cur->type == UCL_OBJECT) {
it = NULL;
while ((cur_bit =
ucl_object_iterate (cur, &it, true)) != NULL) {
if (ucl_object_key (cur_bit) != NULL && cur_bit->type ==
UCL_INT) {
gchar *p;

bit = ucl_obj_toint (cur_bit);
new_bit = rspamd_mempool_alloc (
surbl_module_ctx->surbl_pool,
sizeof (struct surbl_bit_item));
new_bit->bit = bit;
new_bit->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_object_key (cur_bit));
/* Convert to uppercase */
p = new_bit->symbol;
while (*p) {
*p = g_ascii_toupper (*p);
p ++;
}

msg_debug_config ("add new bit suffix: %d with symbol: %s",
(gint)new_bit->bit, new_bit->symbol);
g_array_append_val (new_suffix->bits, *new_bit);
}
}
}

cur = ucl_obj_get_key (cur_rule, "ips");

if (cur != NULL && cur->type == UCL_OBJECT) {
it = NULL;
new_suffix->ips = g_hash_table_new (g_int_hash, g_int_equal);
rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool,
(rspamd_mempool_destruct_t)g_hash_table_unref,
new_suffix->ips);

while ((cur_bit =
ucl_object_iterate (cur, &it, true)) != NULL) {
if (ucl_object_key (cur_bit) != NULL) {
gchar *p;

ip_val = ucl_obj_tostring (cur_bit);
new_bit = rspamd_mempool_alloc (
surbl_module_ctx->surbl_pool,
sizeof (struct surbl_bit_item));

if (inet_pton (AF_INET, ip_val, &bit) != 1) {
msg_err_config ("cannot parse ip %s: %s", ip_val,
strerror (errno));
continue;
}

new_bit->bit = bit;
new_bit->symbol = rspamd_mempool_strdup (
surbl_module_ctx->surbl_pool,
ucl_object_key (cur_bit));
/* Convert to uppercase */
p = new_bit->symbol;
while (*p) {
*p = g_ascii_toupper (*p);
p ++;
}

msg_debug_config ("add new IP suffix: %d with symbol: %s",
(gint)new_bit->bit, new_bit->symbol);
g_hash_table_insert (new_suffix->ips, &new_bit->bit,
new_bit);
}
}
}

if (new_suffix->symbol) {
/* Register just a symbol itself */
rspamd_symbols_cache_add_symbol (cfg->cache,
new_suffix->symbol,
0,
NULL, NULL,
SYMBOL_TYPE_VIRTUAL,
cb_id);
nrules ++;
if (ucl_object_lookup (value, "symbol") != NULL) {
/* Old style */
nrules += surbl_module_parse_rule (value, cfg, monitored_opts);
}
else {
/* New style */
while ((cur_value = ucl_object_iterate (value, &it, true)) != NULL) {
nrules += surbl_module_parse_rule (cur_value, cfg, monitored_opts);
}

new_suffix->m = rspamd_monitored_create (cfg->monitored_ctx,
new_suffix->suffix, RSPAMD_MONITORED_DNS,
RSPAMD_MONITORED_DEFAULT, monitored_opts);

surbl_module_ctx->suffixes = g_list_prepend (
surbl_module_ctx->suffixes,
new_suffix);
}
}
/* Add default suffix */

Loading…
Cancel
Save