~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-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/{control,rules}: enable PIE hardening.
  + 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.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "array.h"
9
9
#include "ostream.h"
10
10
#include "str.h"
11
11
#include "strescape.h"
 
12
#include "master-service.h"
 
13
#include "master-service-settings.h"
 
14
#include "settings-parser.h"
12
15
#include "doveadm-print.h"
13
16
#include "doveadm-util.h"
14
17
#include "doveadm-server.h"
28
31
struct server_connection {
29
32
        struct doveadm_server *server;
30
33
 
 
34
        pool_t pool;
 
35
        struct doveadm_settings *set;
 
36
 
31
37
        int fd;
32
38
        struct io *io;
33
39
        struct istream *input;
34
40
        struct ostream *output;
35
41
 
 
42
        const char *delayed_cmd;
36
43
        server_cmd_callback_t *callback;
37
44
        void *context;
38
45
 
151
158
        i_stream_skip(conn->input, size);
152
159
}
153
160
 
 
161
static void server_connection_authenticated(struct server_connection *conn)
 
162
{
 
163
        conn->authenticated = TRUE;
 
164
        if (conn->delayed_cmd != NULL) {
 
165
                o_stream_send_str(conn->output, conn->delayed_cmd);
 
166
                conn->delayed_cmd = NULL;
 
167
        }
 
168
}
 
169
 
