コード例 #1
0
int acl_shared_namespaces_add(struct mail_namespace *ns)
{
	struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ns->list);
	struct mail_storage *storage = mail_namespace_get_default_storage(ns);
	struct acl_lookup_dict_iter *iter;
	const char *name;

	i_assert(ns->type == MAIL_NAMESPACE_TYPE_SHARED);
	i_assert(strcmp(storage->name, MAIL_SHARED_STORAGE_NAME) == 0);

	if (ioloop_time < alist->last_shared_add_check + SHARED_NS_RETRY_SECS) {
		/* already added, don't bother rechecking */
		return 0;
	}
	alist->last_shared_add_check = ioloop_time;

	iter = acl_lookup_dict_iterate_visible_init(auser->acl_lookup_dict);
	while ((name = acl_lookup_dict_iterate_visible_next(iter)) != NULL) {
		T_BEGIN {
			acl_shared_namespace_add(ns, storage, name);
		} T_END;
	}
	return acl_lookup_dict_iterate_visible_deinit(&iter);
}
コード例 #2
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
int acl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
				bool parent, unsigned int acl_storage_right_idx,
				bool *can_see_r)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
	struct acl_backend *backend = alist->rights.backend;
	const unsigned int *idx_arr = alist->rights.acl_storage_right_idx;
	struct acl_object *aclobj;
	int ret, ret2;

	aclobj = !parent ?
		acl_object_init_from_name(backend, name) :
		acl_object_init_from_parent(backend, name);
	ret = acl_object_have_right(aclobj, idx_arr[acl_storage_right_idx]);

	if (can_see_r != NULL) {
		ret2 = acl_object_have_right(aclobj,
					     idx_arr[ACL_STORAGE_RIGHT_LOOKUP]);
		if (ret2 < 0)
			ret = -1;
		*can_see_r = ret2 > 0;
	}
	acl_object_deinit(&aclobj);

	if (ret < 0)
		mailbox_list_set_internal_error(list);
	return ret;
}
コード例 #3
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
void acl_mail_namespace_storage_added(struct mail_namespace *ns)
{
	struct acl_user *auser = ACL_USER_CONTEXT(ns->user);
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ns->list);
	struct acl_backend *backend;
	const char *current_username, *owner_username;
	bool owner = TRUE;

	if (alist == NULL)
		return;

	owner_username = ns->user->username;
	current_username = auser->acl_user;
	if (current_username == NULL)
		current_username = owner_username;
	else
		owner = strcmp(current_username, owner_username) == 0;

	/* We don't care about the username for non-private mailboxes.
	   It's used only when checking if we're the mailbox owner. We never
	   are for shared/public mailboxes. */
	if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)
		owner = FALSE;

	/* we need to know the storage when initializing backend */
	backend = acl_backend_init(auser->acl_env, ns->list, current_username,
				   auser->groups, owner);
	if (backend == NULL)
		i_fatal("ACL backend initialization failed");
	acl_storage_rights_ctx_init(&alist->rights, backend);
}
コード例 #4
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
static void acl_mailbox_list_deinit(struct mailbox_list *list)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);

	if (alist->rights.backend != NULL)
		acl_backend_deinit(&alist->rights.backend);
	alist->module_ctx.super.deinit(list);
}
コード例 #5
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
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);
}
コード例 #6
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
static struct mailbox_list_iterate_context *
acl_mailbox_list_iter_init(struct mailbox_list *list,
			   const char *const *patterns,
			   enum mailbox_list_iter_flags flags)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
	struct acl_mailbox_list_iterate_context *ctx;
	pool_t pool;
	const char *p;
	unsigned int i;
	bool inboxcase;

	pool = pool_alloconly_create("mailbox list acl iter", 1024);
	ctx = p_new(pool, struct acl_mailbox_list_iterate_context, 1);
	ctx->ctx.pool = pool;
	ctx->ctx.list = list;
	ctx->ctx.flags = flags;

	if (list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE &&
	    (list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0) {
		/* non-private namespace with subscriptions=yes. this could be
		   a site-global subscriptions file, so hide subscriptions for
		   mailboxes the user doesn't see. */
		ctx->hide_nonlistable_subscriptions = TRUE;
	}

	inboxcase = (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
	ctx->sep = mail_namespace_get_sep(list->ns);
	ctx->ctx.glob = imap_match_init_multiple(pool, patterns,
						 inboxcase, ctx->sep);
	/* see if all patterns have only a single '*' and it's at the end.
	   we can use it to do some optimizations. */
	ctx->simple_star_glob = TRUE;
	for (i = 0; patterns[i] != NULL; i++) {
		p = strchr(patterns[i], '*');
		if (p == NULL || p[1] != '\0') {
			ctx->simple_star_glob = FALSE;
			break;
		}
	}

	/* Try to avoid reading ACLs from all mailboxes by getting a smaller
	   list of mailboxes that have even potential to be visible. If we
	   couldn't get such a list, we'll go through all mailboxes. */
	T_BEGIN {
		acl_mailbox_try_list_fast(ctx);
	} T_END;
	ctx->super_ctx = alist->module_ctx.super.
		iter_init(list, patterns, flags);
	return &ctx->ctx;
}
コード例 #7
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
static int
acl_mailbox_list_iter_deinit(struct mailbox_list_iterate_context *_ctx)
{
	struct acl_mailbox_list_iterate_context *ctx =
		(struct acl_mailbox_list_iterate_context *)_ctx;
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(_ctx->list);
	int ret = ctx->ctx.failed ? -1 : 0;

	if (alist->module_ctx.super.iter_deinit(ctx->super_ctx) < 0)
		ret = -1;
	if (ctx->lookup_boxes != NULL)
		mailbox_tree_deinit(&ctx->lookup_boxes);
	pool_unref(&_ctx->pool);
	return ret;
}
コード例 #8
0
void acl_mailbox_allocated(struct mailbox *box)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
	struct mailbox_vfuncs *v = box->vlast;
	struct acl_mailbox *abox;

	if (alist == NULL) {
		/* ACLs disabled */
		return;
	}

	if (box->list->ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
	    (box->list->ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
		/* this is the root shared namespace, which itself doesn't
		   have any existing mailboxes. */
		return;
	}

	abox = p_new(box->pool, struct acl_mailbox, 1);
	abox->module_ctx.super = *v;
	box->vlast = &abox->module_ctx.super;
	/* aclobj can be used for setting ACLs, even when mailbox is opened
	   with IGNORE_ACLS flag */
	abox->aclobj = acl_object_init_from_name(alist->rights.backend,
						 mailbox_get_name(box));

	v->free = acl_mailbox_free;
	if ((box->flags & MAILBOX_FLAG_IGNORE_ACLS) == 0) {
		abox->acl_enabled = TRUE;
		v->is_readonly = acl_is_readonly;
		v->exists = acl_mailbox_exists;
		v->open = acl_mailbox_open;
		v->get_status = acl_mailbox_get_status;
		v->create_box = acl_mailbox_create;
		v->update_box = acl_mailbox_update;
		v->delete_box = acl_mailbox_delete;
		v->rename_box = acl_mailbox_rename;
		v->save_begin = acl_save_begin;
		v->copy = acl_copy;
		v->transaction_commit = acl_transaction_commit;
		v->attribute_set = acl_attribute_set;
		v->attribute_get = acl_attribute_get;
		v->attribute_iter_init = acl_attribute_iter_init;
		v->attribute_iter_next = acl_attribute_iter_next;
		v->attribute_iter_deinit = acl_attribute_iter_deinit;
	}
	MODULE_CONTEXT_SET(box, acl_storage_module, abox);
}
コード例 #9
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
static struct mailbox_list_iterate_context *
acl_mailbox_list_iter_init_shared(struct mailbox_list *list,
				  const char *const *patterns,
				  enum mailbox_list_iter_flags flags)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
	struct mailbox_list_iterate_context *ctx;
	int ret;

	/* before listing anything add namespaces for all users
	   who may have visible mailboxes */
	ret = acl_shared_namespaces_add(list->ns);

	ctx = alist->module_ctx.super.iter_init(list, patterns, flags);
	if (ret < 0)
		ctx->failed = TRUE;
	return ctx;
}
コード例 #10
0
ファイル: acl-mailbox.c プロジェクト: manuelm/dovecot
static int acl_mailbox_open_check_acl(struct mailbox *box)
{
	struct acl_mailbox *abox = ACL_CONTEXT(box);
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
	const unsigned int *idx_arr = alist->rights.acl_storage_right_idx;
	enum acl_storage_rights open_right;
	int ret;

	/* mailbox can be opened either for reading or appending new messages */
	if ((box->flags & MAILBOX_FLAG_IGNORE_ACLS) != 0 ||
	    (box->list->ns->flags & NAMESPACE_FLAG_NOACL) != 0 ||
	    abox->skip_acl_checks)
		return 0;

	if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0) {
		open_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
			ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
	} else if (box->deleting) {
		open_right = ACL_STORAGE_RIGHT_DELETE;
	} else {
		open_right = ACL_STORAGE_RIGHT_READ;
	}

	ret = acl_object_have_right(abox->aclobj, idx_arr[open_right]);
	if (ret <= 0) {
		if (ret == 0) {
			/* no access. */
			acl_mailbox_fail_not_found(box);
		}
		return -1;
	}
	if (open_right != ACL_STORAGE_RIGHT_READ) {
		ret = acl_object_have_right(abox->aclobj,
					    idx_arr[ACL_STORAGE_RIGHT_READ]);
		if (ret < 0)
			return -1;
		if (ret == 0)
			abox->no_read_right = TRUE;
	}
	return 0;
}
コード例 #11
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
static const struct mailbox_info *
acl_mailbox_list_iter_next_info(struct acl_mailbox_list_iterate_context *ctx)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
	const struct mailbox_info *info;

	while ((info = alist->module_ctx.super.iter_next(ctx->super_ctx)) != NULL) {
		/* if we've a list of mailboxes with LOOKUP rights, skip the
		   mailboxes not in the list (since we know they can't be
		   visible to us). */
		if (ctx->lookup_boxes == NULL ||
		    mailbox_tree_lookup(ctx->lookup_boxes, info->vname) != NULL)
			break;
		if (ctx->ctx.list->ns->user->mail_debug) {
			i_debug("acl: Mailbox not in dovecot-acl-list: %s",
				info->vname);
		}
	}

	return info;
}
コード例 #12
0
int acl_mailbox_right_lookup(struct mailbox *box, unsigned int right_idx)
{
	struct acl_mailbox *abox = ACL_CONTEXT(box);
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
	int ret;

	if (abox->skip_acl_checks)
		return 1;

	ret = acl_object_have_right(abox->aclobj,
			alist->rights.acl_storage_right_idx[right_idx]);
	if (ret > 0)
		return 1;
	if (ret < 0) {
		mail_storage_set_internal_error(box->storage);
		return -1;
	}

	mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
			       MAIL_ERRSTR_NO_PERMISSION);
	return 0;
}
コード例 #13
0
static void acl_mailbox_copy_acls_from_parent(struct mailbox *box)
{
	struct acl_mailbox *abox = ACL_CONTEXT(box);
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
	struct acl_object *parent_aclobj;
	struct acl_object_list_iter *iter;
	struct acl_rights_update update;

	memset(&update, 0, sizeof(update));
	update.modify_mode = ACL_MODIFY_MODE_REPLACE;
	update.neg_modify_mode = ACL_MODIFY_MODE_REPLACE;

	parent_aclobj = acl_object_init_from_parent(alist->rights.backend,
						    box->name);
	iter = acl_object_list_init(parent_aclobj);
	while (acl_object_list_next(iter, &update.rights) > 0) {
		/* don't copy global ACL rights. */
		if (!update.rights.global)
			(void)acl_object_update(abox->aclobj, &update);
	}
	acl_object_list_deinit(&iter);
	acl_object_deinit(&parent_aclobj);
}
コード例 #14
0
ファイル: acl-mailbox-list.c プロジェクト: Raffprta/core
struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);

	return alist->rights.backend;
}