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

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Jaldhar H. Vyas
  • Date: 2013-09-09 00:57:32 UTC
  • mfrom: (1.13.11)
  • mto: (4.8.5 experimental) (1.16.1)
  • mto: This revision was merged to the branch mainline in revision 97.
  • Revision ID: package-import@ubuntu.com-20130909005732-dn1eell8srqbhh0e
Tags: upstream-2.2.5
ImportĀ upstreamĀ versionĀ 2.2.5

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
4
#include "base64.h"
7
7
#include "ostream.h"
8
8
#include "strescape.h"
9
9
#include "settings-parser.h"
 
10
#include "iostream-ssl.h"
10
11
#include "master-service.h"
 
12
#include "master-service-ssl.h"
11
13
#include "master-service-settings.h"
12
14
#include "mail-storage-service.h"
13
15
#include "doveadm-util.h"
19
21
 
20
22
#include <unistd.h>
21
23
 
22
 
#define MAX_INBUF_SIZE 1024
 
24
#define MAX_INBUF_SIZE (1024*1024)
23
25
 
24
26
static void client_connection_input(struct client_connection *conn);
25
27
 
26
 
struct client_connection {
27
 
        pool_t pool;
28
 
 
29
 
        int fd;
30
 
        struct io *io;
31
 
        struct istream *input;
32
 
        struct ostream *output;
33
 
        struct ip_addr local_ip, remote_ip;
34
 
        const struct doveadm_settings *set;
35
 
 
36
 
        unsigned int handshaked:1;
37
 
        unsigned int authenticated:1;
38
 
};
39
 
 
40
28
static struct doveadm_mail_cmd_context *
41
29
doveadm_mail_cmd_server_parse(const char *cmd_name,
42
30
                              const struct doveadm_settings *set,
86
74
                                        "Client sent unknown parameter: %c",
87
75
                                        cmd->name, c);
88
76
                                ctx->v.deinit(ctx);
 
77
                                pool_unref(&ctx->pool);
89
78
                                return NULL;
90
79
                        }
91
80
                }
98
87
                i_error("doveadm %s: Client sent unknown parameter: %s",
99
88
                        cmd->name, argv[0]);
100
89
                ctx->v.deinit(ctx);
 
90
                pool_unref(&ctx->pool);
101
91
                return NULL;
102
92
        }
103
93
        ctx->args = (const void *)argv;
119
109
        const char *error;
120
110
        int ret;
121
111
 
 
112
        ctx->conn = conn;
 
113
 
122
114
        if (ctx->v.preinit != NULL)
123
115
                ctx->v.preinit(ctx);
124
116
 
130
122
 
131
123
        if (ret < 0) {
132
124
                i_error("%s: %s", ctx->cmd->name, error);
133
 
                o_stream_send(conn->output, "\n-\n", 3);
 
125
                o_stream_nsend(conn->output, "\n-\n", 3);
134
126
        } else if (ret == 0) {
135
 
                o_stream_send_str(conn->output, "\n-NOUSER\n");
 
127
                o_stream_nsend_str(conn->output, "\n-NOUSER\n");
136
128
        } else if (ctx->exit_code != 0) {
137
129
                /* maybe not an error, but not a full success either */
138
 
                o_stream_send(conn->output, "\n-\n", 3);
 
130
                o_stream_nsend_str(conn->output,
 
131
                                   t_strdup_printf("\n-%u\n", ctx->exit_code));
139
132
        } else {
140
 
                o_stream_send(conn->output, "\n+\n", 3);
 
133
                o_stream_nsend(conn->output, "\n+\n", 3);
141
134
        }
142
135
        pool_unref(&ctx->pool);
143
136
 
176
169
 
177
170
        memset(&input, 0, sizeof(input));
178
171
        input.service = "doveadm";
 
172
        input.local_ip = conn->local_ip;
 
173
        input.remote_ip = conn->remote_ip;
 
174
        input.local_port = conn->local_port;
 
175
        input.remote_port = conn->remote_port;
179
176
 
180
177
        for (argc = 0; args[argc] != NULL; argc++)
181
178
                args[argc] = str_tabunescape(args[argc]);
222
219
        o_stream_cork(conn->output);
223
220
        ctx = doveadm_mail_cmd_server_parse(cmd_name, conn->set, &input, argc, args);
224
221
        if (ctx == NULL)
225
 
                o_stream_send(conn->output, "\n-\n", 3);
 
222
                o_stream_nsend(conn->output, "\n-\n", 3);
226
223
        else
227
224
                doveadm_mail_cmd_server_run(conn, ctx, &input);
228
225
        o_stream_uncork(conn->output);
