]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Finish received headers rework part
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 5 Oct 2021 11:13:21 +0000 (12:13 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 5 Oct 2021 11:13:21 +0000 (12:13 +0100)
src/libmime/received.cxx
src/libmime/received.h
src/libmime/received.hxx
src/lua/lua_task.c

index 3d273081f2eab6018ee2eca434a627a5dd68f3ef..6c79ced0059f45f05f211d8a85c2dadf8f86bac8 100644 (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);
+}
\ No newline at end of file
index 845bf4357c51d9810b27fc464e5361b308ac535f..14f9f848bf9fd30a3d9ef890076696ee04e08884 100644 (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
index fd03fd1fa5dd557edeba9cbc9dedfd46a8492e77..7c8d5f39717379660030db3a6bf6a57f031a2269 100644 (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);
index de2b130d6e40d6b768ee572b4096870513f5297e..1eb67a4309ae5ba1cd5feaf07ea02ed3a7ef18a3 100644 (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 {