mail-crypt-acl-plugin.c revision eb318ea05532d2e54ed3bfc89bc15dcf1adae838
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2015-2017 Dovecot authors, see the included COPYING file */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "lib.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "ioloop-private.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "str.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "sha2.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "module-dir.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "var-expand.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "hex-binary.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "mail-namespace.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "mail-storage-hooks.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "mail-storage-service.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "acl-plugin.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "acl-api-private.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "mail-crypt-common.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "mail-crypt-key.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "mail-crypt-plugin.h"
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen#define MAIL_CRYPT_ACL_LIST_CONTEXT(obj) \
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen MODULE_CONTEXT(obj, mail_crypt_acl_mailbox_list_module)
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainenstruct mail_crypt_acl_mailbox_list {
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen union mailbox_list_module_context module_ctx;
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen struct acl_backend_vfuncs acl_vprev;
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen};
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_crypt_acl_mailbox_list_module,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen &mailbox_list_module_register);
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainenvoid mail_crypt_acl_plugin_init(struct module *module);
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainenvoid mail_crypt_acl_plugin_deinit(void);
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic int
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenmail_crypt_acl_has_user_read_right(struct acl_object *aclobj,
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen const char *username,
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen const char **error_r)
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen{
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct acl_object_list_iter *iter;
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen struct acl_rights rights;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen int ret = 0;
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen iter = acl_object_list_init(aclobj);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen while (acl_object_list_next(iter, &rights)) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (rights.id_type == ACL_ID_USER &&
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen strcmp(rights.identifier, username) == 0) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen ret = str_array_find(rights.rights, MAIL_ACL_READ) ? 1 : 0;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen break;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (acl_object_list_deinit(&iter) < 0) {
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen *error_r = "Failed to iterate ACL objects";
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return -1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return ret;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen}
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainenstatic int mail_crypt_acl_has_nonuser_read_right(struct acl_object *aclobj,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char **error_r)
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen{
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct acl_object_list_iter *iter;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct acl_rights rights;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen int ret = 0;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen iter = acl_object_list_init(aclobj);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen while (acl_object_list_next(iter, &rights)) {
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen if (rights.id_type != ACL_ID_USER &&
5430411539347357344f6bf2552731b62f0a14fdTimo Sirainen rights.id_type != ACL_ID_OWNER &&
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen rights.rights != NULL &&
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen str_array_find(rights.rights, MAIL_ACL_READ)) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen ret = 1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen break;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (acl_object_list_deinit(&iter) < 0) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen *error_r = "Failed to iterate ACL objects";
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return -1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return ret;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen}
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainenstatic int
e106213aebb4170904697814c168548e1ba97de9Timo Sirainenmail_crypt_acl_unset_private_keys(struct mailbox *src_box,
5430411539347357344f6bf2552731b62f0a14fdTimo Sirainen const char *dest_user,
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen enum mail_attribute_type type,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char **error_r)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen{
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen ARRAY_TYPE(const_string) digests;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char *error;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen int ret = 1;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (mailbox_open(src_box) < 0) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen *error_r = t_strdup_printf("mail-crypt-acl-plugin: "
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen "mailbox_open(%s) failed: %s",
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mailbox_get_vname(src_box),
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mailbox_get_last_error(src_box, NULL));
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen return -1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen t_array_init(&digests, 4);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (mail_crypt_box_get_pvt_digests(src_box, pool_datastack_create(),
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen type, &digests, &error) < 0) {
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen *error_r = t_strdup_printf("mail-crypt-acl-plugin: "
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen "Failed to lookup public key digests: %s",
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen error);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mailbox_free(&src_box);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return -1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen struct mailbox_transaction_context *t;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen t = mailbox_transaction_begin(src_box, 0);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char *const *hash;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen array_foreach(&digests, hash) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char *ptr;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* if the id contains username part, skip to key public id */
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen if ((ptr = strchr(*hash, '/')) != NULL)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen ptr++;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen else
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen ptr = *hash;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if ((ret = mail_crypt_box_unset_shared_key(t, ptr, dest_user,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen error_r)) < 0) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen ret = -1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen break;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (ret < 0) {
5430411539347357344f6bf2552731b62f0a14fdTimo Sirainen mailbox_transaction_rollback(&t);
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen } else if (mailbox_transaction_commit(&t) < 0) {
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen *error_r = t_strdup_printf("mail-crypt-acl-plugin: "
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen "mailbox_transaction_commit(%s) failed: %s",
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mailbox_get_vname(src_box),
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen mailbox_get_last_error(src_box, NULL));
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return -1;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen return 0;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen}
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenstatic int
e106213aebb4170904697814c168548e1ba97de9Timo Sirainenmail_crypt_acl_user_create(struct mail_user *user, const char *dest_username,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct mail_user **dest_user_r,
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen struct mail_storage_service_user **dest_service_user_r,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char **error_r)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen{
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const struct mail_storage_service_input *old_input;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct mail_storage_service_input input;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct mail_storage_service_ctx *service_ctx;
5430411539347357344f6bf2552731b62f0a14fdTimo Sirainen struct ioloop_context *cur_ioloop_ctx;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen int ret;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen i_assert(user->_service_user != NULL);
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen service_ctx = mail_storage_service_user_get_service_ctx(user->_service_user);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen old_input = mail_storage_service_user_get_input(user->_service_user);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen if ((cur_ioloop_ctx = io_loop_get_current_context(current_ioloop)) != NULL)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen io_loop_context_deactivate(cur_ioloop_ctx);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen i_zero(&input);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen input.module = old_input->module;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen input.service = old_input->service;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen input.username = dest_username;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen input.session_id_prefix = user->session_id;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen input.flags_override_add = MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS |
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen ret = mail_storage_service_lookup_next(service_ctx, &input,
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen dest_service_user_r,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dest_user_r, error_r);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen return ret;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen}
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenstatic int
e106213aebb4170904697814c168548e1ba97de9Timo Sirainenmail_crypt_acl_update_private_key(struct mailbox *src_box,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct mail_user *dest_user, bool set,
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen bool disallow_insecure,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const char **error_r)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen{
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct dcrypt_public_key *key = NULL;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct dcrypt_private_key **keyp;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen int ret = 0;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen if (!set) {
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen return mail_crypt_acl_unset_private_keys(src_box,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dest_user->username,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen MAIL_ATTRIBUTE_TYPE_SHARED,
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen error_r);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (dest_user != NULL) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* get public key from target user */
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if ((ret = mail_crypt_user_get_public_key(dest_user,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen &key, error_r)) <= 0) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (ret == 0 && disallow_insecure) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen *error_r = t_strdup_printf("User %s has no active public key",
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen dest_user->username);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return -1;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen } else if (ret < 0) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return -1;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen } else if (ret == 0) {
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen /* perform insecure sharing */
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen dest_user = NULL;
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen key = NULL;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen }
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen ARRAY_TYPE(dcrypt_private_key) keys;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen t_array_init(&keys, 8);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct mailbox_transaction_context *t =
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mailbox_transaction_begin(src_box, 0);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen /* get private keys from box */
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (mail_crypt_box_get_private_keys(src_box, &keys, error_r) < 0 ||
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mail_crypt_box_share_private_keys(t, key,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dest_user == NULL ? NULL :
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen dest_user->username,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen &keys, error_r) < 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen ret = -1;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
a8ebb72c0fba1a6a71104e530bf5903d5f149351Timo Sirainen if (ret >= 0) {
a8ebb72c0fba1a6a71104e530bf5903d5f149351Timo Sirainen array_foreach_modifiable(&keys, keyp) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dcrypt_key_unref_private(keyp);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if (mailbox_transaction_commit(&t) < 0) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen *error_r = mailbox_get_last_error(src_box, NULL);
a8ebb72c0fba1a6a71104e530bf5903d5f149351Timo Sirainen ret = -1;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen }
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen return ret;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen}
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainenstatic int mail_crypt_acl_object_update(struct acl_object *aclobj,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen const struct acl_rights_update *update)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen const char *error;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mail_crypt_acl_mailbox_list *mlist =
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen MAIL_CRYPT_ACL_LIST_CONTEXT(aclobj->backend->list);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen const char *username;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mail_user *dest_user;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct mail_storage_service_user *dest_service_user;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen struct ioloop_context *cur_ioloop_ctx;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen bool have_rights;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen int ret = 0;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen if (mlist->acl_vprev.object_update(aclobj, update) < 0)
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen return -1;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen bool disallow_insecure =
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen mail_crypt_acl_secure_sharing_enabled(aclobj->backend->list->ns->user);
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen const char *box_name = mailbox_list_get_vname(aclobj->backend->list,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen aclobj->name);
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen struct mailbox *box = mailbox_alloc(aclobj->backend->list, box_name, 0);
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen switch (update->rights.id_type) {
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen case ACL_ID_USER:
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen /* setting rights for specific user: we can encrypt the
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen mailbox key for the user. */
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen username = update->rights.identifier;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen ret = mail_crypt_acl_has_user_read_right(aclobj, username, &error);
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen if (ret < 0) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen i_error("mail-crypt-acl-plugin: "
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen "mail_crypt_acl_has_user_read_right(%s) failed: %s",
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen username,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen error);
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen break;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen }
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen have_rights = ret > 0;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen ret = mail_crypt_acl_user_create(aclobj->backend->list->ns->user,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen username, &dest_user,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen &dest_service_user, &error);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen /* to make sure we get correct logging context */
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen if (ret > 0)
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen mail_storage_service_io_deactivate_user(dest_service_user);
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen mail_storage_service_io_activate_user(
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen aclobj->backend->list->ns->user->_service_user
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen );
99df8a838cd9c5257ea5a2554383a9a999191e38Pali Rohár
99df8a838cd9c5257ea5a2554383a9a999191e38Pali Rohár if (ret <= 0) {
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen i_error("mail-crypt-acl-plugin: "
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen "Cannot initialize destination user %s: %s",
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen username, error);
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen break;
99df8a838cd9c5257ea5a2554383a9a999191e38Pali Rohár } else {
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen i_assert(dest_user != NULL);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if ((ret = mailbox_open(box)) < 0) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen i_error("mail-crypt-acl-plugin: "
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "mailbox_open(%s) failed: %s",
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_get_vname(box),
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_get_last_error(box, NULL));
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch } else if ((ret = mail_crypt_acl_update_private_key(box, dest_user,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch have_rights,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch disallow_insecure,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch &error)) < 0) {
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch i_error("mail-crypt-acl-plugin: "
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "acl_update_private_key(%s, %s) failed: %s",
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_get_vname(box),
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch username,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch error);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch }
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch }
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch /* logging context swap again */
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mail_storage_service_io_deactivate_user(
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch aclobj->backend->list->ns->user->_service_user
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch );
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mail_storage_service_io_activate_user(dest_service_user);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mail_user_unref(&dest_user);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mail_storage_service_user_unref(&dest_service_user);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch if ((cur_ioloop_ctx = io_loop_get_current_context(current_ioloop)) != NULL)
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch io_loop_context_deactivate(cur_ioloop_ctx);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mail_storage_service_io_activate_user(
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch aclobj->backend->list->ns->user->_service_user
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch );
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch break;
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch case ACL_ID_OWNER:
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch /* we should be the one doing this? ignore */
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch break;
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch case ACL_ID_ANYONE:
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch case ACL_ID_AUTHENTICATED:
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch case ACL_ID_GROUP:
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch case ACL_ID_GROUP_OVERRIDE:
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch if (disallow_insecure) {
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch i_error("mail-crypt-acl-plugin: "
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "Secure key sharing is enabled -"
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "Remove or set plugin { %s = no }",
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch MAIL_CRYPT_ACL_SECURE_SHARE_SETTING);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch ret = -1;
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch break;
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch }
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch /* the mailbox key needs to be stored unencrypted. for groups
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch we could in theory use per-group encrypted keys, which the
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch users belonging to the group would able to decrypt with
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch their private key, but that becomes quite complicated. */
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch if ((ret = mail_crypt_acl_has_nonuser_read_right(aclobj, &error)) < 0) {
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch i_error("mail-crypt-acl-plugin: %s", error);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch } else if ((ret = mailbox_open(box)) < 0) {
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch i_error("mail-crypt-acl-plugin: "
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "mailbox_open(%s) failed: %s",
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_get_vname(box),
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_get_last_error(box, NULL));
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch } else if ((ret = mail_crypt_acl_update_private_key(box,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch NULL,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch TRUE,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch disallow_insecure,
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch &error)) < 0) {
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch i_error("mail-crypt-acl-plugin: "
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "acl_update_private_key(%s, %s) failed: %s",
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_get_vname(box),
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch "",
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch error);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch }
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch break;
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch case ACL_ID_TYPE_COUNT:
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch i_unreached();
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch }
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch mailbox_free(&box);
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch return ret;
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic void
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainenmail_crypt_acl_mail_namespace_storage_added(struct mail_namespace *ns)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
15581297511b658a29c707c6031a258bab7bf1a5Stephan Bosch struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ns->list);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mail_crypt_acl_mailbox_list *mlist =
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen MAIL_CRYPT_ACL_LIST_CONTEXT(ns->list);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct acl_backend *backend;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
if (alist == NULL)
return;
/* FIXME: this method works only if there's a single plugin doing it.
if there are ever multiple plugins hooking into ACL commands the
ACL core code would need some changing to make it work correctly. */
backend = alist->rights.backend;
mlist->acl_vprev = backend->v;
backend->v.object_update = mail_crypt_acl_object_update;
}
static void mail_crypt_acl_mailbox_list_deinit(struct mailbox_list *list)
{
struct mail_crypt_acl_mailbox_list *mlist =
MAIL_CRYPT_ACL_LIST_CONTEXT(list);
mlist->module_ctx.super.deinit(list);
}
static void mail_crypt_acl_mailbox_list_created(struct mailbox_list *list)
{
struct mailbox_list_vfuncs *v = list->vlast;
struct mail_crypt_acl_mailbox_list *mlist;
mlist = p_new(list->pool, struct mail_crypt_acl_mailbox_list, 1);
mlist->module_ctx.super = *v;
list->vlast = &mlist->module_ctx.super;
v->deinit = mail_crypt_acl_mailbox_list_deinit;
MODULE_CONTEXT_SET(list, mail_crypt_acl_mailbox_list_module, mlist);
}
static struct mail_storage_hooks mail_crypt_acl_mail_storage_hooks = {
.mailbox_list_created = mail_crypt_acl_mailbox_list_created,
.mail_namespace_storage_added = mail_crypt_acl_mail_namespace_storage_added
};
void mail_crypt_acl_plugin_init(struct module *module)
{
mail_storage_hooks_add(module, &mail_crypt_acl_mail_storage_hooks);
}
void mail_crypt_acl_plugin_deinit(void)
{
mail_storage_hooks_remove(&mail_crypt_acl_mail_storage_hooks);
}
const char *mail_crypt_acl_plugin_dependencies[] = { "acl", NULL };