From: Josef 'Jeff' Sipek Date: Wed, 9 Dec 2020 14:20:54 +0000 (-0500) Subject: plugins: Remove mail-filter plugin X-Git-Tag: 2.3.14.rc1~212 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=26a6a90baf14c2f6671fbcf07a42fd5ed43046f5;p=thirdparty%2Fdovecot%2Fcore.git plugins: Remove mail-filter plugin --- diff --git a/configure.ac b/configure.ac index ce28cc0c37..a55642e77a 100644 --- a/configure.ac +++ b/configure.ac @@ -898,7 +898,6 @@ src/plugins/fts-squat/Makefile src/plugins/last-login/Makefile src/plugins/lazy-expunge/Makefile src/plugins/listescape/Makefile -src/plugins/mail-filter/Makefile src/plugins/mail-log/Makefile src/plugins/mail-lua/Makefile src/plugins/mailbox-alias/Makefile diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 0957bc1537..e88e3c425a 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -30,7 +30,6 @@ SUBDIRS = \ notify \ notify-status \ push-notification \ - mail-filter \ mail-log \ $(MAIL_LUA) \ mailbox-alias \ diff --git a/src/plugins/mail-filter/Makefile.am b/src/plugins/mail-filter/Makefile.am deleted file mode 100644 index 67b0af257a..0000000000 --- a/src/plugins/mail-filter/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-mail \ - -I$(top_srcdir)/src/lib-imap \ - -I$(top_srcdir)/src/lib-index \ - -I$(top_srcdir)/src/lib-storage - -NOPLUGIN_LDFLAGS = -lib10_mail_filter_plugin_la_LDFLAGS = -module -avoid-version - -module_LTLIBRARIES = \ - lib10_mail_filter_plugin.la - -lib10_mail_filter_plugin_la_SOURCES = \ - mail-filter-plugin.c \ - istream-ext-filter.c \ - ostream-ext-filter.c - -noinst_HEADERS = \ - istream-ext-filter.h \ - ostream-ext-filter.h \ - mail-filter-plugin.h diff --git a/src/plugins/mail-filter/istream-ext-filter.c b/src/plugins/mail-filter/istream-ext-filter.c deleted file mode 100644 index 6da5043828..0000000000 --- a/src/plugins/mail-filter/istream-ext-filter.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "str.h" -#include "strescape.h" -#include "net.h" -#include "eacces-error.h" -#include "ostream.h" -#include "istream-private.h" -#include "istream-ext-filter.h" - -#include - -struct mail_filter_istream { - struct istream_private istream; - - int fd; - struct istream *ext_in; - struct ostream *ext_out; - size_t prev_ret; -}; - -static void -i_stream_mail_filter_close(struct iostream_private *stream, bool close_parent) -{ - struct mail_filter_istream *mstream = - (struct mail_filter_istream *)stream; - - i_stream_destroy(&mstream->ext_in); - o_stream_destroy(&mstream->ext_out); - i_close_fd(&mstream->fd); - if (close_parent) - i_stream_close(mstream->istream.parent); -} - -static ssize_t -i_stream_read_copy_from(struct istream *istream, struct istream *source) -{ - struct istream_private *stream = istream->real_stream; - size_t pos; - ssize_t ret; - - stream->pos -= stream->skip; - stream->skip = 0; - - stream->buffer = i_stream_get_data(source, &pos); - if (pos > stream->pos) - ret = 0; - else do { - if ((ret = i_stream_read_memarea(source)) == -2) - return -2; - - stream->istream.stream_errno = source->stream_errno; - stream->istream.eof = source->eof; - stream->buffer = i_stream_get_data(source, &pos); - /* check again, in case the source stream had been seeked - backwards and the previous read() didn't get us far - enough. */ - } while (pos <= stream->pos && ret > 0); - - ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) : - (ret == 0 ? 0 : -1); - stream->pos = pos; - i_assert(ret != -1 || stream->istream.eof || - stream->istream.stream_errno != 0); - return ret; -} - -static ssize_t -i_stream_mail_filter_read_once(struct mail_filter_istream *mstream) -{ - struct istream_private *stream = &mstream->istream; - ssize_t ret; - - if (mstream->ext_out != NULL) { - /* we haven't sent everything yet */ - switch (o_stream_send_istream(mstream->ext_out, stream->parent)) { - case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: - o_stream_destroy(&mstream->ext_out); - /* if we wanted to be a blocking stream, - from now on the rest of the reads are */ - if (stream->istream.blocking) - net_set_nonblock(mstream->fd, FALSE); - if (shutdown(mstream->fd, SHUT_WR) < 0) - i_error("ext-filter: shutdown() failed: %m"); - break; - case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: - case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: - case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: - break; - case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: - stream->istream.stream_errno = - mstream->ext_out->stream_errno; - io_stream_set_error(&stream->iostream, - "write(%s) failed: %s", - o_stream_get_name(mstream->ext_out), - o_stream_get_error(mstream->ext_out)); - return -1; - } - } - - i_stream_skip(mstream->ext_in, mstream->prev_ret); - ret = i_stream_read_copy_from(&stream->istream, mstream->ext_in); - mstream->prev_ret = ret < 0 ? 0 : ret; - return ret; -} - -static ssize_t i_stream_mail_filter_read(struct istream_private *stream) -{ - struct mail_filter_istream *mstream = - (struct mail_filter_istream *)stream; - ssize_t ret; - - if (mstream->ext_in == NULL) { - stream->istream.stream_errno = EIO; - return -1; - } - - while ((ret = i_stream_mail_filter_read_once(mstream)) == 0) { - if (!stream->istream.blocking) - break; - } - if (ret == -1 && !i_stream_have_bytes_left(&stream->istream) && - stream->istream.v_offset == 0) { - /* EOF without any input -> assume the script is reporting - failure. pretty ugly way, but currently there's no error - reporting channel. */ - stream->istream.stream_errno = EIO; - } - return ret; -} - -static int -i_stream_mail_filter_stat(struct istream_private *stream, bool exact) -{ - const struct stat *st; - - i_assert(!exact); - - if (i_stream_stat(stream->parent, exact, &st) < 0) { - stream->istream.stream_errno = stream->parent->stream_errno; - return -1; - } - stream->statbuf = *st; - return 0; -} - -static int filter_connect(struct mail_filter_istream *mstream, - const char *socket_path, const char *args) -{ - const char **argv; - string_t *str; - ssize_t ret; - int fd; - - argv = t_strsplit(args, " "); - - if ((fd = net_connect_unix_with_retries(socket_path, 1000)) < 0) { - if (errno == EACCES) { - i_error("ext-filter: %s", - eacces_error_get("net_connect_unix", - socket_path)); - } else { - i_error("ext-filter: net_connect_unix(%s) failed: %m", - socket_path); - } - return -1; - } - if (mstream->istream.istream.blocking) - net_set_nonblock(fd, FALSE); - - mstream->fd = fd; - mstream->ext_in = - i_stream_create_fd(fd, mstream->istream.max_buffer_size); - mstream->ext_out = o_stream_create_fd(fd, 0); - - str = t_str_new(256); - str_append(str, "VERSION\tscript\t4\t0\nnoreply\n"); - for (; *argv != NULL; argv++) { - str_append_tabescaped(str, *argv); - str_append_c(str, '\t'); - } - str_append_c(str, '\n'); - - ret = o_stream_send(mstream->ext_out, str_data(str), str_len(str)); - if (ret < 0) { - i_error("ext-filter: write(%s) failed: %s", socket_path, - o_stream_get_error(mstream->ext_out)); - i_stream_mail_filter_close(&mstream->istream.iostream, FALSE); - return -1; - } - i_assert((size_t)ret == str_len(str)); - return 0; -} - -struct istream * -i_stream_create_ext_filter(struct istream *input, const char *socket_path, - const char *args) -{ - struct mail_filter_istream *mstream; - - mstream = i_new(struct mail_filter_istream, 1); - mstream->istream.iostream.close = i_stream_mail_filter_close; - mstream->istream.max_buffer_size = input->real_stream->max_buffer_size; - mstream->istream.read = i_stream_mail_filter_read; - mstream->istream.stat = i_stream_mail_filter_stat; - - mstream->istream.istream.readable_fd = FALSE; - mstream->istream.istream.blocking = input->blocking; - mstream->istream.istream.seekable = FALSE; - - mstream->fd = -1; - (void)filter_connect(mstream, socket_path, args); - - return i_stream_create(&mstream->istream, input, mstream->fd, 0); -} diff --git a/src/plugins/mail-filter/istream-ext-filter.h b/src/plugins/mail-filter/istream-ext-filter.h deleted file mode 100644 index 9f45fd9140..0000000000 --- a/src/plugins/mail-filter/istream-ext-filter.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ISTREAM_MAIL_FILTER_H -#define ISTREAM_MAIL_FILTER_H - -struct istream * -i_stream_create_ext_filter(struct istream *input, const char *socket_path, - const char *args); - -#endif diff --git a/src/plugins/mail-filter/mail-filter-plugin.c b/src/plugins/mail-filter/mail-filter-plugin.c deleted file mode 100644 index 923687ed97..0000000000 --- a/src/plugins/mail-filter/mail-filter-plugin.c +++ /dev/null @@ -1,210 +0,0 @@ -/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "str.h" -#include "safe-mkstemp.h" -#include "mail-user.h" -#include "mail-storage-private.h" -#include "istream.h" -#include "istream-seekable.h" -#include "istream-ext-filter.h" -#include "ostream-ext-filter.h" -#include "mail-filter-plugin.h" - -/* After buffer grows larger than this, create a temporary file to /tmp - where to read the mail. */ -#define MAIL_MAX_MEMORY_BUFFER (1024*128) - -#define MAIL_FILTER_MAIL_CONTEXT(obj) \ - MODULE_CONTEXT_REQUIRE(obj, mail_filter_mail_module) -#define MAIL_FILTER_CONTEXT(obj) \ - MODULE_CONTEXT_REQUIRE(obj, mail_filter_storage_module) -#define MAIL_FILTER_USER_CONTEXT(obj) \ - MODULE_CONTEXT_REQUIRE(obj, mail_filter_user_module) - -struct mail_filter_user { - union mail_user_module_context module_ctx; - - const char *socket_path, *args; - const char *out_socket_path, *out_args; -}; - -const char *mail_filter_plugin_version = DOVECOT_ABI_VERSION; - -static MODULE_CONTEXT_DEFINE_INIT(mail_filter_user_module, - &mail_user_module_register); -static MODULE_CONTEXT_DEFINE_INIT(mail_filter_storage_module, - &mail_storage_module_register); -static MODULE_CONTEXT_DEFINE_INIT(mail_filter_mail_module, - &mail_module_register); - -static int -mail_filter_mail_save_begin(struct mail_save_context *ctx, - struct istream *input) -{ - struct mailbox *box = ctx->transaction->box; - struct mail_filter_user *muser = - MAIL_FILTER_USER_CONTEXT(box->storage->user); - union mailbox_module_context *mbox = MAIL_FILTER_CONTEXT(box); - struct ostream *output; - - if (mbox->super.save_begin(ctx, input) < 0) - return -1; - - output = o_stream_create_ext_filter(ctx->data.output, - muser->out_socket_path, - muser->out_args); - ctx->data.output = output; - return 0; -} - -static int seekable_fd_callback(const char **path_r, void *context) -{ - struct mail_user *user = context; - string_t *path; - int fd; - - path = t_str_new(128); - mail_user_set_get_temp_prefix(path, user->set); - fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1); - if (fd == -1) { - i_error("safe_mkstemp(%s) failed: %m", str_c(path)); - return -1; - } - - /* we just want the fd, unlink it */ - if (i_unlink(str_c(path)) < 0) { - /* shouldn't happen.. */ - i_close_fd(&fd); - return -1; - } - - *path_r = str_c(path); - return fd; -} - -static int -mail_filter_istream_opened(struct mail *_mail, struct istream **stream) -{ - struct mail_private *mail = (struct mail_private *)_mail; - struct mail_user *user = _mail->box->storage->user; - struct mail_filter_user *muser = MAIL_FILTER_USER_CONTEXT(user); - union mail_module_context *mmail = MAIL_FILTER_MAIL_CONTEXT(mail); - struct istream *input, *inputs[2]; - - input = *stream; - *stream = i_stream_create_ext_filter(input, muser->socket_path, - muser->args); - i_stream_unref(&input); - - inputs[0] = *stream; - inputs[1] = NULL; - *stream = i_stream_create_seekable(inputs, MAIL_MAX_MEMORY_BUFFER, - seekable_fd_callback, user); - i_stream_unref(&inputs[0]); - - return mmail->super.istream_opened(_mail, stream); -} - -static void mail_filter_mailbox_allocated(struct mailbox *box) -{ - struct mailbox_vfuncs *v = box->vlast; - struct mail_filter_user *muser = - MAIL_FILTER_USER_CONTEXT(box->storage->user); - union mailbox_module_context *mbox; - enum mail_storage_class_flags class_flags = box->storage->class_flags; - - mbox = p_new(box->pool, union mailbox_module_context, 1); - mbox->super = *v; - box->vlast = &mbox->super; - - MODULE_CONTEXT_SET_SELF(box, mail_filter_storage_module, mbox); - - if ((class_flags & MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0 && - (class_flags & MAIL_STORAGE_CLASS_FLAG_BINARY_DATA) != 0 && - muser->out_socket_path != NULL) - v->save_begin = mail_filter_mail_save_begin; -} - -static void mail_filter_mail_allocated(struct mail *_mail) -{ - struct mail_private *mail = (struct mail_private *)_mail; - struct mail_filter_user *muser = - MAIL_FILTER_USER_CONTEXT(_mail->box->storage->user); - struct mail_vfuncs *v = mail->vlast; - union mail_module_context *mmail; - - mmail = p_new(mail->pool, union mail_module_context, 1); - mmail->super = *v; - mail->vlast = &mmail->super; - - if (muser->socket_path != NULL) - v->istream_opened = mail_filter_istream_opened; - MODULE_CONTEXT_SET_SELF(mail, mail_filter_mail_module, mmail); -} - -static void -mail_filter_parse_setting(struct mail_user *user, const char *name, - const char **socket_path_r, const char **args_r) -{ - const char *value, *p; - - value = mail_user_plugin_getenv(user, name); - if (value == NULL) - return; - - p = strchr(value, ' '); - if (p == NULL) { - *socket_path_r = p_strdup(user->pool, value); - *args_r = ""; - } else { - *socket_path_r = p_strdup_until(user->pool, value, p); - *args_r = p_strdup(user->pool, p + 1); - } - if (**socket_path_r != '/') { - /* relative to base_dir */ - *socket_path_r = p_strdup_printf(user->pool, "%s/%s", - user->set->base_dir, *socket_path_r); - } - e_debug(user->event, "mail_filter: Filtering %s via socket %s", - name, *socket_path_r); -} - -static void mail_filter_mail_user_created(struct mail_user *user) -{ - struct mail_user_vfuncs *v = user->vlast; - struct mail_filter_user *muser; - - muser = p_new(user->pool, struct mail_filter_user, 1); - muser->module_ctx.super = *v; - user->vlast = &muser->module_ctx.super; - - mail_filter_parse_setting(user, "mail_filter", - &muser->socket_path, &muser->args); - mail_filter_parse_setting(user, "mail_filter_out", - &muser->out_socket_path, &muser->out_args); - if (muser->socket_path == NULL && - muser->out_socket_path == NULL) { - e_debug(user->event, "mail_filter and mail_filter_out settings missing, " - "ignoring mail_filter plugin"); - } - - MODULE_CONTEXT_SET(user, mail_filter_user_module, muser); -} - -static struct mail_storage_hooks mail_filter_mail_storage_hooks = { - .mail_user_created = mail_filter_mail_user_created, - .mailbox_allocated = mail_filter_mailbox_allocated, - .mail_allocated = mail_filter_mail_allocated -}; - -void mail_filter_plugin_init(struct module *module) -{ - mail_storage_hooks_add(module, &mail_filter_mail_storage_hooks); -} - -void mail_filter_plugin_deinit(void) -{ - mail_storage_hooks_remove(&mail_filter_mail_storage_hooks); -} diff --git a/src/plugins/mail-filter/mail-filter-plugin.h b/src/plugins/mail-filter/mail-filter-plugin.h deleted file mode 100644 index 5453eb8284..0000000000 --- a/src/plugins/mail-filter/mail-filter-plugin.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef MAIL_FILTER_PLUGIN_H -#define MAIL_FILTER_PLUGIN_H - -void mail_filter_plugin_init(struct module *module); -void mail_filter_plugin_deinit(void); - -#endif diff --git a/src/plugins/mail-filter/ostream-ext-filter.c b/src/plugins/mail-filter/ostream-ext-filter.c deleted file mode 100644 index 6e8481e5e8..0000000000 --- a/src/plugins/mail-filter/ostream-ext-filter.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "str.h" -#include "strescape.h" -#include "net.h" -#include "eacces-error.h" -#include "istream.h" -#include "ostream-private.h" -#include "ostream-ext-filter.h" - -#include - -struct mail_filter_ostream { - struct ostream_private ostream; - - int fd; - struct istream *ext_in; - struct ostream *ext_out; - bool finished; -}; - -static void -o_stream_mail_filter_close(struct iostream_private *stream, bool close_parent) -{ - struct mail_filter_ostream *mstream = - (struct mail_filter_ostream *)stream; - - i_stream_destroy(&mstream->ext_in); - o_stream_destroy(&mstream->ext_out); - i_close_fd(&mstream->fd); - if (close_parent) - o_stream_close(mstream->ostream.parent); -} - -static ssize_t -o_stream_mail_filter_sendv(struct ostream_private *stream, - const struct const_iovec *iov, - unsigned int iov_count) -{ - struct mail_filter_ostream *mstream = - (struct mail_filter_ostream *)stream; - ssize_t ret; - - if (mstream->ext_out == NULL) { - /* connect failed */ - mstream->ostream.ostream.stream_errno = EIO; - return -1; - } - - /* send the data to the filter */ - ret = o_stream_sendv(mstream->ext_out, iov, iov_count); - if (ret < 0) { - io_stream_set_error(&stream->iostream, "%s", - o_stream_get_error(mstream->ext_out)); - stream->ostream.stream_errno = - mstream->ext_out->stream_errno; - return -1; - } - stream->ostream.offset += ret; - return ret; -} - -static int o_stream_mail_filter_finish(struct ostream_private *stream) -{ - struct mail_filter_ostream *mstream = - (struct mail_filter_ostream *)stream; - const unsigned char *data; - size_t size; - ssize_t ret; - - if (mstream->ext_out == NULL) { - /* connect failed */ - return -1; - } - if (mstream->finished) - return 0; - - if (shutdown(mstream->fd, SHUT_WR) < 0) - i_error("ext-filter: shutdown() failed: %m"); - - while ((ret = i_stream_read_more(mstream->ext_in, &data, &size)) > 0) { - ret = o_stream_send(stream->parent, data, size); - if (ret != (ssize_t)size) { - i_assert(ret < 0); - o_stream_copy_error_from_parent(stream); - return -1; - } - i_stream_skip(mstream->ext_in, size); - } - i_assert(ret == -1); - - if (!i_stream_have_bytes_left(mstream->ext_in) && - mstream->ext_in->v_offset == 0) { - /* EOF without any input -> assume the script is reporting - failure. pretty ugly way, but currently there's no error - reporting channel. */ - io_stream_set_error(&stream->iostream, "EOF without input"); - stream->ostream.stream_errno = EIO; - return -1; - } - if (mstream->ext_in->stream_errno != 0) { - io_stream_set_error(&stream->iostream, "%s", - i_stream_get_error(mstream->ext_in)); - stream->ostream.stream_errno = mstream->ext_in->stream_errno; - return -1; - } - - mstream->finished = TRUE; - return ret; -} - -static int o_stream_mail_filter_flush(struct ostream_private *stream) -{ - int ret; - - if (stream->finished) { - if ((ret = o_stream_mail_filter_finish(stream)) <= 0) - return ret; - } - return o_stream_flush_parent(stream); -} - -static int filter_connect(struct mail_filter_ostream *mstream, - const char *socket_path, const char *args) -{ - const char **argv; - string_t *str; - int fd; - - argv = t_strsplit(args, " "); - - if ((fd = net_connect_unix_with_retries(socket_path, 1000)) < 0) { - if (errno == EACCES) { - io_stream_set_error(&mstream->ostream.iostream, "%s", - eacces_error_get("net_connect_unix", - socket_path)); - } else { - io_stream_set_error(&mstream->ostream.iostream, - "net_connect_unix(%s) failed: %m", socket_path); - } - return -1; - } - net_set_nonblock(fd, FALSE); - - mstream->fd = fd; - mstream->ext_in = i_stream_create_fd(fd, IO_BLOCK_SIZE); - mstream->ext_out = o_stream_create_fd(fd, 0); - - str = t_str_new(256); - str_append(str, "VERSION\tscript\t4\t0\nnoreply\n"); - for (; *argv != NULL; argv++) { - str_append_tabescaped(str, *argv); - str_append_c(str, '\t'); - } - str_append_c(str, '\n'); - - ssize_t ret = o_stream_send(mstream->ext_out, str_data(str), str_len(str)); - if (ret < 0) { - io_stream_set_error(&mstream->ostream.iostream, "%s", - o_stream_get_error(mstream->ext_out)); - mstream->ostream.ostream.stream_errno = - mstream->ext_out->stream_errno; - } else if ((size_t)ret != str_len(str)) { - io_stream_set_error(&mstream->ostream.iostream, - "write(%s): Wrote only %zu of %zu bytes", - socket_path, (size_t)ret, str_len(str)); - mstream->ostream.ostream.stream_errno = ENOBUFS; - } - return 0; -} - -struct ostream * -o_stream_create_ext_filter(struct ostream *output, const char *socket_path, - const char *args) -{ - struct mail_filter_ostream *mstream; - - mstream = i_new(struct mail_filter_ostream, 1); - mstream->fd = -1; - mstream->ostream.iostream.close = o_stream_mail_filter_close; - mstream->ostream.sendv = o_stream_mail_filter_sendv; - mstream->ostream.flush = o_stream_mail_filter_flush; - - (void)filter_connect(mstream, socket_path, args); - - return o_stream_create(&mstream->ostream, output, mstream->fd); -} diff --git a/src/plugins/mail-filter/ostream-ext-filter.h b/src/plugins/mail-filter/ostream-ext-filter.h deleted file mode 100644 index 61b990d5a1..0000000000 --- a/src/plugins/mail-filter/ostream-ext-filter.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef OSTREAM_MAIL_FILTER_H -#define OSTREAM_MAIL_FILTER_H - -struct ostream * -o_stream_create_ext_filter(struct ostream *output, const char *socket_path, - const char *args); - -#endif