Browse Source

[Project] Finish received headers rework part

tags/3.1
Vsevolod Stakhov 2 years ago
parent
commit
d79fdd8a40
4 changed files with 215 additions and 156 deletions
  1. 124
    16
      src/libmime/received.cxx
  2. 9
    29
      src/libmime/received.h
  3. 74
    1
      src/libmime/received.hxx
  4. 8
    110
      src/lua/lua_task.c

+ 124
- 16
src/libmime/received.cxx View File

@@ -17,6 +17,7 @@
#include <mempool_vars_internal.h>
#include "config.h"
#include "libserver/url.h"
#include "lua/lua_common.h"
#include "libserver/cfg_file.h"
#include "mime_string.hxx"
#include "smtp_parsers.h"
@@ -587,18 +588,24 @@ received_header_parse(struct rspamd_task *task, const std::string_view &in,
{
std::ptrdiff_t date_pos = -1;

static constexpr const auto protos_map = frozen::make_unordered_map<frozen::string, int>({
{"smtp", RSPAMD_RECEIVED_SMTP},
{"esmtp", RSPAMD_RECEIVED_ESMTP},
{"esmtpa", RSPAMD_RECEIVED_ESMTPA | RSPAMD_RECEIVED_FLAG_AUTHENTICATED},
{"esmtpsa", RSPAMD_RECEIVED_ESMTPSA | RSPAMD_RECEIVED_FLAG_SSL | RSPAMD_RECEIVED_FLAG_AUTHENTICATED},
{"esmtps", RSPAMD_RECEIVED_ESMTPS | RSPAMD_RECEIVED_FLAG_SSL},
{"lmtp", RSPAMD_RECEIVED_LMTP},
{"imap", RSPAMD_RECEIVED_IMAP},
{"imaps", RSPAMD_RECEIVED_IMAP | RSPAMD_RECEIVED_FLAG_SSL},
{"http", RSPAMD_RECEIVED_HTTP},
{"https", RSPAMD_RECEIVED_HTTP | RSPAMD_RECEIVED_FLAG_SSL},
{"local", RSPAMD_RECEIVED_LOCAL}
static constexpr const auto protos_map = frozen::make_unordered_map<frozen::string, received_flags>({
{"smtp", received_flags::SMTP},
{"esmtp", received_flags::ESMTP},
{"esmtpa", received_flags::ESMTPA |
received_flags::AUTHENTICATED},
{"esmtpsa", received_flags::ESMTPSA |
received_flags::SSL |
received_flags::AUTHENTICATED},
{"esmtps", received_flags::ESMTPS |
received_flags::SSL},
{"lmtp", received_flags::LMTP},
{"imap", received_flags::IMAP},
{"imaps", received_flags::IMAP |
received_flags::SSL},
{"http", received_flags::HTTP},
{"https", received_flags::HTTP |
received_flags::SSL},
{"local", received_flags::LOCAL}
});

auto parts = received_spill(task, in, date_pos);
@@ -617,7 +624,7 @@ received_header_parse(struct rspamd_task *task, const std::string_view &in,

auto &rh = recv_chain_ptr->new_received();

rh.flags = RSPAMD_RECEIVED_UNKNOWN;
rh.flags = received_flags::UNKNOWN;
rh.hdr = hdr;

for (const auto &part : parts) {
@@ -707,14 +714,14 @@ received_maybe_fix_task(struct rspamd_task *task) -> bool
" not ours, prepend it with fake one");

auto trecv = recv_chain_ptr->new_received(received_header_chain::append_type::append_head);
trecv.flags |= RSPAMD_RECEIVED_FLAG_ARTIFICIAL;
trecv.flags |= received_flags::ARTIFICIAL;

if (task->flags & RSPAMD_TASK_FLAG_SSL) {
trecv.flags |= RSPAMD_RECEIVED_FLAG_SSL;
trecv.flags |= received_flags::SSL;
}

if (task->user) {
trecv.flags |= RSPAMD_RECEIVED_FLAG_AUTHENTICATED;
trecv.flags |= received_flags::AUTHENTICATED;
}

trecv.real_ip.assign_copy(std::string_view(rspamd_inet_address_to_string(task->from_addr)));
@@ -761,6 +768,99 @@ received_maybe_fix_task(struct rspamd_task *task) -> bool
return false;
}

static auto
received_export_to_lua(received_header_chain *chain, lua_State *L) -> bool
{
if (chain == nullptr) {
return false;
}

lua_createtable(L, chain->size(), 0);

auto push_flag = [L](const received_header &rh, received_flags fl, const char *name) {
lua_pushboolean(L, !!(rh.flags & fl));
lua_setfield(L, -2, name);
};

auto i = 1;

for (const auto &rh : chain->as_vector()) {
lua_createtable (L, 0, 10);

if (rh.hdr && rh.hdr->decoded) {
rspamd_lua_table_set(L, "raw", rh.hdr->decoded);
}

lua_createtable(L, 0, 3);
push_flag(rh, received_flags::ARTIFICIAL, "artificial");
push_flag(rh, received_flags::AUTHENTICATED, "authenticated");
push_flag(rh, received_flags::SSL, "ssl");
lua_setfield(L, -2, "flags");

lua_pushlstring(L, rh.from_hostname.data(), rh.from_hostname.size());
lua_setfield(L, -2, "from_hostname");
lua_pushlstring(L, rh.real_hostname.data(), rh.real_hostname.size());
lua_setfield(L, -2, "real_hostname");
lua_pushlstring(L, rh.from_ip.data(), rh.from_ip.size());
lua_setfield(L, -2, "from_ip");
lua_pushlstring(L, rh.by_hostname.data(), rh.by_hostname.size());
lua_setfield(L, -2, "by_hostname");
lua_pushlstring(L, rh.for_mbox.data(), rh.for_mbox.size());
lua_setfield(L, -2, "for");

rspamd_lua_ip_push (L, rh.addr);
lua_setfield(L, -2, "real_ip");

const auto *proto = "unknown";

switch (received_type_apply_maks(rh.flags)) {
case received_flags::SMTP:
proto = "smtp";
break;
case received_flags::ESMTP:
proto = "esmtp";
break;
case received_flags::ESMTPS:
proto = "esmtps";
break;
case received_flags::ESMTPA:
proto = "esmtpa";
break;
case received_flags::ESMTPSA:
proto = "esmtpsa";
break;
case received_flags::LMTP:
proto = "lmtp";
break;
case received_flags::IMAP:
proto = "imap";
break;
case received_flags::HTTP:
proto = "http";
break;
case received_flags::LOCAL:
proto = "local";
break;
case received_flags::MAPI:
proto = "mapi";
break;
default:
proto = "unknown";
break;
}

lua_pushstring(L, proto);
lua_setfield(L, -2, "proto");

lua_pushinteger(L, rh.timestamp);
lua_setfield(L, -2, "timestamp");

lua_rawseti(L, -2, i++);
}

return true;
}

} // namespace rspamd::mime

bool
@@ -776,3 +876,11 @@ rspamd_received_maybe_fix_task(struct rspamd_task *task)
{
return rspamd::mime::received_maybe_fix_task(task);
}

bool
rspamd_received_export_to_lua(struct rspamd_task *task, lua_State *L)
{
return rspamd::mime::received_export_to_lua(
static_cast<rspamd::mime::received_header_chain *>(MESSAGE_FIELD(task, received_headers)),
L);
}

+ 9
- 29
src/libmime/received.h View File

@@ -28,35 +28,6 @@ extern "C" {
* C bindings for C++ received code
*/

enum rspamd_received_type {
RSPAMD_RECEIVED_SMTP = 1u << 0u,
RSPAMD_RECEIVED_ESMTP = 1u << 1u,
RSPAMD_RECEIVED_ESMTPA = 1u << 2u,
RSPAMD_RECEIVED_ESMTPS = 1u << 3u,
RSPAMD_RECEIVED_ESMTPSA = 1u << 4u,
RSPAMD_RECEIVED_LMTP = 1u << 5u,
RSPAMD_RECEIVED_IMAP = 1u << 6u,
RSPAMD_RECEIVED_LOCAL = 1u << 7u,
RSPAMD_RECEIVED_HTTP = 1u << 8u,
RSPAMD_RECEIVED_MAPI = 1u << 9u,
RSPAMD_RECEIVED_UNKNOWN = 1u << 10u,
RSPAMD_RECEIVED_FLAG_ARTIFICIAL = (1u << 11u),
RSPAMD_RECEIVED_FLAG_SSL = (1u << 12u),
RSPAMD_RECEIVED_FLAG_AUTHENTICATED = (1u << 13u),
};

#define RSPAMD_RECEIVED_FLAG_TYPE_MASK (RSPAMD_RECEIVED_SMTP| \
RSPAMD_RECEIVED_ESMTP| \
RSPAMD_RECEIVED_ESMTPA| \
RSPAMD_RECEIVED_ESMTPS| \
RSPAMD_RECEIVED_ESMTPSA| \
RSPAMD_RECEIVED_LMTP| \
RSPAMD_RECEIVED_IMAP| \
RSPAMD_RECEIVED_LOCAL| \
RSPAMD_RECEIVED_HTTP| \
RSPAMD_RECEIVED_MAPI| \
RSPAMD_RECEIVED_UNKNOWN)

struct rspamd_email_address;
struct rspamd_received_header_chain;
struct rspamd_mime_header;
@@ -80,6 +51,15 @@ bool rspamd_received_header_parse(struct rspamd_task *task,
*/
bool rspamd_received_maybe_fix_task(struct rspamd_task *task);

struct lua_State;
/**
* Push received headers chain to lua
* @param task
* @param L
* @return
*/
bool rspamd_received_export_to_lua(struct rspamd_task *task, struct lua_State *L);

#ifdef __cplusplus
}
#endif

+ 74
- 1
src/libmime/received.hxx View File

@@ -41,6 +41,73 @@ received_char_filter(UChar32 uc) -> UChar32
return 0;
}

enum class received_flags {
DEFAULT = 0,
SMTP = 1u << 0u,
ESMTP = 1u << 1u,
ESMTPA = 1u << 2u,
ESMTPS = 1u << 3u,
ESMTPSA = 1u << 4u,
LMTP = 1u << 5u,
IMAP = 1u << 6u,
LOCAL = 1u << 7u,
HTTP = 1u << 8u,
MAPI = 1u << 9u,
UNKNOWN = 1u << 10u,
ARTIFICIAL = (1u << 11u),
SSL = (1u << 12u),
AUTHENTICATED = (1u << 13u),
};

#define RSPAMD_RECEIVED_FLAG_TYPE_MASK (received_flags::SMTP| \
RSPAMD_RECEIVED_ESMTP| \
RSPAMD_RECEIVED_ESMTPA| \
RSPAMD_RECEIVED_ESMTPS| \
RSPAMD_RECEIVED_ESMTPSA| \
RSPAMD_RECEIVED_LMTP| \
RSPAMD_RECEIVED_IMAP| \
RSPAMD_RECEIVED_LOCAL| \
RSPAMD_RECEIVED_HTTP| \
RSPAMD_RECEIVED_MAPI| \
RSPAMD_RECEIVED_UNKNOWN)

constexpr received_flags operator |(received_flags lhs, received_flags rhs)
{
using ut = std::underlying_type<received_flags>::type;
return static_cast<received_flags>(static_cast<ut>(lhs) | static_cast<ut>(rhs));
}

constexpr received_flags operator |=(received_flags &lhs, const received_flags rhs)
{
using ut = std::underlying_type<received_flags>::type;
lhs = static_cast<received_flags>(static_cast<ut>(lhs) | static_cast<ut>(rhs));
return lhs;
}

constexpr received_flags operator &(received_flags lhs, received_flags rhs)
{
using ut = std::underlying_type<received_flags>::type;
return static_cast<received_flags>(static_cast<ut>(lhs) & static_cast<ut>(rhs));
}

constexpr bool operator !(received_flags fl)
{
return fl == received_flags::DEFAULT;
}

constexpr received_flags received_type_apply_maks(received_flags fl) {
return fl & (received_flags::SMTP|
received_flags::ESMTP|
received_flags::ESMTPA|
received_flags::ESMTPS|
received_flags::ESMTPSA|
received_flags::IMAP|
received_flags::HTTP|
received_flags::LOCAL|
received_flags::MAPI|
received_flags::LMTP);
}

struct received_header {
mime_string from_hostname;
std::string_view from_ip;
@@ -52,7 +119,7 @@ struct received_header {
rspamd_inet_addr_t *addr = nullptr;
struct rspamd_mime_header *hdr = nullptr;
time_t timestamp = 0;
int flags = 0; /* See enum rspamd_received_type */
received_flags flags = received_flags::DEFAULT; /* See enum rspamd_received_type */

received_header() noexcept
: from_hostname(received_char_filter),
@@ -99,6 +166,12 @@ public:

return std::nullopt;
}
constexpr auto size() const -> std::size_t {
return headers.size();
}
constexpr auto as_vector() const -> const std::vector<received_header>& {
return headers;
}
private:
static auto received_header_chain_pool_dtor(void *ptr) -> void {
delete static_cast<received_header_chain *>(ptr);

+ 8
- 110
src/lua/lua_task.c View File

@@ -31,6 +31,7 @@
#include "libserver/maps/map_helpers.h"

#include <math.h>
#include "libmime/received.h"

/***
* @module rspamd_task
@@ -3139,9 +3140,6 @@ lua_task_get_received_headers (lua_State * L)
{
LUA_TRACE_POINT;
struct rspamd_task *task = lua_check_task (L, 1);
struct rspamd_received_header *rh;
const gchar *proto;
guint k = 1;

if (task) {
if (!task->message) {
@@ -3151,115 +3149,15 @@ lua_task_get_received_headers (lua_State * L)
}

if (!lua_task_get_cached (L, task, "received")) {
lua_createtable (L, 0, 0);

DL_FOREACH (MESSAGE_FIELD (task, received), rh) {
lua_createtable (L, 0, 10);

if (rh->hdr && rh->hdr->decoded) {
rspamd_lua_table_set (L, "raw", rh->hdr->decoded);
}

lua_pushstring (L, "flags");
lua_createtable (L, 0, 3);

lua_pushstring (L, "artificial");
if (rh->flags & RSPAMD_RECEIVED_FLAG_ARTIFICIAL) {
lua_pushboolean (L, true);
}
else {
lua_pushboolean (L, false);
}
lua_settable (L, -3);

lua_pushstring (L, "authenticated");
if (rh->flags & RSPAMD_RECEIVED_FLAG_AUTHENTICATED) {
lua_pushboolean (L, true);
}
else {
lua_pushboolean (L, false);
}
lua_settable (L, -3);

lua_pushstring (L, "ssl");
if (rh->flags & RSPAMD_RECEIVED_FLAG_SSL) {
lua_pushboolean (L, true);
}
else {
lua_pushboolean (L, false);
}
lua_settable (L, -3);

lua_settable (L, -3);

if (G_UNLIKELY (rh->from_ip == NULL &&
rh->real_ip == NULL &&
rh->real_hostname == NULL &&
rh->by_hostname == NULL && rh->timestamp == 0 &&
rh->for_mbox == NULL)) {
lua_rawseti (L, -2, k ++);

continue;
}

rspamd_lua_table_set (L, "from_hostname", rh->from_hostname);
rspamd_lua_table_set (L, "from_ip", rh->from_ip);
rspamd_lua_table_set (L, "real_hostname", rh->real_hostname);
lua_pushstring (L, "real_ip");
rspamd_lua_ip_push (L, rh->addr);
lua_settable (L, -3);
lua_pushstring (L, "proto");

switch (rh->flags & RSPAMD_RECEIVED_FLAG_TYPE_MASK) {
case RSPAMD_RECEIVED_SMTP:
proto = "smtp";
break;
case RSPAMD_RECEIVED_ESMTP:
proto = "esmtp";
break;
case RSPAMD_RECEIVED_ESMTPS:
proto = "esmtps";
break;
case RSPAMD_RECEIVED_ESMTPA:
proto = "esmtpa";
break;
case RSPAMD_RECEIVED_ESMTPSA:
proto = "esmtpsa";
break;
case RSPAMD_RECEIVED_LMTP:
proto = "lmtp";
break;
case RSPAMD_RECEIVED_IMAP:
proto = "imap";
break;
case RSPAMD_RECEIVED_HTTP:
proto = "http";
break;
case RSPAMD_RECEIVED_LOCAL:
proto = "local";
break;
case RSPAMD_RECEIVED_MAPI:
proto = "mapi";
break;
case RSPAMD_RECEIVED_UNKNOWN:
default:
proto = "unknown";
break;
}

lua_pushstring (L, proto);
lua_settable (L, -3);

lua_pushstring (L, "timestamp");
lua_pushinteger (L, rh->timestamp);
lua_settable (L, -3);

rspamd_lua_table_set (L, "by_hostname", rh->by_hostname);
rspamd_lua_table_set (L, "for", rh->for_mbox);
lua_rawseti (L, -2, k ++);
if (rspamd_received_export_to_lua(task, L)) {
lua_task_set_cached (L, task, "received", -1);
}
else {
/* no received, preserve compatibility */
lua_newtable (L);
return 1;
}

lua_task_set_cached (L, task, "received", -1);
}
}
else {

Loading…
Cancel
Save