/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
/* FIXME: cache handling could be useful to move to Dovecot core, so that if
we're using this plugin together with zlib plugin there would be just one
cache. */
#include "lib.h"
#include "ioloop.h"
#include "randgen.h"
#include "module-dir.h"
#include "str.h"
#include "safe-mkstemp.h"
#include "istream.h"
#include "istream-decrypt.h"
#include "istream-seekable.h"
#include "ostream.h"
#include "ostream-encrypt.h"
#include "mail-user.h"
#include "mail-copy.h"
#include "index-storage.h"
#include "index-mail.h"
#include "mail-crypt-common.h"
#include "mail-crypt-key.h"
#include "mail-crypt-plugin.h"
#include "sha2.h"
#include "dcrypt-iostream.h"
#include "hex-binary.h"
struct mail_crypt_mailbox {
};
{
return MAIL_CRYPT_USER_CONTEXT(user);
}
{
sizeof(IOSTREAM_CRYPT_MAGIC)) <= 0) {
return FALSE;
}
sizeof(IOSTREAM_CRYPT_MAGIC)) != 0) {
return FALSE;
}
return TRUE;
}
{
}
static struct istream *
{
str_c(temp_prefix));
i_stream_unref(&inputs[0]);
/* index-mail wants the stream to be destroyed at close, so create
a new stream instead of just increasing reference. */
}
return input;
}
struct dcrypt_private_key **priv_key_r,
const char **error_r,
void *context)
{
/* mailbox_crypt_search_all_private_keys requires error_r != NULL */
int ret;
error_r);
} else {
*error_r = "Public emails cannot have keys";
ret = -1;
}
return ret;
}
static int
{
/* use the cached stream. when doing partial reads it should
already be seeked into the wanted offset. */
}
/* decryption is the outmost stream, so add it before others
(e.g. zlib) */
if (!mail_crypt_is_stream_encrypted(*stream))
}
{
/* make sure we have read the entire email into the seekable
stream (which causes the original input stream to be
unrefed). we can't safely keep the original input stream
open after the mail is closed. */
}
}
{
v->close = mail_crypt_close;
}
{
return -1;
/* we're here only if mail-crypt plugin is disabled. we want to make
sure that even though we're saving an unencrypted mail, the mail
can't be faked to look like an encrypted mail. */
return -1;
if (mail_crypt_is_stream_encrypted(input)) {
"Saving mails encrypted by client isn't supported");
return -1;
}
return 0;
}
static int
{
const char *pubid;
} else {
i_panic("mail_crypt_mail_save_begin not supposed to be called"
"when mail_crypt_save_version is 0");
}
return -1;
else {
const char *error;
int ret;
&error)) <= 0)
{
if (ret < 0) {
t_strdup_printf("get_public_key(%s) failed: %s",
error));
return ret;
}
t_strdup_printf("generate_keypair(%s) failed: "
"unsupported save_version=%d",
muser->save_version));
return -1;
}
t_strdup_printf("generate_keypair(%s) failed: %s",
error));
return -1;
}
}
}
/* encryption is the outermost layer (zlib etc. are inside) */
return 0;
}
static int
{
}
{
}
{
if ((class_flags & MAIL_STORAGE_CLASS_FLAG_BINARY_DATA) != 0) {
if (muser->save_version > 0) {
is not necessary, so do not attempt to do it.
with per-folder keys, emails must be re-encrypted
when moving to another folder */
v->copy = mail_crypt_mailbox_copy;
}
} else {
}
}
}
{
}
{
if (user->mail_debug) {
i_debug("mail_crypt_plugin: mail_crypt_curve setting "
"missing - generating EC keys disabled");
}
"mail_crypt_plugin: "
"invalid mail_crypt_curve setting %s: %s - "
"plugin disabled",
} else {
}
"mail_crypt_save_version");
"mail_crypt_plugin: "
"mail_crypt_save_version setting missing "
"- plugin disabled");
} else if (version[0] == '0') {
muser->save_version = 0;
} else if (version[0] == '1') {
} else if (version[0] == '2') {
} else {
"mail_crypt_plugin: Invalid "
"mail_crypt_save_version %s: use 0, 1, or 2 ",
version);
}
"mail_crypt_plugin: %s", error);
}
}
};
};
};
{
const char* error;
/* rather kludgy. we need to hook into mail reading as early as
possible, but we need to hook into mail writing as late as
possible. we could create just two real plugins, but that's a bit
annoying to configure. */
}
void mail_crypt_plugin_deinit(void)
{
}