From 654584a9b9510ec44cab149e6e2cd41108776886 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 6 May 2017 13:41:08 +0100 Subject: [PATCH] [Minor] Convert milter session to HTTP request --- src/libserver/milter.c | 46 ++++++++++++++++++ src/libserver/milter.h | 9 ++++ src/libserver/protocol.c | 61 +---------------------- src/libserver/protocol_internal.h | 80 +++++++++++++++++++++++++++++++ src/libutil/http.c | 50 +++++++++++++++++-- src/libutil/http.h | 11 ++++- 6 files changed, 193 insertions(+), 64 deletions(-) create mode 100644 src/libserver/protocol_internal.h diff --git a/src/libserver/milter.c b/src/libserver/milter.c index 795c99bb0..a45f19c77 100644 --- a/src/libserver/milter.c +++ b/src/libserver/milter.c @@ -22,6 +22,9 @@ #include "unix-std.h" #include "logger.h" #include "ottery.h" +#include "libutil/http.h" +#include "libutil/http_private.h" +#include "libserver/protocol_internal.h" #include "utlist.h" #define msg_err_milter(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL, \ @@ -1081,3 +1084,46 @@ rspamd_milter_session_ref (struct rspamd_milter_session *session) return session; } + +struct rspamd_http_message * +rspamd_milter_to_http (struct rspamd_milter_session *session) +{ + struct rspamd_http_message *msg; + guint i; + struct rspamd_email_address *rcpt; + + g_assert (session != NULL); + + msg = rspamd_http_new_message (HTTP_REQUEST); + + msg->url = rspamd_fstring_assign (msg->url, "/" MSG_CMD_CHECK_V2, + sizeof ("/" MSG_CMD_CHECK_V2) - 1); + + if (session->message) { + rspamd_http_message_set_body_from_fstring_steal (msg, session->message); + } + + if (session->hostname && session->hostname->len > 0) { + rspamd_http_message_add_header_fstr (msg, HOSTNAME_HEADER, + session->hostname); + } + + if (session->helo && session->helo->len > 0) { + rspamd_http_message_add_header_fstr (msg, HELO_HEADER, + session->helo); + } + + if (session->from) { + rspamd_http_message_add_header_len (msg, FROM_HEADER, + session->from->raw, session->from->raw_len); + } + + if (session->rcpts) { + PTR_ARRAY_FOREACH (session->rcpts, i, rcpt) { + rspamd_http_message_add_header_len (msg, RCPT_HEADER, + rcpt->raw, rcpt->raw_len); + } + } + + return msg; +} \ No newline at end of file diff --git a/src/libserver/milter.h b/src/libserver/milter.h index de16062f8..963cc182c 100644 --- a/src/libserver/milter.h +++ b/src/libserver/milter.h @@ -38,6 +38,7 @@ enum rspamd_milter_reply { struct rspamd_email_address; struct event_base; +struct rspamd_http_message; struct rspamd_milter_session { GHashTable *macros; @@ -116,4 +117,12 @@ void rspamd_milter_session_unref (struct rspamd_milter_session *session); struct rspamd_milter_session * rspamd_milter_session_ref ( struct rspamd_milter_session *session); +/** + * Converts milter session to HTTP session that is suitable for Rspamd + * @param session + * @return + */ +struct rspamd_http_message * rspamd_milter_to_http ( + struct rspamd_milter_session *session); + #endif diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index 52ba05188..1c11832a2 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -22,68 +22,9 @@ #include "contrib/zstd/zstd.h" #include "lua/lua_common.h" #include "unix-std.h" +#include "protocol_internal.h" #include -/* - * Just check if the passed message is spam or not and reply as - * described below - */ -#define MSG_CMD_CHECK "check" - -/* - * Modern check version - */ -#define MSG_CMD_CHECK_V2 "checkv2" - -/* - * Check if message is spam or not, and return score plus list - * of symbols hit - */ -#define MSG_CMD_SYMBOLS "symbols" -/* - * Check if message is spam or not, and return score plus report - */ -#define MSG_CMD_REPORT "report" -/* - * Check if message is spam or not, and return score plus report - * if the message is spam - */ -#define MSG_CMD_REPORT_IFSPAM "report_ifspam" -/* - * Ignore this message -- client opened connection then changed - */ -#define MSG_CMD_SKIP "skip" -/* - * Return a confirmation that spamd is alive - */ -#define MSG_CMD_PING "ping" -/* - * Process this message as described above and return modified message - */ -#define MSG_CMD_PROCESS "process" -/* - * Headers - */ -#define HELO_HEADER "Helo" -#define FROM_HEADER "From" -#define IP_ADDR_HEADER "IP" -#define RCPT_HEADER "Rcpt" -#define SUBJECT_HEADER "Subject" -#define SETTINGS_ID_HEADER "Settings-ID" -#define QUEUE_ID_HEADER "Queue-ID" -#define USER_HEADER "User" -#define URLS_HEADER "URL-Format" -#define PASS_HEADER "Pass" -#define JSON_HEADER "Json" -#define HOSTNAME_HEADER "Hostname" -#define DELIVER_TO_HEADER "Deliver-To" -#define NO_LOG_HEADER "Log" -#define MLEN_HEADER "Message-Length" -#define USER_AGENT_HEADER "User-Agent" -#define MTA_TAG_HEADER "MTA-Tag" -#define PROFILE_HEADER "Profile" - - static GQuark rspamd_protocol_quark (void) { diff --git a/src/libserver/protocol_internal.h b/src/libserver/protocol_internal.h new file mode 100644 index 000000000..ac588386b --- /dev/null +++ b/src/libserver/protocol_internal.h @@ -0,0 +1,80 @@ +/*- + * Copyright 2017 Vsevolod Stakhov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RSPAMD_PROTOCOL_INTERNAL_H +#define RSPAMD_PROTOCOL_INTERNAL_H + +/* + * Just check if the passed message is spam or not and reply as + * described below + */ +#define MSG_CMD_CHECK "check" + +/* + * Modern check version + */ +#define MSG_CMD_CHECK_V2 "checkv2" + +/* + * Check if message is spam or not, and return score plus list + * of symbols hit + */ +#define MSG_CMD_SYMBOLS "symbols" +/* + * Check if message is spam or not, and return score plus report + */ +#define MSG_CMD_REPORT "report" +/* + * Check if message is spam or not, and return score plus report + * if the message is spam + */ +#define MSG_CMD_REPORT_IFSPAM "report_ifspam" +/* + * Ignore this message -- client opened connection then changed + */ +#define MSG_CMD_SKIP "skip" +/* + * Return a confirmation that spamd is alive + */ +#define MSG_CMD_PING "ping" +/* + * Process this message as described above and return modified message + */ +#define MSG_CMD_PROCESS "process" +/* + * Headers + */ +#define HELO_HEADER "Helo" +#define FROM_HEADER "From" +#define IP_ADDR_HEADER "IP" +#define RCPT_HEADER "Rcpt" +#define SUBJECT_HEADER "Subject" +#define SETTINGS_ID_HEADER "Settings-ID" +#define QUEUE_ID_HEADER "Queue-ID" +#define USER_HEADER "User" +#define URLS_HEADER "URL-Format" +#define PASS_HEADER "Pass" +#define JSON_HEADER "Json" +#define HOSTNAME_HEADER "Hostname" +#define DELIVER_TO_HEADER "Deliver-To" +#define NO_LOG_HEADER "Log" +#define MLEN_HEADER "Message-Length" +#define USER_AGENT_HEADER "User-Agent" +#define MTA_TAG_HEADER "MTA-Tag" +#define PROFILE_HEADER "Profile" + + +#endif //RSPAMD_PROTOCOL_INTERNAL_H diff --git a/src/libutil/http.c b/src/libutil/http.c index 24c5e730c..8331b2406 100644 --- a/src/libutil/http.c +++ b/src/libutil/http.c @@ -2789,9 +2789,10 @@ rspamd_http_message_set_peer_key (struct rspamd_http_message *msg, } void -rspamd_http_message_add_header (struct rspamd_http_message *msg, +rspamd_http_message_add_header_len (struct rspamd_http_message *msg, const gchar *name, - const gchar *value) + const gchar *value, + gsize len) { struct rspamd_http_header *hdr, *found = NULL; guint nlen, vlen; @@ -2799,7 +2800,7 @@ rspamd_http_message_add_header (struct rspamd_http_message *msg, if (msg != NULL && name != NULL && value != NULL) { hdr = g_slice_alloc (sizeof (struct rspamd_http_header)); nlen = strlen (name); - vlen = strlen (value); + vlen = len; hdr->combined = rspamd_fstring_sized_new (nlen + vlen + 4); rspamd_printf_fstring (&hdr->combined, "%s: %s\r\n", name, value); hdr->value = g_slice_alloc (sizeof (*hdr->value)); @@ -2821,6 +2822,49 @@ rspamd_http_message_add_header (struct rspamd_http_message *msg, } } +void +rspamd_http_message_add_header (struct rspamd_http_message *msg, + const gchar *name, + const gchar *value) +{ + if (value) { + rspamd_http_message_add_header_len (msg, name, value, strlen (value)); + } +} + +void +rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg, + const gchar *name, + rspamd_fstring_t *value) +{ + struct rspamd_http_header *hdr, *found = NULL; + guint nlen, vlen; + + if (msg != NULL && name != NULL && value != NULL) { + hdr = g_slice_alloc (sizeof (struct rspamd_http_header)); + nlen = strlen (name); + vlen = value->len; + hdr->combined = rspamd_fstring_sized_new (nlen + vlen + 4); + rspamd_printf_fstring (&hdr->combined, "%s: %V\r\n", name, value); + hdr->value = g_slice_alloc (sizeof (*hdr->value)); + hdr->name = g_slice_alloc (sizeof (*hdr->name)); + hdr->name->begin = hdr->combined->str; + hdr->name->len = nlen; + hdr->value->begin = hdr->combined->str + nlen + 2; + hdr->value->len = vlen; + + HASH_FIND (hh, msg->headers, hdr->name->begin, + hdr->name->len, found); + + if (found == NULL) { + HASH_ADD_KEYPTR (hh, msg->headers, hdr->name->begin, + hdr->name->len, hdr); + } + + DL_APPEND (found, hdr); + } +} + const rspamd_ftok_t * rspamd_http_message_find_header (struct rspamd_http_message *msg, const gchar *name) diff --git a/src/libutil/http.h b/src/libutil/http.h index 23d2fa3fa..8da1bf5e0 100644 --- a/src/libutil/http.h +++ b/src/libutil/http.h @@ -378,7 +378,7 @@ gboolean rspamd_http_message_append_body (struct rspamd_http_message *msg, const gchar *data, gsize len); /** - * Append a header to reply + * Append a header to http message * @param rep * @param name * @param value @@ -387,6 +387,15 @@ void rspamd_http_message_add_header (struct rspamd_http_message *msg, const gchar *name, const gchar *value); +void rspamd_http_message_add_header_len (struct rspamd_http_message *msg, + const gchar *name, + const gchar *value, + gsize len); + +void rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg, + const gchar *name, + rspamd_fstring_t *value); + /** * Search for a specified header in message * @param msg message -- 2.39.5