95
96
MAILBOX_LIST_ITER_SELECT_SUBSCRIBED)) != 0)
98
if (ns->type == NAMESPACE_PUBLIC) {
99
if (ns->type == MAIL_NAMESPACE_TYPE_PUBLIC) {
99
100
/* mailboxes in public namespace should all be listable to
100
101
someone. we don't benefit from fast listing. */
172
173
ctx->ctx.list = list;
173
174
ctx->ctx.flags = flags;
176
if (list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE &&
177
(list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0) {
178
/* non-private namespace with subscriptions=yes. this could be
179
a site-global subscriptions file, so hide subscriptions for
180
mailboxes the user doesn't see. */
181
ctx->hide_nonlistable_subscriptions = TRUE;
175
184
inboxcase = (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
176
185
ctx->sep = mail_namespace_get_sep(list->ns);
177
186
ctx->ctx.glob = imap_match_init_multiple(pool, patterns,
209
218
mailboxes not in the list (since we know they can't be
210
219
visible to us). */
211
220
if (ctx->lookup_boxes == NULL ||
212
mailbox_tree_lookup(ctx->lookup_boxes, info->name) != NULL)
221
mailbox_tree_lookup(ctx->lookup_boxes, info->vname) != NULL)
214
223
if (ctx->ctx.list->ns->user->mail_debug) {
215
224
i_debug("acl: Mailbox not in dovecot-acl-list: %s",
246
255
/* If all patterns (with '.' separator) are in "name*", "name.*" or
247
256
"%.*" style format, simple_star_glob=TRUE and we can easily test
248
257
this by simply checking if name/child mailbox matches. */
249
child = t_strdup_printf("%s%cx", ctx->info.name, ctx->sep);
258
child = t_strdup_printf("%s%cx", ctx->info.vname, ctx->sep);
250
259
return ctx->simple_star_glob &&
251
260
imap_match(ctx->ctx.glob, child) == IMAP_MATCH_YES;
255
264
iter_mailbox_has_visible_children(struct acl_mailbox_list_iterate_context *ctx,
256
bool only_nonpatterns)
265
bool only_nonpatterns, bool subscribed)
258
267
struct mailbox_list_iterate_context *iter;
259
268
const struct mailbox_info *info;
270
279
if there even are any children with LOOKUP rights. */
271
280
struct mailbox_node *node;
273
node = mailbox_tree_lookup(ctx->lookup_boxes, ctx->info.name);
282
node = mailbox_tree_lookup(ctx->lookup_boxes, ctx->info.vname);
274
283
i_assert(node != NULL);
275
284
if (node->children == NULL)
280
289
LIST wildcard. replace then with '%' and verify later that all
281
290
results have the correct prefix. */
282
291
pattern = t_str_new(128);
283
for (i = 0; ctx->info.name[i] != '\0'; i++) {
284
if (ctx->info.name[i] != '*')
285
str_append_c(pattern, ctx->info.name[i]);
292
for (i = 0; ctx->info.vname[i] != '\0'; i++) {
293
if (ctx->info.vname[i] != '*')
294
str_append_c(pattern, ctx->info.vname[i]);
288
297
str_append_c(pattern, '%');
291
if (i > 0 && ctx->info.name[i-1] != ctx->sep)
300
if (i > 0 && ctx->info.vname[i-1] != ctx->sep)
292
301
str_append_c(pattern, ctx->sep);
293
302
str_append_c(pattern, '*');
294
303
prefix = str_c(pattern);
295
304
prefix_len = str_len(pattern) - 1;
297
306
iter = mailbox_list_iter_init(ctx->ctx.list, str_c(pattern),
308
MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) |
298
309
MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
299
310
while ((info = mailbox_list_iter_next(iter)) != NULL) {
300
311
if (only_nonpatterns &&
301
imap_match(ctx->ctx.glob, info->name) == IMAP_MATCH_YES) {
312
imap_match(ctx->ctx.glob, info->vname) == IMAP_MATCH_YES) {
302
313
/* at least one child matches also the original list
303
314
patterns. we don't need to show this mailbox. */
307
if (!stars || strncmp(info->name, prefix, prefix_len) == 0)
318
if (!stars || strncmp(info->vname, prefix, prefix_len) == 0)
310
321
(void)mailbox_list_iter_deinit(&iter);
327
338
if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 &&
328
(ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0) {
339
(ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0 &&
340
!ctx->hide_nonlistable_subscriptions) {
329
341
/* don't waste time doing an ACL check. we're going to list
330
342
all subscriptions anyway. */
331
343
info->flags &= MAILBOX_SUBSCRIBED | MAILBOX_CHILD_SUBSCRIBED;
335
acl_name = acl_mailbox_list_iter_get_name(&ctx->ctx, info->name);
347
acl_name = acl_mailbox_list_iter_get_name(&ctx->ctx, info->vname);
336
348
ret = acl_mailbox_list_have_right(ctx->ctx.list, acl_name, FALSE,
337
349
ACL_STORAGE_RIGHT_LOOKUP,
342
354
children, but also don't return incorrect flags */
343
355
info->flags &= ~MAILBOX_CHILDREN;
344
356
} else if ((info->flags & MAILBOX_CHILDREN) != 0 &&
345
!iter_mailbox_has_visible_children(ctx, FALSE)) {
357
!iter_mailbox_has_visible_children(ctx, FALSE, FALSE)) {
346
358
info->flags &= ~MAILBOX_CHILDREN;
347
359
info->flags |= MAILBOX_NOCHILDREN;
357
369
i_assert((info->flags & PRESERVE_MAILBOX_FLAGS) != 0);
358
370
info->flags = MAILBOX_NONEXISTENT |
359
371
(info->flags & PRESERVE_MAILBOX_FLAGS);
372
if (ctx->hide_nonlistable_subscriptions) {
373
/* global subscriptions file. hide this entry if there
374
are no visible subscribed children or if we're going
375
to list the subscribed children anyway. */
376
if ((info->flags & MAILBOX_CHILD_SUBSCRIBED) == 0)
378
if (iter_is_listing_all_children(ctx) ||
379
!iter_mailbox_has_visible_children(ctx, TRUE, TRUE))
381
/* e.g. LSUB "" % with visible subscribed children */
363
386
if (!iter_is_listing_all_children(ctx) &&
364
iter_mailbox_has_visible_children(ctx, TRUE)) {
387
iter_mailbox_has_visible_children(ctx, TRUE, FALSE)) {
365
388
/* no child mailboxes match the list pattern(s), but mailbox
366
389
has visible children. we'll need to show this as
420
acl_mailbox_list_create_dir(struct mailbox_list *list, const char *name,
421
enum mailbox_dir_create_type type)
423
struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
426
/* we're looking up CREATE permission from our parent's rights */
427
ret = acl_mailbox_list_have_right(list, name, TRUE,
428
ACL_STORAGE_RIGHT_CREATE, NULL);
432
/* Note that if user didn't have LOOKUP permission to parent
433
mailbox, this may reveal the mailbox's existence to user.
435
mailbox_list_set_error(list, MAIL_ERROR_PERM,
436
MAIL_ERRSTR_NO_PERMISSION);
439
return alist->module_ctx.super.create_mailbox_dir(list, name, type);
442
442
static void acl_mailbox_list_deinit(struct mailbox_list *list)
444
444
struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
493
493
v->iter_init = acl_mailbox_list_iter_init;
494
494
v->iter_next = acl_mailbox_list_iter_next;
495
495
v->iter_deinit = acl_mailbox_list_iter_deinit;
496
v->create_mailbox_dir = acl_mailbox_list_create_dir;
498
497
MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
519
518
/* We don't care about the username for non-private mailboxes.
520
519
It's used only when checking if we're the mailbox owner. We never
521
520
are for shared/public mailboxes. */
522
if (ns->type != NAMESPACE_PRIVATE)
521
if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)
525
524
/* we need to know the storage when initializing backend */
538
537
/* ACLs disabled for this user */
539
538
} else if ((list->ns->flags & NAMESPACE_FLAG_NOACL) != 0) {
540
539
/* no ACL checks for internal namespaces (lda, shared) */
541
if (list->ns->type == NAMESPACE_SHARED)
540
if (list->ns->type == MAIL_NAMESPACE_TYPE_SHARED)
542
541
acl_mailbox_list_init_shared(list);
542
} else if ((list->ns->flags & NAMESPACE_FLAG_UNUSABLE) != 0) {
543
/* this namespace is empty. don't attempt to lookup ACLs,
544
because they're not going to work anyway and we could
544
547
acl_mailbox_list_init_default(list);