~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to src/plugins/acl/acl-mailbox-list.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2006-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2006-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "array.h"
22
22
        struct mailbox_info info;
23
23
 
24
24
        char sep;
 
25
        unsigned int hide_nonlistable_subscriptions:1;
25
26
        unsigned int simple_star_glob:1;
26
27
};
27
28
 
95
96
                               MAILBOX_LIST_ITER_SELECT_SUBSCRIBED)) != 0)
96
97
                return;
97
98
 
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. */
101
102
                return;
172
173
        ctx->ctx.list = list;
173
174
        ctx->ctx.flags = flags;
174
175
 
 
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;
 
182
        }
 
183
 
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)
213
222
                        break;
214
223
                if (ctx->ctx.list->ns->user->mail_debug) {
215
224
                        i_debug("acl: Mailbox not in dovecot-acl-list: %s",
216
 
                                info->name);
 
225
                                info->vname);
217
226
                }
218
227
        }
219
228
 
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;
252
261
}
253
262
 
254
263
static bool
255
264
iter_mailbox_has_visible_children(struct acl_mailbox_list_iterate_context *ctx,
256
 
                                  bool only_nonpatterns)
 
265
                                  bool only_nonpatterns, bool subscribed)
257
266
{
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;
272
281
 
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)
276
285
                        return FALSE;
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]);
286
295
                else {
287
296
                        stars = TRUE;
288
297
                        str_append_c(pattern, '%');
289
298
                }
290
299
        }
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;
296
305
 
297
306
        iter = mailbox_list_iter_init(ctx->ctx.list, str_c(pattern),
 
307
                                      (!subscribed ? 0 :
 
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. */
304
315
                        ret = FALSE;
305
316
                        break;
306
317
                }
307
 
                if (!stars || strncmp(info->name, prefix, prefix_len) == 0)
 
318
                if (!stars || strncmp(info->vname, prefix, prefix_len) == 0)
308
319
                        ret = TRUE;
309
320
        }
310
321
        (void)mailbox_list_iter_deinit(&iter);
325
336
        }
326
337
 
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;
332
344
                return 1;
333
345
        }
334
346
 
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,
338
350
                                          NULL);
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;
348
360
                }
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)
 
377
                                return 0;
 
378
                        if (iter_is_listing_all_children(ctx) ||
 
379
                            !iter_mailbox_has_visible_children(ctx, TRUE, TRUE))
 
380
                                return 0;
 
381
                        /* e.g. LSUB "" % with visible subscribed children */
 
382
                }
360
383
                return 1;
361
384
        }
362
385
 
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
367
390
                   non-existent. */
394
417
                /* skip to next one */
395
418
                if (ctx->ctx.list->ns->user->mail_debug) {
396
419
                        i_debug("acl: No lookup right to mailbox: %s",
397
 
                                info->name);
 
420
                                info->vname);
398
421
                }
399
422
        }
400
423
        return info == NULL ? NULL : &ctx->info;
416
439
        return ret;
417
440
}
418
441
 
419
 
static int
420
 
acl_mailbox_list_create_dir(struct mailbox_list *list, const char *name,
421
 
                            enum mailbox_dir_create_type type)
422
 
{
423
 
        struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
424
 
        int ret;
425
 
 
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);
429
 
        if (ret <= 0) {
430
 
                if (ret < 0)
431
 
                        return -1;
432
 
                /* Note that if user didn't have LOOKUP permission to parent
433
 
                   mailbox, this may reveal the mailbox's existence to user.
434
 
                   Can't help it. */
435
 
                mailbox_list_set_error(list, MAIL_ERROR_PERM,
436
 
                                       MAIL_ERRSTR_NO_PERMISSION);
437
 
                return -1;
438
 
        }
439
 
        return alist->module_ctx.super.create_mailbox_dir(list, name, type);
440
 
}
441
 
 
442
442
static void acl_mailbox_list_deinit(struct mailbox_list *list)
443
443
{
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;
497
496
 
498
497
        MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
499
498
}
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)
523
522
                owner = FALSE;
524
523
 
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
 
545
                   crash doing it. */
543
546
        } else {
544
547
                acl_mailbox_list_init_default(list);
545
548
        }