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

1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
1
/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
2
3
#include "lib.h"
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
4
#include "lib-signals.h"
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
5
#include "base64.h"
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
6
#include "ioloop.h"
7
#include "istream.h"
8
#include "ostream.h"
9
#include "strescape.h"
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
10
#include "settings-parser.h"
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
11
#include "iostream-ssl.h"
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
12
#include "master-service.h"
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
13
#include "master-service-ssl.h"
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
14
#include "master-service-settings.h"
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
15
#include "mail-storage-service.h"
16
#include "doveadm-util.h"
17
#include "doveadm-server.h"
18
#include "doveadm-mail.h"
19
#include "doveadm-print.h"
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
20
#include "doveadm-settings.h"
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
21
#include "client-connection.h"
22
23
#include <unistd.h>
24
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
25
#define MAX_INBUF_SIZE (1024*1024)
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
26
1.13.11 by Jaldhar H. Vyas
Import upstream version 2.1.17
27
static void client_connection_input(struct client_connection *conn);
28
1.13.9 by Micah Anderson
Import upstream version 2.1.3
29
static struct doveadm_mail_cmd_context *
30
doveadm_mail_cmd_server_parse(const char *cmd_name,
31
			      const struct doveadm_settings *set,
32
			      const struct mail_storage_service_input *input,
33
			      int argc, char *argv[])
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
34
{
35
	struct doveadm_mail_cmd_context *ctx;
36
	const struct doveadm_mail_cmd *cmd;
37
	const char *getopt_args;
1.13.9 by Micah Anderson
Import upstream version 2.1.3
38
	bool add_username_header = FALSE;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
39
	int c;
40
41
	cmd = doveadm_mail_cmd_find(cmd_name);
42
	if (cmd == NULL) {
43
		i_error("doveadm: Client sent unknown command: %s", cmd_name);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
44
		return NULL;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
45
	}
46
1.13.9 by Micah Anderson
Import upstream version 2.1.3
47
	ctx = doveadm_mail_cmd_init(cmd, set);
48
	ctx->full_args = (const void *)(argv + 1);
1.13.11 by Jaldhar H. Vyas
Import upstream version 2.1.17
49
	ctx->proxying = TRUE;
1.13.9 by Micah Anderson
Import upstream version 2.1.3
50
51
	ctx->service_flags |=
52
		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT |
53
		MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
54
	if (doveadm_debug)
1.13.9 by Micah Anderson
Import upstream version 2.1.3
55
		ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
56
1.13.9 by Micah Anderson
Import upstream version 2.1.3
57
	getopt_args = t_strconcat("AS:u:", ctx->getopt_args, NULL);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
58
	while ((c = getopt(argc, argv, getopt_args)) > 0) {
59
		switch (c) {
60
		case 'A':
61
			add_username_header = TRUE;
62
			break;
1.13.9 by Micah Anderson
Import upstream version 2.1.3
63
		case 'S':
64
			/* ignore */
65
			break;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
66
		case 'u':
67
			if (strchr(optarg, '*') != NULL ||
68
			    strchr(optarg, '?') != NULL)
69
				add_username_header = TRUE;
70
			break;
71
		default:
72
			if ((ctx->v.parse_arg == NULL ||
73
			     !ctx->v.parse_arg(ctx, c))) {
74
				i_error("doveadm %s: "
75
					"Client sent unknown parameter: %c",
76
					cmd->name, c);
77
				ctx->v.deinit(ctx);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
78
				pool_unref(&ctx->pool);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
79
				return NULL;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
80
			}
81
		}
82
	}
83
1.13.9 by Micah Anderson
Import upstream version 2.1.3
84
	argv += optind;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
85
	optind = 1;
86
87
	if (argv[0] != NULL && cmd->usage_args == NULL) {
88
		i_error("doveadm %s: Client sent unknown parameter: %s",
89
			cmd->name, argv[0]);
90
		ctx->v.deinit(ctx);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
91
		pool_unref(&ctx->pool);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
92
		return NULL;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
93
	}
1.13.9 by Micah Anderson
Import upstream version 2.1.3
94
	ctx->args = (const void *)argv;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
95
96
	if (doveadm_print_is_initialized() && add_username_header) {
97
		doveadm_print_header("username", "Username",
98
				     DOVEADM_PRINT_HEADER_FLAG_STICKY |
99
				     DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
100
		doveadm_print_sticky("username", input->username);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
101
	}
1.13.9 by Micah Anderson
Import upstream version 2.1.3
102
	return ctx;
103
}
104
105
static void
106
doveadm_mail_cmd_server_run(struct client_connection *conn,
107
			    struct doveadm_mail_cmd_context *ctx,
108
			    const struct mail_storage_service_input *input)
109
{
110
	const char *error;
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
111
	struct ioloop *ioloop, *prev_ioloop = current_ioloop;
1.13.9 by Micah Anderson
Import upstream version 2.1.3
112
	int ret;
113
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
114
	ctx->conn = conn;
115
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
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();
1.13.9 by Micah Anderson
Import upstream version 2.1.3
121
	if (ctx->v.preinit != NULL)
122
		ctx->v.preinit(ctx);
123
124
	ret = doveadm_mail_single_user(ctx, input, &error);
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
125
	doveadm_mail_server_flush();
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
126
	ctx->v.deinit(ctx);
127
	doveadm_print_flush();
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
128
	mail_storage_service_deinit(&ctx->storage_service);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
129
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
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
1.13.9 by Micah Anderson
Import upstream version 2.1.3
136
	if (ret < 0) {
137
		i_error("%s: %s", ctx->cmd->name, error);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
138
		o_stream_nsend(conn->output, "\n-\n", 3);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
139
	} else if (ret == 0) {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
140
		o_stream_nsend_str(conn->output, "\n-NOUSER\n");
1.13.9 by Micah Anderson
Import upstream version 2.1.3
141
	} else if (ctx->exit_code != 0) {
142
		/* maybe not an error, but not a full success either */
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
143
		o_stream_nsend_str(conn->output,
144
				   t_strdup_printf("\n-%u\n", ctx->exit_code));
1.13.9 by Micah Anderson
Import upstream version 2.1.3
145
	} else {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
146
		o_stream_nsend(conn->output, "\n+\n", 3);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
147
	}
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
148
	pool_unref(&ctx->pool);
1.13.11 by Jaldhar H. Vyas
Import upstream version 2.1.17
149
150
	/* clear all headers */
151
	doveadm_print_deinit();
152
	doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
153
}
154
155
static bool client_is_allowed_command(const struct doveadm_settings *set,
156
				      const char *cmd_name)
157
{
158
	bool ret = FALSE;
159
160
	if (*set->doveadm_allowed_commands == '\0')
161
		return TRUE;
162
163
	T_BEGIN {
164
		const char *const *cmds =
165
			t_strsplit(set->doveadm_allowed_commands, ",");
166
		for (; *cmds != NULL; cmds++) {
167
			if (strcmp(*cmds, cmd_name) == 0) {
168
				ret = TRUE;
169
				break;
170
			}
171
		}
172
	} T_END;
173
	return ret;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
174
}
175
176
static bool client_handle_command(struct client_connection *conn, char **args)
177
{
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
178
	struct mail_storage_service_input input;
1.13.9 by Micah Anderson
Import upstream version 2.1.3
179
	struct doveadm_mail_cmd_context *ctx;
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
180
	const char *flags, *cmd_name;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
181
	unsigned int argc;
182
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
183
	memset(&input, 0, sizeof(input));
184
	input.service = "doveadm";
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
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;
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
189
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
190
	for (argc = 0; args[argc] != NULL; argc++)
191
		args[argc] = str_tabunescape(args[argc]);
192
193
	if (argc < 3) {
194
		i_error("doveadm client: No command given");
195
		return FALSE;
196
	}
197
	flags = args[0];
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
198
	input.username = args[1];
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
199
	cmd_name = args[2];
1.13.9 by Micah Anderson
Import upstream version 2.1.3
200
	/* leave the command name as args[0] so getopt() works */
201
	args += 2;
202
	argc -= 2;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
203
204
	doveadm_debug = FALSE;
205
	doveadm_verbose = FALSE;
206
207
	for (; *flags != '\0'; flags++) {
208
		switch (*flags) {
209
		case 'D':
210
			doveadm_debug = TRUE;
211
			doveadm_verbose = TRUE;
212
			break;
213
		case 'v':
214
			doveadm_verbose = TRUE;
215
			break;
216
		default:
217
			i_error("doveadm client: Unknown flag: %c", *flags);
218
			return FALSE;
219
		}
220
	}
221
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
222
	if (!client_is_allowed_command(conn->set, cmd_name)) {
223
		i_error("doveadm client isn't allowed to use command: %s",
224
			cmd_name);
225
		return FALSE;
226
	}
227
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
228
	o_stream_cork(conn->output);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
229
	ctx = doveadm_mail_cmd_server_parse(cmd_name, conn->set, &input, argc, args);
230
	if (ctx == NULL)
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
231
		o_stream_nsend(conn->output, "\n-\n", 3);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
232
	else
1.13.9 by Micah Anderson
Import upstream version 2.1.3
233
		doveadm_mail_cmd_server_run(conn, ctx, &input);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
234
	o_stream_uncork(conn->output);
235
236
	/* flush the output and disconnect */
237
	net_set_nonblock(conn->fd, FALSE);
238
	(void)o_stream_flush(conn->output);
239
	net_set_nonblock(conn->fd, TRUE);
240
	return TRUE;
241
}
242
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
243
static int
244
client_connection_authenticate(struct client_connection *conn)
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
245
{
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
246
	const char *line, *pass;
247
	buffer_t *plain;
248
	const unsigned char *data;
249
	size_t size;
250
1.13.11 by Jaldhar H. Vyas
Import upstream version 2.1.17
251
	if ((line = i_stream_read_next_line(conn->input)) == NULL) {
252
		if (conn->input->eof)
253
			return -1;
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
254
		return 0;
1.13.11 by Jaldhar H. Vyas
Import upstream version 2.1.17
255
	}
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
256
257
	if (*conn->set->doveadm_password == '\0') {
258
		i_error("doveadm_password not set, "
259
			"remote authentication disabled");
260
		return -1;
261
	}
262
263
	/* FIXME: some day we should probably let auth process do this and
264
	   support all kinds of authentication */
265
	if (strncmp(line, "PLAIN\t", 6) != 0) {
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
266
		i_error("doveadm client attempted non-PLAIN authentication: %s", line);
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
267
		return -1;
268
	}
269
270
	plain = buffer_create_dynamic(pool_datastack_create(), 128);
271
	if (base64_decode(line + 6, strlen(line + 6), NULL, plain) < 0) {
272
		i_error("doveadm client sent invalid base64 auth PLAIN data");
273
		return -1;
274
	}
275
	data = plain->data;
276
	size = plain->used;
277
278
	if (size < 10 || data[0] != '\0' ||
279
	    memcmp(data+1, "doveadm", 7) != 0 || data[8] != '\0') {
280
		i_error("doveadm client didn't authenticate as 'doveadm'");
281
		return -1;
282
	}
283
	pass = t_strndup(data + 9, size - 9);
284
	if (strcmp(pass, conn->set->doveadm_password) != 0) {
285
		i_error("doveadm client authenticated with wrong password");
286
		return -1;
287
	}
288
	return 1;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
289
}
290
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
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
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
304
static void client_connection_input(struct client_connection *conn)
305
{
306
	const char *line;
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
307
	bool ok = TRUE;
308
	int ret;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
309
310
	if (!conn->handshaked) {
311
		if ((line = i_stream_read_next_line(conn->input)) == NULL) {
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
312
			if (conn->input->eof || conn->input->stream_errno != 0) {
313
				client_log_disconnect_error(conn);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
314
				client_connection_destroy(&conn);
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
315
			}
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
316
			return;
317
		}
318
319
		if (!version_string_verify(line, "doveadm-server",
320
				DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR)) {
321
			i_error("doveadm client not compatible with this server "
322
				"(mixed old and new binaries?)");
323
			client_connection_destroy(&conn);
324
			return;
325
		}
326
		conn->handshaked = TRUE;
327
	}
328
	if (!conn->authenticated) {
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
329
		if ((ret = client_connection_authenticate(conn)) <= 0) {
1.13.9 by Micah Anderson
Import upstream version 2.1.3
330
			if (ret < 0) {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
331
				o_stream_nsend(conn->output, "-\n", 2);
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
332
				client_connection_destroy(&conn);
1.13.9 by Micah Anderson
Import upstream version 2.1.3
333
			}
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
334
			return;
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
335
		}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
336
		o_stream_nsend(conn->output, "+\n", 2);
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
337
		conn->authenticated = TRUE;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
338
	}
339
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
340
	while (ok && !conn->input->closed &&
341
	       (line = i_stream_read_next_line(conn->input)) != NULL) {
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
342
		T_BEGIN {
343
			char **args;
344
345
			args = p_strsplit(pool_datastack_create(), line, "\t");
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
346
			ok = client_handle_command(conn, args);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
347
		} T_END;
348
	}
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
349
	if (conn->input->eof || conn->input->stream_errno != 0 || !ok)
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
350
		client_connection_destroy(&conn);
351
}
352
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
353
static int client_connection_read_settings(struct client_connection *conn)
354
{
355
	const struct setting_parser_info *set_roots[] = {
356
		&doveadm_setting_parser_info,
357
		NULL
358
	};
359
	struct master_service_settings_input input;
360
	struct master_service_settings_output output;
361
	const char *error;
362
	void *set;
363
364
	memset(&input, 0, sizeof(input));
365
	input.roots = set_roots;
366
	input.service = "doveadm";
367
	input.local_ip = conn->local_ip;
368
	input.remote_ip = conn->remote_ip;
369
370
	if (master_service_settings_read(master_service, &input,
371
					 &output, &error) < 0) {
372
		i_error("Error reading configuration: %s", error);
373
		return -1;
374
	}
375
	set = master_service_settings_get_others(master_service)[0];
376
	conn->set = settings_dup(&doveadm_setting_parser_info, set, conn->pool);
377
	return 0;
378
}
379
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
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)
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
420
{
421
	struct client_connection *conn;
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
422
	const char *ip;
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
423
	pool_t pool;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
424
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
425
	pool = pool_alloconly_create("doveadm client", 1024*16);
426
	conn = p_new(pool, struct client_connection, 1);
427
	conn->pool = pool;
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
428
	conn->fd = fd;
429
	conn->io = io_add(fd, IO_READ, client_connection_input, conn);
430
	conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
431
	conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
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
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
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
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
444
	if (client_connection_read_settings(conn) < 0) {
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
445
		client_connection_destroy(&conn);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
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);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
455
	return conn;
456
}
457
458
void client_connection_destroy(struct client_connection **_conn)
459
{
460
	struct client_connection *conn = *_conn;
461
462
	*_conn = NULL;
463
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
464
	if (conn->ssl_iostream != NULL)
465
		ssl_iostream_destroy(&conn->ssl_iostream);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
466
	i_stream_destroy(&conn->input);
467
	o_stream_destroy(&conn->output);
468
	io_remove(&conn->io);
469
	if (close(conn->fd) < 0)
470
		i_error("close(client) failed: %m");
1.14.3 by Marco Nenciarini
Import upstream version 2.0.14
471
	pool_unref(&conn->pool);
1.13.8 by Marco Nenciarini
Import upstream version 2.0.11
472
473
	doveadm_client = NULL;
474
	master_service_client_connection_destroyed(master_service);
475
}
476
477
struct ostream *client_connection_get_output(struct client_connection *conn)
478
{
479
	return conn->output;
480
}