From 51855128c784d0b70c29af1c9a5ca0915ad50354 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 31 Oct 2024 13:29:12 +0000 Subject: [Test] A workaround for brain-damaged libstdc++ from prehistoric ages --- test/rspamd_cxx_unit_cryptobox.hxx | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/test/rspamd_cxx_unit_cryptobox.hxx b/test/rspamd_cxx_unit_cryptobox.hxx index 18ccd98ce..7d9c76b4e 100644 --- a/test/rspamd_cxx_unit_cryptobox.hxx +++ b/test/rspamd_cxx_unit_cryptobox.hxx @@ -21,7 +21,23 @@ #include "libcryptobox/cryptobox.h" #include #include -#include +#include +#include + +namespace std// NOLINT(cert-dcl58-cpp) +{ +template +ostream &operator<<(ostream &stream, const vector &in) +{ + stream << "["; + for (size_t i = 0; i < in.size(); ++i) { + if (i != 0) { stream << ", "; } + stream << in[i]; + } + stream << "]"; + return stream; +} +}// namespace std TEST_SUITE("rspamd_cryptobox") { @@ -190,10 +206,10 @@ TEST_SUITE("rspamd_cryptobox") const char *pk = "k4nz984k36xmcynm1hr9kdbn6jhcxf4ggbrb1quay7f88rpm9kay"; gsize outlen; auto *pk_decoded = rspamd_decode_base32(pk, strlen(pk), &outlen, RSPAMD_BASE32_DEFAULT); - const unsigned char expected[32] = {95, 76, 225, 188, 0, 26, 146, 94, 70, 249, - 90, 189, 35, 51, 1, 42, 9, 37, 94, 254, 204, 55, 198, 91, 180, 90, - 46, 217, 140, 226, 211, 90}; - const auto expected_arr = std::to_array(expected); + unsigned char expected[32] = {95, 76, 225, 188, 0, 26, 146, 94, 70, 249, + 90, 189, 35, 51, 1, 42, 9, 37, 94, 254, 204, 55, 198, 91, 180, 90, + 46, 217, 140, 226, 211, 90}; + const auto expected_arr = std::vector(std::begin(expected), std::end(expected)); CHECK(outlen == 32); unsigned char out[32]; @@ -202,7 +218,7 @@ TEST_SUITE("rspamd_cryptobox") sk[31] &= 127; sk[31] |= 64; CHECK(crypto_scalarmult(out, sk, pk_decoded) != -1); - auto out_arr = std::to_array(out); + auto out_arr = std::vector(std::begin(out), std::end(out)); CHECK(out_arr == expected_arr); } @@ -217,16 +233,16 @@ TEST_SUITE("rspamd_cryptobox") const char *pk = "k4nz984k36xmcynm1hr9kdbn6jhcxf4ggbrb1quay7f88rpm9kay"; gsize outlen; auto *pk_decoded = rspamd_decode_base32(pk, strlen(pk), &outlen, RSPAMD_BASE32_DEFAULT); - const unsigned char expected[32] = {61, 109, 220, 195, 100, 174, 127, 237, 148, - 122, 154, 61, 165, 83, 93, 105, 127, 166, 153, 112, 103, 224, 2, 200, - 136, 243, 73, 51, 8, 163, 150, 7}; - const auto expected_arr = std::to_array(expected); + unsigned char expected[32] = {61, 109, 220, 195, 100, 174, 127, 237, 148, + 122, 154, 61, 165, 83, 93, 105, 127, 166, 153, 112, 103, 224, 2, 200, + 136, 243, 73, 51, 8, 163, 150, 7}; + const auto expected_arr = std::vector(std::begin(expected), std::end(expected)); CHECK(outlen == 32); unsigned char out[32]; rspamd_cryptobox_nm(out, pk_decoded, sk); - auto out_arr = std::to_array(out); + auto out_arr = std::vector(std::begin(out), std::end(out)); CHECK(out_arr == expected_arr); } } -- cgit v1.2.3 From 80cb50dea482246656a49e54a915bdc343ffe897 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 1 Nov 2024 09:38:11 +0000 Subject: [Fix] Fix memory leak in `lua_new_text` invocations --- src/lua/lua_common.h | 5 ++--- src/lua/lua_compress.c | 12 +++++++----- src/lua/lua_text.c | 4 ++-- src/lua/lua_util.c | 11 +++++++++-- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h index 198735c66..1d39d0c52 100644 --- a/src/lua/lua_common.h +++ b/src/lua/lua_common.h @@ -94,8 +94,7 @@ static inline int lua_absindex(lua_State *L, int i) #define LUA_PUBLIC_FUNCTION_DEF(class, name) int lua_##class##_##name(lua_State *L) #define LUA_INTERFACE_DEF(class, name) \ { \ - #name, lua_##class##_##name \ - } + #name, lua_##class##_##name} extern const luaL_reg null_reg[]; @@ -281,7 +280,7 @@ struct rspamd_lua_text *lua_check_text_or_string(lua_State *L, int pos); * @return */ struct rspamd_lua_text *lua_new_text(lua_State *L, const char *start, - gsize len, gboolean own); + gsize len, gboolean allocate_memory); /** * Create new text object from task pool if allocation is needed * @param task diff --git a/src/lua/lua_compress.c b/src/lua/lua_compress.c index 4a348404c..c82394ed6 100644 --- a/src/lua/lua_compress.c +++ b/src/lua/lua_compress.c @@ -1,11 +1,11 @@ -/*- - * Copyright 2021 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. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -504,7 +504,8 @@ lua_zstd_compress_stream(lua_State *L) return lua_zstd_push_error(L, err); } - lua_new_text(L, onb.dst, onb.pos, TRUE); + t = lua_new_text(L, onb.dst, onb.pos, FALSE); + t->flags |= RSPAMD_TEXT_FLAG_OWN; return 1; } @@ -598,7 +599,8 @@ lua_zstd_decompress_stream(lua_State *L) return lua_zstd_push_error(L, err); } - lua_new_text(L, onb.dst, onb.pos, TRUE); + t = lua_new_text(L, onb.dst, onb.pos, FALSE); + t->flags |= RSPAMD_TEXT_FLAG_OWN; return 1; } diff --git a/src/lua/lua_text.c b/src/lua/lua_text.c index 4478314f1..3342fc95c 100644 --- a/src/lua/lua_text.c +++ b/src/lua/lua_text.c @@ -312,14 +312,14 @@ lua_check_text_or_string(lua_State *L, int pos) } struct rspamd_lua_text * -lua_new_text(lua_State *L, const char *start, gsize len, gboolean own) +lua_new_text(lua_State *L, const char *start, gsize len, gboolean allocate_memory) { struct rspamd_lua_text *t; t = lua_newuserdata(L, sizeof(*t)); t->flags = 0; - if (own) { + if (allocate_memory) { char *storage; if (len > 0) { diff --git a/src/lua/lua_util.c b/src/lua/lua_util.c index 92f831f6f..251d1e1e7 100644 --- a/src/lua/lua_util.c +++ b/src/lua/lua_util.c @@ -1025,7 +1025,12 @@ lua_util_encode_base64(lua_State *L) } if (out != NULL) { - lua_new_text(L, out, outlen, TRUE); + /* + * Manually set OWN flag, as `lua_new_text` will allocate another chunk of memory, + * and we will have memory leak of the memory allocated by `rspamd_encode_base64_fold` + */ + t = lua_new_text(L, out, outlen, FALSE); + t->flags = RSPAMD_TEXT_FLAG_OWN; } else { lua_pushnil(L); @@ -1650,7 +1655,9 @@ lua_util_transliterate(lua_State *L) gsize outlen; char *transliterated = rspamd_utf8_transliterate(t->start, t->len, &outlen); - lua_new_text(L, transliterated, outlen, TRUE); + + t = lua_new_text(L, transliterated, outlen, FALSE); + t->flags = RSPAMD_TEXT_FLAG_OWN; return 1; } -- cgit v1.2.3 From 76354f0668fae617940cdfb3a0625d072b8464e1 Mon Sep 17 00:00:00 2001 From: twesterhever <40121680+twesterhever@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:22:56 +0000 Subject: [Minor] Score *.rdp attachments as bad Rationale: https://www.microsoft.com/en-us/security/blog/2024/10/29/midnight-blizzard-conducts-large-scale-spear-phishing-campaign-using-rdp-files/ --- src/plugins/lua/mime_types.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/lua/mime_types.lua b/src/plugins/lua/mime_types.lua index ec8e566f2..c69fa1e7b 100644 --- a/src/plugins/lua/mime_types.lua +++ b/src/plugins/lua/mime_types.lua @@ -75,6 +75,7 @@ local settings = { mht = 2, mhtml = 2, oqy = 2, + rdp = 2, rqy = 2, sfx = 2, slk = 2, -- cgit v1.2.3 From 8c3f67a747221392680483b53f2bda27b30cb4b2 Mon Sep 17 00:00:00 2001 From: twesterhever <40121680+twesterhever@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:49:34 +0000 Subject: [Minor] Improve FREEMAIL_AFF catch rate This "Mail message body" Content-Description header appears to be a common quirk of advance fee fraud e-mails leveraging freemail services. --- conf/composites.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/composites.conf b/conf/composites.conf index 4fb97588f..c3669a675 100644 --- a/conf/composites.conf +++ b/conf/composites.conf @@ -165,7 +165,7 @@ composites { group = "scams"; } FREEMAIL_AFF { - expression = "(FREEMAIL_FROM | FREEMAIL_ENVFROM | FREEMAIL_REPLYTO | FREEMAIL_MDN) & (TO_DN_RECIPIENTS | R_UNDISC_RCPT) & (INTRODUCTION | FROM_NAME_HAS_TITLE | FREEMAIL_REPLYTO_NEQ_FROM_DOM | SUBJECT_HAS_CURRENCY)"; + expression = "(FREEMAIL_FROM | FREEMAIL_ENVFROM | FREEMAIL_REPLYTO | FREEMAIL_MDN) & (TO_DN_RECIPIENTS | R_UNDISC_RCPT | CD_MM_BODY) & (INTRODUCTION | FROM_NAME_HAS_TITLE | FREEMAIL_REPLYTO_NEQ_FROM_DOM | SUBJECT_HAS_CURRENCY)"; score = 4.0; policy = "leave"; description = "Message exhibits strong characteristics of advance fee fraud (AFF a/k/a '419' spam) involving freemail addresses"; -- cgit v1.2.3 From cb3bbb54eadf5e4148ffdad856ba4961c8a78118 Mon Sep 17 00:00:00 2001 From: twesterhever <40121680+twesterhever@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:59:22 +0000 Subject: [Minor] Add "User" HELO in Received headers to ABUSE_FROM_INJECTOR This pattern often surfaces in spam (frequently advance fee fraud) disseminated via compromised accounts, adding it to ABUSE_FROM_INJECTOR to increase the likelihood of such spam getting rejected. --- conf/composites.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/composites.conf b/conf/composites.conf index 4fb97588f..5a3585e10 100644 --- a/conf/composites.conf +++ b/conf/composites.conf @@ -191,7 +191,7 @@ composites { description = "Message authenticated, but from a suspicios origin (potentially an injector)"; } ABUSE_FROM_INJECTOR { - expression = "SUSPICIOUS_AUTH_ORIGIN & (FAKE_REPLY | HAS_IPFS_GATEWAY_URL | HTML_SHORT_LINK_IMG_1)"; + expression = "SUSPICIOUS_AUTH_ORIGIN & (RCVD_HELO_USER | FAKE_REPLY | HAS_IPFS_GATEWAY_URL | HTML_SHORT_LINK_IMG_1)"; score = 2.0; policy = "leave"; description = "Message is sent from a suspicios origin and showing signs of abuse, likely spam injected in compromised account"; -- cgit v1.2.3 From 3548785ebdc0e9a9aefc782c85bccb08456e8f3f Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 4 Nov 2024 16:03:34 +0000 Subject: [Fix] Another story about char sign Ragel still produces a wrong state machine if `const char *` is used for characters representation that are actually utf8. This PR changes all types to `unsigned char *` for consistency. --- src/ragel/smtp_addr_parser.rl | 18 ++++++------ test/lua/unit/smtp_addr.lua | 67 ++++++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/ragel/smtp_addr_parser.rl b/src/ragel/smtp_addr_parser.rl index b5b4863d3..330f3f01d 100644 --- a/src/ragel/smtp_addr_parser.rl +++ b/src/ragel/smtp_addr_parser.rl @@ -8,33 +8,33 @@ action IP4_end {} action User_start { - addr->user = p; + addr->user = (const char *)p; } action User_end { if (addr->user) { - addr->user_len = p - addr->user; + addr->user_len = (const char *)p - addr->user; } } action Domain_start { - addr->domain = p; + addr->domain = (const char *)p; } action Domain_end { if (addr->domain) { - addr->domain_len = p - addr->domain; + addr->domain_len = (const char *)p - addr->domain; } } action Domain_addr_start { - addr->domain = p; + addr->domain = (const char *)p; addr->flags |= RSPAMD_EMAIL_ADDR_IP; } action Domain_addr_end { if (addr->domain) { - addr->domain_len = p - addr->domain; + addr->domain_len = (const char *)p - addr->domain; } } @@ -64,12 +64,12 @@ } action Addr_start { - addr->addr = p; + addr->addr = (const char *)p; } action Addr_end { if (addr->addr) { - addr->addr_len = p - addr->addr; + addr->addr_len = (const char *)p - addr->addr; } } @@ -87,7 +87,7 @@ int rspamd_smtp_addr_parse (const char *data, size_t len, struct rspamd_email_address *addr) { - const char *p = data, *pe = data + len, *eof; + const unsigned char *p = (const unsigned char *)data, *pe = (const unsigned char *)data + len, *eof; int cs; g_assert (addr != NULL); diff --git a/test/lua/unit/smtp_addr.lua b/test/lua/unit/smtp_addr.lua index 2cb7755f8..ffabd838a 100644 --- a/test/lua/unit/smtp_addr.lua +++ b/test/lua/unit/smtp_addr.lua @@ -5,7 +5,7 @@ context("SMTP address check functions", function() local ffi = require("ffi") local util = require("rspamd_util") local fun = require "fun" - ffi.cdef[[ + ffi.cdef [[ struct rspamd_email_address { const char *raw; const char *addr; @@ -24,29 +24,30 @@ context("SMTP address check functions", function() ]] local cases_valid = { - {'<>', {addr = ''}}, - {'', {user = 'a', domain = 'example.com', addr = 'a@example.com'}}, - {'', {user = 'a-b', domain = 'example.com', addr = 'a-b@example.com'}}, - {'', {user = 'a-b', domain = 'ex-ample.com', addr = 'a-b@ex-ample.com'}}, - {'1367=dec2a6ce-81bd-4fa9-ad02-ec5956466c04=9=1655370@example.220-volt.ru', - {user = '1367=dec2a6ce-81bd-4fa9-ad02-ec5956466c04=9=1655370', - domain = 'example.220-volt.ru', - addr = '1367=dec2a6ce-81bd-4fa9-ad02-ec5956466c04=9=1655370@example.220-volt.ru'}}, - {'notification+kjdm---m7wwd@facebookmail.com', {user = 'notification+kjdm---m7wwd'}}, - {'a@example.com', {user = 'a', domain = 'example.com', addr = 'a@example.com'}}, - {'a+b@example.com', {user = 'a+b', domain = 'example.com', addr = 'a+b@example.com'}}, - {'"a"@example.com', {user = 'a', domain = 'example.com', addr = 'a@example.com'}}, - {'"a+b"@example.com', {user = 'a+b', domain = 'example.com', addr = 'a+b@example.com'}}, - {'"<>"@example.com', {user = '<>', domain = 'example.com', addr = '<>@example.com'}}, - {'<"<>"@example.com>', {user = '<>', domain = 'example.com', addr = '<>@example.com'}}, - {'"\\""@example.com', {user = '"', domain = 'example.com', addr = '"@example.com'}}, - {'"\\"abc"@example.com', {user = '"abc', domain = 'example.com', addr = '"abc@example.com'}}, - {'<@domain1,@domain2,@domain3:abc@example.com>', - {user = 'abc', domain = 'example.com', addr = 'abc@example.com'}}, + { '<>', { addr = '' } }, + { '', { user = 'a', domain = 'example.com', addr = 'a@example.com' } }, + { '', { user = 'a-b', domain = 'example.com', addr = 'a-b@example.com' } }, + { '', { user = 'a-b', domain = 'ex-ample.com', addr = 'a-b@ex-ample.com' } }, + { '1367=dec2a6ce-81bd-4fa9-ad02-ec5956466c04=9=1655370@example.220-volt.ru', + { user = '1367=dec2a6ce-81bd-4fa9-ad02-ec5956466c04=9=1655370', + domain = 'example.220-volt.ru', + addr = '1367=dec2a6ce-81bd-4fa9-ad02-ec5956466c04=9=1655370@example.220-volt.ru' } }, + { 'notification+kjdm---m7wwd@facebookmail.com', { user = 'notification+kjdm---m7wwd' } }, + { 'a@example.com', { user = 'a', domain = 'example.com', addr = 'a@example.com' } }, + { 'a+b@example.com', { user = 'a+b', domain = 'example.com', addr = 'a+b@example.com' } }, + { '"a"@example.com', { user = 'a', domain = 'example.com', addr = 'a@example.com' } }, + { '"a+b"@example.com', { user = 'a+b', domain = 'example.com', addr = 'a+b@example.com' } }, + { '"<>"@example.com', { user = '<>', domain = 'example.com', addr = '<>@example.com' } }, + { '<"<>"@example.com>', { user = '<>', domain = 'example.com', addr = '<>@example.com' } }, + { '"\\""@example.com', { user = '"', domain = 'example.com', addr = '"@example.com' } }, + { '"\\"abc"@example.com', { user = '"abc', domain = 'example.com', addr = '"abc@example.com' } }, + { '<@domain1,@domain2,@domain3:abc@example.com>', + { user = 'abc', domain = 'example.com', addr = 'abc@example.com' } }, + -- SMTP UTF8 + { 'ñ@example.com', { user = 'ñ', domain = 'example.com' } } } - fun.each(function(case) test("Parse valid smtp addr: " .. case[1], function() local st = ffi.C.rspamd_email_address_from_smtp(case[1], #case[1]) @@ -69,17 +70,17 @@ context("SMTP address check functions", function() end) end, cases_valid) - local cases_invalid = { - 'a', - 'a"b"@example.com', - 'a"@example.com', - '"a@example.com', - '', - '', - '>', - '<>', - } + local cases_invalid = { + 'a', + 'a"b"@example.com', + 'a"@example.com', + '"a@example.com', + '', + '', + '>', + '<>', + } fun.each(function(case) test("Parse invalid smtp addr: " .. case, function() @@ -95,7 +96,7 @@ context("SMTP address check functions", function() local niter = 100000 local total = 0 - for i = 1,niter do + for i = 1, niter do local ncase = string.format(case, i) local t1 = util.get_ticks() local st = ffi.C.rspamd_email_address_from_smtp(ncase, #ncase) -- cgit v1.2.3 From c99d053df77144d4cf8e7b276d674530e339c4f6 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 4 Nov 2024 16:11:44 +0000 Subject: [Test] Add more test --- test/lua/unit/smtp_addr.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/lua/unit/smtp_addr.lua b/test/lua/unit/smtp_addr.lua index ffabd838a..16f59d07c 100644 --- a/test/lua/unit/smtp_addr.lua +++ b/test/lua/unit/smtp_addr.lua @@ -44,7 +44,8 @@ context("SMTP address check functions", function() { '<@domain1,@domain2,@domain3:abc@example.com>', { user = 'abc', domain = 'example.com', addr = 'abc@example.com' } }, -- SMTP UTF8 - { 'ñ@example.com', { user = 'ñ', domain = 'example.com' } } + { 'ñ@example.com', { user = 'ñ', domain = 'example.com' } }, + { 'ñ@ололо.лол', { user = 'ñ', domain = 'ололо.лол' } } } -- cgit v1.2.3