Example #1
0
int acl_object_have_right(struct acl_object *aclobj, unsigned int right_idx)
{
	struct acl_backend *backend = aclobj->backend;
	const struct acl_mask *have_mask;
	unsigned int read_idx;

	if (backend->v.object_refresh_cache(aclobj) < 0)
		return -1;

	have_mask = acl_cache_get_my_rights(backend->cache, aclobj->name);
	if (have_mask == NULL) {
		if (acl_backend_get_default_rights(backend, &have_mask) < 0)
			return -1;
	}

	if (acl_cache_mask_isset(have_mask, right_idx))
		return 1;

	if (mailbox_list_get_user(aclobj->backend->list)->dsyncing) {
		/* when dsync is running on a shared mailbox, it must be able
		   to do everything inside it. however, dsync shouldn't touch
		   mailboxes where user doesn't have any read access, because
		   that could make them readable on the replica. */
		read_idx = acl_backend_lookup_right(aclobj->backend,
						    MAIL_ACL_READ);
		if (acl_cache_mask_isset(have_mask, read_idx))
			return 1;
	}
	return 0;
}
Example #2
0
static void
acl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
	struct acl_backend *backend = alist->rights.backend;
	const unsigned int *idxp;
	const struct acl_mask *acl_mask;
	struct acl_mailbox_list_context *nonowner_list_ctx;
	struct mail_namespace *ns = ctx->ctx.list->ns;
	struct mailbox_list_iter_update_context update_ctx;
	const char *name;
	int ret;

	if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_RAW_LIST |
			       MAILBOX_LIST_ITER_SELECT_SUBSCRIBED)) != 0)
		return;

	if (ns->type == MAIL_NAMESPACE_TYPE_PUBLIC) {
		/* mailboxes in public namespace should all be listable to
		   someone. we don't benefit from fast listing. */
		return;
	}

	/* if this namespace's default rights contain LOOKUP, we'll need to
	   go through all mailboxes in any case. */
	idxp = alist->rights.acl_storage_right_idx + ACL_STORAGE_RIGHT_LOOKUP;
	if (acl_backend_get_default_rights(backend, &acl_mask) < 0 ||
	    acl_cache_mask_isset(acl_mask, *idxp))
		return;

	/* no LOOKUP right by default, we can optimize this */
	memset(&update_ctx, 0, sizeof(update_ctx));
	update_ctx.iter_ctx = &ctx->ctx;
	update_ctx.glob =
		imap_match_init(pool_datastack_create(), "*",
				(ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0,
				ctx->sep);
	update_ctx.match_parents = TRUE;
	update_ctx.tree_ctx = mailbox_tree_init(ctx->sep);

	nonowner_list_ctx = acl_backend_nonowner_lookups_iter_init(backend);
	while ((ret = acl_backend_nonowner_lookups_iter_next(nonowner_list_ctx,
							     &name)) > 0) {
		T_BEGIN {
			const char *vname =
				mailbox_list_get_vname(ns->list, name);
			mailbox_list_iter_update(&update_ctx, vname);
		} T_END;
	}
	acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx);

	if (ret == 0)
		ctx->lookup_boxes = update_ctx.tree_ctx;
	else
		mailbox_tree_deinit(&update_ctx.tree_ctx);
}
Example #3
0
int acl_object_have_right(struct acl_object *aclobj, unsigned int right_idx)
{
	struct acl_backend *backend = aclobj->backend;
	const struct acl_mask *have_mask;

	if (mailbox_list_get_user(aclobj->backend->list)->admin) {
		/* admin user (especially dsync) can do anything regardless
		   of ACLs */
		return 1;
	}

	if (backend->v.object_refresh_cache(aclobj) < 0)
		return -1;

	have_mask = acl_cache_get_my_rights(backend->cache, aclobj->name);
	if (have_mask == NULL) {
		if (acl_backend_get_default_rights(backend, &have_mask) < 0)
			return -1;
	}

	return acl_cache_mask_isset(have_mask, right_idx);
}