diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-07-23 12:53:08 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-07-23 12:53:08 +0100 |
commit | fe79d8c5a39f2b717f78cc3f3ef21b3cfc46500b (patch) | |
tree | c84e6a5d4c5cd78a7a2cc3c7adbc7af5d0541682 /src/libmime/smtp_proto.c | |
parent | e0483657ff6cf1adc828ccce457814d61fe90a0d (diff) | |
download | rspamd-fe79d8c5a39f2b717f78cc3f3ef21b3cfc46500b.tar.gz rspamd-fe79d8c5a39f2b717f78cc3f3ef21b3cfc46500b.zip |
Revert "Unify code style."
This reverts commit e0483657ff6cf1adc828ccce457814d61fe90a0d.
Diffstat (limited to 'src/libmime/smtp_proto.c')
-rw-r--r-- | src/libmime/smtp_proto.c | 799 |
1 files changed, 361 insertions, 438 deletions
diff --git a/src/libmime/smtp_proto.c b/src/libmime/smtp_proto.c index 3c8395784..3af1c3910 100644 --- a/src/libmime/smtp_proto.c +++ b/src/libmime/smtp_proto.c @@ -22,24 +22,21 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "cfg_file.h" #include "config.h" #include "main.h" +#include "cfg_file.h" +#include "util.h" #include "smtp.h" #include "smtp_proto.h" #include "smtp_utils.h" -#include "util.h" -gchar * -make_smtp_error (rspamd_mempool_t *pool, - gint error_code, - const gchar *format, - ...) +gchar * +make_smtp_error (rspamd_mempool_t *pool, gint error_code, const gchar *format, ...) { - va_list vp; - gchar *result = NULL, *p; - size_t len; - + va_list vp; + gchar *result = NULL, *p; + size_t len; + va_start (vp, format); len = g_printf_string_upper_bound (format, vp); va_end (vp); @@ -56,9 +53,7 @@ make_smtp_error (rspamd_mempool_t *pool, gboolean -parse_smtp_command (struct smtp_session *session, - f_str_t *line, - struct smtp_command **cmd) +parse_smtp_command (struct smtp_session *session, f_str_t *line, struct smtp_command **cmd) { enum { SMTP_PARSE_START = 0, @@ -66,11 +61,11 @@ parse_smtp_command (struct smtp_session *session, SMTP_PARSE_ARGUMENT, SMTP_PARSE_DONE } state; - gchar *p, *c, ch, cmd_buf[4]; - guint i; - f_str_t *arg = NULL; - struct smtp_command *pcmd; - + gchar *p, *c, ch, cmd_buf[4]; + guint i; + f_str_t *arg = NULL; + struct smtp_command *pcmd; + if (line->len == 0) { return FALSE; } @@ -81,129 +76,125 @@ parse_smtp_command (struct smtp_session *session, *cmd = rspamd_mempool_alloc0 (session->pool, sizeof (struct smtp_command)); pcmd = *cmd; - for (i = 0; i < line->len; i++, p++) { + for (i = 0; i < line->len; i ++, p ++) { ch = *p; switch (state) { - case SMTP_PARSE_START: - if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == - line->len - 1) { - if (i == line->len - 1) { - p++; - } - if (p - c == 4) { - cmd_buf[0] = g_ascii_toupper (c[0]); - cmd_buf[1] = g_ascii_toupper (c[1]); - cmd_buf[2] = g_ascii_toupper (c[2]); - cmd_buf[3] = g_ascii_toupper (c[3]); - - if (memcmp (cmd_buf, "HELO", 4) == 0) { - pcmd->command = SMTP_COMMAND_HELO; - } - else if (memcmp (cmd_buf, "EHLO", 4) == 0) { - pcmd->command = SMTP_COMMAND_EHLO; - } - else if (memcmp (cmd_buf, "MAIL", 4) == 0) { - pcmd->command = SMTP_COMMAND_MAIL; + case SMTP_PARSE_START: + if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == line->len - 1) { + if (i == line->len - 1) { + p ++; } - else if (memcmp (cmd_buf, "RCPT", 4) == 0) { - pcmd->command = SMTP_COMMAND_RCPT; + if (p - c == 4) { + cmd_buf[0] = g_ascii_toupper (c[0]); + cmd_buf[1] = g_ascii_toupper (c[1]); + cmd_buf[2] = g_ascii_toupper (c[2]); + cmd_buf[3] = g_ascii_toupper (c[3]); + + if (memcmp (cmd_buf, "HELO", 4) == 0) { + pcmd->command = SMTP_COMMAND_HELO; + } + else if (memcmp (cmd_buf, "EHLO", 4) == 0) { + pcmd->command = SMTP_COMMAND_EHLO; + } + else if (memcmp (cmd_buf, "MAIL", 4) == 0) { + pcmd->command = SMTP_COMMAND_MAIL; + } + else if (memcmp (cmd_buf, "RCPT", 4) == 0) { + pcmd->command = SMTP_COMMAND_RCPT; + } + else if (memcmp (cmd_buf, "DATA", 4) == 0) { + pcmd->command = SMTP_COMMAND_DATA; + } + else if (memcmp (cmd_buf, "QUIT", 4) == 0) { + pcmd->command = SMTP_COMMAND_QUIT; + } + else if (memcmp (cmd_buf, "NOOP", 4) == 0) { + pcmd->command = SMTP_COMMAND_NOOP; + } + else if (memcmp (cmd_buf, "EXPN", 4) == 0) { + pcmd->command = SMTP_COMMAND_EXPN; + } + else if (memcmp (cmd_buf, "RSET", 4) == 0) { + pcmd->command = SMTP_COMMAND_RSET; + } + else if (memcmp (cmd_buf, "HELP", 4) == 0) { + pcmd->command = SMTP_COMMAND_HELP; + } + else if (memcmp (cmd_buf, "VRFY", 4) == 0) { + pcmd->command = SMTP_COMMAND_VRFY; + } + else { + msg_info ("invalid command: %*s", 4, cmd_buf); + return FALSE; + } } - else if (memcmp (cmd_buf, "DATA", 4) == 0) { - pcmd->command = SMTP_COMMAND_DATA; - } - else if (memcmp (cmd_buf, "QUIT", 4) == 0) { - pcmd->command = SMTP_COMMAND_QUIT; - } - else if (memcmp (cmd_buf, "NOOP", 4) == 0) { - pcmd->command = SMTP_COMMAND_NOOP; - } - else if (memcmp (cmd_buf, "EXPN", 4) == 0) { - pcmd->command = SMTP_COMMAND_EXPN; + else { + /* Invalid command */ + msg_info ("invalid command: %*s", 4, c); + return FALSE; } - else if (memcmp (cmd_buf, "RSET", 4) == 0) { - pcmd->command = SMTP_COMMAND_RSET; + /* Now check what we have */ + if (ch == ' ' || ch == ':') { + state = SMTP_PARSE_SPACES; } - else if (memcmp (cmd_buf, "HELP", 4) == 0) { - pcmd->command = SMTP_COMMAND_HELP; + else if (ch == CR) { + state = SMTP_PARSE_DONE; } - else if (memcmp (cmd_buf, "VRFY", 4) == 0) { - pcmd->command = SMTP_COMMAND_VRFY; - } - else { - msg_info ("invalid command: %*s", 4, cmd_buf); - return FALSE; + else if (ch == LF) { + return TRUE; } } - else { - /* Invalid command */ - msg_info ("invalid command: %*s", 4, c); + else if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { + msg_info ("invalid letter code in SMTP command: %d", (gint)ch); return FALSE; } - /* Now check what we have */ - if (ch == ' ' || ch == ':') { - state = SMTP_PARSE_SPACES; - } - else if (ch == CR) { + break; + case SMTP_PARSE_SPACES: + if (ch == CR) { state = SMTP_PARSE_DONE; } else if (ch == LF) { - return TRUE; + goto end; } - } - else if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { - msg_info ("invalid letter code in SMTP command: %d", (gint)ch); - return FALSE; - } - break; - case SMTP_PARSE_SPACES: - if (ch == CR) { - state = SMTP_PARSE_DONE; - } - else if (ch == LF) { - goto end; - } - else if (ch != ' ' && ch != ':') { - state = SMTP_PARSE_ARGUMENT; - arg = rspamd_mempool_alloc (session->pool, sizeof (f_str_t)); - c = p; - } - break; - case SMTP_PARSE_ARGUMENT: - if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == - line->len - 1) { - if (i == line->len - 1 && (ch != ' ' && ch != CR && ch != LF)) { - p++; - } - arg->len = p - c; - arg->begin = rspamd_mempool_alloc (session->pool, arg->len); - memcpy (arg->begin, c, arg->len); - pcmd->args = g_list_prepend (pcmd->args, arg); - if (ch == ' ' || ch == ':') { - state = SMTP_PARSE_SPACES; - } - else if (ch == CR) { - state = SMTP_PARSE_DONE; + else if (ch != ' ' && ch != ':') { + state = SMTP_PARSE_ARGUMENT; + arg = rspamd_mempool_alloc (session->pool, sizeof (f_str_t)); + c = p; } - else { + break; + case SMTP_PARSE_ARGUMENT: + if (ch == ' ' || ch == ':' || ch == CR || ch == LF || i == line->len - 1) { + if (i == line->len - 1 && (ch != ' ' && ch != CR && ch != LF)) { + p ++; + } + arg->len = p - c; + arg->begin = rspamd_mempool_alloc (session->pool, arg->len); + memcpy (arg->begin, c, arg->len); + pcmd->args = g_list_prepend (pcmd->args, arg); + if (ch == ' ' || ch == ':') { + state = SMTP_PARSE_SPACES; + } + else if (ch == CR) { + state = SMTP_PARSE_DONE; + } + else { + goto end; + } + } + break; + case SMTP_PARSE_DONE: + if (ch == LF) { goto end; } - } - break; - case SMTP_PARSE_DONE: - if (ch == LF) { - goto end; - } - msg_info ("CR without LF in SMTP command"); - return FALSE; + msg_info ("CR without LF in SMTP command"); + return FALSE; } } end: if (pcmd->args) { pcmd->args = g_list_reverse (pcmd->args); - rspamd_mempool_add_destructor (session->pool, - (rspamd_mempool_destruct_t)g_list_free, - pcmd->args); + rspamd_mempool_add_destructor (session->pool, (rspamd_mempool_destruct_t)g_list_free, pcmd->args); } return TRUE; } @@ -211,14 +202,14 @@ end: static gboolean check_smtp_path (f_str_t *path) { - guint i; - gchar *p; + guint i; + gchar *p; p = path->begin; if (*p != '<' || path->len < 2) { return FALSE; } - for (i = 0; i < path->len; i++, p++) { + for (i = 0; i < path->len; i++, p ++) { if (*p == '>' && i != path->len - 1) { return FALSE; } @@ -230,7 +221,7 @@ check_smtp_path (f_str_t *path) gboolean parse_smtp_helo (struct smtp_session *session, struct smtp_command *cmd) { - f_str_t *arg; + f_str_t *arg; if (cmd->args == NULL) { session->error = SMTP_ERROR_BAD_ARGUMENTS; @@ -265,8 +256,8 @@ parse_smtp_helo (struct smtp_session *session, struct smtp_command *cmd) gboolean parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd) { - f_str_t *arg; - GList *cur = cmd->args; + f_str_t *arg; + GList *cur = cmd->args; if (cmd->args == NULL) { session->error = SMTP_ERROR_BAD_ARGUMENTS; @@ -275,10 +266,10 @@ parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd) arg = cur->data; /* First argument MUST be FROM */ if (arg->len != 4 || ( - g_ascii_toupper (arg->begin[0]) != 'F' || - g_ascii_toupper (arg->begin[1]) != 'R' || - g_ascii_toupper (arg->begin[2]) != 'O' || - g_ascii_toupper (arg->begin[3]) != 'M')) { + g_ascii_toupper (arg->begin[0]) != 'F' || + g_ascii_toupper (arg->begin[1]) != 'R' || + g_ascii_toupper (arg->begin[2]) != 'O' || + g_ascii_toupper (arg->begin[3]) != 'M')) { session->error = SMTP_ERROR_BAD_ARGUMENTS; return FALSE; } @@ -303,8 +294,8 @@ parse_smtp_from (struct smtp_session *session, struct smtp_command *cmd) gboolean parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd) { - f_str_t *arg; - GList *cur = cmd->args; + f_str_t *arg; + GList *cur = cmd->args; if (cmd->args == NULL) { session->error = SMTP_ERROR_BAD_ARGUMENTS; @@ -313,8 +304,8 @@ parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd) arg = cur->data; /* First argument MUST be FROM */ if (arg->len != 2 || ( - g_ascii_toupper (arg->begin[0]) != 'T' || - g_ascii_toupper (arg->begin[1]) != 'O')) { + g_ascii_toupper (arg->begin[0]) != 'T' || + g_ascii_toupper (arg->begin[1]) != 'O')) { session->error = SMTP_ERROR_BAD_ARGUMENTS; return FALSE; } @@ -341,7 +332,7 @@ parse_smtp_rcpt (struct smtp_session *session, struct smtp_command *cmd) static gint check_smtp_ustream_reply (f_str_t *in, gchar success_code) { - gchar *p; + gchar *p; /* Check for 250 at the begin of line */ if (in->len >= sizeof ("220 ") - 1) { @@ -366,13 +357,13 @@ check_smtp_ustream_reply (f_str_t *in, gchar success_code) size_t smtp_upstream_write_list (GList *args, gchar *buf, size_t buflen) { - GList *cur = args; - size_t r = 0; - f_str_t *arg; + GList *cur = args; + size_t r = 0; + f_str_t *arg; while (cur && r < buflen - 3) { arg = cur->data; - r += rspamd_snprintf (buf + r, buflen - r, " %V", arg); + r += rspamd_snprintf (buf + r, buflen - r, " %V", arg); cur = g_list_next (cur); } @@ -383,351 +374,288 @@ smtp_upstream_write_list (GList *args, gchar *buf, size_t buflen) return r; } -gboolean +gboolean smtp_upstream_write_socket (void *arg) { - struct smtp_session *session = arg; - + struct smtp_session *session = arg; + if (session->upstream_state == SMTP_STATE_IN_SENDFILE) { session->upstream_state = SMTP_STATE_AFTER_DATA; - return rspamd_dispatcher_write (session->upstream_dispatcher, - CRLF DATA_END_TRAILER, - sizeof (CRLF DATA_END_TRAILER) - 1, - FALSE, - TRUE); + return rspamd_dispatcher_write (session->upstream_dispatcher, CRLF DATA_END_TRAILER, sizeof (CRLF DATA_END_TRAILER) - 1, FALSE, TRUE); } return TRUE; } -gboolean +gboolean smtp_upstream_read_socket (f_str_t * in, void *arg) { - struct smtp_session *session = arg; - gchar outbuf[BUFSIZ]; - gint r; - + struct smtp_session *session = 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'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - in->len, FALSE, TRUE)) { - goto err; + case SMTP_STATE_GREETING: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; + else if (r == 1) { + if (session->ctx->use_xclient) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "XCLIENT NAME=%s ADDR=%s" CRLF, + session->resolved ? session->hostname : "[UNDEFINED]", + inet_ntoa (session->client_addr)); + session->upstream_state = SMTP_STATE_HELO; + return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); + } + else { + session->upstream_state = SMTP_STATE_FROM; + if (session->helo) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, + session->esmtp ? "EHLO" : "HELO", + session->helo); + } + else { + return smtp_upstream_read_socket (in, arg); + } + return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); + } } - destroy_session (session->s); - return FALSE; - } - else if (r == 1) { - if (session->ctx->use_xclient) { - r = rspamd_snprintf (outbuf, - sizeof (outbuf), - "XCLIENT NAME=%s ADDR=%s" CRLF, - session->resolved ? session->hostname : "[UNDEFINED]", - inet_ntoa (session->client_addr)); - session->upstream_state = SMTP_STATE_HELO; - return rspamd_dispatcher_write (session->upstream_dispatcher, - outbuf, - r, - FALSE, - FALSE); + break; + case SMTP_STATE_HELO: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; } - else { + else if (r == 1) { session->upstream_state = SMTP_STATE_FROM; if (session->helo) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, - session->esmtp ? "EHLO" : "HELO", - session->helo); + r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, + session->esmtp ? "EHLO" : "HELO", + session->helo); } else { return smtp_upstream_read_socket (in, arg); } - return rspamd_dispatcher_write (session->upstream_dispatcher, - outbuf, - r, - FALSE, - FALSE); + return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); } - } - break; - case SMTP_STATE_HELO: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - in->len, FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; - } - else if (r == 1) { - session->upstream_state = SMTP_STATE_FROM; - if (session->helo) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "%s %s" CRLF, - session->esmtp ? "EHLO" : "HELO", - session->helo); - } - else { - return smtp_upstream_read_socket (in, arg); - } - return rspamd_dispatcher_write (session->upstream_dispatcher, - outbuf, - r, - FALSE, - FALSE); - } - break; - case SMTP_STATE_FROM: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - in->len, FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; - } - else if (r == 1) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "MAIL FROM: "); - r += - smtp_upstream_write_list (session->from, - outbuf + r, - sizeof (outbuf) - r); - session->upstream_state = SMTP_STATE_RCPT; - return rspamd_dispatcher_write (session->upstream_dispatcher, - outbuf, - r, - FALSE, - FALSE); - } - break; - case SMTP_STATE_RCPT: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - in->len, FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; - } - else if (r == 1) { - r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); - session->cur_rcpt = g_list_first (session->rcpt); - r += smtp_upstream_write_list (session->cur_rcpt->data, - outbuf + r, - sizeof (outbuf) - r); - session->cur_rcpt = g_list_next (session->cur_rcpt); - session->upstream_state = SMTP_STATE_BEFORE_DATA; - return rspamd_dispatcher_write (session->upstream_dispatcher, - outbuf, - r, - FALSE, - FALSE); - } - break; - case SMTP_STATE_BEFORE_DATA: - r = check_smtp_ustream_reply (in, '2'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - in->len, FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; + break; + case SMTP_STATE_FROM: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; } - if (session->cur_rcpt) { - session->rcpt = g_list_delete_link (session->rcpt, - session->cur_rcpt); + else if (r == 1) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "MAIL FROM: "); + r += smtp_upstream_write_list (session->from, outbuf + r, sizeof (outbuf) - r); + session->upstream_state = SMTP_STATE_RCPT; + return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); } - else { - session->rcpt = - g_list_delete_link (session->rcpt, session->rcpt); + break; + case SMTP_STATE_RCPT: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; } - session->errors++; - session->state = SMTP_STATE_RCPT; - return TRUE; - } - else if (r == 1) { - if (session->cur_rcpt != NULL) { + else if (r == 1) { r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); - r += smtp_upstream_write_list (session->cur_rcpt, - outbuf + r, - sizeof (outbuf) - r); + session->cur_rcpt = g_list_first (session->rcpt); + r += smtp_upstream_write_list (session->cur_rcpt->data, outbuf + r, sizeof (outbuf) - r); session->cur_rcpt = g_list_next (session->cur_rcpt); - if (!rspamd_dispatcher_write (session->upstream_dispatcher, - outbuf, r, FALSE, FALSE)) { + session->upstream_state = SMTP_STATE_BEFORE_DATA; + return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE); + } + break; + case SMTP_STATE_BEFORE_DATA: + r = check_smtp_ustream_reply (in, '2'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { goto err; } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + if (session->cur_rcpt) { + session->rcpt = g_list_delete_link (session->rcpt, session->cur_rcpt); + } + else { + session->rcpt = g_list_delete_link (session->rcpt, session->rcpt); + } + session->errors ++; + session->state = SMTP_STATE_RCPT; + return TRUE; + } + else if (r == 1) { + if (session->cur_rcpt != NULL) { + r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: "); + r += smtp_upstream_write_list (session->cur_rcpt, outbuf + r, sizeof (outbuf) - r); + session->cur_rcpt = g_list_next (session->cur_rcpt); + if (! rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE)) { + goto err; + } + } + else { + session->upstream_state = SMTP_STATE_DATA; + rspamd_dispatcher_pause (session->upstream_dispatcher); + } + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* Write to client */ + if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + if (session->state == SMTP_STATE_WAIT_UPSTREAM) { + rspamd_dispatcher_restore (session->dispatcher); + session->state = SMTP_STATE_RCPT; + } } - else { - session->upstream_state = SMTP_STATE_DATA; - rspamd_dispatcher_pause (session->upstream_dispatcher); - } - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* Write to client */ - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - in->len, FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { - goto err; + break; + case SMTP_STATE_DATA: + r = check_smtp_ustream_reply (in, '3'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; } - if (session->state == SMTP_STATE_WAIT_UPSTREAM) { + else if (r == 1) { + if (! make_smtp_tempfile (session)) { + session->error = SMTP_ERROR_FILE; + session->state = SMTP_STATE_CRITICAL_ERROR; + rspamd_dispatcher_restore (session->dispatcher); + if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + goto err; + } + destroy_session (session->s); + return FALSE; + } + session->state = SMTP_STATE_AFTER_DATA; + session->error = SMTP_ERROR_DATA_OK; rspamd_dispatcher_restore (session->dispatcher); - session->state = SMTP_STATE_RCPT; + if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + goto err; + } + rspamd_dispatcher_pause (session->upstream_dispatcher); + rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, 0); + session->dispatcher->strip_eol = FALSE; + return TRUE; } - } - break; - case SMTP_STATE_DATA: - r = check_smtp_ustream_reply (in, '3'); - if (r == -1) { + break; + case SMTP_STATE_AFTER_DATA: session->error = rspamd_mempool_alloc (session->pool, in->len + 1); rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ - session->state = SMTP_STATE_CRITICAL_ERROR; + session->state = SMTP_STATE_DATA; rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - 0, FALSE, TRUE)) { + if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { goto err; } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { goto err; } - destroy_session (session->s); - return FALSE; - } - else if (r == 1) { - if (!make_smtp_tempfile (session)) { - session->error = SMTP_ERROR_FILE; + if (! rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, sizeof ("QUIT" CRLF) - 1, FALSE, TRUE)) { + goto err; + } + session->upstream_state = SMTP_STATE_END; + return TRUE; + break; + case SMTP_STATE_END: + r = check_smtp_ustream_reply (in, '5'); + if (r == -1) { + session->error = rspamd_mempool_alloc (session->pool, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); + /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, - session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + goto err; + } + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { goto err; } destroy_session (session->s); return FALSE; } - session->state = SMTP_STATE_AFTER_DATA; - session->error = SMTP_ERROR_DATA_OK; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - 0, FALSE, TRUE)) { - goto err; + else { + remove_normal_event (session->s, (event_finalizer_t)smtp_upstream_finalize_connection, session); } - rspamd_dispatcher_pause (session->upstream_dispatcher); - rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, 0); - session->dispatcher->strip_eol = FALSE; - return TRUE; - } - break; - case SMTP_STATE_AFTER_DATA: - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - session->state = SMTP_STATE_DATA; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, - FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - - 1, FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, - sizeof ("QUIT" CRLF) - 1, FALSE, TRUE)) { - goto err; - } - session->upstream_state = SMTP_STATE_END; - return TRUE; - break; - case SMTP_STATE_END: - r = check_smtp_ustream_reply (in, '5'); - if (r == -1) { - session->error = rspamd_mempool_alloc (session->pool, in->len + 1); - rspamd_strlcpy (session->error, in->begin, in->len + 1); - /* XXX: assume upstream errors as critical errors */ + return FALSE; + break; + default: + msg_err ("got upstream reply at unexpected state: %d, reply: %V", session->upstream_state, in); session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, - 0, FALSE, TRUE)) { + if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { goto err; } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, - sizeof (CRLF) - 1, FALSE, TRUE)) { + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { goto err; } destroy_session (session->s); return FALSE; - } - else { - remove_normal_event (session->s, - (event_finalizer_t)smtp_upstream_finalize_connection, - session); - } - return FALSE; - break; - default: - msg_err ("got upstream reply at unexpected state: %d, reply: %V", - session->upstream_state, - in); - session->state = SMTP_STATE_CRITICAL_ERROR; - rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, - FALSE, TRUE)) { - goto err; - } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - - 1, FALSE, TRUE)) { - goto err; - } - destroy_session (session->s); - return FALSE; } return TRUE; @@ -736,24 +664,20 @@ err: return FALSE; } -void +void smtp_upstream_err_socket (GError *err, void *arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; - msg_info ("abnormally closing connection with upstream %s, error: %s", - session->upstream->name, - err->message); + msg_info ("abnormally closing connection with upstream %s, error: %s", session->upstream->name, err->message); session->error = SMTP_ERROR_UPSTREAM; session->state = SMTP_STATE_CRITICAL_ERROR; /* XXX: assume upstream errors as critical errors */ rspamd_dispatcher_restore (session->dispatcher); - if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, - TRUE)) { + if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { return; } - if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, - FALSE, TRUE)) { + if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { return; } upstream_fail (&session->upstream->up, session->session_time); @@ -763,11 +687,10 @@ smtp_upstream_err_socket (GError *err, void *arg) void smtp_upstream_finalize_connection (gpointer data) { - struct smtp_session *session = data; - + struct smtp_session *session = data; + if (session->state != SMTP_STATE_CRITICAL_ERROR) { - if (!rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, - 0, FALSE, TRUE)) { + if (! rspamd_dispatcher_write (session->upstream_dispatcher, "QUIT" CRLF, 0, FALSE, TRUE)) { msg_warn ("cannot send correctly closing message to upstream"); } } |