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

« back to all changes in this revision

Viewing changes to src/plugins/mail-log/mail-log-plugin.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:
4
4
#include "array.h"
5
5
#include "str.h"
6
6
#include "str-sanitize.h"
 
7
#include "imap-util.h"
7
8
#include "mail-storage-private.h"
8
9
#include "mailbox-list-private.h"
9
10
#include "mail-log-plugin.h"
11
12
#include <stdlib.h>
12
13
 
13
14
#define MAILBOX_NAME_LOG_LEN 64
14
 
#define MSGID_LOG_LEN 80
 
15
#define HEADER_LOG_LEN 80
15
16
 
16
17
#define MAIL_LOG_CONTEXT(obj) \
17
18
        MODULE_CONTEXT(obj, mail_log_storage_module)
25
26
        MAIL_LOG_FIELD_BOX      = 0x02,
26
27
        MAIL_LOG_FIELD_MSGID    = 0x04,
27
28
        MAIL_LOG_FIELD_PSIZE    = 0x08,
28
 
        MAIL_LOG_FIELD_VSIZE    = 0x10
 
29
        MAIL_LOG_FIELD_VSIZE    = 0x10,
 
30
        MAIL_LOG_FIELD_FLAGS    = 0x20,
 
31
        MAIL_LOG_FIELD_FROM     = 0x40,
 
32
        MAIL_LOG_FIELD_SUBJECT  = 0x80
29
33
};
30
34
#define MAIL_LOG_DEFAULT_FIELDS \
31
35
        (MAIL_LOG_FIELD_UID | MAIL_LOG_FIELD_BOX | \
38
42
        MAIL_LOG_EVENT_COPY             = 0x08,
39
43
        MAIL_LOG_EVENT_MAILBOX_DELETE   = 0x10,
40
44
        MAIL_LOG_EVENT_MAILBOX_RENAME   = 0x20,
41
 
 
42
 
        MAIL_LOG_EVENT_MASK_ALL         = 0x1f
 
45
        MAIL_LOG_EVENT_FLAG_CHANGE      = 0x40,
 
46
        MAIL_LOG_EVENT_APPEND           = 0x80
43
47
};
44
 
#define MAIL_LOG_DEFAULT_EVENTS MAIL_LOG_EVENT_MASK_ALL
 
48
#define MAIL_LOG_DEFAULT_EVENTS \
 
49
        (MAIL_LOG_EVENT_DELETE | MAIL_LOG_EVENT_UNDELETE | \
 
50
         MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY | \
 
51
         MAIL_LOG_EVENT_MAILBOX_DELETE | MAIL_LOG_EVENT_MAILBOX_RENAME)
45
52
 
46
53
static const char *field_names[] = {
47
54
        "uid",
49
56
        "msgid",
50
57
        "size",
51
58
        "vsize",
 
59
        "flags",
 
60
        "from",
 
61
        "subject",
52
62
        NULL
53
63
};
54
64
 
58
68
        "expunge",
59
69
        "copy",
60
70
        "mailbox_delete",
 
71
        "mailbox_rename",
 
72
        "flag_change",
 
73
        "append",
61
74
        NULL
62
75
};
63
76
 
79
92
struct mail_log_transaction_context {
80
93
        union mailbox_transaction_module_context module_ctx;
81
94
        pool_t pool;
 
95
        struct mail *tmp_mail;
82
96
 
83
97
        ARRAY_DEFINE(group_changes, struct mail_log_group_changes);
84
98
 
255
269
        }
256
270
}
257
271
 
 
272
static void mail_log_add_hdr(struct mail *mail, string_t *str,
 
273
                             const char *name, const char *header)
 
274
{
 
275
        const char *value;
 
276
 
 
277
        if (mail_get_first_header(mail, header, &value) <= 0)
 
278
                value = "";
 
279
        str_printfa(str, "%s=%s, ", name, str_sanitize(value, HEADER_LOG_LEN));
 
280
}
 
281
 
258
282
static void mail_log_action(struct mailbox_transaction_context *dest_trans,
259
283
                            struct mail *mail, enum mail_log_event event,
260
284
                            const char *data)
261
285
{
262
286
        struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(dest_trans);
263
 
        const char *msgid;
264
287
        uoff_t size;
265
288
        string_t *str;
266
 
        pool_t pool;
267
289
 
268
290
        if ((mail_log_set.events & event) == 0)
269
291
                return;
270
292
 
271
 
        if (lt == NULL) {
272
 
                pool = pool_alloconly_create("mail log transaction", 1024);
273
 
                lt = p_new(pool, struct mail_log_transaction_context, 1);
274
 
                lt->pool = pool;
275
 
                MODULE_CONTEXT_SET(dest_trans, mail_log_storage_module, lt);
276
 
        }
277
293
        lt->changes++;
278
294
 
279
295
        if (mail_log_set.group_events) {
284
300
        str = t_str_new(128);
285
301
        str_printfa(str, "%s: ", mail_log_event_get_name(event));
286
302
 
287
 
        if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0)
 
303
        if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 && mail->uid != 0)
