From: Vsevolod Stakhov Date: Mon, 4 Oct 2021 20:46:15 +0000 (+0100) Subject: [Project] Start using of the new received structure X-Git-Tag: 3.1~94 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=513b6c6ab95cb36b5405de394f24b59f4f2b9a3d;p=rspamd.git [Project] Start using of the new received structure --- diff --git a/src/libmime/message.c b/src/libmime/message.c index e6fc5be94..1676e4218 100644 --- a/src/libmime/message.c +++ b/src/libmime/message.c @@ -39,6 +39,7 @@ #include "lua/lua_common.h" #include "contrib/uthash/utlist.h" #include "contrib/t1ha/t1ha.h" +#include "received.h" #define GTUBE_SYMBOL "GTUBE" @@ -1114,7 +1115,6 @@ rspamd_message_new (struct rspamd_task *task) gboolean rspamd_message_parse (struct rspamd_task *task) { - struct rspamd_received_header *recv, *trecv; const gchar *p; gsize len; guint i; @@ -1221,86 +1221,7 @@ rspamd_message_parse (struct rspamd_task *task) task->queue_id = "undef"; } - if (MESSAGE_FIELD (task, received)) { - gboolean need_recv_correction = FALSE; - rspamd_inet_addr_t *raddr; - - recv = MESSAGE_FIELD (task, received); - /* - * For the first header we must ensure that - * received is consistent with the IP that we obtain through - * client. - */ - - raddr = recv->addr; - if (recv->real_ip == NULL || (task->cfg && task->cfg->ignore_received)) { - need_recv_correction = TRUE; - } - else if (!(task->flags & RSPAMD_TASK_FLAG_NO_IP) && task->from_addr) { - if (!raddr) { - need_recv_correction = TRUE; - } - else { - if (rspamd_inet_address_compare (raddr, task->from_addr, FALSE) != 0) { - need_recv_correction = TRUE; - } - } - } - - if (need_recv_correction && !(task->flags & RSPAMD_TASK_FLAG_NO_IP) - && task->from_addr) { - msg_debug_task ("the first received seems to be" - " not ours, prepend it with fake one"); - - trecv = rspamd_mempool_alloc0 (task->task_pool, - sizeof (struct rspamd_received_header)); - trecv->flags |= RSPAMD_RECEIVED_FLAG_ARTIFICIAL; - - if (task->flags & RSPAMD_TASK_FLAG_SSL) { - trecv->flags |= RSPAMD_RECEIVED_FLAG_SSL; - } - - if (task->user) { - trecv->flags |= RSPAMD_RECEIVED_FLAG_AUTHENTICATED; - } - - trecv->real_ip = rspamd_mempool_strdup (task->task_pool, - rspamd_inet_address_to_string (task->from_addr)); - trecv->from_ip = trecv->real_ip; - trecv->by_hostname = rspamd_mempool_get_variable (task->task_pool, - RSPAMD_MEMPOOL_MTA_NAME); - trecv->addr = rspamd_inet_address_copy (task->from_addr); - rspamd_mempool_add_destructor (task->task_pool, - (rspamd_mempool_destruct_t)rspamd_inet_address_free, - trecv->addr); - - if (task->hostname) { - trecv->real_hostname = task->hostname; - trecv->from_hostname = trecv->real_hostname; - } - - DL_PREPEND (MESSAGE_FIELD (task, received), trecv); - } - } - - /* Extract data from received header if we were not given IP */ - if (MESSAGE_FIELD (task, received) && (task->flags & RSPAMD_TASK_FLAG_NO_IP) && - (task->cfg && !task->cfg->ignore_received)) { - recv = MESSAGE_FIELD (task, received); - if (recv->real_ip) { - if (!rspamd_parse_inet_address (&task->from_addr, - recv->real_ip, - strlen (recv->real_ip), - RSPAMD_INET_ADDRESS_PARSE_NO_UNIX)) { - msg_warn_task ("cannot get IP from received header: '%s'", - recv->real_ip); - task->from_addr = NULL; - } - } - if (recv->real_hostname) { - task->hostname = recv->real_hostname; - } - } + rspamd_received_maybe_fix_task(task); struct rspamd_mime_part *part; diff --git a/src/libmime/mime_headers.c b/src/libmime/mime_headers.c index 7afb0e7a6..88675a629 100644 --- a/src/libmime/mime_headers.c +++ b/src/libmime/mime_headers.c @@ -38,7 +38,6 @@ rspamd_mime_header_check_special (struct rspamd_task *task, struct rspamd_mime_header *rh) { guint64 h; - struct rspamd_received_header *recv; const gchar *p, *end; gchar *id; gint max_recipients = -1, len; @@ -51,16 +50,9 @@ rspamd_mime_header_check_special (struct rspamd_task *task, switch (h) { case 0x88705DC4D9D61ABULL: /* received */ - recv = rspamd_mempool_alloc0 (task->task_pool, - sizeof (struct rspamd_received_header)); - recv->hdr = rh; - - if (rspamd_smtp_received_parse (task, rh->decoded, - strlen (rh->decoded), recv) != -1) { - DL_APPEND (MESSAGE_FIELD (task, received), recv); + if (rspamd_received_header_parse(task, rh->decoded, strlen (rh->decoded), rh)) { + rh->flags |= RSPAMD_HEADER_RECEIVED; } - - rh->flags |= RSPAMD_HEADER_RECEIVED; break; case 0x76F31A09F4352521ULL: /* to */ MESSAGE_FIELD (task, rcpt_mime) = rspamd_email_address_from_mime (task->task_pool, diff --git a/src/libmime/received.cxx b/src/libmime/received.cxx index 78c9f1841..3d273081f 100644 --- a/src/libmime/received.cxx +++ b/src/libmime/received.cxx @@ -14,17 +14,14 @@ * limitations under the License. */ +#include #include "config.h" -#include "received.h" -#include "libserver/task.h" #include "libserver/url.h" +#include "libserver/cfg_file.h" #include "mime_string.hxx" #include "smtp_parsers.h" #include "message.h" - -#include -#include -#include +#include "received.hxx" #include "frozen/string.h" #include "frozen/unordered_map.h" @@ -39,64 +36,6 @@ enum class received_part_type { RSPAMD_RECEIVED_PART_UNKNOWN, }; -static inline auto -received_char_filter(UChar32 uc) -> UChar32 -{ - if (u_isprint(uc)) { - return u_tolower(uc); - } - - return 0; -} - - -struct received_header { - mime_string from_hostname; - std::string_view from_ip; - mime_string real_hostname; - mime_string real_ip; - mime_string by_hostname; - std::string_view for_mbox; - struct rspamd_email_address *for_addr = nullptr; - 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_header() noexcept - : from_hostname(received_char_filter), - real_hostname(received_char_filter), - real_ip(received_char_filter), - by_hostname(received_char_filter), - for_mbox(received_char_filter) {} - - ~received_header() { - if (for_addr) { - rspamd_email_address_free(for_addr); - } - } -}; - -class received_header_chain { -public: - explicit received_header_chain(struct rspamd_task *_task) : task(_task) { - headers.reserve(2); - rspamd_mempool_add_destructor(task->task_pool, - received_header_chain::received_header_chain_pool_dtor, this); - } - - auto new_received() -> received_header & { - headers.emplace_back(); - return headers.back(); - } -private: - static auto received_header_chain_pool_dtor(void *ptr) -> void { - delete static_cast(ptr); - } - std::vector headers; - struct rspamd_task *task; -}; - struct received_part { received_part_type type; mime_string data; @@ -642,7 +581,7 @@ received_process_from(struct rspamd_task *task, } } -auto +static auto received_header_parse(struct rspamd_task *task, const std::string_view &in, struct rspamd_mime_header *hdr) -> bool { @@ -734,6 +673,94 @@ received_header_parse(struct rspamd_task *task, const std::string_view &in, return true; } +static auto +received_maybe_fix_task(struct rspamd_task *task) -> bool +{ + auto *recv_chain_ptr = static_cast(MESSAGE_FIELD(task, received_headers)); + + if (recv_chain_ptr) { + auto need_recv_correction = false; + + auto top_recv_maybe = recv_chain_ptr->get_received(0); + + if (top_recv_maybe.has_value()) { + auto &top_recv = top_recv_maybe.value().get(); + + const auto *raddr = top_recv.addr; + if (top_recv.real_ip.size() == 0 || (task->cfg && task->cfg->ignore_received)) { + need_recv_correction = true; + } + else if (!(task->flags & RSPAMD_TASK_FLAG_NO_IP) && task->from_addr) { + if (!raddr) { + need_recv_correction = true; + } + else { + if (rspamd_inet_address_compare(raddr, task->from_addr, FALSE) != 0) { + need_recv_correction = true; + } + } + } + + if (need_recv_correction && !(task->flags & RSPAMD_TASK_FLAG_NO_IP) + && task->from_addr) { + msg_debug_task ("the first received seems to be" + " 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; + + if (task->flags & RSPAMD_TASK_FLAG_SSL) { + trecv.flags |= RSPAMD_RECEIVED_FLAG_SSL; + } + + if (task->user) { + trecv.flags |= RSPAMD_RECEIVED_FLAG_AUTHENTICATED; + } + + trecv.real_ip.assign_copy(std::string_view(rspamd_inet_address_to_string(task->from_addr))); + trecv.from_ip = trecv.real_ip.as_view(); + + const auto *mta_name = (const char*)rspamd_mempool_get_variable(task->task_pool, + RSPAMD_MEMPOOL_MTA_NAME); + + if (mta_name) { + trecv.by_hostname.assign_copy(std::string_view(mta_name)); + } + trecv.addr = rspamd_inet_address_copy(task->from_addr); + + if (task->hostname) { + trecv.real_hostname.assign_copy(std::string_view(task->hostname)); + trecv.from_hostname.assign_copy(trecv.real_hostname); + } + + return true; + } + + /* Extract data from received header if we were not given IP */ + if (!need_recv_correction && (task->flags & RSPAMD_TASK_FLAG_NO_IP) && + (task->cfg && !task->cfg->ignore_received)) { + if (!top_recv.real_ip.empty()) { + if (!rspamd_parse_inet_address (&task->from_addr, + top_recv.real_ip.data(), + top_recv.real_ip.size(), + RSPAMD_INET_ADDRESS_PARSE_NO_UNIX)) { + msg_warn_task ("cannot get IP from received header: '%s'", + top_recv.real_ip.data()); + task->from_addr = nullptr; + } + } + if (!top_recv.real_hostname.empty()) { + task->hostname = top_recv.real_hostname.data(); + } + + return true; + } + } + } + + return false; +} + } // namespace rspamd::mime bool @@ -743,3 +770,9 @@ rspamd_received_header_parse(struct rspamd_task *task, { return rspamd::mime::received_header_parse(task, std::string_view{data, sz}, hdr); } + +bool +rspamd_received_maybe_fix_task(struct rspamd_task *task) +{ + return rspamd::mime::received_maybe_fix_task(task); +} diff --git a/src/libmime/received.h b/src/libmime/received.h index bc3c31e0d..845bf4357 100644 --- a/src/libmime/received.h +++ b/src/libmime/received.h @@ -24,6 +24,9 @@ #ifdef __cplusplus extern "C" { #endif +/* + * C bindings for C++ received code + */ enum rspamd_received_type { RSPAMD_RECEIVED_SMTP = 1u << 0u, @@ -58,9 +61,25 @@ struct rspamd_email_address; struct rspamd_received_header_chain; struct rspamd_mime_header; +/** + * Parse received header from an input header data + * @param task + * @param data + * @param sz + * @param hdr + * @return + */ bool rspamd_received_header_parse(struct rspamd_task *task, const char *data, size_t sz, struct rspamd_mime_header *hdr); + +/** + * Process task data and the most top received and fix either part if needed + * @param task + * @return + */ +bool rspamd_received_maybe_fix_task(struct rspamd_task *task); + #ifdef __cplusplus } #endif