]> source.dussan.org Git - rspamd.git/commitdiff
* Initial approach to RESTful controller.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Fri, 14 Sep 2012 16:59:23 +0000 (20:59 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Fri, 14 Sep 2012 16:59:23 +0000 (20:59 +0400)
Fix security issues in fstring handling.

src/controller.c
src/fstring.c
src/main.h
src/protocol.c
src/protocol.h
src/smtp.c
src/smtp_proto.c

index c5aebb699426f550420219563f4858eff0ea9573..7bd90e7dba37a49eb942188ec9fc03b4d55861c2 100644 (file)
@@ -70,7 +70,9 @@ enum command_type {
        COMMAND_HELP,
        COMMAND_COUNTERS,
        COMMAND_SYNC,
-       COMMAND_WEIGHTS
+       COMMAND_WEIGHTS,
+       COMMAND_GET,
+       COMMAND_POST
 };
 
 struct controller_command {
@@ -106,7 +108,9 @@ static struct controller_command commands[] = {
        {"counters", FALSE, COMMAND_COUNTERS},
        {"sync", FALSE, COMMAND_SYNC},
        {"learn_spam", TRUE, COMMAND_LEARN_SPAM},
-       {"learn_ham", TRUE, COMMAND_LEARN_HAM}
+       {"learn_ham", TRUE, COMMAND_LEARN_HAM},
+       {"get", FALSE, COMMAND_GET},
+       {"post", FALSE, COMMAND_POST}
 };
 
 static GList                   *custom_commands = NULL;
@@ -190,6 +194,10 @@ free_session (void *ud)
        }
        rspamd_remove_dispatcher (session->dispatcher);
 
+       if (session->kwargs) {
+               g_hash_table_destroy (session->kwargs);
+       }
+
        close (session->sock);
 
        memory_pool_delete (session->session_pool);
@@ -467,6 +475,12 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
        struct rspamd_controller_ctx   *ctx = session->worker->ctx;
 
        switch (cmd->type) {
+       case COMMAND_GET:
+       case COMMAND_POST:
+               session->restful = TRUE;
+               session->state = STATE_HEADER;
+               session->kwargs = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
+               break;
        case COMMAND_PASSWORD:
                arg = *cmd_args;
                if (!arg || *arg == '\0') {
@@ -553,34 +567,65 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                break;
        case COMMAND_LEARN_SPAM:
                if (check_auth (cmd, session)) {
-                       arg = *cmd_args;
-                       if (!arg || *arg == '\0') {
-                               msg_debug ("no statfile specified in learn command");
-                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF);
-                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                                       return FALSE;
+                       if (!session->restful) {
+                               arg = *cmd_args;
+                               if (!arg || *arg == '\0') {
+                                       msg_debug ("no statfile specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
                                }
-                               return TRUE;
-                       }
-                       arg = *(cmd_args + 1);
-                       if (arg == NULL || *arg == '\0') {
-                               msg_debug ("no message size specified in learn command");
-                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: symbol and message size" CRLF);
-                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                                       return FALSE;
+                               arg = *(cmd_args + 1);
+                               if (arg == NULL || *arg == '\0') {
+                                       msg_debug ("no message size specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
                                }
-                               return TRUE;
+                               size = strtoul (arg, &err_str, 10);
+                               if (err_str && *err_str != '\0') {
+                                       msg_debug ("message size is invalid: %s", arg);
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
+                               }
+                               cl = find_classifier_conf (session->cfg, *cmd_args);
                        }
-                       size = strtoul (arg, &err_str, 10);
-                       if (err_str && *err_str != '\0') {
-                               msg_debug ("message size is invalid: %s", arg);
-                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
-                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                                       return FALSE;
+                       else {
+                               if ((arg = g_hash_table_lookup (session->kwargs, "classifier")) == NULL) {
+                                       msg_debug ("no classifier specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
+                               }
+                               else {
+                                       cl = find_classifier_conf (session->cfg, arg);
+                               }
+                               if ((arg = g_hash_table_lookup (session->kwargs, "content-length")) == NULL) {
+                                       msg_debug ("no size specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       return rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+                               }
+                               else {
+                                       size = strtoul (arg, &err_str, 10);
+                                       if (err_str && *err_str != '\0') {
+                                               msg_debug ("message size is invalid: %s", arg);
+                                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
+                                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                                       return FALSE;
+                                               }
+                                               return TRUE;
+                                       }
                                }
-                               return TRUE;
                        }
-                       cl = find_classifier_conf (session->cfg, *cmd_args);
 
                        session->learn_classifier = cl;
 
@@ -592,34 +637,65 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                break;
        case COMMAND_LEARN_HAM:
                if (check_auth (cmd, session)) {
-                       arg = *cmd_args;
-                       if (!arg || *arg == '\0') {
-                               msg_debug ("no statfile specified in learn command");
-                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF);
-                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                                       return FALSE;
+                       if (!session->restful) {
+                               arg = *cmd_args;
+                               if (!arg || *arg == '\0') {
+                                       msg_debug ("no statfile specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
                                }
-                               return TRUE;
-                       }
-                       arg = *(cmd_args + 1);
-                       if (arg == NULL || *arg == '\0') {
-                               msg_debug ("no message size specified in learn command");
-                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: symbol and message size" CRLF);
-                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                                       return FALSE;
+                               arg = *(cmd_args + 1);
+                               if (arg == NULL || *arg == '\0') {
+                                       msg_debug ("no message size specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
                                }
-                               return TRUE;
+                               size = strtoul (arg, &err_str, 10);
+                               if (err_str && *err_str != '\0') {
+                                       msg_debug ("message size is invalid: %s", arg);
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
+                               }
+                               cl = find_classifier_conf (session->cfg, *cmd_args);
                        }
-                       size = strtoul (arg, &err_str, 10);
-                       if (err_str && *err_str != '\0') {
-                               msg_debug ("message size is invalid: %s", arg);
-                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
-                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
-                                       return FALSE;
+                       else {
+                               if ((arg = g_hash_table_lookup (session->kwargs, "classifier")) == NULL) {
+                                       msg_debug ("no classifier specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                               return FALSE;
+                                       }
+                                       return TRUE;
+                               }
+                               else {
+                                       cl = find_classifier_conf (session->cfg, arg);
+                               }
+                               if ((arg = g_hash_table_lookup (session->kwargs, "content-length")) == NULL) {
+                                       msg_debug ("no size specified in learn command");
+                                       r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn_spam command requires at least two arguments: classifier name and a message's size" CRLF);
+                                       return rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+                               }
+                               else {
+                                       size = strtoul (arg, &err_str, 10);
+                                       if (err_str && *err_str != '\0') {
+                                               msg_debug ("message size is invalid: %s", arg);
+                                               r = rspamd_snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
+                                               if (! rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE)) {
+                                                       return FALSE;
+                                               }
+                                               return TRUE;
+                                       }
                                }
-                               return TRUE;
                        }
-                       cl = find_classifier_conf (session->cfg, *cmd_args);
 
                        session->learn_classifier = cl;
 
@@ -631,6 +707,7 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                break;
        case COMMAND_LEARN:
                if (check_auth (cmd, session)) {
+                       /* TODO: remove this command as currenly it should not be used anywhere */
                        arg = *cmd_args;
                        if (!arg || *arg == '\0') {
                                msg_debug ("no statfile specified in learn command");
@@ -722,6 +799,7 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
                break;
 
        case COMMAND_WEIGHTS:
+               /* TODO: remove this command as currenly it should not be used anywhere */
                arg = *cmd_args;
                if (!arg || *arg == '\0') {
                        msg_debug ("no statfile specified in weights command");
@@ -798,35 +876,39 @@ process_command (struct controller_command *cmd, gchar **cmd_args, struct contro
        return TRUE;
 }
 
-static                          gboolean
-process_custom_command (gchar *line, gchar **cmd_args, struct controller_session *session)
+static controller_func_t
+parse_custom_command (gchar *line, gchar **cmd_args, struct controller_session *session, gsize len)
 {
        GList                          *cur;
        struct custom_controller_command *cmd;
 
+       if (len == 0) {
+               len = strlen (line);
+       }
        cur = custom_commands;
        while (cur) {
                cmd = cur->data;
-               if (g_ascii_strcasecmp (cmd->command, line) == 0) {
-                       /* Call handler */
-                       cmd->handler (cmd_args, session);
-                       return TRUE;
+               if (g_ascii_strncasecmp (cmd->command, line, len) == 0) {
+                       return cmd->handler;
                }
                cur = g_list_next (cur);
        }
 
-       return FALSE;
+       return NULL;
 }
 
 static struct controller_command *
-process_normal_command (const gchar *line)
+parse_normal_command (const gchar *line, gsize len)
 {
        guint                           i;
        struct controller_command      *c;
 
+       if (len == 0) {
+               len = strlen (line);
+       }
        for (i = 0; i < G_N_ELEMENTS (commands); i ++) {
                c = &commands[i];
-               if (g_ascii_strcasecmp (line, c->command) == 0) {
+               if (g_ascii_strncasecmp (line, c->command, len) == 0) {
                        return c;
                }
        }
@@ -834,6 +916,58 @@ process_normal_command (const gchar *line)
        return NULL;
 }
 
+static gboolean
+process_header (f_str_t *line, struct controller_session *session)
+{
+       gchar                                                   *headern;
+       struct controller_command               *command;
+       struct rspamd_controller_ctx    *ctx = session->worker->ctx;
+       controller_func_t                                custom_handler;
+
+       headern = separate_command (line, ':');
+
+       if (line == NULL || headern == NULL) {
+               return FALSE;
+       }
+       /* Eat whitespaces */
+       g_strstrip (headern);
+       fstrstrip (line);
+
+       if (*headern == 'c' || *headern == 'C') {
+               if (g_ascii_strcasecmp (headern, "command") == 0) {
+                       /* This header is actually command */
+                       command = parse_normal_command (line->begin, line->len);
+                       if (command == NULL) {
+                               if ((custom_handler = parse_custom_command (line->begin, NULL, session, line->len)) == NULL) {
+                                       msg_info ("bad command header: %V", line);
+                                       return FALSE;
+                               }
+                               else {
+                                       session->custom_handler = custom_handler;
+                               }
+                       }
+                       session->cmd = command;
+                       return TRUE;
+               }
+       }
+       else if (*headern == 'p' || *headern == 'P') {
+               /* Password header */
+               if (g_ascii_strcasecmp (headern, "password") == 0) {
+                       if (line->len == strlen (ctx->password) && memcmp (line->begin, ctx->password, line->len) == 0) {
+                               session->authorized = TRUE;
+                       }
+                       else {
+                               msg_info ("wrong password in controller command");
+                       }
+                       return TRUE;
+               }
+       }
+
+       g_hash_table_insert (session->kwargs, headern, fstrcstr (line, session->session_pool));
+
+       return TRUE;
+}
+
 /*
  * Called if all filters are processed, non-threaded and simple version
  */
@@ -889,6 +1023,7 @@ controller_read_socket (f_str_t * in, void *arg)
        GTree                          *tokens = NULL;
        GError                         *err = NULL;
        f_str_t                         c;
+       controller_func_t                               custom_handler;
 
        switch (session->state) {
        case STATE_COMMAND:
@@ -901,24 +1036,27 @@ controller_read_socket (f_str_t * in, void *arg)
                if (len > 0) {
                        cmd = g_strstrip (params[0]);
 
-                       command = process_normal_command (cmd);
+                       command = parse_normal_command (cmd, 0);
                        if (command != NULL) {
                                if (! process_command (command, &params[1], session)) {
                                        return FALSE;
                                }
                        }
                        else {
-                               if (!process_custom_command (cmd, &params[1], session)) {
+                               if ((custom_handler = parse_custom_command (cmd, &params[1], session, 0)) == NULL) {
                                        msg_debug ("'%s'", cmd);
                                        i = rspamd_snprintf (out_buf, sizeof (out_buf), "Unknown command" CRLF);
                                        if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
                                                return FALSE;
                                        }
                                }
+                               else {
+                                       custom_handler (&params[1], session);
+                               }
                        }
                }
                if (session->state != STATE_LEARN && session->state != STATE_LEARN_SPAM_PRE
-                               && session->state != STATE_WEIGHTS && session->state != STATE_OTHER) {
+                               && session->state != STATE_WEIGHTS && session->state != STATE_OTHER && session->state != STATE_HEADER) {
                        if (!rspamd_dispatcher_write (session->dispatcher, END, sizeof (END) - 1, FALSE, TRUE)) {
                                return FALSE;
                        }
@@ -928,6 +1066,43 @@ controller_read_socket (f_str_t * in, void *arg)
                        }
                }
 
+               break;
+       case STATE_HEADER:
+               if (in->len == 0) {
+                       /* End of headers */
+                       if (session->cmd == NULL && session->custom_handler == NULL) {
+                               i = rspamd_snprintf (out_buf, sizeof (out_buf), "500 Bad command" CRLF);
+                               if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+                                       return FALSE;
+                               }
+                               destroy_session (session->s);
+                               return FALSE;
+                       }
+                       /* Perform command */
+                       else if (session->cmd != NULL) {
+                               if (! process_command (session->cmd, NULL, session)) {
+                                       destroy_session (session->s);
+                                       return FALSE;
+                               }
+                       }
+                       else {
+                               session->custom_handler (NULL, session);
+                       }
+                       if (session->state != STATE_LEARN && session->state != STATE_LEARN_SPAM_PRE
+                                       && session->state != STATE_WEIGHTS && session->state != STATE_OTHER) {
+                               destroy_session (session->s);
+                               return FALSE;
+                       }
+               }
+               if (!process_header (in, session)) {
+                       msg_debug ("'%V'", in);
+                       i = rspamd_snprintf (out_buf, sizeof (out_buf), "500 Bad header" CRLF);
+                       if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+                               return FALSE;
+                       }
+                       destroy_session (session->s);
+                       return FALSE;
+               }
                break;
        case STATE_LEARN:
                session->learn_buf = in;
@@ -1159,8 +1334,14 @@ controller_write_socket (void *arg)
                return TRUE;
        }
        else if (session->state == STATE_REPLY) {
-               session->state = STATE_COMMAND;
-               rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, BUFSIZ);
+               if (session->restful) {
+                       destroy_session (session->s);
+                       return FALSE;
+               }
+               else {
+                       session->state = STATE_COMMAND;
+                       rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, BUFSIZ);
+               }
        }
        rspamd_dispatcher_restore (session->dispatcher);
        return TRUE;
index 07b5546a02e684dc0b40786b08637ea026a4bf19..9f17ac861f1f1d11bf62b35618b2a7851588f920 100644 (file)
@@ -218,7 +218,8 @@ fstrcstr (f_str_t * str, memory_pool_t * pool)
        gchar                           *res;
        res = memory_pool_alloc (pool, str->len + 1);
 
-       memcpy (res, str->begin, str->len);
+       /* Do not allow multiply \0 characters */
+       memccpy (res, str->begin, '\0', str->len);
        res[str->len] = 0;
 
        return res;
index f90edf1d2e1cd5a6cf28813bcafc40384a6ed860..9a28793cd81d14d823bde1b1518c95cc5b4b4dc2 100644 (file)
@@ -131,10 +131,15 @@ union sa_union {
 /**
  * Control session object
  */
+struct controller_command;
+struct controller_session;
+typedef void (*controller_func_t)(gchar **args, struct controller_session *session);
+
 struct controller_session {
        struct rspamd_worker *worker;                                                           /**< pointer to worker structure (controller in fact) */
        enum {
                STATE_COMMAND,
+               STATE_HEADER,
                STATE_LEARN,
                STATE_LEARN_SPAM_PRE,
                STATE_LEARN_SPAM,
@@ -146,7 +151,10 @@ struct controller_session {
        } state;                                                                                                        /**< current session state                                                      */
        gint sock;                                                                                                      /**< socket descriptor                                                          */
        /* Access to authorized commands */
-       gint authorized;                                                                                                /**< whether this session is authorized                         */
+       gboolean authorized;                                                                            /**< whether this session is authorized                         */
+       gboolean restful;                                                                                       /**< whether this session is a restful session          */
+       GHashTable *kwargs;                                                                                     /**< keyword arguments for restful command                      */
+       struct controller_command *cmd;                                                         /**< real command                                                                       */
        memory_pool_t *session_pool;                                                            /**< memory pool for session                                            */
        struct config_file *cfg;                                                                        /**< pointer to config file                                                     */
        gchar *learn_rcpt;                                                                                      /**< recipient for learning                                                     */
@@ -161,14 +169,13 @@ struct controller_session {
        void (*other_handler)(struct controller_session *session, 
                        f_str_t *in);                                   /**< other command handler to execute at the end of processing */
        void *other_data;                                                                                       /**< and its data                                                                       */
+       controller_func_t custom_handler;                                                       /**< custom command handler                                                     */
        struct rspamd_async_session* s;                                                         /**< async session object                                                       */
        struct worker_task *learn_task;
        struct rspamd_dns_resolver *resolver;                                           /**< DNS resolver                                                                       */
        struct event_base *ev_base;                                                                     /**< Event base                                                                         */
 };
 
-typedef void (*controller_func_t)(gchar **args, struct controller_session *session);
-
 /**
  * Worker task structure
  */
index 4f6e0be385f96ad52497af35db4e9b99e2341d72..7df9ae67300a33261c4755dd5d88e416c95ee1b5 100644 (file)
@@ -123,7 +123,7 @@ rspamc_proto_str (guint ver)
        }
 }
 
-static gchar                    *
+gchar                    *
 separate_command (f_str_t * in, gchar c)
 {
        guint                            r = 0;
@@ -137,6 +137,11 @@ separate_command (f_str_t * in, gchar c)
                        in->len -= r + 1;
                        return b;
                }
+               else if (*p == '\0') {
+                       /* Actually we cannot allow several \0 characters in string, so write to the log about it */
+                       msg_warn ("cannot separate command with \0 character, this can be an attack attempt");
+                       return NULL;
+               }
                p++;
                r++;
        }
index de6d0ea03768e40f59b0e980920fe8dd8dbd49d1..72460940f9788697832bde424a7120f69bb09d1d 100644 (file)
@@ -57,6 +57,14 @@ struct custom_command {
        protocol_reply_func func;
 };
 
+/**
+ * Find a character in command in and return pointer to the first part of the string, in is modified to point to the second part of string
+ * @param in f_str_t input
+ * @param c separator character
+ * @return pointer to the first part of string or NULL if there is no separator found
+ */
+gchar* separate_command (f_str_t * in, gchar c);
+
 /**
  * Read one line of user's input for specified task
  * @param task task object
index 6e226c42ab0fc9959e10a78d8a52f7cead71e7f8..c1e8765e4dbda3082bbe444945587d3a92381577 100644 (file)
@@ -34,6 +34,7 @@
 #include "message.h"
 #include "settings.h"
 #include "dns.h"
+#include "lua/lua_common.h"
 
 /* Max line size as it is defined in rfc2822 */
 #define OUTBUFSIZ 1000
@@ -309,6 +310,7 @@ process_smtp_data (struct smtp_session *session)
                session->task->fin_callback = smtp_write_socket;
                session->task->fin_arg = session;
                session->task->msg = memory_pool_alloc (session->pool, sizeof (f_str_t));
+               session->task->s = session->s;
 #ifdef HAVE_MMAP_NOCORE
                if ((session->task->msg->begin = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_NOCORE, session->temp_fd, 0)) == MAP_FAILED) {
 #else
@@ -346,23 +348,22 @@ process_smtp_data (struct smtp_session *session)
                if (process_message (session->task) == -1) {
                        msg_err ("cannot process message");
                        munmap (session->task->msg->begin, st.st_size);
-                       msg_err ("process message failed: %s", strerror (errno));
                        goto err;
                }
-               r = process_filters (session->task);
-               if (r == -1) {
-                       munmap (session->task->msg->begin, st.st_size);
-                       msg_err ("cannot process filters");
-                       goto err;
-               }
-               else if (r == 0) {
-                       session->state = SMTP_STATE_END;
-                       rspamd_dispatcher_pause (session->dispatcher);
+               if (session->task->cfg->pre_filters == NULL) {
+                       r = process_filters (session->task);
+                       if (r == -1) {
+                               msg_err ("cannot process message");
+                               munmap (session->task->msg->begin, st.st_size);
+                               goto err;
+                       }
                }
                else {
-                       process_statfiles (session->task);
-                       session->state = SMTP_STATE_END;
-                       return smtp_write_socket (session);
+                       lua_call_pre_filters (session->task);
+                       /* We want fin_task after pre filters are processed */
+                       session->task->s->wanna_die = TRUE;
+                       session->task->state = WAIT_PRE_FILTER;
+                       check_session_pending (session->task->s);
                }
        }
        else {
index 2211411e1840589f4c89992bee4399eda27bdfa0..e1e7f32299f5358759b0fb089b81800c5a4b2dbc 100644 (file)
@@ -394,6 +394,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg)
        gchar                           outbuf[BUFSIZ];
        gint                            r;
        
+       msg_debug ("in: %V, state: %d", in, session->upstream_state);
        switch (session->upstream_state) {
                case SMTP_STATE_GREETING:
                        r = check_smtp_ustream_reply (in, '2');