diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-07-23 12:57:31 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-07-23 12:57:31 +0100 |
commit | 379055dbbb4af997b4d3ffb161d447872d7ca357 (patch) | |
tree | 3774553d470f93e12ddeb454aad9b3b607cf8918 /src/plugins | |
parent | 602ae7a0b7e215ba2677131b8fdc70abc156b3ca (diff) | |
download | rspamd-379055dbbb4af997b4d3ffb161d447872d7ca357.tar.gz rspamd-379055dbbb4af997b4d3ffb161d447872d7ca357.zip |
Unify style without sorting headers.
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/chartable.c | 71 | ||||
-rw-r--r-- | src/plugins/dkim_check.c | 227 | ||||
-rw-r--r-- | src/plugins/fuzzy_check.c | 534 | ||||
-rw-r--r-- | src/plugins/regexp.c | 1212 | ||||
-rw-r--r-- | src/plugins/spf.c | 165 | ||||
-rw-r--r-- | src/plugins/surbl.c | 795 |
6 files changed, 1902 insertions, 1102 deletions
diff --git a/src/plugins/chartable.c b/src/plugins/chartable.c index e5ea0fb71..8e5bfac5a 100644 --- a/src/plugins/chartable.c +++ b/src/plugins/chartable.c @@ -54,17 +54,17 @@ module_t chartable_module = { }; struct chartable_ctx { - gint (*filter) (struct rspamd_task * task); - const gchar *symbol; - double threshold; + gint (*filter) (struct rspamd_task * task); + const gchar *symbol; + double threshold; - rspamd_mempool_t *chartable_pool; + rspamd_mempool_t *chartable_pool; }; -static struct chartable_ctx *chartable_module_ctx = NULL; +static struct chartable_ctx *chartable_module_ctx = NULL; -static gint chartable_mime_filter (struct rspamd_task *task); -static void chartable_symbol_callback (struct rspamd_task *task, void *unused); +static gint chartable_mime_filter (struct rspamd_task *task); +static void chartable_symbol_callback (struct rspamd_task *task, void *unused); gint chartable_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) @@ -72,7 +72,8 @@ chartable_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) chartable_module_ctx = g_malloc (sizeof (struct chartable_ctx)); chartable_module_ctx->filter = chartable_mime_filter; - chartable_module_ctx->chartable_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + chartable_module_ctx->chartable_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); *ctx = (struct module_ctx *)chartable_module_ctx; @@ -83,16 +84,18 @@ chartable_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint chartable_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value; - gint res = TRUE; + const ucl_object_t *value; + gint res = TRUE; - if ((value = rspamd_config_get_module_opt (cfg, "chartable", "symbol")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "chartable", "symbol")) != NULL) { chartable_module_ctx->symbol = ucl_obj_tostring (value); } else { chartable_module_ctx->symbol = DEFAULT_SYMBOL; - } - if ((value = rspamd_config_get_module_opt (cfg, "chartable", "threshold")) != NULL) { + } + if ((value = + rspamd_config_get_module_opt (cfg, "chartable", "threshold")) != NULL) { if (!ucl_obj_todouble_safe (value, &chartable_module_ctx->threshold)) { msg_warn ("invalid numeric value"); chartable_module_ctx->threshold = DEFAULT_THRESHOLD; @@ -102,7 +105,11 @@ chartable_module_config (struct rspamd_config *cfg) chartable_module_ctx->threshold = DEFAULT_THRESHOLD; } - register_symbol (&cfg->cache, chartable_module_ctx->symbol, 1, chartable_symbol_callback, NULL); + register_symbol (&cfg->cache, + chartable_module_ctx->symbol, + 1, + chartable_symbol_callback, + NULL); return res; } @@ -116,27 +123,31 @@ chartable_module_reconfig (struct rspamd_config *cfg) return chartable_module_config (cfg); } -static gboolean +static gboolean check_part (struct mime_text_part *part, gboolean raw_mode) { - guchar *p, *p1; - gunichar c, t; - GUnicodeScript scc, sct; - guint32 mark = 0, total = 0, max = 0, i; - guint32 remain = part->content->len; - guint32 scripts[G_UNICODE_SCRIPT_NKO]; - GUnicodeScript sel = 0; + guchar *p, *p1; + gunichar c, t; + GUnicodeScript scc, sct; + guint32 mark = 0, total = 0, max = 0, i; + guint32 remain = part->content->len; + guint32 scripts[G_UNICODE_SCRIPT_NKO]; + GUnicodeScript sel = 0; p = part->content->data; if (part->is_raw || raw_mode) { while (remain > 1) { - if ((g_ascii_isalpha (*p) && (*(p + 1) & 0x80)) || ((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) { + if ((g_ascii_isalpha (*p) && + (*(p + 1) & 0x80)) || + ((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) { mark++; total++; } /* Current and next symbols are of one class */ - else if (((*p & 0x80) && (*(p + 1) & 0x80)) || (g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) { + else if (((*p & 0x80) && + (*(p + 1) & 0x80)) || + (g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) { total++; } p++; @@ -147,14 +158,14 @@ check_part (struct mime_text_part *part, gboolean raw_mode) memset (&scripts, 0, sizeof (scripts)); while (remain > 0) { c = g_utf8_get_char_validated (p, remain); - if (c == (gunichar) -2 || c == (gunichar) -1) { + if (c == (gunichar) - 2 || c == (gunichar) - 1) { /* Invalid characters detected, stop processing */ return FALSE; } scc = g_unichar_get_script (c); if (scc < (gint)G_N_ELEMENTS (scripts)) { - scripts[scc] ++; + scripts[scc]++; } p1 = g_utf8_next_char (p); remain -= p1 - p; @@ -162,7 +173,7 @@ check_part (struct mime_text_part *part, gboolean raw_mode) if (remain > 0) { t = g_utf8_get_char_validated (p, remain); - if (t == (gunichar) -2 || t == (gunichar) -1) { + if (t == (gunichar) - 2 || t == (gunichar) - 1) { /* Invalid characters detected, stop processing */ return FALSE; } @@ -180,7 +191,7 @@ check_part (struct mime_text_part *part, gboolean raw_mode) } } /* Detect the mostly charset of this part */ - for (i = 0; i < G_N_ELEMENTS (scripts); i ++) { + for (i = 0; i < G_N_ELEMENTS (scripts); i++) { if (scripts[i] > max) { max = scripts[i]; sel = i; @@ -199,8 +210,8 @@ check_part (struct mime_text_part *part, gboolean raw_mode) static void chartable_symbol_callback (struct rspamd_task *task, void *unused) { - GList *cur; - struct mime_text_part *part; + GList *cur; + struct mime_text_part *part; cur = g_list_first (task->text_parts); while (cur) { diff --git a/src/plugins/dkim_check.c b/src/plugins/dkim_check.c index 78743ebf1..6a162af40 100644 --- a/src/plugins/dkim_check.c +++ b/src/plugins/dkim_check.c @@ -55,24 +55,24 @@ #define DEFAULT_TIME_JITTER 60 struct dkim_ctx { - gint (*filter) (struct rspamd_task * task); - const gchar *symbol_reject; - const gchar *symbol_tempfail; - const gchar *symbol_allow; - - rspamd_mempool_t *dkim_pool; - radix_tree_t *whitelist_ip; - GHashTable *dkim_domains; - guint strict_multiplier; - guint time_jitter; - rspamd_lru_hash_t *dkim_hash; - gboolean trusted_only; - gboolean skip_multi; + gint (*filter) (struct rspamd_task * task); + const gchar *symbol_reject; + const gchar *symbol_tempfail; + const gchar *symbol_allow; + + rspamd_mempool_t *dkim_pool; + radix_tree_t *whitelist_ip; + GHashTable *dkim_domains; + guint strict_multiplier; + guint time_jitter; + rspamd_lru_hash_t *dkim_hash; + gboolean trusted_only; + gboolean skip_multi; }; -static struct dkim_ctx *dkim_module_ctx = NULL; +static struct dkim_ctx *dkim_module_ctx = NULL; -static void dkim_symbol_callback (struct rspamd_task *task, void *unused); +static void dkim_symbol_callback (struct rspamd_task *task, void *unused); /* Initialization */ gint dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx); @@ -92,7 +92,8 @@ dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { dkim_module_ctx = g_malloc0 (sizeof (struct dkim_ctx)); - dkim_module_ctx->dkim_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + dkim_module_ctx->dkim_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); *ctx = (struct module_ctx *)dkim_module_ctx; @@ -102,79 +103,96 @@ dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint dkim_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value; - gint res = TRUE; - guint cache_size, cache_expire; - gboolean got_trusted = FALSE; + const ucl_object_t *value; + gint res = TRUE; + guint cache_size, cache_expire; + gboolean got_trusted = FALSE; dkim_module_ctx->whitelist_ip = radix_tree_create (); - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) { + 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) { + 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) { + 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", "dkim_cache_size")) != NULL) { + 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", "dkim_cache_expire")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", + "dkim_cache_expire")) != NULL) { cache_expire = ucl_obj_todouble (value); } else { cache_expire = DEFAULT_CACHE_MAXAGE; } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) { + 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", "whitelist")) != NULL) { - if (! add_map (cfg, ucl_obj_tostring (value), - "DKIM whitelist", read_radix_list, fin_radix_list, - (void **)&dkim_module_ctx->whitelist_ip)) { - msg_warn ("cannot load whitelist from %s", ucl_obj_tostring (value)); + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) { + if (!add_map (cfg, ucl_obj_tostring (value), + "DKIM whitelist", read_radix_list, fin_radix_list, + (void **)&dkim_module_ctx->whitelist_ip)) { + msg_warn ("cannot load whitelist from %s", + ucl_obj_tostring (value)); } } - if ((value = rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) { - if (! add_map (cfg, ucl_obj_tostring (value), - "DKIM domains", read_kv_list, fin_kv_list, - (void **)&dkim_module_ctx->dkim_domains)) { - msg_warn ("cannot load dkim domains list from %s", ucl_obj_tostring (value)); + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) { + if (!add_map (cfg, ucl_obj_tostring (value), + "DKIM domains", read_kv_list, fin_kv_list, + (void **)&dkim_module_ctx->dkim_domains)) { + msg_warn ("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) { + 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) { + 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) { + if ((value = + rspamd_config_get_module_opt (cfg, "dkim", "skip_multi")) != NULL) { dkim_module_ctx->skip_multi = ucl_obj_toboolean (value); } else { @@ -182,19 +200,33 @@ dkim_module_config (struct rspamd_config *cfg) } if (dkim_module_ctx->trusted_only && !got_trusted) { - msg_err ("trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case"); + msg_err ( + "trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case"); } else { - register_symbol (&cfg->cache, dkim_module_ctx->symbol_reject, 1, dkim_symbol_callback, NULL); - register_virtual_symbol (&cfg->cache, dkim_module_ctx->symbol_tempfail, 1); - register_virtual_symbol (&cfg->cache, dkim_module_ctx->symbol_allow, 1); - - dkim_module_ctx->dkim_hash = rspamd_lru_hash_new (rspamd_strcase_hash, rspamd_strcase_equal, - cache_size, cache_expire, g_free, (GDestroyNotify)rspamd_dkim_key_free); + register_symbol (&cfg->cache, + dkim_module_ctx->symbol_reject, + 1, + dkim_symbol_callback, + NULL); + register_virtual_symbol (&cfg->cache, + dkim_module_ctx->symbol_tempfail, + 1); + register_virtual_symbol (&cfg->cache, + dkim_module_ctx->symbol_allow, + 1); + + dkim_module_ctx->dkim_hash = rspamd_lru_hash_new (rspamd_strcase_hash, + rspamd_strcase_equal, + cache_size, + cache_expire, + g_free, + (GDestroyNotify)rspamd_dkim_key_free); #ifndef HAVE_OPENSSL - msg_warn ("openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results"); + msg_warn ( + "openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results"); #endif } @@ -209,7 +241,8 @@ dkim_module_reconfig (struct rspamd_config *cfg) if (dkim_module_ctx->dkim_domains) { g_hash_table_destroy (dkim_module_ctx->dkim_domains); } - dkim_module_ctx->dkim_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + dkim_module_ctx->dkim_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return dkim_module_config (cfg); } @@ -220,14 +253,14 @@ dkim_module_reconfig (struct rspamd_config *cfg) static gboolean dkim_module_parse_strict (const gchar *value, gint *allow, gint *deny) { - const gchar *colon; - gulong val; + const gchar *colon; + gulong val; colon = strchr (value, ':'); if (colon) { if (rspamd_strtoul (value, colon - value, &val)) { *deny = val; - colon ++; + colon++; if (rspamd_strtoul (colon, strlen (colon), &val)) { *allow = val; return TRUE; @@ -238,25 +271,38 @@ dkim_module_parse_strict (const gchar *value, gint *allow, gint *deny) } static void -dkim_module_check (struct rspamd_task *task, rspamd_dkim_context_t *ctx, rspamd_dkim_key_t *key) +dkim_module_check (struct rspamd_task *task, + rspamd_dkim_context_t *ctx, + rspamd_dkim_key_t *key) { - gint res, score_allow = 1, score_deny = 1; - const gchar *strict_value; + gint res, score_allow = 1, score_deny = 1; + const gchar *strict_value; - msg_debug ("check dkim signature for %s domain from %s", ctx->domain, ctx->dns_key); + msg_debug ("check dkim signature for %s domain from %s", + ctx->domain, + ctx->dns_key); res = rspamd_dkim_check (ctx, key, task); if (dkim_module_ctx->dkim_domains != NULL) { /* Perform strict check */ - if ((strict_value = g_hash_table_lookup (dkim_module_ctx->dkim_domains, ctx->domain)) != NULL) { - if (!dkim_module_parse_strict (strict_value, &score_allow, &score_deny)) { + if ((strict_value = + g_hash_table_lookup (dkim_module_ctx->dkim_domains, + ctx->domain)) != NULL) { + if (!dkim_module_parse_strict (strict_value, &score_allow, + &score_deny)) { score_allow = dkim_module_ctx->strict_multiplier; score_deny = dkim_module_ctx->strict_multiplier; - msg_debug ("no specific score found for %s domain, using %d for it", ctx->domain, score_deny); + msg_debug ( + "no specific score found for %s domain, using %d for it", + ctx->domain, + score_deny); } else { - msg_debug ("specific score found for %s domain: using %d for deny and %d for allow", - ctx->dns_key, score_deny, score_allow); + msg_debug ( + "specific score found for %s domain: using %d for deny and %d for allow", + ctx->dns_key, + score_deny, + score_allow); } } } @@ -273,15 +319,20 @@ dkim_module_check (struct rspamd_task *task, rspamd_dkim_context_t *ctx, rspamd_ } static void -dkim_module_key_handler (rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_context_t *ctx, gpointer ud, GError *err) +dkim_module_key_handler (rspamd_dkim_key_t *key, + gsize keylen, + rspamd_dkim_context_t *ctx, + gpointer ud, + GError *err) { - struct rspamd_task *task = ud; + struct rspamd_task *task = ud; if (key != NULL) { /* Add new key to the lru cache */ - rspamd_lru_hash_insert (dkim_module_ctx->dkim_hash, g_strdup (ctx->dns_key), - key, task->tv.tv_sec, key->ttl); + rspamd_lru_hash_insert (dkim_module_ctx->dkim_hash, + g_strdup (ctx->dns_key), + key, task->tv.tv_sec, key->ttl); dkim_module_check (task, ctx, key); } else { @@ -289,7 +340,8 @@ dkim_module_key_handler (rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_conte msg_info ("cannot get key for domain %s", ctx->dns_key); if (err != NULL) { insert_result (task, dkim_module_ctx->symbol_tempfail, 1, - g_list_prepend (NULL, rspamd_mempool_strdup (task->task_pool, err->message))); + g_list_prepend (NULL, + rspamd_mempool_strdup (task->task_pool, err->message))); } else { @@ -305,19 +357,23 @@ dkim_module_key_handler (rspamd_dkim_key_t *key, gsize keylen, rspamd_dkim_conte static void dkim_symbol_callback (struct rspamd_task *task, void *unused) { - GList *hlist; - rspamd_dkim_context_t *ctx; - rspamd_dkim_key_t *key; - GError *err = NULL; + GList *hlist; + rspamd_dkim_context_t *ctx; + rspamd_dkim_key_t *key; + GError *err = NULL; /* First check if a message has its signature */ - hlist = message_get_header (task->task_pool, task->message, DKIM_SIGNHEADER, FALSE); + hlist = message_get_header (task->task_pool, + task->message, + DKIM_SIGNHEADER, + FALSE); if (hlist != NULL) { /* Check whitelist */ msg_debug ("dkim signature found"); if (task->from_addr.af == AF_INET || - radix32tree_find (dkim_module_ctx->whitelist_ip, - ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) == RADIX_NO_VALUE) { + radix32tree_find (dkim_module_ctx->whitelist_ip, + ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) == + RADIX_NO_VALUE) { /* Parse signature */ msg_debug ("create dkim signature"); /* @@ -326,32 +382,45 @@ dkim_symbol_callback (struct rspamd_task *task, void *unused) */ if (dkim_module_ctx->skip_multi) { if (hlist->next != NULL) { - msg_info ("<%s> skip dkim check as it has several dkim signatures", task->message_id); + msg_info ( + "<%s> skip dkim check as it has several dkim signatures", + task->message_id); return; } } hlist = g_list_last (hlist); - ctx = rspamd_create_dkim_context (hlist->data, task->task_pool, dkim_module_ctx->time_jitter, &err); + ctx = rspamd_create_dkim_context (hlist->data, + task->task_pool, + dkim_module_ctx->time_jitter, + &err); if (ctx == NULL) { msg_info ("cannot parse DKIM context: %s", err->message); g_error_free (err); } else { /* Get key */ - if (dkim_module_ctx->trusted_only && (dkim_module_ctx->dkim_domains == NULL || - g_hash_table_lookup (dkim_module_ctx->dkim_domains, ctx->domain) == NULL)) { + if (dkim_module_ctx->trusted_only && + (dkim_module_ctx->dkim_domains == NULL || + g_hash_table_lookup (dkim_module_ctx->dkim_domains, + ctx->domain) == NULL)) { msg_debug ("skip dkim check for %s domain", ctx->domain); return; } - key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash, ctx->dns_key, task->tv.tv_sec); + key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash, + ctx->dns_key, + task->tv.tv_sec); if (key != NULL) { debug_task ("found key for %s in cache", ctx->dns_key); dkim_module_check (task, ctx, key); } else { debug_task ("request key for %s from DNS", ctx->dns_key); - task->dns_requests ++; - rspamd_get_dkim_key (ctx, task->resolver, task->s, dkim_module_key_handler, task); + task->dns_requests++; + rspamd_get_dkim_key (ctx, + task->resolver, + task->s, + dkim_module_key_handler, + task); } } } diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 1ee1013e6..97b253d9c 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -29,7 +29,7 @@ * - symbol (string): symbol to insert (default: 'R_FUZZY') * - max_score (double): maximum score to that weights of hashes would be normalized (default: 0 - no normalization) * - * - fuzzy_map (string): a string that contains map in format { fuzzy_key => [ symbol, weight ] } where fuzzy_key is number of + * - fuzzy_map (string): a string that contains map in format { fuzzy_key => [ symbol, weight ] } where fuzzy_key is number of * fuzzy list. This string itself should be in format 1:R_FUZZY_SAMPLE1:10,2:R_FUZZY_SAMPLE2:1 etc, where first number is fuzzy * key, second is symbol to insert and third - weight for normalization * @@ -133,10 +133,12 @@ static const gchar hex_digits[] = "0123456789abcdef"; static void fuzzy_symbol_callback (struct rspamd_task *task, void *unused); /* Initialization */ -gint fuzzy_check_module_init (struct rspamd_config *cfg, struct module_ctx **ctx); +gint fuzzy_check_module_init (struct rspamd_config *cfg, + struct module_ctx **ctx); gint fuzzy_check_module_config (struct rspamd_config *cfg); gint fuzzy_check_module_reconfig (struct rspamd_config *cfg); -static gint fuzzy_attach_controller (struct module_ctx *ctx, GHashTable *commands); +static gint fuzzy_attach_controller (struct module_ctx *ctx, + GHashTable *commands); module_t fuzzy_check_module = { "fuzzy_check", @@ -147,14 +149,17 @@ module_t fuzzy_check_module = { }; static void -parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_object_t *val) +parse_flags (struct fuzzy_rule *rule, + struct rspamd_config *cfg, + const ucl_object_t *val) { const ucl_object_t *elt; struct fuzzy_mapping *map; const gchar *sym = NULL; if (val->type == UCL_STRING) { - msg_err ("string mappings are deprecated and no longer supported, use new style configuration"); + msg_err ( + "string mappings are deprecated and no longer supported, use new style configuration"); } else if (val->type == UCL_OBJECT) { elt = ucl_object_find_key (val, "symbol"); @@ -162,7 +167,9 @@ parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_objec sym = ucl_object_key (val); } if (sym != NULL) { - map = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, sizeof (struct fuzzy_mapping)); + map = + rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + sizeof (struct fuzzy_mapping)); map->symbol = sym; elt = ucl_object_find_key (val, "flag"); if (elt != NULL && ucl_obj_toint_safe (elt, &map->fuzzy_flag)) { @@ -174,7 +181,8 @@ parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_objec map->weight = rule->max_score; } /* Add flag to hash table */ - g_hash_table_insert (rule->mappings, GINT_TO_POINTER (map->fuzzy_flag), map); + g_hash_table_insert (rule->mappings, + GINT_TO_POINTER (map->fuzzy_flag), map); register_virtual_symbol (&cfg->cache, map->symbol, 1.0); } else { @@ -193,10 +201,10 @@ parse_flags (struct fuzzy_rule *rule, struct rspamd_config *cfg, const ucl_objec static GList * parse_mime_types (const gchar *str) { - gchar **strvec, *p; - gint num, i; - struct fuzzy_mime_type *type; - GList *res = NULL; + gchar **strvec, *p; + gint num, i; + struct fuzzy_mime_type *type; + GList *res = NULL; strvec = g_strsplit_set (str, ",", 0); num = g_strv_length (strvec); @@ -204,9 +212,13 @@ parse_mime_types (const gchar *str) g_strstrip (strvec[i]); if ((p = strchr (strvec[i], '/')) != NULL) { *p = 0; - type = rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, sizeof (struct fuzzy_mime_type)); - type->type = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, strvec[i]); - type->subtype = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, p + 1); + type = + rspamd_mempool_alloc (fuzzy_module_ctx->fuzzy_pool, + sizeof (struct fuzzy_mime_type)); + type->type = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, + strvec[i]); + type->subtype = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, + p + 1); res = g_list_prepend (res, type); } else { @@ -215,7 +227,8 @@ parse_mime_types (const gchar *str) } if (res != NULL) { - rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, (rspamd_mempool_destruct_t)g_list_free, res); + rspamd_mempool_add_destructor (fuzzy_module_ctx->fuzzy_pool, + (rspamd_mempool_destruct_t)g_list_free, res); } return res; @@ -224,8 +237,8 @@ parse_mime_types (const gchar *str) static gboolean fuzzy_check_content_type (struct fuzzy_rule *rule, GMimeContentType *type) { - struct fuzzy_mime_type *ft; - GList *cur; + struct fuzzy_mime_type *ft; + GList *cur; cur = rule->mime_types; while (cur) { @@ -242,24 +255,27 @@ fuzzy_check_content_type (struct fuzzy_rule *rule, GMimeContentType *type) static void parse_servers_string (struct fuzzy_rule *rule, const gchar *str) { - gchar **strvec; - gint i, num; - struct storage_server *cur; + gchar **strvec; + gint i, num; + struct storage_server *cur; strvec = g_strsplit_set (str, ",", 0); num = g_strv_length (strvec); - rule->servers = rspamd_mempool_alloc0 (fuzzy_module_ctx->fuzzy_pool, sizeof (struct storage_server) * num); + rule->servers = rspamd_mempool_alloc0 (fuzzy_module_ctx->fuzzy_pool, + sizeof (struct storage_server) * num); for (i = 0; i < num; i++) { g_strstrip (strvec[i]); cur = &rule->servers[rule->servers_num]; - if (rspamd_parse_host_port (fuzzy_module_ctx->fuzzy_pool, strvec[i], &cur->addr, &cur->port)) { + if (rspamd_parse_host_port (fuzzy_module_ctx->fuzzy_pool, strvec[i], + &cur->addr, &cur->port)) { if (cur->port == 0) { cur->port = DEFAULT_PORT; } - cur->name = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, strvec[i]); + cur->name = rspamd_mempool_strdup (fuzzy_module_ctx->fuzzy_pool, + strvec[i]); rule->servers_num++; } } @@ -286,10 +302,10 @@ fuzzy_to_string (fuzzy_hash_t *h) { static gchar strbuf [FUZZY_HASHLEN * 2 + 1]; const int max_print = 5; - gint i; + gint i; guint8 byte; - for (i = 0; i < max_print; i ++) { + for (i = 0; i < max_print; i++) { byte = h->hash_pipe[i]; if (byte == '\0') { break; @@ -316,7 +332,9 @@ fuzzy_rule_new (const char *default_symbol, rspamd_mempool_t *pool) rule->mappings = g_hash_table_new (g_direct_hash, g_direct_equal); rule->symbol = default_symbol; - rspamd_mempool_add_destructor (pool, (rspamd_mempool_destruct_t)g_hash_table_unref, rule->mappings); + rspamd_mempool_add_destructor (pool, + (rspamd_mempool_destruct_t)g_hash_table_unref, + rule->mappings); rule->read_only = FALSE; return rule; @@ -334,13 +352,15 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj) return -1; } - rule = fuzzy_rule_new (fuzzy_module_ctx->default_symbol, fuzzy_module_ctx->fuzzy_pool); + rule = fuzzy_rule_new (fuzzy_module_ctx->default_symbol, + fuzzy_module_ctx->fuzzy_pool); if ((value = ucl_object_find_key (obj, "mime_types")) != NULL) { if (value->type == UCL_ARRAY) { value = value->value.av; } - LL_FOREACH (value, cur) { + LL_FOREACH (value, cur) + { rule->mime_types = g_list_concat (rule->mime_types, parse_mime_types (ucl_obj_tostring (cur))); } @@ -363,7 +383,8 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj) if (value->type == UCL_ARRAY) { value = value->value.av; } - LL_FOREACH (value, cur) { + LL_FOREACH (value, cur) + { parse_servers_string (rule, ucl_obj_tostring (cur)); } } @@ -374,11 +395,14 @@ fuzzy_parse_rule (struct rspamd_config *cfg, const ucl_object_t *obj) } if (rule->servers_num == 0) { - msg_err ("no servers defined for fuzzy rule with symbol: %s", rule->symbol); + msg_err ("no servers defined for fuzzy rule with symbol: %s", + rule->symbol); return -1; } else { - fuzzy_module_ctx->fuzzy_rules = g_list_prepend (fuzzy_module_ctx->fuzzy_rules, rule); + fuzzy_module_ctx->fuzzy_rules = g_list_prepend ( + fuzzy_module_ctx->fuzzy_rules, + rule); if (rule->symbol != fuzzy_module_ctx->default_symbol) { register_virtual_symbol (&cfg->cache, rule->symbol, 1.0); } @@ -392,7 +416,8 @@ fuzzy_check_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { fuzzy_module_ctx = g_malloc0 (sizeof (struct fuzzy_ctx)); - fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); fuzzy_module_ctx->cfg = cfg; *ctx = (struct module_ctx *)fuzzy_module_ctx; @@ -403,52 +428,64 @@ fuzzy_check_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint fuzzy_check_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value, *cur; - gint res = TRUE; + const ucl_object_t *value, *cur; + gint res = TRUE; - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "symbol")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", "symbol")) != NULL) { fuzzy_module_ctx->default_symbol = ucl_obj_tostring (value); } else { fuzzy_module_ctx->default_symbol = DEFAULT_SYMBOL; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_length")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_length")) != NULL) { fuzzy_module_ctx->min_hash_len = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_hash_len = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_bytes")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_bytes")) != NULL) { fuzzy_module_ctx->min_bytes = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_bytes = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_height")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_height")) != NULL) { fuzzy_module_ctx->min_height = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_height = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "min_width")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "min_width")) != NULL) { fuzzy_module_ctx->min_width = ucl_obj_toint (value); } else { fuzzy_module_ctx->min_width = 0; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "timeout")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", "timeout")) != NULL) { fuzzy_module_ctx->io_timeout = ucl_obj_todouble (value) * 1000; } else { fuzzy_module_ctx->io_timeout = DEFAULT_IO_TIMEOUT; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "whitelist")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", + "whitelist")) != NULL) { fuzzy_module_ctx->whitelist = radix_tree_create (); if (!add_map (cfg, ucl_obj_tostring (value), - "Fuzzy whitelist", read_radix_list, fin_radix_list, - (void **)&fuzzy_module_ctx->whitelist)) { + "Fuzzy whitelist", read_radix_list, fin_radix_list, + (void **)&fuzzy_module_ctx->whitelist)) { msg_err ("cannot add whitelist '%s'", ucl_obj_tostring (value)); } } @@ -456,8 +493,10 @@ fuzzy_check_module_config (struct rspamd_config *cfg) fuzzy_module_ctx->whitelist = NULL; } - if ((value = rspamd_config_get_module_opt (cfg, "fuzzy_check", "rule")) != NULL) { - LL_FOREACH (value, cur) { + if ((value = + rspamd_config_get_module_opt (cfg, "fuzzy_check", "rule")) != NULL) { + LL_FOREACH (value, cur) + { if (fuzzy_parse_rule (cfg, cur) == -1) { return -1; } @@ -466,7 +505,7 @@ fuzzy_check_module_config (struct rspamd_config *cfg) if (fuzzy_module_ctx->fuzzy_rules != NULL) { register_callback_symbol (&cfg->cache, fuzzy_module_ctx->default_symbol, - 1.0, fuzzy_symbol_callback, NULL); + 1.0, fuzzy_symbol_callback, NULL); } else { msg_warn ("fuzzy module is enabled but no rules are defined"); @@ -480,9 +519,10 @@ fuzzy_check_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (fuzzy_module_ctx->fuzzy_pool); - fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + fuzzy_module_ctx->fuzzy_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); fuzzy_module_ctx->cfg = cfg; - + return fuzzy_check_module_config (cfg); } @@ -490,7 +530,7 @@ fuzzy_check_module_reconfig (struct rspamd_config *cfg) static void fuzzy_io_fin (void *ud) { - struct fuzzy_client_session *session = ud; + struct fuzzy_client_session *session = ud; event_del (&session->ev); close (session->fd); @@ -500,13 +540,13 @@ fuzzy_io_fin (void *ud) static void fuzzy_io_callback (gint fd, short what, void *arg) { - struct fuzzy_client_session *session = arg; - struct fuzzy_cmd cmd; - struct fuzzy_mapping *map; - gchar buf[62], *err_str; - const gchar *symbol; - gint value = 0, flag = 0, r; - double nval; + struct fuzzy_client_session *session = arg; + struct fuzzy_cmd cmd; + struct fuzzy_mapping *map; + gchar buf[62], *err_str; + const gchar *symbol; + gint value = 0, flag = 0, r; + double nval; if (what == EV_WRITE) { /* Send command to storage */ @@ -540,7 +580,9 @@ fuzzy_io_callback (gint fd, short what, void *arg) } *err_str = '\0'; /* Get mapping by flag */ - if ((map = g_hash_table_lookup (session->rule->mappings, GINT_TO_POINTER (flag))) == NULL) { + if ((map = + g_hash_table_lookup (session->rule->mappings, + GINT_TO_POINTER (flag))) == NULL) { /* Default symbol and default weight */ symbol = session->rule->symbol; nval = fuzzy_normalize (value, session->rule->max_score); @@ -550,37 +592,53 @@ fuzzy_io_callback (gint fd, short what, void *arg) symbol = map->symbol; nval = fuzzy_normalize (value, map->weight); } - msg_info ("<%s>, found fuzzy hash '%s' with weight: %.2f, in list: %s:%d%s", - session->task->message_id, fuzzy_to_string (session->h), nval, symbol, - flag, map == NULL ? "(unknown)" : ""); + msg_info ( + "<%s>, found fuzzy hash '%s' with weight: %.2f, in list: %s:%d%s", + session->task->message_id, + fuzzy_to_string (session->h), + nval, + symbol, + flag, + map == NULL ? "(unknown)" : ""); if (map != NULL || !session->rule->skip_unknown) { - rspamd_snprintf (buf, sizeof (buf), "%d: %d / %.2f", flag, value, nval); - insert_result_single (session->task, symbol, nval, g_list_prepend (NULL, - rspamd_mempool_strdup (session->task->task_pool, buf))); + rspamd_snprintf (buf, + sizeof (buf), + "%d: %d / %.2f", + flag, + value, + nval); + insert_result_single (session->task, + symbol, + nval, + g_list_prepend (NULL, + rspamd_mempool_strdup (session->task->task_pool, buf))); } } goto ok; } else { errno = ETIMEDOUT; - goto err; + goto err; } return; - err: - msg_err ("got error on IO with server %s, %d, %s", session->server->name, errno, strerror (errno)); - ok: +err: + msg_err ("got error on IO with server %s, %d, %s", + session->server->name, + errno, + strerror (errno)); +ok: remove_normal_event (session->task->s, fuzzy_io_fin, session); } static void fuzzy_learn_callback (gint fd, short what, void *arg) { - struct fuzzy_learn_session *session = arg; - struct fuzzy_cmd cmd; - gchar buf[512]; - const gchar *cmd_name; + struct fuzzy_learn_session *session = arg; + struct fuzzy_cmd cmd; + gchar buf[512]; + const gchar *cmd_name; cmd_name = (session->cmd == FUZZY_WRITE ? "add" : "delete"); if (what == EV_WRITE) { @@ -593,41 +651,52 @@ fuzzy_learn_callback (gint fd, short what, void *arg) if (write (fd, &cmd, sizeof (struct fuzzy_cmd)) == -1) { if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), - errno, "write socket error: %s", strerror (errno)); + g_quark_from_static_string ("fuzzy check"), + errno, "write socket error: %s", strerror (errno)); } goto err; } else { event_del (&session->ev); - event_set (&session->ev, fd, EV_READ, fuzzy_learn_callback, session); + event_set (&session->ev, fd, EV_READ, fuzzy_learn_callback, + session); event_add (&session->ev, &session->tv); } } else if (what == EV_READ) { if (read (fd, buf, sizeof (buf)) == -1) { - msg_info ("cannot %s fuzzy hash for message <%s>, list %s:%d", cmd_name, - session->task->message_id, session->rule->symbol, session->flag); + msg_info ("cannot %s fuzzy hash for message <%s>, list %s:%d", + cmd_name, + session->task->message_id, + session->rule->symbol, + session->flag); if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), - errno, "read socket error: %s", strerror (errno)); + g_quark_from_static_string ("fuzzy check"), + errno, "read socket error: %s", strerror (errno)); } goto err; } else if (buf[0] == 'O' && buf[1] == 'K') { - msg_info ("%s fuzzy hash '%s', list: %s:%d for message <%s>", cmd_name, - fuzzy_to_string (session->h), session->rule->symbol, - session->flag, session->task->message_id); + msg_info ("%s fuzzy hash '%s', list: %s:%d for message <%s>", + cmd_name, + fuzzy_to_string (session->h), + session->rule->symbol, + session->flag, + session->task->message_id); goto ok; } else { - msg_info ("cannot %s fuzzy hash '%s' for message <%s>, list %s:%d", cmd_name, - fuzzy_to_string (session->h), session->task->message_id, - session->rule->symbol, session->flag); + msg_info ("cannot %s fuzzy hash '%s' for message <%s>, list %s:%d", + cmd_name, + fuzzy_to_string (session->h), + session->task->message_id, + session->rule->symbol, + session->flag); if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), EINVAL, "%s fuzzy error", cmd_name); + g_quark_from_static_string ( + "fuzzy check"), EINVAL, "%s fuzzy error", cmd_name); } goto ok; } @@ -636,16 +705,17 @@ fuzzy_learn_callback (gint fd, short what, void *arg) errno = ETIMEDOUT; if (*(session->err) == NULL) { g_set_error (session->err, - g_quark_from_static_string ("fuzzy check"), EINVAL, "%s fuzzy, IO timeout", cmd_name); + g_quark_from_static_string ( + "fuzzy check"), EINVAL, "%s fuzzy, IO timeout", cmd_name); } - goto err; + goto err; } return; err: msg_err ("got error in IO with server %s, %d, %s", - session->server->name, errno, strerror (errno)); + session->server->name, errno, strerror (errno)); rspamd_http_connection_unref (session->http_entry->conn); rspamd_task_free (session->task, TRUE); event_del (&session->ev); @@ -655,42 +725,63 @@ ok: if (--(*(session->saved)) == 0) { if (*(session->err) != NULL) { rspamd_controller_send_error (session->http_entry, - (*session->err)->code, (*session->err)->message); + (*session->err)->code, (*session->err)->message); g_error_free (*session->err); } else { rspamd_controller_send_string (session->http_entry, - "{\"success\":true}"); + "{\"success\":true}"); } } } static inline void -register_fuzzy_call (struct rspamd_task *task, struct fuzzy_rule *rule, fuzzy_hash_t *h) +register_fuzzy_call (struct rspamd_task *task, + struct fuzzy_rule *rule, + fuzzy_hash_t *h) { - struct fuzzy_client_session *session; - struct storage_server *selected; - gint sock; + struct fuzzy_client_session *session; + struct storage_server *selected; + gint sock; /* Get upstream */ #ifdef HAVE_CLOCK_GETTIME - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->ts.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->ts.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #else - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->tv.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->tv.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #endif if (selected) { - if ((sock = make_universal_socket (selected->addr, selected->port, SOCK_DGRAM, TRUE, FALSE, FALSE)) == -1) { - msg_warn ("cannot connect to %s, %d, %s", selected->name, errno, strerror (errno)); + if ((sock = + make_universal_socket (selected->addr, selected->port, SOCK_DGRAM, + TRUE, FALSE, FALSE)) == -1) { + msg_warn ("cannot connect to %s, %d, %s", + selected->name, + errno, + strerror (errno)); } else { /* Create session for a socket */ - session = rspamd_mempool_alloc (task->task_pool, sizeof (struct fuzzy_client_session)); - event_set (&session->ev, sock, EV_WRITE, fuzzy_io_callback, session); + session = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct fuzzy_client_session)); + event_set (&session->ev, sock, EV_WRITE, fuzzy_io_callback, + session); msec_to_tv (fuzzy_module_ctx->io_timeout, &session->tv); session->state = 0; session->h = h; @@ -699,7 +790,10 @@ register_fuzzy_call (struct rspamd_task *task, struct fuzzy_rule *rule, fuzzy_ha session->server = selected; session->rule = rule; event_add (&session->ev, &session->tv); - register_async_event (task->s, fuzzy_io_fin, session, g_quark_from_static_string ("fuzzy check")); + register_async_event (task->s, + fuzzy_io_fin, + session, + g_quark_from_static_string ("fuzzy check")); } } } @@ -707,13 +801,13 @@ register_fuzzy_call (struct rspamd_task *task, struct fuzzy_rule *rule, fuzzy_ha static void fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) { - struct mime_text_part *part; - struct mime_part *mime_part; - struct rspamd_image *image; - gchar *checksum; - gsize hashlen; - GList *cur; - fuzzy_hash_t *fake_fuzzy; + struct mime_text_part *part; + struct mime_part *mime_part; + struct rspamd_image *image; + gchar *checksum; + gsize hashlen; + GList *cur; + fuzzy_hash_t *fake_fuzzy; cur = task->text_parts; @@ -727,7 +821,7 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) /* Check length of part */ if (fuzzy_module_ctx->min_bytes > part->content->len) { msg_info ("<%s>, part is shorter than %d symbols, skip fuzzy check", - task->message_id, fuzzy_module_ctx->min_bytes); + task->message_id, fuzzy_module_ctx->min_bytes); cur = g_list_next (cur); continue; } @@ -735,14 +829,17 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) hashlen = strlen (part->fuzzy->hash_pipe); if (hashlen == 0) { msg_info ("<%s>, part hash empty, skip fuzzy check", - task->message_id, fuzzy_module_ctx->min_hash_len); + task->message_id, fuzzy_module_ctx->min_hash_len); cur = g_list_next (cur); continue; } if (fuzzy_module_ctx->min_hash_len != 0 && - hashlen * part->fuzzy->block_size < fuzzy_module_ctx->min_hash_len) { - msg_info ("<%s>, part hash is shorter than %d symbols, skip fuzzy check", - task->message_id, fuzzy_module_ctx->min_hash_len); + hashlen * part->fuzzy->block_size < + fuzzy_module_ctx->min_hash_len) { + msg_info ( + "<%s>, part hash is shorter than %d symbols, skip fuzzy check", + task->message_id, + fuzzy_module_ctx->min_hash_len); cur = g_list_next (cur); continue; } @@ -757,12 +854,18 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) while (cur) { image = cur->data; if (image->data->len > 0) { - if (fuzzy_module_ctx->min_height <= 0 || image->height >= fuzzy_module_ctx->min_height) { - if (fuzzy_module_ctx->min_width <= 0 || image->width >= fuzzy_module_ctx->min_width) { - checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, image->data->data, image->data->len); + if (fuzzy_module_ctx->min_height <= 0 || image->height >= + fuzzy_module_ctx->min_height) { + if (fuzzy_module_ctx->min_width <= 0 || image->width >= + fuzzy_module_ctx->min_width) { + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + image->data->data, + image->data->len); /* Construct fake fuzzy hash */ - fake_fuzzy = rspamd_mempool_alloc0 (task->task_pool, sizeof (fuzzy_hash_t)); - rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); + fake_fuzzy = rspamd_mempool_alloc0 (task->task_pool, + sizeof (fuzzy_hash_t)); + rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, + sizeof (fake_fuzzy->hash_pipe)); register_fuzzy_call (task, rule, fake_fuzzy); g_free (checksum); } @@ -774,15 +877,20 @@ fuzzy_check_rule (struct rspamd_task *task, struct fuzzy_rule *rule) cur = task->parts; while (cur) { mime_part = cur->data; - if (mime_part->content->len > 0 && fuzzy_check_content_type (rule, mime_part->type)) { - if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= fuzzy_module_ctx->min_bytes) { - checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, - mime_part->content->data, mime_part->content->len); - /* Construct fake fuzzy hash */ - fake_fuzzy = rspamd_mempool_alloc0 (task->task_pool, sizeof (fuzzy_hash_t)); - rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); - register_fuzzy_call (task, rule, fake_fuzzy); - g_free (checksum); + if (mime_part->content->len > 0 && + fuzzy_check_content_type (rule, mime_part->type)) { + if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= + fuzzy_module_ctx->min_bytes) { + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + mime_part->content->data, mime_part->content->len); + /* Construct fake fuzzy hash */ + fake_fuzzy = + rspamd_mempool_alloc0 (task->task_pool, + sizeof (fuzzy_hash_t)); + rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, + sizeof (fake_fuzzy->hash_pipe)); + register_fuzzy_call (task, rule, fake_fuzzy); + g_free (checksum); } } cur = g_list_next (cur); @@ -799,9 +907,11 @@ fuzzy_symbol_callback (struct rspamd_task *task, void *unused) /* Check whitelist */ if (fuzzy_module_ctx->whitelist && task->from_addr.af == AF_INET) { if (radix32tree_find (fuzzy_module_ctx->whitelist, - ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) != RADIX_NO_VALUE) { + ntohl (task->from_addr.addr.s4.sin_addr.s_addr)) != + RADIX_NO_VALUE) { msg_info ("<%s>, address %s is whitelisted, skip fuzzy check", - task->message_id, rspamd_inet_address_to_string (&task->from_addr)); + task->message_id, + rspamd_inet_address_to_string (&task->from_addr)); return; } } @@ -816,41 +926,54 @@ fuzzy_symbol_callback (struct rspamd_task *task, void *unused) static inline gboolean register_fuzzy_controller_call (struct rspamd_http_connection_entry *entry, - struct fuzzy_rule *rule, struct rspamd_task *task, fuzzy_hash_t *h, - gint cmd, gint value, gint flag, gint *saved, GError **err) + struct fuzzy_rule *rule, struct rspamd_task *task, fuzzy_hash_t *h, + gint cmd, gint value, gint flag, gint *saved, GError **err) { - struct fuzzy_learn_session *s; - struct storage_server *selected; - gint sock; + struct fuzzy_learn_session *s; + struct storage_server *selected; + gint sock; /* Get upstream */ #ifdef HAVE_CLOCK_GETTIME - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->ts.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->ts.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #else - selected = (struct storage_server *)get_upstream_by_hash (rule->servers, rule->servers_num, - sizeof (struct storage_server), task->tv.tv_sec, - DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, - h->hash_pipe, sizeof (h->hash_pipe)); + selected = (struct storage_server *)get_upstream_by_hash (rule->servers, + rule->servers_num, + sizeof (struct storage_server), + task->tv.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS, + h->hash_pipe, + sizeof (h->hash_pipe)); #endif if (selected) { /* Create UDP socket */ if ((sock = make_universal_socket (selected->addr, selected->port, - SOCK_DGRAM, TRUE, FALSE, FALSE)) == -1) { + SOCK_DGRAM, TRUE, FALSE, FALSE)) == -1) { return FALSE; } else { /* Socket is made, create session */ - s = rspamd_mempool_alloc (task->task_pool, sizeof (struct fuzzy_learn_session)); + s = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct fuzzy_learn_session)); event_set (&s->ev, sock, EV_WRITE, fuzzy_learn_callback, s); event_base_set (entry->rt->ev_base, &s->ev); msec_to_tv (fuzzy_module_ctx->io_timeout, &s->tv); s->task = task; - s->h = rspamd_mempool_alloc (task->task_pool, sizeof (fuzzy_hash_t)); + s->h = + rspamd_mempool_alloc (task->task_pool, sizeof (fuzzy_hash_t)); memcpy (s->h, h, sizeof (fuzzy_hash_t)); - s->http_entry =entry; + s->http_entry = entry; s->server = selected; s->cmd = cmd; s->value = value; @@ -871,38 +994,46 @@ register_fuzzy_controller_call (struct rspamd_http_connection_entry *entry, } static int -fuzzy_process_rule (struct rspamd_http_connection_entry *entry, struct fuzzy_rule *rule, - struct rspamd_task *task, GError **err, gint cmd, gint flag, gint value, gint *saved) +fuzzy_process_rule (struct rspamd_http_connection_entry *entry, + struct fuzzy_rule *rule, + struct rspamd_task *task, + GError **err, + gint cmd, + gint flag, + gint value, + gint *saved) { - struct mime_text_part *part; - struct mime_part *mime_part; - struct rspamd_image *image; - GList *cur; - gchar *checksum; - fuzzy_hash_t fake_fuzzy; - gint processed = 0; + struct mime_text_part *part; + struct mime_part *mime_part; + struct rspamd_image *image; + GList *cur; + gchar *checksum; + fuzzy_hash_t fake_fuzzy; + gint processed = 0; /* Plan new event for writing */ cur = task->text_parts; while (cur) { part = cur->data; - if (part->is_empty || part->fuzzy == NULL || part->fuzzy->hash_pipe[0] == '\0' || - (fuzzy_module_ctx->min_bytes > 0 && part->content->len < fuzzy_module_ctx->min_bytes)) { + if (part->is_empty || part->fuzzy == NULL || + part->fuzzy->hash_pipe[0] == '\0' || + (fuzzy_module_ctx->min_bytes > 0 && part->content->len < + fuzzy_module_ctx->min_bytes)) { /* Skip empty parts */ cur = g_list_next (cur); continue; } - if (! register_fuzzy_controller_call (entry, rule, task, - part->fuzzy, cmd, value, flag, saved, err)) { + if (!register_fuzzy_controller_call (entry, rule, task, + part->fuzzy, cmd, value, flag, saved, err)) { goto err; } - if (! register_fuzzy_controller_call (entry, rule, task, - part->double_fuzzy, cmd, value, flag, saved, err)) { + if (!register_fuzzy_controller_call (entry, rule, task, + part->double_fuzzy, cmd, value, flag, saved, err)) { /* Cannot write hash */ goto err; } - processed ++; + processed++; cur = g_list_next (cur); } @@ -911,22 +1042,30 @@ fuzzy_process_rule (struct rspamd_http_connection_entry *entry, struct fuzzy_rul while (cur) { image = cur->data; if (image->data->len > 0) { - if (fuzzy_module_ctx->min_height <= 0 || image->height >= fuzzy_module_ctx->min_height) { - if (fuzzy_module_ctx->min_width <= 0 || image->width >= fuzzy_module_ctx->min_width) { - checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, image->data->data, image->data->len); + if (fuzzy_module_ctx->min_height <= 0 || image->height >= + fuzzy_module_ctx->min_height) { + if (fuzzy_module_ctx->min_width <= 0 || image->width >= + fuzzy_module_ctx->min_width) { + checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + image->data->data, + image->data->len); /* Construct fake fuzzy hash */ fake_fuzzy.block_size = 0; - memset (fake_fuzzy.hash_pipe, 0, sizeof (fake_fuzzy.hash_pipe)); - rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); - if (! register_fuzzy_controller_call (entry, rule, task, - &fake_fuzzy, cmd, value, flag, saved, err)) { + memset (fake_fuzzy.hash_pipe, 0, + sizeof (fake_fuzzy.hash_pipe)); + rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, + sizeof (fake_fuzzy.hash_pipe)); + if (!register_fuzzy_controller_call (entry, rule, task, + &fake_fuzzy, cmd, value, flag, saved, err)) { g_free (checksum); goto err; } - msg_info ("save hash of image: [%s] to list: %d", checksum, flag); + msg_info ("save hash of image: [%s] to list: %d", + checksum, + flag); g_free (checksum); - processed ++; + processed++; } } } @@ -936,23 +1075,26 @@ fuzzy_process_rule (struct rspamd_http_connection_entry *entry, struct fuzzy_rul cur = task->parts; while (cur) { mime_part = cur->data; - if (mime_part->content->len > 0 && fuzzy_check_content_type (rule, mime_part->type)) { - if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= fuzzy_module_ctx->min_bytes) { + if (mime_part->content->len > 0 && + fuzzy_check_content_type (rule, mime_part->type)) { + if (fuzzy_module_ctx->min_bytes <= 0 || mime_part->content->len >= + fuzzy_module_ctx->min_bytes) { checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, mime_part->content->data, mime_part->content->len); /* Construct fake fuzzy hash */ fake_fuzzy.block_size = 0; memset (fake_fuzzy.hash_pipe, 0, sizeof (fake_fuzzy.hash_pipe)); - rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); - if (! register_fuzzy_controller_call (entry, rule, task, - &fake_fuzzy, cmd, value, flag, saved, err)) { + rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, + sizeof (fake_fuzzy.hash_pipe)); + if (!register_fuzzy_controller_call (entry, rule, task, + &fake_fuzzy, cmd, value, flag, saved, err)) { goto err; } msg_info ("save hash of part of type: %s/%s: [%s] to list %d", - mime_part->type->type, mime_part->type->subtype, - checksum, flag); + mime_part->type->type, mime_part->type->subtype, + checksum, flag); g_free (checksum); - processed ++; + processed++; } } cur = g_list_next (cur); @@ -967,8 +1109,8 @@ err: static void fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, gint cmd, gint value, gint flag, - struct fuzzy_ctx *ctx) + struct rspamd_http_message *msg, gint cmd, gint value, gint flag, + struct fuzzy_ctx *ctx) { struct fuzzy_rule *rule; gboolean processed = FALSE, res = TRUE; @@ -990,7 +1132,8 @@ fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, if (r == -1) { msg_warn ("cannot process message for fuzzy"); rspamd_task_free (task, FALSE); - rspamd_controller_send_error (conn_ent, 400, "Message processing error"); + rspamd_controller_send_error (conn_ent, 400, + "Message processing error"); return; } cur = fuzzy_module_ctx->fuzzy_rules; @@ -1003,7 +1146,8 @@ fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, } /* Check for flag */ - if (g_hash_table_lookup (rule->mappings, GINT_TO_POINTER (flag)) == NULL) { + if (g_hash_table_lookup (rule->mappings, + GINT_TO_POINTER (flag)) == NULL) { cur = g_list_next (cur); continue; } @@ -1039,11 +1183,11 @@ fuzzy_process_handler (struct rspamd_http_connection_entry *conn_ent, static gboolean fuzzy_controller_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, struct module_ctx *ctx, gint cmd) + struct rspamd_http_message *msg, struct module_ctx *ctx, gint cmd) { const gchar *arg; gchar *err_str; - gint value = 1, flag = 0; + gint value = 1, flag = 0; /* Get size */ arg = rspamd_http_message_find_header (msg, "Value"); @@ -1066,25 +1210,25 @@ fuzzy_controller_handler (struct rspamd_http_connection_entry *conn_ent, } fuzzy_process_handler (conn_ent, msg, cmd, value, flag, - (struct fuzzy_ctx *)ctx); + (struct fuzzy_ctx *)ctx); return 0; } static gboolean fuzzy_add_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, struct module_ctx *ctx) + struct rspamd_http_message *msg, struct module_ctx *ctx) { return fuzzy_controller_handler (conn_ent, msg, - ctx, FUZZY_WRITE); + ctx, FUZZY_WRITE); } static gboolean fuzzy_delete_handler (struct rspamd_http_connection_entry *conn_ent, - struct rspamd_http_message *msg, struct module_ctx *ctx) + struct rspamd_http_message *msg, struct module_ctx *ctx) { return fuzzy_controller_handler (conn_ent, msg, - ctx, FUZZY_DEL); + ctx, FUZZY_DEL); } static int diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index bddde5383..31d4943fd 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -40,62 +40,82 @@ #define DEFAULT_STATFILE_PREFIX "./" struct regexp_module_item { - struct expression *expr; - const gchar *symbol; - guint32 avg_time; - gpointer lua_function; + struct expression *expr; + const gchar *symbol; + guint32 avg_time; + gpointer lua_function; }; struct autolearn_data { - gchar *statfile_name; - gchar *symbol; - float weight; + gchar *statfile_name; + gchar *symbol; + float weight; }; struct regexp_ctx { - gint (*filter) (struct rspamd_task * task); - GHashTable *autolearn_symbols; - gchar *statfile_prefix; - - rspamd_mempool_t *regexp_pool; - rspamd_mempool_t *dynamic_pool; - gsize max_size; - gsize max_threads; - GThreadPool *workers; + gint (*filter) (struct rspamd_task * task); + GHashTable *autolearn_symbols; + gchar *statfile_prefix; + + rspamd_mempool_t *regexp_pool; + rspamd_mempool_t *dynamic_pool; + gsize max_size; + gsize max_threads; + GThreadPool *workers; }; struct regexp_json_buf { - gchar *buf; - gchar *pos; - size_t buflen; - struct rspamd_config *cfg; + gchar *buf; + gchar *pos; + size_t buflen; + struct rspamd_config *cfg; }; /* Lua regexp module for checking rspamd regexps */ LUA_FUNCTION_DEF (regexp, match); -static const struct luaL_reg regexplib_m[] = { +static const struct luaL_reg regexplib_m[] = { LUA_INTERFACE_DEF (regexp, match), {"__tostring", lua_class_tostring}, {NULL, NULL} }; -static struct regexp_ctx *regexp_module_ctx = NULL; -static GMutex *workers_mtx = NULL; - -static gint regexp_common_filter (struct rspamd_task *task); -static void process_regexp_item_threaded (gpointer data, gpointer user_data); -static gboolean rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void *unused); -static gboolean rspamd_has_content_part (struct rspamd_task *task, GList * args, void *unused); -static gboolean rspamd_has_content_part_len (struct rspamd_task *task, GList * args, void *unused); -static void process_regexp_item (struct rspamd_task *task, void *user_data); +static struct regexp_ctx *regexp_module_ctx = NULL; +static GMutex *workers_mtx = NULL; + +static gint regexp_common_filter (struct rspamd_task *task); +static void process_regexp_item_threaded (gpointer data, gpointer user_data); +static gboolean rspamd_regexp_match_number (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_raw_header_exists (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_check_smtp_data (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_regexp_occurs_number (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_content_type_is_type (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_content_type_is_subtype (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_content_type_has_param (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_content_type_compare_param (struct rspamd_task * task, + GList * args, + void *unused); +static gboolean rspamd_has_content_part (struct rspamd_task *task, + GList * args, + void *unused); +static gboolean rspamd_has_content_part_len (struct rspamd_task *task, + GList * args, + void *unused); +static void process_regexp_item (struct rspamd_task *task, void *user_data); /* Initialization */ @@ -113,13 +133,15 @@ module_t regexp_module = { /* Task cache functions */ #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) -static GStaticMutex task_cache_mtx = G_STATIC_MUTEX_INIT; +static GStaticMutex task_cache_mtx = G_STATIC_MUTEX_INIT; #else G_LOCK_DEFINE (task_cache_mtx); #endif void -task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 result) +task_cache_add (struct rspamd_task *task, + struct rspamd_regexp *re, + gint32 result) { if (result == 0) { result = -1; @@ -130,7 +152,8 @@ task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 resul #else G_LOCK (task_cache_mtx); #endif - g_hash_table_insert (task->re_cache, re->regexp_text, GINT_TO_POINTER (result)); + g_hash_table_insert (task->re_cache, re->regexp_text, + GINT_TO_POINTER (result)); #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) g_static_mutex_unlock (&task_cache_mtx); #else @@ -141,8 +164,8 @@ task_cache_add (struct rspamd_task *task, struct rspamd_regexp *re, gint32 resul gint32 task_cache_check (struct rspamd_task *task, struct rspamd_regexp *re) { - gpointer res; - gint32 r; + gpointer res; + gint32 r; #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) g_static_mutex_lock (&task_cache_mtx); @@ -178,11 +201,11 @@ luaopen_regexp (lua_State * L) return 1; } -static void +static void regexp_dynamic_insert_result (struct rspamd_task *task, void *user_data) { - gchar *symbol = user_data; - + gchar *symbol = user_data; + insert_result (task, symbol, 1, NULL); } @@ -222,18 +245,18 @@ op_less_equal (gint a, gint b) static gboolean parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) { - const gchar *pos; - gchar ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p; - gint state = 0, dots = 0; - - bzero (ip_buf, sizeof (ip_buf)); + const gchar *pos; + gchar ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p; + gint state = 0, dots = 0; + + bzero (ip_buf, sizeof (ip_buf)); bzero (mask_buf, sizeof (mask_buf)); pos = begin; p = ip_buf; if (*pos == '!') { addr->negative = TRUE; - pos ++; + pos++; } else { addr->negative = FALSE; @@ -241,45 +264,45 @@ parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) while (*pos) { switch (state) { - case 0: - state = 1; - p = ip_buf; - dots = 0; - break; - case 1: - /* Begin parse ip */ - if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else if (*pos == '.') { - *p ++ = *pos ++; - dots ++; - } - else if (*pos == '/') { - pos ++; - p = mask_buf; - state = 2; - } - else { - /* Invalid character */ - return FALSE; - } - break; - case 2: - /* Parse mask */ - if (p - mask_buf > 2) { - return FALSE; - } - if (g_ascii_isdigit (*pos)) { - *p ++ = *pos ++; - } - else { - return FALSE; - } - break; + case 0: + state = 1; + p = ip_buf; + dots = 0; + break; + case 1: + /* Begin parse ip */ + if (p - ip_buf >= (gint)sizeof (ip_buf) || dots > 3) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else if (*pos == '.') { + *p++ = *pos++; + dots++; + } + else if (*pos == '/') { + pos++; + p = mask_buf; + state = 2; + } + else { + /* Invalid character */ + return FALSE; + } + break; + case 2: + /* Parse mask */ + if (p - mask_buf > 2) { + return FALSE; + } + if (g_ascii_isdigit (*pos)) { + *p++ = *pos++; + } + else { + return FALSE; + } + break; } } @@ -303,11 +326,14 @@ parse_regexp_ipmask (const gchar *begin, struct dynamic_map_item *addr) } /* Process regexp expression */ -static gboolean -read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chain, - const gchar *symbol, const gchar *line, gboolean raw_mode) +static gboolean +read_regexp_expression (rspamd_mempool_t * pool, + struct regexp_module_item *chain, + const gchar *symbol, + const gchar *line, + gboolean raw_mode) { - struct expression *e, *cur; + struct expression *e, *cur; e = parse_expression (pool, (gchar *)line); if (e == NULL) { @@ -318,9 +344,13 @@ read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chai cur = e; while (cur) { if (cur->type == EXPR_REGEXP) { - cur->content.operand = parse_regexp (pool, cur->content.operand, raw_mode); + cur->content.operand = parse_regexp (pool, + cur->content.operand, + raw_mode); if (cur->content.operand == NULL) { - msg_warn ("cannot parse regexp, skip expression %s = \"%s\"", symbol, line); + msg_warn ("cannot parse regexp, skip expression %s = \"%s\"", + symbol, + line); return FALSE; } cur->type = EXPR_REGEXP_PARSED; @@ -333,11 +363,14 @@ read_regexp_expression (rspamd_mempool_t * pool, struct regexp_module_item *chai /* Callbacks for reading json dynamic rules */ -gchar * -json_regexp_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +gchar * +json_regexp_read_cb (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { - struct regexp_json_buf *jb; - gint free, off; + struct regexp_json_buf *jb; + gint free, off; if (data->cur_data == NULL) { jb = g_malloc (sizeof (struct regexp_json_buf)); @@ -376,16 +409,16 @@ json_regexp_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, struct ma void json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { - struct regexp_json_buf *jb; - guint nelts, i, j; - json_t *js, *cur_elt, *cur_nm, *it_val; - json_error_t je; - gchar *cur_rule, *cur_symbol; - double score; - struct regexp_module_item *cur_item; - GList *cur_networks = NULL; - struct dynamic_map_item *cur_nitem; - rspamd_mempool_t *new_pool; + struct regexp_json_buf *jb; + guint nelts, i, j; + json_t *js, *cur_elt, *cur_nm, *it_val; + json_error_t je; + gchar *cur_rule, *cur_symbol; + double score; + struct regexp_module_item *cur_item; + GList *cur_networks = NULL; + struct dynamic_map_item *cur_nitem; + rspamd_mempool_t *new_pool; if (data->prev_data) { jb = data->prev_data; @@ -413,7 +446,9 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) js = json_loads (jb->buf, &je); if (!js) { - msg_err ("cannot load json data: parse error %s, on line %d", je.text, je.line); + msg_err ("cannot load json data: parse error %s, on line %d", + je.text, + je.line); return; } @@ -422,9 +457,9 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) msg_err ("loaded json is not an array"); return; } - + new_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); - + remove_dynamic_rules (jb->cfg->cache); if (regexp_module_ctx->dynamic_pool != NULL) { rspamd_mempool_delete (regexp_module_ctx->dynamic_pool); @@ -447,14 +482,15 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) msg_err ("factor is not a number or not exists, but is required"); continue; } - score = json_number_value (cur_nm); + score = json_number_value (cur_nm); /* Symbol param */ cur_nm = json_object_get (cur_elt, "symbol"); if (cur_nm == NULL || !json_is_string (cur_nm)) { msg_err ("symbol is not a string or not exists, but is required"); continue; } - cur_symbol = rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); + cur_symbol = + rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); /* Enabled flag */ cur_nm = json_object_get (cur_elt, "enabled"); if (cur_nm != NULL && json_is_boolean (cur_nm)) { @@ -467,7 +503,8 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) /* Rule */ cur_nm = json_object_get (cur_elt, "rule"); if (cur_nm != NULL && json_is_string (cur_nm)) { - cur_rule = rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); + cur_rule = + rspamd_mempool_strdup (new_pool, json_string_value (cur_nm)); } /* Networks array */ cur_nm = json_object_get (cur_elt, "networks"); @@ -475,8 +512,11 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) for (j = 0; j < json_array_size (cur_nm); j++) { it_val = json_array_get (cur_nm, i); if (it_val && json_is_string (it_val)) { - cur_nitem = rspamd_mempool_alloc (new_pool, sizeof (struct dynamic_map_item)); - if (parse_regexp_ipmask (json_string_value (it_val), cur_nitem)) { + cur_nitem = + rspamd_mempool_alloc (new_pool, + sizeof (struct dynamic_map_item)); + if (parse_regexp_ipmask (json_string_value (it_val), + cur_nitem)) { cur_networks = g_list_prepend (cur_networks, cur_nitem); } } @@ -484,10 +524,19 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } if (cur_rule) { /* Dynamic rule has rule option */ - cur_item = rspamd_mempool_alloc0 (new_pool, sizeof (struct regexp_module_item)); + cur_item = + rspamd_mempool_alloc0 (new_pool, + sizeof (struct regexp_module_item)); cur_item->symbol = cur_symbol; - if (read_regexp_expression (new_pool, cur_item, cur_symbol, cur_rule, jb->cfg->raw_mode)) { - register_dynamic_symbol (new_pool, &jb->cfg->cache, cur_symbol, score, process_regexp_item, cur_item, cur_networks); + if (read_regexp_expression (new_pool, cur_item, cur_symbol, + cur_rule, jb->cfg->raw_mode)) { + register_dynamic_symbol (new_pool, + &jb->cfg->cache, + cur_symbol, + score, + process_regexp_item, + cur_item, + cur_networks); } else { msg_warn ("cannot parse dynamic rule"); @@ -495,7 +544,13 @@ json_regexp_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) } else { /* Just rule that is allways true (for whitelisting for example) */ - register_dynamic_symbol (new_pool, &jb->cfg->cache, cur_symbol, score, regexp_dynamic_insert_result, cur_symbol, cur_networks); + register_dynamic_symbol (new_pool, + &jb->cfg->cache, + cur_symbol, + score, + regexp_dynamic_insert_result, + cur_symbol, + cur_networks); } if (cur_networks) { g_list_free (cur_networks); @@ -510,22 +565,44 @@ regexp_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { regexp_module_ctx = g_malloc (sizeof (struct regexp_ctx)); - regexp_module_ctx->regexp_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + regexp_module_ctx->regexp_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); regexp_module_ctx->dynamic_pool = NULL; - regexp_module_ctx->autolearn_symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); + regexp_module_ctx->autolearn_symbols = g_hash_table_new (rspamd_str_hash, + rspamd_str_equal); regexp_module_ctx->workers = NULL; *ctx = (struct module_ctx *)regexp_module_ctx; - register_expression_function ("regexp_match_number", rspamd_regexp_match_number, NULL); - register_expression_function ("regexp_occurs_number", rspamd_regexp_occurs_number, NULL); - register_expression_function ("raw_header_exists", rspamd_raw_header_exists, NULL); - register_expression_function ("check_smtp_data", rspamd_check_smtp_data, NULL); - register_expression_function ("content_type_is_type", rspamd_content_type_is_type, NULL); - register_expression_function ("content_type_is_subtype", rspamd_content_type_is_subtype, NULL); - register_expression_function ("content_type_has_param", rspamd_content_type_has_param, NULL); - register_expression_function ("content_type_compare_param", rspamd_content_type_compare_param, NULL); - register_expression_function ("has_content_part", rspamd_has_content_part, NULL); - register_expression_function ("has_content_part_len", rspamd_has_content_part_len, NULL); + register_expression_function ("regexp_match_number", + rspamd_regexp_match_number, + NULL); + register_expression_function ("regexp_occurs_number", + rspamd_regexp_occurs_number, + NULL); + register_expression_function ("raw_header_exists", + rspamd_raw_header_exists, + NULL); + register_expression_function ("check_smtp_data", + rspamd_check_smtp_data, + NULL); + register_expression_function ("content_type_is_type", + rspamd_content_type_is_type, + NULL); + register_expression_function ("content_type_is_subtype", + rspamd_content_type_is_subtype, + NULL); + register_expression_function ("content_type_has_param", + rspamd_content_type_has_param, + NULL); + register_expression_function ("content_type_compare_param", + rspamd_content_type_compare_param, + NULL); + register_expression_function ("has_content_part", + rspamd_has_content_part, + NULL); + register_expression_function ("has_content_part_len", + rspamd_has_content_part_len, + NULL); (void)luaopen_regexp (cfg->lua_state); @@ -533,18 +610,22 @@ regexp_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) } -/* +/* * Parse string in format: * SYMBOL:statfile:weight */ void -parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_config *cfg) +parse_autolearn_param (const gchar *param, + const gchar *value, + struct rspamd_config *cfg) { - struct autolearn_data *d; - gchar *p; + struct autolearn_data *d; + gchar *p; p = rspamd_mempool_strdup (regexp_module_ctx->regexp_pool, value); - d = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, sizeof (struct autolearn_data)); + d = + rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, + sizeof (struct autolearn_data)); d->symbol = strsep (&p, ":"); if (d->symbol) { @@ -552,7 +633,9 @@ parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_con if (d->statfile_name) { if (p != NULL && *p != '\0') { d->weight = strtod (p, NULL); - g_hash_table_insert (regexp_module_ctx->autolearn_symbols, d->symbol, d); + g_hash_table_insert (regexp_module_ctx->autolearn_symbols, + d->symbol, + d); } } else { @@ -567,11 +650,11 @@ parse_autolearn_param (const gchar *param, const gchar *value, struct rspamd_con gint regexp_module_config (struct rspamd_config *cfg) { - struct regexp_module_item *cur_item; - const ucl_object_t *sec, *value; - ucl_object_iter_t it = NULL; - gint res = TRUE; - struct regexp_json_buf *jb, **pjb; + struct regexp_module_item *cur_item; + const ucl_object_t *sec, *value; + ucl_object_iter_t it = NULL; + gint res = TRUE; + struct regexp_json_buf *jb, **pjb; sec = ucl_object_find_key (cfg->rcl_obj, "regexp"); @@ -585,44 +668,61 @@ regexp_module_config (struct rspamd_config *cfg) regexp_module_ctx->workers = NULL; while ((value = ucl_iterate_object (sec, &it, true)) != NULL) { - if (g_ascii_strncasecmp (ucl_object_key (value), "autolearn", sizeof ("autolearn") - 1) == 0) { - parse_autolearn_param (ucl_object_key (value), ucl_obj_tostring (value), cfg); + if (g_ascii_strncasecmp (ucl_object_key (value), "autolearn", + sizeof ("autolearn") - 1) == 0) { + parse_autolearn_param (ucl_object_key (value), + ucl_obj_tostring (value), cfg); } - else if (g_ascii_strncasecmp (ucl_object_key (value), "dynamic_rules", sizeof ("dynamic_rules") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "dynamic_rules", + sizeof ("dynamic_rules") - 1) == 0) { jb = g_malloc (sizeof (struct regexp_json_buf)); pjb = g_malloc (sizeof (struct regexp_json_buf *)); jb->buf = NULL; jb->cfg = cfg; *pjb = jb; if (!add_map (cfg, ucl_obj_tostring (value), - "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, - (void **)pjb)) { + "Dynamic regexp rules", json_regexp_read_cb, json_regexp_fin_cb, + (void **)pjb)) { msg_err ("cannot add map %s", ucl_obj_tostring (value)); } } - else if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", sizeof ("max_size") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "max_size", + sizeof ("max_size") - 1) == 0) { regexp_module_ctx->max_size = ucl_obj_toint (value); } - else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", sizeof ("max_threads") - 1) == 0) { + else if (g_ascii_strncasecmp (ucl_object_key (value), "max_threads", + sizeof ("max_threads") - 1) == 0) { regexp_module_ctx->max_threads = ucl_obj_toint (value); } else if (value->type == UCL_STRING) { - cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); + 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->raw_mode)) { + if (!read_regexp_expression (regexp_module_ctx->regexp_pool, + cur_item, ucl_object_key (value), + ucl_obj_tostring (value), cfg->raw_mode)) { res = FALSE; } - register_symbol (&cfg->cache, cur_item->symbol, 1, process_regexp_item, cur_item); + register_symbol (&cfg->cache, + cur_item->symbol, + 1, + process_regexp_item, + cur_item); } else if (value->type == UCL_USERDATA) { - cur_item = rspamd_mempool_alloc0 (regexp_module_ctx->regexp_pool, sizeof (struct regexp_module_item)); + 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 = value->value.ud; - register_symbol (&cfg->cache, cur_item->symbol, 1, process_regexp_item, cur_item); + register_symbol (&cfg->cache, + cur_item->symbol, + 1, + process_regexp_item, + cur_item); } else { - msg_warn ("unknown type of attribute %s for regexp module", ucl_object_key (value)); + msg_warn ("unknown type of attribute %s for regexp module", + ucl_object_key (value)); } } @@ -633,63 +733,72 @@ gint regexp_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (regexp_module_ctx->regexp_pool); - regexp_module_ctx->regexp_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + regexp_module_ctx->regexp_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return regexp_module_config (cfg); } struct url_regexp_param { - struct rspamd_task *task; - GRegex *regexp; - struct rspamd_regexp *re; - gboolean found; + struct rspamd_task *task; + GRegex *regexp; + struct rspamd_regexp *re; + gboolean found; }; -static gboolean +static gboolean tree_url_callback (gpointer key, gpointer value, void *data) { - struct url_regexp_param *param = data; - struct uri *url = value; - GError *err = NULL; + struct url_regexp_param *param = data; + struct uri *url = value; + GError *err = NULL; - if (g_regex_match_full (param->regexp, struri (url), -1, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (param->regexp, struri (url), -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (param->re->is_test)) { - msg_info ("process test regexp %s for url %s returned TRUE", struri (url)); + msg_info ("process test regexp %s for url %s returned TRUE", + struri (url)); } task_cache_add (param->task, param->re, 1); param->found = TRUE; return TRUE; } else if (G_UNLIKELY (param->re->is_test)) { - msg_info ("process test regexp %s for url %s returned FALSE", struri (url)); + msg_info ("process test regexp %s for url %s returned FALSE", + struri (url)); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", param->re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + param->re->regexp_text, + err->message); } return FALSE; } -static gsize -process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar *additional, - gint limit, int_compare_func f) +static gsize +process_regexp (struct rspamd_regexp *re, + struct rspamd_task *task, + const gchar *additional, + gint limit, + int_compare_func f) { - guint8 *ct; - gsize clen; - gint r, passed = 0, start, end, old; - gboolean matched = FALSE; - - GList *cur, *headerlist; - GRegex *regexp; - GMatchInfo *info; - GError *err = NULL; - struct url_regexp_param callback_param = { + guint8 *ct; + gsize clen; + gint r, passed = 0, start, end, old; + gboolean matched = FALSE; + + GList *cur, *headerlist; + GRegex *regexp; + GMatchInfo *info; + GError *err = NULL; + struct url_regexp_param callback_param = { .task = task, .re = re, .found = FALSE }; - struct mime_text_part *part; - struct raw_header *rh; + struct mime_text_part *part; + struct raw_header *rh; if (re == NULL) { msg_info ("invalid regexp passed"); @@ -698,16 +807,21 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar callback_param.regexp = re->regexp; if ((r = task_cache_check (task, re)) != -1) { - debug_task ("regexp /%s/ is found in cache, result: %d", re->regexp_text, r); + debug_task ("regexp /%s/ is found in cache, result: %d", + re->regexp_text, + r); return r == 1; } - + if (additional != NULL) { /* We have additional parameter defined, so ignore type of regexp expression and use it for parsing */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s with test %s", re->regexp_text, additional); + msg_info ("process test regexp %s with test %s", + re->regexp_text, + additional); } - if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, 0, NULL, NULL) == TRUE) { + if (g_regex_match_full (re->regexp, additional, strlen (additional), 0, + 0, NULL, NULL) == TRUE) { if (G_UNLIKELY (re->is_test)) { msg_info ("result of regexp %s is true", re->regexp_text); } @@ -722,39 +836,53 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar switch (re->type) { case REGEXP_NONE: - msg_warn ("bad error detected: %s has invalid regexp type", re->regexp_text); + msg_warn ("bad error detected: %s has invalid regexp type", + re->regexp_text); return 0; case REGEXP_HEADER: /* Check header's name */ if (re->header == NULL) { - msg_info ("header regexp without header name: '%s'", re->regexp_text); + msg_info ("header regexp without header name: '%s'", + re->regexp_text); task_cache_add (task, re, 0); return 0; } - debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); + debug_task ("checking header regexp: %s = %s", + re->header, + re->regexp_text); /* Get list of specified headers */ - headerlist = message_get_header (task->task_pool, task->message, re->header, re->is_strong); + headerlist = message_get_header (task->task_pool, + task->message, + re->header, + re->is_strong); if (headerlist == NULL) { /* Header is not found */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); + msg_info ( + "process test regexp %s for header %s returned FALSE: no header found", + re->regexp_text, + re->header); } task_cache_add (task, re, 0); return 0; } else { - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_list_free, headerlist); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_list_free, headerlist); /* Check whether we have regexp for it */ if (re->regexp == NULL) { - debug_task ("regexp contains only header and it is found %s", re->header); + debug_task ("regexp contains only header and it is found %s", + re->header); task_cache_add (task, re, 1); return 1; } /* Iterate throught headers */ cur = headerlist; while (cur) { - debug_task ("found header \"%s\" with value \"%s\"", re->header, (const gchar *)cur->data); + debug_task ("found header \"%s\" with value \"%s\"", + re->header, + (const gchar *)cur->data); /* Try to match regexp */ if (!re->is_raw) { /* Validate input */ @@ -763,9 +891,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } } - if (cur->data && g_regex_match_full (re->regexp, cur->data, -1, 0, 0, NULL, &err) == TRUE) { + if (cur->data && + g_regex_match_full (re->regexp, cur->data, -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned TRUE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned TRUE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (f != NULL && limit > 1) { /* If we have limit count, increase passed count and compare with limit */ @@ -780,10 +914,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } } else if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned FALSE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned FALSE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ( + "error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -803,8 +944,11 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } /* Skip too large parts */ - if (regexp_module_ctx->max_size != 0 && part->content->len > regexp_module_ctx->max_size) { - msg_info ("<%s> skip part of size %Hud", task->message_id, part->content->len); + if (regexp_module_ctx->max_size != 0 && part->content->len > + regexp_module_ctx->max_size) { + msg_info ("<%s> skip part of size %Hud", + task->message_id, + part->content->len); cur = g_list_next (cur); continue; } @@ -828,12 +972,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar /* If we have limit, apply regexp so much times as we can */ if (f != NULL && limit > 1) { end = 0; - while ((matched = g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, &info, &err)) == TRUE) { + while ((matched = + g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, + 0, &info, &err)) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", - re->regexp_text, - (gint)clen, - end); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen, + end); } if (f (++passed, limit)) { task_cache_add (task, re, 1); @@ -842,7 +989,8 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Match not found, skip further cycles */ old = end; - if (!g_match_info_fetch_pos (info, 0, &start, &end) || end <= 0) { + if (!g_match_info_fetch_pos (info, 0, &start, + &end) || end <= 0) { break; } end += old; @@ -852,10 +1000,13 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar g_match_info_free (info); } else { - if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } task_cache_add (task, re, 1); return 1; @@ -863,11 +1014,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } if (!matched && G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned FALSE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned FALSE", + re->regexp_text, + (gint)clen); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -879,17 +1034,22 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar ct = task->msg->str; clen = task->msg->len; - if (regexp_module_ctx->max_size != 0 && clen > regexp_module_ctx->max_size) { + if (regexp_module_ctx->max_size != 0 && clen > + regexp_module_ctx->max_size) { msg_info ("<%s> skip message of size %Hz", task->message_id, clen); return 0; } /* If we have limit, apply regexp so much times as we can */ if (f != NULL && limit > 1) { end = 0; - while ((matched = g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, &info, &err)) == TRUE) { + while ((matched = + g_regex_match_full (regexp, ct + end + 1, clen - end - 1, 0, 0, + &info, &err)) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for mime part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for mime part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } if (f (++passed, limit)) { task_cache_add (task, re, 1); @@ -898,7 +1058,8 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Match not found, skip further cycles */ old = end; - if (!g_match_info_fetch_pos (info, 0, &start, &end) || end <= 0) { + if (!g_match_info_fetch_pos (info, 0, &start, + &end) || end <= 0) { break; } old += end; @@ -908,10 +1069,13 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar g_match_info_free (info); } else { - if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, &err) == TRUE) { + if (g_regex_match_full (regexp, ct, clen, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for message part of length %d returned TRUE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for message part of length %d returned TRUE", + re->regexp_text, + (gint)clen); } task_cache_add (task, re, 1); return 1; @@ -919,11 +1083,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } if (!matched && G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for message part of length %d returned FALSE", re->regexp_text, - (gint)clen); + msg_info ( + "process test regexp %s for message part of length %d returned FALSE", + re->regexp_text, + (gint)clen); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ("error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } task_cache_add (task, re, 0); return 0; @@ -949,21 +1117,29 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } return 0; case REGEXP_RAW_HEADER: - debug_task ("checking for raw header: %s with regexp: %s", re->header, re->regexp_text); + debug_task ("checking for raw header: %s with regexp: %s", + re->header, + re->regexp_text); /* Check header's name */ if (re->header == NULL) { - msg_info ("header regexp without header name: '%s'", re->regexp_text); + msg_info ("header regexp without header name: '%s'", + re->regexp_text); task_cache_add (task, re, 0); return 0; } - debug_task ("checking header regexp: %s = %s", re->header, re->regexp_text); + debug_task ("checking header regexp: %s = %s", + re->header, + re->regexp_text); /* Get list of specified headers */ headerlist = message_get_raw_header (task, re->header, re->is_strong); if (headerlist == NULL) { /* Header is not found */ if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s returned FALSE: no header found", re->regexp_text, re->header); + msg_info ( + "process test regexp %s for header %s returned FALSE: no header found", + re->regexp_text, + re->header); } task_cache_add (task, re, 0); return 0; @@ -971,14 +1147,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar else { /* Check whether we have regexp for it */ if (re->regexp == NULL) { - debug_task ("regexp contains only header and it is found %s", re->header); + debug_task ("regexp contains only header and it is found %s", + re->header); task_cache_add (task, re, 1); return 1; } /* Iterate throught headers */ cur = headerlist; while (cur) { - debug_task ("found header \"%s\" with value \"%s\"", re->header, (const gchar *)cur->data); + debug_task ("found header \"%s\" with value \"%s\"", + re->header, + (const gchar *)cur->data); rh = cur->data; /* Try to match regexp */ if (!re->is_raw) { @@ -988,9 +1167,15 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar continue; } } - if (rh->value && g_regex_match_full (re->regexp, rh->value, -1, 0, 0, NULL, &err) == TRUE) { + if (rh->value && + g_regex_match_full (re->regexp, rh->value, -1, 0, 0, NULL, + &err) == TRUE) { if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned TRUE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned TRUE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (f != NULL && limit > 1) { /* If we have limit count, increase passed count and compare with limit */ @@ -1005,10 +1190,17 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } } else if (G_UNLIKELY (re->is_test)) { - msg_info ("process test regexp %s for header %s with value '%s' returned FALSE", re->regexp_text, re->header, (const gchar *)cur->data); + msg_info ( + "process test regexp %s for header %s with value '%s' returned FALSE", + re->regexp_text, + re->header, + (const gchar *)cur->data); } if (err != NULL) { - msg_info ("error occured while processing regexp \"%s\": %s", re->regexp_text, err->message); + msg_info ( + "error occured while processing regexp \"%s\": %s", + re->regexp_text, + err->message); } cur = g_list_next (cur); } @@ -1025,10 +1217,12 @@ process_regexp (struct rspamd_regexp *re, struct rspamd_task *task, const gchar } static gboolean -maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State *L) +maybe_call_lua_function (const gchar *name, + struct rspamd_task *task, + lua_State *L) { - struct rspamd_task **ptask; - gboolean res; + struct rspamd_task **ptask; + gboolean res; lua_getglobal (L, name); if (lua_isfunction (L, -1)) { @@ -1037,7 +1231,8 @@ maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State *ptask = task; /* Call function */ if (lua_pcall (L, 1, 1, 0) != 0) { - msg_info ("call to %s failed: %s", (gchar *)name, lua_tostring (L, -1)); + msg_info ("call to %s failed: %s", (gchar *)name, + lua_tostring (L, -1)); return FALSE; } res = lua_toboolean (L, -1); @@ -1050,12 +1245,12 @@ maybe_call_lua_function (const gchar *name, struct rspamd_task *task, lua_State return FALSE; } -static gboolean +static gboolean optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res) { - struct expression *it = (*e)->next; - gboolean ret = FALSE, is_nearest = TRUE; - gint skip_level = 0; + struct expression *it = (*e)->next; + gboolean ret = FALSE, is_nearest = TRUE; + gint skip_level = 0; /* Skip nearest logical operators from optimization */ if (!it || (it->type == EXPR_OPERATION && it->content.operation != '!')) { @@ -1106,22 +1301,29 @@ optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res) return ret; } -static gboolean -process_regexp_expression (struct expression *expr, const gchar *symbol, struct rspamd_task *task, - const gchar *additional, struct lua_locked_state *nL) +static gboolean +process_regexp_expression (struct expression *expr, + const gchar *symbol, + struct rspamd_task *task, + const gchar *additional, + struct lua_locked_state *nL) { - GQueue *stack; - gsize cur, op1, op2; - struct expression *it = expr; - struct rspamd_regexp *re; - gboolean try_optimize = TRUE; + GQueue *stack; + gsize cur, op1, op2; + struct expression *it = expr; + struct rspamd_regexp *re; + gboolean try_optimize = TRUE; stack = g_queue_new (); while (it) { if (it->type == EXPR_REGEXP_PARSED) { /* Find corresponding symbol */ - cur = process_regexp ((struct rspamd_regexp *)it->content.operand, task, additional, 0, NULL); + cur = process_regexp ((struct rspamd_regexp *)it->content.operand, + task, + additional, + 0, + NULL); debug_task ("regexp %s found", cur ? "is" : "is not"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); @@ -1133,13 +1335,21 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct else if (it->type == EXPR_FUNCTION) { if (nL) { rspamd_mutex_lock (nL->m); - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, nL->L); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, nL->L); rspamd_mutex_unlock (nL->m); } else { - cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task, task->cfg->lua_state); - } - debug_task ("function %s returned %s", ((struct expression_function *)it->content.operand)->name, cur ? "true" : "false"); + cur = + (gsize) call_expression_function ((struct + expression_function + *)it->content.operand, task, task->cfg->lua_state); + } + debug_task ("function %s returned %s", + ((struct expression_function *)it->content.operand)->name, + cur ? "true" : "false"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); } @@ -1151,13 +1361,21 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct /* This may be lua function, try to call it */ if (nL) { rspamd_mutex_lock (nL->m); - cur = maybe_call_lua_function ((const gchar*)it->content.operand, task, nL->L); + cur = maybe_call_lua_function ( + (const gchar *)it->content.operand, + task, + nL->L); rspamd_mutex_unlock (nL->m); } else { - cur = maybe_call_lua_function ((const gchar*)it->content.operand, task, task->cfg->lua_state); - } - debug_task ("function %s returned %s", (const gchar *)it->content.operand, cur ? "true" : "false"); + cur = maybe_call_lua_function ( + (const gchar *)it->content.operand, + task, + task->cfg->lua_state); + } + debug_task ("function %s returned %s", + (const gchar *)it->content.operand, + cur ? "true" : "false"); if (try_optimize) { try_optimize = optimize_regexp_expression (&it, stack, cur); } @@ -1171,7 +1389,9 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct it = it->next; continue; } - re = parse_regexp (task->cfg->cfg_pool, it->content.operand, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + it->content.operand, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot parse regexp, skip expression"); g_queue_free (stack); @@ -1185,7 +1405,8 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct else if (it->type == EXPR_OPERATION) { if (g_queue_is_empty (stack)) { /* Queue has no operands for operation, exiting */ - msg_warn ("regexp expression seems to be invalid: empty stack while reading operation"); + msg_warn ( + "regexp expression seems to be invalid: empty stack while reading operation"); g_queue_free (stack); return FALSE; } @@ -1199,12 +1420,16 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct case '&': op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); - try_optimize = optimize_regexp_expression (&it, stack, op1 && op2); + try_optimize = optimize_regexp_expression (&it, + stack, + op1 && op2); break; case '|': op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack)); - try_optimize = optimize_regexp_expression (&it, stack, op1 || op2); + try_optimize = optimize_regexp_expression (&it, + stack, + op1 || op2); break; default: it = it->next; @@ -1223,7 +1448,9 @@ process_regexp_expression (struct expression *expr, const gchar *symbol, struct } } else { - msg_warn ("regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", symbol); + msg_warn ( + "regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", + symbol); } g_queue_free (stack); @@ -1239,11 +1466,12 @@ struct regexp_threaded_ud { static void process_regexp_item_threaded (gpointer data, gpointer user_data) { - struct regexp_threaded_ud *ud = data; - struct lua_locked_state *nL = user_data; + struct regexp_threaded_ud *ud = data; + struct lua_locked_state *nL = user_data; /* Process expression */ - if (process_regexp_expression (ud->item->expr, ud->item->symbol, ud->task, NULL, nL)) { + if (process_regexp_expression (ud->item->expr, ud->item->symbol, ud->task, + NULL, nL)) { g_mutex_lock (workers_mtx); insert_result (ud->task, ud->item->symbol, 1, NULL); g_mutex_unlock (workers_mtx); @@ -1254,18 +1482,18 @@ process_regexp_item_threaded (gpointer data, gpointer user_data) static void process_regexp_item (struct rspamd_task *task, void *user_data) { - struct regexp_module_item *item = user_data; - gboolean res = FALSE; - struct regexp_threaded_ud *thr_ud; - GError *err = NULL; - struct lua_locked_state *nL; + struct regexp_module_item *item = user_data; + gboolean res = FALSE; + struct regexp_threaded_ud *thr_ud; + GError *err = NULL; + struct lua_locked_state *nL; if (!item->lua_function && regexp_module_ctx->max_threads > 1) { if (regexp_module_ctx->workers == NULL) { #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) # if GLIB_MINOR_VERSION > 20 - if (! g_thread_get_initialized ()) { + if (!g_thread_get_initialized ()) { g_thread_init (NULL); } # else @@ -1273,20 +1501,27 @@ process_regexp_item (struct rspamd_task *task, void *user_data) # endif workers_mtx = g_mutex_new (); #else - workers_mtx = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, sizeof (GMutex)); + workers_mtx = rspamd_mempool_alloc (regexp_module_ctx->regexp_pool, + sizeof (GMutex)); g_mutex_init (workers_mtx); #endif nL = init_lua_locked (task->cfg); luaopen_regexp (nL->L); - regexp_module_ctx->workers = g_thread_pool_new (process_regexp_item_threaded, - nL, regexp_module_ctx->max_threads, TRUE, &err); + regexp_module_ctx->workers = g_thread_pool_new ( + process_regexp_item_threaded, + nL, + regexp_module_ctx->max_threads, + TRUE, + &err); if (err != NULL) { msg_err ("thread pool creation failed: %s", err->message); regexp_module_ctx->max_threads = 0; return; } } - thr_ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct regexp_threaded_ud)); + thr_ud = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct regexp_threaded_ud)); thr_ud->item = item; thr_ud->task = task; @@ -1294,7 +1529,8 @@ process_regexp_item (struct rspamd_task *task, void *user_data) register_async_thread (task->s); g_thread_pool_push (regexp_module_ctx->workers, thr_ud, &err); if (err != NULL) { - msg_err ("error pushing task to the regexp thread pool: %s", err->message); + msg_err ("error pushing task to the regexp thread pool: %s", + err->message); remove_async_thread (task->s); } } @@ -1302,25 +1538,28 @@ process_regexp_item (struct rspamd_task *task, void *user_data) /* Non-threaded version */ if (item->lua_function) { /* Just call function */ - if (lua_call_expression_func (item->lua_function, task, NULL, &res) && res) { + if (lua_call_expression_func (item->lua_function, task, NULL, + &res) && res) { insert_result (task, item->symbol, 1, NULL); } } else { /* Process expression */ - if (process_regexp_expression (item->expr, item->symbol, task, NULL, NULL)) { + if (process_regexp_expression (item->expr, item->symbol, task, NULL, + NULL)) { insert_result (task, item->symbol, 1, NULL); } } } } -static gboolean -rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused) +static gboolean +rspamd_regexp_match_number (struct rspamd_task *task, GList * args, + void *unused) { - gint param_count, res = 0; - struct expression_argument *arg; - GList *cur; + gint param_count, res = 0; + struct expression_argument *arg; + GList *cur; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1339,7 +1578,8 @@ rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused } } else { - if (process_regexp_expression (cur->data, "regexp_match_number", task, NULL, NULL)) { + if (process_regexp_expression (cur->data, "regexp_match_number", + task, NULL, NULL)) { res++; } if (res >= param_count) { @@ -1352,14 +1592,16 @@ rspamd_regexp_match_number (struct rspamd_task *task, GList * args, void *unused return res >= param_count; } -static gboolean -rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unused) +static gboolean +rspamd_regexp_occurs_number (struct rspamd_task *task, + GList * args, + void *unused) { - gint limit; - struct expression_argument *arg; - struct rspamd_regexp *re; - gchar *param, *err_str, op; - int_compare_func f = NULL; + gint limit; + struct expression_argument *arg; + struct rspamd_regexp *re; + gchar *param, *err_str, op; + int_compare_func f = NULL; if (args == NULL || args->next == NULL) { msg_warn ("wrong number of parameters to function, must be 2"); @@ -1382,13 +1624,13 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse op = '='; } else { - param ++; + param++; } switch (op) { case '>': if (*param == '=') { f = op_more_equal; - param ++; + param++; } else { f = op_more; @@ -1397,7 +1639,7 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse case '<': if (*param == '=') { f = op_less_equal; - param ++; + param++; } else { f = op_less; @@ -1407,7 +1649,9 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse f = op_equal; break; default: - msg_err ("wrong operation character: %c, assumed '=', '>', '<', '>=', '<=' or empty op", op); + msg_err ( + "wrong operation character: %c, assumed '=', '>', '<', '>=', '<=' or empty op", + op); return FALSE; } @@ -1419,10 +1663,10 @@ rspamd_regexp_occurs_number (struct rspamd_task *task, GList * args, void *unuse return process_regexp (re, task, NULL, limit, f); } -static gboolean +static gboolean rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; + struct expression_argument *arg; if (args == NULL || task == NULL) { return FALSE; @@ -1438,15 +1682,19 @@ rspamd_raw_header_exists (struct rspamd_task *task, GList * args, void *unused) } static gboolean -match_smtp_data (struct rspamd_task *task, const gchar *re_text, const gchar *what) +match_smtp_data (struct rspamd_task *task, + const gchar *re_text, + const gchar *what) { - struct rspamd_regexp *re; - gint r; + struct rspamd_regexp *re; + gint r; if (*re_text == '/') { /* This is a regexp */ if ((re = re_cache_check (re_text, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, (gchar *)re_text, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + (gchar *)re_text, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1471,12 +1719,12 @@ match_smtp_data (struct rspamd_task *task, const gchar *re_text, const gchar *wh return FALSE; } -static gboolean +static gboolean rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) { - struct expression_argument *arg; - GList *cur, *rcpt_list = NULL; - gchar *type, *what = NULL; + struct expression_argument *arg; + GList *cur, *rcpt_list = NULL; + gchar *type, *what = NULL; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1492,59 +1740,59 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) else { type = arg->data; switch (*type) { - case 'f': - case 'F': - if (g_ascii_strcasecmp (type, "from") == 0) { - what = task->from; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'h': - case 'H': - if (g_ascii_strcasecmp (type, "helo") == 0) { - what = task->helo; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'u': - case 'U': - if (g_ascii_strcasecmp (type, "user") == 0) { - what = task->user; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 's': - case 'S': - if (g_ascii_strcasecmp (type, "subject") == 0) { - what = task->subject; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - case 'r': - case 'R': - if (g_ascii_strcasecmp (type, "rcpt") == 0) { - rcpt_list = task->rcpt; - } - else { - msg_warn ("bad argument to function: %s", type); - return FALSE; - } - break; - default: + case 'f': + case 'F': + if (g_ascii_strcasecmp (type, "from") == 0) { + what = task->from; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'h': + case 'H': + if (g_ascii_strcasecmp (type, "helo") == 0) { + what = task->helo; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'u': + case 'U': + if (g_ascii_strcasecmp (type, "user") == 0) { + what = task->user; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 's': + case 'S': + if (g_ascii_strcasecmp (type, "subject") == 0) { + what = task->subject; + } + else { + msg_warn ("bad argument to function: %s", type); + return FALSE; + } + break; + case 'r': + case 'R': + if (g_ascii_strcasecmp (type, "rcpt") == 0) { + rcpt_list = task->rcpt; + } + else { msg_warn ("bad argument to function: %s", type); return FALSE; + } + break; + default: + msg_warn ("bad argument to function: %s", type); + return FALSE; } } @@ -1552,7 +1800,7 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) /* Not enough data so regexp would NOT be found anyway */ return FALSE; } - + /* We would process only one more argument, others are ignored */ cur = args->next; if (cur) { @@ -1572,13 +1820,16 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) } else if (arg != NULL) { if (what != NULL) { - if (process_regexp_expression (arg->data, "regexp_check_smtp_data", task, what, NULL)) { + if (process_regexp_expression (arg->data, + "regexp_check_smtp_data", task, what, NULL)) { return TRUE; } } else { while (rcpt_list) { - if (process_regexp_expression (arg->data, "regexp_check_smtp_data", task, rcpt_list->data, NULL)) { + if (process_regexp_expression (arg->data, + "regexp_check_smtp_data", task, rcpt_list->data, + NULL)) { return TRUE; } rcpt_list = g_list_next (rcpt_list); @@ -1594,11 +1845,11 @@ rspamd_check_smtp_data (struct rspamd_task *task, GList * args, void *unused) static gint lua_regexp_match (lua_State *L) { - void *ud = luaL_checkudata (L, 1, "rspamd{task}"); - struct rspamd_task *task; - const gchar *re_text; - struct rspamd_regexp *re; - gint r = 0; + void *ud = luaL_checkudata (L, 1, "rspamd{task}"); + struct rspamd_task *task; + const gchar *re_text; + struct rspamd_regexp *re; + gint r = 0; luaL_argcheck (L, ud != NULL, 1, "'task' expected"); task = ud ? *((struct rspamd_task **)ud) : NULL; @@ -1607,7 +1858,9 @@ lua_regexp_match (lua_State *L) /* This is a regexp */ if (task != NULL) { if ((re = re_cache_check (re_text, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, (gchar *)re_text, task->cfg->raw_mode); + re = parse_regexp (task->cfg->cfg_pool, + (gchar *)re_text, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1622,18 +1875,20 @@ lua_regexp_match (lua_State *L) } static gboolean -rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_compare_param (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_name, *param_pattern; - const gchar *param_data; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_name, *param_pattern; + const gchar *param_data; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1656,7 +1911,8 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1677,15 +1933,21 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) == NULL) { + for (;; ) { + if ((param_data = + g_mime_content_type_get_parameter ((GMimeContentType *)ct, + param_name)) == NULL) { result = FALSE; } else { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1693,7 +1955,8 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void re_cache_add (param_pattern, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, param_data, 0, NULL) == TRUE) { + if (g_regex_match (re->regexp, param_data, 0, + NULL) == TRUE) { task_cache_add (task, re, 1); return TRUE; } @@ -1711,7 +1974,7 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1733,16 +1996,18 @@ rspamd_content_type_compare_param (struct rspamd_task * task, GList * args, void } static gboolean -rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_has_param (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_name; - const gchar *param_data; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_name; + const gchar *param_data; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1757,7 +2022,8 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1778,12 +2044,14 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { - if ((param_data = g_mime_content_type_get_parameter ((GMimeContentType *)ct, param_name)) != NULL) { + for (;; ) { + if ((param_data = + g_mime_content_type_get_parameter ((GMimeContentType *)ct, + param_name)) != NULL) { return TRUE; } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1805,17 +2073,19 @@ rspamd_content_type_has_param (struct rspamd_task * task, GList * args, void *un } static gboolean -rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *unused) +rspamd_content_type_is_subtype (struct rspamd_task *task, + GList * args, + void *unused) { - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1830,7 +2100,8 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1851,11 +2122,15 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { + for (;; ) { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1863,7 +2138,8 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un re_cache_add (param_pattern, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (g_regex_match (re->regexp, ct->subtype, 0, NULL) == TRUE) { + if (g_regex_match (re->regexp, ct->subtype, 0, + NULL) == TRUE) { task_cache_add (task, re, 1); return TRUE; } @@ -1880,7 +2156,7 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1902,17 +2178,19 @@ rspamd_content_type_is_subtype (struct rspamd_task *task, GList * args, void *un } static gboolean -rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unused) +rspamd_content_type_is_type (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_pattern; - struct rspamd_regexp *re; - struct expression_argument *arg, *arg1; - GMimeObject *part; - GMimeContentType *ct; - gint r; - gboolean recursive = FALSE, result = FALSE; - GList *cur = NULL; - struct mime_part *cur_part; + gchar *param_pattern; + struct rspamd_regexp *re; + struct expression_argument *arg, *arg1; + GMimeObject *part; + GMimeContentType *ct; + gint r; + gboolean recursive = FALSE, result = FALSE; + GList *cur = NULL; + struct mime_part *cur_part; if (args == NULL) { msg_warn ("no parameters to function"); @@ -1928,7 +2206,8 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus if (args->next) { args = g_list_next (args); arg1 = get_function_arg (args->data, task, TRUE); - if (g_ascii_strncasecmp (arg1->data, "true", sizeof ("true") - 1) == 0) { + if (g_ascii_strncasecmp (arg1->data, "true", + sizeof ("true") - 1) == 0) { recursive = TRUE; } } @@ -1949,11 +2228,15 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus #ifndef GMIME24 g_object_unref (part); #endif - for (;;) { + for (;; ) { if (*param_pattern == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_pattern, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_pattern, task->cfg->raw_mode); + if ((re = + re_cache_check (param_pattern, + task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_pattern, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -1978,7 +2261,7 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus } } /* Get next part */ - if (! recursive) { + if (!recursive) { return result; } else if (cur != NULL) { @@ -1999,11 +2282,12 @@ rspamd_content_type_is_type (struct rspamd_task * task, GList * args, void *unus return FALSE; } -static gboolean -compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype) +static gboolean +compare_subtype (struct rspamd_task *task, GMimeContentType * ct, + gchar *subtype) { - struct rspamd_regexp *re; - gint r; + struct rspamd_regexp *re; + gint r; if (subtype == NULL || ct == NULL) { msg_warn ("invalid parameters passed"); @@ -2012,7 +2296,9 @@ compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype if (*subtype == '/') { /* This is regexp, so compile and create g_regexp object */ if ((re = re_cache_check (subtype, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, subtype, task->cfg->raw_mode); + re = + parse_regexp (task->cfg->cfg_pool, subtype, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); return FALSE; @@ -2040,7 +2326,7 @@ compare_subtype (struct rspamd_task *task, GMimeContentType * ct, gchar *subtype return FALSE; } -static gboolean +static gboolean compare_len (struct mime_part *part, guint min, guint max) { if (min == 0 && max == 0) { @@ -2059,13 +2345,17 @@ compare_len (struct mime_part *part, guint min, guint max) } static gboolean -common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *param_subtype, gint min_len, gint max_len) +common_has_content_part (struct rspamd_task * task, + gchar *param_type, + gchar *param_subtype, + gint min_len, + gint max_len) { - struct rspamd_regexp *re; - struct mime_part *part; - GList *cur; - GMimeContentType *ct; - gint r; + struct rspamd_regexp *re; + struct mime_part *part; + GList *cur; + GMimeContentType *ct; + gint r; cur = g_list_first (task->parts); while (cur) { @@ -2078,8 +2368,11 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa if (*param_type == '/') { /* This is regexp, so compile and create g_regexp object */ - if ((re = re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { - re = parse_regexp (task->cfg->cfg_pool, param_type, task->cfg->raw_mode); + if ((re = + re_cache_check (param_type, task->cfg->cfg_pool)) == NULL) { + re = parse_regexp (task->cfg->cfg_pool, + param_type, + task->cfg->raw_mode); if (re == NULL) { msg_warn ("cannot compile regexp for function"); cur = g_list_next (cur); @@ -2088,7 +2381,8 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa re_cache_add (param_type, re, task->cfg->cfg_pool); } if ((r = task_cache_check (task, re)) == -1) { - if (ct->type && g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { + if (ct->type && + g_regex_match (re->regexp, ct->type, 0, NULL) == TRUE) { if (param_subtype) { if (compare_subtype (task, ct, param_subtype)) { if (compare_len (part, min_len, max_len)) { @@ -2143,8 +2437,8 @@ common_has_content_part (struct rspamd_task * task, gchar *param_type, gchar *pa static gboolean rspamd_has_content_part (struct rspamd_task * task, GList * args, void *unused) { - gchar *param_type = NULL, *param_subtype = NULL; - struct expression_argument *arg; + gchar *param_type = NULL, *param_subtype = NULL; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -2163,11 +2457,13 @@ rspamd_has_content_part (struct rspamd_task * task, GList * args, void *unused) } static gboolean -rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unused) +rspamd_has_content_part_len (struct rspamd_task * task, + GList * args, + void *unused) { - gchar *param_type = NULL, *param_subtype = NULL; - gint min = 0, max = 0; - struct expression_argument *arg; + gchar *param_type = NULL, *param_subtype = NULL; + gint min = 0, max = 0; + struct expression_argument *arg; if (args == NULL) { msg_warn ("no parameters to function"); @@ -2186,7 +2482,9 @@ rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unus errno = 0; min = strtoul (arg->data, NULL, 10); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } args = args->next; @@ -2194,7 +2492,9 @@ rspamd_has_content_part_len (struct rspamd_task * task, GList * args, void *unus arg = get_function_arg (args->data, task, TRUE); max = strtoul (arg->data, NULL, 10); if (errno != 0) { - msg_warn ("invalid numeric value '%s': %s", (gchar *)arg->data, strerror (errno)); + msg_warn ("invalid numeric value '%s': %s", + (gchar *)arg->data, + strerror (errno)); return FALSE; } } diff --git a/src/plugins/spf.c b/src/plugins/spf.c index 8b9e64754..bf0956e78 100644 --- a/src/plugins/spf.c +++ b/src/plugins/spf.c @@ -49,21 +49,21 @@ #define DEFAULT_CACHE_MAXAGE 86400 struct spf_ctx { - gint (*filter) (struct rspamd_task * task); - const gchar *symbol_fail; - const gchar *symbol_softfail; - const gchar *symbol_allow; - - rspamd_mempool_t *spf_pool; - radix_tree_t *whitelist_ip; - rspamd_lru_hash_t *spf_hash; + gint (*filter) (struct rspamd_task * task); + const gchar *symbol_fail; + const gchar *symbol_softfail; + const gchar *symbol_allow; + + rspamd_mempool_t *spf_pool; + radix_tree_t *whitelist_ip; + rspamd_lru_hash_t *spf_hash; }; -static struct spf_ctx *spf_module_ctx = NULL; +static struct spf_ctx *spf_module_ctx = NULL; -static void spf_symbol_callback (struct rspamd_task *task, void *unused); -static GList * spf_record_copy (GList *addrs); -static void spf_record_destroy (gpointer list); +static void spf_symbol_callback (struct rspamd_task *task, void *unused); +static GList * spf_record_copy (GList *addrs); +static void spf_record_destroy (gpointer list); /* Initialization */ gint spf_module_init (struct rspamd_config *cfg, struct module_ctx **ctx); @@ -83,7 +83,8 @@ spf_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) { spf_module_ctx = g_malloc (sizeof (struct spf_ctx)); - spf_module_ctx->spf_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + spf_module_ctx->spf_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); *ctx = (struct module_ctx *)spf_module_ctx; @@ -94,56 +95,71 @@ spf_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) gint spf_module_config (struct rspamd_config *cfg) { - const ucl_object_t *value; - gint res = TRUE; - guint cache_size, cache_expire; + const ucl_object_t *value; + gint res = TRUE; + guint cache_size, cache_expire; spf_module_ctx->whitelist_ip = radix_tree_create (); - - if ((value = rspamd_config_get_module_opt (cfg, "spf", "symbol_fail")) != NULL) { + + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "symbol_fail")) != NULL) { spf_module_ctx->symbol_fail = ucl_obj_tostring (value); } else { spf_module_ctx->symbol_fail = DEFAULT_SYMBOL_FAIL; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "symbol_softfail")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "symbol_softfail")) != NULL) { spf_module_ctx->symbol_softfail = ucl_obj_tostring (value); } else { spf_module_ctx->symbol_softfail = DEFAULT_SYMBOL_SOFTFAIL; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "symbol_allow")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "symbol_allow")) != NULL) { spf_module_ctx->symbol_allow = ucl_obj_tostring (value); } else { spf_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "spf_cache_size")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "spf_cache_size")) != NULL) { cache_size = ucl_obj_toint (value); } else { cache_size = DEFAULT_CACHE_SIZE; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "spf_cache_expire")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", + "spf_cache_expire")) != NULL) { cache_expire = ucl_obj_toint (value); } else { cache_expire = DEFAULT_CACHE_MAXAGE; } - if ((value = rspamd_config_get_module_opt (cfg, "spf", "whitelist")) != NULL) { - if (! add_map (cfg, ucl_obj_tostring (value), - "SPF whitelist", read_radix_list, fin_radix_list, - (void **)&spf_module_ctx->whitelist_ip)) { + if ((value = + rspamd_config_get_module_opt (cfg, "spf", "whitelist")) != NULL) { + if (!add_map (cfg, ucl_obj_tostring (value), + "SPF whitelist", read_radix_list, fin_radix_list, + (void **)&spf_module_ctx->whitelist_ip)) { msg_warn ("cannot load whitelist from %s", value); } } - register_symbol (&cfg->cache, spf_module_ctx->symbol_fail, 1, spf_symbol_callback, NULL); + register_symbol (&cfg->cache, + spf_module_ctx->symbol_fail, + 1, + spf_symbol_callback, + NULL); register_virtual_symbol (&cfg->cache, spf_module_ctx->symbol_softfail, 1); - register_virtual_symbol (&cfg->cache, spf_module_ctx->symbol_allow, 1); + register_virtual_symbol (&cfg->cache, spf_module_ctx->symbol_allow, 1); - spf_module_ctx->spf_hash = rspamd_lru_hash_new (rspamd_strcase_hash, rspamd_strcase_equal, - cache_size, cache_expire, g_free, spf_record_destroy); + spf_module_ctx->spf_hash = rspamd_lru_hash_new (rspamd_strcase_hash, + rspamd_strcase_equal, + cache_size, + cache_expire, + g_free, + spf_record_destroy); return res; } @@ -153,7 +169,8 @@ spf_module_reconfig (struct rspamd_config *cfg) { rspamd_mempool_delete (spf_module_ctx->spf_pool); radix_tree_free (spf_module_ctx->whitelist_ip); - spf_module_ctx->spf_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + spf_module_ctx->spf_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); return spf_module_config (cfg); } @@ -161,26 +178,30 @@ spf_module_reconfig (struct rspamd_config *cfg) static gboolean spf_check_element (struct spf_addr *addr, struct rspamd_task *task) { - gboolean res = FALSE; - guint8 *s, *d, t; - guint nbits, addrlen; - struct in_addr in4s, in4d; - struct in6_addr in6s, in6d; + gboolean res = FALSE; + guint8 *s, *d, t; + guint nbits, addrlen; + struct in_addr in4s, in4d; + struct in6_addr in6s, in6d; /* Basic comparing algorithm */ if ((addr->data.normal.ipv6 && task->from_addr.af == AF_INET6) || - (!addr->data.normal.ipv6 && task->from_addr.af == AF_INET)) { + (!addr->data.normal.ipv6 && task->from_addr.af == AF_INET)) { if (addr->data.normal.ipv6) { addrlen = sizeof (struct in6_addr); - memcpy (&in6s, &addr->data.normal.d.in6, sizeof (struct in6_addr)); - memcpy (&in6d, &task->from_addr.addr.s6.sin6_addr, sizeof (struct in6_addr)); + memcpy (&in6s, &addr->data.normal.d.in6, + sizeof (struct in6_addr)); + memcpy (&in6d, &task->from_addr.addr.s6.sin6_addr, + sizeof (struct in6_addr)); s = (guint8 *)&in6s; d = (guint8 *)&in6d; } else { addrlen = sizeof (struct in_addr); - memcpy (&in4s, &addr->data.normal.d.in4, sizeof (struct in_addr)); - memcpy (&in4d, &task->from_addr.addr.s4.sin_addr, sizeof (struct in_addr)); + memcpy (&in4s, &addr->data.normal.d.in4, + sizeof (struct in_addr)); + memcpy (&in4d, &task->from_addr.addr.s4.sin_addr, + sizeof (struct in_addr)); s = (guint8 *)&in4s; d = (guint8 *)&in4d; } @@ -189,12 +210,14 @@ spf_check_element (struct spf_addr *addr, struct rspamd_task *task) s += addrlen - 1; d += addrlen - 1; /* TODO: improve this cycle by masking by words */ - for (nbits = 0; nbits < addrlen * CHAR_BIT - addr->data.normal.mask; nbits ++) { + for (nbits = 0; + nbits < addrlen * CHAR_BIT - addr->data.normal.mask; + nbits++) { /* Skip bits from the beginning as we know that data is in network byte order */ if (nbits != 0 && nbits % 8 == 0) { /* Move pointer to the next byte */ - s --; - d --; + s--; + d--; t = 0x1; } *s |= t; @@ -220,17 +243,28 @@ spf_check_element (struct spf_addr *addr, struct rspamd_task *task) if (res) { switch (addr->mech) { case SPF_FAIL: - insert_result (task, spf_module_ctx->symbol_fail, 1, g_list_prepend (NULL, addr->spf_string)); + insert_result (task, + spf_module_ctx->symbol_fail, + 1, + g_list_prepend (NULL, addr->spf_string)); task->messages = g_list_prepend (task->messages, "(SPF): spf fail"); break; case SPF_SOFT_FAIL: case SPF_NEUTRAL: - insert_result (task, spf_module_ctx->symbol_softfail, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf softfail"); + insert_result (task, + spf_module_ctx->symbol_softfail, + 1, + g_list_prepend (NULL, addr->spf_string)); + task->messages = g_list_prepend (task->messages, + "(SPF): spf softfail"); break; default: - insert_result (task, spf_module_ctx->symbol_allow, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf allow"); + insert_result (task, + spf_module_ctx->symbol_allow, + 1, + g_list_prepend (NULL, addr->spf_string)); + task->messages = + g_list_prepend (task->messages, "(SPF): spf allow"); break; } return TRUE; @@ -242,8 +276,8 @@ spf_check_element (struct spf_addr *addr, struct rspamd_task *task) static gboolean spf_check_list (GList *list, struct rspamd_task *task) { - GList *cur; - struct spf_addr *addr; + GList *cur; + struct spf_addr *addr; cur = list; @@ -266,16 +300,19 @@ spf_check_list (GList *list, struct rspamd_task *task) return FALSE; } -static void +static void spf_plugin_callback (struct spf_record *record, struct rspamd_task *task) { - GList *l; + GList *l; if (record && record->addrs && record->sender_domain) { - if ((l = rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, record->sender_domain, task->tv.tv_sec)) == NULL) { + if ((l = + rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, + record->sender_domain, task->tv.tv_sec)) == NULL) { l = spf_record_copy (record->addrs); - rspamd_lru_hash_insert (spf_module_ctx->spf_hash, g_strdup (record->sender_domain), + rspamd_lru_hash_insert (spf_module_ctx->spf_hash, + g_strdup (record->sender_domain), l, task->tv.tv_sec, record->ttl); } spf_check_list (l, task); @@ -283,16 +320,18 @@ spf_plugin_callback (struct spf_record *record, struct rspamd_task *task) } -static void +static void spf_symbol_callback (struct rspamd_task *task, void *unused) { - gchar *domain; - GList *l; + gchar *domain; + GList *l; if (task->from_addr.af != AF_UNIX) { domain = get_spf_domain (task); if (domain) { - if ((l = rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, domain, task->tv.tv_sec)) != NULL) { + if ((l = + rspamd_lru_hash_lookup (spf_module_ctx->spf_hash, domain, + task->tv.tv_sec)) != NULL) { spf_check_list (l, task); } else if (!resolve_spf (task, spf_plugin_callback)) { @@ -308,8 +347,8 @@ spf_symbol_callback (struct rspamd_task *task, void *unused) static GList * spf_record_copy (GList *addrs) { - GList *cur, *newl = NULL; - struct spf_addr *addr, *newa; + GList *cur, *newl = NULL; + struct spf_addr *addr, *newa; cur = addrs; @@ -341,8 +380,8 @@ spf_record_copy (GList *addrs) static void spf_record_destroy (gpointer list) { - GList *cur = list; - struct spf_addr *addr; + GList *cur = list; + struct spf_addr *addr; while (cur) { addr = cur->data; diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index ef25c1d78..be5a60276 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -53,15 +53,15 @@ #include "surbl.h" -static struct surbl_ctx *surbl_module_ctx = NULL; +static struct surbl_ctx *surbl_module_ctx = NULL; static void surbl_test_url (struct rspamd_task *task, void *user_data); static void dns_callback (struct rdns_reply *reply, gpointer arg); static void process_dns_results (struct rspamd_task *task, - struct suffix_item *suffix, gchar *url, guint32 addr); + struct suffix_item *suffix, gchar *url, guint32 addr); -#define NO_REGEXP (gpointer)-1 +#define NO_REGEXP (gpointer) - 1 #define SURBL_ERROR surbl_error_quark () #define WHITELIST_ERROR 0 @@ -89,50 +89,63 @@ module_t surbl_module = { static void exception_insert (gpointer st, gconstpointer key, gpointer value) { - GHashTable **t = st; - gint level = 0; - const gchar *p = key; - f_str_t *val; - + GHashTable **t = st; + gint level = 0; + const gchar *p = key; + f_str_t *val; + while (*p) { if (*p == '.') { - level ++; + level++; } - p ++; + p++; } if (level >= MAX_LEVELS) { - msg_err ("invalid domain in exceptions list: %s, levels: %d", (gchar *)key, level); + msg_err ("invalid domain in exceptions list: %s, levels: %d", + (gchar *)key, + level); return; } - + val = g_malloc (sizeof (f_str_t)); val->begin = (gchar *)key; val->len = strlen (key); if (t[level] == NULL) { - t[level] = g_hash_table_new_full (fstr_strcase_hash, fstr_strcase_equal, g_free, NULL); + t[level] = g_hash_table_new_full (fstr_strcase_hash, + fstr_strcase_equal, + g_free, + NULL); } g_hash_table_insert (t[level], val, value); } static gchar * -read_exceptions_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +read_exceptions_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { - data->cur_data = rspamd_mempool_alloc0 (pool, sizeof (GHashTable *) * MAX_LEVELS); + data->cur_data = rspamd_mempool_alloc0 (pool, + sizeof (GHashTable *) * MAX_LEVELS); } - return abstract_parse_list (pool, chunk, len, data, (insert_func) exception_insert); + return abstract_parse_list (pool, + chunk, + len, + data, + (insert_func) exception_insert); } static void fin_exceptions_list (rspamd_mempool_t * pool, struct map_cb_data *data) { - GHashTable **t; - gint i; + GHashTable **t; + gint i; if (data->prev_data) { t = data->prev_data; - for (i = 0; i < MAX_LEVELS; i ++) { + for (i = 0; i < MAX_LEVELS; i++) { if (t[i] != NULL) { g_hash_table_destroy (t[i]); } @@ -143,16 +156,16 @@ fin_exceptions_list (rspamd_mempool_t * pool, struct map_cb_data *data) static void redirector_insert (gpointer st, gconstpointer key, gpointer value) { - GHashTable *t = st; - const gchar *p = key, *begin = key; - gchar *new; - gsize len; - GRegex *re = NO_REGEXP; - GError *err = NULL; - guint idx; + GHashTable *t = st; + const gchar *p = key, *begin = key; + gchar *new; + gsize len; + GRegex *re = NO_REGEXP; + GError *err = NULL; + guint idx; while (*p && !g_ascii_isspace (*p)) { - p ++; + p++; } len = p - begin; @@ -165,13 +178,17 @@ redirector_insert (gpointer st, gconstpointer key, gpointer value) if (g_ascii_isspace (*p)) { while (g_ascii_isspace (*p) && *p) { - p ++; + p++; } if (*p) { - re = g_regex_new (p, G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE | G_REGEX_CASELESS, - 0, &err); + re = g_regex_new (p, + G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE | G_REGEX_CASELESS, + 0, + &err); if (re == NULL) { - msg_warn ("could not read regexp: %s while reading regexp %s", err->message, p); + msg_warn ("could not read regexp: %s while reading regexp %s", + err->message, + p); re = NO_REGEXP; } } @@ -182,21 +199,31 @@ redirector_insert (gpointer st, gconstpointer key, gpointer value) static void redirector_item_free (gpointer p) { - GRegex *re; + GRegex *re; if (p != NULL && p != NO_REGEXP) { re = (GRegex *)p; g_regex_unref (re); } } -static gchar * -read_redirectors_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data) +static gchar * +read_redirectors_list (rspamd_mempool_t * pool, + gchar * chunk, + gint len, + struct map_cb_data *data) { if (data->cur_data == NULL) { - data->cur_data = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, redirector_item_free); + data->cur_data = g_hash_table_new_full (rspamd_strcase_hash, + rspamd_strcase_equal, + g_free, + redirector_item_free); } - return abstract_parse_list (pool, chunk, len, data, (insert_func) redirector_insert); + return abstract_parse_list (pool, + chunk, + len, + data, + (insert_func) redirector_insert); } void @@ -214,7 +241,8 @@ surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) surbl_module_ctx->use_redirector = 0; surbl_module_ctx->suffixes = NULL; - surbl_module_ctx->surbl_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + surbl_module_ctx->surbl_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); surbl_module_ctx->tld2_file = NULL; surbl_module_ctx->whitelist_file = NULL; @@ -222,16 +250,28 @@ surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) surbl_module_ctx->redirector_trie = rspamd_trie_create (TRUE); surbl_module_ctx->redirector_ptrs = g_ptr_array_new (); - surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); - surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); + surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); /* Zero exceptions hashes */ - surbl_module_ctx->exceptions = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool, MAX_LEVELS * sizeof (GHashTable *)); + surbl_module_ctx->exceptions = rspamd_mempool_alloc0 ( + surbl_module_ctx->surbl_pool, + MAX_LEVELS * sizeof (GHashTable *)); /* Register destructors */ - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->whitelist); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->redirector_hosts); - - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) rspamd_trie_free, surbl_module_ctx->redirector_trie); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_ptr_array_unref, surbl_module_ctx->redirector_ptrs); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->whitelist); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->redirector_hosts); + + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) rspamd_trie_free, + surbl_module_ctx->redirector_trie); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_ptr_array_unref, + surbl_module_ctx->redirector_ptrs); *ctx = (struct module_ctx *)surbl_module_ctx; @@ -244,8 +284,8 @@ surbl_module_init (struct rspamd_config *cfg, struct module_ctx **ctx) static void register_bit_symbols (struct rspamd_config *cfg, struct suffix_item *suffix) { - GList *cur; - struct surbl_bit_item *bit; + GList *cur; + struct surbl_bit_item *bit; if (suffix->bits != NULL) { /* Prepend bit to symbol */ @@ -264,131 +304,163 @@ register_bit_symbols (struct rspamd_config *cfg, struct suffix_item *suffix) 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; + 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; - guint32 bit; - gint i, idx; + const ucl_object_t *value, *cur, *cur_rule, *cur_bit; + ucl_object_iter_t it = NULL; + const gchar *redir_val; + guint32 bit; + gint i, idx; - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "redirector")) != NULL) { i = 0; - LL_FOREACH (value, cur) { - i ++; + LL_FOREACH (value, cur) + { + i++; } - surbl_module_ctx->redirectors = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool, - i * sizeof (struct redirector_upstream)); + surbl_module_ctx->redirectors = rspamd_mempool_alloc0 ( + surbl_module_ctx->surbl_pool, + i * sizeof (struct redirector_upstream)); idx = 0; - LL_FOREACH (value, cur) { + LL_FOREACH (value, cur) + { redir_val = ucl_obj_tostring (cur); surbl_module_ctx->redirectors[idx].up.priority = 100; - if (! rspamd_parse_host_port_priority (surbl_module_ctx->surbl_pool, - redir_val, &surbl_module_ctx->redirectors[idx].addr, - &surbl_module_ctx->redirectors[idx].port, - &surbl_module_ctx->redirectors[idx].up.priority)) { + if (!rspamd_parse_host_port_priority (surbl_module_ctx->surbl_pool, + redir_val, &surbl_module_ctx->redirectors[idx].addr, + &surbl_module_ctx->redirectors[idx].port, + &surbl_module_ctx->redirectors[idx].up.priority)) { msg_warn ("invalid redirector definition: %s", redir_val); } else { if (surbl_module_ctx->redirectors[idx].port != 0) { - surbl_module_ctx->redirectors[idx].name = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, + surbl_module_ctx->redirectors[idx].name = + rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, redir_val); - msg_info ("add redirector %s", surbl_module_ctx->redirectors[idx].name); - idx ++; + msg_info ("add redirector %s", + surbl_module_ctx->redirectors[idx].name); + idx++; } } - i ++; + i++; } surbl_module_ctx->redirectors_number = idx; - surbl_module_ctx->use_redirector = (surbl_module_ctx->redirectors_number != 0); + surbl_module_ctx->use_redirector = + (surbl_module_ctx->redirectors_number != 0); } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_symbol")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_symbol")) != NULL) { surbl_module_ctx->redirector_symbol = ucl_obj_tostring (value); - register_virtual_symbol (&cfg->cache, surbl_module_ctx->redirector_symbol, 1.0); + register_virtual_symbol (&cfg->cache, + surbl_module_ctx->redirector_symbol, + 1.0); } else { surbl_module_ctx->redirector_symbol = NULL; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "weight")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "weight")) != NULL) { surbl_module_ctx->weight = ucl_obj_toint (value); } else { surbl_module_ctx->weight = DEFAULT_SURBL_WEIGHT; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "url_expire")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "url_expire")) != NULL) { surbl_module_ctx->url_expire = ucl_obj_todouble (value); } else { surbl_module_ctx->url_expire = DEFAULT_SURBL_URL_EXPIRE; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_connect_timeout")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_connect_timeout")) != NULL) { surbl_module_ctx->connect_timeout = ucl_obj_todouble (value); } else { surbl_module_ctx->connect_timeout = DEFAULT_REDIRECTOR_CONNECT_TIMEOUT; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_read_timeout")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_read_timeout")) != NULL) { surbl_module_ctx->read_timeout = ucl_obj_todouble (value); } else { surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "redirector_hosts_map")) != NULL) { - add_map (cfg, ucl_obj_tostring (value), - "SURBL redirectors list", read_redirectors_list, fin_redirectors_list, - (void **)&surbl_module_ctx->redirector_hosts); + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", + "redirector_hosts_map")) != NULL) { + add_map (cfg, ucl_obj_tostring ( + value), + "SURBL redirectors list", read_redirectors_list, fin_redirectors_list, + (void **)&surbl_module_ctx->redirector_hosts); } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "max_urls")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "max_urls")) != NULL) { surbl_module_ctx->max_urls = ucl_obj_toint (value); } else { surbl_module_ctx->max_urls = DEFAULT_SURBL_MAX_URLS; } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "exceptions")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "exceptions")) != NULL) { if (add_map (cfg, ucl_obj_tostring (value), - "SURBL exceptions list", read_exceptions_list, fin_exceptions_list, - (void **)&surbl_module_ctx->exceptions)) { - surbl_module_ctx->tld2_file = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (value) + sizeof ("file://") - 1); + "SURBL exceptions list", read_exceptions_list, fin_exceptions_list, + (void **)&surbl_module_ctx->exceptions)) { + surbl_module_ctx->tld2_file = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (value) + sizeof ("file://") - 1); } } - if ((value = rspamd_config_get_module_opt (cfg, "surbl", "whitelist")) != NULL) { + if ((value = + rspamd_config_get_module_opt (cfg, "surbl", "whitelist")) != NULL) { if (add_map (cfg, ucl_obj_tostring (value), - "SURBL whitelist", read_host_list, fin_host_list, - (void **)&surbl_module_ctx->whitelist)) { - surbl_module_ctx->whitelist_file = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (value) + sizeof ("file://") - 1); + "SURBL whitelist", read_host_list, fin_host_list, + (void **)&surbl_module_ctx->whitelist)) { + surbl_module_ctx->whitelist_file = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (value) + sizeof ("file://") - 1); } } value = rspamd_config_get_module_opt (cfg, "surbl", "rule"); if (value != NULL && value->type == UCL_OBJECT) { - LL_FOREACH (value, cur_rule) { + LL_FOREACH (value, cur_rule) + { cur = ucl_obj_get_key (cur_rule, "suffix"); if (cur == NULL) { msg_err ("surbl rule must have explicit symbol definition"); continue; } - new_suffix = rspamd_mempool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct suffix_item)); - new_suffix->suffix = rspamd_mempool_strdup (surbl_module_ctx->surbl_pool, - ucl_obj_tostring (cur)); + new_suffix = rspamd_mempool_alloc (surbl_module_ctx->surbl_pool, + sizeof (struct suffix_item)); + new_suffix->suffix = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_obj_tostring (cur)); new_suffix->options = 0; new_suffix->bits = NULL; cur = ucl_obj_get_key (cur_rule, "symbol"); if (cur == NULL) { - msg_warn ("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); + msg_warn ( + "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)); + 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) { @@ -399,19 +471,33 @@ surbl_module_config (struct rspamd_config *cfg) cur = ucl_obj_get_key (cur_rule, "bits"); if (cur != NULL && cur->type == UCL_OBJECT) { it = NULL; - while ((cur_bit = ucl_iterate_object (cur, &it, true)) != NULL) { - if (ucl_object_key (cur_bit) != NULL && cur_bit->type == UCL_INT) { + while ((cur_bit = + ucl_iterate_object (cur, &it, true)) != NULL) { + if (ucl_object_key (cur_bit) != NULL && cur_bit->type == + UCL_INT) { bit = ucl_obj_toint (cur_bit); - new_bit = rspamd_mempool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct surbl_bit_item)); + 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)); - msg_debug ("add new bit suffix: %d with symbol: %s", (gint)new_bit->bit, new_bit->symbol); - new_suffix->bits = g_list_prepend (new_suffix->bits, new_bit); + new_bit->symbol = rspamd_mempool_strdup ( + surbl_module_ctx->surbl_pool, + ucl_object_key (cur_bit)); + msg_debug ("add new bit suffix: %d with symbol: %s", + (gint)new_bit->bit, new_bit->symbol); + new_suffix->bits = g_list_prepend (new_suffix->bits, + new_bit); } } } - surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes, new_suffix); - register_callback_symbol (&cfg->cache, new_suffix->symbol, 1, surbl_test_url, new_suffix); + surbl_module_ctx->suffixes = g_list_prepend ( + surbl_module_ctx->suffixes, + new_suffix); + register_callback_symbol (&cfg->cache, + new_suffix->symbol, + 1, + surbl_test_url, + new_suffix); } } /* Add default suffix */ @@ -421,8 +507,9 @@ surbl_module_config (struct rspamd_config *cfg) } if (surbl_module_ctx->suffixes != NULL) { - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_list_free, - surbl_module_ctx->suffixes); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_list_free, + surbl_module_ctx->suffixes); } cur_opt = surbl_module_ctx->suffixes; @@ -430,8 +517,9 @@ surbl_module_config (struct rspamd_config *cfg) cur_suffix = cur_opt->data; if (cur_suffix->bits != NULL) { register_bit_symbols (cfg, cur_suffix); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_list_free, - cur_suffix->bits); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_list_free, + cur_suffix->bits); } cur_opt = g_list_next (cur_opt); } @@ -447,25 +535,40 @@ surbl_module_reconfig (struct rspamd_config *cfg) /* Reinit module */ surbl_module_ctx->use_redirector = 0; surbl_module_ctx->suffixes = NULL; - surbl_module_ctx->surbl_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ()); + surbl_module_ctx->surbl_pool = rspamd_mempool_new ( + rspamd_mempool_suggest_size ()); surbl_module_ctx->tld2_file = NULL; surbl_module_ctx->whitelist_file = NULL; surbl_module_ctx->redirectors_number = 0; surbl_module_ctx->redirector_trie = rspamd_trie_create (TRUE); - surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); - surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); + surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); + surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, + rspamd_strcase_equal); /* Zero exceptions hashes */ - surbl_module_ctx->exceptions = rspamd_mempool_alloc0 (surbl_module_ctx->surbl_pool, MAX_LEVELS * sizeof (GHashTable *)); + surbl_module_ctx->exceptions = rspamd_mempool_alloc0 ( + surbl_module_ctx->surbl_pool, + MAX_LEVELS * sizeof (GHashTable *)); /* Register destructors */ - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->whitelist); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_hash_table_destroy, surbl_module_ctx->redirector_hosts); - - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_list_free, surbl_module_ctx->suffixes); - - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) rspamd_trie_free, surbl_module_ctx->redirector_trie); - rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, (rspamd_mempool_destruct_t) g_ptr_array_unref, surbl_module_ctx->redirector_ptrs); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->whitelist); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_hash_table_destroy, + surbl_module_ctx->redirector_hosts); + + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_list_free, + surbl_module_ctx->suffixes); + + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) rspamd_trie_free, + surbl_module_ctx->redirector_trie); + rspamd_mempool_add_destructor (surbl_module_ctx->surbl_pool, + (rspamd_mempool_destruct_t) g_ptr_array_unref, + surbl_module_ctx->redirector_ptrs); /* Perform configure */ return surbl_module_config (cfg); @@ -473,16 +576,22 @@ surbl_module_reconfig (struct rspamd_config *cfg) -static gchar * -format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix_item *suffix, - gboolean append_suffix, GError ** err, gboolean forced, GTree *tree) +static gchar * +format_surbl_request (rspamd_mempool_t * pool, + f_str_t * hostname, + struct suffix_item *suffix, + gboolean append_suffix, + GError ** err, + gboolean forced, + GTree *tree) { - GHashTable *t; - gchar *result = NULL, *dots[MAX_LEVELS], num_buf[sizeof("18446744073709551616")], *p; - gint len, slen, r, i, dots_num = 0, level = MAX_LEVELS; - gboolean is_numeric = TRUE; - guint64 ip_num; - f_str_t f; + GHashTable *t; + gchar *result = NULL, *dots[MAX_LEVELS], + num_buf[sizeof("18446744073709551616")], *p; + gint len, slen, r, i, dots_num = 0, level = MAX_LEVELS; + gboolean is_numeric = TRUE; + guint64 ip_num; + f_str_t f; if (G_LIKELY (suffix != NULL)) { slen = strlen (suffix->suffix); @@ -494,19 +603,19 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix g_assert_not_reached (); } len = hostname->len + slen + 2; - + p = hostname->begin; while (p - hostname->begin < (gint)hostname->len && dots_num < MAX_LEVELS) { if (*p == '.') { dots[dots_num] = p; - dots_num ++; + dots_num++; } - else if (! g_ascii_isdigit (*p)) { + else if (!g_ascii_isdigit (*p)) { is_numeric = FALSE; } - p ++; + p++; } - + /* Check for numeric expressions */ if (is_numeric && dots_num == 3) { /* This is ip address */ @@ -516,7 +625,7 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix return NULL; } result = rspamd_mempool_alloc (pool, len); - r = rspamd_snprintf (result, len, "%*s.%*s.%*s.%*s", + r = rspamd_snprintf (result, len, "%*s.%*s.%*s.%*s", (gint)(hostname->len - (dots[2] - hostname->begin + 1)), dots[2] + 1, (gint)(dots[2] - dots[1] - 1), @@ -533,13 +642,16 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix msg_info ("ignore request of ip url for list %s", suffix->symbol); return NULL; } - rspamd_strlcpy (num_buf, hostname->begin, MIN (hostname->len + 1, sizeof (num_buf))); + rspamd_strlcpy (num_buf, hostname->begin, + MIN (hostname->len + 1, sizeof (num_buf))); errno = 0; ip_num = strtoull (num_buf, NULL, 10); if (errno != 0) { - msg_info ("cannot convert ip to number '%s': %s", num_buf, strerror (errno)); - g_set_error (err, SURBL_ERROR, /* error domain */ - CONVERSION_ERROR, /* error code */ + msg_info ("cannot convert ip to number '%s': %s", + num_buf, + strerror (errno)); + g_set_error (err, SURBL_ERROR, /* error domain */ + CONVERSION_ERROR, /* error code */ "URL cannot be decoded"); return NULL; } @@ -549,19 +661,25 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix /* Hack for bugged windows resolver */ ip_num &= 0xFFFFFFFF; /* Get octets */ - r = rspamd_snprintf (result, len, "%ud.%ud.%ud.%ud", - (guint32) ip_num & 0x000000FF, (guint32) (ip_num & 0x0000FF00) >> 8, (guint32) (ip_num & 0x00FF0000) >> 16, (guint32) (ip_num & 0xFF000000) >> 24); + r = rspamd_snprintf (result, + len, + "%ud.%ud.%ud.%ud", + (guint32) ip_num & 0x000000FF, + (guint32) (ip_num & 0x0000FF00) >> 8, + (guint32) (ip_num & 0x00FF0000) >> 16, + (guint32) (ip_num & 0xFF000000) >> 24); } else { /* Not a numeric url */ result = rspamd_mempool_alloc (pool, len); /* Now we should try to check for exceptions */ - if (! forced) { - for (i = MAX_LEVELS - 1; i >= 0; i --) { + if (!forced) { + for (i = MAX_LEVELS - 1; i >= 0; i--) { t = surbl_module_ctx->exceptions[i]; if (t != NULL && dots_num >= i + 1) { f.begin = dots[dots_num - i - 1] + 1; - f.len = hostname->len - (dots[dots_num - i - 1] - hostname->begin + 1); + f.len = hostname->len - + (dots[dots_num - i - 1] - hostname->begin + 1); if (g_hash_table_lookup (t, &f) != NULL) { level = dots_num - i - 1; break; @@ -571,31 +689,41 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix } if (level != MAX_LEVELS) { if (level == 0) { - r = rspamd_snprintf (result, len, "%*s", (gint)hostname->len, hostname->begin); + r = rspamd_snprintf (result, + len, + "%*s", + (gint)hostname->len, + hostname->begin); } else { - r = rspamd_snprintf (result, len, "%*s", - (gint)(hostname->len - (dots[level - 1] - hostname->begin + 1)), - dots[level - 1] + 1); + r = rspamd_snprintf (result, len, "%*s", + (gint)(hostname->len - + (dots[level - 1] - hostname->begin + 1)), + dots[level - 1] + 1); } } else if (dots_num >= 2) { r = rspamd_snprintf (result, len, "%*s", - (gint)(hostname->len - (dots[dots_num - 2] - hostname->begin + 1)), + (gint)(hostname->len - + (dots[dots_num - 2] - hostname->begin + 1)), dots[dots_num - 2] + 1); } else { - r = rspamd_snprintf (result, len, "%*s", (gint)hostname->len, hostname->begin); + r = rspamd_snprintf (result, + len, + "%*s", + (gint)hostname->len, + hostname->begin); } } if (tree != NULL) { if (g_tree_lookup (tree, result) != NULL) { msg_debug ("url %s is already registered", result); - g_set_error (err, SURBL_ERROR, /* error domain */ - DUPLICATE_ERROR, /* error code */ - "URL is duplicated: %s", /* error message format string */ - result); + g_set_error (err, SURBL_ERROR, /* error domain */ + DUPLICATE_ERROR, /* error code */ + "URL is duplicated: %s", /* error message format string */ + result); return NULL; } else { @@ -603,12 +731,13 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix } } - if (!forced && g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) { + if (!forced && + g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) { msg_debug ("url %s is whitelisted", result); - g_set_error (err, SURBL_ERROR, /* error domain */ - WHITELIST_ERROR, /* error code */ - "URL is whitelisted: %s", /* error message format string */ - result); + g_set_error (err, SURBL_ERROR, /* error domain */ + WHITELIST_ERROR, /* error code */ + "URL is whitelisted: %s", /* error message format string */ + result); return NULL; } @@ -617,38 +746,48 @@ format_surbl_request (rspamd_mempool_t * pool, f_str_t * hostname, struct suffix rspamd_snprintf (result + r, len - r, ".%s", suffix->suffix); } - msg_debug ("request: %s, dots: %d, level: %d, orig: %*s", result, dots_num, level, (gint)hostname->len, hostname->begin); + msg_debug ("request: %s, dots: %d, level: %d, orig: %*s", + result, + dots_num, + level, + (gint)hostname->len, + hostname->begin); return result; } static void make_surbl_requests (struct uri *url, struct rspamd_task *task, - struct suffix_item *suffix, gboolean forced, GTree *tree) + struct suffix_item *suffix, gboolean forced, GTree *tree) { - gchar *surbl_req; - f_str_t f; - GError *err = NULL; - struct dns_param *param; + gchar *surbl_req; + f_str_t f; + GError *err = NULL; + struct dns_param *param; f.begin = url->host; f.len = url->hostlen; if ((surbl_req = format_surbl_request (task->task_pool, &f, suffix, TRUE, - &err, forced, tree)) != NULL) { - param = rspamd_mempool_alloc (task->task_pool, sizeof (struct dns_param)); + &err, forced, tree)) != NULL) { + param = + rspamd_mempool_alloc (task->task_pool, sizeof (struct dns_param)); param->url = url; param->task = task; param->suffix = suffix; - param->host_resolve = rspamd_mempool_strdup (task->task_pool, surbl_req); + param->host_resolve = + rspamd_mempool_strdup (task->task_pool, surbl_req); debug_task ("send surbl dns request %s", surbl_req); - if (make_dns_request (task->resolver, task->s, task->task_pool, dns_callback, - (void *)param, RDNS_REQUEST_A, surbl_req)) { - task->dns_requests ++; + if (make_dns_request (task->resolver, task->s, task->task_pool, + dns_callback, + (void *)param, RDNS_REQUEST_A, surbl_req)) { + task->dns_requests++; } } - else if (err != NULL && err->code != WHITELIST_ERROR && err->code != DUPLICATE_ERROR) { - msg_info ("cannot format url string for surbl %s, %s", struri (url), err->message); + else if (err != NULL && err->code != WHITELIST_ERROR && err->code != + DUPLICATE_ERROR) { + msg_info ("cannot format url string for surbl %s, %s", struri ( + url), err->message); g_error_free (err); return; } @@ -658,58 +797,67 @@ make_surbl_requests (struct uri *url, struct rspamd_task *task, } static void -process_dns_results (struct rspamd_task *task, struct suffix_item *suffix, gchar *url, guint32 addr) +process_dns_results (struct rspamd_task *task, + struct suffix_item *suffix, + gchar *url, + guint32 addr) { - GList *cur; - struct surbl_bit_item *bit; + GList *cur; + struct surbl_bit_item *bit; if (suffix->bits != NULL) { cur = g_list_first (suffix->bits); while (cur) { bit = (struct surbl_bit_item *)cur->data; - debug_task ("got result(%d) AND bit(%d): %d", (gint)addr, (gint)ntohl (bit->bit), - (gint)bit->bit & (gint)ntohl (addr)); + debug_task ("got result(%d) AND bit(%d): %d", + (gint)addr, + (gint)ntohl (bit->bit), + (gint)bit->bit & (gint)ntohl (addr)); if (((gint)bit->bit & (gint)ntohl (addr)) != 0) { insert_result (task, bit->symbol, 1, - g_list_prepend (NULL, rspamd_mempool_strdup (task->task_pool, url))); + g_list_prepend (NULL, + rspamd_mempool_strdup (task->task_pool, url))); } cur = g_list_next (cur); } } else { - insert_result (task, suffix->symbol, 1, g_list_prepend (NULL, rspamd_mempool_strdup (task->task_pool, url))); + insert_result (task, suffix->symbol, 1, + g_list_prepend (NULL, + rspamd_mempool_strdup (task->task_pool, url))); } } static void dns_callback (struct rdns_reply *reply, gpointer arg) { - struct dns_param *param = (struct dns_param *)arg; - struct rspamd_task *task = param->task; - struct rdns_reply_entry *elt; + struct dns_param *param = (struct dns_param *)arg; + struct rspamd_task *task = param->task; + struct rdns_reply_entry *elt; debug_task ("in surbl request callback"); /* If we have result from DNS server, this url exists in SURBL, so increase score */ if (reply->code == RDNS_RC_NOERROR && reply->entries) { msg_info ("<%s> domain [%s] is in surbl %s", param->task->message_id, - param->host_resolve, param->suffix->suffix); + param->host_resolve, param->suffix->suffix); elt = reply->entries; if (elt->type == RDNS_REQUEST_A) { process_dns_results (param->task, param->suffix, - param->host_resolve, (guint32)elt->content.a.addr.s_addr); + param->host_resolve, (guint32)elt->content.a.addr.s_addr); } } else { debug_task ("<%s> domain [%s] is not in surbl %s", - param->task->message_id, param->host_resolve, param->suffix->suffix); + param->task->message_id, param->host_resolve, + param->suffix->suffix); } } static void free_redirector_session (void *ud) { - struct redirector_param *param = (struct redirector_param *)ud; + struct redirector_param *param = (struct redirector_param *)ud; event_del (¶m->ev); g_string_free (param->buf, TRUE); @@ -719,38 +867,55 @@ free_redirector_session (void *ud) static void redirector_callback (gint fd, short what, void *arg) { - struct redirector_param *param = (struct redirector_param *)arg; - struct rspamd_task *task = param->task; - gchar url_buf[512]; - gint r; - struct timeval *timeout; - gchar *p, *c; - gboolean found = FALSE; + struct redirector_param *param = (struct redirector_param *)arg; + struct rspamd_task *task = param->task; + gchar url_buf[512]; + gint r; + struct timeval *timeout; + gchar *p, *c; + gboolean found = FALSE; switch (param->state) { case STATE_CONNECT: /* We have write readiness after connect call, so reinit event */ if (what == EV_WRITE) { - timeout = rspamd_mempool_alloc (param->task->task_pool, sizeof (struct timeval)); + timeout = + rspamd_mempool_alloc (param->task->task_pool, + sizeof (struct timeval)); timeout->tv_sec = surbl_module_ctx->read_timeout / 1000; - timeout->tv_usec = (surbl_module_ctx->read_timeout - timeout->tv_sec * 1000) * 1000; + timeout->tv_usec = + (surbl_module_ctx->read_timeout - timeout->tv_sec * + 1000) * 1000; event_del (¶m->ev); - event_set (¶m->ev, param->sock, EV_READ | EV_PERSIST, redirector_callback, (void *)param); + event_set (¶m->ev, + param->sock, + EV_READ | EV_PERSIST, + redirector_callback, + (void *)param); event_add (¶m->ev, timeout); - r = rspamd_snprintf (url_buf, sizeof (url_buf), "GET %s HTTP/1.0\r\n\r\n", struri (param->url)); + r = rspamd_snprintf (url_buf, + sizeof (url_buf), + "GET %s HTTP/1.0\r\n\r\n", + struri (param->url)); if (write (param->sock, url_buf, r) == -1) { - msg_err ("write failed %s to %s", strerror (errno), param->redirector->name); + msg_err ("write failed %s to %s", strerror ( + errno), param->redirector->name); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, + free_redirector_session, + param); return; } param->state = STATE_READ; } else { - msg_info ("<%s> connection to redirector %s timed out while waiting for write", - param->task->message_id, param->redirector->name); + msg_info ( + "<%s> connection to redirector %s timed out while waiting for write", + param->task->message_id, + param->redirector->name); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, free_redirector_session, + param); return; } @@ -759,10 +924,17 @@ redirector_callback (gint fd, short what, void *arg) if (what == EV_READ) { r = read (param->sock, url_buf, sizeof (url_buf) - 1); if (r <= 0) { - msg_err ("read failed: %s from %s", strerror (errno), param->redirector->name); + msg_err ("read failed: %s from %s", strerror ( + errno), param->redirector->name); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - make_surbl_requests (param->url, param->task, param->suffix, FALSE, param->tree); - remove_normal_event (param->task->s, free_redirector_session, param); + make_surbl_requests (param->url, + param->task, + param->suffix, + FALSE, + param->tree); + remove_normal_event (param->task->s, + free_redirector_session, + param); return; } @@ -779,21 +951,36 @@ redirector_callback (gint fd, short what, void *arg) } } if (found) { - debug_task ("<%s> got reply from redirector: '%s' -> '%s'", param->task->message_id, struri (param->url), c); - r = parse_uri (param->url, rspamd_mempool_strdup (param->task->task_pool, c), param->task->task_pool); - if (r == URI_ERRNO_OK || r == URI_ERRNO_NO_SLASHES || r == URI_ERRNO_NO_HOST_SLASH) { - make_surbl_requests (param->url, param->task, param->suffix, FALSE, param->tree); + debug_task ("<%s> got reply from redirector: '%s' -> '%s'", + param->task->message_id, + struri (param->url), + c); + r = + parse_uri (param->url, + rspamd_mempool_strdup (param->task->task_pool, + c), param->task->task_pool); + if (r == URI_ERRNO_OK || r == URI_ERRNO_NO_SLASHES || r == + URI_ERRNO_NO_HOST_SLASH) { + make_surbl_requests (param->url, + param->task, + param->suffix, + FALSE, + param->tree); } } } upstream_ok (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, free_redirector_session, + param); } else { - msg_info ("<%s> reading redirector %s timed out, while waiting for read", - param->redirector->name, param->task->message_id); + msg_info ( + "<%s> reading redirector %s timed out, while waiting for read", + param->redirector->name, + param->task->message_id); upstream_fail (¶m->redirector->up, param->task->tv.tv_sec); - remove_normal_event (param->task->s, free_redirector_session, param); + remove_normal_event (param->task->s, free_redirector_session, + param); } break; } @@ -802,30 +989,42 @@ redirector_callback (gint fd, short what, void *arg) static void register_redirector_call (struct uri *url, struct rspamd_task *task, - struct suffix_item *suffix, const gchar *rule, GTree *tree) + struct suffix_item *suffix, const gchar *rule, GTree *tree) { - gint s = -1; - struct redirector_param *param; - struct timeval *timeout; - struct redirector_upstream *selected; - - selected = (struct redirector_upstream *)get_upstream_round_robin (surbl_module_ctx->redirectors, - surbl_module_ctx->redirectors_number, - sizeof (struct redirector_upstream), - task->tv.tv_sec, DEFAULT_UPSTREAM_ERROR_TIME, - DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + gint s = -1; + struct redirector_param *param; + struct timeval *timeout; + struct redirector_upstream *selected; + + selected = (struct redirector_upstream *)get_upstream_round_robin ( + surbl_module_ctx->redirectors, + surbl_module_ctx->redirectors_number, + sizeof (struct redirector_upstream), + task->tv.tv_sec, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected) { - s = make_universal_socket (selected->addr, selected->port, SOCK_STREAM, TRUE, FALSE, FALSE); + s = make_universal_socket (selected->addr, + selected->port, + SOCK_STREAM, + TRUE, + FALSE, + FALSE); } if (s == -1) { - msg_info ("<%s> cannot create tcp socket failed: %s", task->message_id, strerror (errno)); + msg_info ("<%s> cannot create tcp socket failed: %s", + task->message_id, + strerror (errno)); make_surbl_requests (url, task, suffix, FALSE, tree); return; } - param = rspamd_mempool_alloc (task->task_pool, sizeof (struct redirector_param)); + param = + rspamd_mempool_alloc (task->task_pool, + sizeof (struct redirector_param)); param->url = url; param->task = task; param->state = STATE_CONNECT; @@ -836,25 +1035,33 @@ register_redirector_call (struct uri *url, struct rspamd_task *task, param->tree = tree; timeout = rspamd_mempool_alloc (task->task_pool, sizeof (struct timeval)); timeout->tv_sec = surbl_module_ctx->connect_timeout / 1000; - timeout->tv_usec = (surbl_module_ctx->connect_timeout - timeout->tv_sec * 1000) * 1000; + timeout->tv_usec = + (surbl_module_ctx->connect_timeout - timeout->tv_sec * 1000) * 1000; event_set (¶m->ev, s, EV_WRITE, redirector_callback, (void *)param); event_add (¶m->ev, timeout); - register_async_event (task->s, free_redirector_session, param, g_quark_from_static_string ("surbl")); - - msg_info ("<%s> registered redirector call for %s to %s, according to rule: %s", - task->message_id, struri (url), selected->name, rule); + register_async_event (task->s, + free_redirector_session, + param, + g_quark_from_static_string ("surbl")); + + msg_info ( + "<%s> registered redirector call for %s to %s, according to rule: %s", + task->message_id, + struri (url), + selected->name, + rule); } -static gboolean +static gboolean surbl_tree_url_callback (gpointer key, gpointer value, void *data) { - struct redirector_param *param = data; - struct rspamd_task *task; - struct uri *url = value; - gchar *red_domain; - const gchar *pos; - GRegex *re; - guint idx, len; + struct redirector_param *param = data; + struct rspamd_task *task; + struct uri *url = value; + gchar *red_domain; + const gchar *pos; + GRegex *re; + guint idx, len; task = param->task; debug_task ("check url %s", struri (url)); @@ -866,32 +1073,48 @@ surbl_tree_url_callback (gpointer key, gpointer value, void *data) if (surbl_module_ctx->use_redirector) { /* Search in trie */ if (surbl_module_ctx->redirector_trie && - (pos = rspamd_trie_lookup (surbl_module_ctx->redirector_trie, url->host, url->hostlen, &idx)) != NULL && - idx < surbl_module_ctx->redirector_ptrs->len) { + (pos = + rspamd_trie_lookup (surbl_module_ctx->redirector_trie, url->host, + url->hostlen, &idx)) != NULL && + idx < surbl_module_ctx->redirector_ptrs->len) { /* Get corresponding prefix */ - red_domain = g_ptr_array_index (surbl_module_ctx->redirector_ptrs, idx); + red_domain = g_ptr_array_index (surbl_module_ctx->redirector_ptrs, + idx); if (red_domain != NULL) { len = strlen (red_domain); /* First check that we have found domain at the end of host */ if (pos + len == url->host + url->hostlen && (pos == url->host || *(pos - 1) == '.')) { /* Try to find corresponding regexp */ - re = g_hash_table_lookup (surbl_module_ctx->redirector_hosts, red_domain); - if (re != NULL && (re == NO_REGEXP || g_regex_match (re, url->string, 0, NULL))) { + re = g_hash_table_lookup ( + surbl_module_ctx->redirector_hosts, + red_domain); + if (re != NULL && + (re == NO_REGEXP || + g_regex_match (re, url->string, 0, NULL))) { /* If no regexp found or founded regexp matches url string register redirector's call */ if (surbl_module_ctx->redirector_symbol != NULL) { - insert_result (param->task, surbl_module_ctx->redirector_symbol, 1, g_list_prepend (NULL, red_domain)); + insert_result (param->task, + surbl_module_ctx->redirector_symbol, + 1, + g_list_prepend (NULL, red_domain)); } - register_redirector_call (url, param->task, param->suffix, red_domain, param->tree); + register_redirector_call (url, + param->task, + param->suffix, + red_domain, + param->tree); return FALSE; } } } } - make_surbl_requests (url, param->task, param->suffix, FALSE, param->tree); + make_surbl_requests (url, param->task, param->suffix, FALSE, + param->tree); } else { - make_surbl_requests (url, param->task, param->suffix, FALSE, param->tree); + make_surbl_requests (url, param->task, param->suffix, FALSE, + param->tree); } return FALSE; @@ -900,13 +1123,15 @@ surbl_tree_url_callback (gpointer key, gpointer value, void *data) static void surbl_test_url (struct rspamd_task *task, void *user_data) { - struct redirector_param param; - struct suffix_item *suffix = user_data; + struct redirector_param param; + struct suffix_item *suffix = user_data; param.task = task; param.suffix = suffix; param.tree = g_tree_new ((GCompareFunc)strcmp); - rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)g_tree_destroy, param.tree); + rspamd_mempool_add_destructor (task->task_pool, + (rspamd_mempool_destruct_t)g_tree_destroy, + param.tree); g_tree_foreach (task->urls, surbl_tree_url_callback, ¶m); } /* @@ -914,17 +1139,17 @@ surbl_test_url (struct rspamd_task *task, void *user_data) */ #if 0 struct urls_tree_cb_data { - gchar *buf; - gsize len; - gsize off; - struct rspamd_task *task; + gchar *buf; + gsize len; + gsize off; + struct rspamd_task *task; }; static gboolean calculate_buflen_cb (gpointer key, gpointer value, gpointer cbdata) { - struct urls_tree_cb_data *cb = cbdata; - struct uri *url = value; + struct urls_tree_cb_data *cb = cbdata; + struct uri *url = value; cb->len += strlen (struri (url)) + url->hostlen + sizeof (" <\"\">, ") - 1; @@ -934,23 +1159,30 @@ calculate_buflen_cb (gpointer key, gpointer value, gpointer cbdata) static gboolean write_urls_buffer (gpointer key, gpointer value, gpointer cbdata) { - struct urls_tree_cb_data *cb = cbdata; - struct uri *url = value; - f_str_t f; - gchar *urlstr; - gsize len; + struct urls_tree_cb_data *cb = cbdata; + struct uri *url = value; + f_str_t f; + gchar *urlstr; + gsize len; f.begin = url->host; f.len = url->hostlen; - if ((urlstr = format_surbl_request (cb->task->task_pool, &f, NULL, FALSE, NULL, FALSE)) != NULL) { + if ((urlstr = + format_surbl_request (cb->task->task_pool, &f, NULL, FALSE, NULL, + FALSE)) != NULL) { len = strlen (urlstr); if (cb->off + len >= cb->len) { - msg_info ("cannot write urls header completely, stripped reply at: %z", cb->off); + msg_info ( + "cannot write urls header completely, stripped reply at: %z", + cb->off); return TRUE; } else { - cb->off += rspamd_snprintf (cb->buf + cb->off, cb->len - cb->off, " %s <\"%s\">,", - urlstr, struri (url)); + cb->off += rspamd_snprintf (cb->buf + cb->off, + cb->len - cb->off, + " %s <\"%s\">,", + urlstr, + struri (url)); } } @@ -961,7 +1193,7 @@ write_urls_buffer (gpointer key, gpointer value, gpointer cbdata) static gboolean urls_command_handler (struct rspamd_task *task) { - struct urls_tree_cb_data cb; + struct urls_tree_cb_data cb; /* First calculate buffer length */ cb.len = sizeof (RSPAMD_REPLY_BANNER "/1.0 0 " SPAMD_OK CRLF "Urls: " CRLF); @@ -969,9 +1201,12 @@ urls_command_handler (struct rspamd_task *task) g_tree_foreach (task->urls, calculate_buflen_cb, &cb); cb.buf = rspamd_mempool_alloc (task->task_pool, cb.len * sizeof (gchar)); - cb.off += rspamd_snprintf (cb.buf + cb.off, cb.len - cb.off, "%s/%s 0 %s" CRLF "Urls:", - (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, - "1.3", SPAMD_OK); + cb.off += rspamd_snprintf (cb.buf + cb.off, + cb.len - cb.off, + "%s/%s 0 %s" CRLF "Urls:", + (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, + "1.3", + SPAMD_OK); cb.task = task; /* Write urls to buffer */ @@ -982,10 +1217,12 @@ urls_command_handler (struct rspamd_task *task) cb.buf[--cb.off] = '\0'; } /* Write result */ - if (! rspamd_dispatcher_write (task->dispatcher, cb.buf, cb.off, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (task->dispatcher, cb.buf, cb.off, FALSE, + TRUE)) { return FALSE; } - if (!rspamd_dispatcher_write (task->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (task->dispatcher, CRLF, sizeof (CRLF) - 1, + FALSE, TRUE)) { return FALSE; } task->state = STATE_REPLY; @@ -994,5 +1231,5 @@ urls_command_handler (struct rspamd_task *task) } #endif /* - * vi:ts=4 + * vi:ts=4 */ |