bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 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"
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen#include "mailbox-list-iter-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
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen#define MAILBOX_FLAG_MATCHED 0x40000000
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainenstruct acl_mailbox_list_iterate_context {
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi union mailbox_list_iterate_module_context module_ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen struct mailbox_tree_context *lookup_boxes;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct mailbox_info info;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen char sep;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool hide_nonlistable_subscriptions:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool simple_star_glob:1;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen bool autocreate_acls_checked:1;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen};
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_LOOKUP,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_READ,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_WRITE,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_WRITE_SEEN,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_WRITE_DELETED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_INSERT,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_POST,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_EXPUNGE,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_CREATE,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_DELETE,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_ACL_ADMIN
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen};
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi#define ACL_LIST_ITERATE_CONTEXT(obj) \
3131b3878de3245db7552234e66d437e8fde9351Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, acl_mailbox_list_module)
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstruct acl_mailbox_list_module acl_mailbox_list_module =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MODULE_CONTEXT_INIT(&mailbox_list_module_register);
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainenstruct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen{
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(list);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen return alist->rights.backend;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen}
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint acl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool parent, unsigned int acl_storage_right_idx,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool *can_see_r)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen{
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(list);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct acl_backend *backend = alist->rights.backend;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const unsigned int *idx_arr = alist->rights.acl_storage_right_idx;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct acl_object *aclobj;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int ret, ret2;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen aclobj = !parent ?
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen acl_object_init_from_name(backend, name) :
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen acl_object_init_from_parent(backend, name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = acl_object_have_right(aclobj, idx_arr[acl_storage_right_idx]);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (can_see_r != NULL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret2 = acl_object_have_right(aclobj,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen idx_arr[ACL_STORAGE_RIGHT_LOOKUP]);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret2 < 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *can_see_r = ret2 > 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen acl_object_deinit(&aclobj);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen if (ret < 0)
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen mailbox_list_set_internal_error(list);
da9f6acdcb303d0fe5160b669668aedf39c8f45aTimo Sirainen return ret;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen}
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainenstatic void
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomiacl_mailbox_try_list_fast(struct mailbox_list_iterate_context *_ctx)
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen{
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi struct acl_mailbox_list_iterate_context *ctx =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(_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;
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi struct mail_namespace *ns = _ctx->list->ns;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen struct mailbox_list_iter_update_context update_ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen const char *name;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if ((_ctx->flags & (MAILBOX_LIST_ITER_RAW_LIST |
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen MAILBOX_LIST_ITER_SELECT_SUBSCRIBED)) != 0)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen return;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if (ns->type == MAIL_NAMESPACE_TYPE_PUBLIC) {
36aa287d32a78048d66cff024a8f7e848c45a8bfTimo Sirainen /* mailboxes in public namespace should all be listable to
36aa287d32a78048d66cff024a8f7e848c45a8bfTimo Sirainen someone. we don't benefit from fast listing. */
36aa287d32a78048d66cff024a8f7e848c45a8bfTimo Sirainen return;
36aa287d32a78048d66cff024a8f7e848c45a8bfTimo Sirainen }
36aa287d32a78048d66cff024a8f7e848c45a8bfTimo 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 */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&update_ctx);
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi update_ctx.iter_ctx = _ctx;
44fda09101a94883f45b8a6214628e541550cebcTimo Sirainen update_ctx.glob =
44fda09101a94883f45b8a6214628e541550cebcTimo Sirainen imap_match_init(pool_datastack_create(), "*",
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 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);
c7f6992db44e9cd33b3b0d754833a1503ee9a53fAki Tuomi while (acl_backend_nonowner_lookups_iter_next(nonowner_list_ctx,
c7f6992db44e9cd33b3b0d754833a1503ee9a53fAki Tuomi &name)) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen T_BEGIN {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mailbox_list_get_vname(ns->list, name);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mailbox_list_iter_update(&update_ctx, vname);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } T_END;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen }
a81e49899669137f9d7d1ba4c3130c9389cee530Timo Sirainen
bbc7e2c2e726cf84da49f4062d05b0c35a9377bdAki Tuomi if (acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx) >= 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
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainenstatic struct mailbox_list_iterate_context *
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainenacl_mailbox_list_iter_init_shared(struct mailbox_list *list,
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen const char *const *patterns,
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen enum mailbox_list_iter_flags flags)
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen{
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(list);
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen struct mailbox_list_iterate_context *ctx;
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen int ret;
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen /* before listing anything add namespaces for all users
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen who may have visible mailboxes */
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen ret = acl_shared_namespaces_add(list->ns);
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen ctx = alist->module_ctx.super.iter_init(list, patterns, flags);
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen if (ret < 0)
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen ctx->failed = TRUE;
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen return ctx;
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen}
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo 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{
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(list);
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi struct mailbox_list_iterate_context *_ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen struct acl_mailbox_list_iterate_context *ctx;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen const char *p;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen unsigned int i;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi _ctx = alist->module_ctx.super.iter_init(list, patterns, flags);
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ctx = p_new(_ctx->pool, struct acl_mailbox_list_iterate_context, 1);
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen if (list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE &&
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen (list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0) {
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen /* non-private namespace with subscriptions=yes. this could be
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen a site-global subscriptions file, so hide subscriptions for
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen mailboxes the user doesn't see. */
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen ctx->hide_nonlistable_subscriptions = TRUE;
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen }
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ctx->sep = mail_namespace_get_sep(list->ns);
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
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi MODULE_CONTEXT_SET(_ctx, acl_mailbox_list_module, ctx);
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi
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 {
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi acl_mailbox_try_list_fast(_ctx);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi return _ctx;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
61e84692827b6a64912343f515c984853021483aTimo Sirainenstatic const struct mailbox_info *
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomiacl_mailbox_list_iter_next_info(struct mailbox_list_iterate_context *_ctx)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen{
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi struct acl_mailbox_list_iterate_context *ctx =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(_ctx->list);
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen const struct mailbox_info *info;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi while ((info = alist->module_ctx.super.iter_next(_ctx)) != 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). */
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen if (ctx->lookup_boxes == NULL ||
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen mailbox_tree_lookup(ctx->lookup_boxes, info->vname) != NULL)
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen break;
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if (_ctx->list->ns->user->mail_debug) {
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen i_debug("acl: Mailbox not in dovecot-acl-list: %s",
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen info->vname);
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen }
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen }
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,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen{
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen struct mail_namespace *ns = ctx->list->ns;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *name;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len;
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen name = mailbox_list_get_storage_name(ns->list, vname);
d7d3f11df97aa1e816964399a07c2ef23e573abbTimo Sirainen len = strlen(name);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (len > 0 && name[len-1] == mailbox_list_get_hierarchy_sep(ns->list)) {
d7d3f11df97aa1e816964399a07c2ef23e573abbTimo Sirainen /* name ends with separator. this can happen if doing e.g.
d7d3f11df97aa1e816964399a07c2ef23e573abbTimo Sirainen LIST "" foo/% and it lists "foo/". */
d7d3f11df97aa1e816964399a07c2ef23e573abbTimo Sirainen name = t_strndup(name, len-1);
d7d3f11df97aa1e816964399a07c2ef23e573abbTimo Sirainen }
d7d3f11df97aa1e816964399a07c2ef23e573abbTimo Sirainen return name;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen}
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainenstatic bool
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomiiter_is_listing_all_children(struct mailbox_list_iterate_context *_ctx)
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen{
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi struct acl_mailbox_list_iterate_context *ctx =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
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. */
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen child = t_strdup_printf("%s%cx", ctx->info.vname, ctx->sep);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen return ctx->simple_star_glob &&
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi imap_match(_ctx->glob, child) == IMAP_MATCH_YES;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen}
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainenstatic bool
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomiiter_mailbox_has_visible_children(struct mailbox_list_iterate_context *_ctx,
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen bool only_nonpatterns, bool subscribed)
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen{
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi struct acl_mailbox_list_iterate_context *ctx =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen struct mailbox_list_iterate_context *iter;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen const struct mailbox_info *info;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen string_t *pattern;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen const char *prefix;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t 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
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen node = mailbox_tree_lookup(ctx->lookup_boxes, ctx->info.vname);
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);
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen for (i = 0; ctx->info.vname[i] != '\0'; i++) {
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen if (ctx->info.vname[i] != '*')
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen str_append_c(pattern, ctx->info.vname[i]);
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen else {
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen stars = TRUE;
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen str_append_c(pattern, '%');
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen }
a8de8d06e459b4725cc4d1637a2baf00cab73924Timo Sirainen }
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen if (i > 0 && ctx->info.vname[i-1] != ctx->sep)
0a167fd961775cb203f862a3a6bc5e55ce8e76c9Timo 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
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi iter = mailbox_list_iter_init(_ctx->list, str_c(pattern),
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen (!subscribed ? 0 :
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) |
c07e35cfc9587fc7589cbc1db0daeeb828456b2bTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen if (only_nonpatterns &&
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi imap_match(_ctx->glob, info->vname) == 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 }
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen if (!stars || strncmp(info->vname, 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
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomiacl_mailbox_list_info_is_visible(struct mailbox_list_iterate_context *_ctx)
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen{
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi struct acl_mailbox_list_iterate_context *ctx =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
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
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if ((_ctx->flags & MAILBOX_LIST_ITER_RAW_LIST) != 0) {
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen /* skip ACL checks. */
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return 1;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen }
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if ((_ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 &&
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi (_ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0 &&
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen !ctx->hide_nonlistable_subscriptions) {
9d7718a765e54cc41d75e7a661a44b31a166e987Timo Sirainen /* don't waste time doing an ACL check. we're going to list
9d7718a765e54cc41d75e7a661a44b31a166e987Timo Sirainen all subscriptions anyway. */
9d7718a765e54cc41d75e7a661a44b31a166e987Timo Sirainen info->flags &= MAILBOX_SUBSCRIBED | MAILBOX_CHILD_SUBSCRIBED;
9d7718a765e54cc41d75e7a661a44b31a166e987Timo Sirainen return 1;
9d7718a765e54cc41d75e7a661a44b31a166e987Timo Sirainen }
9d7718a765e54cc41d75e7a661a44b31a166e987Timo Sirainen
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi acl_name = acl_mailbox_list_iter_get_name(_ctx, info->vname);
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi ret = acl_mailbox_list_have_right(_ctx->list, acl_name, FALSE,
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen ACL_STORAGE_RIGHT_LOOKUP,
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen NULL);
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen if (ret != 0) {
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if ((_ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0) {
0a167fd961775cb203f862a3a6bc5e55ce8e76c9Timo Sirainen /* don't waste time checking if there are visible
0a167fd961775cb203f862a3a6bc5e55ce8e76c9Timo Sirainen children, but also don't return incorrect flags */
0a167fd961775cb203f862a3a6bc5e55ce8e76c9Timo Sirainen info->flags &= ~MAILBOX_CHILDREN;
0a167fd961775cb203f862a3a6bc5e55ce8e76c9Timo Sirainen } else if ((info->flags & MAILBOX_CHILDREN) != 0 &&
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi !iter_mailbox_has_visible_children(_ctx, FALSE, FALSE)) {
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen info->flags &= ~MAILBOX_CHILDREN;
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen info->flags |= MAILBOX_NOCHILDREN;
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen }
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return ret;
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen }
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen /* no permission to see this mailbox */
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if ((_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);
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen if (ctx->hide_nonlistable_subscriptions) {
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen /* global subscriptions file. hide this entry if there
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen are no visible subscribed children or if we're going
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen to list the subscribed children anyway. */
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen if ((info->flags & MAILBOX_CHILD_SUBSCRIBED) == 0)
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen return 0;
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if (iter_is_listing_all_children(_ctx) ||
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi !iter_mailbox_has_visible_children(_ctx, TRUE, TRUE))
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen return 0;
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen /* e.g. LSUB "" % with visible subscribed children */
49b3aba19447f9d15fbe0506d81d6572b210a124Timo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen return 1;
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen }
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if (!iter_is_listing_all_children(_ctx) &&
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi iter_mailbox_has_visible_children(_ctx, TRUE, FALSE)) {
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. */
ecff11c6c8418a365da4e2b154327d52de2aa563Timo Sirainen info->flags = MAILBOX_NONEXISTENT | MAILBOX_CHILDREN |
ef893433824a4e9a8e423cfc493b8423ae32ef0fTimo Sirainen (info->flags & PRESERVE_MAILBOX_FLAGS);
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return 1;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen }
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen return 0;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainenstatic int
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainenacl_mailbox_list_iter_check_autocreate_acls(struct mailbox_list_iterate_context *_ctx)
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen{
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen struct acl_mailbox_list_iterate_context *ctx =
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen ACL_LIST_ITERATE_CONTEXT(_ctx);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen struct mailbox_settings *const *box_sets;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen unsigned int i, count;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen int ret;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen ctx->autocreate_acls_checked = TRUE;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen if (_ctx->autocreate_ctx == NULL)
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen return 0;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen if ((_ctx->flags & MAILBOX_LIST_ITER_RAW_LIST) != 0) {
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen /* skip ACL checks. */
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen return 0;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen }
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen box_sets = array_get(&_ctx->autocreate_ctx->box_sets, &count);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen i_assert(array_count(&_ctx->autocreate_ctx->boxes) == count);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen for (i = 0; i < count; ) {
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen const char *acl_name =
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen acl_mailbox_list_iter_get_name(_ctx, box_sets[i]->name);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen ret = acl_mailbox_list_have_right(_ctx->list, acl_name, FALSE,
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen ACL_STORAGE_RIGHT_LOOKUP,
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen NULL);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen if (ret < 0)
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen return -1;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen if (ret > 0)
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen i++;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen else {
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen /* no list right - remove the whole autobox */
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen array_delete(&_ctx->autocreate_ctx->box_sets, i, 1);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen array_delete(&_ctx->autocreate_ctx->boxes, i, 1);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen box_sets = array_get(&_ctx->autocreate_ctx->box_sets, &count);
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen }
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen }
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen return 0;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen}
ab7687e9b029a16a6d4f4542943811262387ae87Timo 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 =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen const struct mailbox_info *info;
721f9e3d2ca029b6bca93396801f3131e4e0e5f4Timo Sirainen int ret;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen if (!ctx->autocreate_acls_checked) {
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen if (acl_mailbox_list_iter_check_autocreate_acls(_ctx) < 0) {
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen _ctx->failed = TRUE;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen return NULL;
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen }
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen }
ab7687e9b029a16a6d4f4542943811262387ae87Timo Sirainen
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi while ((info = acl_mailbox_list_iter_next_info(_ctx)) != NULL) {
0b219481c3b695a18ba5801aa4843cf4d532dd86Timo Sirainen ctx->info = *info;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi 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) {
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi _ctx->failed = TRUE;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen return NULL;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen /* skip to next one */
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi if (_ctx->list->ns->user->mail_debug) {
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen i_debug("acl: No lookup right to mailbox: %s",
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen info->vname);
925915badca5cf87bf45050c2fcc103534bef71aTimo Sirainen }
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 =
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi ACL_LIST_ITERATE_CONTEXT(_ctx);
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(_ctx->list);
2e295aaaf04febd3bb7be66cddd4d8ffa96fa5dcAki Tuomi int ret = _ctx->failed ? -1 : 0;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi if (ctx->lookup_boxes != NULL)
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi mailbox_tree_deinit(&ctx->lookup_boxes);
7e1600ded6fe7e056cea3771bb28fc11d571f039Aki Tuomi if (alist->module_ctx.super.iter_deinit(_ctx) < 0)
5707c94de29af4645a93e0d36ffa57af5537172cTimo Sirainen ret = -1;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen return ret;
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen}
2f122b4db3f0d4eeb59ff9d306e54b2009d72cf9Timo Sirainen
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainenstatic void acl_mailbox_list_deinit(struct mailbox_list *list)
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen{
5e10e813a3f0c0f568cf642dbdf440a40b183ae6Aki Tuomi struct acl_mailbox_list *alist = ACL_LIST_CONTEXT_REQUIRE(list);
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen
835e8c5861889b7945e40ad022e2d262b56386aeTimo Sirainen if (alist->rights.backend != NULL)
835e8c5861889b7945e40ad022e2d262b56386aeTimo Sirainen acl_backend_deinit(&alist->rights.backend);
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen alist->module_ctx.super.deinit(list);
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen}
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainenstatic void acl_mailbox_list_init_shared(struct mailbox_list *list)
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen{
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen struct acl_mailbox_list *alist;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mailbox_list_vfuncs *v = list->vlast;
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen alist = p_new(list->pool, struct acl_mailbox_list, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen alist->module_ctx.super = *v;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen list->vlast = &alist->module_ctx.super;
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen v->deinit = acl_mailbox_list_deinit;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->iter_init = acl_mailbox_list_iter_init_shared;
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen}
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void acl_storage_rights_ctx_init(struct acl_storage_rights_context *ctx,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct acl_backend *backend)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int i;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->backend = backend;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; i < ACL_STORAGE_RIGHT_COUNT; i++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->acl_storage_right_idx[i] =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen acl_backend_lookup_right(backend,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen acl_storage_right_names[i]);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainenstatic void acl_mailbox_list_init_default(struct mailbox_list *list)
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mailbox_list_vfuncs *v = list->vlast;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen struct acl_mailbox_list *alist;
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen if (list->mail_set->mail_full_filesystem_access) {
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen /* not necessarily, but safer to do this for now. */
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen i_fatal("mail_full_filesystem_access=yes is "
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen "incompatible with ACLs");
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen }
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen alist = p_new(list->pool, struct acl_mailbox_list, 1);
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen alist->module_ctx.super = *v;
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen list->vlast = &alist->module_ctx.super;
c22572f8d98de4d8bf3d017421ed9f534b69186bTimo Sirainen v->deinit = acl_mailbox_list_deinit;
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen v->iter_init = acl_mailbox_list_iter_init;
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen v->iter_next = acl_mailbox_list_iter_next;
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen v->iter_deinit = acl_mailbox_list_iter_deinit;
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen}
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainenvoid acl_mail_namespace_storage_added(struct mail_namespace *ns)
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen{
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ns->list);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen struct acl_backend *backend;
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen const char *current_username, *owner_username;
a52bb32f47ea8e2c242189dcfe203a0749b62c77Timo Sirainen bool owner = TRUE;
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen
9298394f818e96140eef4eb942f6bcfbbef78859Timo Sirainen if (alist == NULL)
9298394f818e96140eef4eb942f6bcfbbef78859Timo Sirainen return;
88a4bd48b03c451596414c16f72c0f4cc31b4745Aki Tuomi struct acl_user *auser = ACL_USER_CONTEXT_REQUIRE(ns->user);
9298394f818e96140eef4eb942f6bcfbbef78859Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen owner_username = ns->user->username;
dd5683e19979085fdfe9f269876f2a91ea604679Timo Sirainen current_username = auser->acl_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. */
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)
a52bb32f47ea8e2c242189dcfe203a0749b62c77Timo Sirainen owner = FALSE;
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen /* we need to know the storage when initializing backend */
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen backend = acl_backend_init(auser->acl_env, ns->list, current_username,
81e6e1ef0feef60644a4c4b745d82a4c98223affTimo Sirainen auser->groups, owner);
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if (backend == NULL)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen i_fatal("ACL backend initialization failed");
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen acl_storage_rights_ctx_init(&alist->rights, backend);
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen}
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainenvoid acl_mailbox_list_created(struct mailbox_list *list)
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen{
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen struct acl_user *auser = ACL_USER_CONTEXT(list->ns->user);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (auser == NULL) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* ACLs disabled for this user */
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen } else if ((list->ns->flags & NAMESPACE_FLAG_NOACL) != 0) {
dc7c35479b96456dcca68b7d8e1ae9b9beac1074Timo Sirainen /* no ACL checks for internal namespaces (lda, shared) */
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen if (list->ns->type == MAIL_NAMESPACE_TYPE_SHARED)
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen acl_mailbox_list_init_shared(list);
9b706b345064ce8e8a657f54633f009a101298eaTimo Sirainen } else if ((list->ns->flags & NAMESPACE_FLAG_UNUSABLE) != 0) {
9b706b345064ce8e8a657f54633f009a101298eaTimo Sirainen /* this namespace is empty. don't attempt to lookup ACLs,
9b706b345064ce8e8a657f54633f009a101298eaTimo Sirainen because they're not going to work anyway and we could
9b706b345064ce8e8a657f54633f009a101298eaTimo Sirainen crash doing it. */
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen } else {
cb433472848dddf0a42aa7252eda6721559a7c72Timo Sirainen acl_mailbox_list_init_default(list);
cb5a43d2dd99db0037b3450701ed83df78bc90f5Timo Sirainen }
f9c7106cc05eedb57d1beee3ca3c47f49fafb172Timo Sirainen}