acl-mailbox-list.c revision a8de8d06e459b4725cc4d1637a2baf00cab73924
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen#include "lib.h"
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen#include "array.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "str.h"
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen#include "imap-match.h"
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen#include "mailbox-tree.h"
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen#include "mail-namespace.h"
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen#include "mailbox-list-private.h"
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen#include "acl-api-private.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "acl-cache.h"
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen#include "acl-shared-storage.h"
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen#include "acl-plugin.h"
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
2caa8fdbada1a0804fa978bdffb27c89e452933eTimo Sirainen#define ACL_LIST_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, acl_mailbox_list_module)
2caa8fdbada1a0804fa978bdffb27c89e452933eTimo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen#define MAILBOX_FLAG_MATCHED 0x40000000
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainenstruct acl_mailbox_list {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_list_module_context module_ctx;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen struct acl_storage_rights_context rights;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen};
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenstruct acl_mailbox_list_iterate_context {
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct mailbox_list_iterate_context ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct mailbox_list_iterate_context *super_ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen struct mailbox_tree_context *lookup_boxes;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct mailbox_info info;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen struct imap_match_glob *glob;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen char sep;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen unsigned int simple_star_glob:1;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen};
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(acl_mailbox_list_module,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen &mailbox_list_module_register);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainenstruct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen{
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen return alist->rights.backend;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen}
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainenstatic int
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainenacl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen unsigned int acl_storage_right_idx, bool *can_see_r)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen{
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen int ret;
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_storage_rights_ctx_have_right(&alist->rights, name, FALSE,
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen acl_storage_right_idx,
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen can_see_r);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen if (ret < 0)
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen mailbox_list_set_internal_error(list);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen return ret;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen}
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainenstatic void
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainenacl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen{
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_backend *backend = alist->rights.backend;
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen const unsigned int *idxp;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen const struct acl_mask *acl_mask;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list_context *nonowner_list_ctx;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen struct mail_namespace *ns = ctx->ctx.list->ns;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen struct mailbox_list_iter_update_context update_ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen const char *name;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen string_t *vname = NULL;
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen int ret;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_RAW_LIST |
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen MAILBOX_LIST_ITER_SELECT_SUBSCRIBED)) != 0)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen /* if this namespace's default rights contain LOOKUP, we'll need to
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen go through all mailboxes in any case. */
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen idxp = alist->rights.acl_storage_right_idx + ACL_STORAGE_RIGHT_LOOKUP;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen if (acl_backend_get_default_rights(backend, &acl_mask) < 0 ||
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen acl_cache_mask_isset(acl_mask, *idxp))
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen /* no LOOKUP right by default, we can optimize this */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if ((ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen vname = t_str_new(256);
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen memset(&update_ctx, 0, sizeof(update_ctx));
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen update_ctx.iter_ctx = &ctx->ctx;
44fda09101a94883f45b8a6214628e541550cebcTimo Sirainen update_ctx.glob =
44fda09101a94883f45b8a6214628e541550cebcTimo Sirainen imap_match_init(pool_datastack_create(), "*",
44fda09101a94883f45b8a6214628e541550cebcTimo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX) != 0,
44fda09101a94883f45b8a6214628e541550cebcTimo Sirainen ctx->sep);
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen update_ctx.match_parents = TRUE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen update_ctx.tree_ctx = mailbox_tree_init(ctx->sep);
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen nonowner_list_ctx = acl_backend_nonowner_lookups_iter_init(backend);
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen while ((ret = acl_backend_nonowner_lookups_iter_next(nonowner_list_ctx,
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen &name)) > 0) {
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen if (vname != NULL)
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen name = mail_namespace_get_vname(ns, vname, name);
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen mailbox_list_iter_update(&update_ctx, name);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen }
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx);
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen if (ret == 0)
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen ctx->lookup_boxes = update_ctx.tree_ctx;
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen else
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen mailbox_tree_deinit(&update_ctx.tree_ctx);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenstatic struct mailbox_list_iterate_context *
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenacl_mailbox_list_iter_init(struct mailbox_list *list,
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen const char *const *patterns,
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen enum mailbox_list_iter_flags flags)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen{
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list_iterate_context *ctx;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen const char *p;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen unsigned int i;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen bool inboxcase;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen ctx = i_new(struct acl_mailbox_list_iterate_context, 1);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen ctx->ctx.list = list;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen ctx->ctx.flags = flags;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen inboxcase = (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen ctx->sep = (ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0 ?
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen list->ns->sep : list->ns->real_sep;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen ctx->glob = imap_match_init_multiple(default_pool, patterns,
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen inboxcase, ctx->sep);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* see if all patterns have only a single '*' and it's at the end.
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen we can use it to do some optimizations. */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen ctx->simple_star_glob = TRUE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen for (i = 0; patterns[i] != NULL; i++) {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen p = strchr(patterns[i], '*');
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if (p == NULL || p[1] != '\0') {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen ctx->simple_star_glob = FALSE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen break;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (list->ns->type == NAMESPACE_SHARED &&
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen (list->ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen /* before listing anything add namespaces for all users
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen who may have visible mailboxes */
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen if (acl_shared_namespaces_add(list->ns) < 0)
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen ctx->ctx.failed = TRUE;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen }
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen /* Try to avoid reading ACLs from all mailboxes by getting a smaller
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen list of mailboxes that have even potential to be visible. If we
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen couldn't get such a list, we'll go through all mailboxes. */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen acl_mailbox_try_list_fast(ctx);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen ctx->super_ctx = alist->module_ctx.super.
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen iter_init(list, patterns, flags);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen return &ctx->ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
61e84692827b6a64912343f515c984853021483aTimo Sirainenstatic const struct mailbox_info *
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainenacl_mailbox_list_iter_next_info(struct acl_mailbox_list_iterate_context *ctx)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen{
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen const struct mailbox_info *info;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen do {
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen info = alist->module_ctx.super.iter_next(ctx->super_ctx);
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen if (info == NULL)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return NULL;
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen /* if we've a list of mailboxes with LOOKUP rights, skip the
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen mailboxes not in the list (since we know they can't be
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen visible to us). */
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen } while (ctx->lookup_boxes != NULL &&
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen mailbox_tree_lookup(ctx->lookup_boxes, info->name) == NULL);
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return info;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen}
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainenstatic const char *
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainenacl_mailbox_list_iter_get_name(struct mailbox_list_iterate_context *ctx,
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen const char *name)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen{
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen struct mail_namespace *ns = ctx->list->ns;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen if ((ctx->flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) == 0)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return name;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen /* Mailbox names contain namespace prefix,
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen except when listing INBOX. */
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen if (strncmp(name, ns->prefix, ns->prefix_len) == 0)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen name += ns->prefix_len;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return mail_namespace_fix_sep(ns, name);
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen}
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainenstatic bool
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Siraineniter_is_listing_all_children(struct acl_mailbox_list_iterate_context *ctx)
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen{
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen const char *child;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* If all patterns (with '.' separator) are in "name*", "name.*" or
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen "%.*" style format, simple_star_glob=TRUE and we can easily test
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen this by simply checking if name/child mailbox matches. */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen child = t_strdup_printf("%s%cx", ctx->info.name, ctx->sep);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen return ctx->simple_star_glob &&
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen imap_match(ctx->glob, child) == IMAP_MATCH_YES;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen}
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainenstatic bool
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Siraineniter_mailbox_has_visible_children(struct acl_mailbox_list_iterate_context *ctx)
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen{
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen struct mailbox_list_iterate_context *iter;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen const struct mailbox_info *info;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen enum mailbox_list_iter_flags flags;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen string_t *pattern;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen const char *prefix;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen unsigned int i, prefix_len;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen bool stars = FALSE, ret = FALSE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* do we have child mailboxes with LOOKUP right that don't match
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen the list pattern? */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if (ctx->lookup_boxes != NULL) {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* we have a list of mailboxes with LOOKUP rights. before
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen starting the slow list iteration, check check first
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if there even are any children with LOOKUP rights. */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen struct mailbox_node *node;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen node = mailbox_tree_lookup(ctx->lookup_boxes, ctx->info.name);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen i_assert(node != NULL);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if (node->children == NULL)
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen return FALSE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen /* if mailbox name has '*' characters in it, they'll conflict with the
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen LIST wildcard. replace then with '%' and verify later that all
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen results have the correct prefix. */
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen pattern = t_str_new(128);
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen for (i = 0; ctx->info.name[i] != '\0'; i++) {
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen if (ctx->info.name[i] != '*')
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen str_append_c(pattern, ctx->info.name[i]);
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen else {
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen stars = TRUE;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen str_append_c(pattern, '%');
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen }
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen }
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen str_append_c(pattern, ctx->sep);
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen str_append_c(pattern, '*');
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen prefix = str_c(pattern);
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen prefix_len = str_len(pattern) - 1;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen flags = (ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) |
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen iter = mailbox_list_iter_init(ctx->ctx.list, str_c(pattern), flags);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if (imap_match(ctx->glob, info->name) == IMAP_MATCH_YES) {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* at least one child matches also the original list
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen patterns. we don't need to show this mailbox. */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen ret = FALSE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen break;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen if (!stars || strncmp(info->name, prefix, prefix_len) == 0)
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen ret = TRUE;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen (void)mailbox_list_iter_deinit(&iter);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen return ret;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen}
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainenstatic int
0b219481c3b695a18ba5801aa4843cf4d532dd86Timo Sirainenacl_mailbox_list_info_is_visible(struct acl_mailbox_list_iterate_context *ctx)
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen{
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen#define PRESERVE_MAILBOX_FLAGS (MAILBOX_SUBSCRIBED | MAILBOX_CHILD_SUBSCRIBED)
0b219481c3b695a18ba5801aa4843cf4d532dd86Timo Sirainen struct mailbox_info *info = &ctx->info;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen const char *acl_name;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen int ret;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RAW_LIST) != 0) {
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen /* skip ACL checks. */
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return 1;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen }
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen acl_name = acl_mailbox_list_iter_get_name(&ctx->ctx, info->name);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_mailbox_list_have_right(ctx->ctx.list, acl_name,
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen ACL_STORAGE_RIGHT_LOOKUP,
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen NULL);
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen if (ret != 0)
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return ret;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen /* no permission to see this mailbox */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* we're listing subscribed mailboxes. this one or its child
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen is subscribed, so we'll need to list it. but since we don't
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen have LOOKUP right, we'll need to show it as nonexistent. */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen i_assert((info->flags & PRESERVE_MAILBOX_FLAGS) != 0);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen info->flags = MAILBOX_NONEXISTENT |
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen (info->flags & PRESERVE_MAILBOX_FLAGS);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen return 1;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if (!iter_is_listing_all_children(ctx) &&
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen iter_mailbox_has_visible_children(ctx)) {
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen /* no child mailboxes match the list pattern(s), but mailbox
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen has visible children. we'll need to show this as
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen non-existent. */
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen info->flags = MAILBOX_NONEXISTENT |
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen (info->flags & PRESERVE_MAILBOX_FLAGS);
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return 1;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen }
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return 0;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainenstatic const struct mailbox_info *
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainenacl_mailbox_list_iter_next(struct mailbox_list_iterate_context *_ctx)
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen{
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen struct acl_mailbox_list_iterate_context *ctx =
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen (struct acl_mailbox_list_iterate_context *)_ctx;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen const struct mailbox_info *info;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen int ret;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen while ((info = acl_mailbox_list_iter_next_info(ctx)) != NULL) {
0b219481c3b695a18ba5801aa4843cf4d532dd86Timo Sirainen ctx->info = *info;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
0b219481c3b695a18ba5801aa4843cf4d532dd86Timo Sirainen ret = acl_mailbox_list_info_is_visible(ctx);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen if (ret > 0)
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen break;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen if (ret < 0) {
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen ctx->ctx.failed = TRUE;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return NULL;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen /* skip to next one */
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen }
1eb915768b58044845eb83eeafc9eb72c2e985ecTimo Sirainen return info == NULL ? NULL : &ctx->info;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen}
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenstatic int
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenacl_mailbox_list_iter_deinit(struct mailbox_list_iterate_context *_ctx)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen{
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list_iterate_context *ctx =
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen (struct acl_mailbox_list_iterate_context *)_ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(_ctx->list);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen int ret = ctx->ctx.failed ? -1 : 0;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen if (alist->module_ctx.super.iter_deinit(ctx->super_ctx) < 0)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen ret = -1;
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen if (ctx->lookup_boxes != NULL)
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen mailbox_tree_deinit(&ctx->lookup_boxes);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen if (ctx->glob != NULL)
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen imap_match_deinit(&ctx->glob);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen i_free(ctx);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen return ret;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainenstatic int acl_get_mailbox_name_status(struct mailbox_list *list,
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen const char *name,
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen enum mailbox_name_status *status)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen{
2caa8fdbada1a0804fa978bdffb27c89e452933eTimo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen int ret;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_mailbox_list_have_right(list, name, ACL_STORAGE_RIGHT_LOOKUP,
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen NULL);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen if (ret < 0)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return -1;
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen if (ret == 0) {
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen /* If we have INSERT right for the mailbox, we'll need to
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen reveal its existence so that APPEND and COPY works. */
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_mailbox_list_have_right(list, name,
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen ACL_STORAGE_RIGHT_INSERT,
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen NULL);
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen if (ret < 0)
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen return -1;
2d641a38497bc4f9fc9782968f3f7b754abdaed6Timo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (alist->module_ctx.super.get_mailbox_name_status(list, name,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen status) < 0)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return -1;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen if (ret > 0)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return 0;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen /* we shouldn't reveal this mailbox's existance */
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen switch (*status) {
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen case MAILBOX_NAME_EXISTS:
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen *status = MAILBOX_NAME_VALID;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen break;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen case MAILBOX_NAME_VALID:
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen case MAILBOX_NAME_INVALID:
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen break;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen case MAILBOX_NAME_NOINFERIORS:
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen /* have to check if we are allowed to see the parent */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_storage_rights_ctx_have_right(&alist->rights, name,
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen TRUE, ACL_STORAGE_RIGHT_LOOKUP, NULL);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen if (ret < 0) {
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen mailbox_list_set_internal_error(list);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return -1;
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen if (ret == 0) {
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen /* no permission to see the parent */
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen *status = MAILBOX_NAME_VALID;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen break;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return 0;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen}
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenacl_mailbox_list_delete(struct mailbox_list *list, const char *name)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen bool can_see;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen int ret;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_mailbox_list_have_right(list, name, ACL_STORAGE_RIGHT_DELETE,
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen &can_see);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret <= 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret < 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (can_see) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PERM,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERRSTR_NO_PERMISSION);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return alist->module_ctx.super.delete_mailbox(list, name);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenacl_mailbox_list_rename(struct mailbox_list *list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldname, const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen bool can_see;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen int ret;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* renaming requires rights to delete the old mailbox */
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_mailbox_list_have_right(list, oldname,
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen ACL_STORAGE_RIGHT_DELETE, &can_see);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret <= 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret < 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (can_see) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PERM,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERRSTR_NO_PERMISSION);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* and create the new one under the parent mailbox */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen ret = acl_storage_rights_ctx_have_right(&alist->rights, newname,
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen TRUE, ACL_STORAGE_RIGHT_CREATE, NULL);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret <= 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret == 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* Note that if the mailbox didn't have LOOKUP
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen permission, this not reveals to user the mailbox's
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen existence. Can't help it. */
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PERM,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERRSTR_NO_PERMISSION);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen } else {
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen mailbox_list_set_internal_error(list);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return alist->module_ctx.super.rename_mailbox(list, oldname, newname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainenvoid acl_mailbox_list_created(struct mailbox_list *list)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen{
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen struct acl_user *auser = ACL_USER_CONTEXT(list->ns->user);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen struct acl_mailbox_list *alist;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen struct acl_backend *backend;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen struct mail_namespace *ns;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen enum mailbox_list_flags flags;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *current_username, *owner_username;
a52bb32f47ea8e2c242189dcfe203a0749b62c77Timo Sirainen bool owner = TRUE;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen if ((list->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0) {
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen /* no ACL checks for internal namespaces (deliver) */
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen return;
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen }
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen owner_username = list->ns->user->username;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen current_username = auser->master_user;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if (current_username == NULL)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen current_username = owner_username;
a52bb32f47ea8e2c242189dcfe203a0749b62c77Timo Sirainen else
a52bb32f47ea8e2c242189dcfe203a0749b62c77Timo Sirainen owner = strcmp(current_username, owner_username) == 0;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen /* We don't care about the username for non-private mailboxes.
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen It's used only when checking if we're the mailbox owner. We never
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen are for shared/public mailboxes. */
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen ns = mailbox_list_get_namespace(list);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if (ns->type != NAMESPACE_PRIVATE)
a52bb32f47ea8e2c242189dcfe203a0749b62c77Timo Sirainen owner = FALSE;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen backend = acl_backend_init(auser->acl_env, list, current_username,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen auser->groups, owner);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if (backend == NULL)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen i_fatal("ACL backend initialization failed");
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen flags = mailbox_list_get_flags(list);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if ((flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0) {
04870054863757edf048c81dcce3c5e7dec453cdTimo Sirainen /* not necessarily, but safer to do this for now. */
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen i_fatal("mail_full_filesystem_access=yes is "
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen "incompatible with ACLs");
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen }
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen alist = p_new(list->pool, struct acl_mailbox_list, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen alist->module_ctx.super = list->v;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen list->v.iter_init = acl_mailbox_list_iter_init;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen list->v.iter_next = acl_mailbox_list_iter_next;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen list->v.iter_deinit = acl_mailbox_list_iter_deinit;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen list->v.get_mailbox_name_status = acl_get_mailbox_name_status;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen list->v.delete_mailbox = acl_mailbox_list_delete;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen list->v.rename_mailbox = acl_mailbox_list_rename;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen acl_storage_rights_ctx_init(&alist->rights, backend);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen if (acl_next_hook_mailbox_list_created != NULL)
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen acl_next_hook_mailbox_list_created(list);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen}