AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-dict \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
acl-backend-vfile.c \
acl-backend-vfile-acllist.c \
acl-cache.c \
+ acl-lookup-dict.c \
acl-mailbox.c \
acl-mailbox-list.c \
acl-plugin.c \
+ acl-shared-storage.c \
acl-storage.c
noinst_HEADERS = \
acl-api-private.h \
acl-backend-vfile.h \
acl-cache.h \
+ acl-lookup-dict.h \
acl-plugin.h \
+ acl-shared-storage.h \
acl-storage.h
install-exec-local:
const struct acl_mask *mask, pool_t pool);
int acl_backend_get_default_rights(struct acl_backend *backend,
const struct acl_mask **mask_r);
+void acl_rights_write_id(string_t *dest, const struct acl_rights *right);
bool acl_rights_has_nonowner_lookup_changes(const struct acl_rights *rights);
#endif
/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "str.h"
#include "hash.h"
#include "acl-cache.h"
#include "acl-api-private.h"
ctx->backend->v.nonowner_lookups_iter_deinit(ctx);
}
+void acl_rights_write_id(string_t *dest, const struct acl_rights *right)
+{
+ switch (right->id_type) {
+ case ACL_ID_ANYONE:
+ str_append(dest, ACL_ID_NAME_ANYONE);
+ break;
+ case ACL_ID_AUTHENTICATED:
+ str_append(dest, ACL_ID_NAME_AUTHENTICATED);
+ break;
+ case ACL_ID_OWNER:
+ str_append(dest, ACL_ID_NAME_OWNER);
+ break;
+ case ACL_ID_USER:
+ str_append(dest, ACL_ID_NAME_USER_PREFIX);
+ str_append(dest, right->identifier);
+ break;
+ case ACL_ID_GROUP:
+ str_append(dest, ACL_ID_NAME_GROUP_PREFIX);
+ str_append(dest, right->identifier);
+ break;
+ case ACL_ID_GROUP_OVERRIDE:
+ str_append(dest, ACL_ID_NAME_GROUP_OVERRIDE_PREFIX);
+ str_append(dest, right->identifier);
+ break;
+ case ACL_ID_TYPE_COUNT:
+ i_unreached();
+ }
+}
+
bool acl_rights_has_nonowner_lookup_changes(const struct acl_rights *rights)
{
const char *const *p;
#include "mail-storage.h"
#include "acl-plugin.h"
#include "acl-cache.h"
+#include "acl-lookup-dict.h"
#include "acl-backend-vfile.h"
#include <stdio.h>
}
}
if (ret == 0) {
+ struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
+
backend->acllist_mtime = st.st_mtime;
backend->acllist_last_check = ioloop_time;
+ /* FIXME: dict reubild is expensive, try to avoid it */
+ (void)acl_lookup_dict_rebuild(auser->acl_lookup_dict);
} else {
acllist_clear(backend, 0);
if (unlink(str_c(path)) < 0 && errno != ENOENT)
const char *const *rights = neg ? right->neg_rights : right->rights;
if (neg) str_append_c(dest,'-');
-
- switch (right->id_type) {
- case ACL_ID_ANYONE:
- str_append(dest, ACL_ID_NAME_ANYONE);
- break;
- case ACL_ID_AUTHENTICATED:
- str_append(dest, ACL_ID_NAME_AUTHENTICATED);
- break;
- case ACL_ID_OWNER:
- str_append(dest, ACL_ID_NAME_OWNER);
- break;
- case ACL_ID_USER:
- str_append(dest, ACL_ID_NAME_USER_PREFIX);
- str_append(dest, right->identifier);
- break;
- case ACL_ID_GROUP:
- str_append(dest, ACL_ID_NAME_GROUP_PREFIX);
- str_append(dest, right->identifier);
- break;
- case ACL_ID_GROUP_OVERRIDE:
- str_append(dest, ACL_ID_NAME_GROUP_OVERRIDE_PREFIX);
- str_append(dest, right->identifier);
- break;
- case ACL_ID_TYPE_COUNT:
- i_unreached();
- }
+ acl_rights_write_id(dest, right);
str_append_c(dest, ' ');
vfile_write_rights_list(dest, rights);
str_append_c(dest, '\n');
--- /dev/null
+/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+#include "dict.h"
+#include "mail-user.h"
+#include "mail-namespace.h"
+#include "acl-api-private.h"
+#include "acl-storage.h"
+#include "acl-plugin.h"
+#include "acl-lookup-dict.h"
+
+#include <stdlib.h>
+
+#define DICT_SHARED_BOXES_PATH "shared-boxes/"
+
+struct acl_lookup_dict {
+ struct mail_user *user;
+};
+
+struct acl_lookup_dict_iter {
+ pool_t pool;
+ struct acl_lookup_dict *dict;
+
+ ARRAY_TYPE(const_string) iter_ids;
+ struct dict_iterate_context *dict_iter;
+ unsigned int iter_idx;
+
+ const char *prefix;
+ unsigned int prefix_len;
+
+ unsigned int failed:1;
+};
+
+static struct dict *acl_dict;
+
+void acl_lookup_dicts_init(void)
+{
+ const char *uri;
+
+ uri = getenv("ACL_SHARED_DICT");
+ if (uri == NULL) {
+ if (getenv("DEBUG") != NULL) {
+ i_info("acl: No acl_shared_dict setting - "
+ "shared mailbox listing is disabled");
+ }
+ return;
+ }
+
+ acl_dict = dict_init(uri, DICT_DATA_TYPE_STRING, "");
+ if (acl_dict == NULL)
+ i_fatal("acl: dict_init(%s) failed", uri);
+}
+
+void acl_lookup_dicts_deinit(void)
+{
+ if (acl_dict != NULL)
+ dict_deinit(&acl_dict);
+}
+
+struct acl_lookup_dict *acl_lookup_dict_init(struct mail_user *user)
+{
+ struct acl_lookup_dict *dict;
+
+ dict = i_new(struct acl_lookup_dict, 1);
+ dict->user = user;
+ return dict;
+}
+
+void acl_lookup_dict_deinit(struct acl_lookup_dict **_dict)
+{
+ struct acl_lookup_dict *dict = *_dict;
+
+ *_dict = NULL;
+ i_free(dict);
+}
+
+static void
+acl_lookup_dict_write_rights_id(string_t *dest, const struct acl_rights *right)
+{
+ switch (right->id_type) {
+ case ACL_ID_ANYONE:
+ case ACL_ID_AUTHENTICATED:
+ /* don't bother separating these */
+ str_append(dest, "anyone");
+ break;
+ case ACL_ID_USER:
+ str_append(dest, "user/");
+ str_append(dest, right->identifier);
+ break;
+ case ACL_ID_GROUP:
+ case ACL_ID_GROUP_OVERRIDE:
+ str_append(dest, "group/");
+ str_append(dest, right->identifier);
+ break;
+ case ACL_ID_OWNER:
+ case ACL_ID_TYPE_COUNT:
+ i_unreached();
+ }
+}
+
+static int acl_lookup_dict_rebuild_add_backend(struct mail_namespace *ns,
+ ARRAY_TYPE(const_string) *ids)
+{
+ struct acl_backend *backend;
+ struct acl_mailbox_list_context *ctx;
+ struct acl_object *aclobj;
+ struct acl_object_list_iter *iter;
+ struct acl_rights rights;
+ const char *name, *id_dup;
+ string_t *id;
+ int ret, ret2 = 0;
+
+ id = t_str_new(128);
+ backend = acl_storage_get_backend(ns->storage);
+ ctx = acl_backend_nonowner_lookups_iter_init(backend);
+ while ((ret = acl_backend_nonowner_lookups_iter_next(ctx, &name)) > 0) {
+ aclobj = acl_object_init_from_name(backend, ns->storage, name);
+
+ iter = acl_object_list_init(aclobj);
+ while ((ret = acl_object_list_next(iter, &rights)) > 0) {
+ if (acl_rights_has_nonowner_lookup_changes(&rights)) {
+ str_truncate(id, 0);
+ acl_lookup_dict_write_rights_id(id, &rights);
+ id_dup = t_strdup(str_c(id));
+ array_append(ids, &id_dup, 1);
+ }
+ }
+ acl_object_list_deinit(&iter);
+ if (ret < 0)
+ ret2 = -1;
+ acl_object_deinit(&aclobj);
+ }
+ acl_backend_nonowner_lookups_iter_deinit(&ctx);
+ return ret < 0 || ret2 < 0 ? -1 : 0;
+}
+
+static int
+acl_lookup_dict_rebuild_update(struct acl_lookup_dict *dict,
+ const ARRAY_TYPE(const_string) *new_ids_arr,
+ bool no_removes)
+{
+ const char *username = dict->user->username;
+ struct dict_iterate_context *iter;
+ struct dict_transaction_context *dt;
+ const char *prefix, *key, *value, **old_ids, *const *new_ids, *p;
+ ARRAY_TYPE(const_string) old_ids_arr;
+ unsigned int newi, oldi, old_count, new_count;
+ string_t *path;
+ unsigned int prefix_len;
+ int ret;
+
+ /* get all existing identifiers for the user */
+ t_array_init(&old_ids_arr, 128);
+ prefix = DICT_PATH_SHARED DICT_SHARED_BOXES_PATH;
+ prefix_len = strlen(prefix);
+ iter = dict_iterate_init(acl_dict, prefix, DICT_ITERATE_FLAG_RECURSE);
+ while ((ret = dict_iterate(iter, &key, &value)) > 0) {
+ /* prefix/$dest/$source */
+ key += prefix_len;
+ p = strchr(key, '/');
+ if (p != NULL && strcmp(p + 1, username) == 0) {
+ key = t_strdup_until(key, p);
+ array_append(&old_ids_arr, &key, 1);
+ }
+ }
+ dict_iterate_deinit(&iter);
+ if (ret < 0) {
+ i_error("acl: dict iteration failed, can't update dict");
+ return -1;
+ }
+
+ /* sort the existing identifiers */
+ old_ids = array_get_modifiable(&old_ids_arr, &old_count);
+ qsort(old_ids, old_count, sizeof(*old_ids), i_strcmp_p);
+
+ /* sync the identifiers */
+ path = t_str_new(256);
+ str_append(path, prefix);
+
+ dt = dict_transaction_begin(acl_dict);
+ new_ids = array_get(new_ids_arr, &new_count);
+ for (newi = oldi = 0; newi < new_count || oldi < old_count; ) {
+ ret = newi == new_count ? 1 :
+ oldi == old_count ? -1 :
+ strcmp(new_ids[newi], old_ids[oldi]);
+ if (ret == 0) {
+ newi++; oldi++;
+ } else if (ret < 0) {
+ /* new identifier, add it */
+ str_truncate(path, prefix_len);
+ str_append(path, new_ids[newi]);
+ str_append_c(path, '/');
+ str_append(path, username);
+ dict_set(dt, str_c(path), "1");
+ newi++;
+ } else if (!no_removes) {
+ /* old identifier removed */
+ str_truncate(path, prefix_len);
+ str_append(path, old_ids[oldi]);
+ str_append_c(path, '/');
+ str_append(path, username);
+ dict_unset(dt, str_c(path));
+ oldi++;
+ }
+ }
+ if (dict_transaction_commit(&dt) < 0) {
+ i_error("acl: dict commit failed");
+ return -1;
+ }
+ return 0;
+}
+
+int acl_lookup_dict_rebuild(struct acl_lookup_dict *dict)
+{
+ struct mail_namespace *ns;
+ ARRAY_TYPE(const_string) ids_arr;
+ const char **ids;
+ unsigned int i, dest, count;
+ int ret = 0;
+
+ /* get all ACL identifiers with a positive lookup right */
+ t_array_init(&ids_arr, 128);
+ for (ns = dict->user->namespaces; ns != NULL; ns = ns->next) {
+ if (acl_lookup_dict_rebuild_add_backend(ns, &ids_arr) < 0)
+ ret = -1;
+ }
+
+ /* sort identifiers and remove duplicates */
+ ids = array_get_modifiable(&ids_arr, &count);
+ qsort(ids, count, sizeof(*ids), i_strcmp_p);
+
+ for (i = 1, dest = 0; i < count; i++) {
+ if (strcmp(ids[dest], ids[i]) != 0) {
+ if (++dest != i)
+ ids[dest] = ids[i];
+ }
+ }
+ if (++dest < count)
+ array_delete(&ids_arr, dest, count-dest);
+
+ /* if lookup failed at some point we can still add new ids,
+ but we can't remove any existing ones */
+ if (acl_lookup_dict_rebuild_update(dict, &ids_arr, ret < 0) < 0)
+ ret = -1;
+ return ret;
+}
+
+static void acl_lookup_dict_iterate_start(struct acl_lookup_dict_iter *iter)
+{
+ const char *const *idp;
+
+ idp = array_idx(&iter->iter_ids, iter->iter_idx);
+ iter->iter_idx++;
+ iter->prefix = p_strconcat(iter->pool, DICT_PATH_SHARED
+ DICT_SHARED_BOXES_PATH, *idp, "/", NULL);
+ iter->prefix_len = strlen(iter->prefix);
+
+ iter->dict_iter = dict_iterate_init(acl_dict, iter->prefix,
+ DICT_ITERATE_FLAG_RECURSE);
+}
+
+struct acl_lookup_dict_iter *
+acl_lookup_dict_iterate_visible_init(struct acl_lookup_dict *dict)
+{
+ struct acl_user *auser = ACL_USER_CONTEXT(dict->user);
+ struct acl_lookup_dict_iter *iter;
+ const char *id;
+ unsigned int i;
+ pool_t pool;
+
+ pool = pool_alloconly_create("acl lookup dict iter", 512);
+ iter = p_new(pool, struct acl_lookup_dict_iter, 1);
+ iter->pool = pool;
+ iter->dict = dict;
+
+ p_array_init(&iter->iter_ids, pool, 16);
+ id = "anyone";
+ array_append(&iter->iter_ids, &id, 1);
+ id = p_strconcat(pool, "user/", dict->user->username, NULL);
+ array_append(&iter->iter_ids, &id, 1);
+
+ /* get all groups we belong to */
+ if (auser->groups != NULL) {
+ for (i = 0; auser->groups[i] != NULL; i++) {
+ id = p_strconcat(pool, "group/", auser->groups[i],
+ NULL);
+ array_append(&iter->iter_ids, &id, 1);
+ }
+ }
+
+ /* iterate through all identifiers that match us, start with the
+ first one */
+ acl_lookup_dict_iterate_start(iter);
+ return iter;
+}
+
+const char *
+acl_lookup_dict_iterate_visible_next(struct acl_lookup_dict_iter *iter)
+{
+ const char *key, *value;
+ int ret;
+
+ ret = dict_iterate(iter->dict_iter, &key, &value);
+ if (ret > 0) {
+ i_assert(iter->prefix_len < strlen(key));
+ return key + iter->prefix_len;
+ }
+ if (ret < 0)
+ iter->failed = TRUE;
+ dict_iterate_deinit(&iter->dict_iter);
+
+ if (iter->iter_idx < array_count(&iter->iter_ids)) {
+ /* get to the next iterator */
+ acl_lookup_dict_iterate_start(iter);
+ return acl_lookup_dict_iterate_visible_next(iter);
+ }
+ return NULL;
+}
+
+int acl_lookup_dict_iterate_visible_deinit(struct acl_lookup_dict_iter **_iter)
+{
+ struct acl_lookup_dict_iter *iter = *_iter;
+ int ret = iter->failed ? -1 : 0;
+
+ *_iter = NULL;
+ if (iter->dict_iter != NULL)
+ dict_iterate_deinit(&iter->dict_iter);
+ pool_unref(&iter->pool);
+ return ret;
+}
--- /dev/null
+#ifndef ACL_LOOKUP_DICT_H
+#define ACL_LOOKUP_DICT_H
+
+void acl_lookup_dicts_init(void);
+void acl_lookup_dicts_deinit(void);
+
+struct acl_lookup_dict *acl_lookup_dict_init(struct mail_user *user);
+void acl_lookup_dict_deinit(struct acl_lookup_dict **dict);
+
+int acl_lookup_dict_rebuild(struct acl_lookup_dict *dict);
+
+struct acl_lookup_dict_iter *
+acl_lookup_dict_iterate_visible_init(struct acl_lookup_dict *dict);
+const char *
+acl_lookup_dict_iterate_visible_next(struct acl_lookup_dict_iter *iter);
+int acl_lookup_dict_iterate_visible_deinit(struct acl_lookup_dict_iter **iter);
+
+#endif
#include "mailbox-tree.h"
#include "mail-namespace.h"
#include "mailbox-list-private.h"
-#include "acl-cache.h"
#include "acl-api-private.h"
+#include "acl-cache.h"
+#include "acl-shared-storage.h"
#include "acl-plugin.h"
-#include <stdlib.h>
-
#define ACL_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, acl_mailbox_list_module)
ctx->ctx.list = list;
ctx->ctx.flags = flags;
+ if (list->ns->type == NAMESPACE_SHARED &&
+ (list->ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
+ /* before listing anything add namespaces for all users
+ who may have visible mailboxes */
+ if (acl_shared_namespaces_add(list->ns) < 0)
+ ctx->ctx.failed = TRUE;
+ }
+
T_BEGIN {
acl_mailbox_try_list_fast(ctx, patterns);
} T_END;
void acl_mailbox_list_created(struct mailbox_list *list)
{
+ struct acl_user *auser = ACL_USER_CONTEXT(list->ns->user);
struct acl_mailbox_list *alist;
struct acl_backend *backend;
struct mail_namespace *ns;
enum mailbox_list_flags flags;
- const char *acl_env, *current_username, *owner_username;
+ const char *current_username, *owner_username;
bool owner = TRUE;
if ((list->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0) {
return;
}
- acl_env = getenv("ACL");
- i_assert(acl_env != NULL);
-
owner_username = list->ns->user->username;
- current_username = getenv("MASTER_USER");
+ current_username = auser->master_user;
if (current_username == NULL)
current_username = owner_username;
else
if (ns->type != NAMESPACE_PRIVATE)
owner = FALSE;
- backend = acl_backend_init(acl_env, list, current_username,
- getenv("ACL_GROUPS") == NULL ? NULL :
- t_strsplit(getenv("ACL_GROUPS"), ","),
- owner);
+ backend = acl_backend_init(auser->acl_env, list, current_username,
+ auser->groups, owner);
if (backend == NULL)
i_fatal("ACL backend initialization failed");
static MODULE_CONTEXT_DEFINE_INIT(acl_mail_module, &mail_module_register);
static struct acl_transaction_context acl_transaction_failure;
+struct acl_backend *acl_storage_get_backend(struct mail_storage *storage)
+{
+ struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
+
+ return astorage->rights.backend;
+}
+
struct acl_object *acl_storage_get_default_aclobj(struct mail_storage *storage)
{
struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
#include "lib.h"
#include "mailbox-list-private.h"
#include "acl-api.h"
+#include "acl-lookup-dict.h"
#include "acl-plugin.h"
#include <stdlib.h>
void (*acl_next_hook_mail_storage_created)(struct mail_storage *storage);
void (*acl_next_hook_mailbox_list_created)(struct mailbox_list *list);
+void (*acl_next_hook_mail_user_created)(struct mail_user *user);
const char *acl_plugin_version = PACKAGE_VERSION;
acl_next_hook_mailbox_list_created = hook_mailbox_list_created;
hook_mailbox_list_created = acl_mailbox_list_created;
+
+ acl_next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = acl_mail_user_created;
+
+ acl_lookup_dicts_init();
} else {
if (getenv("DEBUG") != NULL)
i_info("acl: No acl setting - ACLs are disabled");
void acl_plugin_deinit(void)
{
if (acl_next_hook_mail_storage_created != NULL) {
- hook_mail_storage_created =
- acl_next_hook_mail_storage_created;
- hook_mailbox_list_created =
- acl_next_hook_mailbox_list_created;
+ acl_lookup_dicts_deinit();
+ hook_mail_storage_created = acl_next_hook_mail_storage_created;
+ hook_mailbox_list_created = acl_next_hook_mailbox_list_created;
+ hook_mail_user_created = acl_next_hook_mail_user_created;
}
}
#ifndef ACL_PLUGIN_H
#define ACL_PLUGIN_H
+#include "mail-user.h"
#include "mail-storage-private.h"
#include "acl-storage.h"
#define ACL_CONTEXT(obj) \
MODULE_CONTEXT(obj, acl_storage_module)
+#define ACL_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, acl_user_module)
+
+struct acl_user {
+ union mail_user_module_context module_ctx;
+
+ const char *master_user;
+ const char *acl_env;
+ const char *const *groups;
+
+ struct acl_lookup_dict *acl_lookup_dict;
+ time_t last_shared_add_check;
+};
struct acl_storage_rights_context {
struct acl_backend *backend;
struct acl_storage_rights_context rights;
};
-extern void (*acl_next_hook_mail_storage_created)
- (struct mail_storage *storage);
+extern void (*acl_next_hook_mail_storage_created)(struct mail_storage *storage);
extern void (*acl_next_hook_mailbox_list_created)(struct mailbox_list *list);
+extern void (*acl_next_hook_mail_user_created)(struct mail_user *user);
extern MODULE_CONTEXT_DEFINE(acl_storage_module, &mail_storage_module_register);
+extern MODULE_CONTEXT_DEFINE(acl_user_module, &mail_user_module_register);
void acl_mail_storage_created(struct mail_storage *storage);
void acl_mailbox_list_created(struct mailbox_list *list);
+void acl_mail_user_created(struct mail_user *list);
struct mailbox *acl_mailbox_open_box(struct mailbox *box);
--- /dev/null
+/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "ioloop.h"
+#include "str.h"
+#include "var-expand.h"
+#include "acl-plugin.h"
+#include "acl-lookup-dict.h"
+#include "acl-shared-storage.h"
+#include "index/shared/shared-storage.h"
+
+#define SHARED_NS_RETRY_SECS (60*60)
+
+static void
+acl_shared_namespace_add(struct mail_user *user,
+ struct shared_storage *sstorage,
+ const char *userdomain)
+{
+ static struct var_expand_table static_tab[] = {
+ { 'u', NULL },
+ { 'n', NULL },
+ { 'd', NULL },
+ { '\0', NULL }
+ };
+ struct var_expand_table *tab;
+ struct mail_namespace *ns;
+ const char *p, *mailbox;
+ string_t *str;
+
+ if (strcmp(user->username, userdomain) == 0) {
+ /* skip ourself */
+ return;
+ }
+
+ p = strchr(userdomain, '@');
+
+ tab = t_malloc(sizeof(static_tab));
+ memcpy(tab, static_tab, sizeof(static_tab));
+ tab[0].value = userdomain;
+ tab[1].value = p == NULL ? userdomain : t_strdup_until(userdomain, p);
+ tab[2].value = p == NULL ? "" : p + 1;
+
+ str = t_str_new(128);
+ var_expand(str, sstorage->ns_prefix_pattern, tab);
+ mailbox = str_c(str);
+ shared_storage_get_namespace(&sstorage->storage, &mailbox, &ns);
+}
+
+int acl_shared_namespaces_add(struct mail_namespace *ns)
+{
+ struct shared_storage *sstorage = (struct shared_storage *)ns->storage;
+ struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
+ struct acl_lookup_dict_iter *iter;
+ const char *name;
+
+ i_assert(ns->type == NAMESPACE_SHARED);
+ i_assert(strcmp(ns->storage->name, SHARED_STORAGE_NAME) == 0);
+
+ if (ioloop_time < auser->last_shared_add_check + SHARED_NS_RETRY_SECS) {
+ /* already added, don't bother rechecking */
+ return 0;
+ }
+ auser->last_shared_add_check = ioloop_time;
+
+ iter = acl_lookup_dict_iterate_visible_init(auser->acl_lookup_dict);
+ while ((name = acl_lookup_dict_iterate_visible_next(iter)) != NULL) {
+ T_BEGIN {
+ acl_shared_namespace_add(ns->user, sstorage, name);
+ } T_END;
+ }
+ return acl_lookup_dict_iterate_visible_deinit(&iter);
+}
--- /dev/null
+#ifndef ACL_SHARED_STORAGE_H
+#define ACL_SHARED_STORAGE_H
+
+int acl_shared_namespaces_add(struct mail_namespace *ns);
+
+#endif
#include "mail-namespace.h"
#include "mailbox-list-private.h"
#include "acl-api-private.h"
+#include "acl-lookup-dict.h"
#include "acl-plugin.h"
+#include <stdlib.h>
+
struct acl_storage_module acl_storage_module =
MODULE_CONTEXT_INIT(&mail_storage_module_register);
+struct acl_user_module acl_user_module =
+ MODULE_CONTEXT_INIT(&mail_user_module_register);
static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = {
MAIL_ACL_LOOKUP,
acl_next_hook_mail_storage_created(storage);
}
+static void acl_user_deinit(struct mail_user *user)
+{
+ struct acl_user *auser = ACL_USER_CONTEXT(user);
+
+ acl_lookup_dict_deinit(&auser->acl_lookup_dict);
+ auser->module_ctx.super.deinit(user);
+}
+
+void acl_mail_user_created(struct mail_user *user)
+{
+ struct acl_user *auser;
+ const char *env;
+
+ auser = p_new(user->pool, struct acl_user, 1);
+ auser->module_ctx.super = user->v;
+ user->v.deinit = acl_user_deinit;
+ auser->acl_lookup_dict = acl_lookup_dict_init(user);
+
+ auser->acl_env = getenv("ACL");
+ i_assert(auser->acl_env != NULL);
+ auser->master_user = getenv("MASTER_USER");
+
+ env = getenv("ACL_GROUPS");
+ if (env != NULL) {
+ auser->groups =
+ (const char *const *)p_strsplit(user->pool, env, ",");
+ }
+
+ MODULE_CONTEXT_SET(user, acl_user_module, auser);
+
+ if (acl_next_hook_mail_user_created != NULL)
+ acl_next_hook_mail_user_created(user);
+}
+
ACL_STORAGE_RIGHT_COUNT
};
+/* Returns acl_backend for the given mail storage. */
+struct acl_backend *acl_storage_get_backend(struct mail_storage *storage);
/* Returns default acl_object for the given mail storage. */
struct acl_object *acl_storage_get_default_aclobj(struct mail_storage *storage);
/* Returns acl_object for the given mailbox. */