~ubuntu-branches/ubuntu/trusty/dovecot/trusty-updates

« back to all changes in this revision

Viewing changes to src/doveadm/client-connection.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (1.15.3) (96.1.1 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20140108093549-814nkqdcxfbvgktg
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) 2010-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
 
4
#include "lib-signals.h"
4
5
#include "base64.h"
5
6
#include "ioloop.h"
6
7
#include "istream.h"
7
8
#include "ostream.h"
8
9
#include "strescape.h"
9
10
#include "settings-parser.h"
 
11
#include "iostream-ssl.h"
10
12
#include "master-service.h"
 
13
#include "master-service-ssl.h"
11
14
#include "master-service-settings.h"
12
15
#include "mail-storage-service.h"
13
16
#include "doveadm-util.h"
19
22
 
20
23
#include <unistd.h>
21
24
 
22
 
#define MAX_INBUF_SIZE 1024
23
 
 
24
 
struct client_connection {
25
 
        pool_t pool;
26
 
 
27
 
        int fd;
28
 
        struct io *io;
29
 
        struct istream *input;
30
 
        struct ostream *output;
31
 
        struct ip_addr local_ip, remote_ip;
32
 
        const struct doveadm_settings *set;
33
 
 
34
 
        unsigned int handshaked:1;
35
 
        unsigned int authenticated:1;
36
 
};
 
25
#define MAX_INBUF_SIZE (1024*1024)
 
26
 
 
27
static void client_connection_input(struct client_connection *conn);
37
28
 
38
29
static struct doveadm_mail_cmd_context *
39
30
doveadm_mail_cmd_server_parse(const char *cmd_name,
55
46
 
56
47
        ctx = doveadm_mail_cmd_init(cmd, set);
57
48
        ctx->full_args = (const void *)(argv + 1);
 
49
        ctx->proxying = TRUE;
58
50
 
59
51
        ctx->service_flags |=
60
52
                MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT |
83
75
                                        "Client sent unknown parameter: %c",
84
76
                                        cmd->name, c);
85
77
                                ctx->v.deinit(ctx);
 
78
                                pool_unref(&ctx->pool);
86
79
                                return NULL;
87
80
                        }
88
81
                }
95
88
                i_error("doveadm %s: Client sent unknown parameter: %s",
96
89
                        cmd->name, argv[0]);
97
90
                ctx->v.deinit(ctx);
 
91
                pool_unref(&ctx->pool);
98
92
                return NULL;
99
93
        }
100
94
        ctx->args = (const void *)argv;
114
108
                            const struct mail_storage_service_input *input)
115
109
{
116
110
        const char *error;
 
111
        struct ioloop *ioloop, *prev_ioloop = current_ioloop;
117
112
        int ret;
118
113
 
 
114
        ctx->conn = conn;
 
115
 
 
116
        /* some commands will want to call io_loop_run(), but we're already
 
117
           running one and we can't call the original one recursively, so
 
118
           create a new ioloop. */
 
119
        ioloop = io_loop_create();
 
120
        lib_signals_reset_ioloop();
119
121
        if (ctx->v.preinit != NULL)
120
122
                ctx->v.preinit(ctx);
121
123
 
125
127
        doveadm_print_flush();
126
128
        mail_storage_service_deinit(&ctx->storage_service);
127
129
 
 
130
        io_loop_set_current(prev_ioloop);
 
131
        lib_signals_reset_ioloop();
 
132
        o_stream_switch_ioloop(conn->output);
 
133
        io_loop_set_current(ioloop);
 
134
        io_loop_destroy(&ioloop);
 
135
 
128
136
        if (ret < 0) {
129
137
                i_error("%s: %s", ctx->cmd->name, error);
130
 
                o_stream_send(conn->output, "\n-\n", 3);
 
138
                o_stream_nsend(conn->output, "\n-\n", 3);
131
139
        } else if (ret == 0) {
132
 
                o_stream_send_str(conn->output, "\n-NOUSER\n");
 
140
                o_stream_nsend_str(conn->output, "\n-NOUSER\n");
133
141
        } else if (ctx->exit_code != 0) {
134
142
                /* maybe not an error, but not a full success either */
135
 
                o_stream_send(conn->output, "\n-\n", 3);
 
143
                o_stream_nsend_str(conn->output,
 
144
                                   t_strdup_printf("\n-%u\n", ctx->exit_code));
136
145
        } else {
137
 
                o_stream_send(conn->output, "\n+\n", 3);
 
146
                o_stream_nsend(conn->output, "\n+\n", 3);
138
147
        }
139
148
        pool_unref(&ctx->pool);
 
149
 
 
150
        /* clear all headers */
 
151
        doveadm_print_deinit();
 
152
        doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
140
153
}
141
154
 
142
155
static bool client_is_allowed_command(const struct doveadm_settings *set,
169
182
 
170
183
        memset(&input, 0, sizeof(input));
171
184
        input.service = "doveadm";
 
185
        input.local_ip = conn->local_ip;
 
186
        input.remote_ip = conn->remote_ip;
 
187
        input.local_port = conn->local_port;
 
188
        input.remote_port = conn->remote_port;
172
189
 
173
190
        for (argc = 0; args[argc] != NULL; argc++)
174
191
                args[argc] = str_tabunescape(args[argc]);
211
228
        o_stream_cork(conn->output);
212
229
        ctx = doveadm_mail_cmd_server_parse(cmd_name, conn->set, &input, argc, args);
213
230
        if (ctx == NULL)
214
 
                o_stream_send(conn->output, "\n-\n", 3);
 
231
                o_stream_nsend(conn->output, "\n-\n", 3);
215
232
        else
216
233
                doveadm_mail_cmd_server_run(conn, ctx, &input);
217
234
        o_stream_uncork(conn->output);
231
248
        const unsigned char *data;
232
249
        size_t size;
233
250
 
234
 
        if ((line = i_stream_read_next_line(conn->input)) == NULL)
 
251
        if ((line = i_stream_read_next_line(conn->input)) == NULL) {
 
252
                if (conn->input->eof)
 
253
                        return -1;
235
254
                return 0;
 
255
        }
236
256
 
237
257
        if (*conn->set->doveadm_password == '\0') {
238
258
                i_error("doveadm_password not set, "
243
263
        /* FIXME: some day we should probably let auth process do this and
244
264
           support all kinds of authentication */
245
265
        if (strncmp(line, "PLAIN\t", 6) != 0) {
246
 
                i_error("doveadm client attempted non-PLAIN authentication");
 
266
                i_error("doveadm client attempted non-PLAIN authentication: %s", line);
247
267
                return -1;
248
268
        }
249
269
 
268
288
        return 1;
269
289
}
270
290
 
 
291
static void client_log_disconnect_error(struct client_connection *conn)
 
292
{
 
293
        const char *error;
 
294
 
 
295
        error = conn->ssl_iostream == NULL ? NULL :
 
296
                ssl_iostream_get_last_error(conn->ssl_iostream);
 
297
        if (error == NULL) {
 
298
                error = conn->input->stream_errno == 0 ? "EOF" :
 
299
                        strerror(conn->input->stream_errno);
 
300
        }
 
301
        i_error("doveadm client disconnected before handshake: %s", error);
 
302
}
 
303
 
271
304
static void client_connection_input(struct client_connection *conn)
272
305
{
273
306
        const char *line;
276
309
 
277
310
        if (!conn->handshaked) {
278
311
                if ((line = i_stream_read_next_line(conn->input)) == NULL) {
279
 
                        if (conn->input->eof || conn->input->stream_errno != 0)
 
312
                        if (conn->input->eof || conn->input->stream_errno != 0) {
 
313
                                client_log_disconnect_error(conn);
280
314
                                client_connection_destroy(&conn);
 
315
                        }
281
316
                        return;
282
317
                }
283
318
 
293
328
        if (!conn->authenticated) {
294
329
                if ((ret = client_connection_authenticate(conn)) <= 0) {
295
330
                        if (ret < 0) {
296
 
                                o_stream_send(conn->output, "-\n", 2);
 
331
                                o_stream_nsend(conn->output, "-\n", 2);
297
332
                                client_connection_destroy(&conn);
298
333
                        }
299
334
                        return;
300
335
                }
301
 
                o_stream_send(conn->output, "+\n", 2);
 
336
                o_stream_nsend(conn->output, "+\n", 2);
302
337
                conn->authenticated = TRUE;
303
338
        }
304
339
 
305
 
        while (ok && (line = i_stream_read_next_line(conn->input)) != NULL) {
 
340
        while (ok && !conn->input->closed &&
 
341
               (line = i_stream_read_next_line(conn->input)) != NULL) {
306
342
                T_BEGIN {
307
343
                        char **args;
308
344
 
341
377
        return 0;
342
378
}
343
379
 
344
 
struct client_connection *client_connection_create(int fd, int listen_fd)
 
380
static int client_connection_init_ssl(struct client_connection *conn)
 
381
{
 
382
        const char *error;
 
383
 
 
384
        if (master_service_ssl_init(master_service,
 
385
                                    &conn->input, &conn->output,
 
386
                                    &conn->ssl_iostream, &error) < 0) {
 
387
                i_error("SSL init failed: %s", error);
 
388
                return -1;
 
389
        }
 
390
        if (ssl_iostream_handshake(conn->ssl_iostream) < 0) {
 
391
                i_error("SSL handshake failed: %s",
 
392
                        ssl_iostream_get_last_error(conn->ssl_iostream));
 
393
                return -1;
 
394
        }
 
395
        return 0;
 
396
}
 
397
 
 
398
static void
 
399
client_connection_send_auth_handshake(struct client_connection *
 
400
                                      conn, int listen_fd)
 
401
{
 
402
        const char *listen_path;
 
403
        struct stat st;
 
404
 
 
405
        /* we'll have to do this with stat(), because at least in Linux
 
406
           fstat() always returns mode as 0777 */
 
407
        if (net_getunixname(listen_fd, &listen_path) == 0 &&
 
408
            stat(listen_path, &st) == 0 && S_ISSOCK(st.st_mode) &&
 
409
            (st.st_mode & 0777) == 0600) {
 
410
                /* no need for client to authenticate */
 
411
                conn->authenticated = TRUE;
 
412
                o_stream_nsend(conn->output, "+\n", 2);
 
413
        } else {
 
414
                o_stream_nsend(conn->output, "-\n", 2);
 
415
        }
 
416
}
 
417
 
 
418
struct client_connection *
 
419
client_connection_create(int fd, int listen_fd, bool ssl)
345
420
{
346
421
        struct client_connection *conn;
347
 
        struct stat st;
348
 
        const char *listen_path;
349
 
        unsigned int port;
 
422
        const char *ip;
350
423
        pool_t pool;
351
424
 
352
425
        pool = pool_alloconly_create("doveadm client", 1024*16);
356
429
        conn->io = io_add(fd, IO_READ, client_connection_input, conn);
357
430
        conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
358
431
        conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
359
 
 
360
 
        (void)net_getsockname(fd, &conn->local_ip, &port);
361
 
        (void)net_getpeername(fd, &conn->remote_ip, &port);
362
 
 
363
 
        /* we'll have to do this with stat(), because at least in Linux
364
 
           fstat() always returns mode as 0777 */
365
 
        if (net_getunixname(listen_fd, &listen_path) == 0 &&
366
 
            stat(listen_path, &st) == 0 && S_ISSOCK(st.st_mode) &&
367
 
            (st.st_mode & 0777) == 0600) {
368
 
                /* no need for client to authenticate */
369
 
                conn->authenticated = TRUE;
370
 
                o_stream_send(conn->output, "+\n", 2);
371
 
        } else {
372
 
                o_stream_send(conn->output, "-\n", 2);
373
 
        }
374
 
        if (client_connection_read_settings(conn) < 0)
 
432
        o_stream_set_no_error_handling(conn->output, TRUE);
 
433
 
 
434
        (void)net_getsockname(fd, &conn->local_ip, &conn->local_port);
 
435
        (void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port);
 
436
 
 
437
        i_stream_set_name(conn->input, net_ip2addr(&conn->remote_ip));
 
438
        o_stream_set_name(conn->output, net_ip2addr(&conn->remote_ip));
 
439
 
 
440
        ip = net_ip2addr(&conn->remote_ip);
 
441
        if (ip[0] != '\0')
 
442
                i_set_failure_prefix("doveadm(%s): ", ip);
 
443
 
 
444
        if (client_connection_read_settings(conn) < 0) {
375
445
                client_connection_destroy(&conn);
 
446
                return NULL;
 
447
        }
 
448
        if (ssl) {
 
449
                if (client_connection_init_ssl(conn) < 0) {
 
450
                        client_connection_destroy(&conn);
 
451
                        return NULL;
 
452
                }
 
453
        }
 
454
        client_connection_send_auth_handshake(conn, listen_fd);
376
455
        return conn;
377
456
}
378
457
 
382
461
 
383
462
        *_conn = NULL;
384
463
 
 
464
        if (conn->ssl_iostream != NULL)
 
465
                ssl_iostream_destroy(&conn->ssl_iostream);
385
466
        i_stream_destroy(&conn->input);
386
467
        o_stream_destroy(&conn->output);
387
468
        io_remove(&conn->io);