~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/plugins/quota/quota-maildir.c

  • Committer: Bazaar Package Importer
  • Author(s): CHuck Short, Chuck Short
  • Date: 2009-11-06 00:47:29 UTC
  • mfrom: (4.1.9 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091106004729-i39n7v9e7d4h51f6
Tags: 1:1.2.6-1ubuntu1
* Merge from debian testing, remaining changes:
  Add new binary pkg dovecot-postfix that integrates postfix and dovecot
  automatically: (LP: #164837)
  + debian/control:
    - add new binary with short description
    - set Architecture all for dovecot-postfix (LP: #329878)
  + debian/dovecot-postfix.postinst:
    - create initial certificate symlinks to snakeoil.
    - set up postfix with postconf to:
      - use Maildir/ as the default mailbox.
      - use dovecot as the sasl authentication server.
      - use dovecot LDA (deliver).
      - use tls for smtp{d} services.
    - fix certificates paths in postfix' main.cf
    - add reject_unauth_destination to postfix' recipient restrictions
    - add reject_unknown_sender_domain to postfix' sender restrictions
    - rename configuration name on remove, delete on purge
    - restart dovecot after linking certificates
    - handle use case when postfix is unconfigurated
   + debian/dovecot-postfix.dirs: create backup directory for postfix's configuration
   + restart postfix and dovecot.
   + debian/dovecot-postfix.postrm:
     - remove all dovecot related configuration from postfix.
     - restart postfix and dovecot.
   + debian/dovecot-common.init:
     - check if /etc/dovecot/dovecot-postfix.conf exists and use it
       as the configuration file if so.
   + debian/patches/warning-ubuntu-postfix.dpatch
     - add warning about dovecot-postfix.conf in dovecot default 
       configuration file
   + debian/patches/dovecot-postfix.conf.diff:
     - Ubuntu server custom changes to the default dovecot configuration for
       better interfation with postfix
     - enable sieve plugin
   + debian/patches/dovecot-postfix.conf.diff:
     + Ubuntu server custom changes to the default dovecot configuration for
       better integration with postfix:
       - enable imap, pop3, imaps, pop3s and managesieve by default.
       - enable dovecot LDA (deliver).
       - enable SASL auth socket in postfix private directory.
   + debian/rules:
     - copy, patch and install dovecot-postfix.conf in /etc/dovecot/.
     - build architecure independent packages too
   + Use Snakeoil SSL certificates by default.
     - debian/control: Depend on ssl-cert.
     - debian/patches/ssl-cert-snakeoil.dpatch: Change default SSL cert
       paths to snakeoil.
     - debian/dovecot-common.postinst: Relax grep for SSL_* a bit.
   + Add autopkgtest to debian/tests/*.
   + Fast TearDown: Update the lsb init header to not stop in level 6.
   + Add ufw integration:
     - Created debian/dovecot-common.ufw.profile.
     - debian/rules:
       + install profile
     - debian/control:
       + Suggest ufw
   + debian/{control,rules}: enable PIE hardening.
   + dovecot-imapd, dovecot-pop3: Replaces dovecot-common (<< 1:1.1). LP: #254721
   + debian/control:
     - Update Vcs-* headers.
   + debian/rules:
     - Create emtpy stamp.h.in files in dovecot-sieve/ and dovecot-managesieve/
       if they're not there since empty files are not included in the diff.gz 
       file.
   + Add SMTP-AUTH support for Outlook (login auth mechanism)
   + Dropped:
     - debian/patches/security-CVE-2009-3235: Applied upstream.
     - debian/patches/fix-pop3-assertion.dpatch: Applied upstream.
     - dovecot-sieve and dovecot-managesieve: Use the debian patches instead.

  [Chuck Short]
  - Updated dovecot-sieve to 0.1.13.
  - Updated dovecot-managesieve to 0.11.9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
150
150
                        if (ctx->info == NULL)
151
151
                                return NULL;
152
152
 
153
 
                        rule = quota_root_rule_find(&ctx->root->root,
 
153
                        rule = quota_root_rule_find(ctx->root->root.set,
154
154
                                                    ctx->info->name);
155
155
                        if (rule != NULL && rule->ignore) {
156
156
                                /* mailbox not included in quota */
218
218
 
219
219
static int maildirsize_write(struct maildir_quota_root *root, const char *path)
220
220
{
221
 
        const struct quota_rule *rule = &root->root.default_rule;
 
221
        struct quota_root *_root = &root->root;
 
222
        struct mail_storage *const *storages;
 
223
        unsigned int i, count;
222
224
        struct dotlock *dotlock;
223
 
        const char *p, *dir;
 
225
        const char *p, *dir, *gid_origin, *dir_gid_origin;
224
226
        string_t *str;
 
227
        mode_t mode, dir_mode;
 
228
        gid_t gid, dir_gid;
225
229
        int fd;
226
230
 
227
231
        i_assert(root->fd == -1);
228
232
 
 
233
        /* figure out what permissions we should use for maildirsize.
 
234
           use the inbox namespace's permissions if possible. */
 
235
        mode = 0600; dir_mode = 0700; gid_origin = "default";
 
236
        gid = dir_gid = (gid_t)-1;
 
237
        storages = array_get(&root->root.quota->storages, &count);
 
238
        for (i = 0; i < count; i++) {
 
239
                if ((storages[i]->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
 
240
                        mailbox_list_get_permissions(storages[i]->ns->list,
 
241
                                                     NULL, &mode, &gid,
 
242
                                                     &gid_origin);
 
243
                        mailbox_list_get_dir_permissions(storages[i]->ns->list,
 
244
                                                         NULL,
 
245
                                                         &dir_mode, &dir_gid,
 
246
                                                         &dir_gid_origin);
 
247
                        break;
 
248
                }
 
249
        }
 
250
 
229
251
        dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL;
230
252
        dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL;
231
 
        fd = file_dotlock_open(&dotlock_settings, path,
232
 
                               DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock);
 
253
        fd = file_dotlock_open_group(&dotlock_settings, path,
 
254
                                     DOTLOCK_CREATE_FLAG_NONBLOCK,
 
255
                                     mode, gid, gid_origin, &dotlock);
233
256
        if (fd == -1 && errno == ENOENT) {
234
257
                /* the control directory doesn't exist yet? create it */
235
258
                p = strrchr(path, '/');
236
259
                dir = t_strdup_until(path, p);
237
 
                if (mkdir_parents(dir, 0700) < 0 && errno != EEXIST) {
 
260
                if (mkdir_parents_chgrp(dir, dir_mode, dir_gid,
 
261
                                        dir_gid_origin) < 0 &&
 
262
                    errno != EEXIST) {
238
263
                        i_error("mkdir_parents(%s) failed: %m", dir);
239
264
                        return -1;
240
265
                }
241
 
                fd = file_dotlock_open(&dotlock_settings, path,
242
 
                                       DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock);
 
266
                fd = file_dotlock_open_group(&dotlock_settings, path,
 
267
                                             DOTLOCK_CREATE_FLAG_NONBLOCK,
 
268
                                             mode, gid, gid_origin, &dotlock);
243
269
        }
244
270
        if (fd == -1) {
245
271
                if (errno == EAGAIN) {
253
279
 
254
280
        str = t_str_new(128);
255
281
        /* if we have no limits, write 0S instead of an empty line */
256
 
        if (rule->bytes_limit != 0 || rule->count_limit == 0) {
 
282
        if (_root->bytes_limit != 0 || _root->count_limit == 0) {
257
283
                str_printfa(str, "%lluS",
258
 
                            (unsigned long long)rule->bytes_limit);
 
284
                            (unsigned long long)_root->bytes_limit);
259
285
        }
260
 
        if (rule->count_limit != 0) {
 
286
        if (_root->count_limit != 0) {
261
287
                if (str_len(str) > 0)
262
288
                        str_append_c(str, ',');
263
289
                str_printfa(str, "%lluC",
264
 
                            (unsigned long long)rule->count_limit);
 
290
                            (unsigned long long)_root->count_limit);
265
291
        }
266
292
        str_printfa(str, "\n%llu %llu\n",
267
293
                    (unsigned long long)root->total_bytes,
315
341
 
316
342
static void maildirsize_rebuild_later(struct maildir_quota_root *root)
317
343
{
318
 
        if (!root->root.force_default_rule) {
 
344
        if (!root->root.set->force_default_rule) {
319
345
                /* FIXME: can't unlink(), because the limits would be lost. */
320
346
                return;
321
347
        }
349
375
        /* count mails from all storages */
350
376
        storages = array_get(&root->root.quota->storages, &count);
351
377
        for (i = 0; i < count; i++) {
 
378
                if (!quota_root_is_storage_visible(&root->root, storages[i]))
 
379
                        continue;
 
380
 
352
381
                if (maildirsize_recalculate_storage(root, storages[i]) < 0) {
353
382
                        ret = -1;
354
383
                        break;
358
387
        if (ret == 0) {
359
388
                /* check if any of the directories have changed */
360
389
                for (i = 0; i < count; i++) {
 
390
                        if (!quota_root_is_storage_visible(&root->root,
 
391
                                                           storages[i]))
 
392
                                continue;
 
393
 
361
394
                        ret = maildirs_check_have_changed(root, storages[i],
362
395
                                                root->recalc_last_stamp);
363
396
                        if (ret != 0)
406
439
static int maildirsize_parse(struct maildir_quota_root *root,
407
440
                             int fd, const char *const *lines)
408
441
{
409
 
        struct quota_rule *rule = &root->root.default_rule;
 
442
        struct quota_root *_root = &root->root;
410
443
        uint64_t message_bytes_limit, message_count_limit;
411
444
        long long bytes_diff, total_bytes;
412
445
        int count_diff, total_count;
425
458
        if (message_count_limit >= (1ULL << 63))
426
459
                message_count_limit = (1ULL << 63) - 1;
427
460
 
428
 
        if (rule->bytes_limit == (int64_t)message_bytes_limit &&
429
 
            rule->count_limit == (int64_t)message_count_limit) {
 
461
        if (root->root.bytes_limit == (int64_t)message_bytes_limit &&
 
462
            root->root.count_limit == (int64_t)message_count_limit) {
430
463
                /* limits haven't changed */
431
 
        } else if (root->root.force_default_rule) {
 
464
        } else if (root->root.set->force_default_rule) {
432
465
                /* we know the limits and they've changed.
433
466
                   the file must be rewritten. */
434
467
                return 0;
435
468
        } else {
436
469
                /* we're using limits from the file. */
437
 
                rule->bytes_limit = message_bytes_limit;
438
 
                rule->count_limit = message_count_limit;
439
 
                quota_root_recalculate_relative_rules(&root->root);
 
470
                root->root.bytes_limit = message_bytes_limit;
 
471
                root->root.count_limit = message_count_limit;
 
472
                quota_root_recalculate_relative_rules(root->root.set);
440
473
        }
441
474
 
442
475
        if (*lines == NULL) {
459
492
                return -1;
460
493
        }
461
494
 
462
 
        if ((total_bytes > rule->bytes_limit && rule->bytes_limit != 0) ||
463
 
            (total_count > rule->count_limit && rule->count_limit != 0)) {
 
495
        if ((total_bytes > _root->bytes_limit && _root->bytes_limit != 0) ||
 
496
            (total_count > _root->count_limit && _root->count_limit != 0)) {
464
497
                /* we're over quota. don't trust these values if the file
465
498
                   contains more than the initial summary line, or if the file
466
499
                   is older than 15 minutes. */
595
628
        return root->maildirsize_path != NULL;
596
629
}
597
630
 
598
 
static int maildirquota_refresh(struct maildir_quota_root *root)
 
631
static int maildirquota_read_limits(struct maildir_quota_root *root)
599
632
{
600
633
        int ret;
601
634
 
602
635
        if (!maildirquota_limits_init(root))
603
 
                return 0;
 
636
                return 1;
604
637
 
605
638
        T_BEGIN {
606
639
                ret = maildirsize_read(root);
607
640
        } T_END;
 
641
        return ret;
 
642
}
 
643
 
 
644
static int
 
645
maildirquota_refresh(struct maildir_quota_root *root, bool *recalculated_r)
 
646
{
 
647
        int ret;
 
648
 
 
649
        *recalculated_r = FALSE;
 
650
 
 
651
        ret = maildirquota_read_limits(root);
608
652
        if (ret == 0) {
609
 
                if (root->root.default_rule.bytes_limit == 0 &&
610
 
                    root->root.default_rule.count_limit == 0) {
 
653
                if (root->root.bytes_limit == 0 &&
 
654
                    root->root.count_limit == 0 &&
 
655
                    root->root.set->default_rule.bytes_limit == 0 &&
 
656
                    root->root.set->default_rule.count_limit == 0) {
611
657
                        /* no quota */
612
 
                        if (!root->root.force_default_rule)
 
658
                        if (!root->root.set->force_default_rule)
613
659
                                return 0;
614
660
                        /* explicitly specified 0 as quota. keep the quota
615
661
                           updated even if it's not enforced. */
616
662
                }
617
663
 
618
664
                ret = maildirsize_recalculate(root);
 
665
                if (ret == 0)
 
666
                        *recalculated_r = TRUE;
619
667
        }
620
668
        return ret < 0 ? -1 : 0;
621
669
}
657
705
        return &root->root;
658
706
}
659
707
 
 
708
static int maildir_quota_init(struct quota_root *_root, const char *args)
 
709
{
 
710
        const char *const *tmp;
 
711
 
 
712
        if (args == NULL)
 
713
                return 0;
 
714
 
 
715
        for (tmp = t_strsplit(args, ":"); *tmp != NULL; tmp++) {
 
716
                if (strcmp(*tmp, "noenforcing") == 0)
 
717
                        _root->no_enforcing = TRUE;
 
718
                else if (strncmp(*tmp, "ns=", 3) == 0)
 
719
                        _root->ns_prefix = p_strdup(_root->pool, *tmp + 3);
 
720
                else {
 
721
                        i_error("maildir quota: Invalid parameter: %s", *tmp);
 
722
                        return -1;
 
723
                }
 
724
        }
 
725
        return 0;
 
726
}
 
727
 
660
728
static void maildir_quota_deinit(struct quota_root *_root)
661
729
{
662
730
        struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
667
735
}
668
736
 
669
737
static bool
670
 
maildir_quota_parse_rule(struct quota_root *root ATTR_UNUSED,
 
738
maildir_quota_parse_rule(struct quota_root_settings *root_set ATTR_UNUSED,
671
739
                         struct quota_rule *rule,
672
740
                         const char *str, const char **error_r)
673
741
{
683
751
        return TRUE;
684
752
}
685
753
 
 
754
static int maildir_quota_init_limits(struct quota_root *_root)
 
755
{
 
756
        struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
 
757
 
 
758
        return maildirquota_read_limits(root) < 0 ? -1 : 0;
 
759
}
 
760
 
686
761
static void
687
762
maildir_quota_root_storage_added(struct quota_root *_root,
688
763
                                 struct mail_storage *storage)
710
785
 
711
786
        roots = array_get_modifiable(&quota->roots, &count);
712
787
        for (i = 0; i < count; i++) {
713
 
                if (roots[i]->backend.name == quota_backend_maildir.name)
 
788
                if (roots[i]->backend.name == quota_backend_maildir.name &&
 
789
                    ((roots[i]->ns_prefix == NULL &&
 
790
                      storage->ns->type == NAMESPACE_PRIVATE) ||
 
791
                     roots[i]->ns == storage->ns))
714
792
                        maildir_quota_root_storage_added(roots[i], storage);
715
793
        }
716
794
}
732
810
                           uint64_t *value_r)
733
811
{
734
812
        struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
 
813
        bool recalculated;
735
814
 
736
 
        if (maildirquota_refresh(root) < 0)
 
815
        if (maildirquota_refresh(root, &recalculated) < 0)
737
816
                return -1;
738
817
 
739
818
        if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0) {
749
828
maildir_quota_update(struct quota_root *_root,
750
829
                     struct quota_transaction_context *ctx)
751
830
{
752
 
        struct maildir_quota_root *root =
753
 
                (struct maildir_quota_root *) _root;
 
831
        struct maildir_quota_root *root = (struct maildir_quota_root *)_root;
 
832
        bool recalculated;
754
833
 
755
834
        if (!maildirquota_limits_init(root)) {
756
835
                /* no limits */
761
840
           we do want to make sure the header gets updated if the limits have
762
841
           changed. also this makes sure the maildirsize file is created if
763
842
           it doesn't exist. */
764
 
        if (maildirquota_refresh(root) < 0)
 
843
        if (maildirquota_refresh(root, &recalculated) < 0)
765
844
                return -1;
766
845
 
767
 
        if (root->fd == -1 || ctx->recalculate ||
768
 
            maildirsize_update(root, ctx->count_used, ctx->bytes_used) < 0)
 
846
        if (recalculated) {
 
847
                /* quota was just recalculated and it already contains the changes
 
848
                   we wanted to do. */
 
849
        } else if (root->fd == -1 || ctx->recalculate)
 
850
                maildirsize_rebuild_later(root);
 
851
        else if (maildirsize_update(root, ctx->count_used, ctx->bytes_used) < 0)
769
852
                maildirsize_rebuild_later(root);
770
853
 
771
854
        return 0;
776
859
 
777
860
        {
778
861
                maildir_quota_alloc,
779
 
                NULL,
 
862
                maildir_quota_init,
780
863
                maildir_quota_deinit,
781
864
                maildir_quota_parse_rule,
 
865
                maildir_quota_init_limits,
782
866
                maildir_quota_storage_added,
783
867
                maildir_quota_root_get_resources,
784
868
                maildir_quota_get_resource,
785
 
                maildir_quota_update
 
869
                maildir_quota_update,
 
870
                NULL
786
871
        }
787
872
};