154
170
static int
155
171
server_connection_authenticate(struct server_connection *conn)
156
172
{
157
173
        string_t *plain = t_str_new(128);
158
174
        string_t *cmd = t_str_new(128);
159
175
 
160
 
        if (*doveadm_settings->doveadm_password == '\0') {
161
 
                i_error("doveadm_password not set, can't authenticate");
 
176
        if (*conn->set->doveadm_password == '\0') {
 
177
                i_error("doveadm_password not set, "
 
178
                        "can't authenticate to remote server");
162
179
                return -1;
163
180
        }
164
181
 
165
182
        str_append_c(plain, '\0');
166
183
        str_append(plain, "doveadm");
167
184
        str_append_c(plain, '\0');
168
 
        str_append(plain, doveadm_settings->doveadm_password);
 
185
        str_append(plain, conn->set->doveadm_password);
169
186
 
170
187
        str_append(cmd, "PLAIN\t");
171
188
        base64_encode(plain->data, plain->used, cmd);
180
197
        const unsigned char *data;
181
198
        size_t size;
182
199
        const char *line;
 
200
        enum server_cmd_reply reply;
183
201
 
184
202
        if (!conn->handshaked) {
185
203
                if ((line = i_stream_read_next_line(conn->input)) == NULL) {
190
208
 
191
209
                conn->handshaked = TRUE;
192
210
                if (strcmp(line, "+") == 0)
193
 
                        conn->authenticated = TRUE;
 
211
                        server_connection_authenticated(conn);
194
212
                else if (strcmp(line, "-") == 0) {
195
213
                        if (server_connection_authenticate(conn) < 0) {
196
214
                                server_connection_destroy(&conn);
197
215
                                return;
198
216
                        }
 
217
                        return;
199
218
                } else {
200
219
                        i_error("doveadm server sent invalid handshake: %s",
201
220
                                line);
209
228
                server_connection_destroy(&conn);
210
229
                return;
211
230
        }
212
 
        data = i_stream_get_data(conn->input, &size);
213
 
        if (size == 0)
214
 
                return;
215
231
 
216
232
        if (!conn->authenticated) {
217
233
                if ((line = i_stream_next_line(conn->input)) == NULL)
218
234
                        return;
219
235
                if (strcmp(line, "+") == 0)
220
 
                        conn->authenticated = TRUE;
 
236
                        server_connection_authenticated(conn);
221
237
                else {
222
238
                        i_error("doveadm authentication failed (%s)", line+1);
223
239
                        server_connection_destroy(&conn);
225
241
                }
226
242
        }
227
243
 
 
244
        data = i_stream_get_data(conn->input, &size);
 
245
        if (size == 0)
 
246
                return;
 
247
 
228
248
        switch (conn->state) {
229
249
        case SERVER_REPLY_STATE_DONE:
230
250
                i_error("doveadm server sent unexpected input");
235
255
                if (conn->state != SERVER_REPLY_STATE_RET)
236
256
                        break;
237
257
                /* fall through */
238
 
                data = i_stream_get_data(conn->input, &size);
239
258
        case SERVER_REPLY_STATE_RET:
240
 
                if (size < 2)
 
259
                line = i_stream_next_line(conn->input);
 
260
                if (line == NULL)
241
261
                        return;
242
 
                if (data[0] == '+' && data[1] == '\n')
 
262
                if (line[0] == '+')
243
263
                        server_connection_callback(conn, SERVER_CMD_REPLY_OK);
244
 
                else if (data[0] == '-' && data[1] == '\n')
245
 
                        server_connection_callback(conn, SERVER_CMD_REPLY_FAIL);
246
 
                else {
 
264
                else if (line[0] == '-') {
 
265
                        reply = strcmp(line+1, "NOUSER") == 0 ?
 
266
                                SERVER_CMD_REPLY_UNKNOWN_USER :
 
267
                                SERVER_CMD_REPLY_FAIL;
 
268
                        server_connection_callback(conn, reply);
 
269
                } else
247
270
                        i_error("doveadm server sent broken input");
248
 
                        server_connection_destroy(&conn);
249
 
                        return;
250
 
                }
 
271
                /* we're finished, close the connection */
 
272
                server_connection_destroy(&conn);
251
273
                break;
252
274
        }
253
275
}
254
276
 
 
277
static int server_connection_read_settings(struct server_connection *conn)
 
278
{
 
279
        const struct setting_parser_info *set_roots[] = {
 
280
                &doveadm_setting_parser_info,
 
281
                NULL
 
282
        };
 
283
        struct master_service_settings_input input;
 
284
        struct master_service_settings_output output;
 
285
        const char *error;
 
286
        unsigned int port;
 
287
        void *set;
 
288
 
 
289
        memset(&input, 0, sizeof(input));
 
290
        input.roots = set_roots;
 
291
        input.service = "doveadm";
 
292
 
 
293
        (void)net_getsockname(conn->fd, &input.local_ip, &port);
 
294
        (void)net_getpeername(conn->fd, &input.remote_ip, &port);
 
295
 
 
296
        if (master_service_settings_read(master_service, &input,
 
297
                                         &output, &error) < 0) {
 
298
                i_error("Error reading configuration: %s", error);
 
299
                return -1;
 
300
        }
 
301
        set = master_service_settings_get_others(master_service)[0];
 
302
        conn->set = settings_dup(&doveadm_setting_parser_info, set, conn->pool);
 
303
        return 0;
 
304
}
 
305
 
255
306
struct server_connection *
256
307
server_connection_create(struct doveadm_server *server)
257
308
{
258
309
#define DOVEADM_SERVER_HANDSHAKE "VERSION\tdoveadm-server\t1\t0\n"
259
310
        struct server_connection *conn;
 
311
        pool_t pool;
260
312
 
261
 
        conn = i_new(struct server_connection, 1);
 
313
        pool = pool_alloconly_create("doveadm server connection", 1024*16);
 
314
        conn = p_new(pool, struct server_connection, 1);
 
315
        conn->pool = pool;
262
316
        conn->server = server;
263
317
        conn->fd = doveadm_connect(server->name);
264
318
        net_set_nonblock(conn->fd, TRUE);
269
323
        o_stream_send_str(conn->output, DOVEADM_SERVER_HANDSHAKE);
270
324
 
271
325
        array_append(&conn->server->connections, &conn, 1);
 
326
        server_connection_read_settings(conn);
272
327
        return conn;
273
328
}
274
329
 
301
356
                io_remove(&conn->io);
302
357
        if (close(conn->fd) < 0)
303
358
                i_error("close(server) failed: %m");
304
 
        i_free(conn);
 
359
        pool_unref(&conn->pool);
305
360
}
306
361
 
307
362
struct doveadm_server *
313
368
void server_connection_cmd(struct server_connection *conn, const char *line,
314
369
                           server_cmd_callback_t *callback, void *context)
315
370
{
 
371
        i_assert(conn->delayed_cmd == NULL);
 
372
 
316
373
        conn->state = SERVER_REPLY_STATE_PRINT;
317
 
        o_stream_send_str(conn->output, line);
 
374
        if (conn->authenticated)
 
375
                o_stream_send_str(conn->output, line);
 
376
        else
 
377
                conn->delayed_cmd = p_strdup(conn->pool, line);
318
378
        conn->callback = callback;
319
379
        conn->context = context;
320
380
}