commit 1755ad1: [Project] Add possibility to modify body in milter context

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Jul 18 15:14:06 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-07-18 15:05:28 +0100
URL: https://github.com/rspamd/rspamd/commit/1755ad1ce5a0165f08f1b4d778f198d652d48b9c

[Project] Add possibility to modify body in milter context

---
 src/libserver/milter.c            |  9 +++-
 src/libserver/milter.h            |  4 +-
 src/libserver/protocol.c          |  2 +-
 src/libserver/protocol_internal.h |  1 +
 src/rspamd_proxy.c                | 91 ++++++++++++++++++++++++++++++++++-----
 5 files changed, 94 insertions(+), 13 deletions(-)

diff --git a/src/libserver/milter.c b/src/libserver/milter.c
index 2e00e4c46..50a84a42a 100644
--- a/src/libserver/milter.c
+++ b/src/libserver/milter.c
@@ -1786,7 +1786,9 @@ rspamd_milter_process_milter_block (struct rspamd_milter_session *session,
 
 void
 rspamd_milter_send_task_results (struct rspamd_milter_session *session,
-		const ucl_object_t *results)
+								 const ucl_object_t *results,
+								 const gchar *new_body,
+								 gsize bodylen)
 {
 	const ucl_object_t *elt;
 	struct rspamd_milter_private *priv = session->priv;
@@ -1883,6 +1885,11 @@ rspamd_milter_send_task_results (struct rspamd_milter_session *session,
 		goto cleanup;
 	}
 
+	if (new_body) {
+		rspamd_milter_send_action (session, RSPAMD_MILTER_REPLBODY,
+				bodylen, new_body);
+	}
+
 	if (priv->no_action) {
 		msg_info_milter ("do not apply action %s, no_action is set",
 				str_action);
diff --git a/src/libserver/milter.h b/src/libserver/milter.h
index 10d2c3c47..df2a5efc6 100644
--- a/src/libserver/milter.h
+++ b/src/libserver/milter.h
@@ -163,7 +163,9 @@ struct rspamd_http_message *rspamd_milter_to_http (
  * @param results
  */
 void rspamd_milter_send_task_results (struct rspamd_milter_session *session,
-									  const ucl_object_t *results);
+									  const ucl_object_t *results,
+									  const gchar *new_body,
+									  gsize bodylen);
 
 /**
  * Init internal milter context
diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c
index 02dc73607..e8bbd979b 100644
--- a/src/libserver/protocol.c
+++ b/src/libserver/protocol.c
@@ -1564,7 +1564,7 @@ rspamd_protocol_http_reply (struct rspamd_http_message *msg,
 			GString *hdr_offset = g_string_sized_new (30);
 
 			rspamd_printf_gstring (hdr_offset, "%z", RSPAMD_FSTRING_LEN (reply));
-			rspamd_http_message_add_header (msg, "Message-Offset",
+			rspamd_http_message_add_header (msg, MESSAGE_OFFSET_HEADER,
 					hdr_offset->str);
 			msg_debug_protocol ("write body block at position %s",
 					hdr_offset->str);
diff --git a/src/libserver/protocol_internal.h b/src/libserver/protocol_internal.h
index 418af70d9..d9616e03d 100644
--- a/src/libserver/protocol_internal.h
+++ b/src/libserver/protocol_internal.h
@@ -88,6 +88,7 @@ extern "C" {
 #define CERT_ISSUER_HEADER "TLS-Cert-Issuer"
 #define MAILER_HEADER "Mailer"
 #define RAW_DATA_HEADER "Raw"
+#define MESSAGE_OFFSET_HEADER "Message-Offset"
 
 #ifdef  __cplusplus
 }
diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c
index 8d1f7c116..cca9f792f 100644
--- a/src/rspamd_proxy.c
+++ b/src/rspamd_proxy.c
@@ -854,17 +854,36 @@ proxy_backend_close_connection (struct rspamd_proxy_backend_connection *conn)
 
 static gboolean
 proxy_backend_parse_results (struct rspamd_proxy_session *session,
-		struct rspamd_proxy_backend_connection *conn,
-		lua_State *L, gint parser_ref,
-		const gchar *in, gsize inlen)
+							 struct rspamd_proxy_backend_connection *conn,
+							 lua_State *L, gint parser_ref,
+							 struct rspamd_http_message *msg,
+							 goffset *body_offset)
 {
 	struct ucl_parser *parser;
 	gint err_idx;
+	const gchar *in = msg->body_buf.begin;
+	gsize inlen = msg->body_buf.len;
+	const rspamd_ftok_t *offset_hdr;
 
 	if (inlen == 0 || in == NULL) {
 		return FALSE;
 	}
 
+	offset_hdr = rspamd_http_message_find_header (msg, MESSAGE_OFFSET_HEADER);
+
+	if (offset_hdr) {
+		gulong val;
+
+		if (rspamd_strtoul (offset_hdr->begin, offset_hdr->len, &val)
+			&& val < inlen) {
+
+			if (body_offset) {
+				*body_offset = val;
+			}
+			inlen = val;
+		}
+	}
+
 	if (parser_ref != -1) {
 		/* Call parser function */
 		lua_pushcfunction (L, &rspamd_lua_traceback);
@@ -1300,7 +1319,7 @@ proxy_backend_mirror_finish_handler (struct rspamd_http_connection *conn,
 	proxy_request_decompress (msg);
 
 	if (!proxy_backend_parse_results (session, bk_conn, session->ctx->lua_state,
-			bk_conn->parser_from_ref, msg->body_buf.begin, msg->body_buf.len)) {
+			bk_conn->parser_from_ref, msg, NULL)) {
 		msg_warn_session ("cannot parse results from the mirror backend %s:%s",
 				bk_conn->name,
 				rspamd_inet_address_to_string (
@@ -1503,11 +1522,12 @@ proxy_backend_master_error_handler (struct rspamd_http_connection *conn, GError
 
 static gint
 proxy_backend_master_finish_handler (struct rspamd_http_connection *conn,
-	struct rspamd_http_message *msg)
+									 struct rspamd_http_message *msg)
 {
 	struct rspamd_proxy_backend_connection *bk_conn = conn->ud;
 	struct rspamd_proxy_session *session, *nsession;
 	rspamd_fstring_t *reply;
+	goffset body_offset = -1;
 
 	session = bk_conn->s;
 	rspamd_http_connection_steal_msg (session->master_conn->backend_conn);
@@ -1518,7 +1538,7 @@ proxy_backend_master_finish_handler (struct rspamd_http_connection *conn,
 	rspamd_http_connection_reset (session->master_conn->backend_conn);
 
 	if (!proxy_backend_parse_results (session, bk_conn, session->ctx->lua_state,
-			bk_conn->parser_from_ref, msg->body_buf.begin, msg->body_buf.len)) {
+			bk_conn->parser_from_ref, msg, &body_offset)) {
 		msg_warn_session ("cannot parse results from the master backend");
 	}
 
@@ -1549,8 +1569,17 @@ proxy_backend_master_finish_handler (struct rspamd_http_connection *conn,
 
 	if (session->client_milter_conn) {
 		nsession = proxy_session_refresh (session);
-		rspamd_milter_send_task_results (nsession->client_milter_conn,
-				session->master_conn->results);
+
+		if (body_offset > 0) {
+			rspamd_milter_send_task_results (nsession->client_milter_conn,
+					session->master_conn->results,
+					msg->body_buf.begin + body_offset,
+					msg->body_buf.len - body_offset);
+		}
+		else {
+			rspamd_milter_send_task_results (nsession->client_milter_conn,
+					session->master_conn->results, NULL, 0);
+		}
 		REF_RELEASE (session);
 		rspamd_http_message_free (msg);
 	}
@@ -1602,8 +1631,50 @@ rspamd_proxy_scan_self_reply (struct rspamd_task *task)
 
 	if (session->client_milter_conn) {
 		nsession = proxy_session_refresh (session);
-		rspamd_milter_send_task_results (nsession->client_milter_conn,
-				session->master_conn->results);
+
+		if (task->flags & RSPAMD_TASK_FLAG_MESSAGE_REWRITE) {
+			const gchar *start;
+			goffset len, hdr_off;
+
+			start = task->msg.begin;
+			len = task->msg.len;
+
+			hdr_off = MESSAGE_FIELD (task, raw_headers_content).len;
+
+			if (hdr_off < len) {
+				start += hdr_off;
+				len -= hdr_off;
+
+				/* The problem here is that we need not end of headers, we need
+				 * start of body.
+				 *
+				 * Hence, we need to skip one \r\n till there is anything else in
+				 * a line.
+				 */
+
+				if (*start == '\r' && len > 0) {
+					start++;
+					len--;
+				}
+
+				if (*start == '\n' && len > 0) {
+					start++;
+					len--;
+				}
+
+				rspamd_milter_send_task_results (nsession->client_milter_conn,
+						session->master_conn->results, start, len);
+			}
+			else {
+				/* XXX: should never happen! */
+				rspamd_milter_send_task_results (nsession->client_milter_conn,
+						session->master_conn->results, NULL, 0);
+			}
+		}
+		else {
+			rspamd_milter_send_task_results (nsession->client_milter_conn,
+					session->master_conn->results, NULL, 0);
+		}
 		rspamd_http_message_free (msg);
 		REF_RELEASE (session);
 	}


More information about the Commits mailing list