aboutsummaryrefslogtreecommitdiffstats
path: root/src/lmtp_proto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lmtp_proto.c')
-rw-r--r--src/lmtp_proto.c247
1 files changed, 157 insertions, 90 deletions
diff --git a/src/lmtp_proto.c b/src/lmtp_proto.c
index 81cd13607..ff00a5d3a 100644
--- a/src/lmtp_proto.c
+++ b/src/lmtp_proto.c
@@ -22,62 +22,64 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "main.h"
#include "cfg_file.h"
-#include "util.h"
+#include "config.h"
#include "lmtp.h"
#include "lmtp_proto.h"
+#include "main.h"
+#include "util.h"
/* Max line size as it is defined in rfc2822 */
#define OUTBUFSIZ 1000
/* LMTP commands */
-static f_str_t lhlo_command = {
+static f_str_t lhlo_command = {
.begin = "LHLO",
.len = sizeof ("LHLO") - 1
};
-static f_str_t mail_command = {
+static f_str_t mail_command = {
.begin = "MAIL FROM:",
.len = sizeof ("MAIL FROM:") - 1
};
-static f_str_t rcpt_command = {
+static f_str_t rcpt_command = {
.begin = "RCPT TO:",
.len = sizeof ("RCPT TO:") - 1
};
-static f_str_t data_command = {
+static f_str_t data_command = {
.begin = "DATA",
.len = sizeof ("DATA") - 1
};
-static f_str_t data_dot = {
+static f_str_t data_dot = {
.begin = ".\r\n",
.len = sizeof (".\r\n") - 1
};
-static const gchar *mail_regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
-static GRegex *mail_re = NULL;
+static const gchar *mail_regexp =
+ "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
+static GRegex *mail_re = NULL;
/*
- * Extract e-mail from read line
+ * Extract e-mail from read line
* return <> if no valid address detected
*/
-static gchar *
+static gchar *
extract_mail (rspamd_mempool_t * pool, f_str_t * line)
{
- GError *err = NULL;
- gchar *match;
- GMatchInfo *info;
+ GError *err = NULL;
+ gchar *match;
+ GMatchInfo *info;
if (mail_re == NULL) {
/* Compile regexp */
mail_re = g_regex_new (mail_regexp, G_REGEX_RAW, 0, &err);
}
- if (g_regex_match_full (mail_re, line->begin, line->len, 0, 0, &info, NULL) == TRUE) {
+ if (g_regex_match_full (mail_re, line->begin, line->len, 0, 0, &info,
+ NULL) == TRUE) {
match = rspamd_mempool_strdup (pool, g_match_info_fetch (info, 0));
g_match_info_free (info);
}
@@ -91,16 +93,18 @@ extract_mail (rspamd_mempool_t * pool, f_str_t * line)
static gboolean
out_lmtp_reply (struct rspamd_task *task, gint code, gchar *rcode, gchar *msg)
{
- gchar outbuf[OUTBUFSIZ];
- gint r;
+ gchar outbuf[OUTBUFSIZ];
+ gint r;
if (*rcode == '\0') {
r = rspamd_snprintf (outbuf, OUTBUFSIZ, "%d %s\r\n", code, msg);
}
else {
- r = rspamd_snprintf (outbuf, OUTBUFSIZ, "%d %s %s\r\n", code, rcode, msg);
+ r =
+ rspamd_snprintf (outbuf, OUTBUFSIZ, "%d %s %s\r\n", code, rcode,
+ msg);
}
- if (! rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE)) {
+ if (!rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE)) {
return FALSE;
}
return TRUE;
@@ -109,16 +113,19 @@ out_lmtp_reply (struct rspamd_task *task, gint code, gchar *rcode, gchar *msg)
gint
read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
{
- gchar *c, *rcpt;
- f_str_t fstr;
- gint i = 0, l = 0, size;
+ gchar *c, *rcpt;
+ f_str_t fstr;
+ gint i = 0, l = 0, size;
switch (lmtp->state) {
case LMTP_READ_LHLO:
/* Search LHLO line */
if ((i = fstrstri (line, &lhlo_command)) == -1) {
msg_info ("LHLO expected but not found");
- (void)out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need LHLO here");
+ (void)out_lmtp_reply (lmtp->task,
+ LMTP_BAD_CMD,
+ "5.0.0",
+ "Need LHLO here");
return -1;
}
else {
@@ -129,11 +136,12 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
i++;
c++;
}
- lmtp->task->helo = rspamd_mempool_alloc (lmtp->task->task_pool, line->len - i + 1);
+ lmtp->task->helo = rspamd_mempool_alloc (lmtp->task->task_pool,
+ line->len - i + 1);
/* Strlcpy makes string null terminated by design */
rspamd_strlcpy (lmtp->task->helo, c, line->len - i + 1);
lmtp->state = LMTP_READ_FROM;
- if (! out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok")) {
+ if (!out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok")) {
return -1;
}
return 0;
@@ -143,7 +151,10 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
/* Search MAIL FROM: line */
if ((i = fstrstri (line, &mail_command)) == -1) {
msg_info ("MAIL expected but not found");
- (void)out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need MAIL here");
+ (void)out_lmtp_reply (lmtp->task,
+ LMTP_BAD_CMD,
+ "5.0.0",
+ "Need MAIL here");
return -1;
}
else {
@@ -153,7 +164,7 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
fstr.len = line->len - i;
lmtp->task->from = extract_mail (lmtp->task->task_pool, &fstr);
lmtp->state = LMTP_READ_RCPT;
- if (! out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Sender ok")) {
+ if (!out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Sender ok")) {
return -1;
}
return 0;
@@ -163,7 +174,10 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
/* Search RCPT_TO: line */
if ((i = fstrstri (line, &rcpt_command)) == -1) {
msg_info ("RCPT expected but not found");
- (void)out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Need RCPT here");
+ (void)out_lmtp_reply (lmtp->task,
+ LMTP_NO_RCPT,
+ "5.5.4",
+ "Need RCPT here");
return -1;
}
else {
@@ -175,13 +189,17 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
if (*rcpt == '<' && *(rcpt + 1) == '>') {
/* Invalid or empty rcpt not allowed */
msg_info ("bad recipient");
- (void)out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Bad recipient");
+ (void)out_lmtp_reply (lmtp->task,
+ LMTP_NO_RCPT,
+ "5.5.4",
+ "Bad recipient");
return -1;
}
/* Strlcpy makes string null terminated by design */
lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt);
lmtp->state = LMTP_READ_DATA;
- if (! out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Recipient ok")) {
+ if (!out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0",
+ "Recipient ok")) {
return -1;
}
return 0;
@@ -191,7 +209,10 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
/* Search DATA line */
if ((i = fstrstri (line, &data_command)) == -1) {
msg_info ("DATA expected but not found");
- (void)out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need DATA here");
+ (void)out_lmtp_reply (lmtp->task,
+ LMTP_BAD_CMD,
+ "5.0.0",
+ "Need DATA here");
return -1;
}
else {
@@ -201,12 +222,14 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
while (g_ascii_isspace (*c++)) {
i++;
}
- rcpt = rspamd_mempool_alloc (lmtp->task->task_pool, line->len - i + 1);
+ rcpt = rspamd_mempool_alloc (lmtp->task->task_pool,
+ line->len - i + 1);
/* Strlcpy makes string null terminated by design */
rspamd_strlcpy (rcpt, c, line->len - i + 1);
lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt);
lmtp->state = LMTP_READ_MESSAGE;
- if (! out_lmtp_reply (lmtp->task, LMTP_DATA, "", "Enter message, ending with \".\" on a line by itself")) {
+ if (!out_lmtp_reply (lmtp->task, LMTP_DATA, "",
+ "Enter message, ending with \".\" on a line by itself")) {
return -1;
}
lmtp->task->msg = fstralloc (lmtp->task->task_pool, BUFSIZ);
@@ -231,17 +254,19 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
/* size *= 2 */
size <<= 1;
}
- lmtp->task->msg = fstrgrow (lmtp->task->task_pool, lmtp->task->msg, size);
+ lmtp->task->msg = fstrgrow (lmtp->task->task_pool,
+ lmtp->task->msg,
+ size);
}
fstrcat (lmtp->task->msg, line);
return 0;
}
break;
case LMTP_READ_DOT:
- /* We have some input after reading dot, close connection as we have no currently support of multiply
+ /* We have some input after reading dot, close connection as we have no currently support of multiply
* messages per session
*/
- if (! out_lmtp_reply (lmtp->task, LMTP_QUIT, "", "Bye")) {
+ if (!out_lmtp_reply (lmtp->task, LMTP_QUIT, "", "Bye")) {
return -1;
}
return 0;
@@ -252,8 +277,8 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
}
struct mta_callback_data {
- struct rspamd_task *task;
- rspamd_io_dispatcher_t *dispatcher;
+ struct rspamd_task *task;
+ rspamd_io_dispatcher_t *dispatcher;
enum {
LMTP_WANT_GREETING,
LMTP_WANT_MAIL,
@@ -264,18 +289,20 @@ struct mta_callback_data {
} state;
};
-static gboolean
+static gboolean
parse_mta_str (f_str_t * in, struct mta_callback_data *cd)
{
- gint r;
- static f_str_t okres1 = {
+ gint r;
+ static f_str_t okres1 = {
.begin = "250 ",
.len = sizeof ("250 ") - 1,
}
, okres2 = {
- .begin = "220 ",.len = sizeof ("220 ") - 1,}
+ .begin = "220 ",.len = sizeof ("220 ") - 1,
+ }
, datares = {
- .begin = "354 ",.len = sizeof ("354 ") - 1,};
+ .begin = "354 ",.len = sizeof ("354 ") - 1,
+ };
switch (cd->state) {
case LMTP_WANT_GREETING:
@@ -301,12 +328,12 @@ close_mta_connection (struct mta_callback_data *cd, gboolean is_success)
{
cd->task->state = CLOSING_CONNECTION;
if (is_success) {
- if (! out_lmtp_reply (cd->task, LMTP_OK, "", "Delivery completed")) {
+ if (!out_lmtp_reply (cd->task, LMTP_OK, "", "Delivery completed")) {
return;
}
}
else {
- if (! out_lmtp_reply (cd->task, LMTP_FAILURE, "", "Delivery failure")) {
+ if (!out_lmtp_reply (cd->task, LMTP_FAILURE, "", "Delivery failure")) {
return;
}
}
@@ -316,19 +343,20 @@ close_mta_connection (struct mta_callback_data *cd, gboolean is_success)
/*
* Callback that is called when there is data to read in buffer
*/
-static gboolean
+static gboolean
mta_read_socket (f_str_t * in, void *arg)
{
- struct mta_callback_data *cd = (struct mta_callback_data *)arg;
- gchar outbuf[1024], *hostbuf, *c;
- gint hostmax, r;
- GList *cur;
- static f_str_t contres1 = {
+ struct mta_callback_data *cd = (struct mta_callback_data *)arg;
+ gchar outbuf[1024], *hostbuf, *c;
+ gint hostmax, r;
+ GList *cur;
+ static f_str_t contres1 = {
.begin = "250-",
.len = sizeof ("250-") - 1,
}
, contres2 = {
- .begin = "220-",.len = sizeof ("220-") - 1,};
+ .begin = "220-",.len = sizeof ("220-") - 1,
+ };
if (fstrstr (in, &contres1) != -1 || fstrstr (in, &contres2) != -1) {
/* Skip such lines */
@@ -347,12 +375,19 @@ mta_read_socket (f_str_t * in, void *arg)
gethostname (hostbuf, hostmax);
hostbuf[hostmax - 1] = '\0';
if (cd->task->cfg->deliver_lmtp) {
- r = rspamd_snprintf (outbuf, sizeof (outbuf), "LHLO %s" CRLF, hostbuf);
+ r = rspamd_snprintf (outbuf,
+ sizeof (outbuf),
+ "LHLO %s" CRLF,
+ hostbuf);
}
else {
- r = rspamd_snprintf (outbuf, sizeof (outbuf), "HELO %s" CRLF, hostbuf);
+ r = rspamd_snprintf (outbuf,
+ sizeof (outbuf),
+ "HELO %s" CRLF,
+ hostbuf);
}
- if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) {
+ if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE,
+ FALSE)) {
return FALSE;
}
cd->state = LMTP_WANT_MAIL;
@@ -363,8 +398,12 @@ mta_read_socket (f_str_t * in, void *arg)
close_mta_connection (cd, FALSE);
return FALSE;
}
- r = rspamd_snprintf (outbuf, sizeof (outbuf), "MAIL FROM: <%s>" CRLF, cd->task->from);
- if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) {
+ r = rspamd_snprintf (outbuf,
+ sizeof (outbuf),
+ "MAIL FROM: <%s>" CRLF,
+ cd->task->from);
+ if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE,
+ FALSE)) {
return FALSE;
}
cd->state = LMTP_WANT_RCPT;
@@ -378,11 +417,15 @@ mta_read_socket (f_str_t * in, void *arg)
cur = g_list_first (cd->task->rcpt);
r = 0;
while (cur) {
- r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "RCPT TO: <%s>" CRLF, (gchar *)cur->data);
+ r += rspamd_snprintf (outbuf + r,
+ sizeof (outbuf) - r,
+ "RCPT TO: <%s>" CRLF,
+ (gchar *)cur->data);
cur = g_list_next (cur);
}
- if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) {
+ if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE,
+ FALSE)) {
return FALSE;
}
cd->state = LMTP_WANT_DATA;
@@ -394,7 +437,8 @@ mta_read_socket (f_str_t * in, void *arg)
return FALSE;
}
r = rspamd_snprintf (outbuf, sizeof (outbuf), "DATA" CRLF);
- if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) {
+ if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE,
+ FALSE)) {
return FALSE;
}
cd->state = LMTP_WANT_DOT;
@@ -407,12 +451,14 @@ mta_read_socket (f_str_t * in, void *arg)
}
c = g_mime_object_to_string ((GMimeObject *) cd->task->message);
r = strlen (c);
- if (! rspamd_dispatcher_write (cd->task->dispatcher, c, r, TRUE, TRUE)) {
+ if (!rspamd_dispatcher_write (cd->task->dispatcher, c, r, TRUE, TRUE)) {
return FALSE;
}
- rspamd_mempool_add_destructor (cd->task->task_pool, (rspamd_mempool_destruct_t) g_free, c);
+ rspamd_mempool_add_destructor (cd->task->task_pool,
+ (rspamd_mempool_destruct_t) g_free, c);
r = rspamd_snprintf (outbuf, sizeof (outbuf), CRLF "." CRLF);
- if (! rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE)) {
+ if (!rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE,
+ FALSE)) {
return FALSE;
}
cd->state = LMTP_WANT_CLOSING;
@@ -436,7 +482,7 @@ mta_read_socket (f_str_t * in, void *arg)
static void
mta_err_socket (GError * err, void *arg)
{
- struct mta_callback_data *cd = (struct mta_callback_data *)arg;
+ struct mta_callback_data *cd = (struct mta_callback_data *)arg;
msg_info ("abnormaly terminating connection with MTA");
close_mta_connection (cd, FALSE);
}
@@ -447,36 +493,54 @@ mta_err_socket (GError * err, void *arg)
static gint
lmtp_deliver_mta (struct rspamd_task *task)
{
- gint sock;
- struct sockaddr_un *un;
- struct mta_callback_data *cd;
+ gint sock;
+ struct sockaddr_un *un;
+ struct mta_callback_data *cd;
if (task->cfg->deliver_family == AF_UNIX) {
un = alloca (sizeof (struct sockaddr_un));
- sock = make_unix_socket (task->cfg->deliver_host, un, SOCK_STREAM, FALSE, TRUE);
+ sock = make_unix_socket (task->cfg->deliver_host,
+ un,
+ SOCK_STREAM,
+ FALSE,
+ TRUE);
}
else {
- sock = make_universal_socket (task->cfg->deliver_host, task->cfg->deliver_port,
- SOCK_STREAM, TRUE, FALSE, TRUE);
+ sock = make_universal_socket (task->cfg->deliver_host,
+ task->cfg->deliver_port,
+ SOCK_STREAM,
+ TRUE,
+ FALSE,
+ TRUE);
}
if (sock == -1) {
- msg_warn ("cannot create socket for %s, %s", task->cfg->deliver_host, strerror (errno));
+ msg_warn ("cannot create socket for %s, %s",
+ task->cfg->deliver_host,
+ strerror (errno));
}
- cd = rspamd_mempool_alloc (task->task_pool, sizeof (struct mta_callback_data));
+ cd = rspamd_mempool_alloc (task->task_pool,
+ sizeof (struct mta_callback_data));
cd->task = task;
cd->state = LMTP_WANT_GREETING;
- cd->dispatcher = rspamd_create_dispatcher (task->ev_base, sock, BUFFER_LINE, mta_read_socket, NULL, mta_err_socket, NULL, (void *)cd);
+ cd->dispatcher = rspamd_create_dispatcher (task->ev_base,
+ sock,
+ BUFFER_LINE,
+ mta_read_socket,
+ NULL,
+ mta_err_socket,
+ NULL,
+ (void *)cd);
return 0;
}
-static gchar *
+static gchar *
format_lda_args (struct rspamd_task *task)
{
- gchar *res, *c, *r;
- size_t len;
- GList *rcpt;
- gboolean got_args = FALSE;
+ gchar *res, *c, *r;
+ size_t len;
+ GList *rcpt;
+ gboolean got_args = FALSE;
c = task->cfg->deliver_agent_path;
/* Find first arg */
@@ -557,10 +621,10 @@ format_lda_args (struct rspamd_task *task)
static gint
lmtp_deliver_lda (struct rspamd_task *task)
{
- gchar *args, **argv;
- GMimeStream *stream;
- gint rc, ecode, p[2], argc;
- pid_t cpid, pid;
+ gchar *args, **argv;
+ GMimeStream *stream;
+ gint rc, ecode, p[2], argc;
+ pid_t cpid, pid;
if ((args = format_lda_args (task)) == NULL) {
return -1;
@@ -609,7 +673,8 @@ lmtp_deliver_lda (struct rspamd_task *task)
close (p[0]);
stream = g_mime_stream_fs_new (p[1]);
- if (g_mime_object_write_to_stream ((GMimeObject *) task->message, stream) == -1) {
+ if (g_mime_object_write_to_stream ((GMimeObject *) task->message,
+ stream) == -1) {
g_strfreev (argv);
msg_info ("cannot write stream to lda");
return -1;
@@ -667,12 +732,13 @@ lmtp_deliver_message (struct rspamd_task *task)
gint
write_lmtp_reply (struct rspamd_lmtp_proto *lmtp)
{
- gint r;
- struct rspamd_task *task = lmtp->task;
+ gint r;
+ struct rspamd_task *task = lmtp->task;
debug_task ("writing reply to client");
if (lmtp->task->error_code != 0) {
- if (! out_lmtp_reply (lmtp->task, lmtp->task->error_code, "", lmtp->task->last_error)) {
+ if (!out_lmtp_reply (lmtp->task, lmtp->task->error_code, "",
+ lmtp->task->last_error)) {
return -1;
}
}
@@ -683,7 +749,8 @@ write_lmtp_reply (struct rspamd_lmtp_proto *lmtp)
return -1;
}
else if (r == 0) {
- if (! out_lmtp_reply (lmtp->task, LMTP_OK, "", "Delivery completed")) {
+ if (!out_lmtp_reply (lmtp->task, LMTP_OK, "",
+ "Delivery completed")) {
return -1;
}
}
@@ -695,6 +762,6 @@ write_lmtp_reply (struct rspamd_lmtp_proto *lmtp)
return 0;
}
-/*
- * vi:ts=4
+/*
+ * vi:ts=4
*/