dovecot-2.0: zlib: Don't allow clients to save compressed data d...

dovecot at dovecot.org dovecot at dovecot.org
Wed Sep 9 07:54:08 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/aecf6e5be9e2
changeset: 9915:aecf6e5be9e2
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Sep 09 00:54:01 2009 -0400
description:
zlib: Don't allow clients to save compressed data directly.
This way clients can't try to exploit uncompression bugs in zlib/bzlib.

diffstat:

1 file changed, 101 insertions(+), 5 deletions(-)
src/plugins/zlib/zlib-plugin.c |  106 ++++++++++++++++++++++++++++++++++++++--

diffs (139 lines):

diff -r 3e4f64af6c9a -r aecf6e5be9e2 src/plugins/zlib/zlib-plugin.c
--- a/src/plugins/zlib/zlib-plugin.c	Tue Sep 08 20:05:45 2009 -0400
+++ b/src/plugins/zlib/zlib-plugin.c	Wed Sep 09 00:54:01 2009 -0400
@@ -27,6 +27,12 @@ struct zlib_handler {
 	const char *ext;
 	bool (*is_compressed)(struct istream *input);
 	struct istream *(*create_istream)(int fd);
+};
+
+struct zlib_transaction_context {
+	union mailbox_transaction_module_context module_ctx;
+
+	struct mail *tmp_mail;
 };
 
 const char *zlib_plugin_version = PACKAGE_VERSION;
@@ -167,6 +173,93 @@ zlib_maildir_mail_alloc(struct mailbox_t
 	return _mail;
 }
 
+static struct mailbox_transaction_context *
+zlib_mailbox_transaction_begin(struct mailbox *box,
+			       enum mailbox_transaction_flags flags)
+{
+	union mailbox_module_context *zbox = ZLIB_CONTEXT(box);
+	struct mailbox_transaction_context *t;
+	struct zlib_transaction_context *zt;
+
+	t = zbox->super.transaction_begin(box, flags);
+
+	zt = i_new(struct zlib_transaction_context, 1);
+
+	MODULE_CONTEXT_SET(t, zlib_storage_module, zt);
+	return t;
+}
+
+static void
+zlib_mailbox_transaction_rollback(struct mailbox_transaction_context *t)
+{
+	union mailbox_module_context *zbox = ZLIB_CONTEXT(t->box);
+	struct zlib_transaction_context *zt = ZLIB_CONTEXT(t);
+
+	if (zt->tmp_mail != NULL)
+		mail_free(&zt->tmp_mail);
+
+	zbox->super.transaction_rollback(t);
+	i_free(zt);
+}
+
+static int
+zlib_mailbox_transaction_commit(struct mailbox_transaction_context *t,
+				struct mail_transaction_commit_changes *changes_r)
+{
+	union mailbox_module_context *zbox = ZLIB_CONTEXT(t->box);
+	struct zlib_transaction_context *zt = ZLIB_CONTEXT(t);
+	int ret;
+
+	if (zt->tmp_mail != NULL)
+		mail_free(&zt->tmp_mail);
+
+	ret = zbox->super.transaction_commit(t, changes_r);
+	i_free(zt);
+	return ret;
+}
+
+static int
+zlib_mail_save_begin(struct mail_save_context *ctx, struct istream *input)
+{
+	struct mailbox_transaction_context *t = ctx->transaction;
+	struct zlib_transaction_context *zt = ZLIB_CONTEXT(t);
+	union mailbox_module_context *zbox = ZLIB_CONTEXT(t->box);
+
+	if (ctx->dest_mail == NULL) {
+		if (zt->tmp_mail == NULL) {
+			zt->tmp_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE,
+						  NULL);
+		}
+		ctx->dest_mail = zt->tmp_mail;
+	}
+
+	return zbox->super.save_begin(ctx, input);
+}
+
+static int zlib_mail_save_finish(struct mail_save_context *ctx)
+{
+	struct mailbox *box = ctx->transaction->box;
+	union mailbox_module_context *zbox = ZLIB_CONTEXT(box);
+	struct istream *input;
+	unsigned int i;
+
+	if (zbox->super.save_finish(ctx) < 0)
+		return -1;
+
+	if (mail_get_stream(ctx->dest_mail, NULL, NULL, &input) < 0)
+		return -1;
+
+	for (i = 0; i < N_ELEMENTS(zlib_handlers); i++) {
+		if (zlib_handlers[i].is_compressed(input)) {
+			mail_storage_set_error(box->storage,
+				MAIL_ERROR_NOTPOSSIBLE,
+				"Saving mails compressed by client isn't supported");
+			return -1;
+		}
+	}
+	return 0;
+}
+
 static void zlib_maildir_open_init(struct mailbox *box)
 {
 	union mailbox_module_context *zbox;
@@ -174,6 +267,11 @@ static void zlib_maildir_open_init(struc
 	zbox = p_new(box->pool, union mailbox_module_context, 1);
 	zbox->super = box->v;
 	box->v.mail_alloc = zlib_maildir_mail_alloc;
+	box->v.transaction_begin = zlib_mailbox_transaction_begin;
+	box->v.transaction_rollback = zlib_mailbox_transaction_rollback;
+	box->v.transaction_commit = zlib_mailbox_transaction_commit;
+	box->v.save_begin = zlib_mail_save_begin;
+	box->v.save_finish = zlib_mail_save_finish;
 
 	MODULE_CONTEXT_SET_SELF(box, zlib_storage_module, zbox);
 }
@@ -242,13 +340,11 @@ static void zlib_mail_storage_created(st
 
 void zlib_plugin_init(void)
 {
-	zlib_next_hook_mail_storage_created =
-		hook_mail_storage_created;
+	zlib_next_hook_mail_storage_created = hook_mail_storage_created;
 	hook_mail_storage_created = zlib_mail_storage_created;
 }
 
 void zlib_plugin_deinit(void)
 {
-	hook_mail_storage_created =
-		zlib_next_hook_mail_storage_created;
-}
+	hook_mail_storage_created = zlib_next_hook_mail_storage_created;
+}


More information about the dovecot-cvs mailing list