288
304
                str_printfa(str, "uid=%u, ", mail->uid);
289
305
 
290
306
        if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
291
307
                mail_log_append_mailbox_name(str, mail->box);
292
 
 
 
308
        if ((mail_log_set.fields & MAIL_LOG_FIELD_FLAGS) != 0) {
 
309
                str_printfa(str, "flags=(");
 
310
                imap_write_flags(str, mail_get_flags(mail),
 
311
                                 mail_get_keywords(mail));
 
312
                str_append(str, "), ");
 
313
        }
293
314
        if (event == MAIL_LOG_EVENT_COPY)
294
315
                str_printfa(str, "dest=%s, ", data);
295
316
 
296
 
        if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0) {
297
 
                if (mail_get_first_header(mail, "Message-ID", &msgid) <= 0)
298
 
                        msgid = "(null)";
299
 
                str_printfa(str, "msgid=%s, ",
300
 
                            str_sanitize(msgid, MSGID_LOG_LEN));
301
 
        }
 
317
        if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0)
 
318
                mail_log_add_hdr(mail, str, "msgid", "Message-ID");
 
319
        if ((mail_log_set.fields & MAIL_LOG_FIELD_FROM) != 0)
 
320
                mail_log_add_hdr(mail, str, "from", "From");
 
321
        if ((mail_log_set.fields & MAIL_LOG_FIELD_SUBJECT) != 0)
 
322
                mail_log_add_hdr(mail, str, "subject", "Subject");
302
323
 
303
324
        if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
304
325
            (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
350
371
                new_flags = flags;
351
372
                break;
352
373
        }
353
 
        if (((old_flags ^ new_flags) & MAIL_DELETED) == 0)
354
 
                return;
355
374
 
356
 
        T_BEGIN {
 
375
        if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) T_BEGIN {
357
376
                mail_log_action(_mail->transaction, _mail,
358
377
                                (new_flags & MAIL_DELETED) != 0 ?
359
378
                                MAIL_LOG_EVENT_DELETE :
360
379
                                MAIL_LOG_EVENT_UNDELETE, NULL);
361
380
        } T_END;
 
381
 
 
382
        if ((old_flags & ~MAIL_DELETED) != (new_flags & ~MAIL_DELETED)) {
 
383
                mail_log_action(_mail->transaction, _mail,
 
384
                                MAIL_LOG_EVENT_FLAG_CHANGE, NULL);
 
385
        }
 
386
}
 
387
 
 
388
static void
 
389
mail_log_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
 
390
                              struct mail_keywords *keywords)
 
391
{
 
392
        struct mail_private *mail = (struct mail_private *)_mail;
 
393
        union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
 
394
        const char *const *old_keywords, *const *new_keywords;
 
395
        unsigned int i;
 
396
 
 
397
        old_keywords = mail_get_keywords(_mail);
 
398
        lmail->super.update_keywords(_mail, modify_type, keywords);
 
399
        new_keywords = mail_get_keywords(_mail);
 
400
 
 
401
        for (i = 0; old_keywords[i] != NULL && new_keywords[i] != NULL; i++) {
 
402
                if (strcmp(old_keywords[i], new_keywords[i]) != 0)
 
403
                        break;
 
404
        }
 
405
 
 
406
        if (old_keywords[i] != NULL || new_keywords[i] != NULL) {
 
407
                mail_log_action(_mail->transaction, _mail,
 
408
                                MAIL_LOG_EVENT_FLAG_CHANGE, NULL);
 
409
        }
362
410
}
363
411
 
364
412
static struct mail *
378
426
        lmail->super = mail->v;
379
427
 
380
428
        mail->v.update_flags = mail_log_mail_update_flags;
 
429
        mail->v.update_keywords = mail_log_mail_update_keywords;
381
430
        mail->v.expunge = mail_log_mail_expunge;
382
431
        MODULE_CONTEXT_SET_SELF(mail, mail_log_mail_module, lmail);
383
432
        return _mail;
384
433
}
385
434
 
386
435
static int
387
 
mail_log_copy(struct mailbox_transaction_context *t, struct mail *mail,
388
 
              enum mail_flags flags, struct mail_keywords *keywords,
389
 
              struct mail *dest_mail)
 
