1 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "llist.h"
5 #include "array.h"
6 #include "safe-memset.h"
7 #include "ioloop.h"
8 #include "net.h"
9 #include "base64.h"
10 #include "istream.h"
11 #include "ostream.h"
12 #include "ostream-dot.h"
13 #include "iostream-rawlog.h"
14 #include "iostream-ssl.h"
15 #include "str.h"
16 #include "dsasl-client.h"
17 #include "dns-lookup.h"
18 #include "smtp-syntax.h"
19 #include "smtp-reply-parser.h"
20 #include "smtp-client-private.h"
21
22 #include <ctype.h>
23
24 const char *const smtp_client_connection_state_names[] = {
25 "disconnected",
26 "connecting",
27 "handshaking",
28 "authenticating",
29 "ready",
30 "transaction"
31 };
32
33 static int
34 smtp_client_connection_ssl_init(struct smtp_client_connection *conn,
35 const char **error_r);
36 static void
37 smtp_client_connection_handshake(struct smtp_client_connection *conn);
38 static void
39 smtp_client_connection_established(struct smtp_client_connection *conn);
40 static void
41 smtp_client_connection_start_transaction(struct smtp_client_connection *conn);
42 static void
43 smtp_client_connection_connect_next_ip(struct smtp_client_connection *conn);
44 static bool
45 smtp_client_connection_last_ip(struct smtp_client_connection *conn);
46
47 /*
48 * Capabilities
49 */
50
51 enum smtp_capability
smtp_client_connection_get_capabilities(struct smtp_client_connection * conn)52 smtp_client_connection_get_capabilities(struct smtp_client_connection *conn)
53 {
54 return conn->caps.standard;
55 }
56
smtp_client_connection_get_size_capability(struct smtp_client_connection * conn)57 uoff_t smtp_client_connection_get_size_capability(
58 struct smtp_client_connection *conn)
59 {
60 return conn->caps.size;
61 }
62
63 static const struct smtp_client_capability_extra *
smtp_client_connection_find_extra_capability(struct smtp_client_connection * conn,const char * cap_name)64 smtp_client_connection_find_extra_capability(
65 struct smtp_client_connection *conn, const char *cap_name)
66 {
67 const struct smtp_client_capability_extra *cap;
68
69 if (!array_is_created(&conn->extra_capabilities))
70 return NULL;
71 array_foreach(&conn->extra_capabilities, cap) {
72 if (strcasecmp(cap->name, cap_name) == 0)
73 return cap;
74 }
75 return NULL;
76 }
77
smtp_client_connection_accept_extra_capability(struct smtp_client_connection * conn,const struct smtp_client_capability_extra * cap)78 void smtp_client_connection_accept_extra_capability(
79 struct smtp_client_connection *conn,
80 const struct smtp_client_capability_extra *cap)
81 {
82 i_assert(smtp_client_connection_find_extra_capability(conn, cap->name)
83 == NULL);
84
85 if (!array_is_created(&conn->extra_capabilities))
86 p_array_init(&conn->extra_capabilities, conn->pool, 8);
87
88 struct smtp_client_capability_extra cap_new = {
89 .name = p_strdup(conn->pool, cap->name),
90 };
91
92 if (cap->mail_param_extensions != NULL) {
93 cap_new.mail_param_extensions =
94 p_strarray_dup(conn->pool, cap->mail_param_extensions);
95 }
96 if (cap->rcpt_param_extensions != NULL) {
97 cap_new.rcpt_param_extensions =
98 p_strarray_dup(conn->pool, cap->rcpt_param_extensions);
99 }
100
101 array_push_back(&conn->extra_capabilities, &cap_new);
102 }
103
104 const struct smtp_capability_extra *
smtp_client_connection_get_extra_capability(struct smtp_client_connection * conn,const char * name)105 smtp_client_connection_get_extra_capability(struct smtp_client_connection *conn,
106 const char *name)
107 {
108 const struct smtp_capability_extra *cap;
109
110 if (!array_is_created(&conn->caps.extra))
111 return NULL;
112
113 array_foreach(&conn->caps.extra, cap) {
114 if (strcasecmp(cap->name, name) == 0)
115 return cap;
116 }
117
118 return NULL;
119 }
120
121 /*
122 *
123 */
124
125 static void
smtp_client_connection_commands_abort(struct smtp_client_connection * conn)126 smtp_client_connection_commands_abort(struct smtp_client_connection *conn)
127 {
128 smtp_client_commands_list_abort(conn->cmd_wait_list_head,
129 conn->cmd_wait_list_count);
130 smtp_client_commands_list_abort(conn->cmd_send_queue_head,
131 conn->cmd_send_queue_count);
132 smtp_client_commands_abort_delayed(conn);
133 }
134
135 static void
smtp_client_connection_commands_fail_reply(struct smtp_client_connection * conn,const struct smtp_reply * reply)136 smtp_client_connection_commands_fail_reply(struct smtp_client_connection *conn,
137 const struct smtp_reply *reply)
138 {
139 smtp_client_commands_list_fail_reply(conn->cmd_wait_list_head,
140 conn->cmd_wait_list_count, reply);
141 smtp_client_commands_list_fail_reply(conn->cmd_send_queue_head,
142 conn->cmd_send_queue_count, reply);
143 smtp_client_commands_fail_delayed(conn);
144 }
145
146 static void
smtp_client_connection_commands_fail(struct smtp_client_connection * conn,unsigned int status,const char * error)147 smtp_client_connection_commands_fail(struct smtp_client_connection *conn,
148 unsigned int status, const char *error)
149 {
150 struct smtp_reply reply;
151
152 smtp_reply_init(&reply, status, error);
153 reply.enhanced_code.x = 9;
154
155 smtp_client_connection_commands_fail_reply(conn, &reply);
156 }
157
158 static void
smtp_client_connection_transactions_abort(struct smtp_client_connection * conn)159 smtp_client_connection_transactions_abort(struct smtp_client_connection *conn)
160 {
161 struct smtp_client_transaction *trans;
162
163 trans = conn->transactions_head;
164 while (trans != NULL) {
165 struct smtp_client_transaction *trans_next = trans->next;
166 smtp_client_transaction_abort(trans);
167 trans = trans_next;
168 }
169 }
170
171 static void
smtp_client_connection_transactions_fail_reply(struct smtp_client_connection * conn,const struct smtp_reply * reply)172 smtp_client_connection_transactions_fail_reply(
173 struct smtp_client_connection *conn, const struct smtp_reply *reply)
174 {
175 struct smtp_client_transaction *trans;
176
177 trans = conn->transactions_head;
178 while (trans != NULL) {
179 struct smtp_client_transaction *trans_next = trans->next;
180 smtp_client_transaction_connection_result(trans, reply);
181 trans = trans_next;
182 }
183 }
184
185 static void
smtp_client_connection_transactions_fail(struct smtp_client_connection * conn,unsigned int status,const char * error)186 smtp_client_connection_transactions_fail(
187 struct smtp_client_connection *conn,
188 unsigned int status, const char *error)
189 {
190 struct smtp_reply reply;
191
192 smtp_reply_init(&reply, status, error);
193 reply.enhanced_code.x = 9;
194
195 smtp_client_connection_transactions_fail_reply(conn, &reply);
196 }
197
198 static void
smtp_client_connection_transactions_drop(struct smtp_client_connection * conn)199 smtp_client_connection_transactions_drop(struct smtp_client_connection *conn)
200 {
201 struct smtp_client_transaction *trans;
202
203 trans = conn->transactions_head;
204 while (trans != NULL) {
205 struct smtp_client_transaction *trans_next = trans->next;
206 smtp_client_transaction_connection_destroyed(trans);
207 trans = trans_next;
208 }
209 }
210
211 static void
smtp_client_connection_login_callback(struct smtp_client_connection * conn,const struct smtp_reply * reply)212 smtp_client_connection_login_callback(struct smtp_client_connection *conn,
213 const struct smtp_reply *reply)
214 {
215 const struct smtp_client_login_callback *cb;
216 ARRAY(struct smtp_client_login_callback) login_cbs;
217
218 if (conn->state_data.login_reply == NULL) {
219 conn->state_data.login_reply =
220 smtp_reply_clone(conn->state_pool, reply);
221 }
222
223 if (!array_is_created(&conn->login_callbacks) ||
224 array_count(&conn->login_callbacks) == 0)
225 return;
226
227 t_array_init(&login_cbs, array_count(&conn->login_callbacks));
228 array_copy(&login_cbs.arr, 0, &conn->login_callbacks.arr, 0,
229 array_count(&conn->login_callbacks));
230 array_foreach(&login_cbs, cb) {
231 i_assert(cb->callback != NULL);
232 if (conn->closed)
233 break;
234 if (cb->callback != NULL)
235 cb->callback(reply, cb->context);
236 }
237 array_clear(&conn->login_callbacks);
238 }
239
240 static void
smtp_client_connection_login_fail(struct smtp_client_connection * conn,unsigned int status,const char * error)241 smtp_client_connection_login_fail(struct smtp_client_connection *conn,
242 unsigned int status, const char *error)
243 {
244 struct smtp_reply reply;
245
246 smtp_reply_init(&reply, status, error);
247 reply.enhanced_code.x = 9;
248
249 smtp_client_connection_login_callback(conn, &reply);
250 }
251
252 static void
smtp_client_connection_set_state(struct smtp_client_connection * conn,enum smtp_client_connection_state state)253 smtp_client_connection_set_state(struct smtp_client_connection *conn,
254 enum smtp_client_connection_state state)
255 {
256 conn->state = state;
257 }
258
smtp_client_connection_cork(struct smtp_client_connection * conn)259 void smtp_client_connection_cork(struct smtp_client_connection *conn)
260 {
261 conn->corked = TRUE;
262 if (conn->conn.output != NULL)
263 o_stream_cork(conn->conn.output);
264 }
265
smtp_client_connection_uncork(struct smtp_client_connection * conn)266 void smtp_client_connection_uncork(struct smtp_client_connection *conn)
267 {
268 conn->corked = FALSE;
269 if (conn->conn.output != NULL) {
270 if (o_stream_uncork_flush(conn->conn.output) < 0) {
271 smtp_client_connection_handle_output_error(conn);
272 return;
273 }
274 smtp_client_connection_trigger_output(conn);
275 }
276 }
277
278 enum smtp_client_connection_state
smtp_client_connection_get_state(struct smtp_client_connection * conn)279 smtp_client_connection_get_state(struct smtp_client_connection *conn)
280 {
281 return conn->state;
282 }
283
284 static void
smtp_client_command_timeout(struct smtp_client_connection * conn)285 smtp_client_command_timeout(struct smtp_client_connection *conn)
286 {
287 smtp_client_connection_ref(conn);
288
289 e_error(conn->event, "Command timed out, disconnecting");
290 smtp_client_connection_fail(conn, SMTP_CLIENT_COMMAND_ERROR_TIMED_OUT,
291 "Command timed out");
292 smtp_client_connection_unref(&conn);
293 }
294
smtp_client_connection_start_cmd_timeout(struct smtp_client_connection * conn)295 void smtp_client_connection_start_cmd_timeout(
296 struct smtp_client_connection *conn)
297 {
298 unsigned int msecs = conn->set.command_timeout_msecs;
299
300 if (conn->state < SMTP_CLIENT_CONNECTION_STATE_READY) {
301 /* pre-login uses connect timeout */
302 return;
303 }
304 if (msecs == 0) {
305 /* no timeout configured */
306 timeout_remove(&conn->to_commands);
307 return;
308 }
309 if (conn->cmd_wait_list_head == NULL && !conn->sending_command) {
310 /* no commands pending */
311 timeout_remove(&conn->to_commands);
312 return;
313 }
314
315 e_debug(conn->event, "Start timeout");
316 if (conn->to_commands == NULL) {
317 conn->to_commands = timeout_add(
318 msecs, smtp_client_command_timeout, conn);
319 }
320 }
321
smtp_client_connection_update_cmd_timeout(struct smtp_client_connection * conn)322 void smtp_client_connection_update_cmd_timeout(
323 struct smtp_client_connection *conn)
324 {
325 unsigned int msecs = conn->set.command_timeout_msecs;
326
327 if (conn->state < SMTP_CLIENT_CONNECTION_STATE_READY) {
328 /* pre-login uses connect timeout */
329 return;
330 }
331 if (msecs == 0) {
332 /* no timeout configured */
333 timeout_remove(&conn->to_commands);
334 return;
335 }
336
337 if (conn->cmd_wait_list_head == NULL && !conn->sending_command) {
338 if (conn->to_commands != NULL) {
339 e_debug(conn->event,
340 "No commands pending; stop timeout");
341 }
342 timeout_remove(&conn->to_commands);
343 } else if (conn->to_commands != NULL) {
344 e_debug(conn->event, "Reset timeout");
345 timeout_reset(conn->to_commands);
346 } else {
347 smtp_client_connection_start_cmd_timeout(conn);
348 }
349 }
350
351 static void
smtp_client_connection_fail_reply(struct smtp_client_connection * conn,const struct smtp_reply * reply)352 smtp_client_connection_fail_reply(struct smtp_client_connection *conn,
353 const struct smtp_reply *reply)
354 {
355 e_debug(conn->event, "Connection failed: %s", smtp_reply_log(reply));
356
357 smtp_client_connection_ref(conn);
358 conn->failing = TRUE;
359
360 smtp_client_connection_disconnect(conn);
361 smtp_client_connection_login_callback(conn, reply);
362
363 smtp_client_connection_transactions_fail_reply(conn, reply);
364 smtp_client_connection_commands_fail_reply(conn, reply);
365
366 conn->failing = FALSE;
367 smtp_client_connection_unref(&conn);
368 }
369
smtp_client_connection_fail(struct smtp_client_connection * conn,unsigned int status,const char * error)370 void smtp_client_connection_fail(struct smtp_client_connection *conn,
371 unsigned int status, const char *error)
372 {
373 struct smtp_reply reply;
374 const char *text_lines[] = {error, NULL};
375
376 timeout_remove(&conn->to_connect);
377
378 if (status == SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED &&
379 !smtp_client_connection_last_ip(conn)) {
380 conn->to_connect = timeout_add_short(
381 0, smtp_client_connection_connect_next_ip, conn);
382 return;
383 }
384
385 i_zero(&reply);
386 reply.status = status;
387 reply.text_lines = text_lines;
388 reply.enhanced_code.x = 9;
389
390 smtp_client_connection_fail_reply(conn, &reply);
391 }
392
393 static void
smtp_client_connection_lost(struct smtp_client_connection * conn,const char * error,const char * user_error)394 smtp_client_connection_lost(struct smtp_client_connection *conn,
395 const char *error, const char *user_error)
396 {
397 if (error != NULL)
398 error = t_strdup_printf("Connection lost: %s", error);
399
400 if (user_error == NULL)
401 user_error = "Lost connection to remote server";
402 else {
403 user_error = t_strdup_printf(
404 "Lost connection to remote server: %s",
405 user_error);
406 }
407
408 if (conn->ssl_iostream != NULL) {
409 const char *sslerr =
410 ssl_iostream_get_last_error(conn->ssl_iostream);
411
412 if (error != NULL && sslerr != NULL) {
413 error = t_strdup_printf("%s (last SSL error: %s)",
414 error, sslerr);
415 } else if (sslerr != NULL) {
416 error = t_strdup_printf(
417 "Connection lost (last SSL error: %s)", sslerr);
418 }
419 if (ssl_iostream_has_handshake_failed(conn->ssl_iostream)) {
420 /* This isn't really a "connection lost", but that we
421 don't trust the remote's SSL certificate. */
422 i_assert(error != NULL);
423 e_error(conn->event, "%s", error);
424 smtp_client_connection_fail(
425 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
426 user_error);
427 return;
428 }
429 }
430
431 if (error != NULL)
432 e_error(conn->event, "%s", error);
433 smtp_client_connection_fail(
434 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECTION_LOST, user_error);
435 }
436
smtp_client_connection_handle_output_error(struct smtp_client_connection * conn)437 void smtp_client_connection_handle_output_error(
438 struct smtp_client_connection *conn)
439 {
440 struct ostream *output = conn->conn.output;
441
442 if (output->stream_errno != EPIPE &&
443 output->stream_errno != ECONNRESET) {
444 smtp_client_connection_lost(
445 conn,
446 t_strdup_printf("write(%s) failed: %s",
447 o_stream_get_name(conn->conn.output),
448 o_stream_get_error(conn->conn.output)),
449 "Write failure");
450 } else {
451 smtp_client_connection_lost(
452 conn, "Remote disconnected while writing output",
453 "Remote closed connection unexpectedly");
454 }
455 }
456
stmp_client_connection_ready(struct smtp_client_connection * conn,const struct smtp_reply * reply)457 static void stmp_client_connection_ready(struct smtp_client_connection *conn,
458 const struct smtp_reply *reply)
459 {
460 timeout_remove(&conn->to_connect);
461
462 smtp_client_connection_set_state(
463 conn, SMTP_CLIENT_CONNECTION_STATE_READY);
464 conn->reset_needed = FALSE;
465
466 e_debug(conn->event, "Connection ready");
467
468 smtp_client_connection_login_callback(conn, reply);
469
470 smtp_client_connection_update_cmd_timeout(conn);
471
472 smtp_client_connection_start_transaction(conn);
473 }
474
475 static void
smtp_client_connection_xclient_cb(const struct smtp_reply * reply,struct smtp_client_connection * conn)476 smtp_client_connection_xclient_cb(const struct smtp_reply *reply,
477 struct smtp_client_connection *conn)
478 {
479 e_debug(conn->event, "Received XCLIENT handshake reply: %s",
480 smtp_reply_log(reply));
481
482 i_assert(conn->xclient_replies_expected > 0);
483
484 if (reply->status == 421) {
485 smtp_client_connection_fail_reply(conn, reply);
486 return;
487 }
488 if (conn->state == SMTP_CLIENT_CONNECTION_STATE_DISCONNECTED)
489 return;
490
491 if (conn->to_connect != NULL)
492 timeout_reset(conn->to_connect);
493 if (--conn->xclient_replies_expected == 0)
494 smtp_client_connection_handshake(conn);
495 }
496
497 static void
smtp_client_connection_xclient_submit(struct smtp_client_connection * conn,const char * cmdstr)498 smtp_client_connection_xclient_submit(struct smtp_client_connection *conn,
499 const char *cmdstr)
500 {
501 struct smtp_client_command *cmd;
502 enum smtp_client_command_flags flags;
503
504 e_debug(conn->event, "Sending XCLIENT handshake");
505
506 flags = SMTP_CLIENT_COMMAND_FLAG_PRELOGIN |
507 SMTP_CLIENT_COMMAND_FLAG_PRIORITY;
508
509 cmd = smtp_client_command_new(conn, flags,
510 smtp_client_connection_xclient_cb, conn);
511 smtp_client_command_write(cmd, cmdstr);
512 smtp_client_command_submit(cmd);
513
514 conn->xclient_replies_expected++;
515 }
516
517 static void
smtp_client_connection_xclient_add(struct smtp_client_connection * conn,string_t * str,size_t offset,const char * field,const char * value)518 smtp_client_connection_xclient_add(struct smtp_client_connection *conn,
519 string_t *str, size_t offset,
520 const char *field, const char *value)
521 {
522 size_t prev_offset = str_len(str);
523 const char *new_field;
524
525 i_assert(prev_offset >= offset);
526
527 str_append_c(str, ' ');
528 str_append(str, field);
529 str_append_c(str, '=');
530 smtp_xtext_encode_cstr(str, value);
531
532 if (prev_offset == offset ||
533 str_len(str) <= SMTP_CLIENT_BASE_LINE_LENGTH_LIMIT)
534 return;
535
536 /* preserve field we just added */
537 new_field = t_strdup(str_c(str) + prev_offset);
538
539 /* revert to previous position */
540 str_truncate(str, prev_offset);
541
542 /* send XCLIENT command */
543 smtp_client_connection_xclient_submit(conn, str_c(str));
544
545 /* start next XCLIENT command with new field */
546 str_truncate(str, offset);
547 str_append(str, new_field);
548 }
549
550 static void ATTR_FORMAT(5, 6)
smtp_client_connection_xclient_addf(struct smtp_client_connection * conn,string_t * str,size_t offset,const char * field,const char * format,...)551 smtp_client_connection_xclient_addf(struct smtp_client_connection *conn,
552 string_t *str, size_t offset,
553 const char *field, const char *format, ...)
554 {
555 va_list args;
556
557 va_start(args, format);
558 smtp_client_connection_xclient_add(conn, str, offset, field,
559 t_strdup_vprintf(format, args));
560 va_end(args);
561 }
562
smtp_client_connection_send_xclient(struct smtp_client_connection * conn)563 void smtp_client_connection_send_xclient(struct smtp_client_connection *conn)
564 {
565 const struct smtp_proxy_data *xclient = &conn->set.proxy_data;
566 const char **xclient_args = conn->caps.xclient_args;
567 size_t offset;
568 string_t *str;
569
570 if (!conn->set.peer_trusted)
571 return;
572 if (conn->xclient_sent)
573 return;
574 if ((conn->caps.standard & SMTP_CAPABILITY_XCLIENT) == 0 ||
575 conn->caps.xclient_args == NULL)
576 return;
577
578 i_assert(conn->xclient_replies_expected == 0);
579
580 /* http://www.postfix.org/XCLIENT_README.html:
581
582 The client must not send XCLIENT commands that exceed the 512
583 character limit for SMTP commands. To avoid exceeding the limit the
584 client should send the information in multiple XCLIENT commands; for
585 example, send NAME and ADDR last, after HELO and PROTO. Once ADDR is
586 sent, the client is usually no longer authorized to send XCLIENT
587 commands.
588 */
589
590 str = t_str_new(64);
591 str_append(str, "XCLIENT");
592 offset = str_len(str);
593
594 /* HELO */
595 if (xclient->helo != NULL &&
596 str_array_icase_find(xclient_args, "HELO")) {
597 smtp_client_connection_xclient_add(conn, str, offset,
598 "HELO", xclient->helo);
599 }
600
601 /* PROTO */
602 if (str_array_icase_find(xclient_args, "PROTO")) {
603 switch (xclient->proto) {
604 case SMTP_PROXY_PROTOCOL_SMTP:
605 smtp_client_connection_xclient_add(conn, str, offset,
606 "PROTO", "SMTP");
607 break;
608 case SMTP_PROXY_PROTOCOL_ESMTP:
609 smtp_client_connection_xclient_add(conn, str, offset,
610 "PROTO", "ESMTP");
611 break;
612 case SMTP_PROXY_PROTOCOL_LMTP:
613 smtp_client_connection_xclient_add(conn, str, offset,
614 "PROTO", "LMTP");
615 break;
616 default:
617 break;
618 }
619 }
620
621 /* LOGIN */
622 if (xclient->login != NULL &&
623 str_array_icase_find(xclient_args, "LOGIN")) {
624 smtp_client_connection_xclient_add(conn, str, offset,
625 "LOGIN", xclient->login);
626 }
627
628 /* TTL */
629 if (xclient->ttl_plus_1 > 0 &&
630 str_array_icase_find(xclient_args, "TTL")) {
631 smtp_client_connection_xclient_addf(conn, str, offset,
632 "TTL", "%u",
633 xclient->ttl_plus_1-1);
634 }
635
636 /* TIMEOUT */
637 if (xclient->timeout_secs > 0 &&
638 str_array_icase_find(xclient_args, "TIMEOUT")) {
639 smtp_client_connection_xclient_addf(conn, str, offset,
640 "TIMEOUT", "%u",
641 xclient->timeout_secs);
642 }
643
644 /* PORT */
645 if (xclient->source_port != 0 &&
646 str_array_icase_find(xclient_args, "PORT")) {
647 smtp_client_connection_xclient_addf(conn, str, offset,
648 "PORT", "%u",
649 xclient->source_port);
650 }
651
652 /* ADDR */
653 if (xclient->source_ip.family != 0 &&
654 str_array_icase_find(xclient_args, "ADDR")) {
655 const char *addr = net_ip2addr(&xclient->source_ip);
656
657 /* Older versions of Dovecot LMTP don't quite follow Postfix'
658 specification of the XCLIENT command regarding IPv6
659 addresses: the "IPV6:" prefix is omitted. For now, we
660 maintain this deviation for LMTP. Newer versions of Dovecot
661 LMTP can work with or without the prefix. */
662 if (conn->protocol != SMTP_PROTOCOL_LMTP &&
663 xclient->source_ip.family == AF_INET6)
664 addr = t_strconcat("IPV6:", addr, NULL);
665 smtp_client_connection_xclient_add(conn, str, offset,
666 "ADDR", addr);
667 }
668
669 /* final XCLIENT command */
670 if (str_len(str) > offset)
671 smtp_client_connection_xclient_submit(conn, str_c(str));
672
673 conn->xclient_sent = TRUE;
674 }
675
676 static void
smtp_client_connection_clear_password(struct smtp_client_connection * conn)677 smtp_client_connection_clear_password(struct smtp_client_connection *conn)
678 {
679 if (conn->set.remember_password)
680 return;
681 if (conn->password == NULL)
682 return;
683 safe_memset(conn->password, 0, strlen(conn->password));
684 conn->set.password = NULL;
685 conn->password = NULL;
686 }
687
688 static void
smtp_client_connection_auth_cb(const struct smtp_reply * reply,struct smtp_client_connection * conn)689 smtp_client_connection_auth_cb(const struct smtp_reply *reply,
690 struct smtp_client_connection *conn)
691 {
692 if (reply->status == 334) {
693 const unsigned char *sasl_output;
694 size_t sasl_output_len, input_len;
695 buffer_t *buf;
696 const char *error;
697
698 if (reply->text_lines[1] != NULL) {
699 e_error(conn->event, "Authentication failed: "
700 "Server returned multi-line reply: %s",
701 smtp_reply_log(reply));
702 smtp_client_connection_fail(
703 conn, SMTP_CLIENT_COMMAND_ERROR_AUTH_FAILED,
704 "Authentication protocol error");
705 return;
706 }
707
708 input_len = strlen(reply->text_lines[0]);
709 buf = buffer_create_dynamic(pool_datastack_create(),
710 MAX_BASE64_DECODED_SIZE(input_len));
711 if (base64_decode(reply->text_lines[0], input_len,
712 NULL, buf) < 0) {
713 e_error(conn->event, "Authentication failed: "
714 "Server sent non-base64 input for AUTH: %s",
715 reply->text_lines[0]);
716 } else if (dsasl_client_input(conn->sasl_client,
717 buf->data, buf->used,
718 &error) < 0) {
719 e_error(conn->event, "Authentication failed: %s",
720 error);
721 } else if (dsasl_client_output(conn->sasl_client, &sasl_output,
722 &sasl_output_len, &error) < 0) {
723 e_error(conn->event, "Authentication failed: %s",
724 error);
725 } else {
726 string_t *smtp_output = t_str_new(
727 MAX_BASE64_ENCODED_SIZE(sasl_output_len) + 2);
728 base64_encode(sasl_output, sasl_output_len,
729 smtp_output);
730 str_append(smtp_output, "\r\n");
731 o_stream_nsend(conn->conn.output, str_data(smtp_output),
732 str_len(smtp_output));
733 return;
734 }
735
736 smtp_client_connection_fail(
737 conn, SMTP_CLIENT_COMMAND_ERROR_AUTH_FAILED,
738 "Authentication failed");
739 return;
740 }
741
742 if ((reply->status / 100) != 2) {
743 e_error(conn->event, "Authentication failed: %s",
744 smtp_reply_log(reply));
745 smtp_client_connection_fail_reply(conn, reply);
746 return;
747 }
748
749 smtp_client_connection_clear_password(conn);
750
751 e_debug(conn->event, "Authenticated successfully");
752 dsasl_client_free(&conn->sasl_client);
753
754 if (conn->to_connect != NULL)
755 timeout_reset(conn->to_connect);
756 conn->authenticated = TRUE;
757 smtp_client_connection_handshake(conn);
758 }
759
760 static int
smtp_client_connection_get_sasl_mech(struct smtp_client_connection * conn,const struct dsasl_client_mech ** mech_r,const char ** error_r)761 smtp_client_connection_get_sasl_mech(struct smtp_client_connection *conn,
762 const struct dsasl_client_mech **mech_r,
763 const char **error_r)
764 {
765 const struct smtp_client_settings *set = &conn->set;
766 const char *const *mechanisms;
767
768 if (set->sasl_mech != NULL) {
769 const char *mech = dsasl_client_mech_get_name(set->sasl_mech);
770
771 if (!str_array_icase_find(conn->caps.auth_mechanisms, mech)) {
772 *error_r = t_strdup_printf(
773 "Server doesn't support `%s' SASL mechanism",
774 mech);
775 return -1;
776 }
777 *mech_r = set->sasl_mech;
778 return 0;
779 }
780 if (set->sasl_mechanisms == NULL ||
781 set->sasl_mechanisms[0] == '\0') {
782 *mech_r = &dsasl_client_mech_plain;
783 return 0;
784 }
785
786 /* find one of the specified SASL mechanisms */
787 mechanisms = t_strsplit_spaces(set->sasl_mechanisms, ", ");
788 for (; *mechanisms != NULL; mechanisms++) {
789 if (str_array_icase_find(conn->caps.auth_mechanisms,
790 *mechanisms)) {
791 *mech_r = dsasl_client_mech_find(*mechanisms);
792 if (*mech_r != NULL)
793 return 0;
794
795 *error_r = t_strdup_printf(
796 "Support for SASL mechanism `%s' is missing",
797 *mechanisms);
798 return -1;
799 }
800 }
801 *error_r = t_strdup_printf(
802 "Server doesn't support any of "
803 "the requested SASL mechanisms: %s", set->sasl_mechanisms);
804 return -1;
805 }
806
807 static bool
smtp_client_connection_authenticate(struct smtp_client_connection * conn)808 smtp_client_connection_authenticate(struct smtp_client_connection *conn)
809 {
810 const struct smtp_client_settings *set = &conn->set;
811 struct dsasl_client_settings sasl_set;
812 const struct dsasl_client_mech *sasl_mech = NULL;
813 struct smtp_client_command *cmd;
814 const unsigned char *sasl_output;
815 size_t sasl_output_len;
816 string_t *sasl_output_base64;
817 const char *init_resp, *error;
818
819 if (set->username == NULL && set->sasl_mech == NULL) {
820 if (!conn->set.xclient_defer)
821 smtp_client_connection_send_xclient(conn);
822 return (conn->xclient_replies_expected == 0);
823 }
824
825 smtp_client_connection_send_xclient(conn);
826 if (conn->xclient_replies_expected > 0)
827 return FALSE;
828 if (conn->authenticated)
829 return TRUE;
830
831 if ((conn->caps.standard & SMTP_CAPABILITY_AUTH) == 0) {
832 smtp_client_connection_fail(
833 conn, SMTP_CLIENT_COMMAND_ERROR_AUTH_FAILED,
834 "Authentication not supported");
835 return FALSE;
836 }
837
838 if (set->master_user != NULL) {
839 e_debug(conn->event, "Authenticating as %s for user %s",
840 set->master_user, set->username);
841 } else if (set->username == NULL) {
842 e_debug(conn->event, "Authenticating");
843 } else {
844 e_debug(conn->event, "Authenticating as %s", set->username);
845 }
846
847 if (smtp_client_connection_get_sasl_mech(conn, &sasl_mech,
848 &error) < 0) {
849 e_error(conn->event, "Authentication failed: %s", error);
850 smtp_client_connection_fail(
851 conn, SMTP_CLIENT_COMMAND_ERROR_AUTH_FAILED,
852 "Server authentication mechanisms incompatible");
853 return FALSE;
854 }
855
856 i_zero(&sasl_set);
857 if (set->master_user == NULL)
858 sasl_set.authid = set->username;
859 else {
860 sasl_set.authid = set->master_user;
861 sasl_set.authzid = set->username;
862 }
863 sasl_set.password = set->password;
864
865 conn->sasl_client = dsasl_client_new(sasl_mech, &sasl_set);
866
867 if (dsasl_client_output(conn->sasl_client, &sasl_output,
868 &sasl_output_len, &error) < 0) {
869 e_error(conn->event,
870 "Failed to create initial %s SASL reply: %s",
871 dsasl_client_mech_get_name(sasl_mech), error);
872 smtp_client_connection_fail(
873 conn, SMTP_CLIENT_COMMAND_ERROR_AUTH_FAILED,
874 "Internal authentication failure");
875 return FALSE;
876 }
877
878 sasl_output_base64 = t_str_new(
879 MAX_BASE64_ENCODED_SIZE(sasl_output_len));
880 base64_encode(sasl_output, sasl_output_len, sasl_output_base64);
881
882 /* RFC 4954, Section 4:
883
884 If the client is transmitting an initial response of zero
885 length, it MUST instead transmit the response as a single
886 equals sign ("="). This indicates that the response is
887 present, but contains no data. */
888 init_resp = (str_len(sasl_output_base64) == 0 ?
889 "=" : str_c(sasl_output_base64));
890
891 cmd = smtp_client_command_new(conn, SMTP_CLIENT_COMMAND_FLAG_PRELOGIN,
892 smtp_client_connection_auth_cb, conn);
893 smtp_client_command_printf(cmd, "AUTH %s %s",
894 dsasl_client_mech_get_name(sasl_mech),
895 init_resp);
896 smtp_client_command_submit(cmd);
897
898 smtp_client_connection_set_state(
899 conn, SMTP_CLIENT_CONNECTION_STATE_AUTHENTICATING);
900 return FALSE;
901 }
902
903 static void
smtp_client_connection_starttls_cb(const struct smtp_reply * reply,struct smtp_client_connection * conn)904 smtp_client_connection_starttls_cb(const struct smtp_reply *reply,
905 struct smtp_client_connection *conn)
906 {
907 const char *error;
908
909 e_debug(conn->event, "Received STARTTLS reply: %s",
910 smtp_reply_log(reply));
911
912 if ((reply->status / 100) != 2) {
913 smtp_client_connection_fail_reply(conn, reply);
914 return;
915 }
916
917 if (smtp_client_connection_ssl_init(conn, &error) < 0) {
918 smtp_client_connection_fail(
919 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED, error);
920 } else {
921 if (conn->to_connect != NULL)
922 timeout_reset(conn->to_connect);
923 smtp_client_connection_handshake(conn);
924 }
925 }
926
927 static bool
smtp_client_connection_starttls(struct smtp_client_connection * conn)928 smtp_client_connection_starttls(struct smtp_client_connection *conn)
929 {
930 struct smtp_client_command *cmd;
931
932 if (conn->ssl_mode == SMTP_CLIENT_SSL_MODE_STARTTLS &&
933 conn->ssl_iostream == NULL) {
934 if ((conn->caps.standard & SMTP_CAPABILITY_STARTTLS) == 0) {
935 e_error(conn->event, "Requested STARTTLS, "
936 "but server doesn't support it");
937 smtp_client_connection_fail(
938 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
939 "STARTTLS not supported");
940 return FALSE;
941 }
942
943 e_debug(conn->event, "Starting TLS");
944
945 cmd = smtp_client_command_new(
946 conn, SMTP_CLIENT_COMMAND_FLAG_PRELOGIN,
947 smtp_client_connection_starttls_cb, conn);
948 smtp_client_command_write(cmd, "STARTTLS");
949 smtp_client_command_submit(cmd);
950 return FALSE;
951 }
952
953 return smtp_client_connection_authenticate(conn);
954 }
955
956 static void
smtp_client_connection_record_param_extensions(struct smtp_client_connection * conn,ARRAY_TYPE (const_string)* arr,const char * const * extensions)957 smtp_client_connection_record_param_extensions(
958 struct smtp_client_connection *conn, ARRAY_TYPE(const_string) *arr,
959 const char *const *extensions)
960 {
961 pool_t pool = conn->cap_pool;
962
963 if (extensions == NULL || *extensions == NULL)
964 return;
965
966 if (!array_is_created(arr))
967 p_array_init(arr, pool, 4);
968 else {
969 const char *const *end;
970
971 /* Drop end marker */
972 i_assert(array_count(arr) > 0);
973 end = array_back(arr);
974 i_assert(*end == NULL);
975 array_pop_back(arr);
976 }
977
978 const char *const *new_p;
979 for (new_p = extensions; *new_p != NULL; new_p++) {
980 /* Drop duplicates */
981 if (array_lsearch(arr, new_p, i_strcasecmp_p) != NULL)
982 continue;
983
984 array_push_back(arr, new_p);
985 }
986
987 /* Add new end marker */
988 array_append_zero(arr);
989 }
990
991 static void
smtp_client_connection_record_extra_capability(struct smtp_client_connection * conn,const char * cap_name,const char * const * params)992 smtp_client_connection_record_extra_capability(
993 struct smtp_client_connection *conn, const char *cap_name,
994 const char *const *params)
995 {
996 const struct smtp_client_capability_extra *ccap_extra;
997 struct smtp_capability_extra cap_extra;
998 pool_t pool = conn->cap_pool;
999
1000 ccap_extra = smtp_client_connection_find_extra_capability(
1001 conn, cap_name);
1002 if (ccap_extra == NULL)
1003 return;
1004 if (smtp_client_connection_get_extra_capability(conn, cap_name) != NULL)
1005 return;
1006
1007 if (!array_is_created(&conn->caps.extra))
1008 p_array_init(&conn->caps.extra, pool, 4);
1009
1010 i_zero(&cap_extra);
1011 cap_extra.name = p_strdup(pool, ccap_extra->name);
1012 cap_extra.params = p_strarray_dup(pool, params);
1013
1014 array_push_back(&conn->caps.extra, &cap_extra);
1015
1016 smtp_client_connection_record_param_extensions(
1017 conn, &conn->caps.mail_param_extensions,
1018 ccap_extra->mail_param_extensions);
1019 smtp_client_connection_record_param_extensions(
1020 conn, &conn->caps.rcpt_param_extensions,
1021 ccap_extra->rcpt_param_extensions);
1022 }
1023
1024 static void
smtp_client_connection_handshake_cb(const struct smtp_reply * reply,struct smtp_client_connection * conn)1025 smtp_client_connection_handshake_cb(const struct smtp_reply *reply,
1026 struct smtp_client_connection *conn)
1027 {
1028 const char *const *lines;
1029
1030 e_debug(conn->event, "Received handshake reply");
1031
1032 /* check reply status */
1033 if ((reply->status / 100) != 2) {
1034 /* RFC 5321, Section 3.2:
1035 For a particular connection attempt, if the server returns a
1036 "command not recognized" response to EHLO, the client SHOULD
1037 be able to fall back and send HELO. */
1038 if (conn->protocol == SMTP_PROTOCOL_SMTP && !conn->old_smtp &&
1039 (reply->status == 500 || reply->status == 502)) {
1040 /* try HELO */
1041 conn->old_smtp = TRUE;
1042 smtp_client_connection_handshake(conn);
1043 return;
1044 }
1045 /* failed */
1046 smtp_client_connection_fail_reply(conn, reply);
1047 return;
1048 }
1049
1050 /* reset capabilities */
1051 p_clear(conn->cap_pool);
1052 i_zero(&conn->caps);
1053 conn->caps.standard = conn->set.forced_capabilities;
1054
1055 lines = reply->text_lines;
1056 if (*lines == NULL) {
1057 smtp_client_connection_fail(
1058 conn, SMTP_CLIENT_COMMAND_ERROR_BAD_REPLY,
1059 "Invalid handshake reply");
1060 return;
1061 }
1062
1063 /* greeting line */
1064 lines++;
1065
1066 /* capability lines */
1067 while (*lines != NULL) {
1068 enum smtp_capability cap;
1069 const char *const *params;
1070 const char *cap_name, *error;
1071
1072 if (smtp_ehlo_line_parse(*lines, &cap_name, ¶ms,
1073 &error) <= 0) {
1074 e_warning(conn->event,
1075 "Received invalid EHLO response line: %s",
1076 error);
1077 lines++;
1078 continue;
1079 }
1080
1081 cap = smtp_capability_find_by_name(cap_name);
1082 switch (cap) {
1083 case SMTP_CAPABILITY_AUTH:
1084 conn->caps.auth_mechanisms =
1085 p_strarray_dup(conn->cap_pool, params);
1086 break;
1087 case SMTP_CAPABILITY_SIZE:
1088 if (params == NULL || *params == NULL)
1089 break;
1090 if (str_to_uoff(*params, &conn->caps.size) < 0) {
1091 e_warning(conn->event,
1092 "Received invalid SIZE capability "
1093 "in EHLO response line");
1094 cap = SMTP_CAPABILITY_NONE;
1095 }
1096 break;
1097 case SMTP_CAPABILITY_XCLIENT:
1098 conn->caps.xclient_args =
1099 p_strarray_dup(conn->cap_pool, params);
1100 break;
1101 case SMTP_CAPABILITY_NONE:
1102 smtp_client_connection_record_extra_capability(
1103 conn, cap_name, params);
1104 break;
1105 default:
1106 break;
1107 }
1108
1109 conn->caps.standard |= cap;
1110 lines++;
1111 }
1112
1113 e_debug(conn->event, "Received server capabilities");
1114
1115 if (conn->to_connect != NULL)
1116 timeout_reset(conn->to_connect);
1117 if (smtp_client_connection_starttls(conn)) {
1118 stmp_client_connection_ready(conn, reply);
1119 }
1120 }
1121
1122 static void
smtp_client_connection_handshake(struct smtp_client_connection * conn)1123 smtp_client_connection_handshake(struct smtp_client_connection *conn)
1124 {
1125 struct smtp_client_command *cmd;
1126 enum smtp_client_command_flags flags;
1127 const char *command;
1128
1129 flags = SMTP_CLIENT_COMMAND_FLAG_PRELOGIN |
1130 SMTP_CLIENT_COMMAND_FLAG_PRIORITY;
1131
1132 switch (conn->protocol) {
1133 case SMTP_PROTOCOL_SMTP:
1134 command = (conn->old_smtp ? "HELO" : "EHLO");
1135 break;
1136 case SMTP_PROTOCOL_LMTP:
1137 command = "LHLO";
1138 break;
1139 default:
1140 i_unreached();
1141 }
1142
1143 e_debug(conn->event, "Sending %s handshake", command);
1144
1145 cmd = smtp_client_command_new(
1146 conn, flags, smtp_client_connection_handshake_cb, conn);
1147 smtp_client_command_write(cmd, command);
1148 smtp_client_command_write(cmd, " ");
1149 smtp_client_command_write(cmd, conn->set.my_hostname);
1150 smtp_client_command_submit(cmd);
1151 smtp_client_connection_set_state(
1152 conn, SMTP_CLIENT_CONNECTION_STATE_HANDSHAKING);
1153 }
1154
1155 static int
smtp_client_connection_input_reply(struct smtp_client_connection * conn,const struct smtp_reply * reply)1156 smtp_client_connection_input_reply(struct smtp_client_connection *conn,
1157 const struct smtp_reply *reply)
1158 {
1159 int ret;
1160
1161 /* initial greeting? */
1162 if (conn->state == SMTP_CLIENT_CONNECTION_STATE_CONNECTING) {
1163 e_debug(conn->event, "Received greeting from server: %s",
1164 smtp_reply_log(reply));
1165 if (reply->status != 220) {
1166 if (smtp_reply_is_success(reply)) {
1167 smtp_client_connection_fail(
1168 conn,
1169 SMTP_CLIENT_COMMAND_ERROR_BAD_REPLY,
1170 "Received inappropriate greeting");
1171 } else {
1172 smtp_client_connection_fail_reply(conn, reply);
1173 }
1174 return -1;
1175 }
1176 smtp_client_connection_handshake(conn);
1177 return 1;
1178 }
1179
1180 if (reply->status == SMTP_CLIENT_COMMAND_ERROR_CONNECTION_CLOSED) {
1181 smtp_client_connection_fail_reply(conn, reply);
1182 return -1;
1183 }
1184
1185 /* unexpected reply? */
1186 if (conn->cmd_wait_list_head == NULL) {
1187 e_debug(conn->event, "Unexpected reply: %s",
1188 smtp_reply_log(reply));
1189 smtp_client_connection_fail(
1190 conn, SMTP_CLIENT_COMMAND_ERROR_BAD_REPLY,
1191 "Got unexpected reply");
1192 return -1;
1193 }
1194
1195 /* replied early? */
1196 if (conn->cmd_wait_list_head == conn->cmd_streaming &&
1197 !conn->cmd_wait_list_head->stream_finished) {
1198 e_debug(conn->event, "Early reply: %s", smtp_reply_log(reply));
1199 if (smtp_reply_is_success(reply)) {
1200 smtp_client_connection_fail(
1201 conn, SMTP_CLIENT_COMMAND_ERROR_BAD_REPLY,
1202 "Got early success reply");
1203 return -1;
1204 }
1205 }
1206
1207 /* command reply */
1208 ret = smtp_client_command_input_reply(conn->cmd_wait_list_head, reply);
1209
1210 if (conn->state == SMTP_CLIENT_CONNECTION_STATE_DISCONNECTED ||
1211 conn->conn.output == NULL)
1212 return -1;
1213 return ret;
1214 }
1215
smtp_client_connection_input(struct connection * _conn)1216 static void smtp_client_connection_input(struct connection *_conn)
1217 {
1218 struct smtp_client_connection *conn =
1219 (struct smtp_client_connection *)_conn;
1220 bool enhanced_codes = ((conn->caps.standard &
1221 SMTP_CAPABILITY_ENHANCEDSTATUSCODES) != 0);
1222 struct smtp_reply *reply;
1223 const char *error = NULL;
1224 int ret;
1225
1226 if (conn->ssl_iostream != NULL &&
1227 !ssl_iostream_is_handshaked(conn->ssl_iostream)) {
1228 /* finish SSL negotiation by reading from input stream */
1229 while ((ret = i_stream_read(conn->conn.input)) > 0 ||
1230 ret == -2) {
1231 if (ssl_iostream_is_handshaked(conn->ssl_iostream))
1232 break;
1233 }
1234 if (ret < 0) {
1235 /* failed somehow */
1236 i_assert(ret != -2);
1237 e_error(conn->event,
1238 "SSL handshaking with %s failed: "
1239 "read(%s) failed: %s", _conn->name,
1240 i_stream_get_name(conn->conn.input),
1241 i_stream_get_error(conn->conn.input));
1242 smtp_client_connection_fail(
1243 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1244 "Failed to connect to remote server");
1245 return;
1246 }
1247
1248 if (!ssl_iostream_is_handshaked(conn->ssl_iostream)) {
1249 /* not finished */
1250 i_assert(ret == 0);
1251 return;
1252 }
1253
1254 if (conn->to_connect != NULL)
1255 timeout_reset(conn->to_connect);
1256 }
1257
1258 if (!conn->connect_succeeded) {
1259 /* just got ready for SMTP handshake */
1260 smtp_client_connection_established(conn);
1261 }
1262
1263 smtp_client_connection_ref(conn);
1264 o_stream_cork(conn->conn.output);
1265 for (;;) {
1266 if (conn->cmd_wait_list_head != NULL &&
1267 conn->cmd_wait_list_head->ehlo) {
1268 if ((ret = smtp_reply_parse_ehlo(conn->reply_parser,
1269 &reply, &error)) <= 0)
1270 break;
1271 } else {
1272 if ((ret = smtp_reply_parse_next(conn->reply_parser,
1273 enhanced_codes,
1274 &reply, &error)) <= 0)
1275 break;
1276 }
1277
1278 T_BEGIN {
1279 ret = smtp_client_connection_input_reply(conn, reply);
1280 } T_END;
1281 if (ret < 0) {
1282 if (conn->conn.output != NULL && !conn->corked)
1283 o_stream_uncork(conn->conn.output);
1284 smtp_client_connection_unref(&conn);
1285 return;
1286 }
1287 }
1288
1289 if (ret < 0 || (ret == 0 && conn->conn.input->eof)) {
1290 if (conn->conn.input->stream_errno == ENOBUFS) {
1291 smtp_client_connection_fail(
1292 conn, SMTP_CLIENT_COMMAND_ERROR_BAD_REPLY,
1293 "Command reply line too long");
1294 } else if (conn->conn.input->stream_errno != 0) {
1295 smtp_client_connection_lost(
1296 conn,
1297 t_strdup_printf(
1298 "read(%s) failed: %s",
1299 i_stream_get_name(conn->conn.input),
1300 i_stream_get_error(conn->conn.input)),
1301 "Read failure");
1302 } else if (!i_stream_have_bytes_left(conn->conn.input)) {
1303 if (conn->sent_quit) {
1304 smtp_client_connection_lost(
1305 conn, NULL,
1306 "Remote closed connection");
1307 } else {
1308 smtp_client_connection_lost(
1309 conn, NULL,
1310 "Remote closed connection unexpectedly");
1311 }
1312 } else {
1313 i_assert(error != NULL);
1314 smtp_client_connection_fail(
1315 conn, SMTP_CLIENT_COMMAND_ERROR_BAD_REPLY,
1316 t_strdup_printf("Invalid command reply: %s",
1317 error));
1318 }
1319 }
1320 if (ret >= 0 && conn->conn.output != NULL && !conn->corked) {
1321 if (o_stream_uncork_flush(conn->conn.output) < 0)
1322 smtp_client_connection_handle_output_error(conn);
1323 }
1324 smtp_client_connection_unref(&conn);
1325 }
1326
smtp_client_connection_output(struct smtp_client_connection * conn)1327 static int smtp_client_connection_output(struct smtp_client_connection *conn)
1328 {
1329 int ret;
1330
1331 if (conn->to_connect != NULL)
1332 timeout_reset(conn->to_connect);
1333
1334 ret = o_stream_flush(conn->conn.output);
1335 if (ret <= 0) {
1336 if (ret < 0)
1337 smtp_client_connection_handle_output_error(conn);
1338 return ret;
1339 }
1340
1341 smtp_client_connection_ref(conn);
1342 o_stream_cork(conn->conn.output);
1343 if (smtp_client_command_send_more(conn) < 0)
1344 ret = -1;
1345 if (ret >= 0 && conn->conn.output != NULL && !conn->corked) {
1346 if (o_stream_uncork_flush(conn->conn.output) < 0)
1347 smtp_client_connection_handle_output_error(conn);
1348 }
1349 smtp_client_connection_unref(&conn);
1350 return ret;
1351 }
1352
smtp_client_connection_trigger_output(struct smtp_client_connection * conn)1353 void smtp_client_connection_trigger_output(struct smtp_client_connection *conn)
1354 {
1355 if (conn->conn.output != NULL)
1356 o_stream_set_flush_pending(conn->conn.output, TRUE);
1357 }
1358
smtp_client_connection_destroy(struct connection * _conn)1359 static void smtp_client_connection_destroy(struct connection *_conn)
1360 {
1361 struct smtp_client_connection *conn =
1362 (struct smtp_client_connection *)_conn;
1363
1364 switch (_conn->disconnect_reason) {
1365 case CONNECTION_DISCONNECT_NOT:
1366 break;
1367 case CONNECTION_DISCONNECT_DEINIT:
1368 e_debug(conn->event, "Connection deinit");
1369 smtp_client_connection_close(&conn);
1370 break;
1371 case CONNECTION_DISCONNECT_CONNECT_TIMEOUT:
1372 e_error(conn->event, "connect(%s) failed: Connection timed out",
1373 _conn->name);
1374 smtp_client_connection_fail(
1375 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1376 "Connect timed out");
1377 break;
1378 default:
1379 case CONNECTION_DISCONNECT_CONN_CLOSED:
1380 if (conn->connect_failed) {
1381 smtp_client_connection_fail(conn,
1382 SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1383 "Failed to connect to remote server");
1384 break;
1385 }
1386 if (_conn->input != NULL && _conn->input->stream_errno != 0) {
1387 smtp_client_connection_lost(
1388 conn,
1389 t_strdup_printf("read(%s) failed: %s",
1390 i_stream_get_name(conn->conn.input),
1391 i_stream_get_error(conn->conn.input)),
1392 "Read failure");
1393 break;
1394 }
1395 smtp_client_connection_lost(
1396 conn, "Remote disconnected",
1397 "Remote closed connection unexpectedly");
1398 break;
1399 }
1400 }
1401
1402 static void
smtp_client_connection_established(struct smtp_client_connection * conn)1403 smtp_client_connection_established(struct smtp_client_connection *conn)
1404 {
1405 i_assert(!conn->connect_succeeded);
1406 conn->connect_succeeded = TRUE;
1407
1408 if (conn->to_connect != NULL)
1409 timeout_reset(conn->to_connect);
1410
1411 /* set flush callback */
1412 o_stream_set_flush_callback(conn->conn.output,
1413 smtp_client_connection_output, conn);
1414 }
1415
1416 static int
smtp_client_connection_ssl_handshaked(const char ** error_r,void * context)1417 smtp_client_connection_ssl_handshaked(const char **error_r, void *context)
1418 {
1419 struct smtp_client_connection *conn = context;
1420 const char *error, *host = conn->host;
1421
1422 if (ssl_iostream_check_cert_validity(conn->ssl_iostream,
1423 host, &error) == 0) {
1424 e_debug(conn->event, "SSL handshake successful");
1425 } else if (conn->set.ssl->allow_invalid_cert) {
1426 e_debug(conn->event, "SSL handshake successful, "
1427 "ignoring invalid certificate: %s", error);
1428 } else {
1429 *error_r = error;
1430 return -1;
1431 }
1432 return 0;
1433 }
1434
1435 static void
smtp_client_connection_streams_changed(struct smtp_client_connection * conn)1436 smtp_client_connection_streams_changed(struct smtp_client_connection *conn)
1437 {
1438 struct stat st;
1439
1440 if (conn->set.rawlog_dir != NULL &&
1441 stat(conn->set.rawlog_dir, &st) == 0) {
1442 iostream_rawlog_create(conn->set.rawlog_dir,
1443 &conn->conn.input, &conn->conn.output);
1444 }
1445
1446 if (conn->reply_parser == NULL) {
1447 conn->reply_parser = smtp_reply_parser_init(
1448 conn->conn.input, conn->set.max_reply_size);
1449 } else {
1450 smtp_reply_parser_set_stream(conn->reply_parser,
1451 conn->conn.input);
1452 }
1453
1454 connection_streams_changed(&conn->conn);
1455 }
1456
1457 static int
smtp_client_connection_init_ssl_ctx(struct smtp_client_connection * conn,const char ** error_r)1458 smtp_client_connection_init_ssl_ctx(struct smtp_client_connection *conn,
1459 const char **error_r)
1460 {
1461 struct smtp_client *client = conn->client;
1462 const char *error;
1463
1464 if (conn->ssl_ctx != NULL)
1465 return 0;
1466
1467 if (conn->set.ssl == client->set.ssl) {
1468 if (smtp_client_init_ssl_ctx(client, error_r) < 0)
1469 return -1;
1470 conn->ssl_ctx = client->ssl_ctx;
1471 ssl_iostream_context_ref(conn->ssl_ctx);
1472 return 0;
1473 }
1474
1475 if (conn->set.ssl == NULL) {
1476 *error_r =
1477 "Requested SSL connection, but no SSL settings given";
1478 return -1;
1479 }
1480 if (ssl_iostream_client_context_cache_get(conn->set.ssl, &conn->ssl_ctx,
1481 &error) < 0) {
1482 *error_r = t_strdup_printf(
1483 "Couldn't initialize SSL context: %s", error);
1484 return -1;
1485 }
1486 return 0;
1487 }
1488
1489 static int
smtp_client_connection_ssl_init(struct smtp_client_connection * conn,const char ** error_r)1490 smtp_client_connection_ssl_init(struct smtp_client_connection *conn,
1491 const char **error_r)
1492 {
1493 const char *error;
1494
1495 if (smtp_client_connection_init_ssl_ctx(conn, &error) < 0) {
1496 *error_r = t_strdup_printf(
1497 "Failed to initialize SSL: %s", error);
1498 return -1;
1499 }
1500
1501 e_debug(conn->event, "Starting SSL handshake");
1502
1503 if (conn->raw_input != conn->conn.input) {
1504 /* recreate rawlog after STARTTLS */
1505 i_stream_ref(conn->raw_input);
1506 o_stream_ref(conn->raw_output);
1507 i_stream_destroy(&conn->conn.input);
1508 o_stream_destroy(&conn->conn.output);
1509 conn->conn.input = conn->raw_input;
1510 conn->conn.output = conn->raw_output;
1511 }
1512
1513 connection_input_halt(&conn->conn);
1514 if (io_stream_create_ssl_client(
1515 conn->ssl_ctx, conn->host, conn->set.ssl,
1516 &conn->conn.input, &conn->conn.output,
1517 &conn->ssl_iostream, &error) < 0) {
1518 *error_r = t_strdup_printf(
1519 "Couldn't initialize SSL client for %s: %s",
1520 conn->conn.name, error);
1521 return -1;
1522 }
1523 connection_input_resume(&conn->conn);
1524 smtp_client_connection_streams_changed(conn);
1525
1526 ssl_iostream_set_handshake_callback(
1527 conn->ssl_iostream, smtp_client_connection_ssl_handshaked,
1528 conn);
1529 if (ssl_iostream_handshake(conn->ssl_iostream) < 0) {
1530 *error_r = t_strdup_printf(
1531 "SSL handshake to %s failed: %s", conn->conn.name,
1532 ssl_iostream_get_last_error(conn->ssl_iostream));
1533 return -1;
1534 }
1535
1536 if (ssl_iostream_is_handshaked(conn->ssl_iostream) &&
1537 !conn->connect_succeeded) {
1538 smtp_client_connection_established(conn);
1539 } else {
1540 /* wait for handshake to complete; connection input handler
1541 does the rest by reading from the input stream */
1542 o_stream_set_flush_callback(
1543 conn->conn.output, smtp_client_connection_output, conn);
1544 }
1545 return 0;
1546 }
1547
1548 static void
smtp_client_connection_connected(struct connection * _conn,bool success)1549 smtp_client_connection_connected(struct connection *_conn, bool success)
1550 {
1551 struct smtp_client_connection *conn =
1552 (struct smtp_client_connection *)_conn;
1553 const struct smtp_client_settings *set = &conn->set;
1554 const char *error;
1555
1556 if (!success) {
1557 e_error(conn->event, "connect(%s) failed: %m", _conn->name);
1558 conn->connect_failed = TRUE;
1559 return;
1560 }
1561
1562 if (conn->set.debug) {
1563 struct ip_addr local_ip;
1564 in_port_t local_port;
1565 int ret;
1566
1567 ret = net_getsockname(_conn->fd_in, &local_ip, &local_port);
1568 i_assert(ret == 0);
1569 e_debug(conn->event, "Connected to server (from %s:%u)",
1570 net_ip2addr(&local_ip), local_port);
1571 }
1572
1573 (void)net_set_tcp_nodelay(_conn->fd_out, TRUE);
1574 if (set->socket_send_buffer_size > 0 &&
1575 net_set_send_buffer_size(_conn->fd_out,
1576 set->socket_send_buffer_size) < 0) {
1577 e_error(conn->event,
1578 "net_set_send_buffer_size(%zu) failed: %m",
1579 set->socket_send_buffer_size);
1580 }
1581 if (set->socket_recv_buffer_size > 0 &&
1582 net_set_recv_buffer_size(_conn->fd_in,
1583 set->socket_recv_buffer_size) < 0) {
1584 e_error(conn->event,
1585 "net_set_recv_buffer_size(%zu) failed: %m",
1586 set->socket_recv_buffer_size);
1587 }
1588
1589 conn->raw_input = conn->conn.input;
1590 conn->raw_output = conn->conn.output;
1591 smtp_client_connection_streams_changed(conn);
1592
1593 if (conn->ssl_mode == SMTP_CLIENT_SSL_MODE_IMMEDIATE) {
1594 if (smtp_client_connection_ssl_init(conn, &error) < 0) {
1595 e_error(conn->event, "connect(%s) failed: %s",
1596 _conn->name, error);
1597 smtp_client_connection_fail(
1598 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1599 "Failed to connect to remote server");
1600 }
1601 } else {
1602 smtp_client_connection_established(conn);
1603 smtp_client_connection_input(_conn);
1604 }
1605 }
1606
1607 static void
smtp_client_connection_connect_timeout(struct smtp_client_connection * conn)1608 smtp_client_connection_connect_timeout(struct smtp_client_connection *conn)
1609 {
1610 switch (conn->state) {
1611 case SMTP_CLIENT_CONNECTION_STATE_CONNECTING:
1612 e_error(conn->event, "connect(%s) failed: "
1613 "Connection timed out after %u seconds",
1614 conn->conn.name,
1615 conn->set.connect_timeout_msecs/1000);
1616 smtp_client_connection_fail(
1617 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1618 "Connect timed out");
1619 break;
1620 case SMTP_CLIENT_CONNECTION_STATE_HANDSHAKING:
1621 e_error(conn->event,
1622 "SMTP handshake timed out after %u seconds",
1623 conn->set.connect_timeout_msecs/1000);
1624 smtp_client_connection_fail(
1625 conn, SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1626 "Handshake timed out");
1627 break;
1628 case SMTP_CLIENT_CONNECTION_STATE_AUTHENTICATING:
1629 e_error(conn->event,
1630 "Authentication timed out after %u seconds",
1631 conn->set.connect_timeout_msecs/1000);
1632 smtp_client_connection_fail(
1633 conn, SMTP_CLIENT_COMMAND_ERROR_AUTH_FAILED,
1634 "Authentication timed out");
1635 break;
1636 default:
1637 i_unreached();
1638 }
1639 }
1640
1641 static void
smtp_client_connection_delayed_connect_error(struct smtp_client_connection * conn)1642 smtp_client_connection_delayed_connect_error(
1643 struct smtp_client_connection *conn)
1644 {
1645 e_debug(conn->event, "Delayed connect error");
1646
1647 timeout_remove(&conn->to_connect);
1648 errno = conn->connect_errno;
1649 smtp_client_connection_connected(&conn->conn, FALSE);
1650 smtp_client_connection_fail(conn,
1651 SMTP_CLIENT_COMMAND_ERROR_CONNECT_FAILED,
1652 "Failed to connect to remote server");
1653 }
1654
1655 static void
smtp_client_connection_do_connect(struct smtp_client_connection * conn)1656 smtp_client_connection_do_connect(struct smtp_client_connection *conn)
1657 {
1658 unsigned int msecs;
1659
1660 if (conn->closed || conn->failing)
1661 return;
1662
1663 /* Clear state data */
1664 i_zero(&conn->state_data);
1665 p_clear(conn->state_pool);
1666
1667 if (connection_client_connect(&conn->conn) < 0) {
1668 conn->connect_errno = errno;
1669 e_debug(conn->event, "Connect failed: %m");
1670 conn->to_connect = timeout_add_short(0,
1671 smtp_client_connection_delayed_connect_error, conn);
1672 return;
1673 }
1674
1675 /* don't use connection.h timeout because we want this timeout
1676 to include also the SSL handshake */
1677 msecs = conn->set.connect_timeout_msecs;
1678 if (msecs == 0)
1679 msecs = conn->set.command_timeout_msecs;
1680 i_assert(conn->to_connect == NULL);
1681 if (msecs > 0) {
1682 conn->to_connect = timeout_add(
1683 msecs, smtp_client_connection_connect_timeout, conn);
1684 }
1685 }
1686
1687 static bool
smtp_client_connection_last_ip(struct smtp_client_connection * conn)1688 smtp_client_connection_last_ip(struct smtp_client_connection *conn)
1689 {
1690 i_assert(conn->prev_connect_idx < conn->ips_count);
1691 return (conn->prev_connect_idx + 1) % conn->ips_count == 0;
1692 }
1693
1694 static void
smtp_client_connection_connect_next_ip(struct smtp_client_connection * conn)1695 smtp_client_connection_connect_next_ip(struct smtp_client_connection *conn)
1696 {
1697 const struct ip_addr *ip, *my_ip = &conn->set.my_ip;
1698
1699 timeout_remove(&conn->to_connect);
1700
1701 conn->prev_connect_idx = (conn->prev_connect_idx+1) % conn->ips_count;
1702 ip = &conn->ips[conn->prev_connect_idx];
1703
1704 if (my_ip->family != 0) {
1705 e_debug(conn->event, "Connecting to %s:%u (from %s)",
1706 net_ip2addr(ip), conn->port, net_ip2addr(my_ip));
1707 } else {
1708 e_debug(conn->event, "Connecting to %s:%u",
1709 net_ip2addr(ip), conn->port);
1710 }
1711
1712 connection_init_client_ip_from(conn->client->conn_list, &conn->conn,
1713 (conn->host_is_ip ? NULL : conn->host),
1714 ip, conn->port, my_ip);
1715
1716 smtp_client_connection_do_connect(conn);
1717 }
1718
1719 static void
smtp_client_connection_connect_unix(struct smtp_client_connection * conn)1720 smtp_client_connection_connect_unix(struct smtp_client_connection *conn)
1721 {
1722 timeout_remove(&conn->to_connect);
1723
1724 e_debug(conn->event, "Connecting to socket %s", conn->path);
1725
1726 connection_init_client_unix(conn->client->conn_list, &conn->conn,
1727 conn->path);
1728
1729 smtp_client_connection_do_connect(conn);
1730 }
1731
1732 static void
smtp_client_connection_delayed_host_lookup_failure(struct smtp_client_connection * conn)1733 smtp_client_connection_delayed_host_lookup_failure(
1734 struct smtp_client_connection *conn)
1735 {
1736 e_debug(conn->event, "Delayed host lookup failure");
1737
1738 i_assert(conn->to_connect != NULL);
1739 timeout_remove(&conn->to_connect);
1740 smtp_client_connection_fail(
1741 conn, SMTP_CLIENT_COMMAND_ERROR_HOST_LOOKUP_FAILED,
1742 "Failed to lookup remote server");
1743 }
1744
1745 static void
smtp_client_connection_dns_callback(const struct dns_lookup_result * result,struct smtp_client_connection * conn)1746 smtp_client_connection_dns_callback(const struct dns_lookup_result *result,
1747 struct smtp_client_connection *conn)
1748 {
1749 conn->dns_lookup = NULL;
1750
1751 if (result->ret != 0) {
1752 e_error(conn->event, "dns_lookup(%s) failed: %s",
1753 conn->host, result->error);
1754 timeout_remove(&conn->to_connect);
1755 conn->to_connect = timeout_add_short(
1756 0, smtp_client_connection_delayed_host_lookup_failure,
1757 conn);
1758 return;
1759 }
1760
1761 e_debug(conn->event, "DNS lookup successful; got %d IPs",
1762 result->ips_count);
1763
1764 i_assert(result->ips_count > 0);
1765 conn->ips_count = result->ips_count;
1766 conn->ips = i_new(struct ip_addr, conn->ips_count);
1767 memcpy(conn->ips, result->ips, sizeof(*conn->ips) * conn->ips_count);
1768 conn->prev_connect_idx = conn->ips_count - 1;
1769
1770 smtp_client_connection_connect_next_ip(conn);
1771 }
1772
1773 static void
smtp_client_connection_lookup_ip(struct smtp_client_connection * conn)1774 smtp_client_connection_lookup_ip(struct smtp_client_connection *conn)
1775 {
1776 struct dns_lookup_settings dns_set;
1777 struct ip_addr ip, *ips;
1778 unsigned int ips_count;
1779 int ret;
1780
1781 if (conn->ips_count != 0)
1782 return;
1783
1784 e_debug(conn->event, "Looking up IP address");
1785
1786 if (net_addr2ip(conn->host, &ip) == 0) {
1787 /* IP address */
1788 conn->ips_count = 1;
1789 conn->ips = i_new(struct ip_addr, conn->ips_count);
1790 conn->ips[0] = ip;
1791 conn->host_is_ip = TRUE;
1792 } else if (conn->set.dns_client != NULL) {
1793 e_debug(conn->event, "Performing asynchronous DNS lookup");
1794 (void)dns_client_lookup(
1795 conn->set.dns_client, conn->host,
1796 smtp_client_connection_dns_callback, conn,
1797 &conn->dns_lookup);
1798 } else if (conn->set.dns_client_socket_path != NULL) {
1799 i_zero(&dns_set);
1800 dns_set.dns_client_socket_path =
1801 conn->set.dns_client_socket_path;
1802 dns_set.timeout_msecs = conn->set.connect_timeout_msecs;
1803 dns_set.event_parent = conn->event;
1804 e_debug(conn->event, "Performing asynchronous DNS lookup");
1805 (void)dns_lookup(conn->host, &dns_set,
1806 smtp_client_connection_dns_callback, conn,
1807 &conn->dns_lookup);
1808 } else {
1809 /* no dns-conn, use blocking lookup */
1810 ret = net_gethostbyname(conn->host, &ips, &ips_count);
1811 if (ret != 0) {
1812 e_error(conn->event, "net_gethostbyname(%s) failed: %s",
1813 conn->host, net_gethosterror(ret));
1814 timeout_remove(&conn->to_connect);
1815 conn->to_connect = timeout_add_short(
1816 0,
1817 smtp_client_connection_delayed_host_lookup_failure,
1818 conn);
1819 return;
1820 }
1821
1822 e_debug(conn->event, "DNS lookup successful; got %d IPs",
1823 ips_count);
1824
1825 conn->ips_count = ips_count;
1826 conn->ips = i_new(struct ip_addr, ips_count);
1827 memcpy(conn->ips, ips, ips_count * sizeof(*ips));
1828 }
1829 }
1830
1831 static void
smtp_client_connection_already_connected(struct smtp_client_connection * conn)1832 smtp_client_connection_already_connected(struct smtp_client_connection *conn)
1833 {
1834 i_assert(conn->state_data.login_reply != NULL);
1835
1836 timeout_remove(&conn->to_connect);
1837
1838 e_debug(conn->event, "Already connected");
1839
1840 smtp_client_connection_login_callback(
1841 conn, conn->state_data.login_reply);
1842 }
1843
1844 static void
smtp_client_connection_connect_more(struct smtp_client_connection * conn)1845 smtp_client_connection_connect_more(struct smtp_client_connection *conn)
1846 {
1847 if (!array_is_created(&conn->login_callbacks) ||
1848 array_count(&conn->login_callbacks) == 0) {
1849 /* No login callbacks required */
1850 return;
1851 }
1852 if (conn->state < SMTP_CLIENT_CONNECTION_STATE_READY) {
1853 /* Login callbacks will be called once the connection succeeds
1854 or fails. */
1855 return;
1856 }
1857
1858 if (array_count(&conn->login_callbacks) > 1) {
1859 /* Another login callback is already pending */
1860 i_assert(conn->to_connect != NULL);
1861 return;
1862 }
1863
1864 /* Schedule immediate login callback */
1865 i_assert(conn->to_connect == NULL);
1866 conn->to_connect = timeout_add(
1867 0, smtp_client_connection_already_connected, conn);
1868 }
1869
smtp_client_connection_connect(struct smtp_client_connection * conn,smtp_client_command_callback_t login_callback,void * login_context)1870 void smtp_client_connection_connect(
1871 struct smtp_client_connection *conn,
1872 smtp_client_command_callback_t login_callback, void *login_context)
1873 {
1874 struct smtp_client_login_callback *login_cb;
1875
1876 if (conn->closed)
1877 return;
1878
1879 if (login_callback != NULL) {
1880 if (!array_is_created(&conn->login_callbacks))
1881 i_array_init(&conn->login_callbacks, 4);
1882
1883 login_cb = array_append_space(&conn->login_callbacks);
1884 login_cb->callback = login_callback;
1885 login_cb->context = login_context;
1886 }
1887
1888 if (conn->state != SMTP_CLIENT_CONNECTION_STATE_DISCONNECTED) {
1889 /* Already connecting or connected */
1890 smtp_client_connection_connect_more(conn);
1891 return;
1892 }
1893 if (conn->failing)
1894 return;
1895
1896 e_debug(conn->event, "Disconnected");
1897
1898 conn->xclient_replies_expected = 0;
1899 conn->authenticated = FALSE;
1900 conn->xclient_sent = FALSE;
1901 conn->connect_failed = FALSE;
1902 conn->connect_succeeded = FALSE;
1903 conn->handshake_failed = FALSE;
1904 conn->sent_quit = FALSE;
1905 conn->reset_needed = FALSE;
1906
1907 smtp_client_connection_set_state(
1908 conn, SMTP_CLIENT_CONNECTION_STATE_CONNECTING);
1909
1910 if (conn->path == NULL) {
1911 smtp_client_connection_lookup_ip(conn);
1912 if (conn->ips_count == 0)
1913 return;
1914
1915 /* always work asynchronously */
1916 timeout_remove(&conn->to_connect);
1917 conn->to_connect = timeout_add(
1918 0, smtp_client_connection_connect_next_ip, conn);
1919 } else {
1920 /* always work asynchronously */
1921 timeout_remove(&conn->to_connect);
1922 conn->to_connect = timeout_add(
1923 0, smtp_client_connection_connect_unix, conn);
1924 }
1925 }
1926
1927 static const struct connection_settings smtp_client_connection_set = {
1928 .input_max_size = SIZE_MAX,
1929 .output_max_size = SIZE_MAX,
1930 .client = TRUE,
1931 .delayed_unix_client_connected_callback = TRUE,
1932 .log_connection_id = TRUE,
1933 };
1934
1935 static const struct connection_vfuncs smtp_client_connection_vfuncs = {
1936 .destroy = smtp_client_connection_destroy,
1937 .input = smtp_client_connection_input,
1938 .client_connected = smtp_client_connection_connected
1939 };
1940
smtp_client_connection_list_init(void)1941 struct connection_list *smtp_client_connection_list_init(void)
1942 {
1943 return connection_list_init(&smtp_client_connection_set,
1944 &smtp_client_connection_vfuncs);
1945 }
1946
smtp_client_connection_disconnect(struct smtp_client_connection * conn)1947 void smtp_client_connection_disconnect(struct smtp_client_connection *conn)
1948 {
1949 if (conn->state == SMTP_CLIENT_CONNECTION_STATE_DISCONNECTED)
1950 return;
1951
1952 e_debug(conn->event, "Disconnected");
1953
1954 smtp_client_connection_clear_password(conn);
1955
1956 if (conn->conn.output != NULL && !conn->sent_quit &&
1957 !conn->sending_command) {
1958 /* Close the connection gracefully if possible */
1959 o_stream_nsend_str(conn->conn.output, "QUIT\r\n");
1960 o_stream_uncork(conn->conn.output);
1961 }
1962
1963 if (conn->dns_lookup != NULL)
1964 dns_lookup_abort(&conn->dns_lookup);
1965 io_remove(&conn->io_cmd_payload);
1966 timeout_remove(&conn->to_connect);
1967 timeout_remove(&conn->to_trans);
1968 timeout_remove(&conn->to_commands);
1969 timeout_remove(&conn->to_cmd_fail);
1970
1971 ssl_iostream_destroy(&conn->ssl_iostream);
1972 if (conn->ssl_ctx != NULL)
1973 ssl_iostream_context_unref(&conn->ssl_ctx);
1974 if (conn->sasl_client != NULL)
1975 dsasl_client_free(&conn->sasl_client);
1976
1977 o_stream_destroy(&conn->dot_output);
1978
1979 connection_disconnect(&conn->conn);
1980
1981 smtp_client_connection_set_state(
1982 conn, SMTP_CLIENT_CONNECTION_STATE_DISCONNECTED);
1983
1984 if (!conn->failing) {
1985 smtp_client_connection_login_fail(
1986 conn, SMTP_CLIENT_COMMAND_ERROR_ABORTED,
1987 "Disconnected from server");
1988 smtp_client_connection_transactions_fail(
1989 conn, SMTP_CLIENT_COMMAND_ERROR_ABORTED,
1990 "Disconnected from server");
1991 smtp_client_connection_commands_fail(
1992 conn, SMTP_CLIENT_COMMAND_ERROR_ABORTED,
1993 "Disconnected from server");
1994 }
1995 smtp_client_command_unref(&conn->cmd_streaming);
1996 }
1997
1998 static struct smtp_client_connection *
smtp_client_connection_do_create(struct smtp_client * client,const char * name,enum smtp_protocol protocol,const struct smtp_client_settings * set)1999 smtp_client_connection_do_create(struct smtp_client *client, const char *name,
2000 enum smtp_protocol protocol,
2001 const struct smtp_client_settings *set)
2002 {
2003 struct smtp_client_connection *conn;
2004 struct event *conn_event;
2005 pool_t pool;
2006
2007 pool = pool_alloconly_create("smtp client connection", 2048);
2008 conn = p_new(pool, struct smtp_client_connection, 1);
2009 conn->refcount = 1;
2010 conn->pool = pool;
2011
2012 conn->client = client;
2013 conn->protocol = protocol;
2014
2015 conn->set = client->set;
2016 if (set != NULL) {
2017 if (set->my_ip.family != 0)
2018 conn->set.my_ip = set->my_ip;
2019 if (set->my_hostname != NULL && *set->my_hostname != '\0')
2020 conn->set.my_hostname = p_strdup(pool, set->my_hostname);
2021
2022 conn->set.forced_capabilities |= set->forced_capabilities;
2023 if (set->extra_capabilities != NULL) {
2024 conn->set.extra_capabilities =
2025 p_strarray_dup(pool, set->extra_capabilities);
2026 }
2027
2028 if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
2029 conn->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
2030
2031 if (set->ssl != NULL)
2032 conn->set.ssl = ssl_iostream_settings_dup(pool, set->ssl);
2033
2034 if (set->master_user != NULL && *set->master_user != '\0')
2035 conn->set.master_user = p_strdup_empty(pool, set->master_user);
2036 if (set->username != NULL && *set->username != '\0')
2037 conn->set.username = p_strdup_empty(pool, set->username);
2038 if (set->password != NULL && *set->password != '\0') {
2039 conn->password = p_strdup(pool, set->password);
2040 conn->set.password = conn->password;
2041 }
2042 if (set->sasl_mech != NULL)
2043 conn->set.sasl_mech = set->sasl_mech;
2044 else if (set->sasl_mechanisms != NULL &&
2045 *set->sasl_mechanisms != '\0') {
2046 conn->set.sasl_mechanisms =
2047 p_strdup(pool, set->sasl_mechanisms);
2048 }
2049 conn->set.remember_password = set->remember_password;
2050
2051 if (set->command_timeout_msecs > 0)
2052 conn->set.command_timeout_msecs = set->command_timeout_msecs;
2053 if (set->connect_timeout_msecs > 0)
2054 conn->set.connect_timeout_msecs = set->connect_timeout_msecs;
2055 if (set->max_reply_size > 0)
2056 conn->set.max_reply_size = set->max_reply_size;
2057 if (set->max_data_chunk_size > 0)
2058 conn->set.max_data_chunk_size = set->max_data_chunk_size;
2059 if (set->max_data_chunk_pipeline > 0)
2060 conn->set.max_data_chunk_pipeline = set->max_data_chunk_pipeline;
2061
2062 if (set->socket_send_buffer_size > 0)
2063 conn->set.socket_send_buffer_size = set->socket_send_buffer_size;
2064 if (set->socket_recv_buffer_size > 0)
2065 conn->set.socket_recv_buffer_size = set->socket_recv_buffer_size;
2066 conn->set.debug = conn->set.debug || set->debug;
2067
2068 smtp_proxy_data_merge(conn->pool, &conn->set.proxy_data,
2069 &set->proxy_data);
2070 conn->set.xclient_defer = set->xclient_defer;
2071 conn->set.peer_trusted = set->peer_trusted;
2072
2073 conn->set.mail_send_broken_path = set->mail_send_broken_path;
2074 }
2075
2076
2077 if (set != NULL && set->extra_capabilities != NULL) {
2078 const char *const *extp;
2079
2080 p_array_init(&conn->extra_capabilities, pool,
2081 str_array_length(set->extra_capabilities) + 8);
2082 for (extp = set->extra_capabilities; *extp != NULL; extp++) {
2083 struct smtp_client_capability_extra cap = {
2084 .name = p_strdup(pool, *extp),
2085 };
2086
2087 array_push_back(&conn->extra_capabilities, &cap);
2088 }
2089 }
2090
2091 i_assert(conn->set.my_hostname != NULL &&
2092 *conn->set.my_hostname != '\0');
2093
2094 conn->caps.standard = conn->set.forced_capabilities;
2095 conn->cap_pool = pool_alloconly_create(
2096 "smtp client connection capabilities", 128);
2097 conn->state_pool = pool_alloconly_create(
2098 "smtp client connection state", 256);
2099
2100 if (set != NULL && set->event_parent != NULL)
2101 conn_event = event_create(set->event_parent);
2102 else
2103 conn_event = event_create(client->event);
2104 event_set_append_log_prefix(
2105 conn_event,
2106 t_strdup_printf("%s-client: ",
2107 smtp_protocol_name(conn->protocol)));
2108 event_add_str(conn_event, "protocol",
2109 smtp_protocol_name(conn->protocol));
2110 event_set_forced_debug(conn_event, (set != NULL && set->debug));
2111
2112 conn->conn.event_parent = conn_event;
2113 connection_init(conn->client->conn_list, &conn->conn, name);
2114 conn->event = conn->conn.event;
2115 event_unref(&conn_event);
2116
2117 return conn;
2118 }
2119
2120 struct smtp_client_connection *
smtp_client_connection_create(struct smtp_client * client,enum smtp_protocol protocol,const char * host,in_port_t port,enum smtp_client_connection_ssl_mode ssl_mode,const struct smtp_client_settings * set)2121 smtp_client_connection_create(struct smtp_client *client,
2122 enum smtp_protocol protocol,
2123 const char *host, in_port_t port,
2124 enum smtp_client_connection_ssl_mode ssl_mode,
2125 const struct smtp_client_settings *set)
2126 {
2127 struct smtp_client_connection *conn;
2128 const char *name = t_strdup_printf("%s:%u", host, port);
2129
2130 conn = smtp_client_connection_do_create(client, name, protocol, set);
2131 conn->host = p_strdup(conn->pool, host);
2132 conn->port = port;
2133 conn->ssl_mode = ssl_mode;
2134
2135 event_add_str(conn->event, "host", host);
2136
2137 e_debug(conn->event, "Connection created");
2138
2139 return conn;
2140 }
2141
2142 struct smtp_client_connection *
smtp_client_connection_create_ip(struct smtp_client * client,enum smtp_protocol protocol,const struct ip_addr * ip,in_port_t port,const char * hostname,enum smtp_client_connection_ssl_mode ssl_mode,const struct smtp_client_settings * set)2143 smtp_client_connection_create_ip(struct smtp_client *client,
2144 enum smtp_protocol protocol,
2145 const struct ip_addr *ip, in_port_t port,
2146 const char *hostname,
2147 enum smtp_client_connection_ssl_mode ssl_mode,
2148 const struct smtp_client_settings *set)
2149 {
2150 struct smtp_client_connection *conn;
2151 bool host_is_ip = FALSE;
2152
2153 if (hostname == NULL) {
2154 hostname = net_ip2addr(ip);
2155 host_is_ip = TRUE;
2156 }
2157
2158 conn = smtp_client_connection_create(client, protocol, hostname, port,
2159 ssl_mode, set);
2160 conn->ips_count = 1;
2161 conn->ips = i_new(struct ip_addr, conn->ips_count);
2162 conn->ips[0] = *ip;
2163 conn->host_is_ip = host_is_ip;
2164 return conn;
2165 }
2166
2167 struct smtp_client_connection *
smtp_client_connection_create_unix(struct smtp_client * client,enum smtp_protocol protocol,const char * path,const struct smtp_client_settings * set)2168 smtp_client_connection_create_unix(struct smtp_client *client,
2169 enum smtp_protocol protocol,
2170 const char *path,
2171 const struct smtp_client_settings *set)
2172 {
2173 struct smtp_client_connection *conn;
2174 const char *name = t_strconcat("unix:", path, NULL);
2175
2176 conn = smtp_client_connection_do_create(client, name, protocol, set);
2177 conn->path = p_strdup(conn->pool, path);
2178
2179 e_debug(conn->event, "Connection created");
2180
2181 return conn;
2182 }
2183
smtp_client_connection_ref(struct smtp_client_connection * conn)2184 void smtp_client_connection_ref(struct smtp_client_connection *conn)
2185 {
2186 i_assert(conn->refcount >= 0);
2187 conn->refcount++;
2188 }
2189
smtp_client_connection_unref(struct smtp_client_connection ** _conn)2190 void smtp_client_connection_unref(struct smtp_client_connection **_conn)
2191 {
2192 struct smtp_client_connection *conn = *_conn;
2193
2194 *_conn = NULL;
2195
2196 i_assert(conn->refcount > 0);
2197 if (--conn->refcount > 0)
2198 return;
2199 if (conn->destroying)
2200 return;
2201
2202 conn->destroying = TRUE;
2203
2204 smtp_client_connection_clear_password(conn);
2205 smtp_client_connection_disconnect(conn);
2206
2207 /* could have been created while already disconnected */
2208 timeout_remove(&conn->to_commands);
2209 timeout_remove(&conn->to_cmd_fail);
2210
2211 e_debug(conn->event, "Destroy");
2212
2213 if (conn->reply_parser != NULL)
2214 smtp_reply_parser_deinit(&conn->reply_parser);
2215
2216 smtp_client_connection_login_fail(
2217 conn, SMTP_CLIENT_COMMAND_ERROR_ABORTED,
2218 "Connection destroy");
2219 smtp_client_connection_transactions_fail(
2220 conn, SMTP_CLIENT_COMMAND_ERROR_ABORTED,
2221 "Connection destroy");
2222 smtp_client_connection_commands_fail(
2223 conn, SMTP_CLIENT_COMMAND_ERROR_ABORTED,
2224 "Connection destroy");
2225 smtp_client_connection_transactions_drop(conn);
2226
2227 connection_deinit(&conn->conn);
2228
2229 i_free(conn->ips);
2230 array_free(&conn->login_callbacks);
2231 pool_unref(&conn->cap_pool);
2232 pool_unref(&conn->state_pool);
2233 pool_unref(&conn->pool);
2234 }
2235
smtp_client_connection_close(struct smtp_client_connection ** _conn)2236 void smtp_client_connection_close(struct smtp_client_connection **_conn)
2237 {
2238 struct smtp_client_connection *conn = *_conn;
2239
2240 *_conn = NULL;
2241
2242 if (conn->closed)
2243 return;
2244 conn->closed = TRUE;
2245
2246 smtp_client_connection_transactions_abort(conn);
2247 smtp_client_connection_commands_abort(conn);
2248 smtp_client_connection_disconnect(conn);
2249
2250 /* could have been created while already disconnected */
2251 timeout_remove(&conn->to_commands);
2252 timeout_remove(&conn->to_cmd_fail);
2253
2254 smtp_client_connection_unref(&conn);
2255 }
2256
smtp_client_connection_update_proxy_data(struct smtp_client_connection * conn,const struct smtp_proxy_data * proxy_data)2257 void smtp_client_connection_update_proxy_data(
2258 struct smtp_client_connection *conn,
2259 const struct smtp_proxy_data *proxy_data)
2260 {
2261 if (conn->xclient_sent)
2262 return;
2263
2264 smtp_proxy_data_merge(conn->pool, &conn->set.proxy_data, proxy_data);
2265 }
2266
smtp_client_connection_switch_ioloop(struct smtp_client_connection * conn)2267 void smtp_client_connection_switch_ioloop(struct smtp_client_connection *conn)
2268 {
2269 struct smtp_client_transaction *trans;
2270
2271 if (conn->io_cmd_payload != NULL)
2272 conn->io_cmd_payload = io_loop_move_io(&conn->io_cmd_payload);
2273 if (conn->to_connect != NULL)
2274 conn->to_connect = io_loop_move_timeout(&conn->to_connect);
2275 if (conn->to_trans != NULL)
2276 conn->to_trans = io_loop_move_timeout(&conn->to_trans);
2277 if (conn->to_commands != NULL)
2278 conn->to_commands = io_loop_move_timeout(&conn->to_commands);
2279 if (conn->to_cmd_fail != NULL)
2280 conn->to_cmd_fail = io_loop_move_timeout(&conn->to_cmd_fail);
2281 connection_switch_ioloop(&conn->conn);
2282
2283 trans = conn->transactions_head;
2284 while (trans != NULL) {
2285 smtp_client_transaction_switch_ioloop(trans);
2286 trans = trans->next;
2287 }
2288 }
2289
2290 static void
smtp_client_connection_rset_dummy_cb(const struct smtp_reply * reply ATTR_UNUSED,struct smtp_client_connection * conn ATTR_UNUSED)2291 smtp_client_connection_rset_dummy_cb(
2292 const struct smtp_reply *reply ATTR_UNUSED,
2293 struct smtp_client_connection *conn ATTR_UNUSED)
2294 {
2295 /* nothing */
2296 }
2297
2298 static void
smtp_client_connection_reset(struct smtp_client_connection * conn)2299 smtp_client_connection_reset(struct smtp_client_connection *conn)
2300 {
2301 e_debug(conn->event, "Submitting RSET command");
2302
2303 conn->reset_needed = FALSE;
2304
2305 (void)smtp_client_command_rset_submit(
2306 conn, SMTP_CLIENT_COMMAND_FLAG_PRIORITY,
2307 smtp_client_connection_rset_dummy_cb, conn);
2308 }
2309
2310 static void
smtp_client_connection_do_start_transaction(struct smtp_client_connection * conn)2311 smtp_client_connection_do_start_transaction(struct smtp_client_connection *conn)
2312 {
2313 struct smtp_reply reply;
2314
2315 timeout_remove(&conn->to_trans);
2316
2317 if (conn->state != SMTP_CLIENT_CONNECTION_STATE_TRANSACTION)
2318 return;
2319 if (conn->transactions_head == NULL) {
2320 smtp_client_connection_set_state(
2321 conn, SMTP_CLIENT_CONNECTION_STATE_READY);
2322 return;
2323 }
2324
2325 if (conn->reset_needed)
2326 smtp_client_connection_reset(conn);
2327
2328 e_debug(conn->event, "Start next transaction");
2329
2330 smtp_reply_init(&reply, 200, "Connection ready");
2331 smtp_client_transaction_connection_result(
2332 conn->transactions_head, &reply);
2333 }
2334
2335 static void
smtp_client_connection_start_transaction(struct smtp_client_connection * conn)2336 smtp_client_connection_start_transaction(struct smtp_client_connection *conn)
2337 {
2338 if (conn->state != SMTP_CLIENT_CONNECTION_STATE_READY)
2339 return;
2340 if (conn->transactions_head == NULL)
2341 return;
2342 if (conn->to_trans != NULL)
2343 return;
2344
2345 smtp_client_connection_set_state(
2346 conn, SMTP_CLIENT_CONNECTION_STATE_TRANSACTION);
2347 conn->to_trans = timeout_add_short(
2348 0, smtp_client_connection_do_start_transaction, conn);
2349 }
2350
smtp_client_connection_add_transaction(struct smtp_client_connection * conn,struct smtp_client_transaction * trans)2351 void smtp_client_connection_add_transaction(
2352 struct smtp_client_connection *conn,
2353 struct smtp_client_transaction *trans)
2354 {
2355 e_debug(conn->event, "Add transaction");
2356
2357 DLLIST2_APPEND(&conn->transactions_head, &conn->transactions_tail,
2358 trans);
2359
2360 smtp_client_connection_connect(conn, NULL, NULL);
2361 smtp_client_connection_start_transaction(conn);
2362 }
2363
smtp_client_connection_abort_transaction(struct smtp_client_connection * conn,struct smtp_client_transaction * trans)2364 void smtp_client_connection_abort_transaction(
2365 struct smtp_client_connection *conn,
2366 struct smtp_client_transaction *trans)
2367 {
2368 bool was_first = (trans == conn->transactions_head);
2369
2370 e_debug(conn->event, "Abort transaction");
2371
2372 DLLIST2_REMOVE(&conn->transactions_head, &conn->transactions_tail,
2373 trans);
2374
2375 if (!was_first)
2376 return;
2377 i_assert(conn->state != SMTP_CLIENT_CONNECTION_STATE_READY);
2378 if (conn->state != SMTP_CLIENT_CONNECTION_STATE_TRANSACTION)
2379 return;
2380
2381 /* transaction messed up; protocol state needs to be reset for
2382 next transaction */
2383 conn->reset_needed = TRUE;
2384
2385 smtp_client_connection_set_state(
2386 conn, SMTP_CLIENT_CONNECTION_STATE_READY);
2387 smtp_client_connection_start_transaction(conn);
2388 }
2389
smtp_client_connection_next_transaction(struct smtp_client_connection * conn,struct smtp_client_transaction * trans)2390 void smtp_client_connection_next_transaction(
2391 struct smtp_client_connection *conn,
2392 struct smtp_client_transaction *trans)
2393 {
2394 e_debug(conn->event, "Initiate next transaction");
2395
2396 i_assert(trans == conn->transactions_head);
2397
2398 DLLIST2_REMOVE(&conn->transactions_head, &conn->transactions_tail,
2399 trans);
2400
2401 i_assert(conn->state != SMTP_CLIENT_CONNECTION_STATE_READY);
2402 if (conn->state != SMTP_CLIENT_CONNECTION_STATE_TRANSACTION)
2403 return;
2404
2405 smtp_client_connection_set_state(
2406 conn, SMTP_CLIENT_CONNECTION_STATE_READY);
2407 smtp_client_connection_start_transaction(conn);
2408 }
2409