Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8433:dfe39e9a9e78 HEAD
Initial support for LISTing users with shared mailboxes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 16 Nov 2008 19:20:28 +0200 |
parents | 8f083c8482e1 |
children | fa755adddb11 |
files | src/plugins/acl/Makefile.am src/plugins/acl/acl-api-private.h src/plugins/acl/acl-api.c src/plugins/acl/acl-backend-vfile-acllist.c src/plugins/acl/acl-backend-vfile.c src/plugins/acl/acl-lookup-dict.c src/plugins/acl/acl-lookup-dict.h src/plugins/acl/acl-mailbox-list.c src/plugins/acl/acl-mailbox.c src/plugins/acl/acl-plugin.c src/plugins/acl/acl-plugin.h src/plugins/acl/acl-shared-storage.c src/plugins/acl/acl-shared-storage.h src/plugins/acl/acl-storage.c src/plugins/acl/acl-storage.h |
diffstat | 15 files changed, 563 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/acl/Makefile.am Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/Makefile.am Sun Nov 16 19:20:28 2008 +0200 @@ -1,5 +1,6 @@ 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 \ @@ -16,9 +17,11 @@ 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 = \ @@ -26,7 +29,9 @@ 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:
--- a/src/plugins/acl/acl-api-private.h Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-api-private.h Sun Nov 16 19:20:28 2008 +0200 @@ -82,6 +82,7 @@ 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
--- a/src/plugins/acl/acl-api.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-api.c Sun Nov 16 19:20:28 2008 +0200 @@ -1,6 +1,7 @@ /* 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" @@ -172,6 +173,35 @@ 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;
--- a/src/plugins/acl/acl-backend-vfile-acllist.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-backend-vfile-acllist.c Sun Nov 16 19:20:28 2008 +0200 @@ -10,6 +10,7 @@ #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> @@ -241,8 +242,12 @@ } } 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)
--- a/src/plugins/acl/acl-backend-vfile.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-backend-vfile.c Sun Nov 16 19:20:28 2008 +0200 @@ -999,32 +999,7 @@ 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 Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/acl/acl-lookup-dict.c Sun Nov 16 19:20:28 2008 +0200 @@ -0,0 +1,332 @@ +/* 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 Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/acl/acl-lookup-dict.h Sun Nov 16 19:20:28 2008 +0200 @@ -0,0 +1,18 @@ +#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
--- a/src/plugins/acl/acl-mailbox-list.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-mailbox-list.c Sun Nov 16 19:20:28 2008 +0200 @@ -7,12 +7,11 @@ #include "mailbox-tree.h" #include "mail-namespace.h" #include "mailbox-list-private.h" +#include "acl-api-private.h" #include "acl-cache.h" -#include "acl-api-private.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) @@ -134,6 +133,14 @@ 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; @@ -394,11 +401,12 @@ 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) { @@ -406,11 +414,8 @@ 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 @@ -423,10 +428,8 @@ 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");
--- a/src/plugins/acl/acl-mailbox.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-mailbox.c Sun Nov 16 19:20:28 2008 +0200 @@ -30,6 +30,13 @@ 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);
--- a/src/plugins/acl/acl-plugin.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-plugin.c Sun Nov 16 19:20:28 2008 +0200 @@ -3,12 +3,14 @@ #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; @@ -21,6 +23,11 @@ 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"); @@ -30,9 +37,9 @@ 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; } }
--- a/src/plugins/acl/acl-plugin.h Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-plugin.h Sun Nov 16 19:20:28 2008 +0200 @@ -1,11 +1,25 @@ #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; @@ -17,13 +31,15 @@ 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 Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/acl/acl-shared-storage.c Sun Nov 16 19:20:28 2008 +0200 @@ -0,0 +1,73 @@ +/* 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 Thu Jan 01 00:00:00 1970 +0000 +++ b/src/plugins/acl/acl-shared-storage.h Sun Nov 16 19:20:28 2008 +0200 @@ -0,0 +1,6 @@ +#ifndef ACL_SHARED_STORAGE_H +#define ACL_SHARED_STORAGE_H + +int acl_shared_namespaces_add(struct mail_namespace *ns); + +#endif
--- a/src/plugins/acl/acl-storage.c Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-storage.c Sun Nov 16 19:20:28 2008 +0200 @@ -6,10 +6,15 @@ #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, @@ -187,3 +192,37 @@ 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); +} +
--- a/src/plugins/acl/acl-storage.h Sun Nov 16 19:19:26 2008 +0200 +++ b/src/plugins/acl/acl-storage.h Sun Nov 16 19:20:28 2008 +0200 @@ -17,6 +17,8 @@ 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. */