]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Support modern style SURBL configuration
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 17 Nov 2016 18:09:20 +0000 (18:09 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 17 Nov 2016 18:09:20 +0000 (18:09 +0000)
src/plugins/surbl.c

index 34016f361f6ea6c336300f432b929f266a486fce..1ad09e6494e5da8cee6d8202e66a29da0469054e 100644 (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 */