From fe3ee5123602ac2b8af8d1209087c2c61274c8c5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 27 Feb 2011 10:49:15 +0100 Subject: mailtrain: redirect stdout/stderr to /dev/null for execv This fixes a bug where sa-learn and similar tools fail because they cannot write to stdout or stderr at all, and propagate the error (EBADF or such). --- mailtrain.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'mailtrain.c') diff --git a/mailtrain.c b/mailtrain.c index 41071bc..5529f03 100644 --- a/mailtrain.c +++ b/mailtrain.c @@ -71,7 +71,7 @@ static int run_sendmail(int mailfd, enum classification wanted) } else { char **argv; int sz = sizeof(char *) * (2 + extra_args_num + 1); - int i; + int i, fd; argv = i_malloc(sz); memset(argv, 0, sz); @@ -84,8 +84,10 @@ static int run_sendmail(int mailfd, enum classification wanted) argv[i + 1] = (char *) dest; dup2(mailfd, 0); - close(1); - close(2); + fd = open("/dev/null", O_WRONLY); + dup2(fd, 1); + dup2(fd, 2); + close(fd); execv(sendmail_binary, argv); _exit(1); /* not reached */ -- cgit v1.2.3 From 57cfc0aac9f8cc5d00fa1155367dfd055da27761 Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Sun, 27 Feb 2011 01:49:00 +0100 Subject: make backend selection at runtime --- mailtrain.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'mailtrain.c') diff --git a/mailtrain.c b/mailtrain.c index 5529f03..276eb4a 100644 --- a/mailtrain.c +++ b/mailtrain.c @@ -101,7 +101,7 @@ struct antispam_transaction_context { int tmplen; }; -struct antispam_transaction_context * +static struct antispam_transaction_context * backend_start(struct mailbox *box __attr_unused__) { struct antispam_transaction_context *ast; @@ -178,7 +178,7 @@ static void clear_tmpdir(struct antispam_transaction_context *ast) t_pop(); } -void backend_rollback(struct antispam_transaction_context *ast) +static void backend_rollback(struct antispam_transaction_context *ast) { if (ast->tmpdir) { /* clear it! */ @@ -189,8 +189,8 @@ void backend_rollback(struct antispam_transaction_context *ast) i_free(ast); } -int backend_commit(struct mailbox_transaction_context *ctx, - struct antispam_transaction_context *ast) +static int backend_commit(struct mailbox_transaction_context *ctx, + struct antispam_transaction_context *ast) { int ret; @@ -209,9 +209,9 @@ int backend_commit(struct mailbox_transaction_context *ctx, return ret; } -int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification wanted) +static int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification wanted) { struct istream *mailstream; struct ostream *outstream; @@ -310,7 +310,7 @@ int backend_handle_mail(struct mailbox_transaction_context *t, return ret; } -void backend_init(pool_t pool __attr_unused__) +static void backend_init(pool_t pool __attr_unused__) { const char *tmp; int i; @@ -349,6 +349,15 @@ void backend_init(pool_t pool __attr_unused__) debug("mail backend tmpdir %s\n", tmpdir); } -void backend_exit(void) +static void backend_exit(void) { } + +struct backend antispam_backend = { + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, +}; -- cgit v1.2.3 From ca91e1366a57ff45597168592781cdaf35af48a0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 27 Feb 2011 11:09:49 +0100 Subject: add an API version to the backend struct Just to make sure nobody loads a backend plugin that isn't suitable for the version of antispam itself. --- mailtrain.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'mailtrain.c') diff --git a/mailtrain.c b/mailtrain.c index 276eb4a..e1c7bab 100644 --- a/mailtrain.c +++ b/mailtrain.c @@ -354,10 +354,11 @@ static void backend_exit(void) } struct backend antispam_backend = { - .init = backend_init, - .exit = backend_exit, - .handle_mail = backend_handle_mail, - .start = backend_start, - .rollback = backend_rollback, - .commit = backend_commit, + .api_version = BACKEND_API_VERSION, + .init = backend_init, + .exit = backend_exit, + .handle_mail = backend_handle_mail, + .start = backend_start, + .rollback = backend_rollback, + .commit = backend_commit, }; -- cgit v1.2.3 From d52daf7e31928c1b52bef6e57ec316f5f057d85a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 27 Feb 2011 11:35:01 +0100 Subject: rename mailtrain to pipe --- mailtrain.c | 364 ------------------------------------------------------------ 1 file changed, 364 deletions(-) delete mode 100644 mailtrain.c (limited to 'mailtrain.c') diff --git a/mailtrain.c b/mailtrain.c deleted file mode 100644 index e1c7bab..0000000 --- a/mailtrain.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * mailing backend for dovecot antispam plugin - * - * Copyright (C) 2007 Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include - -#include "lib.h" -#include "dict.h" -#include "mail-storage-private.h" -#include "ostream.h" -#include "istream.h" - -#include "antispam-plugin.h" - -static const char *spamaddr = NULL; -static const char *hamaddr = NULL; -static const char *sendmail_binary = "/usr/sbin/sendmail"; -static const char *tmpdir = "/tmp"; -static char **extra_args = NULL; -static int extra_args_num = 0; - -static int run_sendmail(int mailfd, enum classification wanted) -{ - const char *dest; - pid_t pid; - int status; - - switch (wanted) { - case CLASS_SPAM: - dest = spamaddr; - break; - case CLASS_NOTSPAM: - dest = hamaddr; - break; - } - - if (!dest) - return -1; - - pid = fork(); - - if (pid == -1) - return -1; - - debug("running mailtrain backend program %s", sendmail_binary); - - if (pid) { - if (waitpid(pid, &status, 0) == -1) - return -1; - if (!WIFEXITED(status)) - return -1; - return WEXITSTATUS(status); - } else { - char **argv; - int sz = sizeof(char *) * (2 + extra_args_num + 1); - int i, fd; - - argv = i_malloc(sz); - memset(argv, 0, sz); - - argv[0] = (char *) sendmail_binary; - - for (i = 0; i < extra_args_num; i++) - argv[i + 1] = (char *) extra_args[i]; - - argv[i + 1] = (char *) dest; - - dup2(mailfd, 0); - fd = open("/dev/null", O_WRONLY); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - execv(sendmail_binary, argv); - _exit(1); - /* not reached */ - return -1; - } -} - -struct antispam_transaction_context { - char *tmpdir; - int count; - int tmplen; -}; - -static struct antispam_transaction_context * -backend_start(struct mailbox *box __attr_unused__) -{ - struct antispam_transaction_context *ast; - char *tmp; - - ast = i_new(struct antispam_transaction_context, 1); - - ast->count = 0; - - tmp = i_strconcat(tmpdir, "/antispam-mail-XXXXXX", NULL); - - ast->tmpdir = mkdtemp(tmp); - if (!ast->tmpdir) - i_free(tmp); - else - ast->tmplen = strlen(ast->tmpdir); - - return ast; -} - -static int process_tmpdir(struct mailbox_transaction_context *ctx, - struct antispam_transaction_context *ast) -{ - int cnt = ast->count; - int fd; - char *buf; - enum classification wanted; - int rc = 0; - - t_push(); - - buf = t_malloc(20 + ast->tmplen); - - while (rc == 0 && cnt > 0) { - cnt--; - i_snprintf(buf, 20 + ast->tmplen - 1, "%s/%d", - ast->tmpdir, cnt); - - fd = open(buf, O_RDONLY); - read(fd, &wanted, sizeof(wanted)); - - if ((rc = run_sendmail(fd, wanted))) { - mail_storage_set_error(ctx->box->storage, - ME(TEMP) - "failed to send mail"); - debug("run program failed with exit code %d\n", rc); - rc = -1; - } - - close(fd); - } - - t_pop(); - - return rc; -} - -static void clear_tmpdir(struct antispam_transaction_context *ast) -{ - char *buf; - - t_push(); - - buf = t_malloc(20 + ast->tmplen); - - while (ast->count > 0) { - ast->count--; - i_snprintf(buf, 20 + ast->tmplen - 1, "%s/%d", - ast->tmpdir, ast->count); - unlink(buf); - } - rmdir(ast->tmpdir); - - t_pop(); -} - -static void backend_rollback(struct antispam_transaction_context *ast) -{ - if (ast->tmpdir) { - /* clear it! */ - clear_tmpdir(ast); - i_free(ast->tmpdir); - } - - i_free(ast); -} - -static int backend_commit(struct mailbox_transaction_context *ctx, - struct antispam_transaction_context *ast) -{ - int ret; - - if (!ast->tmpdir) { - i_free(ast); - return 0; - } - - ret = process_tmpdir(ctx, ast); - - clear_tmpdir(ast); - - i_free(ast->tmpdir); - i_free(ast); - - return ret; -} - -static int backend_handle_mail(struct mailbox_transaction_context *t, - struct antispam_transaction_context *ast, - struct mail *mail, enum classification wanted) -{ - struct istream *mailstream; - struct ostream *outstream; - int ret; - char *buf; - const unsigned char *beginning; - size_t size; - int fd; - - if (!ast->tmpdir) { - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "Failed to initialise temporary dir"); - return -1; - } - - if (!hamaddr || !spamaddr) { - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "antispam plugin not configured"); - return -1; - } - - mailstream = get_mail_stream(mail); - if (!mailstream) { - mail_storage_set_error(t->box->storage, - ME(EXPUNGED) - "Failed to get mail contents"); - return -1; - } - - t_push(); - - buf = t_malloc(20 + ast->tmplen); - i_snprintf(buf, 20 + ast->tmplen - 1, "%s/%d", ast->tmpdir, ast->count); - - fd = creat(buf, 0600); - if (fd < 0) { - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "Failed to create temporary file"); - ret = -1; - goto out; - } - - ast->count++; - - outstream = o_stream_create_from_fd(fd, t->box->pool); - if (!outstream) { - ret = -1; - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "Failed to stream temporary file"); - goto out_close; - } - - if (o_stream_send(outstream, &wanted, sizeof(wanted)) - != sizeof(wanted)) { - ret = -1; - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "Failed to write marker to temp file"); - goto failed_to_copy; - } - - if (i_stream_read_data(mailstream, &beginning, &size, 5) < 0 || - size < 5) { - ret = -1; - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "Failed to read mail beginning"); - goto failed_to_copy; - } - - /* "From "? skip line */ - if (memcmp("From ", beginning, 5) == 0) - i_stream_read_next_line(mailstream); - - if (o_stream_send_istream(outstream, mailstream) < 0) { - ret = -1; - mail_storage_set_error(t->box->storage, - ME(NOTPOSSIBLE) - "Failed to copy to temporary file"); - goto failed_to_copy; - } - - ret = 0; - - failed_to_copy: - o_stream_destroy(&outstream); - out_close: - close(fd); - out: - t_pop(); - - return ret; -} - -static void backend_init(pool_t pool __attr_unused__) -{ - const char *tmp; - int i; - - tmp = get_setting("MAIL_SPAM"); - if (tmp) { - spamaddr = tmp; - debug("mail backend spam address %s\n", tmp); - } - - tmp = get_setting("MAIL_NOTSPAM"); - if (tmp) { - hamaddr = tmp; - debug("mail backend not-spam address %s\n", tmp); - } - - tmp = get_setting("MAIL_SENDMAIL"); - if (tmp) { - sendmail_binary = tmp; - debug("mail backend sendmail %s\n", tmp); - } - - tmp = get_setting("MAIL_SENDMAIL_ARGS"); - if (tmp) { - extra_args = p_strsplit(pool, tmp, ";"); - extra_args_num = str_array_length( - (const char *const *)extra_args); - for (i = 0; i < extra_args_num; i++) - debug("mail backend sendmail arg %s\n", - extra_args[i]); - } - - tmp = get_setting("MAIL_TMPDIR"); - if (tmp) - tmpdir = tmp; - debug("mail backend tmpdir %s\n", tmpdir); -} - -static void backend_exit(void) -{ -} - -struct backend antispam_backend = { - .api_version = BACKEND_API_VERSION, - .init = backend_init, - .exit = backend_exit, - .handle_mail = backend_handle_mail, - .start = backend_start, - .rollback = backend_rollback, - .commit = backend_commit, -}; -- cgit v1.2.3