diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libmime/scan_result.c | 48 | ||||
-rw-r--r-- | src/libserver/cfg_file.h | 1 | ||||
-rw-r--r-- | src/libserver/cfg_rcl.cxx | 18 | ||||
-rw-r--r-- | src/libserver/cfg_utils.cxx | 2 | ||||
-rw-r--r-- | src/libserver/milter.c | 8 | ||||
-rw-r--r-- | src/libserver/protocol.c | 19 | ||||
-rw-r--r-- | src/libserver/protocol_internal.h | 1 | ||||
-rw-r--r-- | src/lua/lua_config.c | 2 | ||||
-rw-r--r-- | src/lua/lua_redis.c | 23 | ||||
-rw-r--r-- | src/plugins/fuzzy_check.c | 2 | ||||
-rw-r--r-- | src/plugins/lua/once_received.lua | 103 | ||||
-rw-r--r-- | src/rspamadm/configdump.c | 5 | ||||
-rw-r--r-- | src/rspamd_proxy.c | 10 |
13 files changed, 133 insertions, 109 deletions
diff --git a/src/libmime/scan_result.c b/src/libmime/scan_result.c index f15290b95..894ae4f9e 100644 --- a/src/libmime/scan_result.c +++ b/src/libmime/scan_result.c @@ -201,16 +201,34 @@ rspamd_check_group_score(struct rspamd_task *task, double *group_score, double w) { - if (gr != NULL && group_score && gr->max_score > 0.0 && w > 0.0) { - if (*group_score >= gr->max_score && w > 0) { + double group_limit = NAN; + + if (gr != NULL && group_score) { + if ((*group_score + w) >= 0 && !isnan(gr->max_score) && gr->max_score > 0) { + group_limit = gr->max_score; + } + else if ((*group_score + w) < 0 && !isnan(gr->min_score) && gr->min_score < 0) { + group_limit = -gr->min_score; + } + } + + if (gr != NULL && group_limit && !isnan(group_limit)) { + if (fabs(*group_score) >= group_limit && signbit(*group_score) == signbit(w)) { + /* Cannot add more to the group */ msg_info_task("maximum group score %.2f for group %s has been reached," " ignoring symbol %s with weight %.2f", - gr->max_score, + group_limit, gr->name, symbol, w); return NAN; } - else if (*group_score + w > gr->max_score) { - w = gr->max_score - *group_score; + else if (fabs(*group_score + w) > group_limit) { + /* Reduce weight */ + double new_w = signbit(w) ? -group_limit - *group_score : group_limit - *group_score; + msg_info_task("maximum group score %.2f for group %s has been reached," + " reduce weight of symbol %s from %.2f to %.2f", + group_limit, + gr->name, symbol, w, new_w); + w = new_w; } } @@ -393,15 +411,7 @@ insert_metric_result(struct rspamd_task *task, } else if (gr_score) { *gr_score += cur_diff; - - if (cur_diff < diff) { - /* Reduce */ - msg_debug_metric( - "group limit %.2f is reached for %s when inserting symbol %s;" - " reduce score %.2f - %.2f", - *gr_score, gr->name, symbol, diff, cur_diff); - diff = cur_diff; - } + diff = cur_diff; } } } @@ -461,15 +471,7 @@ insert_metric_result(struct rspamd_task *task, } else if (gr_score) { *gr_score += cur_score; - - if (cur_score < final_score) { - /* Reduce */ - msg_debug_metric( - "group limit %.2f is reached for %s when inserting symbol %s;" - " reduce score %.2f - %.2f", - *gr_score, gr->name, symbol, final_score, cur_score); - final_score = cur_score; - } + final_score = cur_score; } } } diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h index 1ba1d84ad..fa784f2a2 100644 --- a/src/libserver/cfg_file.h +++ b/src/libserver/cfg_file.h @@ -102,6 +102,7 @@ struct rspamd_symbols_group { char *description; GHashTable *symbols; double max_score; + double min_score; unsigned int flags; }; diff --git a/src/libserver/cfg_rcl.cxx b/src/libserver/cfg_rcl.cxx index 8a479fa6d..9b6e759bb 100644 --- a/src/libserver/cfg_rcl.cxx +++ b/src/libserver/cfg_rcl.cxx @@ -420,6 +420,18 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj, return FALSE; } + if (!std::isnan(gr->max_score) && gr->max_score < 0) { + msg_err_config("group %s has negative max_score which is broken, use min_score if required", gr->name); + + return FALSE; + } + if (!std::isnan(gr->min_score) && gr->min_score > 0) { + msg_err_config("group %s has positive min_score which is broken, use max_score if required", gr->name); + + return FALSE; + } + + if (const auto *elt = ucl_object_lookup(obj, "one_shot"); elt != nullptr) { if (ucl_object_type(elt) != UCL_BOOLEAN) { g_set_error(err, @@ -2349,6 +2361,12 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections) G_STRUCT_OFFSET(struct rspamd_symbols_group, max_score), 0, "Maximum score that could be reached by this symbols group"); + rspamd_rcl_add_default_handler(sub, + "min_score", + rspamd_rcl_parse_struct_double, + G_STRUCT_OFFSET(struct rspamd_symbols_group, min_score), + 0, + "Maximum negative score that could be reached by this symbols group"); } if (!(skip_sections && g_hash_table_lookup(skip_sections, "worker"))) { diff --git a/src/libserver/cfg_utils.cxx b/src/libserver/cfg_utils.cxx index 1344bc4f9..d8696e72d 100644 --- a/src/libserver/cfg_utils.cxx +++ b/src/libserver/cfg_utils.cxx @@ -1052,6 +1052,8 @@ rspamd_config_new_group(struct rspamd_config *cfg, const char *name) rspamd_mempool_add_destructor(cfg->cfg_pool, (rspamd_mempool_destruct_t) g_hash_table_unref, gr->symbols); gr->name = rspamd_mempool_strdup(cfg->cfg_pool, name); + gr->max_score = NAN; + gr->min_score = NAN; if (strcmp(gr->name, "ungrouped") == 0) { gr->flags |= RSPAMD_SYMBOL_GROUP_UNGROUPED; diff --git a/src/libserver/milter.c b/src/libserver/milter.c index f35278a0e..94b0d6cc1 100644 --- a/src/libserver/milter.c +++ b/src/libserver/milter.c @@ -1465,10 +1465,16 @@ rspamd_milter_macro_http(struct rspamd_milter_session *session, return; } + /* + * When we get a queue-id we try to pass it to the backend, where possible + * We also need that for logging consistency + */ IF_MACRO("{i}") { rspamd_http_message_add_header_len(msg, QUEUE_ID_HEADER, found->begin, found->len); + rspamd_http_message_add_header_len(msg, LOG_TAG_HEADER, + found->begin, found->len); } else { @@ -1476,6 +1482,8 @@ rspamd_milter_macro_http(struct rspamd_milter_session *session, { rspamd_http_message_add_header_len(msg, QUEUE_ID_HEADER, found->begin, found->len); + rspamd_http_message_add_header_len(msg, LOG_TAG_HEADER, + found->begin, found->len); } } diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index db83b0bfb..ee2192913 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -660,9 +660,9 @@ rspamd_protocol_handle_headers(struct rspamd_task *task, IF_HEADER(USER_HEADER) { /* - * We must ignore User header in case of spamc, as SA has - * different meaning of this header - */ + * We must ignore User header in case of spamc, as SA has + * different meaning of this header + */ msg_debug_protocol("read user header, value: %T", hv_tok); if (!RSPAMD_TASK_IS_SPAMC(task)) { task->auth_user = rspamd_mempool_ftokdup(task->task_pool, @@ -708,6 +708,15 @@ rspamd_protocol_handle_headers(struct rspamd_task *task, task->flags |= RSPAMD_TASK_FLAG_NO_LOG; } } + IF_HEADER(LOG_TAG_HEADER) + { + msg_debug_protocol("read log-tag header, value: %T", hv_tok); + /* Ensure that a tag is valid */ + if (rspamd_fast_utf8_validate(hv_tok->begin, hv_tok->len) == 0) { + memcpy(task->task_pool->tag.uid, hv_tok->begin, + MIN(hv_tok->len, sizeof(task->task_pool->tag.uid))); + } + } break; case 'm': case 'M': @@ -752,9 +761,9 @@ rspamd_protocol_handle_headers(struct rspamd_task *task, default: msg_debug_protocol("generic header: %T", hn_tok); break; - } + } - rspamd_task_add_request_header (task, hn_tok, hv_tok); + rspamd_task_add_request_header (task, hn_tok, hv_tok); } }); /* End of kh_foreach_value */ diff --git a/src/libserver/protocol_internal.h b/src/libserver/protocol_internal.h index 7a70ccef0..e55e54851 100644 --- a/src/libserver/protocol_internal.h +++ b/src/libserver/protocol_internal.h @@ -78,6 +78,7 @@ extern "C" { #define HOSTNAME_HEADER "Hostname" #define DELIVER_TO_HEADER "Deliver-To" #define NO_LOG_HEADER "Log" +#define LOG_TAG_HEADER "Log-Tag" #define MLEN_HEADER "Message-Length" #define USER_AGENT_HEADER "User-Agent" #define MTA_TAG_HEADER "MTA-Tag" diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c index f9a79eef1..717aa81ce 100644 --- a/src/lua/lua_config.c +++ b/src/lua/lua_config.c @@ -3933,6 +3933,8 @@ lua_config_get_groups(lua_State *L) lua_setfield(L, -2, "description"); lua_pushnumber(L, gr->max_score); lua_setfield(L, -2, "max_score"); + lua_pushnumber(L, gr->min_score); + lua_setfield(L, -2, "min_score"); lua_pushboolean(L, (gr->flags & RSPAMD_SYMBOL_GROUP_PUBLIC) != 0); lua_setfield(L, -2, "is_public"); /* TODO: maybe push symbols as well */ diff --git a/src/lua/lua_redis.c b/src/lua/lua_redis.c index f95abb577..d20c496ed 100644 --- a/src/lua/lua_redis.c +++ b/src/lua/lua_redis.c @@ -104,7 +104,7 @@ struct lua_redis_userdata { char *server; char log_tag[RSPAMD_LOG_ID_LEN + 1]; struct lua_redis_request_specific_userdata *specific; - double timeout; + ev_tstamp timeout; uint16_t port; uint16_t terminated; }; @@ -280,16 +280,23 @@ lua_redis_fin(void *arg) * @param code * @param ud */ +#ifdef __GNUC__ +__attribute__((format(printf, 1, 5))) +#endif static void lua_redis_push_error(const char *err, struct lua_redis_ctx *ctx, struct lua_redis_request_specific_userdata *sp_ud, - gboolean connected) + gboolean connected, + ...) { struct lua_redis_userdata *ud = sp_ud->c; struct lua_callback_state cbs; lua_State *L; + va_list ap; + va_start(ap, connected); + if (!(sp_ud->flags & (LUA_REDIS_SPECIFIC_REPLIED | LUA_REDIS_SPECIFIC_FINISHED))) { if (sp_ud->cbref != -1) { @@ -302,7 +309,7 @@ lua_redis_push_error(const char *err, lua_rawgeti(cbs.L, LUA_REGISTRYINDEX, sp_ud->cbref); /* String of error */ - lua_pushstring(cbs.L, err); + lua_pushvfstring(cbs.L, err, ap); /* Data is nil */ lua_pushnil(cbs.L); @@ -331,6 +338,8 @@ lua_redis_push_error(const char *err, lua_redis_fin(sp_ud); } } + + va_end(ap); } static void @@ -479,7 +488,7 @@ lua_redis_callback(redisAsyncContext *c, gpointer r, gpointer priv) lua_redis_push_data(reply, ctx, sp_ud); } else { - lua_redis_push_error(reply->str, ctx, sp_ud, TRUE); + lua_redis_push_error("%s", ctx, sp_ud, TRUE, reply->str); } } else { @@ -488,10 +497,10 @@ lua_redis_callback(redisAsyncContext *c, gpointer r, gpointer priv) } else { if (c->err == REDIS_ERR_IO) { - lua_redis_push_error(strerror(errno), ctx, sp_ud, TRUE); + lua_redis_push_error("%s", ctx, sp_ud, TRUE, strerror(errno)); } else { - lua_redis_push_error(c->errstr, ctx, sp_ud, TRUE); + lua_redis_push_error("%s", ctx, sp_ud, TRUE, c->errstr); } } } @@ -750,7 +759,7 @@ lua_redis_timeout(EV_P_ ev_timer *w, int revents) REDIS_RETAIN(ctx); msg_debug_lua_redis("timeout while querying redis server: %p, redis: %p", sp_ud, sp_ud->c->ctx); - lua_redis_push_error("timeout while connecting the server", ctx, sp_ud, TRUE); + lua_redis_push_error("timeout while connecting the server (%.2f sec)", ctx, sp_ud, TRUE, ud->timeout); if (sp_ud->c->ctx) { ac = sp_ud->c->ctx; diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index a035eeaae..b92177f1b 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -2299,6 +2299,8 @@ fuzzy_insert_result(struct fuzzy_client_session *session, * Otherwise `value` means error code */ + msg_debug_fuzzy_check("got reply with probability %.2f and value %.2f", + (double) rep->v1.prob, (double) rep->v1.value); nval = fuzzy_normalize(rep->v1.value, weight); if (io) { diff --git a/src/plugins/lua/once_received.lua b/src/plugins/lua/once_received.lua index 2a5552ab9..5c5ff7986 100644 --- a/src/plugins/lua/once_received.lua +++ b/src/plugins/lua/once_received.lua @@ -19,10 +19,7 @@ if confighelp then end -- 0 or 1 received: = spam - local symbol = 'ONCE_RECEIVED' -local symbol_rdns = 'RDNS_NONE' -local symbol_rdns_dnsfail = 'RDNS_DNSFAIL' local symbol_mx = 'DIRECT_TO_MX' -- Symbol for strict checks local symbol_strict = nil @@ -47,54 +44,6 @@ local function check_quantity_received (task) return not h['flags']['artificial'] end, recvh)) - local function recv_dns_cb(_, to_resolve, results, err) - if err and (err ~= 'requested record is not found' and err ~= 'no records with this name') then - rspamd_logger.errx(task, 'error looking up %s: %s', to_resolve, err) - task:insert_result(symbol_rdns_dnsfail, 1.0) - end - - if not results then - if nreceived <= 1 then - task:insert_result(symbol, 1) - -- Avoid strict symbol inserting as the remaining symbols have already - -- quote a significant weight, so a message could be rejected by just - -- this property. - --task:insert_result(symbol_strict, 1) - -- Check for MUAs - local ua = task:get_header('User-Agent') - local xm = task:get_header('X-Mailer') - if (ua or xm) then - task:insert_result(symbol_mx, 1, (ua or xm)) - end - end - task:insert_result(symbol_rdns, 1) - else - rspamd_logger.infox(task, 'source hostname has not been passed to Rspamd from MTA, ' .. - 'but we could resolve source IP address PTR %s as "%s"', - to_resolve, results[1]) - task:set_hostname(results[1]) - - if good_hosts then - for _, gh in ipairs(good_hosts) do - if string.find(results[1], gh) then - return - end - end - end - - if nreceived <= 1 then - task:insert_result(symbol, 1) - for _, h in ipairs(bad_hosts) do - if string.find(results[1], h) then - - task:insert_result(symbol_strict, 1, h) - return - end - end - end - end - end - local task_ip = task:get_ip() if ((not check_authed and task:get_user()) or @@ -110,13 +59,39 @@ local function check_quantity_received (task) local hn = task:get_hostname() -- Here we don't care about received - if (not hn) and task_ip and task_ip:is_valid() then - task:get_resolver():resolve_ptr({ task = task, - name = task_ip:to_string(), - callback = recv_dns_cb, - forced = true - }) + if not hn then + if nreceived <= 1 then + task:insert_result(symbol, 1) + -- Avoid strict symbol inserting as the remaining symbols have already + -- quote a significant weight, so a message could be rejected by just + -- this property. + --task:insert_result(symbol_strict, 1) + -- Check for MUAs + local ua = task:get_header('User-Agent') + local xm = task:get_header('X-Mailer') + if (ua or xm) then + task:insert_result(symbol_mx, 1, (ua or xm)) + end + end return + else + if good_hosts then + for _, gh in ipairs(good_hosts) do + if string.find(hn, gh) then + return + end + end + end + + if nreceived <= 1 then + task:insert_result(symbol, 1) + for _, h in ipairs(bad_hosts) do + if string.find(hn, h) then + task:insert_result(symbol_strict, 1, h) + break + end + end + end end if nreceived <= 1 then @@ -181,10 +156,6 @@ if opts then for n, v in pairs(opts) do if n == 'symbol_strict' then symbol_strict = v - elseif n == 'symbol_rdns' then - symbol_rdns = v - elseif n == 'symbol_rdns_dnsfail' then - symbol_rdns_dnsfail = v elseif n == 'bad_host' then if type(v) == 'string' then bad_hosts[1] = v @@ -207,16 +178,6 @@ if opts then end rspamd_config:register_symbol({ - name = symbol_rdns, - type = 'virtual', - parent = id - }) - rspamd_config:register_symbol({ - name = symbol_rdns_dnsfail, - type = 'virtual', - parent = id - }) - rspamd_config:register_symbol({ name = symbol_strict, type = 'virtual', parent = id diff --git a/src/rspamadm/configdump.c b/src/rspamadm/configdump.c index 167b4c891..456875cf2 100644 --- a/src/rspamadm/configdump.c +++ b/src/rspamadm/configdump.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 Vsevolod Stakhov + * Copyright 2024 Vsevolod Stakhov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -445,6 +445,9 @@ rspamadm_configdump(int argc, char **argv, const struct rspamadm_command *cmd) ucl_object_fromdouble(gr->max_score), "max_score", strlen("max_score"), false); ucl_object_insert_key(gr_ucl, + ucl_object_fromdouble(gr->min_score), + "min_score", strlen("min_score"), false); + ucl_object_insert_key(gr_ucl, ucl_object_fromstring(gr->description), "description", strlen("description"), false); diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c index 4f08e81b9..6c8869e22 100644 --- a/src/rspamd_proxy.c +++ b/src/rspamd_proxy.c @@ -1398,7 +1398,8 @@ proxy_backend_mirror_finish_handler(struct rspamd_http_connection *conn, bk_conn->err = "cannot parse ucl"; } - msg_info_session("finished mirror connection to %s", bk_conn->name); + msg_info_session("finished mirror connection to %s; HTTP code: %d", + bk_conn->name, msg->code); rspamd_upstream_ok(bk_conn->up); proxy_backend_close_connection(bk_conn); @@ -2203,6 +2204,8 @@ proxy_client_finish_handler(struct rspamd_http_connection *conn, rspamd_http_message_remove_header(msg, "Keep-Alive"); rspamd_http_message_remove_header(msg, "Connection"); rspamd_http_message_remove_header(msg, "Key"); + rspamd_http_message_add_header_len(msg, LOG_TAG_HEADER, session->pool->tag.uid, + sizeof(session->pool->tag.uid)); proxy_open_mirror_connections(session); rspamd_http_connection_reset(session->client_conn); @@ -2210,7 +2213,10 @@ proxy_client_finish_handler(struct rspamd_http_connection *conn, proxy_send_master_message(session); } else { - msg_info_session("finished master connection"); + msg_info_session("finished master connection to %s; HTTP code: %d", + rspamd_inet_address_to_string_pretty( + rspamd_upstream_addr_cur(session->master_conn->up)), + msg->code); proxy_backend_close_connection(session->master_conn); REF_RELEASE(session); } |