1
/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
1
/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
4
#include "lib-signals.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"
20
23
#include <unistd.h>
22
#define MAX_INBUF_SIZE 1024
24
struct client_connection {
29
struct istream *input;
30
struct ostream *output;
31
struct ip_addr local_ip, remote_ip;
32
const struct doveadm_settings *set;
34
unsigned int handshaked:1;
35
unsigned int authenticated:1;
25
#define MAX_INBUF_SIZE (1024*1024)
27
static void client_connection_input(struct client_connection *conn);
38
29
static struct doveadm_mail_cmd_context *
39
30
doveadm_mail_cmd_server_parse(const char *cmd_name,
114
108
const struct mail_storage_service_input *input)
116
110
const char *error;
111
struct ioloop *ioloop, *prev_ioloop = current_ioloop;
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);
125
127
doveadm_print_flush();
126
128
mail_storage_service_deinit(&ctx->storage_service);
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);
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));
137
o_stream_send(conn->output, "\n+\n", 3);
146
o_stream_nsend(conn->output, "\n+\n", 3);
139
148
pool_unref(&ctx->pool);
150
/* clear all headers */
151
doveadm_print_deinit();
152
doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
142
155
static bool client_is_allowed_command(const struct doveadm_settings *set,
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;
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);
214
o_stream_send(conn->output, "\n-\n", 3);
231
o_stream_nsend(conn->output, "\n-\n", 3);
216
233
doveadm_mail_cmd_server_run(conn, ctx, &input);
217
234
o_stream_uncork(conn->output);
231
248
const unsigned char *data;
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)
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);
291
static void client_log_disconnect_error(struct client_connection *conn)
295
error = conn->ssl_iostream == NULL ? NULL :
296
ssl_iostream_get_last_error(conn->ssl_iostream);
298
error = conn->input->stream_errno == 0 ? "EOF" :
299
strerror(conn->input->stream_errno);
301
i_error("doveadm client disconnected before handshake: %s", error);
271
304
static void client_connection_input(struct client_connection *conn)
273
306
const char *line;
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);
293
328
if (!conn->authenticated) {
294
329
if ((ret = client_connection_authenticate(conn)) <= 0) {
296
o_stream_send(conn->output, "-\n", 2);
331
o_stream_nsend(conn->output, "-\n", 2);
297
332
client_connection_destroy(&conn);
301
o_stream_send(conn->output, "+\n", 2);
336
o_stream_nsend(conn->output, "+\n", 2);
302
337
conn->authenticated = TRUE;
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) {
344
struct client_connection *client_connection_create(int fd, int listen_fd)
380
static int client_connection_init_ssl(struct client_connection *conn)
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);
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));
399
client_connection_send_auth_handshake(struct client_connection *
402
const char *listen_path;
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);
414
o_stream_nsend(conn->output, "-\n", 2);
418
struct client_connection *
419
client_connection_create(int fd, int listen_fd, bool ssl)
346
421
struct client_connection *conn;
348
const char *listen_path;
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);
360
(void)net_getsockname(fd, &conn->local_ip, &port);
361
(void)net_getpeername(fd, &conn->remote_ip, &port);
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);
372
o_stream_send(conn->output, "-\n", 2);
374
if (client_connection_read_settings(conn) < 0)
432
o_stream_set_no_error_handling(conn->output, TRUE);
434
(void)net_getsockname(fd, &conn->local_ip, &conn->local_port);
435
(void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port);
437
i_stream_set_name(conn->input, net_ip2addr(&conn->remote_ip));
438
o_stream_set_name(conn->output, net_ip2addr(&conn->remote_ip));
440
ip = net_ip2addr(&conn->remote_ip);
442
i_set_failure_prefix("doveadm(%s): ", ip);
444
if (client_connection_read_settings(conn) < 0) {
375
445
client_connection_destroy(&conn);
449
if (client_connection_init_ssl(conn) < 0) {
450
client_connection_destroy(&conn);
454
client_connection_send_auth_handshake(conn, listen_fd);