mirror of
https://0xacab.org/liberate/trees.git
synced 2024-11-21 17:50:04 +01:00
Rename project from tofu-scrambler to trees
Signed-off-by: David Goulet <dgoulet@riseup.net>
This commit is contained in:
parent
cc076fec13
commit
300f0dbf69
4
.gitignore
vendored
4
.gitignore
vendored
@ -18,8 +18,8 @@ Makefile.in
|
||||
configure
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
libscrambler-config.h
|
||||
libscrambler-config.h.in
|
||||
trees-config.h
|
||||
trees-config.h.in
|
||||
config.log
|
||||
config.status
|
||||
stamp-h1
|
||||
|
58
README.md
58
README.md
@ -1,12 +1,12 @@
|
||||
Tofu Scrambler - A NaCL-based Dovecot encryption plugin
|
||||
TREES - A NaCL-based Dovecot encryption plugin
|
||||
=======================================================
|
||||
|
||||
This plugin adds individually encrypted mail storage to the Dovecot IMAP
|
||||
server.
|
||||
|
||||
This plugin is inspired by Posteo's [scrambler](https://github.com/posteo
|
||||
/scrambler-plugin) which uses OpenSSL and RSA keypairs. Tofu Scrambler works in
|
||||
a similar way, but uses the Sodium crypto library (based on NaCL).
|
||||
/scrambler-plugin) which uses OpenSSL and RSA keypairs. TREES works in a
|
||||
similar way, but uses the Sodium crypto library (based on NaCL).
|
||||
|
||||
How it works:
|
||||
|
||||
@ -45,11 +45,11 @@ Installation
|
||||
|
||||
* Type `make` to compile the plugin.
|
||||
|
||||
* Find the plugin at `src/.libs/lib18_scrambler_plugin.so`.
|
||||
* Find the plugin at `src/.libs/lib18_trees_plugin.so`.
|
||||
|
||||
* Copy to `/usr/lib/dovecot/modules/`
|
||||
|
||||
* Enable the plugin. For example, add `mail_plugins = expire quota scrambler`
|
||||
* Enable the plugin. For example, add `mail_plugins = expire quota trees`
|
||||
to `/etc/dovecot/conf.d/10-mail.conf`
|
||||
|
||||
See below for how to configure the plugin.
|
||||
@ -60,24 +60,24 @@ Database
|
||||
In order to run, the plugin needs the following configuration values (via the
|
||||
dovecot environment).
|
||||
|
||||
* `scrambler_password` The plain user password. It's used to unlock the
|
||||
`scrambler_locked_secretbox` in order to get access to the private key.
|
||||
* `trees_password` The plain user password. It's used to unlock the
|
||||
`trees_locked_secretbox` in order to get access to the private key.
|
||||
|
||||
* `scrambler_enabled` Can be either the integer `1` or `0`.
|
||||
* `trees_enabled` Can be either the integer `1` or `0`.
|
||||
|
||||
* `scrambler_public_key` The public Curve25519 key of the user (hex string).
|
||||
* `trees_public_key` The public Curve25519 key of the user (hex string).
|
||||
|
||||
* `scrambler_locked_secretbox` contains the Curve25519 private key of a user
|
||||
* `trees_locked_secretbox` contains the Curve25519 private key of a user
|
||||
which is locked using the argon2 digest of the user's password (hex string).
|
||||
|
||||
* `scrambler_sk_nonce` 24 byte random nonce for locked_secretbox (hex string).
|
||||
* `trees_sk_nonce` 24 byte random nonce for `locked_secretbox` (hex string).
|
||||
|
||||
* `scrambler_pwhash_opslimit` argon2 CPU usage parameter (3..10 int).
|
||||
* `trees_pwhash_opslimit` argon2 CPU usage parameter (3..10 int).
|
||||
|
||||
* `scrambler_pwhash_memlimit` argon2 memory usage parameter (must be in range
|
||||
* `trees_pwhash_memlimit` argon2 memory usage parameter (must be in range
|
||||
8192 bytes to 4 TB, expressed in bytes).
|
||||
|
||||
* `scrambler_pwhash_salt` 16 byte random argon2 salt (hex string).
|
||||
* `trees_pwhash_salt` 16 byte random argon2 salt (hex string).
|
||||
|
||||
An example database scheme for this might be:
|
||||
|
||||
@ -114,8 +114,8 @@ Dovecot Configuration
|
||||
|
||||
* `default_pass_scheme = ARGON2` recommended (Note: this will use the crypt-
|
||||
style argon2 digest string for authentication, which is a very different
|
||||
format than is used by tofu-scrambler. It is out of tofu-scrambler's scope
|
||||
how to set up Argon2 authentication with Dovecot).
|
||||
format than is used by TREES. It is out of TREES's scope how to set up
|
||||
Argon2 authentication with Dovecot).
|
||||
|
||||
SQL Configuration
|
||||
-------------------------------------
|
||||
@ -155,14 +155,14 @@ Here is a dovecot SQL query configuration that will work with the sample
|
||||
8 AS userdb_uid, \
|
||||
8 AS userdb_gid, \
|
||||
CONCAT('/maildir/', mailboxes.maildir) AS userdb_home, \
|
||||
REPLACE('%w', '%%', '%%%%') AS userdb_scrambler_password, \
|
||||
storage_keys.enabled AS userdb_scrambler_enabled, \
|
||||
storage_keys.public_key AS userdb_scrambler_public_key, \
|
||||
storage_keys.locked_secretbox AS userdb_scrambler_locked_secretbox, \
|
||||
storage_keys.sk_nonce AS userdb_scrambler_sk_nonce, \
|
||||
storage_keys.pwhash_opslimit AS userdb_scrambler_pwhash_opslimit, \
|
||||
storage_keys.pwhash_memlimit AS userdb_scrambler_pwhash_memlimit, \
|
||||
storage_keys.pwhash_salt AS userdb_scrambler_pwhash_salt \
|
||||
REPLACE('%w', '%%', '%%%%') AS userdb_trees_password, \
|
||||
storage_keys.enabled AS userdb_trees_enabled, \
|
||||
storage_keys.public_key AS userdb_trees_public_key, \
|
||||
storage_keys.locked_secretbox AS userdb_trees_locked_secretbox, \
|
||||
storage_keys.sk_nonce AS userdb_trees_sk_nonce, \
|
||||
storage_keys.pwhash_opslimit AS userdb_trees_pwhash_opslimit, \
|
||||
storage_keys.pwhash_memlimit AS userdb_trees_pwhash_memlimit, \
|
||||
storage_keys.pwhash_salt AS userdb_trees_pwhash_salt \
|
||||
FROM mailboxes \
|
||||
LEFT OUTER JOIN storage_keys ON mailboxes.user_id = storage_keys.user_id \
|
||||
WHERE mailboxes.username = '%n' AND mailboxes.domain = '%d' \
|
||||
@ -179,8 +179,8 @@ Here is a dovecot SQL query configuration that will work with the sample
|
||||
8 AS uid, \
|
||||
8 AS gid, \
|
||||
CONCAT('/maildir/', mailboxes.maildir) AS home, \
|
||||
storage_keys.enabled AS scrambler_enabled, \
|
||||
storage_keys.public_key AS scrambler_public_key, \
|
||||
storage_keys.enabled AS trees_enabled, \
|
||||
storage_keys.public_key AS trees_public_key, \
|
||||
CONCAT('*:bytes=', mailboxes.quota) AS quota_rule \
|
||||
FROM mailboxes \
|
||||
LEFT OUTER JOIN storage_keys ON mailboxes.user_id = storage_keys.user_id \
|
||||
@ -188,14 +188,14 @@ Here is a dovecot SQL query configuration that will work with the sample
|
||||
AND mailboxes.is_active = 1
|
||||
|
||||
The odd line `REPLACE('%w', '%%', '%%%%')` is needed to pass the cleartext
|
||||
password to tofu-scrambler, and allow `%` as a valid password character.
|
||||
password to TREES, and allow `%` as a valid password character.
|
||||
|
||||
Argon2 Parameters
|
||||
----------------------------------------------
|
||||
|
||||
There are three recommended levels for the Argon2 parameters, Interactive,
|
||||
Moderate, and Sensitive. In the case of tofu-scrambler, setting the parameters
|
||||
at Moderate or Sensitive will make checking email very slow.
|
||||
Moderate, and Sensitive. In the case of TREES, setting the parameters at
|
||||
Moderate or Sensitive will make checking email very slow.
|
||||
|
||||
Interactive: For interactive, online operations, that need to be fast, a
|
||||
reasonable minimum is:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#
|
||||
# This is a simple command line script to create a set of values expected
|
||||
# by tofu_scrambler. Useful for testing.
|
||||
# by the TREES plugin. Useful for testing.
|
||||
#
|
||||
# NOTE: this requires rbnacl-4.0.0.pre.gem or newer, or Riseup's fork of rbnacl:
|
||||
#
|
||||
@ -26,7 +26,7 @@ end
|
||||
|
||||
def usage
|
||||
puts "USAGE:"
|
||||
puts " tofu-create --password PASSWORD [OPTIONS]"
|
||||
puts " trees-create --password PASSWORD [OPTIONS]"
|
||||
puts
|
||||
puts "OPTIONS may include:"
|
||||
puts " --opslimit OPSLIMIT -- argon2 ops limit, integer in 3..10, or one of"
|
||||
@ -202,4 +202,4 @@ class StorageKey
|
||||
end
|
||||
end
|
||||
|
||||
main()
|
||||
main()
|
@ -1,7 +1,8 @@
|
||||
AC_PREREQ([2.64])
|
||||
AC_INIT([tofu-scrambler],[1.0.0],[],[],[https://0xacab.org/riseuplabs/tofu-scrambler.git])
|
||||
AC_INIT([trees],[1.0.0],[https://0xacab.org/riseuplabs/trees/issues],
|
||||
[trees-plugin],[https://0xacab.org/riseuplabs/trees.git])
|
||||
|
||||
AC_CONFIG_HEADERS([libscrambler-config.h])
|
||||
AC_CONFIG_HEADERS([trees-config.h])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
AC_CONFIG_SRCDIR([src])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
@ -1,16 +1,16 @@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(builddir) $(LIBDOVECOT_INCLUDE)
|
||||
|
||||
lib_LTLIBRARIES = lib18_scrambler_plugin.la
|
||||
lib_LTLIBRARIES = lib18_trees_plugin.la
|
||||
|
||||
lib18_scrambler_plugin_la_SOURCES = \
|
||||
scrambler-common.c \
|
||||
scrambler-common.h \
|
||||
scrambler-istream.c \
|
||||
scrambler-istream.h \
|
||||
scrambler-ostream.c \
|
||||
scrambler-ostream.h \
|
||||
scrambler-plugin.c \
|
||||
scrambler-plugin.h
|
||||
lib18_trees_plugin_la_SOURCES = \
|
||||
trees-common.c \
|
||||
trees-common.h \
|
||||
trees-istream.c \
|
||||
trees-istream.h \
|
||||
trees-ostream.c \
|
||||
trees-ostream.h \
|
||||
trees-plugin.c \
|
||||
trees-plugin.h
|
||||
|
||||
lib18_scrambler_plugin_la_LDFLAGS = \
|
||||
lib18_trees_plugin_la_LDFLAGS = \
|
||||
-shared -rdynamic -avoid-version -module
|
||||
|
@ -31,23 +31,23 @@
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#include "scrambler-common.h"
|
||||
#include "trees-common.h"
|
||||
|
||||
const unsigned char scrambler_header[] = { 0xee, 0xff, 0xcc };
|
||||
const unsigned char trees_header[] = { 0xee, 0xff, 0xcc };
|
||||
|
||||
int
|
||||
scrambler_initialize(void)
|
||||
trees_initialize(void)
|
||||
{
|
||||
if (sodium_init() < 0) {
|
||||
i_info("scrambler plugin libsodium failed to initialized.");
|
||||
i_info("trees plugin libsodium failed to initialized.");
|
||||
return -1;
|
||||
}
|
||||
i_info("scrambler plugin initialized");
|
||||
i_info("trees plugin initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
scrambler_read_line_fd(pool_t pool, int fd)
|
||||
trees_read_line_fd(pool_t pool, int fd)
|
||||
{
|
||||
string_t *buffer = str_new(pool, MAXIMAL_PASSWORD_LENGTH);
|
||||
char *result = str_c_modifiable(buffer);
|
@ -20,8 +20,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRAMBLER_COMMON_H
|
||||
#define SCRAMBLER_COMMON_H
|
||||
#ifndef TREES_COMMON_H
|
||||
#define TREES_COMMON_H
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#define MIN_VERSION VERSION_ONE
|
||||
#define MAX_VERSION VERSION_ONE
|
||||
|
||||
#define MAGIC_SIZE (sizeof(scrambler_header))
|
||||
#define MAGIC_SIZE (sizeof(trees_header))
|
||||
#define VERSION_SIZE (sizeof(uint32_t))
|
||||
#define HEADER_SIZE (MAGIC_SIZE + VERSION_SIZE)
|
||||
|
||||
@ -50,12 +50,12 @@
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
extern const unsigned char scrambler_header[3];
|
||||
extern const unsigned char trees_header[3];
|
||||
|
||||
int scrambler_initialize(void);
|
||||
int trees_initialize(void);
|
||||
|
||||
const char *scrambler_read_line_fd(pool_t pool, int file_descriptor);
|
||||
const char *trees_read_line_fd(pool_t pool, int file_descriptor);
|
||||
|
||||
void i_debug_hex(const char *prefix, const unsigned char *data, size_t size);
|
||||
|
||||
#endif /* SCRAMBLER_COMMON_H */
|
||||
#endif /* TREES_COMMON_H */
|
@ -28,19 +28,19 @@
|
||||
#include <dovecot/istream.h>
|
||||
#include <dovecot/istream-private.h>
|
||||
|
||||
#include "scrambler-common.h"
|
||||
#include "scrambler-istream.h"
|
||||
#include "trees-common.h"
|
||||
#include "trees-istream.h"
|
||||
|
||||
enum scrambler_istream_mode {
|
||||
enum trees_istream_mode {
|
||||
ISTREAM_MODE_DETECT = 1,
|
||||
ISTREAM_MODE_DECRYPT = 2,
|
||||
ISTREAM_MODE_PLAIN = 3,
|
||||
};
|
||||
|
||||
struct scrambler_istream {
|
||||
struct trees_istream {
|
||||
struct istream_private istream;
|
||||
|
||||
enum scrambler_istream_mode mode;
|
||||
enum trees_istream_mode mode;
|
||||
|
||||
uint32_t version;
|
||||
|
||||
@ -56,9 +56,9 @@ struct scrambler_istream {
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read_parent(struct scrambler_istream *sstream,
|
||||
size_t minimal_read_size,
|
||||
size_t minimal_alloc_size)
|
||||
trees_istream_read_parent(struct trees_istream *sstream,
|
||||
size_t minimal_read_size,
|
||||
size_t minimal_alloc_size)
|
||||
{
|
||||
struct istream_private *stream = &sstream->istream;
|
||||
size_t size;
|
||||
@ -85,14 +85,14 @@ scrambler_istream_read_parent(struct scrambler_istream *sstream,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read_detect_header(struct scrambler_istream *sstream,
|
||||
const unsigned char *source)
|
||||
trees_istream_read_detect_header(struct trees_istream *sstream,
|
||||
const unsigned char *source)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
/* Check for the scrambler header and if so we have an encrypted email that
|
||||
/* Check for the trees header and if so we have an encrypted email that
|
||||
* we'll try to decrypt. */
|
||||
if (!memcmp(scrambler_header, source, MAGIC_SIZE)) {
|
||||
if (!memcmp(trees_header, source, MAGIC_SIZE)) {
|
||||
/* Yay we have an encrypted mail! Let's get the version of the plugin it
|
||||
* was encrypted for. */
|
||||
uint32_t version_to_network;
|
||||
@ -101,7 +101,7 @@ scrambler_istream_read_detect_header(struct scrambler_istream *sstream,
|
||||
sstream->version = ntohl(version_to_network);
|
||||
sstream->mode = ISTREAM_MODE_DECRYPT;
|
||||
if (sstream->private_key == NULL) {
|
||||
i_error("[scrambler] No private key for decryption.");
|
||||
i_error("[trees] No private key for decryption.");
|
||||
sstream->istream.istream.stream_errno = EACCES;
|
||||
sstream->istream.istream.eof = TRUE;
|
||||
ret = -1;
|
||||
@ -109,7 +109,7 @@ scrambler_istream_read_detect_header(struct scrambler_istream *sstream,
|
||||
}
|
||||
if (sstream->version < MIN_VERSION ||
|
||||
sstream->version > MAX_VERSION) {
|
||||
i_error("[scrambler] Unknown version %" PRIu32 ". Supporting %d to %d",
|
||||
i_error("[trees] Unknown version %" PRIu32 ". Supporting %d to %d",
|
||||
sstream->version, MIN_VERSION, MAX_VERSION);
|
||||
sstream->istream.istream.stream_errno = EACCES;
|
||||
sstream->istream.istream.eof = TRUE;
|
||||
@ -128,7 +128,7 @@ end:
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read_detect(struct scrambler_istream *sstream)
|
||||
trees_istream_read_detect(struct trees_istream *sstream)
|
||||
{
|
||||
struct istream_private *stream = &sstream->istream;
|
||||
const unsigned char *source;
|
||||
@ -138,14 +138,14 @@ scrambler_istream_read_detect(struct scrambler_istream *sstream)
|
||||
i_stream_set_max_buffer_size(sstream->istream.parent,
|
||||
MAX_ISTREAM_BUFFER_SIZE);
|
||||
|
||||
result = scrambler_istream_read_parent(sstream, MAGIC_SIZE, 0);
|
||||
result = trees_istream_read_parent(sstream, MAGIC_SIZE, 0);
|
||||
if (result <= 0) {
|
||||
/* Make sure we return an error here. */
|
||||
result = -1;
|
||||
goto end;
|
||||
}
|
||||
source = i_stream_get_data(stream->parent, &source_size);
|
||||
result = scrambler_istream_read_detect_header(sstream, source);
|
||||
result = trees_istream_read_detect_header(sstream, source);
|
||||
if (result < 0) {
|
||||
goto end;
|
||||
}
|
||||
@ -163,14 +163,14 @@ end:
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read_decrypt_chunk(struct scrambler_istream *sstream,
|
||||
unsigned char *destination,
|
||||
const unsigned char *source,
|
||||
size_t source_size)
|
||||
trees_istream_read_decrypt_chunk(struct trees_istream *sstream,
|
||||
unsigned char *destination,
|
||||
const unsigned char *source,
|
||||
size_t source_size)
|
||||
{
|
||||
#ifdef DEBUG_STREAMS
|
||||
sstream->in_byte_count += source_size;
|
||||
i_debug("[scrambler] Decrypt chunk source size: %lu", source_size);
|
||||
i_debug("[trees] Decrypt chunk source size: %lu", source_size);
|
||||
#endif
|
||||
|
||||
/* Note that we skip the header in the source for decryption. */
|
||||
@ -179,7 +179,7 @@ scrambler_istream_read_decrypt_chunk(struct scrambler_istream *sstream,
|
||||
sstream->public_key,
|
||||
sstream->private_key);
|
||||
if (ret != 0) {
|
||||
i_error("[scrambler] Box seal open failed with %ld", ret);
|
||||
i_error("[trees] Box seal open failed with %ld", ret);
|
||||
ret = -1;
|
||||
} else {
|
||||
/* We just decrypted that amount of bytes. */
|
||||
@ -189,7 +189,7 @@ scrambler_istream_read_decrypt_chunk(struct scrambler_istream *sstream,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
trees_istream_read_decrypt(struct trees_istream *sstream)
|
||||
{
|
||||
struct istream_private *stream = &sstream->istream;
|
||||
const unsigned char *parent_data, *source, *source_end;
|
||||
@ -197,7 +197,7 @@ scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
ssize_t result;
|
||||
size_t source_size;
|
||||
|
||||
result = scrambler_istream_read_parent(sstream, ENCRYPTED_CHUNK_SIZE,
|
||||
result = trees_istream_read_parent(sstream, ENCRYPTED_CHUNK_SIZE,
|
||||
CHUNK_SIZE + stream->pos);
|
||||
if (result <= 0 && result != -1) {
|
||||
return result;
|
||||
@ -211,7 +211,7 @@ scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
|
||||
while ((source_end - source) >= ENCRYPTED_CHUNK_SIZE) {
|
||||
if (destination_end - destination < CHUNK_SIZE) {
|
||||
i_error("[scrambler] Decrypting to a destination too small. "
|
||||
i_error("[trees] Decrypting to a destination too small. "
|
||||
"Expected %ld but remaining %ld. Stopping.",
|
||||
destination_end - destination,
|
||||
source_end - source);
|
||||
@ -222,7 +222,7 @@ scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
|
||||
/* Decrypt a chunk of our ENCRYPTED_CHUNK_SIZE as we know that we are
|
||||
* expecting at least that amount. */
|
||||
result = scrambler_istream_read_decrypt_chunk(sstream, destination,
|
||||
result = trees_istream_read_decrypt_chunk(sstream, destination,
|
||||
source,
|
||||
ENCRYPTED_CHUNK_SIZE);
|
||||
if (result < 0) {
|
||||
@ -245,7 +245,7 @@ scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
stream->istream.eof = FALSE;
|
||||
|
||||
if (destination_end - destination < CHUNK_SIZE) {
|
||||
i_error("[scrambler] At EOF, decrypting to a destination too small. "
|
||||
i_error("[trees] At EOF, decrypting to a destination too small. "
|
||||
"Expected %ld but remaining %ld",
|
||||
destination_end - destination,
|
||||
source_end - source);
|
||||
@ -254,7 +254,7 @@ scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = scrambler_istream_read_decrypt_chunk(sstream, destination,
|
||||
result = trees_istream_read_decrypt_chunk(sstream, destination,
|
||||
source,
|
||||
source_end - source);
|
||||
if (result < 0) {
|
||||
@ -282,21 +282,21 @@ scrambler_istream_read_decrypt(struct scrambler_istream *sstream)
|
||||
|
||||
#ifdef DEBUG_STREAMS
|
||||
sstream->out_byte_count += result;
|
||||
i_debug("[scrambler] Read decrypt %ld bytes", result);
|
||||
i_debug("[trees] Read decrypt %ld bytes", result);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read_plain(struct scrambler_istream *sstream)
|
||||
trees_istream_read_plain(struct trees_istream *sstream)
|
||||
{
|
||||
size_t source_size, copy_size;
|
||||
ssize_t result;
|
||||
const unsigned char *source;
|
||||
struct istream_private *stream = &sstream->istream;
|
||||
|
||||
result = scrambler_istream_read_parent(sstream, 1, 0);
|
||||
result = trees_istream_read_parent(sstream, 1, 0);
|
||||
if (result <= 0) {
|
||||
return result;
|
||||
}
|
||||
@ -317,13 +317,13 @@ scrambler_istream_read_plain(struct scrambler_istream *sstream)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_istream_read(struct istream_private *stream)
|
||||
trees_istream_read(struct istream_private *stream)
|
||||
{
|
||||
int ret;
|
||||
struct scrambler_istream *sstream = (struct scrambler_istream *) stream;
|
||||
struct trees_istream *sstream = (struct trees_istream *) stream;
|
||||
|
||||
if (sstream->mode == ISTREAM_MODE_DETECT) {
|
||||
ret = scrambler_istream_read_detect(sstream);
|
||||
ret = trees_istream_read_detect(sstream);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -332,9 +332,9 @@ scrambler_istream_read(struct istream_private *stream)
|
||||
/* We've now detected the mode, process it. */
|
||||
switch (sstream->mode) {
|
||||
case ISTREAM_MODE_DECRYPT:
|
||||
return scrambler_istream_read_decrypt(sstream);
|
||||
return trees_istream_read_decrypt(sstream);
|
||||
case ISTREAM_MODE_PLAIN:
|
||||
return scrambler_istream_read_plain(sstream);
|
||||
return trees_istream_read_plain(sstream);
|
||||
case ISTREAM_MODE_DETECT:
|
||||
/* Something went terribly wrong. */
|
||||
assert(0);
|
||||
@ -345,13 +345,13 @@ scrambler_istream_read(struct istream_private *stream)
|
||||
}
|
||||
|
||||
static void
|
||||
scrambler_istream_seek(struct istream_private *stream, uoff_t v_offset,
|
||||
bool mark)
|
||||
trees_istream_seek(struct istream_private *stream, uoff_t v_offset,
|
||||
bool mark)
|
||||
{
|
||||
struct scrambler_istream *sstream = (struct scrambler_istream *) stream;
|
||||
struct trees_istream *sstream = (struct trees_istream *) stream;
|
||||
|
||||
#ifdef DEBUG_STREAMS
|
||||
i_debug("[scrambler] istream seek %d / %d / %d",
|
||||
i_debug("[trees] istream seek %d / %d / %d",
|
||||
(int)stream->istream.v_offset, (int)v_offset, (int)mark);
|
||||
#endif
|
||||
|
||||
@ -375,7 +375,7 @@ scrambler_istream_seek(struct istream_private *stream, uoff_t v_offset,
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_istream_stat(struct istream_private *stream, bool exact)
|
||||
trees_istream_stat(struct istream_private *stream, bool exact)
|
||||
{
|
||||
const struct stat *stat;
|
||||
if (i_stream_stat(stream->parent, exact, &stat) < 0) {
|
||||
@ -386,12 +386,12 @@ scrambler_istream_stat(struct istream_private *stream, bool exact)
|
||||
}
|
||||
|
||||
static void
|
||||
scrambler_istream_close(struct iostream_private *stream, bool close_parent)
|
||||
trees_istream_close(struct iostream_private *stream, bool close_parent)
|
||||
{
|
||||
struct scrambler_istream *sstream = (struct scrambler_istream *) stream;
|
||||
struct trees_istream *sstream = (struct trees_istream *) stream;
|
||||
|
||||
#ifdef DEBUG_STREAMS
|
||||
i_debug("[scrambler] istream close - %u bytes in / %u bytes out / "
|
||||
i_debug("[trees] istream close - %u bytes in / %u bytes out / "
|
||||
"%u bytes overhead", sstream->in_byte_count,
|
||||
sstream->out_byte_count,
|
||||
sstream->in_byte_count - sstream->out_byte_count);
|
||||
@ -403,11 +403,11 @@ scrambler_istream_close(struct iostream_private *stream, bool close_parent)
|
||||
}
|
||||
|
||||
struct istream *
|
||||
scrambler_istream_create(struct istream *input,
|
||||
const unsigned char *public_key,
|
||||
unsigned char *private_key)
|
||||
trees_istream_create(struct istream *input,
|
||||
const unsigned char *public_key,
|
||||
unsigned char *private_key)
|
||||
{
|
||||
struct scrambler_istream *sstream = i_new(struct scrambler_istream, 1);
|
||||
struct trees_istream *sstream = i_new(struct trees_istream, 1);
|
||||
|
||||
sstream->mode = ISTREAM_MODE_DETECT;
|
||||
|
||||
@ -416,11 +416,11 @@ scrambler_istream_create(struct istream *input,
|
||||
|
||||
sstream->last_chunk_read = 0;
|
||||
|
||||
sstream->istream.iostream.close = scrambler_istream_close;
|
||||
sstream->istream.iostream.close = trees_istream_close;
|
||||
sstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
|
||||
sstream->istream.read = scrambler_istream_read;
|
||||
sstream->istream.seek = scrambler_istream_seek;
|
||||
sstream->istream.stat = scrambler_istream_stat;
|
||||
sstream->istream.read = trees_istream_read;
|
||||
sstream->istream.seek = trees_istream_seek;
|
||||
sstream->istream.stat = trees_istream_stat;
|
||||
|
||||
sstream->istream.istream.readable_fd = FALSE;
|
||||
sstream->istream.istream.blocking = input->blocking;
|
@ -20,13 +20,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRAMBLER_ISTREAM_H
|
||||
#define SCRAMBLER_ISTREAM_H
|
||||
#ifndef TREES_ISTREAM_H
|
||||
#define TREES_ISTREAM_H
|
||||
|
||||
#include <dovecot/istream.h>
|
||||
|
||||
struct istream *scrambler_istream_create(struct istream *input,
|
||||
const unsigned char *public_key,
|
||||
unsigned char *private_key);
|
||||
struct istream *trees_istream_create(struct istream *input,
|
||||
const unsigned char *public_key,
|
||||
unsigned char *private_key);
|
||||
|
||||
#endif /* SCRAMBLER_ISTREAM_H */
|
||||
#endif /* TREES_ISTREAM_H */
|
@ -30,11 +30,11 @@
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#include "scrambler-common.h"
|
||||
#include "scrambler-ostream.h"
|
||||
#include "trees-common.h"
|
||||
#include "trees-ostream.h"
|
||||
|
||||
|
||||
struct scrambler_ostream {
|
||||
struct trees_ostream {
|
||||
struct ostream_private ostream;
|
||||
|
||||
uint32_t version;
|
||||
@ -52,13 +52,13 @@ struct scrambler_ostream {
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
scrambler_ostream_send_header(struct scrambler_ostream *sstream)
|
||||
trees_ostream_send_header(struct trees_ostream *sstream)
|
||||
{
|
||||
char header[HEADER_SIZE];
|
||||
uint32_t version_to_host;
|
||||
|
||||
/* First set the header magic number. */
|
||||
memcpy(header, scrambler_header, MAGIC_SIZE);
|
||||
memcpy(header, trees_header, MAGIC_SIZE);
|
||||
/* Then, put in the version. */
|
||||
version_to_host = htonl(sstream->version);
|
||||
memcpy(header + MAGIC_SIZE, &version_to_host, VERSION_SIZE);
|
||||
@ -73,8 +73,8 @@ scrambler_ostream_send_header(struct scrambler_ostream *sstream)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_ostream_send_chunk(struct scrambler_ostream *sstream,
|
||||
const unsigned char *chunk, size_t chunk_size)
|
||||
trees_ostream_send_chunk(struct trees_ostream *sstream,
|
||||
const unsigned char *chunk, size_t chunk_size)
|
||||
{
|
||||
int ret;
|
||||
/* Extra protection here against overflow. Maybe too agressive! */
|
||||
@ -101,13 +101,13 @@ scrambler_ostream_send_chunk(struct scrambler_ostream *sstream,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
scrambler_ostream_sendv(struct ostream_private *stream,
|
||||
const struct const_iovec *iov, unsigned int iov_count)
|
||||
trees_ostream_sendv(struct ostream_private *stream,
|
||||
const struct const_iovec *iov, unsigned int iov_count)
|
||||
{
|
||||
size_t chunk_size;
|
||||
ssize_t result = 0, encrypt_result = 0;
|
||||
const unsigned char *source, *source_end;
|
||||
struct scrambler_ostream *sstream = (struct scrambler_ostream *) stream;
|
||||
struct trees_ostream *sstream = (struct trees_ostream *) stream;
|
||||
|
||||
for (unsigned int index = 0; index < iov_count; index++) {
|
||||
source = iov[index].iov_base;
|
||||
@ -123,7 +123,7 @@ scrambler_ostream_sendv(struct ostream_private *stream,
|
||||
sstream->chunk_buffer_size += chunk_size;
|
||||
|
||||
if (sstream->chunk_buffer_size == CHUNK_SIZE) {
|
||||
encrypt_result = scrambler_ostream_send_chunk(sstream,
|
||||
encrypt_result = trees_ostream_send_chunk(sstream,
|
||||
sstream->chunk_buffer,
|
||||
CHUNK_SIZE);
|
||||
if (encrypt_result < 0) {
|
||||
@ -132,7 +132,7 @@ scrambler_ostream_sendv(struct ostream_private *stream,
|
||||
sstream->chunk_buffer_size = 0;
|
||||
}
|
||||
} else {
|
||||
encrypt_result = scrambler_ostream_send_chunk(sstream, source,
|
||||
encrypt_result = trees_ostream_send_chunk(sstream, source,
|
||||
CHUNK_SIZE);
|
||||
if (encrypt_result < 0) {
|
||||
return encrypt_result;
|
||||
@ -149,26 +149,26 @@ scrambler_ostream_sendv(struct ostream_private *stream,
|
||||
|
||||
#ifdef DEBUG_STREAMS
|
||||
sstream->in_byte_count += result;
|
||||
i_debug("[scrambler] ostream send (%ld)", result);
|
||||
i_debug("[trees] ostream send (%ld)", result);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_ostream_flush(struct ostream_private *stream)
|
||||
trees_ostream_flush(struct ostream_private *stream)
|
||||
{
|
||||
ssize_t result = 0;
|
||||
struct scrambler_ostream *sstream = (struct scrambler_ostream *) stream;
|
||||
struct trees_ostream *sstream = (struct trees_ostream *) stream;
|
||||
|
||||
if (sstream->flushed) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = scrambler_ostream_send_chunk(sstream, sstream->chunk_buffer,
|
||||
result = trees_ostream_send_chunk(sstream, sstream->chunk_buffer,
|
||||
sstream->chunk_buffer_size);
|
||||
if (result < 0) {
|
||||
i_error("[scrambler] Error sending last chunk on close");
|
||||
i_error("[trees] Error sending last chunk on close");
|
||||
goto end;
|
||||
}
|
||||
sstream->chunk_buffer_size = 0;
|
||||
@ -183,19 +183,19 @@ scrambler_ostream_flush(struct ostream_private *stream)
|
||||
|
||||
end:
|
||||
#ifdef DEBUG_STREAMS
|
||||
i_debug("[scrambler] ostream flush (%ld)", result);
|
||||
i_debug("[trees] ostream flush (%ld)", result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
scrambler_ostream_close(struct iostream_private *stream,
|
||||
bool close_parent)
|
||||
trees_ostream_close(struct iostream_private *stream,
|
||||
bool close_parent)
|
||||
{
|
||||
struct scrambler_ostream *sstream = (struct scrambler_ostream *) stream;
|
||||
struct trees_ostream *sstream = (struct trees_ostream *) stream;
|
||||
|
||||
#ifdef DEBUG_STREAMS
|
||||
i_debug("[scrambler] ostream close - %u bytes in / %u bytes out / "
|
||||
i_debug("[trees] ostream close - %u bytes in / %u bytes out / "
|
||||
"%u bytes overhead", sstream->in_byte_count,
|
||||
sstream->out_byte_count,
|
||||
sstream->out_byte_count - sstream->in_byte_count);
|
||||
@ -207,11 +207,11 @@ scrambler_ostream_close(struct iostream_private *stream,
|
||||
}
|
||||
|
||||
struct ostream *
|
||||
scrambler_ostream_create(struct ostream *output,
|
||||
const unsigned char *public_key,
|
||||
uint32_t version)
|
||||
trees_ostream_create(struct ostream *output,
|
||||
const unsigned char *public_key,
|
||||
uint32_t version)
|
||||
{
|
||||
struct scrambler_ostream *sstream = i_new(struct scrambler_ostream, 1);
|
||||
struct trees_ostream *sstream = i_new(struct trees_ostream, 1);
|
||||
struct ostream *result;
|
||||
|
||||
sstream->public_key = public_key;
|
||||
@ -220,9 +220,9 @@ scrambler_ostream_create(struct ostream *output,
|
||||
sstream->chunk_buffer_size = 0;
|
||||
sstream->flushed = 0;
|
||||
|
||||
sstream->ostream.iostream.close = scrambler_ostream_close;
|
||||
sstream->ostream.sendv = scrambler_ostream_sendv;
|
||||
sstream->ostream.flush = scrambler_ostream_flush;
|
||||
sstream->ostream.iostream.close = trees_ostream_close;
|
||||
sstream->ostream.sendv = trees_ostream_sendv;
|
||||
sstream->ostream.flush = trees_ostream_flush;
|
||||
|
||||
#ifdef DEBUG_STREAMS
|
||||
sstream->in_byte_count = 0;
|
||||
@ -231,8 +231,8 @@ scrambler_ostream_create(struct ostream *output,
|
||||
|
||||
result = o_stream_create(&sstream->ostream, output,
|
||||
o_stream_get_fd(output));
|
||||
if (scrambler_ostream_send_header(sstream) < 0) {
|
||||
i_error("[scrambler] Unable to create ostream");
|
||||
if (trees_ostream_send_header(sstream) < 0) {
|
||||
i_error("[trees] Unable to create ostream");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -20,13 +20,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRAMBLER_OSTREAM_H
|
||||
#define SCRAMBLER_OSTREAM_H
|
||||
#ifndef TREES_OSTREAM_H
|
||||
#define TREES_OSTREAM_H
|
||||
|
||||
#include <dovecot/ostream.h>
|
||||
|
||||
struct ostream *scrambler_ostream_create(struct ostream *parent_ostream,
|
||||
const unsigned char *public_key,
|
||||
uint32_t version);
|
||||
struct ostream *trees_ostream_create(struct ostream *parent_ostream,
|
||||
const unsigned char *public_key,
|
||||
uint32_t version);
|
||||
|
||||
#endif /* SCRAMBLER_OSTREAM_H */
|
||||
#endif /* TREES_OSTREAM_H */
|
@ -40,19 +40,19 @@
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
#include "scrambler-plugin.h"
|
||||
#include "scrambler-common.h"
|
||||
#include "scrambler-ostream.h"
|
||||
#include "scrambler-istream.h"
|
||||
#include "trees-plugin.h"
|
||||
#include "trees-common.h"
|
||||
#include "trees-ostream.h"
|
||||
#include "trees-istream.h"
|
||||
|
||||
#define SCRAMBLER_CONTEXT(obj) \
|
||||
MODULE_CONTEXT(obj, scrambler_storage_module)
|
||||
#define SCRAMBLER_MAIL_CONTEXT(obj) \
|
||||
MODULE_CONTEXT(obj, scrambler_mail_module)
|
||||
#define SCRAMBLER_USER_CONTEXT(obj) \
|
||||
MODULE_CONTEXT(obj, scrambler_user_module)
|
||||
#define TREES_CONTEXT(obj) \
|
||||
MODULE_CONTEXT(obj, trees_storage_module)
|
||||
#define TREES_MAIL_CONTEXT(obj) \
|
||||
MODULE_CONTEXT(obj, trees_mail_module)
|
||||
#define TREES_USER_CONTEXT(obj) \
|
||||
MODULE_CONTEXT(obj, trees_user_module)
|
||||
|
||||
struct scrambler_user {
|
||||
struct trees_user {
|
||||
/* Dovecot module context. */
|
||||
union mail_user_module_context module_ctx;
|
||||
|
||||
@ -71,25 +71,25 @@ struct scrambler_user {
|
||||
unsigned char private_key[crypto_box_SECRETKEYBYTES];
|
||||
};
|
||||
|
||||
const char *scrambler_plugin_version = DOVECOT_ABI_VERSION;
|
||||
const char *trees_plugin_version = DOVECOT_ABI_VERSION;
|
||||
|
||||
static MODULE_CONTEXT_DEFINE_INIT(scrambler_storage_module,
|
||||
static MODULE_CONTEXT_DEFINE_INIT(trees_storage_module,
|
||||
&mail_storage_module_register);
|
||||
static MODULE_CONTEXT_DEFINE_INIT(scrambler_mail_module,
|
||||
static MODULE_CONTEXT_DEFINE_INIT(trees_mail_module,
|
||||
&mail_module_register);
|
||||
static MODULE_CONTEXT_DEFINE_INIT(scrambler_user_module,
|
||||
static MODULE_CONTEXT_DEFINE_INIT(trees_user_module,
|
||||
&mail_user_module_register);
|
||||
|
||||
static const char *
|
||||
scrambler_get_string_setting(struct mail_user *user, const char *name)
|
||||
trees_get_string_setting(struct mail_user *user, const char *name)
|
||||
{
|
||||
return mail_user_plugin_getenv(user, name);
|
||||
}
|
||||
|
||||
static unsigned long long int
|
||||
scrambler_get_ullong_setting(struct mail_user *user, const char *name)
|
||||
trees_get_ullong_setting(struct mail_user *user, const char *name)
|
||||
{
|
||||
const char *value = scrambler_get_string_setting(user, name);
|
||||
const char *value = trees_get_string_setting(user, name);
|
||||
if (value == NULL) {
|
||||
return ULLONG_MAX;
|
||||
}
|
||||
@ -97,9 +97,9 @@ scrambler_get_ullong_setting(struct mail_user *user, const char *name)
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_get_integer_setting(struct mail_user *user, const char *name)
|
||||
trees_get_integer_setting(struct mail_user *user, const char *name)
|
||||
{
|
||||
const char *value = scrambler_get_string_setting(user, name);
|
||||
const char *value = trees_get_string_setting(user, name);
|
||||
if (value == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@ -107,12 +107,12 @@ scrambler_get_integer_setting(struct mail_user *user, const char *name)
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_get_user_hexdata(struct mail_user *user, const char *param,
|
||||
unsigned char *out, size_t out_len)
|
||||
trees_get_user_hexdata(struct mail_user *user, const char *param,
|
||||
unsigned char *out, size_t out_len)
|
||||
{
|
||||
const char *hex_str;
|
||||
|
||||
hex_str = scrambler_get_string_setting(user, param);
|
||||
hex_str = trees_get_string_setting(user, param);
|
||||
if (hex_str == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@ -121,7 +121,7 @@ scrambler_get_user_hexdata(struct mail_user *user, const char *param,
|
||||
user->error = p_strdup_printf(user->pool,
|
||||
"Unable to convert %s for user %s.", param,
|
||||
user->username);
|
||||
i_error("[scrambler] Failing to hex2bin for %s", param);
|
||||
i_error("[trees] Failing to hex2bin for %s", param);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -132,8 +132,8 @@ error:
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_get_private_key(struct mail_user *user,
|
||||
struct scrambler_user *suser)
|
||||
trees_get_private_key(struct mail_user *user,
|
||||
struct trees_user *suser)
|
||||
{
|
||||
int have_salt, password_fd;
|
||||
unsigned long long opslimit, memlimit;
|
||||
@ -148,10 +148,10 @@ scrambler_get_private_key(struct mail_user *user,
|
||||
const char *password;
|
||||
|
||||
/* Get the user password that we'll use to . */
|
||||
password = scrambler_get_string_setting(user, "scrambler_password");
|
||||
password_fd = scrambler_get_integer_setting(user, "scrambler_password_fd");
|
||||
password = trees_get_string_setting(user, "trees_password");
|
||||
password_fd = trees_get_integer_setting(user, "trees_password_fd");
|
||||
if (password == NULL && password_fd >= 0) {
|
||||
password = scrambler_read_line_fd(user->pool, password_fd);
|
||||
password = trees_read_line_fd(user->pool, password_fd);
|
||||
}
|
||||
|
||||
/* No password means that we are receiving email and have no access to the
|
||||
@ -161,32 +161,32 @@ scrambler_get_private_key(struct mail_user *user,
|
||||
}
|
||||
|
||||
/* Get the nonce. */
|
||||
if (scrambler_get_user_hexdata(user, "scrambler_sk_nonce",
|
||||
if (trees_get_user_hexdata(user, "trees_sk_nonce",
|
||||
sk_nonce, sizeof(sk_nonce))) {
|
||||
user->error = p_strdup_printf(user->pool,
|
||||
"Unable to find nonce value for user %s.",
|
||||
user->username);
|
||||
i_error("[scrambler] Unable to get sk_nonce.");
|
||||
i_error("[trees] Unable to get sk_nonce.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get the opslimit and memlimit. */
|
||||
opslimit = scrambler_get_ullong_setting(user, "scrambler_pwhash_opslimit");
|
||||
opslimit = trees_get_ullong_setting(user, "trees_pwhash_opslimit");
|
||||
if (opslimit == ULLONG_MAX) {
|
||||
i_error("[scrambler] Bad pwhash_opslimit value.");
|
||||
i_error("[trees] Bad pwhash_opslimit value.");
|
||||
goto error;
|
||||
}
|
||||
memlimit = scrambler_get_ullong_setting(user, "scrambler_pwhash_memlimit");
|
||||
memlimit = trees_get_ullong_setting(user, "trees_pwhash_memlimit");
|
||||
if (memlimit == ULLONG_MAX) {
|
||||
i_error("[scrambler] Bad pwhash_memlimit value.");
|
||||
i_error("[trees] Bad pwhash_memlimit value.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get the scrambler user salt. It's possible that it's not available. */
|
||||
have_salt = scrambler_get_user_hexdata(user, "scrambler_pwhash_salt",
|
||||
/* Get the trees user salt. It's possible that it's not available. */
|
||||
have_salt = trees_get_user_hexdata(user, "trees_pwhash_salt",
|
||||
pw_salt, sizeof(pw_salt));
|
||||
if (have_salt == -1) {
|
||||
i_error("[scrambler] Unable to get the pwhash_salt.");
|
||||
i_error("[trees] Unable to get the pwhash_salt.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -199,19 +199,19 @@ scrambler_get_private_key(struct mail_user *user,
|
||||
user->error = p_strdup_printf(user->pool,
|
||||
"Unable to derive private key for user %s.",
|
||||
user->username);
|
||||
i_error("[scrambler] pwhash failed for %s", user->username);
|
||||
i_error("[trees] pwhash failed for %s", user->username);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (scrambler_get_user_hexdata(user, "scrambler_locked_secretbox",
|
||||
if (trees_get_user_hexdata(user, "trees_locked_secretbox",
|
||||
secretbox, sizeof(secretbox))) {
|
||||
i_error("[scrambler] Unable to get locked_secretbox");
|
||||
i_error("[trees] Unable to get locked_secretbox");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (crypto_secretbox_open_easy(suser->private_key, secretbox,
|
||||
sizeof(secretbox), sk_nonce, sk) < 0) {
|
||||
i_error("[scrambler] Unable to open secretbox.");
|
||||
i_error("[trees] Unable to open secretbox.");
|
||||
goto error;
|
||||
}
|
||||
/* Got the private key! */
|
||||
@ -225,20 +225,20 @@ error:
|
||||
}
|
||||
|
||||
static void
|
||||
scrambler_mail_user_created(struct mail_user *user)
|
||||
trees_mail_user_created(struct mail_user *user)
|
||||
{
|
||||
int version;
|
||||
struct mail_user_vfuncs *v = user->vlast;
|
||||
struct scrambler_user *suser;
|
||||
struct trees_user *suser;
|
||||
|
||||
suser = p_new(user->pool, struct scrambler_user, 1);
|
||||
suser = p_new(user->pool, struct trees_user, 1);
|
||||
memset(suser, 0, sizeof(*suser));
|
||||
|
||||
suser->module_ctx.super = *v;
|
||||
user->vlast = &suser->module_ctx.super;
|
||||
|
||||
/* Does this user should use the scrambler or not? */
|
||||
suser->enabled = scrambler_get_integer_setting(user, "scrambler_enabled");
|
||||
/* Does this user should use the trees or not? */
|
||||
suser->enabled = trees_get_integer_setting(user, "trees_enabled");
|
||||
if (suser->enabled == -1 || suser->enabled == 0) {
|
||||
/* Not present means disabled. Stop right now because we won't use
|
||||
* anything of this plugin for the user. */
|
||||
@ -247,19 +247,19 @@ scrambler_mail_user_created(struct mail_user *user)
|
||||
}
|
||||
|
||||
/* Get plugin version that the user is configured for. */
|
||||
version = scrambler_get_integer_setting(user, "scrambler_version");
|
||||
version = trees_get_integer_setting(user, "trees_version");
|
||||
if (version < MIN_VERSION || version > MAX_VERSION) {
|
||||
i_error("[scrambler] Bad version value.");
|
||||
i_error("[trees] Bad version value.");
|
||||
goto end;
|
||||
}
|
||||
suser->version = (uint32_t) version;
|
||||
|
||||
/* Getting user public key. Without it, we can't do much so error if we
|
||||
* can't find it. */
|
||||
if (scrambler_get_user_hexdata(user, "scrambler_public_key",
|
||||
if (trees_get_user_hexdata(user, "trees_public_key",
|
||||
suser->public_key,
|
||||
sizeof(suser->public_key))) {
|
||||
i_error("[scrambler] Unable to find public_key");
|
||||
i_error("[trees] Unable to find public_key");
|
||||
goto end;
|
||||
}
|
||||
suser->public_key_set = 1;
|
||||
@ -269,21 +269,21 @@ scrambler_mail_user_created(struct mail_user *user)
|
||||
* email. If we are successful at getting the private key, this flag will
|
||||
* be set to 1. */
|
||||
suser->private_key_set = 0;
|
||||
if (scrambler_get_private_key(user, suser) < 0) {
|
||||
if (trees_get_private_key(user, suser) < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
MODULE_CONTEXT_SET(user, scrambler_user_module, suser);
|
||||
MODULE_CONTEXT_SET(user, trees_user_module, suser);
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_mail_save_begin(struct mail_save_context *context,
|
||||
struct istream *input)
|
||||
trees_mail_save_begin(struct mail_save_context *context,
|
||||
struct istream *input)
|
||||
{
|
||||
struct mailbox *box = context->transaction->box;
|
||||
union mailbox_module_context *mbox = SCRAMBLER_CONTEXT(box);
|
||||
struct scrambler_user *suser = SCRAMBLER_USER_CONTEXT(box->storage->user);
|
||||
union mailbox_module_context *mbox = TREES_CONTEXT(box);
|
||||
struct trees_user *suser = TREES_USER_CONTEXT(box->storage->user);
|
||||
struct ostream *output;
|
||||
|
||||
if (mbox->super.save_begin(context, input) < 0) {
|
||||
@ -296,21 +296,21 @@ scrambler_mail_save_begin(struct mail_save_context *context,
|
||||
|
||||
if (!suser->public_key_set) {
|
||||
/* No public key for a user that have the plugin enabled is not good. */
|
||||
i_error("[scrambler] User public key not found. Skipping.");
|
||||
i_error("[trees] User public key not found. Skipping.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
// TODO: find a better solution for this. this currently works, because
|
||||
// there is only one other ostream (zlib) in the setup. the scrambler should
|
||||
// there is only one other ostream (zlib) in the setup. the trees should
|
||||
// be added to the other end of the ostream chain, not to the
|
||||
// beginning (the usual way).
|
||||
if (context->data.output->real_stream->parent == NULL) {
|
||||
output = scrambler_ostream_create(context->data.output,
|
||||
output = trees_ostream_create(context->data.output,
|
||||
suser->public_key, suser->version);
|
||||
o_stream_unref(&context->data.output);
|
||||
context->data.output = output;
|
||||
} else {
|
||||
output = scrambler_ostream_create(context->data.output->real_stream->parent,
|
||||
output = trees_ostream_create(context->data.output->real_stream->parent,
|
||||
suser->public_key, suser->version);
|
||||
o_stream_unref(&context->data.output->real_stream->parent);
|
||||
context->data.output->real_stream->parent = output;
|
||||
@ -321,7 +321,7 @@ end:
|
||||
}
|
||||
|
||||
static void
|
||||
scrambler_mailbox_allocated(struct mailbox *box)
|
||||
trees_mailbox_allocated(struct mailbox *box)
|
||||
{
|
||||
struct mailbox_vfuncs *v = box->vlast;
|
||||
union mailbox_module_context *mbox;
|
||||
@ -331,28 +331,28 @@ scrambler_mailbox_allocated(struct mailbox *box)
|
||||
mbox->super = *v;
|
||||
box->vlast = &mbox->super;
|
||||
|
||||
MODULE_CONTEXT_SET_SELF(box, scrambler_storage_module, mbox);
|
||||
MODULE_CONTEXT_SET_SELF(box, trees_storage_module, mbox);
|
||||
|
||||
if ((class_flags & MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
|
||||
v->save_begin = scrambler_mail_save_begin;
|
||||
v->save_begin = trees_mail_save_begin;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
scrambler_istream_opened(struct mail *_mail, struct istream **stream)
|
||||
trees_istream_opened(struct mail *_mail, struct istream **stream)
|
||||
{
|
||||
unsigned char *private_key = NULL;
|
||||
struct mail_private *mail = (struct mail_private *)_mail;
|
||||
struct mail_user *user = _mail->box->storage->user;
|
||||
struct scrambler_user *suser = SCRAMBLER_USER_CONTEXT(user);
|
||||
union mail_module_context *mmail = SCRAMBLER_MAIL_CONTEXT(mail);
|
||||
struct trees_user *suser = TREES_USER_CONTEXT(user);
|
||||
union mail_module_context *mmail = TREES_MAIL_CONTEXT(mail);
|
||||
struct istream *input;
|
||||
|
||||
input = *stream;
|
||||
if (suser->private_key_set) {
|
||||
private_key = suser->private_key;
|
||||
}
|
||||
*stream = scrambler_istream_create(input, suser->public_key,
|
||||
*stream = trees_istream_create(input, suser->public_key,
|
||||
private_key);
|
||||
i_stream_unref(&input);
|
||||
|
||||
@ -360,7 +360,7 @@ scrambler_istream_opened(struct mail *_mail, struct istream **stream)
|
||||
}
|
||||
|
||||
static void
|
||||
scrambler_mail_allocated(struct mail *_mail)
|
||||
trees_mail_allocated(struct mail *_mail)
|
||||
{
|
||||
struct mail_private *mail = (struct mail_private *)_mail;
|
||||
struct mail_vfuncs *v = mail->vlast;
|
||||
@ -370,29 +370,29 @@ scrambler_mail_allocated(struct mail *_mail)
|
||||
mmail->super = *v;
|
||||
mail->vlast = &mmail->super;
|
||||
|
||||
v->istream_opened = scrambler_istream_opened;
|
||||
v->istream_opened = trees_istream_opened;
|
||||
|
||||
MODULE_CONTEXT_SET_SELF(mail, scrambler_mail_module, mmail);
|
||||
MODULE_CONTEXT_SET_SELF(mail, trees_mail_module, mmail);
|
||||
}
|
||||
|
||||
static struct mail_storage_hooks scrambler_mail_storage_hooks = {
|
||||
.mail_user_created = scrambler_mail_user_created,
|
||||
.mailbox_allocated = scrambler_mailbox_allocated,
|
||||
.mail_allocated = scrambler_mail_allocated
|
||||
static struct mail_storage_hooks trees_mail_storage_hooks = {
|
||||
.mail_user_created = trees_mail_user_created,
|
||||
.mailbox_allocated = trees_mailbox_allocated,
|
||||
.mail_allocated = trees_mail_allocated
|
||||
};
|
||||
|
||||
void
|
||||
scrambler_plugin_init(struct module *module)
|
||||
trees_plugin_init(struct module *module)
|
||||
{
|
||||
if (scrambler_initialize() < 0) {
|
||||
if (trees_initialize() < 0) {
|
||||
/* Don't hook anything has we weren't able to initialize ourself. */
|
||||
return;
|
||||
}
|
||||
mail_storage_hooks_add(module, &scrambler_mail_storage_hooks);
|
||||
mail_storage_hooks_add(module, &trees_mail_storage_hooks);
|
||||
}
|
||||
|
||||
void
|
||||
scrambler_plugin_deinit(void)
|
||||
trees_plugin_deinit(void)
|
||||
{
|
||||
mail_storage_hooks_remove(&scrambler_mail_storage_hooks);
|
||||
mail_storage_hooks_remove(&trees_mail_storage_hooks);
|
||||
}
|
@ -20,10 +20,10 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRAMBLER_PLUGIN_H
|
||||
#define SCRAMBLER_PLUGIN_H
|
||||
#ifndef TREES_PLUGIN_H
|
||||
#define TREES_PLUGIN_H
|
||||
|
||||
void scrambler_plugin_init(struct module *module);
|
||||
void scrambler_plugin_deinit(void);
|
||||
void trees_plugin_init(struct module *module);
|
||||
void trees_plugin_deinit(void);
|
||||
|
||||
#endif /* SCRAMBLER_PLUGIN_H */
|
||||
#endif /* TREES_PLUGIN_H */
|
Loading…
Reference in New Issue
Block a user