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 |
}
|