zlib-plugin.c revision 1d2b188f0eedc3cab6e27ceac5425a037f38042e
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen const char *ext;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenconst char *zlib_plugin_version = PACKAGE_VERSION;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void (*zlib_next_hook_mail_storage_created)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(zlib_storage_module,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(zlib_mail_module, &mail_module_register);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic bool is_compressed_zlib(struct istream *input)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen const unsigned char *data;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* Peek in to the stream and see if it looks like it's compressed
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen (based on its header). This also means that users can try to exploit
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen security holes in the uncompression library by APPENDing a specially
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen crafted mail. So let's hope zlib is free of holes. */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (i_stream_read_data(input, &data, &size, 1) <= 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic bool is_compressed_bzlib(struct istream *input)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen const unsigned char *data;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (i_stream_read_data(input, &data, &size, 4+6 - 1) <= 0)
a9b3887f4d9ed75a76fed964c1930432bf84f4f5Timo Sirainen return memcmp(data + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen { ".gz", is_compressed_zlib, i_stream_create_zlib },
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen { ".bz2", is_compressed_bzlib, i_stream_create_bzlib }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic struct zlib_handler *zlib_get_zlib_handler(struct istream *input)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen unsigned int i;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen for (i = 0; i < N_ELEMENTS(zlib_handlers); i++) {
a9b3887f4d9ed75a76fed964c1930432bf84f4f5Timo Sirainenstatic struct zlib_handler *zlib_get_zlib_handler_ext(const char *name)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen for (i = 0; i < N_ELEMENTS(zlib_handlers); i++) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen strcmp(name + name_len - len, zlib_handlers[i].ext) == 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic int zlib_maildir_get_stream(struct mail *_mail,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct index_mail *imail = (struct index_mail *)mail;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen union mail_module_context *zmail = ZLIB_MAIL_CONTEXT(mail);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return zmail->super.get_stream(_mail, hdr_size, body_size,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (zmail->super.get_stream(_mail, NULL, NULL, &input) < 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen handler = zlib_get_zlib_handler(imail->data.stream);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen mail_storage_set_critical(_mail->box->storage,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen "zlib plugin: Detected %s compression "
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen fd = dup(i_stream_get_fd(imail->data.stream));
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen mail_storage_set_critical(_mail->box->storage,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen "zlib plugin: dup() failed: %m");
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen imail->data.stream = handler->create_istream(fd);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return index_mail_init_stream(imail, hdr_size, body_size, stream_r);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic struct mail *
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenzlib_maildir_mail_alloc(struct mailbox_transaction_context *t,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen union mailbox_module_context *zbox = ZLIB_CONTEXT(t->box);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen _mail = zbox->super.mail_alloc(t, wanted_fields, wanted_headers);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen zmail = p_new(mail->pool, union mail_module_context, 1);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, zlib_mail_module, zmail);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void zlib_maildir_open_init(struct mailbox *box)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen zbox = p_new(box->pool, union mailbox_module_context, 1);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen MODULE_CONTEXT_SET_SELF(box, zlib_storage_module, zbox);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic struct istream *
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenzlib_mailbox_open_input(struct mail_storage *storage, struct mailbox_list *list,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (handler == NULL || handler->create_istream == NULL)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* looks like a compressed single file mailbox. we should be
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen able to handle this. */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic struct mailbox *
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenzlib_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen union mail_storage_module_context *qstorage = ZLIB_CONTEXT(storage);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (input == NULL && strcmp(storage->name, "mbox") == 0) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen box = qstorage->super.mailbox_alloc(storage, list, name, input, flags);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (strcmp(box->storage->name, "maildir") == 0)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void zlib_mail_storage_created(struct mail_storage *storage)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen storage->v.mailbox_alloc = zlib_mailbox_alloc;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen MODULE_CONTEXT_SET_SELF(storage, zlib_storage_module, qstorage);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (zlib_next_hook_mail_storage_created != NULL)