static int acl_mailbox_create(struct mailbox *box, const struct mailbox_update *update, bool directory) { struct acl_mailbox *abox = ACL_CONTEXT(box); int ret; /* we're looking up CREATE permission from our parent's rights */ ret = acl_mailbox_list_have_right(box->list, box->name, TRUE, ACL_STORAGE_RIGHT_CREATE, NULL); if (ret <= 0) { if (ret < 0) { mail_storage_set_internal_error(box->storage); return -1; } /* Note that if user didn't have LOOKUP permission to parent mailbox, this may reveal the mailbox's existence to user. Can't help it. */ mail_storage_set_error(box->storage, MAIL_ERROR_PERM, MAIL_ERRSTR_NO_PERMISSION); return -1; } /* ignore ACLs in this mailbox until creation is complete, because super.create() may call e.g. mailbox_open() which will fail since we haven't yet copied ACLs to this mailbox. */ abox->skip_acl_checks = TRUE; ret = abox->module_ctx.super.create_box(box, update, directory); abox->skip_acl_checks = FALSE; if (ret == 0) acl_mailbox_copy_acls_from_parent(box); return ret; }
static int acl_mailbox_rename(struct mailbox *src, struct mailbox *dest) { struct acl_mailbox *abox = ACL_CONTEXT(src); int ret; /* renaming requires rights to delete the old mailbox */ ret = acl_mailbox_right_lookup(src, ACL_STORAGE_RIGHT_DELETE); if (ret <= 0) { if (ret == 0) acl_mailbox_fail_not_found(src); return -1; } /* and create the new one under the parent mailbox */ T_BEGIN { ret = acl_mailbox_list_have_right(dest->list, dest->name, TRUE, ACL_STORAGE_RIGHT_CREATE, NULL); } T_END; if (ret <= 0) { if (ret == 0) { /* Note that if the mailbox didn't have LOOKUP permission, this now reveals to user the mailbox's existence. Can't help it. */ mail_storage_set_error(src->storage, MAIL_ERROR_PERM, MAIL_ERRSTR_NO_PERMISSION); } else { mail_storage_set_internal_error(src->storage); } return -1; } return abox->module_ctx.super.rename_box(src, dest); }
static int acl_mailbox_list_info_is_visible(struct acl_mailbox_list_iterate_context *ctx) { #define PRESERVE_MAILBOX_FLAGS (MAILBOX_SUBSCRIBED | MAILBOX_CHILD_SUBSCRIBED) struct mailbox_info *info = &ctx->info; const char *acl_name; int ret; if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RAW_LIST) != 0) { /* skip ACL checks. */ return 1; } if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 && (ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0 && !ctx->hide_nonlistable_subscriptions) { /* don't waste time doing an ACL check. we're going to list all subscriptions anyway. */ info->flags &= MAILBOX_SUBSCRIBED | MAILBOX_CHILD_SUBSCRIBED; return 1; } acl_name = acl_mailbox_list_iter_get_name(&ctx->ctx, info->vname); ret = acl_mailbox_list_have_right(ctx->ctx.list, acl_name, FALSE, ACL_STORAGE_RIGHT_LOOKUP, NULL); if (ret != 0) { if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0) { /* don't waste time checking if there are visible children, but also don't return incorrect flags */ info->flags &= ~MAILBOX_CHILDREN; } else if ((info->flags & MAILBOX_CHILDREN) != 0 && !iter_mailbox_has_visible_children(ctx, FALSE, FALSE)) { info->flags &= ~MAILBOX_CHILDREN; info->flags |= MAILBOX_NOCHILDREN; } return ret; } /* no permission to see this mailbox */ if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) { /* we're listing subscribed mailboxes. this one or its child is subscribed, so we'll need to list it. but since we don't have LOOKUP right, we'll need to show it as nonexistent. */ i_assert((info->flags & PRESERVE_MAILBOX_FLAGS) != 0); info->flags = MAILBOX_NONEXISTENT | (info->flags & PRESERVE_MAILBOX_FLAGS); if (ctx->hide_nonlistable_subscriptions) { /* global subscriptions file. hide this entry if there are no visible subscribed children or if we're going to list the subscribed children anyway. */ if ((info->flags & MAILBOX_CHILD_SUBSCRIBED) == 0) return 0; if (iter_is_listing_all_children(ctx) || !iter_mailbox_has_visible_children(ctx, TRUE, TRUE)) return 0; /* e.g. LSUB "" % with visible subscribed children */ } return 1; } if (!iter_is_listing_all_children(ctx) && iter_mailbox_has_visible_children(ctx, TRUE, FALSE)) { /* no child mailboxes match the list pattern(s), but mailbox has visible children. we'll need to show this as non-existent. */ info->flags = MAILBOX_NONEXISTENT | MAILBOX_CHILDREN | (info->flags & PRESERVE_MAILBOX_FLAGS); return 1; } return 0; }