acl-mailbox-list.c revision 306cfd77100131c08b243de10f6d40500f4c27c6
/* Copyright (c) 2006-2010 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "imap-match.h"
#include "mailbox-tree.h"
#include "mail-namespace.h"
#include "mailbox-list-private.h"
#include "acl-api-private.h"
#include "acl-cache.h"
#include "acl-shared-storage.h"
#include "acl-plugin.h"
#define MAILBOX_FLAG_MATCHED 0x40000000
struct acl_mailbox_list_iterate_context {
struct mailbox_list_iterate_context ctx;
struct mailbox_list_iterate_context *super_ctx;
struct mailbox_tree_context *lookup_boxes;
struct mailbox_info info;
struct imap_match_glob *glob;
char sep;
unsigned int simple_star_glob:1;
};
static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = {
};
{
}
bool parent, unsigned int acl_storage_right_idx,
bool *can_see_r)
{
struct acl_object *aclobj;
if (ret2 < 0)
ret = -1;
}
if (ret < 0)
return ret;
}
static void
{
const unsigned int *idxp;
const char *name;
int ret;
return;
/* 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. */
return;
/* no LOOKUP right by default, we can optimize this */
&name)) > 0) {
}
if (ret == 0)
else
}
static struct mailbox_list_iterate_context *
const char *const *patterns,
enum mailbox_list_iter_flags flags)
{
struct mailbox_list_iterate_context *ctx;
int ret;
/* before listing anything add namespaces for all users
who may have visible mailboxes */
if (ret < 0)
return ctx;
}
static struct mailbox_list_iterate_context *
const char *const *patterns,
enum mailbox_list_iter_flags flags)
{
struct acl_mailbox_list_iterate_context *ctx;
const char *p;
unsigned int i;
bool inboxcase;
/* see if all patterns have only a single '*' and it's at the end.
we can use it to do some optimizations. */
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 {
} T_END;
}
static const struct mailbox_info *
{
const struct mailbox_info *info;
/* 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). */
break;
i_debug("acl: Mailbox not in dovecot-acl-list: %s",
}
}
return info;
}
static const char *
const char *name)
{
unsigned int len;
/* name ends with separator. this can happen if doing e.g.
LIST "" foo/% and it lists "foo/". */
}
return name;
}
static bool
{
const char *child;
/* If all patterns (with '.' separator) are in "name*", "name.*" or
"%.*" style format, simple_star_glob=TRUE and we can easily test
return ctx->simple_star_glob &&
}
static bool
bool only_nonpatterns)
{
struct mailbox_list_iterate_context *iter;
const struct mailbox_info *info;
const char *prefix;
unsigned int i, prefix_len;
/* do we have child mailboxes with LOOKUP right that don't match
the list pattern? */
/* we have a list of mailboxes with LOOKUP rights. before
starting the slow list iteration, check check first
if there even are any children with LOOKUP rights. */
struct mailbox_node *node;
return FALSE;
}
/* if mailbox name has '*' characters in it, they'll conflict with the
LIST wildcard. replace then with '%' and verify later that all
results have the correct prefix. */
else {
}
}
if (only_nonpatterns &&
/* at least one child matches also the original list
patterns. we don't need to show this mailbox. */
break;
}
}
(void)mailbox_list_iter_deinit(&iter);
return ret;
}
static int
{
const char *acl_name;
int ret;
/* skip ACL checks. */
return 1;
}
NULL);
if (ret != 0) {
/* don't waste time checking if there are visible
children, but also don't return incorrect flags */
}
return ret;
}
/* no permission to see this mailbox */
/* 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. */
return 1;
}
if (!iter_is_listing_all_children(ctx) &&
/* no child mailboxes match the list pattern(s), but mailbox
has visible children. we'll need to show this as
non-existent. */
return 1;
}
return 0;
}
static const struct mailbox_info *
{
struct acl_mailbox_list_iterate_context *ctx =
(struct acl_mailbox_list_iterate_context *)_ctx;
const struct mailbox_info *info;
int ret;
T_BEGIN {
} T_END;
if (ret > 0)
break;
if (ret < 0) {
return NULL;
}
/* skip to next one */
i_debug("acl: No lookup right to mailbox: %s",
}
}
}
static int
{
struct acl_mailbox_list_iterate_context *ctx =
(struct acl_mailbox_list_iterate_context *)_ctx;
ret = -1;
return ret;
}
static int
enum mailbox_dir_create_type type)
{
int ret;
/* we're looking up CREATE permission from our parent's rights */
if (ret <= 0) {
if (ret < 0)
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. */
return -1;
}
}
{
}
{
struct acl_mailbox_list *alist;
}
struct acl_backend *backend)
{
unsigned int i;
for (i = 0; i < ACL_STORAGE_RIGHT_COUNT; i++) {
ctx->acl_storage_right_idx[i] =
}
}
{
struct acl_mailbox_list *alist;
/* not necessarily, but safer to do this for now. */
i_fatal("mail_full_filesystem_access=yes is "
"incompatible with ACLs");
}
}
{
struct acl_backend *backend;
const char *current_username, *owner_username;
return;
if (current_username == NULL)
else
/* 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
/* we need to know the storage when initializing backend */
i_fatal("ACL backend initialization failed");
}
{
/* ACLs disabled for this user */
/* no ACL checks for internal namespaces (lda, shared) */
} else {
}
}