~ubuntu-dev/ubuntu/lucid/dovecot/lucid-201002101901

« back to all changes in this revision

Viewing changes to libsieve/src/lib-sieve-tool/mail-raw.c

  • Committer: Chuck Short
  • Date: 2010-01-21 20:21:25 UTC
  • mfrom: (4.1.11 squeeze)
  • Revision ID: zulcss@ubuntu.com-20100121202125-pme73o491kfwj5nc
* 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 restriction
    - 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 config
    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.
    - 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.
   + Add SMTP-AUTH support for Outlook (login auth mechanism)
* New upstream release.
* debian/patches/gold-fix.patch: Removed. Fixed upstream.
* Moved libexec to lib corrections in dovecot-managesieve.patch and
  dovecot-managesieve-dist.patch to dovecot-example.patch
* debian/patches/dovecot-mboxlocking.patch: Regenerated to avoid FTBFS
  when quilt isn't installed.
* debian/patches/quota-mountpoint.patch: Removed. Not needed anymore.
* debian/patches/dovecot-quota.patch: Removed. Quotas aren't properly
  enabled unless mail_plugins = quota imap_quota.
* debian/patches/gold-fix.patch: Fixed configure script to build even
  with binutils-gold or --no-add-needed linker flag (Closes: #554306)
* debian/dovecot-common.init: fixed LSB headers. Thanks to Pascal Volk.
  (Closes: #558040)
* debian/changelog: added CVE references to previous changelog entry.
* debian/rules: checked up the build system. It's not fragile anymore.
  (Closes: 493803)
* debian/dovecot-common.postinst: Now invoking dpkg-reconfigure
  on dovecot-common is enough to generate new certificates
  if the previous ones were removed. (Closes: #545582)
* debian/rules: No longer install convert-tool in /usr/bin.
  It isn't an user utility and it should stay in /usr/lib/dovecot
  like all other similar tool.
* New upstream release. (Closes: #557601)
* [SECURITY] Fixes local information disclosure and denial of service.
  (see: http://www.dovecot.org/list/dovecot-news/2009-November/000143.html
  and CVE-2009-3897)
* Added myself to uploaders.
* Switched to the new source format "3.0 (quilt)":
  - removed dpatch from build-depends
  - removed debian/README.source because now we use only standard
    dpkg features
  - regenerated all patches
* Prepared to switch to multi-origin source:
  - recreated dovecot-libsieve.patch and dovecot-managesieve-dist.patch
    starting from the upstream tarball
  - removed all autotools related build-depends and build-conflict
  - renamed dovecot-libsieve and dovecot-managesieve directories
    to libsieve and managesieve.
* debian/rules: Moved the configuration of libsieve and managesieve from
  the build phase to the configuration phase
* Added dovecot-dbg package  with debugging symbols.  Thanks Stephan Bosch.
  (Closes: #554710)
* Fixed some stray libexec'isms in the default configuration.
* New upstream release.
* debian/dovecot-common.init:
  - use $CONF when starting the daemon. (Closes: #549944)
  - always output start/stop messages. (Closes: #523810)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
 
2
 */
 
3
 
 
4
/* FIXME: This file was gratefully stolen from dovecot/src/deliver/deliver.c and 
 
5
 * altered to suit our needs. So, this contains lots and lots of duplicated 
 
6
 * code. 
 
7
 */
 
8
 
 
9
#include "lib.h"
 
10
#include "istream.h"
 
11
#include "istream-seekable.h"
 
12
#include "fd-set-nonblock.h"
 
13
#include "str.h"
 
14
#include "str-sanitize.h"
 
15
#include "strescape.h"
 
16
#include "safe-mkstemp.h"
 
17
#include "close-keep-errno.h"
 
18
#include "mkdir-parents.h"
 
19
#include "message-address.h"
 
20
#include "mbox-from.h"
 
21
#include "raw-storage.h"
 
22
#include "mail-namespace.h"
 
23
 
 
24
#include "mail-raw.h"
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <unistd.h>
 
29
#include <fcntl.h>
 
30
#include <pwd.h>
 
31
 
 
32
/*
 
33
 * Configuration
 
34
 */
 
35
 
 
36
#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON"
 
37
 
 
38
/* After buffer grows larger than this, create a temporary file to /tmp
 
39
   where to read the mail. */
 
40
#define MAIL_MAX_MEMORY_BUFFER (1024*128)
 
41
 
 
42
static const char *wanted_headers[] = {
 
43
        "From", "Message-ID", "Subject", "Return-Path",
 
44
        NULL
 
45
};
 
46
 
 
47
/*
 
48
 * Global data
 
49
 */
 
50
 
 
51
static struct mail_namespace *raw_ns;
 
52
static struct mail_user *raw_mail_user;
 
53
 
 
54
/*
 
55
 * Raw mail implementation
 
56
 */
 
57
 
 
58
static int seekable_fd_callback
 
59
(const char **path_r, void *context ATTR_UNUSED)
 
60
{
 
61
        const char *dir, *p;
 
62
        string_t *path;
 
63
        int fd;
 
64
 
 
65
        path = t_str_new(128);
 
66
        str_append(path, "/tmp/dovecot.sieve-tool.");
 
67
        fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
 
68
        if (fd == -1 && errno == ENOENT) {
 
69
                dir = str_c(path);
 
70
                p = strrchr(dir, '/');
 
71
                if (p != NULL) {
 
72
                        dir = t_strdup_until(dir, p);
 
73
                        if ( mkdir_parents(dir, 0600) < 0 ) {
 
74
                                i_error("mkdir_parents(%s) failed: %m", dir);
 
75
                                return -1;
 
76
                        }
 
77
                        fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
 
78
                }
 
79
        }
 
80
 
 
81
        if (fd == -1) {
 
82
                i_error("safe_mkstemp(%s) failed: %m", str_c(path));
 
83
                return -1;
 
84
        }
 
85
 
 
86
        /* we just want the fd, unlink it */
 
87
        if (unlink(str_c(path)) < 0) {
 
88
                /* shouldn't happen.. */
 
89
                i_error("unlink(%s) failed: %m", str_c(path));
 
90
                close_keep_errno(fd);
 
91
                return -1;
 
92
        }
 
93
 
 
94
        *path_r = str_c(path);
 
95
        return fd;
 
96
}
 
97
 
 
98
static struct istream *create_raw_stream
 
99
(int fd, time_t *mtime_r, const char **sender)
 
100
{
 
101
        struct istream *input, *input2, *input_list[2];
 
102
        const unsigned char *data;
 
103
        size_t i, size;
 
104
        int ret, tz;
 
105
        char *env_sender;
 
106
 
 
107
        *mtime_r = (time_t)-1;
 
108
        fd_set_nonblock(fd, FALSE);
 
109
 
 
110
        input = i_stream_create_fd(fd, 4096, FALSE);
 
111
        input->blocking = TRUE;
 
112
        /* If input begins with a From-line, drop it */
 
113
        ret = i_stream_read_data(input, &data, &size, 5);
 
114
        if (ret > 0 && size >= 5 && memcmp(data, "From ", 5) == 0) {
 
115
                /* skip until the first LF */
 
116
                i_stream_skip(input, 5);
 
117
                while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
 
118
                        for (i = 0; i < size; i++) {
 
119
                                if (data[i] == '\n')
 
120
                                        break;
 
121
                        }
 
122
                        if (i != size) {
 
123
                                (void)mbox_from_parse(data, i, mtime_r, &tz, &env_sender);
 
124
                                i_stream_skip(input, i + 1);
 
125
                                break;
 
126
                        }
 
127
                        i_stream_skip(input, size);
 
128
                }
 
129
        }
 
130
 
 
131
        if (sender != NULL) {
 
132
                *sender = t_strdup(env_sender);
 
133
        }
 
134
        i_free(env_sender);
 
135
 
 
136
        if (input->v_offset == 0) {
 
137
                input2 = input;
 
138
                i_stream_ref(input2);
 
139
        } else {
 
140
                input2 = i_stream_create_limit(input, (uoff_t)-1);
 
141
        }
 
142
        i_stream_unref(&input);
 
143
 
 
144
    input_list[0] = input2; input_list[1] = NULL;
 
145
    input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER,
 
146
                     seekable_fd_callback, raw_mail_user);
 
147
    i_stream_unref(&input2);
 
148
    return input;
 
149
 
 
150
}
 
151
 
 
152
/*
 
153
 * Init/Deinit
 
154
 */
 
155
 
 
156
void mail_raw_init(const char *user) 
 
157
{
 
158
        const char *error;
 
159
 
 
160
        raw_mail_user = mail_user_init(user);
 
161
        mail_user_set_home(raw_mail_user, NULL);
 
162
        raw_ns = mail_namespaces_init_empty(raw_mail_user);
 
163
        raw_ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
 
164
        
 
165
        if ( mail_storage_create(raw_ns, "raw", "/tmp",
 
166
                MAIL_STORAGE_FLAG_FULL_FS_ACCESS,
 
167
                FILE_LOCK_METHOD_FCNTL, &error) < 0 ) {
 
168
                i_fatal("Couldn't create internal raw storage: %s", error);
 
169
        }
 
170
}
 
171
 
 
172
void mail_raw_deinit(void)
 
173
{
 
174
        mail_user_unref(&raw_mail_user);
 
175
}
 
176
 
 
177
 
 
178
/*
 
179
 * Open raw mail data
 
180
 */
 
181
 
 
182
static struct mail_raw *mail_raw_create
 
183
(struct istream *input, const char *mailfile, const char *sender,
 
184
        time_t mtime)
 
185
{
 
186
        pool_t pool;
 
187
        struct raw_mailbox *raw_box;
 
188
        struct mail_raw *mailr;
 
189
        enum mail_error error;
 
190
 
 
191
        if ( mailfile != NULL ) {
 
192
                if ( *mailfile != '/') {
 
193
                        char cwd[PATH_MAX];
 
194
 
 
195
                        /* Expand relative paths */
 
196
                        if (getcwd(cwd, sizeof(cwd)) == NULL)
 
197
                                i_fatal("getcwd() failed: %m");
 
198
 
 
199
                        mailfile = t_strconcat(cwd, "/", mailfile, NULL);               
 
200
                } 
 
201
        }
 
202
 
 
203
        pool = pool_alloconly_create("mail_raw", 1024);
 
204
        mailr = p_new(pool, struct mail_raw, 1);
 
205
        mailr->pool = pool;
 
206
 
 
207
        if ( mailfile == NULL ) {
 
208
                mailr->box = mailbox_open(&raw_ns->storage, "Dovecot Raw Mail",
 
209
                                   input, MAILBOX_OPEN_NO_INDEX_FILES);
 
210
        } else {
 
211
                mtime = (time_t)-1;
 
212
                mailr->box = mailbox_open(&raw_ns->storage, mailfile, NULL,
 
213
                                   MAILBOX_OPEN_NO_INDEX_FILES);
 
214
        }
 
215
 
 
216
        if ( mailr->box == NULL ) {
 
217
                i_fatal("Can't open mail stream as raw: %s",
 
218
                        mail_storage_get_last_error(raw_ns->storage, &error));
 
219
        }
 
220
 
 
221
        if ( mailbox_sync(mailr->box, 0, 0, NULL ) < 0) {
 
222
                enum mail_error error;
 
223
 
 
224
                i_fatal("Can't sync delivery mail: %s",
 
225
                        mail_storage_get_last_error(raw_ns->storage, &error));
 
226
        }
 
227
 
 
228
        raw_box = (struct raw_mailbox *)mailr->box;
 
229
        raw_box->envelope_sender = sender != NULL ? sender : DEFAULT_ENVELOPE_SENDER;
 
230
        raw_box->mtime = mtime;
 
231
 
 
232
        mailr->trans = mailbox_transaction_begin(mailr->box, 0);
 
233
        mailr->headers_ctx = mailbox_header_lookup_init(mailr->box, wanted_headers);
 
234
        mailr->mail = mail_alloc(mailr->trans, 0, mailr->headers_ctx);
 
235
        mail_set_seq(mailr->mail, 1);
 
236
 
 
237
        return mailr;
 
238
}
 
239
 
 
240
struct mail_raw *mail_raw_open_data(string_t *mail_data)
 
241
{
 
242
        struct mail_raw *mailr;
 
243
        struct istream *input;
 
244
 
 
245
        input = i_stream_create_from_data(str_data(mail_data), str_len(mail_data));
 
246
        
 
247
        mailr = mail_raw_create(input, NULL, NULL, (time_t)-1);
 
248
 
 
249
        i_stream_unref(&input);
 
250
 
 
251
        return mailr;
 
252
}
 
253
        
 
254
struct mail_raw *mail_raw_open_file(const char *path)
 
255
{
 
256
        struct mail_raw *mailr;
 
257
        struct istream *input = NULL;
 
258
        time_t mtime;
 
259
        const char *sender = NULL;
 
260
        
 
261
        if ( path == NULL || strcmp(path, "-") == 0 ) {
 
262
                path = NULL;
 
263
                input = create_raw_stream(0, &mtime, &sender);
 
264
        }
 
265
 
 
266
        mailr = mail_raw_create(input, path, sender, mtime);
 
267
 
 
268
        if ( input != NULL )
 
269
                i_stream_unref(&input);
 
270
 
 
271
        return mailr;
 
272
}
 
273
 
 
274
void mail_raw_close(struct mail_raw *mailr) 
 
275
{
 
276
        mailbox_header_lookup_unref(&mailr->headers_ctx);
 
277
 
 
278
        mail_free(&mailr->mail);
 
279
        mailbox_transaction_rollback(&mailr->trans);
 
280
        mailbox_close(&mailr->box);
 
281
 
 
282
        pool_unref(&mailr->pool);
 
283
}
 
284