309
306
        if (!conn->authenticated) {
310
307
                if ((ret = client_connection_authenticate(conn)) <= 0) {
311
308
                        if (ret < 0) {
312
 
                                o_stream_send(conn->output, "-\n", 2);
 
309
                                o_stream_nsend(conn->output, "-\n", 2);
313
310
                                client_connection_destroy(&conn);
314
311
                        }
315
312
                        return;
316
313
                }
317
 
                o_stream_send(conn->output, "+\n", 2);
 
314
                o_stream_nsend(conn->output, "+\n", 2);
318
315
                conn->authenticated = TRUE;
319
316
        }
320
317
 
321
 
        while (ok && (line = i_stream_read_next_line(conn->input)) != NULL) {
 
318
        while (ok && !conn->input->closed &&
 
319
               (line = i_stream_read_next_line(conn->input)) != NULL) {
322
320
                T_BEGIN {
323
321
                        char **args;
324
322
 
357
355
        return 0;
358
356
}
359
357
 
360
 
struct client_connection *client_connection_create(int fd, int listen_fd)
 
358
static int client_connection_init_ssl(struct client_connection *conn)
 
359
{
 
360
        const char *error;
 
361
 
 
362
        if (master_service_ssl_init(master_service,
 
363
                                    &conn->input, &conn->output,
 
364
                                    &conn->ssl_iostream, &error) < 0) {
 
365
                i_error("SSL init failed: %s", error);
 
366
                return -1;
 
367
        }
 
368
        if (ssl_iostream_handshake(conn->ssl_iostream) < 0) {
 
369
                i_error("SSL handshake failed: %s",
 
370
                        ssl_iostream_get_last_error(conn->ssl_iostream));
 
371
                return -1;
 
372
        }
 
373
        return 0;
 
374
}
 
375
 
 
376
static void
 
377
client_connection_send_auth_handshake(struct client_connection *
 
378
                                      conn, int listen_fd)
 
379
{
 
380
        const char *listen_path;
 
381
        struct stat st;
 
382
 
 
383
        /* we'll have to do this with stat(), because at least in Linux
 
384
           fstat() always returns mode as 0777 */
 
385
        if (net_getunixname(listen_fd, &listen_path) == 0 &&
 
386
            stat(listen_path, &st) == 0 && S_ISSOCK(st.st_mode) &&
 
387
            (st.st_mode & 0777) == 0600) {
 
388
                /* no need for client to authenticate */
 
389
                conn->authenticated = TRUE;
 
390
                o_stream_nsend(conn->output, "+\n", 2);
 
391
        } else {
 
392
                o_stream_nsend(conn->output, "-\n", 2);
 
393
        }
 
394
}
 
395
 
 
396
struct client_connection *
 
397
client_connection_create(int fd, int listen_fd, bool ssl)
361
398
{
362
399
        struct client_connection *conn;
363
 
        struct stat st;
364
 
        const char *listen_path;
365
 
        unsigned int port;
366
400
        pool_t pool;
367
401
 
368
402
        pool = pool_alloconly_create("doveadm client", 1024*16);
372
406
        conn->io = io_add(fd, IO_READ, client_connection_input, conn);
373
407
        conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
374
408
        conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
375
 
 
376
 
        (void)net_getsockname(fd, &conn->local_ip, &port);
377
 
        (void)net_getpeername(fd, &conn->remote_ip, &port);
378
 
 
379
 
        /* we'll have to do this with stat(), because at least in Linux
380
 
           fstat() always returns mode as 0777 */
381
 
        if (net_getunixname(listen_fd, &listen_path) == 0 &&
382
 
            stat(listen_path, &st) == 0 && S_ISSOCK(st.st_mode) &&
383
 
            (st.st_mode & 0777) == 0600) {
384
 
                /* no need for client to authenticate */
385
 
                conn->authenticated = TRUE;
386
 
                o_stream_send(conn->output, "+\n", 2);
387
 
        } else {
388
 
                o_stream_send(conn->output, "-\n", 2);
389
 
        }
390
 
        if (client_connection_read_settings(conn) < 0)
 
409
        o_stream_set_no_error_handling(conn->output, TRUE);
 
410
 
 
411
        (void)net_getsockname(fd, &conn->local_ip, &conn->local_port);
 
412
        (void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port);
 
413
 
 
414
        if (client_connection_read_settings(conn) < 0) {
391
415
                client_connection_destroy(&conn);
 
416
                return NULL;
 
417
        }
 
418
        if (ssl) {
 
419
                if (client_connection_init_ssl(conn) < 0) {
 
420
                        client_connection_destroy(&conn);
 
421
                        return NULL;
 
422
                }
 
423
        }
 
424
        client_connection_send_auth_handshake(conn, listen_fd);
392
425
        return conn;
393
426
}
394
427
 
398
431
 
399
432
        *_conn = NULL;
400
433
 
 
434
        if (conn->ssl_iostream != NULL)
 
435
                ssl_iostream_destroy(&conn->ssl_iostream);
401
436
        i_stream_destroy(&conn->input);
402
437
        o_stream_destroy(&conn->output);
403
438
        io_remove(&conn->io);