Rename project from tofu-scrambler to trees

Signed-off-by: David Goulet <dgoulet@riseup.net>
This commit is contained in:
David Goulet 2017-02-12 13:17:41 -05:00
parent cc076fec13
commit 300f0dbf69
13 changed files with 242 additions and 241 deletions

4
.gitignore vendored
View File

@ -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

View File

@ -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:

View File

@ -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()

View File

@ -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])

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */