aboutsummaryrefslogtreecommitdiffstats
path: root/src/libserver/milter.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-05-08 13:17:33 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-05-08 13:17:33 +0100
commit5f2ef07094e6c0b4116f4cc1122c8fe95ee2a651 (patch)
treec6811b7a6a1729804b0c1ba6213064e6a37f4355 /src/libserver/milter.c
parentc9b63f6a3d73d4ef8895391ff196dbc680895735 (diff)
downloadrspamd-5f2ef07094e6c0b4116f4cc1122c8fe95ee2a651.tar.gz
rspamd-5f2ef07094e6c0b4116f4cc1122c8fe95ee2a651.zip
[Feature] Implement milter protocol scan reply
Diffstat (limited to 'src/libserver/milter.c')
-rw-r--r--src/libserver/milter.c189
1 files changed, 189 insertions, 0 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