gint dkim_module_config (struct rspamd_config *cfg) { const ucl_object_t *value; gint res = TRUE, cb_id = -1, check_id = -1; guint cache_size; gboolean got_trusted = FALSE; if (!rspamd_config_is_module_enabled (cfg, "dkim")) { return TRUE; } dkim_module_ctx->whitelist_ip = radix_create_compressed (); if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) { dkim_module_ctx->symbol_reject = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_reject = DEFAULT_SYMBOL_REJECT; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_tempfail")) != NULL) { dkim_module_ctx->symbol_tempfail = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_tempfail = DEFAULT_SYMBOL_TEMPFAIL; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_allow")) != NULL) { dkim_module_ctx->symbol_allow = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_na")) != NULL) { dkim_module_ctx->symbol_na = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_na = DEFAULT_SYMBOL_NA; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "dkim_cache_size")) != NULL) { cache_size = ucl_obj_toint (value); } else { cache_size = DEFAULT_CACHE_SIZE; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) { dkim_module_ctx->time_jitter = ucl_obj_todouble (value); } else { dkim_module_ctx->time_jitter = DEFAULT_TIME_JITTER; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "max_sigs")) != NULL) { dkim_module_ctx->max_sigs = ucl_object_toint (value); } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) { rspamd_config_radix_from_ucl (cfg, value, "DKIM whitelist", &dkim_module_ctx->whitelist_ip, NULL); } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) { if (!rspamd_map_add_from_ucl (cfg, value, "DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin, (void **)&dkim_module_ctx->dkim_domains)) { msg_warn_config ("cannot load dkim domains list from %s", ucl_obj_tostring (value)); } else { got_trusted = TRUE; } } if (!got_trusted && (value = rspamd_config_get_module_opt (cfg, "dkim", "trusted_domains")) != NULL) { if (!rspamd_map_add_from_ucl (cfg, value, "DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin, (void **)&dkim_module_ctx->dkim_domains)) { msg_warn_config ("cannot load dkim domains list from %s", ucl_obj_tostring (value)); } else { got_trusted = TRUE; } } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "strict_multiplier")) != NULL) { dkim_module_ctx->strict_multiplier = ucl_obj_toint (value); } else { dkim_module_ctx->strict_multiplier = 1; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "trusted_only")) != NULL) { dkim_module_ctx->trusted_only = ucl_obj_toboolean (value); } else { dkim_module_ctx->trusted_only = FALSE; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "skip_multi")) != NULL) { dkim_module_ctx->skip_multi = ucl_obj_toboolean (value); } else { dkim_module_ctx->skip_multi = FALSE; } if (dkim_module_ctx->trusted_only && !got_trusted) { msg_err_config ( "trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case"); } else { cb_id = rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_reject, 0, dkim_symbol_callback, NULL, SYMBOL_TYPE_NORMAL|SYMBOL_TYPE_FINE, -1); rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_na, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_tempfail, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_allow, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); dkim_module_ctx->dkim_hash = rspamd_lru_hash_new ( cache_size, g_free, /* Keys are just C-strings */ dkim_module_key_dtor); msg_info_config ("init internal dkim module"); #ifndef HAVE_OPENSSL msg_warn_config ( "openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results"); #endif } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "sign_condition")) != NULL) { const gchar *lua_script; lua_script = ucl_object_tostring (value); if (lua_script) { if (luaL_dostring (cfg->lua_state, lua_script) != 0) { msg_err_config ("cannot execute lua script for fuzzy " "learn condition: %s", lua_tostring (cfg->lua_state, -1)); } else { if (lua_type (cfg->lua_state, -1) == LUA_TFUNCTION) { dkim_module_ctx->sign_condition_ref = luaL_ref (cfg->lua_state, LUA_REGISTRYINDEX); dkim_module_ctx->dkim_sign_hash = rspamd_lru_hash_new ( 128, g_free, /* Keys are just C-strings */ (GDestroyNotify)rspamd_dkim_sign_key_unref); check_id = rspamd_symbols_cache_add_symbol (cfg->cache, "DKIM_SIGN", 0, dkim_sign_callback, NULL, SYMBOL_TYPE_CALLBACK|SYMBOL_TYPE_FINE, -1); msg_info_config ("init condition script for DKIM signing"); /* * Allow dkim signing to be executed only after dkim check */ if (cb_id > 0) { rspamd_symbols_cache_add_delayed_dependency (cfg->cache, "DKIM_SIGN", dkim_module_ctx->symbol_reject); } rspamd_config_add_metric_symbol (cfg, DEFAULT_METRIC, "DKIM_SIGN", 0.0, "DKIM signature fake symbol", "dkim", RSPAMD_SYMBOL_FLAG_IGNORE, 1); } else { msg_err_config ("lua script must return " "function(task) and not %s", lua_typename (cfg->lua_state, lua_type (cfg->lua_state, -1))); } } } } return res; }
gint regexp_module_config (struct rspamd_config *cfg) { struct regexp_module_item *cur_item; const ucl_object_t *sec, *value, *elt; ucl_object_iter_t it = NULL; gint res = TRUE, id; if (!rspamd_config_is_module_enabled (cfg, "regexp")) { return TRUE; } sec = ucl_object_find_key (cfg->rcl_obj, "regexp"); if (sec == NULL) { msg_err_config ("regexp module enabled, but no rules are defined"); return TRUE; } regexp_module_ctx->max_size = 0; while ((value = ucl_iterate_object (sec, &it, true)) != NULL) { if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", sizeof ("max_size") - 1) == 0) { regexp_module_ctx->max_size = ucl_obj_toint (value); rspamd_mime_expression_set_re_limit (regexp_module_ctx->max_size); } else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", sizeof ("max_threads") - 1) == 0) { msg_warn_config ("regexp module is now single threaded, max_threads is ignored"); } else if (value->type == UCL_STRING) { cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); if (!read_regexp_expression (regexp_module_ctx->regexp_pool, cur_item, ucl_object_key (value), ucl_obj_tostring (value), cfg)) { res = FALSE; } else { rspamd_symbols_cache_add_symbol (cfg->cache, cur_item->symbol, 0, process_regexp_item, cur_item, SYMBOL_TYPE_NORMAL, -1); } } else if (value->type == UCL_USERDATA) { /* Just a lua function */ cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); cur_item->lua_function = ucl_object_toclosure (value); rspamd_symbols_cache_add_symbol (cfg->cache, cur_item->symbol, 0, process_regexp_item, cur_item, SYMBOL_TYPE_NORMAL, -1); } else if (value->type == UCL_OBJECT) { const gchar *description = NULL, *group = NULL, *metric = DEFAULT_METRIC; gdouble score = 0.0; gboolean one_shot = FALSE, is_lua = FALSE, valid_expression = TRUE; /* We have some lua table, extract its arguments */ elt = ucl_object_find_key (value, "callback"); if (elt == NULL || elt->type != UCL_USERDATA) { /* Try plain regexp expression */ elt = ucl_object_find_any_key (value, "regexp", "re", NULL); if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); if (!read_regexp_expression (regexp_module_ctx->regexp_pool, cur_item, ucl_object_key (value), ucl_obj_tostring (elt), cfg)) { res = FALSE; } else { valid_expression = TRUE; } } else { msg_err_config ( "no callback/expression defined for regexp symbol: " "%s", ucl_object_key (value)); } } else { is_lua = TRUE; cur_item = rspamd_mempool_alloc0 ( regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); cur_item->symbol = ucl_object_key (value); cur_item->lua_function = ucl_object_toclosure (value); } if (cur_item && (is_lua || valid_expression)) { id = rspamd_symbols_cache_add_symbol (cfg->cache, cur_item->symbol, 0, process_regexp_item, cur_item, SYMBOL_TYPE_NORMAL, -1); elt = ucl_object_find_key (value, "condition"); if (elt != NULL && ucl_object_type (elt) == UCL_USERDATA) { struct ucl_lua_funcdata *conddata; conddata = ucl_object_toclosure (elt); rspamd_symbols_cache_add_condition (cfg->cache, id, conddata->L, conddata->idx); } elt = ucl_object_find_key (value, "metric"); if (elt) { metric = ucl_object_tostring (elt); } elt = ucl_object_find_key (value, "description"); if (elt) { description = ucl_object_tostring (elt); } elt = ucl_object_find_key (value, "group"); if (elt) { group = ucl_object_tostring (elt); } elt = ucl_object_find_key (value, "score"); if (elt) { score = ucl_object_todouble (elt); } elt = ucl_object_find_key (value, "one_shot"); if (elt) { one_shot = ucl_object_toboolean (elt); } rspamd_config_add_metric_symbol (cfg, metric, cur_item->symbol, score, description, group, one_shot, FALSE); } } else { msg_warn_config ("unknown type of attribute %s for regexp module", ucl_object_key (value)); } } return res; }