aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libserver/milter.c189
-rw-r--r--src/libserver/milter.h9
-rw-r--r--src/libserver/milter_internal.h9
-rw-r--r--src/rspamd_proxy.c14
4 files changed, 211 insertions, 10 deletions
diff --git a/src/libserver/milter.c b/src/libserver/milter.c
index 6beadad7e..6f67a03ff 100644
--- a/src/libserver/milter.c
+++ b/src/libserver/milter.c
@@ -25,6 +25,7 @@
#include "libutil/http.h"
#include "libutil/http_private.h"
#include "libserver/protocol_internal.h"
+#include "libmime/filter.h"
#include "utlist.h"
#define msg_err_milter(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL, \
@@ -1226,4 +1227,192 @@ rspamd_milter_update_userdata (struct rspamd_milter_session *session,
priv->ud = ud;
return prev_ud;
+}
+
+static void
+rspamd_milter_process_rmilter_block (struct rspamd_milter_session *session,
+ const ucl_object_t *obj)
+{
+ const ucl_object_t *elt, *cur, *cur_elt;
+ ucl_object_iter_t it;
+ GString *hname, *hvalue;
+ gint nhdr;
+
+ if (obj && ucl_object_type (obj) == UCL_OBJECT) {
+ elt = ucl_object_lookup (obj, "remove_headers");
+ /*
+ * remove_headers: {"name": 1, ... }
+ * where number is the header's position starting from '1'
+ */
+ if (elt && ucl_object_type (elt) == UCL_OBJECT) {
+ it = NULL;
+
+ while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
+ if (ucl_object_type (cur) == UCL_INT) {
+ nhdr = ucl_object_toint (cur);
+ hname = g_string_new (ucl_object_key (cur));
+ hvalue = g_string_new ("");
+
+ if (nhdr >= 1) {
+ rspamd_milter_send_action (session,
+ RSPAMD_MILTER_CHGHEADER,
+ nhdr, hname, hvalue);
+ }
+
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ }
+ }
+ }
+
+ elt = ucl_object_lookup (obj, "add_headers");
+ /*
+ * add_headers: {"name": "value", ... }
+ * name could have multiple values
+ */
+ if (elt && ucl_object_type (elt) == UCL_OBJECT) {
+ it = NULL;
+
+ while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
+ LL_FOREACH (cur, cur_elt) {
+ if (ucl_object_type (cur_elt) == UCL_STRING) {
+ hname = g_string_new (ucl_object_key (cur));
+ hvalue = g_string_new (ucl_object_tostring (cur_elt));
+
+ rspamd_milter_send_action (session,
+ RSPAMD_MILTER_ADDHEADER,
+ hname, hvalue);
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+rspamd_milter_send_task_results (struct rspamd_milter_session *session,
+ const ucl_object_t *results)
+{
+ const ucl_object_t *elt;
+ struct rspamd_milter_private *priv = session->priv;
+ gint action = METRIC_ACTION_REJECT;
+ rspamd_fstring_t *xcode, *rcode, *reply = NULL;
+ GString *hname, *hvalue;
+
+ if (results == NULL) {
+ msg_err_milter ("cannot find scan results, tempfail");
+ rspamd_milter_send_action (session, RSPAMD_MILTER_TEMPFAIL);
+
+ return;
+ }
+
+ elt = ucl_object_lookup (results, "action");
+
+ if (!elt) {
+ msg_err_milter ("cannot find action in results, tempfail");
+ rspamd_milter_send_action (session, RSPAMD_MILTER_TEMPFAIL);
+
+ return;
+ }
+
+ rspamd_action_from_str (ucl_object_tostring (elt), &action);
+
+ elt = ucl_object_lookup (results, "messages");
+ if (elt) {
+ const ucl_object_t *smtp_res;
+ const gchar *msg;
+ gsize len = 0;
+
+ smtp_res = ucl_object_lookup (elt, "smtp_message");
+
+ if (smtp_res) {
+ msg = ucl_object_tolstring (smtp_res, &len);
+ reply = rspamd_fstring_new_init (msg, len);
+ }
+ }
+
+ /* Deal with milter headers */
+ elt = ucl_object_lookup (results, "rmilter");
+ if (elt) {
+ rspamd_milter_process_rmilter_block (session, elt);
+ }
+
+ /* DKIM-Signature */
+ elt = ucl_object_lookup (results, "dkim-signature");
+ if (elt) {
+ hname = g_string_new (RSPAMD_MILTER_DKIM_HEADER);
+ hvalue = g_string_new (ucl_object_tostring (elt));
+
+ rspamd_milter_send_action (session, RSPAMD_MILTER_ADDHEADER,
+ hname, hvalue);
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ }
+
+ switch (action) {
+ case METRIC_ACTION_REJECT:
+ rcode = rspamd_fstring_new_init (RSPAMD_MILTER_RCODE_REJECT,
+ sizeof (RSPAMD_MILTER_RCODE_REJECT) - 1);
+ xcode = rspamd_fstring_new_init (RSPAMD_MILTER_XCODE_REJECT,
+ sizeof (RSPAMD_MILTER_XCODE_REJECT) - 1);
+
+ if (!reply) {
+ reply = rspamd_fstring_new_init (RSPAMD_MILTER_REJECT_MESSAGE,
+ sizeof (RSPAMD_MILTER_REJECT_MESSAGE) - 1);
+ }
+
+ rspamd_milter_set_reply (session, rcode, xcode, reply);
+ rspamd_milter_send_action (session, RSPAMD_MILTER_REJECT);
+
+ break;
+ case METRIC_ACTION_SOFT_REJECT:
+ case METRIC_ACTION_GREYLIST:
+ rcode = rspamd_fstring_new_init (RSPAMD_MILTER_RCODE_TEMPFAIL,
+ sizeof (RSPAMD_MILTER_RCODE_TEMPFAIL) - 1);
+ xcode = rspamd_fstring_new_init (RSPAMD_MILTER_XCODE_TEMPFAIL,
+ sizeof (RSPAMD_MILTER_XCODE_TEMPFAIL) - 1);
+
+ if (!reply) {
+ reply = rspamd_fstring_new_init (RSPAMD_MILTER_TEMPFAIL_MESSAGE,
+ sizeof (RSPAMD_MILTER_TEMPFAIL_MESSAGE) - 1);
+ }
+
+ rspamd_milter_set_reply (session, rcode, xcode, reply);
+ rspamd_milter_send_action (session, RSPAMD_MILTER_REJECT);
+ break;
+
+ case METRIC_ACTION_REWRITE_SUBJECT:
+ elt = ucl_object_lookup (results, "subject");
+
+ if (elt) {
+ hname = g_string_new ("Subject");
+ hvalue = g_string_new (ucl_object_tostring (elt));
+
+ rspamd_milter_send_action (session, RSPAMD_MILTER_CHGHEADER,
+ (guint32)1, hname, hvalue);
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ }
+
+ rspamd_milter_send_action (session, RSPAMD_MILTER_ACCEPT);
+ break;
+
+ case METRIC_ACTION_ADD_HEADER:
+ hname = g_string_new (RSPAMD_MILTER_SPAM_HEADER);
+ hvalue = g_string_new ("Yes");
+
+ rspamd_milter_send_action (session, RSPAMD_MILTER_CHGHEADER,
+ (guint32)1, hname, hvalue);
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ rspamd_milter_send_action (session, RSPAMD_MILTER_ACCEPT);
+ break;
+
+ case METRIC_ACTION_NOACTION:
+ default:
+ rspamd_milter_send_action (session, RSPAMD_MILTER_ACCEPT);
+ break;
+ }
} \ No newline at end of file
diff --git a/src/libserver/milter.h b/src/libserver/milter.h
index 3786f3b7b..869bc892d 100644
--- a/src/libserver/milter.h
+++ b/src/libserver/milter.h
@@ -19,6 +19,7 @@
#include "config.h"
#include "fstring.h"
#include "addr.h"
+#include "contrib/libucl/ucl.h"
#include "ref.h"
enum rspamd_milter_reply {
@@ -134,4 +135,12 @@ struct rspamd_milter_session * rspamd_milter_session_ref (
struct rspamd_http_message * rspamd_milter_to_http (
struct rspamd_milter_session *session);
+/**
+ * Sends task results to the
+ * @param session
+ * @param results
+ */
+void rspamd_milter_send_task_results (struct rspamd_milter_session *session,
+ const ucl_object_t *results);
+
#endif
diff --git a/src/libserver/milter_internal.h b/src/libserver/milter_internal.h
index 4c01b8624..0008967ec 100644
--- a/src/libserver/milter_internal.h
+++ b/src/libserver/milter_internal.h
@@ -139,4 +139,13 @@ enum rspamd_milter_connect_proto {
#define RSPAMD_MILTER_MESSAGE_CHUNK 65536
+#define RSPAMD_MILTER_RCODE_REJECT "554"
+#define RSPAMD_MILTER_RCODE_TEMPFAIL "451"
+#define RSPAMD_MILTER_RCODE_LATER "452"
+#define RSPAMD_MILTER_XCODE_REJECT "5.7.1"
+#define RSPAMD_MILTER_XCODE_TEMPFAIL "4.7.1"
+#define RSPAMD_MILTER_REJECT_MESSAGE "Spam message rejected"
+#define RSPAMD_MILTER_TEMPFAIL_MESSAGE "Try again later"
+#define RSPAMD_MILTER_SPAM_HEADER "X-Spam"
+#define RSPAMD_MILTER_DKIM_HEADER "DKIM-Signature"
#endif
diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c
index 7ba8759d7..bb20306c5 100644
--- a/src/rspamd_proxy.c
+++ b/src/rspamd_proxy.c
@@ -1266,12 +1266,9 @@ proxy_backend_master_finish_handler (struct rspamd_http_connection *conn,
rspamd_upstream_ok (bk_conn->up);
if (session->client_milter_conn) {
- /*
- * TODO: convert reply to milter reply
- */
nsession = proxy_session_refresh (session);
- rspamd_milter_send_action (nsession->client_milter_conn,
- RSPAMD_MILTER_ACCEPT);
+ rspamd_milter_send_task_results (nsession->client_milter_conn,
+ session->master_conn->results);
REF_RELEASE (session);
rspamd_http_message_free (msg);
}
@@ -1323,12 +1320,9 @@ rspamd_proxy_scan_self_reply (struct rspamd_task *task)
}
if (session->client_milter_conn) {
- /*
- * TODO: convert reply to milter reply
- */
nsession = proxy_session_refresh (session);
- rspamd_milter_send_action (nsession->client_milter_conn,
- RSPAMD_MILTER_ACCEPT);
+ rspamd_milter_send_task_results (nsession->client_milter_conn,
+ session->master_conn->results);
rspamd_http_message_free (msg);
REF_RELEASE (session);
}