commit 513b6c6: [Project] Start using of the new received structure

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Oct 5 11:14:07 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-10-04 21:46:15 +0100
URL: https://github.com/rspamd/rspamd/commit/513b6c6ab95cb36b5405de394f24b59f4f2b9a3d

[Project] Start using of the new received structure

---
 src/libmime/message.c      |  83 +----------------------
 src/libmime/mime_headers.c |  12 +---
 src/libmime/received.cxx   | 163 +++++++++++++++++++++++++++------------------
 src/libmime/received.h     |  19 ++++++
 4 files changed, 121 insertions(+), 156 deletions(-)

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 <mempool_vars_internal.h>
 #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 <vector>
-#include <string_view>
-#include <utility>
+#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<received_header_chain *>(ptr);
-	}
-	std::vector<received_header> 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<received_header_chain *>(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


More information about the Commits mailing list