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);
}
Esempio n. 3
0
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;
}