436
mail_log_copy(struct mail_save_context *ctx, struct mail *mail)
390
437
{
391
 
        union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
 
438
        union mailbox_module_context *lbox =
 
439
                MAIL_LOG_CONTEXT(ctx->transaction->box);
392
440
        const char *name;
393
441
 
394
 
        if (lbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
 
442
        if (lbox->super.copy(ctx, mail) < 0)
395
443
                return -1;
396
444
 
397
445
        T_BEGIN {
398
 
                name = str_sanitize(mailbox_get_name(t->box),
 
446
                name = str_sanitize(mailbox_get_name(ctx->transaction->box),
399
447
                                    MAILBOX_NAME_LOG_LEN);
400
 
                mail_log_action(t, mail, MAIL_LOG_EVENT_COPY, name);
401
 
        } T_END;
402
 
        return 0;
 
448
                mail_log_action(ctx->transaction, mail,
 
449
                                MAIL_LOG_EVENT_COPY, name);
 
450
        } T_END;
 
451
        return 0;
 
452
}
 
453
 
 
454
static int
 
455
mail_log_save_begin(struct mail_save_context *ctx, struct istream *input)
 
456
{
 
457
        struct mail_log_transaction_context *lt =
 
458
                MAIL_LOG_CONTEXT(ctx->transaction);
 
459
        union mailbox_module_context *lbox =
 
460
                MAIL_LOG_CONTEXT(ctx->transaction->box);
 
461
 
 
462
        if (ctx->dest_mail == NULL) {
 
463
                if (lt->tmp_mail == NULL)
 
464
                        lt->tmp_mail = mail_alloc(ctx->transaction, 0, NULL);
 
465
                ctx->dest_mail = lt->tmp_mail;
 
466
        }
 
467
 
 
468
        return lbox->super.save_begin(ctx, input);
 
469
}
 
470
 
 
471
static int mail_log_save_finish(struct mail_save_context *ctx)
 
472
{
 
473
        union mailbox_module_context *lbox =
 
474
                MAIL_LOG_CONTEXT(ctx->transaction->box);
 
475
 
 
476
        if (lbox->super.save_finish(ctx) < 0)
 
477
                return -1;
 
478
 
 
479
        T_BEGIN {
 
480
                mail_log_action(ctx->transaction, ctx->dest_mail,
 
481
                                MAIL_LOG_EVENT_APPEND, NULL);
 
482
        } T_END;
 
483
        return 0;
 
484
}
 
485
 
 
486
static struct mailbox_transaction_context *
 
487
mail_log_transaction_begin(struct mailbox *box,
 
488
                           enum mailbox_transaction_flags flags)
 
489
{
 
490
        union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(box);
 
491
        struct mailbox_transaction_context *t;
 
492
        struct mail_log_transaction_context *lt;
 
493
        pool_t pool;
 
494
 
 
495
        t = lbox->super.transaction_begin(box, flags);
 
496
 
 
497
        pool = pool_alloconly_create("mail log transaction", 1024);
 
498
        lt = p_new(pool, struct mail_log_transaction_context, 1);
 
499
        lt->pool = pool;
 
500
        MODULE_CONTEXT_SET(t, mail_log_storage_module, lt);
 
501
        return t;
403
502
}
404
503
 
405
504
static int
411
510
        struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
412
511
        union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
413
512
 
414
 
        if (lt != NULL) {
415
 
                if (lt->changes > 0 && mail_log_set.group_events)
416
 
                        mail_log_group_changes(t->box, lt);
417
 
                pool_unref(&lt->pool);
418
 
        }
 
513
        if (lt->changes > 0 && mail_log_set.group_events)
 
514
                mail_log_group_changes(t->box, lt);
 
515
        if (lt->tmp_mail != NULL)
 
516
                mail_free(&lt->tmp_mail);
 
517
        pool_unref(&lt->pool);
419
518
 
420
519
        return lbox->super.transaction_commit(t, uid_validity_r,
421
520
                                              first_saved_uid_r,
428
527
        struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
429
528
        union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
430
529
 
431
 
        if (lt != NULL) {
432
 
                if (lt->changes > 0 && !mail_log_set.group_events) {
433
 
                        i_info("Transaction rolled back: "
434
 
                               "Ignore last %u changes", lt->changes);
435
 
                }
436
 
                pool_unref(&lt->pool);
 
530
        if (lt->changes > 0 && !mail_log_set.group_events) {
 
531
                i_info("Transaction rolled back: "
 
532
                       "Ignore last %u changes", lt->changes);
437
533
        }
 
534
        if (lt->tmp_mail != NULL)
 
535
                mail_free(&lt->tmp_mail);
 
536
        pool_unref(&lt->pool);
438
537
 
439
538
        lbox->super.transaction_rollback(t);
440
539
}
456
555
 
457
556
        box->v.mail_alloc = mail_log_mail_alloc;
458
557
        box->v.copy = mail_log_copy;
 
558
        box->v.save_begin = mail_log_save_begin;
 
559
        box->v.save_finish = mail_log_save_finish;
 
560
        box->v.transaction_begin = mail_log_transaction_begin;
459
561
        box->v.transaction_commit = mail_log_transaction_commit;
460
562
        box->v.transaction_rollback = mail_log_transaction_rollback;
461
563
        MODULE_CONTEXT_SET_SELF(box, mail_log_storage_module, lbox);