1 /* $OpenBSD: mta_session.c,v 1.152 2024/09/03 18:27:04 op Exp $ */
2
3 /*
4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
6 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
7 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include <sys/stat.h>
23
24 #include <ctype.h>
25 #include <errno.h>
26 #include <inttypes.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <tls.h>
31 #include <unistd.h>
32
33 #include "smtpd.h"
34 #include "log.h"
35
36 #define MAX_TRYBEFOREDISABLE 10
37
38 #define MTA_HIWAT 65535
39
40 enum mta_state {
41 MTA_INIT,
42 MTA_BANNER,
43 MTA_EHLO,
44 MTA_HELO,
45 MTA_LHLO,
46 MTA_STARTTLS,
47 MTA_AUTH,
48 MTA_AUTH_PLAIN,
49 MTA_AUTH_LOGIN,
50 MTA_AUTH_LOGIN_USER,
51 MTA_AUTH_LOGIN_PASS,
52 MTA_READY,
53 MTA_MAIL,
54 MTA_RCPT,
55 MTA_DATA,
56 MTA_BODY,
57 MTA_EOM,
58 MTA_LMTP_EOM,
59 MTA_RSET,
60 MTA_QUIT,
61 };
62
63 #define MTA_FORCE_ANYSSL 0x0001
64 #define MTA_FORCE_SMTPS 0x0002
65 #define MTA_FORCE_TLS 0x0004
66 #define MTA_FORCE_PLAIN 0x0008
67 #define MTA_WANT_SECURE 0x0010
68 #define MTA_DOWNGRADE_PLAIN 0x0080
69
70 #define MTA_TLS 0x0100
71 #define MTA_TLS_VERIFIED 0x0200
72
73 #define MTA_FREE 0x0400
74 #define MTA_LMTP 0x0800
75 #define MTA_WAIT 0x1000
76 #define MTA_HANGON 0x2000
77 #define MTA_RECONN 0x4000
78
79 #define MTA_EXT_STARTTLS 0x01
80 #define MTA_EXT_PIPELINING 0x02
81 #define MTA_EXT_AUTH 0x04
82 #define MTA_EXT_AUTH_PLAIN 0x08
83 #define MTA_EXT_AUTH_LOGIN 0x10
84 #define MTA_EXT_SIZE 0x20
85
86 struct mta_session {
87 uint64_t id;
88 struct mta_relay *relay;
89 struct mta_route *route;
90 char *helo;
91 char *mxname;
92
93 char *username;
94
95 int flags;
96
97 int attempt;
98 int use_smtps;
99 int use_starttls;
100 int use_smtp_tls;
101 int ready;
102
103 struct event ev;
104 struct io *io;
105 int ext;
106
107 size_t ext_size;
108
109 size_t msgtried;
110 size_t msgcount;
111 size_t rcptcount;
112 int hangon;
113
114 enum mta_state state;
115 struct mta_task *task;
116 struct mta_envelope *currevp;
117 FILE *datafp;
118 size_t datalen;
119
120 size_t failures;
121
122 char replybuf[2048];
123 };
124
125 static void mta_session_init(void);
126 static void mta_start(int fd, short ev, void *arg);
127 static void mta_io(struct io *, int, void *);
128 static void mta_free(struct mta_session *);
129 static void mta_getnameinfo_cb(void *, int, const char *, const char *);
130 static void mta_on_ptr(void *, void *, void *);
131 static void mta_on_timeout(struct runq *, void *);
132 static void mta_connect(struct mta_session *);
133 static void mta_enter_state(struct mta_session *, int);
134 static void mta_flush_task(struct mta_session *, int, const char *, size_t, int);
135 static void mta_error(struct mta_session *, const char *, ...)
136 __attribute__((__format__ (printf, 2, 3)));
137 static void mta_send(struct mta_session *, char *, ...)
138 __attribute__((__format__ (printf, 2, 3)));
139 static ssize_t mta_queue_data(struct mta_session *);
140 static void mta_response(struct mta_session *, char *);
141 static const char * mta_strstate(int);
142 static void mta_tls_init(struct mta_session *);
143 static void mta_tls_started(struct mta_session *);
144 static struct mta_session *mta_tree_pop(struct tree *, uint64_t);
145 static const char * dsn_strret(enum dsn_ret);
146 static const char * dsn_strnotify(uint8_t);
147
148 void mta_hoststat_update(const char *, const char *);
149 void mta_hoststat_reschedule(const char *);
150 void mta_hoststat_cache(const char *, uint64_t);
151 void mta_hoststat_uncache(const char *, uint64_t);
152
153
154 static void mta_filter_begin(struct mta_session *);
155 static void mta_filter_end(struct mta_session *);
156 static void mta_connected(struct mta_session *);
157 static void mta_disconnected(struct mta_session *);
158
159 static void mta_report_link_connect(struct mta_session *, const char *, int,
160 const struct sockaddr_storage *,
161 const struct sockaddr_storage *);
162 static void mta_report_link_greeting(struct mta_session *, const char *);
163 static void mta_report_link_identify(struct mta_session *, const char *, const char *);
164 static void mta_report_link_tls(struct mta_session *, const char *);
165 static void mta_report_link_disconnect(struct mta_session *);
166 static void mta_report_link_auth(struct mta_session *, const char *, const char *);
167 static void mta_report_tx_reset(struct mta_session *, uint32_t);
168 static void mta_report_tx_begin(struct mta_session *, uint32_t);
169 static void mta_report_tx_mail(struct mta_session *, uint32_t, const char *, int);
170 static void mta_report_tx_rcpt(struct mta_session *, uint32_t, const char *, int);
171 static void mta_report_tx_envelope(struct mta_session *, uint32_t, uint64_t);
172 static void mta_report_tx_data(struct mta_session *, uint32_t, int);
173 static void mta_report_tx_commit(struct mta_session *, uint32_t, size_t);
174 static void mta_report_tx_rollback(struct mta_session *, uint32_t);
175 static void mta_report_protocol_client(struct mta_session *, const char *);
176 static void mta_report_protocol_server(struct mta_session *, const char *);
177 #if 0
178 static void mta_report_filter_response(struct mta_session *, int, int, const char *);
179 #endif
180 static void mta_report_timeout(struct mta_session *);
181
182
183 static struct tree wait_helo;
184 static struct tree wait_ptr;
185 static struct tree wait_fd;
186 static struct tree wait_tls_init;
187 static struct tree wait_tls_verify;
188
189 static struct runq *hangon;
190
191 #define SESSION_FILTERED(s) \
192 ((s)->relay->dispatcher->u.remote.filtername)
193
194 static void
mta_session_init(void)195 mta_session_init(void)
196 {
197 static int init = 0;
198
199 if (!init) {
200 tree_init(&wait_helo);
201 tree_init(&wait_ptr);
202 tree_init(&wait_fd);
203 tree_init(&wait_tls_init);
204 tree_init(&wait_tls_verify);
205 runq_init(&hangon, mta_on_timeout);
206 init = 1;
207 }
208 }
209
210 void
mta_session(struct mta_relay * relay,struct mta_route * route,const char * mxname)211 mta_session(struct mta_relay *relay, struct mta_route *route, const char *mxname)
212 {
213 struct mta_session *s;
214 struct timeval tv;
215
216 mta_session_init();
217
218 s = xcalloc(1, sizeof *s);
219 s->id = generate_uid();
220 s->relay = relay;
221 s->route = route;
222 s->mxname = xstrdup(mxname);
223
224 mta_filter_begin(s);
225
226 if (relay->flags & RELAY_LMTP)
227 s->flags |= MTA_LMTP;
228 switch (relay->tls) {
229 case RELAY_TLS_SMTPS:
230 s->flags |= MTA_FORCE_SMTPS;
231 s->flags |= MTA_WANT_SECURE;
232 break;
233 case RELAY_TLS_STARTTLS:
234 s->flags |= MTA_FORCE_TLS;
235 s->flags |= MTA_WANT_SECURE;
236 break;
237 case RELAY_TLS_OPPORTUNISTIC:
238 /* do not force anything, try tls then smtp */
239 break;
240 case RELAY_TLS_NO:
241 s->flags |= MTA_FORCE_PLAIN;
242 break;
243 default:
244 fatalx("bad value for relay->tls: %d", relay->tls);
245 }
246
247 log_debug("debug: mta: %p: spawned for relay %s", s,
248 mta_relay_to_text(relay));
249 stat_increment("mta.session", 1);
250
251 if (route->dst->ptrname || route->dst->lastptrquery) {
252 /* We want to delay the connection since to always notify
253 * the relay asynchronously.
254 */
255 tv.tv_sec = 0;
256 tv.tv_usec = 0;
257 evtimer_set(&s->ev, mta_start, s);
258 evtimer_add(&s->ev, &tv);
259 } else if (waitq_wait(&route->dst->ptrname, mta_on_ptr, s)) {
260 resolver_getnameinfo(s->route->dst->sa, NI_NUMERICSERV,
261 mta_getnameinfo_cb, s);
262 }
263 }
264
265 void
mta_session_imsg(struct mproc * p,struct imsg * imsg)266 mta_session_imsg(struct mproc *p, struct imsg *imsg)
267 {
268 struct mta_session *s;
269 struct msg m;
270 uint64_t reqid;
271 const char *name;
272 int status, fd;
273 struct stat sb;
274
275 switch (imsg->hdr.type) {
276
277 case IMSG_MTA_OPEN_MESSAGE:
278 m_msg(&m, imsg);
279 m_get_id(&m, &reqid);
280 m_end(&m);
281
282 fd = imsg_get_fd(imsg);
283 s = mta_tree_pop(&wait_fd, reqid);
284 if (s == NULL) {
285 if (fd != -1)
286 close(fd);
287 return;
288 }
289
290 if (fd == -1) {
291 log_debug("debug: mta: failed to obtain msg fd");
292 mta_flush_task(s, IMSG_MTA_DELIVERY_TEMPFAIL,
293 "Could not get message fd", 0, 0);
294 mta_enter_state(s, MTA_READY);
295 return;
296 }
297
298 if ((s->ext & MTA_EXT_SIZE) && s->ext_size != 0) {
299 if (fstat(fd, &sb) == -1) {
300 log_debug("debug: mta: failed to stat msg fd");
301 mta_flush_task(s, IMSG_MTA_DELIVERY_TEMPFAIL,
302 "Could not stat message fd", 0, 0);
303 mta_enter_state(s, MTA_READY);
304 close(fd);
305 return;
306 }
307 if (sb.st_size > (off_t)s->ext_size) {
308 log_debug("debug: mta: message too large for peer");
309 mta_flush_task(s, IMSG_MTA_DELIVERY_PERMFAIL,
310 "message too large for peer", 0, 0);
311 mta_enter_state(s, MTA_READY);
312 close(fd);
313 return;
314 }
315 }
316
317 s->datafp = fdopen(fd, "r");
318 if (s->datafp == NULL)
319 fatal("mta: fdopen");
320
321 mta_enter_state(s, MTA_MAIL);
322 return;
323
324 case IMSG_MTA_LOOKUP_HELO:
325 m_msg(&m, imsg);
326 m_get_id(&m, &reqid);
327 m_get_int(&m, &status);
328 if (status == LKA_OK)
329 m_get_string(&m, &name);
330 m_end(&m);
331
332 s = mta_tree_pop(&wait_helo, reqid);
333 if (s == NULL)
334 return;
335
336 if (status == LKA_OK) {
337 s->helo = xstrdup(name);
338 mta_connect(s);
339 } else {
340 mta_source_error(s->relay, s->route,
341 "Failed to retrieve helo string");
342 mta_free(s);
343 }
344 return;
345
346 default:
347 fatalx("mta_session_imsg: unexpected %s imsg",
348 imsg_to_str(imsg->hdr.type));
349 }
350 }
351
352 static struct mta_session *
mta_tree_pop(struct tree * wait,uint64_t reqid)353 mta_tree_pop(struct tree *wait, uint64_t reqid)
354 {
355 struct mta_session *s;
356
357 s = tree_xpop(wait, reqid);
358 if (s->flags & MTA_FREE) {
359 log_debug("debug: mta: %p: zombie session", s);
360 mta_free(s);
361 return (NULL);
362 }
363 s->flags &= ~MTA_WAIT;
364
365 return (s);
366 }
367
368 static void
mta_free(struct mta_session * s)369 mta_free(struct mta_session *s)
370 {
371 struct mta_relay *relay;
372 struct mta_route *route;
373
374 log_debug("debug: mta: %p: session done", s);
375
376 mta_disconnected(s);
377
378 if (s->ready)
379 s->relay->nconn_ready -= 1;
380
381 if (s->flags & MTA_HANGON) {
382 log_debug("debug: mta: %p: cancelling hangon timer", s);
383 runq_cancel(hangon, s);
384 }
385
386 if (s->io)
387 io_free(s->io);
388
389 if (s->task)
390 fatalx("current task should have been deleted already");
391 if (s->datafp) {
392 fclose(s->datafp);
393 s->datalen = 0;
394 }
395 free(s->helo);
396
397 relay = s->relay;
398 route = s->route;
399 free(s->username);
400 free(s->mxname);
401 free(s);
402 stat_decrement("mta.session", 1);
403 mta_route_collect(relay, route);
404 }
405
406 static void
mta_getnameinfo_cb(void * arg,int gaierrno,const char * host,const char * serv)407 mta_getnameinfo_cb(void *arg, int gaierrno, const char *host, const char *serv)
408 {
409 struct mta_session *s = arg;
410 struct mta_host *h;
411
412 h = s->route->dst;
413 h->lastptrquery = time(NULL);
414 if (host)
415 h->ptrname = xstrdup(host);
416 waitq_run(&h->ptrname, h->ptrname);
417 }
418
419 static void
mta_on_timeout(struct runq * runq,void * arg)420 mta_on_timeout(struct runq *runq, void *arg)
421 {
422 struct mta_session *s = arg;
423
424 log_debug("mta: timeout for session hangon");
425
426 s->flags &= ~MTA_HANGON;
427 s->hangon++;
428
429 mta_enter_state(s, MTA_READY);
430 }
431
432 static void
mta_on_ptr(void * tag,void * arg,void * data)433 mta_on_ptr(void *tag, void *arg, void *data)
434 {
435 struct mta_session *s = arg;
436
437 mta_connect(s);
438 }
439
440 static void
mta_start(int fd,short ev,void * arg)441 mta_start(int fd, short ev, void *arg)
442 {
443 struct mta_session *s = arg;
444
445 mta_connect(s);
446 }
447
448 static void
mta_connect(struct mta_session * s)449 mta_connect(struct mta_session *s)
450 {
451 struct sockaddr_storage ss;
452 struct sockaddr *sa;
453 int portno;
454 const char *schema;
455
456 if (s->helo == NULL) {
457 if (s->relay->helotable && s->route->src->sa) {
458 m_create(p_lka, IMSG_MTA_LOOKUP_HELO, 0, 0, -1);
459 m_add_id(p_lka, s->id);
460 m_add_string(p_lka, s->relay->helotable);
461 m_add_sockaddr(p_lka, s->route->src->sa);
462 m_close(p_lka);
463 tree_xset(&wait_helo, s->id, s);
464 s->flags |= MTA_WAIT;
465 return;
466 }
467 else if (s->relay->heloname)
468 s->helo = xstrdup(s->relay->heloname);
469 else
470 s->helo = xstrdup(env->sc_hostname);
471 }
472
473 if (s->io) {
474 io_free(s->io);
475 s->io = NULL;
476 }
477
478 s->use_smtps = s->use_starttls = s->use_smtp_tls = 0;
479
480 switch (s->attempt) {
481 case 0:
482 if (s->flags & MTA_FORCE_SMTPS)
483 s->use_smtps = 1; /* smtps */
484 else if (s->flags & (MTA_FORCE_TLS|MTA_FORCE_ANYSSL))
485 s->use_starttls = 1; /* tls, tls+smtps */
486 else if (!(s->flags & MTA_FORCE_PLAIN))
487 s->use_smtp_tls = 1;
488 break;
489 case 1:
490 if (s->flags & MTA_FORCE_ANYSSL) {
491 s->use_smtps = 1; /* tls+smtps */
492 break;
493 }
494 else if (s->flags & MTA_DOWNGRADE_PLAIN) {
495 /* smtp, with tls failure */
496 break;
497 }
498 default:
499 mta_free(s);
500 return;
501 }
502 portno = s->use_smtps ? 465 : 25;
503
504 /* Override with relay-specified port */
505 if (s->relay->port)
506 portno = s->relay->port;
507
508 memmove(&ss, s->route->dst->sa, s->route->dst->sa->sa_len);
509 sa = (struct sockaddr *)&ss;
510
511 if (sa->sa_family == AF_INET)
512 ((struct sockaddr_in *)sa)->sin_port = htons(portno);
513 else if (sa->sa_family == AF_INET6)
514 ((struct sockaddr_in6 *)sa)->sin6_port = htons(portno);
515
516 s->attempt += 1;
517 if (s->use_smtp_tls)
518 schema = "smtp://";
519 else if (s->use_starttls)
520 schema = "smtp+tls://";
521 else if (s->use_smtps)
522 schema = "smtps://";
523 else if (s->flags & MTA_LMTP)
524 schema = "lmtp://";
525 else
526 schema = "smtp+notls://";
527
528 log_info("%016"PRIx64" mta "
529 "connecting address=%s%s:%d host=%s",
530 s->id, schema, sa_to_text(s->route->dst->sa),
531 portno, s->route->dst->ptrname);
532
533 mta_enter_state(s, MTA_INIT);
534 s->io = io_new();
535 io_set_callback(s->io, mta_io, s);
536 io_set_timeout(s->io, 300000);
537 if (io_connect(s->io, sa, s->route->src->sa) == -1) {
538 /*
539 * This error is most likely a "no route",
540 * so there is no need to try again.
541 */
542 log_debug("debug: mta: io_connect failed: %s", io_error(s->io));
543 if (errno == EADDRNOTAVAIL)
544 mta_source_error(s->relay, s->route, io_error(s->io));
545 else
546 mta_error(s, "Connection failed: %s", io_error(s->io));
547 mta_free(s);
548 }
549 }
550
551 static void
mta_enter_state(struct mta_session * s,int newstate)552 mta_enter_state(struct mta_session *s, int newstate)
553 {
554 struct mta_envelope *e;
555 size_t envid_sz;
556 int oldstate;
557 ssize_t q;
558 char ibuf[LINE_MAX];
559 char obuf[LINE_MAX];
560 int offset;
561 const char *srs_sender;
562
563 again:
564 oldstate = s->state;
565
566 log_trace(TRACE_MTA, "mta: %p: %s -> %s", s,
567 mta_strstate(oldstate),
568 mta_strstate(newstate));
569
570 s->state = newstate;
571
572 memset(s->replybuf, 0, sizeof s->replybuf);
573
574 /* don't try this at home! */
575 #define mta_enter_state(_s, _st) do { newstate = _st; goto again; } while (0)
576
577 switch (s->state) {
578 case MTA_INIT:
579 case MTA_BANNER:
580 break;
581
582 case MTA_EHLO:
583 s->ext = 0;
584 mta_send(s, "EHLO %s", s->helo);
585 mta_report_link_identify(s, "EHLO", s->helo);
586 break;
587
588 case MTA_HELO:
589 s->ext = 0;
590 mta_send(s, "HELO %s", s->helo);
591 mta_report_link_identify(s, "HELO", s->helo);
592 break;
593
594 case MTA_LHLO:
595 s->ext = 0;
596 mta_send(s, "LHLO %s", s->helo);
597 mta_report_link_identify(s, "LHLO", s->helo);
598 break;
599
600 case MTA_STARTTLS:
601 if (s->flags & MTA_DOWNGRADE_PLAIN)
602 mta_enter_state(s, MTA_AUTH);
603 if (s->flags & MTA_TLS) /* already started */
604 mta_enter_state(s, MTA_AUTH);
605 else if ((s->ext & MTA_EXT_STARTTLS) == 0) {
606 if (s->flags & MTA_FORCE_TLS || s->flags & MTA_WANT_SECURE) {
607 mta_error(s, "TLS required but not supported by remote host");
608 s->flags |= MTA_RECONN;
609 }
610 else
611 /* server doesn't support starttls, do not use it */
612 mta_enter_state(s, MTA_AUTH);
613 }
614 else
615 mta_send(s, "STARTTLS");
616 break;
617
618 case MTA_AUTH:
619 if (s->relay->secret && s->flags & MTA_TLS) {
620 if (s->ext & MTA_EXT_AUTH) {
621 if (s->ext & MTA_EXT_AUTH_PLAIN) {
622 mta_enter_state(s, MTA_AUTH_PLAIN);
623 break;
624 }
625 if (s->ext & MTA_EXT_AUTH_LOGIN) {
626 mta_enter_state(s, MTA_AUTH_LOGIN);
627 break;
628 }
629 log_debug("debug: mta: %p: no supported AUTH method on session", s);
630 mta_error(s, "no supported AUTH method");
631 }
632 else {
633 log_debug("debug: mta: %p: AUTH not advertised on session", s);
634 mta_error(s, "AUTH not advertised");
635 }
636 }
637 else if (s->relay->secret) {
638 log_debug("debug: mta: %p: not using AUTH on non-TLS "
639 "session", s);
640 mta_error(s, "Refuse to AUTH over insecure channel");
641 mta_connect(s);
642 } else {
643 mta_enter_state(s, MTA_READY);
644 }
645 break;
646
647 case MTA_AUTH_PLAIN:
648 memset(ibuf, 0, sizeof ibuf);
649 if (base64_decode(s->relay->secret, (unsigned char *)ibuf,
650 sizeof(ibuf)-1) == -1) {
651 log_debug("debug: mta: %p: credentials too large on session", s);
652 mta_error(s, "Credentials too large");
653 break;
654 }
655 s->username = xstrdup(ibuf+1);
656 mta_send(s, "AUTH PLAIN %s", s->relay->secret);
657 break;
658
659 case MTA_AUTH_LOGIN:
660 mta_send(s, "AUTH LOGIN");
661 break;
662
663 case MTA_AUTH_LOGIN_USER:
664 memset(ibuf, 0, sizeof ibuf);
665 if (base64_decode(s->relay->secret, (unsigned char *)ibuf,
666 sizeof(ibuf)-1) == -1) {
667 log_debug("debug: mta: %p: credentials too large on session", s);
668 mta_error(s, "Credentials too large");
669 break;
670 }
671 s->username = xstrdup(ibuf+1);
672
673 memset(obuf, 0, sizeof obuf);
674 base64_encode((unsigned char *)ibuf + 1, strlen(ibuf + 1), obuf, sizeof obuf);
675 mta_send(s, "%s", obuf);
676
677 memset(ibuf, 0, sizeof ibuf);
678 memset(obuf, 0, sizeof obuf);
679 break;
680
681 case MTA_AUTH_LOGIN_PASS:
682 memset(ibuf, 0, sizeof ibuf);
683 if (base64_decode(s->relay->secret, (unsigned char *)ibuf,
684 sizeof(ibuf)-1) == -1) {
685 log_debug("debug: mta: %p: credentials too large on session", s);
686 mta_error(s, "Credentials too large");
687 break;
688 }
689
690 offset = strlen(ibuf+1)+2;
691 memset(obuf, 0, sizeof obuf);
692 base64_encode((unsigned char *)ibuf + offset, strlen(ibuf + offset), obuf, sizeof obuf);
693 mta_send(s, "%s", obuf);
694
695 memset(ibuf, 0, sizeof ibuf);
696 memset(obuf, 0, sizeof obuf);
697 break;
698
699 case MTA_READY:
700 /* Ready to send a new mail */
701 if (s->ready == 0) {
702 s->ready = 1;
703 s->relay->nconn_ready += 1;
704 mta_route_ok(s->relay, s->route);
705 }
706
707 if (s->msgtried >= MAX_TRYBEFOREDISABLE) {
708 log_info("%016"PRIx64" mta host-rejects-all-mails",
709 s->id);
710 mta_route_down(s->relay, s->route);
711 mta_enter_state(s, MTA_QUIT);
712 break;
713 }
714
715 if (s->msgcount >= s->relay->limits->max_mail_per_session) {
716 log_debug("debug: mta: "
717 "%p: cannot send more message to relay %s", s,
718 mta_relay_to_text(s->relay));
719 mta_enter_state(s, MTA_QUIT);
720 break;
721 }
722
723 /*
724 * When downgrading from opportunistic TLS, clear flag and
725 * possibly reuse the same task (forbidden in other cases).
726 */
727 if (s->flags & MTA_DOWNGRADE_PLAIN)
728 s->flags &= ~MTA_DOWNGRADE_PLAIN;
729 else if (s->task)
730 fatalx("task should be NULL at this point");
731
732 if (s->task == NULL)
733 s->task = mta_route_next_task(s->relay, s->route);
734 if (s->task == NULL) {
735 log_debug("debug: mta: %p: no task for relay %s",
736 s, mta_relay_to_text(s->relay));
737
738 if (s->relay->nconn > 1 ||
739 s->hangon >= s->relay->limits->sessdelay_keepalive) {
740 mta_enter_state(s, MTA_QUIT);
741 break;
742 }
743
744 log_debug("mta: debug: last connection: hanging on for %llds",
745 (long long)(s->relay->limits->sessdelay_keepalive -
746 s->hangon));
747 s->flags |= MTA_HANGON;
748 runq_schedule(hangon, 1, s);
749 break;
750 }
751
752 log_debug("debug: mta: %p: handling next task for relay %s", s,
753 mta_relay_to_text(s->relay));
754
755 stat_increment("mta.task.running", 1);
756
757 m_create(p_queue, IMSG_MTA_OPEN_MESSAGE, 0, 0, -1);
758 m_add_id(p_queue, s->id);
759 m_add_msgid(p_queue, s->task->msgid);
760 m_close(p_queue);
761
762 tree_xset(&wait_fd, s->id, s);
763 s->flags |= MTA_WAIT;
764 break;
765
766 case MTA_MAIL:
767 s->currevp = TAILQ_FIRST(&s->task->envelopes);
768
769 e = s->currevp;
770 s->hangon = 0;
771 s->msgtried++;
772 envid_sz = strlen(e->dsn_envid);
773
774 /* SRS-encode if requested for the relay action, AND we're not
775 * bouncing, AND we have an RCPT which means we are forwarded,
776 * AND the RCPT has a '@' just for sanity check (will always).
777 */
778 if (env->sc_srs_key != NULL &&
779 s->relay->srs &&
780 strchr(s->task->sender, '@') &&
781 e->rcpt &&
782 strchr(e->rcpt, '@')) {
783 /* encode and replace task sender with new SRS-sender */
784 srs_sender = srs_encode(s->task->sender,
785 strchr(e->rcpt, '@') + 1);
786 if (srs_sender) {
787 free(s->task->sender);
788 s->task->sender = xstrdup(srs_sender);
789 }
790 }
791
792 if (s->ext & MTA_EXT_DSN) {
793 mta_send(s, "MAIL FROM:<%s>%s%s%s%s",
794 s->task->sender,
795 e->dsn_ret ? " RET=" : "",
796 e->dsn_ret ? dsn_strret(e->dsn_ret) : "",
797 envid_sz ? " ENVID=" : "",
798 envid_sz ? e->dsn_envid : "");
799 } else
800 mta_send(s, "MAIL FROM:<%s>", s->task->sender);
801 break;
802
803 case MTA_RCPT:
804 if (s->currevp == NULL)
805 s->currevp = TAILQ_FIRST(&s->task->envelopes);
806
807 e = s->currevp;
808 if (s->ext & MTA_EXT_DSN) {
809 mta_send(s, "RCPT TO:<%s>%s%s%s%s",
810 e->dest,
811 e->dsn_notify ? " NOTIFY=" : "",
812 e->dsn_notify ? dsn_strnotify(e->dsn_notify) : "",
813 e->dsn_orcpt ? " ORCPT=" : "",
814 e->dsn_orcpt ? e->dsn_orcpt : "");
815 } else
816 mta_send(s, "RCPT TO:<%s>", e->dest);
817
818 mta_report_tx_envelope(s, s->task->msgid, e->id);
819 s->rcptcount++;
820 break;
821
822 case MTA_DATA:
823 fseek(s->datafp, 0, SEEK_SET);
824 mta_send(s, "DATA");
825 break;
826
827 case MTA_BODY:
828 if (s->datafp == NULL) {
829 log_trace(TRACE_MTA, "mta: %p: end-of-file", s);
830 mta_enter_state(s, MTA_EOM);
831 break;
832 }
833
834 if ((q = mta_queue_data(s)) == -1) {
835 s->flags |= MTA_FREE;
836 break;
837 }
838 if (q == 0) {
839 mta_enter_state(s, MTA_BODY);
840 break;
841 }
842
843 log_trace(TRACE_MTA, "mta: %p: >>> [...%zd bytes...]", s, q);
844 break;
845
846 case MTA_EOM:
847 mta_send(s, ".");
848 break;
849
850 case MTA_LMTP_EOM:
851 /* LMTP reports status of each delivery, so enable read */
852 io_set_read(s->io);
853 break;
854
855 case MTA_RSET:
856 if (s->datafp) {
857 fclose(s->datafp);
858 s->datafp = NULL;
859 s->datalen = 0;
860 }
861 mta_send(s, "RSET");
862 break;
863
864 case MTA_QUIT:
865 mta_send(s, "QUIT");
866 break;
867
868 default:
869 fatalx("mta_enter_state: unknown state");
870 }
871 #undef mta_enter_state
872 }
873
874 /*
875 * Handle a response to an SMTP command
876 */
877 static void
mta_response(struct mta_session * s,char * line)878 mta_response(struct mta_session *s, char *line)
879 {
880 struct mta_envelope *e;
881 struct sockaddr_storage ss;
882 struct sockaddr *sa;
883 const char *domain;
884 char *pbuf;
885 socklen_t sa_len;
886 char buf[LINE_MAX];
887 int delivery;
888
889 switch (s->state) {
890
891 case MTA_BANNER:
892 if (line[0] != '2') {
893 mta_error(s, "BANNER rejected: %s", line);
894 s->flags |= MTA_FREE;
895 return;
896 }
897
898 pbuf = "";
899 if (strlen(line) > 4) {
900 (void)strlcpy(buf, line + 4, sizeof buf);
901 if ((pbuf = strchr(buf, ' ')))
902 *pbuf = '\0';
903 pbuf = valid_domainpart(buf) ? buf : "";
904 }
905 mta_report_link_greeting(s, pbuf);
906
907 if (s->flags & MTA_LMTP)
908 mta_enter_state(s, MTA_LHLO);
909 else
910 mta_enter_state(s, MTA_EHLO);
911 break;
912
913 case MTA_EHLO:
914 if (line[0] != '2') {
915 /* rejected at ehlo state */
916 if ((s->relay->flags & RELAY_AUTH) ||
917 (s->flags & MTA_WANT_SECURE)) {
918 mta_error(s, "EHLO rejected: %s", line);
919 s->flags |= MTA_FREE;
920 return;
921 }
922 mta_enter_state(s, MTA_HELO);
923 return;
924 }
925 if (!(s->flags & MTA_FORCE_PLAIN))
926 mta_enter_state(s, MTA_STARTTLS);
927 else
928 mta_enter_state(s, MTA_READY);
929 break;
930
931 case MTA_HELO:
932 if (line[0] != '2') {
933 mta_error(s, "HELO rejected: %s", line);
934 s->flags |= MTA_FREE;
935 return;
936 }
937 mta_enter_state(s, MTA_READY);
938 break;
939
940 case MTA_LHLO:
941 if (line[0] != '2') {
942 mta_error(s, "LHLO rejected: %s", line);
943 s->flags |= MTA_FREE;
944 return;
945 }
946 mta_enter_state(s, MTA_READY);
947 break;
948
949 case MTA_STARTTLS:
950 if (line[0] != '2') {
951 if (!(s->flags & MTA_WANT_SECURE)) {
952 mta_enter_state(s, MTA_AUTH);
953 return;
954 }
955 /* XXX mark that the MX doesn't support STARTTLS */
956 mta_error(s, "STARTTLS rejected: %s", line);
957 s->flags |= MTA_FREE;
958 return;
959 }
960
961 mta_tls_init(s);
962 break;
963
964 case MTA_AUTH_PLAIN:
965 if (line[0] != '2') {
966 mta_error(s, "AUTH rejected: %s", line);
967 mta_report_link_auth(s, s->username, "fail");
968 s->flags |= MTA_FREE;
969 return;
970 }
971 mta_report_link_auth(s, s->username, "pass");
972 mta_enter_state(s, MTA_READY);
973 break;
974
975 case MTA_AUTH_LOGIN:
976 if (strncmp(line, "334 ", 4) != 0) {
977 mta_error(s, "AUTH rejected: %s", line);
978 mta_report_link_auth(s, s->username, "fail");
979 s->flags |= MTA_FREE;
980 return;
981 }
982 mta_enter_state(s, MTA_AUTH_LOGIN_USER);
983 break;
984
985 case MTA_AUTH_LOGIN_USER:
986 if (strncmp(line, "334 ", 4) != 0) {
987 mta_error(s, "AUTH rejected: %s", line);
988 mta_report_link_auth(s, s->username, "fail");
989 s->flags |= MTA_FREE;
990 return;
991 }
992 mta_enter_state(s, MTA_AUTH_LOGIN_PASS);
993 break;
994
995 case MTA_AUTH_LOGIN_PASS:
996 if (line[0] != '2') {
997 mta_error(s, "AUTH rejected: %s", line);
998 mta_report_link_auth(s, s->username, "fail");
999 s->flags |= MTA_FREE;
1000 return;
1001 }
1002 mta_report_link_auth(s, s->username, "pass");
1003 mta_enter_state(s, MTA_READY);
1004 break;
1005
1006 case MTA_MAIL:
1007 if (line[0] != '2') {
1008 if (line[0] == '5')
1009 delivery = IMSG_MTA_DELIVERY_PERMFAIL;
1010 else
1011 delivery = IMSG_MTA_DELIVERY_TEMPFAIL;
1012
1013 mta_flush_task(s, delivery, line, 0, 0);
1014 mta_enter_state(s, MTA_RSET);
1015 return;
1016 }
1017 mta_report_tx_begin(s, s->task->msgid);
1018 mta_report_tx_mail(s, s->task->msgid, s->task->sender, 1);
1019 mta_enter_state(s, MTA_RCPT);
1020 break;
1021
1022 case MTA_RCPT:
1023 e = s->currevp;
1024
1025 /* remove envelope from hosttat cache if there */
1026 if ((domain = strchr(e->dest, '@')) != NULL) {
1027 domain++;
1028 mta_hoststat_uncache(domain, e->id);
1029 }
1030
1031 s->currevp = TAILQ_NEXT(s->currevp, entry);
1032 if (line[0] == '2') {
1033 s->failures = 0;
1034 /*
1035 * this host is up, reschedule envelopes that
1036 * were cached for reschedule.
1037 */
1038 if (domain)
1039 mta_hoststat_reschedule(domain);
1040 }
1041 else {
1042 mta_report_tx_rollback(s, s->task->msgid);
1043 mta_report_tx_reset(s, s->task->msgid);
1044 if (line[0] == '5')
1045 delivery = IMSG_MTA_DELIVERY_PERMFAIL;
1046 else
1047 delivery = IMSG_MTA_DELIVERY_TEMPFAIL;
1048 s->failures++;
1049
1050 /* remove failed envelope from task list */
1051 TAILQ_REMOVE(&s->task->envelopes, e, entry);
1052 stat_decrement("mta.envelope", 1);
1053
1054 /* log right away */
1055 (void)snprintf(buf, sizeof(buf), "%s",
1056 mta_host_to_text(s->route->dst));
1057
1058 e->session = s->id;
1059 /* XXX */
1060 /*
1061 * getsockname() can only fail with ENOBUFS here
1062 * best effort, don't log source ...
1063 */
1064 sa_len = sizeof(ss);
1065 sa = (struct sockaddr *)&ss;
1066 if (getsockname(io_fileno(s->io), sa, &sa_len) == -1)
1067 mta_delivery_log(e, NULL, buf, delivery, line);
1068 else
1069 mta_delivery_log(e, sa_to_text(sa),
1070 buf, delivery, line);
1071
1072 if (domain)
1073 mta_hoststat_update(domain, e->status);
1074 mta_delivery_notify(e);
1075
1076 if (s->relay->limits->max_failures_per_session &&
1077 s->failures == s->relay->limits->max_failures_per_session) {
1078 mta_flush_task(s, IMSG_MTA_DELIVERY_TEMPFAIL,
1079 "Too many consecutive errors, closing connection", 0, 1);
1080 mta_enter_state(s, MTA_QUIT);
1081 break;
1082 }
1083
1084 /*
1085 * if no more envelopes, flush failed queue
1086 */
1087 if (TAILQ_EMPTY(&s->task->envelopes)) {
1088 mta_flush_task(s, IMSG_MTA_DELIVERY_OK,
1089 "No envelope", 0, 0);
1090 mta_enter_state(s, MTA_RSET);
1091 break;
1092 }
1093 }
1094
1095 switch (line[0]) {
1096 case '2':
1097 mta_report_tx_rcpt(s,
1098 s->task->msgid, e->dest, 1);
1099 break;
1100 case '4':
1101 mta_report_tx_rcpt(s,
1102 s->task->msgid, e->dest, -1);
1103 break;
1104 case '5':
1105 mta_report_tx_rcpt(s,
1106 s->task->msgid, e->dest, 0);
1107 break;
1108 }
1109
1110 if (s->currevp == NULL)
1111 mta_enter_state(s, MTA_DATA);
1112 else
1113 mta_enter_state(s, MTA_RCPT);
1114 break;
1115
1116 case MTA_DATA:
1117 if (line[0] == '2' || line[0] == '3') {
1118 mta_report_tx_data(s, s->task->msgid, 1);
1119 mta_enter_state(s, MTA_BODY);
1120 break;
1121 }
1122
1123 if (line[0] == '5')
1124 delivery = IMSG_MTA_DELIVERY_PERMFAIL;
1125 else
1126 delivery = IMSG_MTA_DELIVERY_TEMPFAIL;
1127 mta_report_tx_data(s, s->task->msgid,
1128 delivery == IMSG_MTA_DELIVERY_TEMPFAIL ? -1 : 0);
1129 mta_report_tx_rollback(s, s->task->msgid);
1130 mta_report_tx_reset(s, s->task->msgid);
1131 mta_flush_task(s, delivery, line, 0, 0);
1132 mta_enter_state(s, MTA_RSET);
1133 break;
1134
1135 case MTA_LMTP_EOM:
1136 case MTA_EOM:
1137 if (line[0] == '2') {
1138 delivery = IMSG_MTA_DELIVERY_OK;
1139 s->msgtried = 0;
1140 s->msgcount++;
1141 }
1142 else if (line[0] == '5')
1143 delivery = IMSG_MTA_DELIVERY_PERMFAIL;
1144 else
1145 delivery = IMSG_MTA_DELIVERY_TEMPFAIL;
1146 if (delivery != IMSG_MTA_DELIVERY_OK) {
1147 mta_report_tx_rollback(s, s->task->msgid);
1148 mta_report_tx_reset(s, s->task->msgid);
1149 }
1150 else {
1151 mta_report_tx_commit(s, s->task->msgid, s->datalen);
1152 mta_report_tx_reset(s, s->task->msgid);
1153 }
1154 mta_flush_task(s, delivery, line, (s->flags & MTA_LMTP) ? 1 : 0, 0);
1155 if (s->task) {
1156 s->rcptcount--;
1157 mta_enter_state(s, MTA_LMTP_EOM);
1158 } else {
1159 s->rcptcount = 0;
1160 if (s->relay->limits->sessdelay_transaction) {
1161 log_debug("debug: mta: waiting for %llds before next transaction",
1162 (long long)s->relay->limits->sessdelay_transaction);
1163 s->hangon = s->relay->limits->sessdelay_transaction -1;
1164 s->flags |= MTA_HANGON;
1165 runq_schedule(hangon,
1166 s->relay->limits->sessdelay_transaction, s);
1167 }
1168 else
1169 mta_enter_state(s, MTA_READY);
1170 }
1171 break;
1172
1173 case MTA_RSET:
1174 s->rcptcount = 0;
1175
1176 if (s->task) {
1177 mta_report_tx_rollback(s, s->task->msgid);
1178 mta_report_tx_reset(s, s->task->msgid);
1179 }
1180 if (s->relay->limits->sessdelay_transaction) {
1181 log_debug("debug: mta: waiting for %llds after reset",
1182 (long long)s->relay->limits->sessdelay_transaction);
1183 s->hangon = s->relay->limits->sessdelay_transaction -1;
1184 s->flags |= MTA_HANGON;
1185 runq_schedule(hangon,
1186 s->relay->limits->sessdelay_transaction, s);
1187 }
1188 else
1189 mta_enter_state(s, MTA_READY);
1190 break;
1191
1192 default:
1193 fatalx("mta_response() bad state");
1194 }
1195 }
1196
1197 static void
mta_io(struct io * io,int evt,void * arg)1198 mta_io(struct io *io, int evt, void *arg)
1199 {
1200 struct mta_session *s = arg;
1201 char *line, *msg, *p;
1202 size_t len;
1203 const char *error;
1204 int cont;
1205
1206 log_trace(TRACE_IO, "mta: %p: %s %s", s, io_strevent(evt),
1207 io_strio(io));
1208
1209 switch (evt) {
1210
1211 case IO_CONNECTED:
1212 mta_connected(s);
1213
1214 if (s->use_smtps) {
1215 io_set_write(io);
1216 mta_tls_init(s);
1217 if (s->flags & MTA_FREE)
1218 mta_free(s);
1219 }
1220 else {
1221 mta_enter_state(s, MTA_BANNER);
1222 io_set_read(io);
1223 }
1224 break;
1225
1226 case IO_TLSREADY:
1227 log_info("%016"PRIx64" mta tls ciphers=%s",
1228 s->id, tls_to_text(io_tls(s->io)));
1229 s->flags |= MTA_TLS;
1230 if (s->relay->dispatcher->u.remote.tls_verify)
1231 s->flags |= MTA_TLS_VERIFIED;
1232
1233 mta_tls_started(s);
1234 mta_report_link_tls(s,
1235 tls_to_text(io_tls(s->io)));
1236 break;
1237
1238 case IO_DATAIN:
1239 nextline:
1240 line = io_getline(s->io, &len);
1241 if (line == NULL) {
1242 if (io_datalen(s->io) >= LINE_MAX) {
1243 mta_error(s, "Input too long");
1244 mta_free(s);
1245 }
1246 return;
1247 }
1248
1249 /* Strip trailing '\r' */
1250 if (len && line[len - 1] == '\r')
1251 line[--len] = '\0';
1252
1253 log_trace(TRACE_MTA, "mta: %p: <<< %s", s, line);
1254 mta_report_protocol_server(s, line);
1255
1256 if ((error = parse_smtp_response(line, len, &msg, &cont))) {
1257 mta_error(s, "Bad response: %s", error);
1258 mta_free(s);
1259 return;
1260 }
1261
1262 /* read extensions */
1263 if (s->state == MTA_EHLO) {
1264 if (strcmp(msg, "STARTTLS") == 0)
1265 s->ext |= MTA_EXT_STARTTLS;
1266 else if (strncmp(msg, "AUTH ", 5) == 0) {
1267 s->ext |= MTA_EXT_AUTH;
1268 if ((p = strstr(msg, " PLAIN")) &&
1269 (*(p+6) == '\0' || *(p+6) == ' '))
1270 s->ext |= MTA_EXT_AUTH_PLAIN;
1271 if ((p = strstr(msg, " LOGIN")) &&
1272 (*(p+6) == '\0' || *(p+6) == ' '))
1273 s->ext |= MTA_EXT_AUTH_LOGIN;
1274 }
1275 else if (strcmp(msg, "PIPELINING") == 0)
1276 s->ext |= MTA_EXT_PIPELINING;
1277 else if (strcmp(msg, "DSN") == 0)
1278 s->ext |= MTA_EXT_DSN;
1279 else if (strncmp(msg, "SIZE ", 5) == 0) {
1280 s->ext_size = strtonum(msg+5, 0, UINT32_MAX, &error);
1281 if (error == NULL)
1282 s->ext |= MTA_EXT_SIZE;
1283 }
1284 }
1285
1286 /* continuation reply, we parse out the repeating statuses and ESC */
1287 if (cont) {
1288 if (s->replybuf[0] == '\0')
1289 (void)strlcat(s->replybuf, line, sizeof s->replybuf);
1290 else if (len > 4) {
1291 p = line + 4;
1292 if (isdigit((unsigned char)p[0]) && p[1] == '.' &&
1293 isdigit((unsigned char)p[2]) && p[3] == '.' &&
1294 isdigit((unsigned char)p[4]) && isspace((unsigned char)p[5]))
1295 p += 5;
1296 (void)strlcat(s->replybuf, p, sizeof s->replybuf);
1297 }
1298 goto nextline;
1299 }
1300
1301 /* last line of a reply, check if we're on a continuation to parse out status and ESC.
1302 * if we overflow reply buffer or are not on continuation, log entire last line.
1303 */
1304 if (s->replybuf[0] == '\0')
1305 (void)strlcat(s->replybuf, line, sizeof s->replybuf);
1306 else if (len > 4) {
1307 p = line + 4;
1308 if (isdigit((unsigned char)p[0]) && p[1] == '.' &&
1309 isdigit((unsigned char)p[2]) && p[3] == '.' &&
1310 isdigit((unsigned char)p[4]) && isspace((unsigned char)p[5]))
1311 p += 5;
1312 if (strlcat(s->replybuf, p, sizeof s->replybuf) >= sizeof s->replybuf)
1313 (void)strlcpy(s->replybuf, line, sizeof s->replybuf);
1314 }
1315
1316 if (s->state == MTA_QUIT) {
1317 log_info("%016"PRIx64" mta disconnected reason=quit messages=%zu",
1318 s->id, s->msgcount);
1319 mta_free(s);
1320 return;
1321 }
1322 io_set_write(io);
1323 mta_response(s, s->replybuf);
1324 if (s->flags & MTA_FREE) {
1325 mta_free(s);
1326 return;
1327 }
1328 if (s->flags & MTA_RECONN) {
1329 s->flags &= ~MTA_RECONN;
1330 mta_connect(s);
1331 return;
1332 }
1333
1334 if (io_datalen(s->io)) {
1335 log_debug("debug: mta: remaining data in input buffer");
1336 mta_error(s, "Remote host sent too much data");
1337 if (s->flags & MTA_WAIT)
1338 s->flags |= MTA_FREE;
1339 else
1340 mta_free(s);
1341 }
1342 break;
1343
1344 case IO_LOWAT:
1345 if (s->state == MTA_BODY) {
1346 mta_enter_state(s, MTA_BODY);
1347 if (s->flags & MTA_FREE) {
1348 mta_free(s);
1349 return;
1350 }
1351 }
1352
1353 if (io_queued(s->io) == 0)
1354 io_set_read(io);
1355 break;
1356
1357 case IO_TIMEOUT:
1358 log_debug("debug: mta: %p: connection timeout", s);
1359 mta_error(s, "Connection timeout");
1360 mta_report_timeout(s);
1361 if (!s->ready)
1362 mta_connect(s);
1363 else
1364 mta_free(s);
1365 break;
1366
1367 case IO_ERROR:
1368 log_debug("debug: mta: %p: IO error: %s", s, io_error(io));
1369
1370 if (s->state == MTA_STARTTLS && s->use_smtp_tls) {
1371 /* error in non-strict SSL negotiation, downgrade to plain */
1372 log_info("smtp-out: Error on session %016"PRIx64
1373 ": opportunistic TLS failed, "
1374 "downgrading to plain", s->id);
1375 s->flags &= ~MTA_TLS;
1376 s->flags |= MTA_DOWNGRADE_PLAIN;
1377 mta_connect(s);
1378 break;
1379 }
1380
1381 mta_error(s, "IO Error: %s", io_error(io));
1382 mta_free(s);
1383 break;
1384
1385 case IO_DISCONNECTED:
1386 log_debug("debug: mta: %p: disconnected in state %s",
1387 s, mta_strstate(s->state));
1388 mta_error(s, "Connection closed unexpectedly");
1389 if (!s->ready)
1390 mta_connect(s);
1391 else
1392 mta_free(s);
1393 break;
1394
1395 default:
1396 fatalx("mta_io() bad event");
1397 }
1398 }
1399
1400 static void
mta_send(struct mta_session * s,char * fmt,...)1401 mta_send(struct mta_session *s, char *fmt, ...)
1402 {
1403 va_list ap;
1404 char *p;
1405 int len;
1406
1407 va_start(ap, fmt);
1408 if ((len = vasprintf(&p, fmt, ap)) == -1)
1409 fatal("mta: vasprintf");
1410 va_end(ap);
1411
1412 log_trace(TRACE_MTA, "mta: %p: >>> %s", s, p);
1413
1414 if (strncasecmp(p, "AUTH PLAIN ", 11) == 0)
1415 mta_report_protocol_client(s, "AUTH PLAIN ********");
1416 else if (s->state == MTA_AUTH_LOGIN_USER || s->state == MTA_AUTH_LOGIN_PASS)
1417 mta_report_protocol_client(s, "********");
1418 else
1419 mta_report_protocol_client(s, p);
1420
1421 io_xprintf(s->io, "%s\r\n", p);
1422
1423 free(p);
1424 }
1425
1426 /*
1427 * Queue some data into the input buffer
1428 */
1429 static ssize_t
mta_queue_data(struct mta_session * s)1430 mta_queue_data(struct mta_session *s)
1431 {
1432 char *ln = NULL;
1433 size_t sz = 0, q;
1434 ssize_t len;
1435
1436 q = io_queued(s->io);
1437
1438 while (io_queued(s->io) < MTA_HIWAT) {
1439 if ((len = getline(&ln, &sz, s->datafp)) == -1)
1440 break;
1441 if (ln[len - 1] == '\n')
1442 ln[len - 1] = '\0';
1443 s->datalen += io_xprintf(s->io, "%s%s\r\n", *ln == '.' ? "." : "", ln);
1444 }
1445
1446 free(ln);
1447 if (ferror(s->datafp)) {
1448 mta_flush_task(s, IMSG_MTA_DELIVERY_TEMPFAIL,
1449 "Error reading content file", 0, 0);
1450 return (-1);
1451 }
1452
1453 if (feof(s->datafp)) {
1454 fclose(s->datafp);
1455 s->datafp = NULL;
1456 }
1457
1458 return (io_queued(s->io) - q);
1459 }
1460
1461 static void
mta_flush_task(struct mta_session * s,int delivery,const char * error,size_t count,int cache)1462 mta_flush_task(struct mta_session *s, int delivery, const char *error, size_t count,
1463 int cache)
1464 {
1465 struct mta_envelope *e;
1466 char relay[LINE_MAX];
1467 size_t n;
1468 struct sockaddr_storage ss;
1469 struct sockaddr *sa;
1470 socklen_t sa_len;
1471 const char *domain;
1472
1473 (void)snprintf(relay, sizeof relay, "%s", mta_host_to_text(s->route->dst));
1474 n = 0;
1475 while ((e = TAILQ_FIRST(&s->task->envelopes))) {
1476
1477 if (count && n == count) {
1478 stat_decrement("mta.envelope", n);
1479 return;
1480 }
1481
1482 TAILQ_REMOVE(&s->task->envelopes, e, entry);
1483
1484 /* we're about to log, associate session to envelope */
1485 e->session = s->id;
1486 e->ext = s->ext;
1487
1488 /* XXX */
1489 /*
1490 * getsockname() can only fail with ENOBUFS here
1491 * best effort, don't log source ...
1492 */
1493 sa = (struct sockaddr *)&ss;
1494 sa_len = sizeof(ss);
1495 if (getsockname(io_fileno(s->io), sa, &sa_len) == -1)
1496 mta_delivery_log(e, NULL, relay, delivery, error);
1497 else
1498 mta_delivery_log(e, sa_to_text(sa),
1499 relay, delivery, error);
1500
1501 mta_delivery_notify(e);
1502
1503 domain = strchr(e->dest, '@');
1504 if (domain) {
1505 domain++;
1506 mta_hoststat_update(domain, error);
1507 if (cache)
1508 mta_hoststat_cache(domain, e->id);
1509 }
1510
1511 n++;
1512 }
1513
1514 free(s->task->sender);
1515 free(s->task);
1516 s->task = NULL;
1517
1518 if (s->datafp) {
1519 fclose(s->datafp);
1520 s->datafp = NULL;
1521 }
1522
1523 stat_decrement("mta.envelope", n);
1524 stat_decrement("mta.task.running", 1);
1525 stat_decrement("mta.task", 1);
1526 }
1527
1528 static void
mta_error(struct mta_session * s,const char * fmt,...)1529 mta_error(struct mta_session *s, const char *fmt, ...)
1530 {
1531 va_list ap;
1532 char *error;
1533 int len;
1534
1535 va_start(ap, fmt);
1536 if ((len = vasprintf(&error, fmt, ap)) == -1)
1537 fatal("mta: vasprintf");
1538 va_end(ap);
1539
1540 if (s->msgcount)
1541 log_info("smtp-out: Error on session %016"PRIx64
1542 " after %zu message%s sent: %s", s->id, s->msgcount,
1543 (s->msgcount > 1) ? "s" : "", error);
1544 else
1545 log_info("%016"PRIx64" mta error reason=%s",
1546 s->id, error);
1547
1548 /*
1549 * If not connected yet, and the error is not local, just ignore it
1550 * and try to reconnect.
1551 */
1552 if (s->state == MTA_INIT &&
1553 (errno == ETIMEDOUT || errno == ECONNREFUSED)) {
1554 log_debug("debug: mta: not reporting route error yet");
1555 free(error);
1556 return;
1557 }
1558
1559 mta_route_error(s->relay, s->route);
1560
1561 if (s->task)
1562 mta_flush_task(s, IMSG_MTA_DELIVERY_TEMPFAIL, error, 0, 0);
1563
1564 free(error);
1565 }
1566
1567 static void
mta_tls_init(struct mta_session * s)1568 mta_tls_init(struct mta_session *s)
1569 {
1570 struct dispatcher_remote *remote;
1571 struct tls *tls;
1572
1573 if ((tls = tls_client()) == NULL) {
1574 log_info("%016"PRIx64" mta closing reason=tls-failure", s->id);
1575 s->flags |= MTA_FREE;
1576 return;
1577 }
1578
1579 remote = &s->relay->dispatcher->u.remote;
1580 if ((s->flags & MTA_WANT_SECURE) && !remote->tls_required) {
1581 /* If TLS not explicitly configured, use implicit config. */
1582 remote->tls_required = 1;
1583 remote->tls_verify = 1;
1584 tls_config_verify(remote->tls_config);
1585 }
1586 if (tls_configure(tls, remote->tls_config) == -1) {
1587 log_info("%016"PRIx64" mta closing reason=tls-failure", s->id);
1588 tls_free(tls);
1589 s->flags |= MTA_FREE;
1590 return;
1591 }
1592
1593 if (io_connect_tls(s->io, tls, s->mxname) == -1) {
1594 log_info("%016"PRIx64" mta closing reason=tls-connect-failed", s->id);
1595 tls_free(tls);
1596 s->flags |= MTA_FREE;
1597 }
1598 }
1599
1600 static void
mta_tls_started(struct mta_session * s)1601 mta_tls_started(struct mta_session *s)
1602 {
1603 if (tls_peer_cert_provided(io_tls(s->io))) {
1604 log_info("%016"PRIx64" mta "
1605 "cert-check result=\"%s\" fingerprint=\"%s\"",
1606 s->id,
1607 (s->flags & MTA_TLS_VERIFIED) ? "valid" : "unverified",
1608 tls_peer_cert_hash(io_tls(s->io)));
1609 }
1610 else {
1611 log_info("%016"PRIx64" smtp "
1612 "cert-check result=\"no certificate presented\"",
1613 s->id);
1614 }
1615
1616 if (s->use_smtps) {
1617 mta_enter_state(s, MTA_BANNER);
1618 io_set_read(s->io);
1619 }
1620 else
1621 mta_enter_state(s, MTA_EHLO);
1622 }
1623
1624 static const char *
dsn_strret(enum dsn_ret ret)1625 dsn_strret(enum dsn_ret ret)
1626 {
1627 if (ret == DSN_RETHDRS)
1628 return "HDRS";
1629 else if (ret == DSN_RETFULL)
1630 return "FULL";
1631 else {
1632 log_debug("mta: invalid ret %d", ret);
1633 return "???";
1634 }
1635 }
1636
1637 static const char *
dsn_strnotify(uint8_t arg)1638 dsn_strnotify(uint8_t arg)
1639 {
1640 static char buf[32];
1641 size_t sz;
1642
1643 buf[0] = '\0';
1644 if (arg & DSN_SUCCESS)
1645 (void)strlcat(buf, "SUCCESS,", sizeof(buf));
1646
1647 if (arg & DSN_FAILURE)
1648 (void)strlcat(buf, "FAILURE,", sizeof(buf));
1649
1650 if (arg & DSN_DELAY)
1651 (void)strlcat(buf, "DELAY,", sizeof(buf));
1652
1653 if (arg & DSN_NEVER)
1654 (void)strlcat(buf, "NEVER,", sizeof(buf));
1655
1656 /* trim trailing comma */
1657 sz = strlen(buf);
1658 if (sz)
1659 buf[sz - 1] = '\0';
1660
1661 return (buf);
1662 }
1663
1664 #define CASE(x) case x : return #x
1665
1666 static const char *
mta_strstate(int state)1667 mta_strstate(int state)
1668 {
1669 switch (state) {
1670 CASE(MTA_INIT);
1671 CASE(MTA_BANNER);
1672 CASE(MTA_EHLO);
1673 CASE(MTA_HELO);
1674 CASE(MTA_STARTTLS);
1675 CASE(MTA_AUTH);
1676 CASE(MTA_AUTH_PLAIN);
1677 CASE(MTA_AUTH_LOGIN);
1678 CASE(MTA_AUTH_LOGIN_USER);
1679 CASE(MTA_AUTH_LOGIN_PASS);
1680 CASE(MTA_READY);
1681 CASE(MTA_MAIL);
1682 CASE(MTA_RCPT);
1683 CASE(MTA_DATA);
1684 CASE(MTA_BODY);
1685 CASE(MTA_EOM);
1686 CASE(MTA_LMTP_EOM);
1687 CASE(MTA_RSET);
1688 CASE(MTA_QUIT);
1689 default:
1690 return "MTA_???";
1691 }
1692 }
1693
1694 static void
mta_filter_begin(struct mta_session * s)1695 mta_filter_begin(struct mta_session *s)
1696 {
1697 if (!SESSION_FILTERED(s))
1698 return;
1699
1700 m_create(p_lka, IMSG_FILTER_SMTP_BEGIN, 0, 0, -1);
1701 m_add_id(p_lka, s->id);
1702 m_add_string(p_lka, s->relay->dispatcher->u.remote.filtername);
1703 m_close(p_lka);
1704 }
1705
1706 static void
mta_filter_end(struct mta_session * s)1707 mta_filter_end(struct mta_session *s)
1708 {
1709 if (!SESSION_FILTERED(s))
1710 return;
1711
1712 m_create(p_lka, IMSG_FILTER_SMTP_END, 0, 0, -1);
1713 m_add_id(p_lka, s->id);
1714 m_close(p_lka);
1715 }
1716
1717 static void
mta_connected(struct mta_session * s)1718 mta_connected(struct mta_session *s)
1719 {
1720 struct sockaddr_storage sa_src;
1721 struct sockaddr_storage sa_dest;
1722 int sa_len;
1723
1724 log_info("%016"PRIx64" mta connected", s->id);
1725
1726 sa_len = sizeof sa_src;
1727 if (getsockname(io_fileno(s->io),
1728 (struct sockaddr *)&sa_src, &sa_len) == -1)
1729 bzero(&sa_src, sizeof sa_src);
1730 sa_len = sizeof sa_dest;
1731 if (getpeername(io_fileno(s->io),
1732 (struct sockaddr *)&sa_dest, &sa_len) == -1)
1733 bzero(&sa_dest, sizeof sa_dest);
1734
1735 mta_report_link_connect(s,
1736 s->route->dst->ptrname, 1,
1737 &sa_src,
1738 &sa_dest);
1739 }
1740
1741 static void
mta_disconnected(struct mta_session * s)1742 mta_disconnected(struct mta_session *s)
1743 {
1744 mta_report_link_disconnect(s);
1745 mta_filter_end(s);
1746 }
1747
1748
1749 static void
mta_report_link_connect(struct mta_session * s,const char * rdns,int fcrdns,const struct sockaddr_storage * ss_src,const struct sockaddr_storage * ss_dest)1750 mta_report_link_connect(struct mta_session *s, const char *rdns, int fcrdns,
1751 const struct sockaddr_storage *ss_src,
1752 const struct sockaddr_storage *ss_dest)
1753 {
1754 if (! SESSION_FILTERED(s))
1755 return;
1756
1757 report_smtp_link_connect("smtp-out", s->id, rdns, fcrdns, ss_src, ss_dest);
1758 }
1759
1760 static void
mta_report_link_greeting(struct mta_session * s,const char * domain)1761 mta_report_link_greeting(struct mta_session *s,
1762 const char *domain)
1763 {
1764 if (! SESSION_FILTERED(s))
1765 return;
1766
1767 report_smtp_link_greeting("smtp-out", s->id, domain);
1768 }
1769
1770 static void
mta_report_link_identify(struct mta_session * s,const char * method,const char * identity)1771 mta_report_link_identify(struct mta_session *s, const char *method, const char *identity)
1772 {
1773 if (! SESSION_FILTERED(s))
1774 return;
1775
1776 report_smtp_link_identify("smtp-out", s->id, method, identity);
1777 }
1778
1779 static void
mta_report_link_tls(struct mta_session * s,const char * ssl)1780 mta_report_link_tls(struct mta_session *s, const char *ssl)
1781 {
1782 if (! SESSION_FILTERED(s))
1783 return;
1784
1785 report_smtp_link_tls("smtp-out", s->id, ssl);
1786 }
1787
1788 static void
mta_report_link_disconnect(struct mta_session * s)1789 mta_report_link_disconnect(struct mta_session *s)
1790 {
1791 if (! SESSION_FILTERED(s))
1792 return;
1793
1794 report_smtp_link_disconnect("smtp-out", s->id);
1795 }
1796
1797 static void
mta_report_link_auth(struct mta_session * s,const char * user,const char * result)1798 mta_report_link_auth(struct mta_session *s, const char *user, const char *result)
1799 {
1800 if (! SESSION_FILTERED(s))
1801 return;
1802
1803 report_smtp_link_auth("smtp-out", s->id, user, result);
1804 }
1805
1806 static void
mta_report_tx_reset(struct mta_session * s,uint32_t msgid)1807 mta_report_tx_reset(struct mta_session *s, uint32_t msgid)
1808 {
1809 if (! SESSION_FILTERED(s))
1810 return;
1811
1812 report_smtp_tx_reset("smtp-out", s->id, msgid);
1813 }
1814
1815 static void
mta_report_tx_begin(struct mta_session * s,uint32_t msgid)1816 mta_report_tx_begin(struct mta_session *s, uint32_t msgid)
1817 {
1818 if (! SESSION_FILTERED(s))
1819 return;
1820
1821 report_smtp_tx_begin("smtp-out", s->id, msgid);
1822 }
1823
1824 static void
mta_report_tx_mail(struct mta_session * s,uint32_t msgid,const char * address,int ok)1825 mta_report_tx_mail(struct mta_session *s, uint32_t msgid, const char *address, int ok)
1826 {
1827 if (! SESSION_FILTERED(s))
1828 return;
1829
1830 report_smtp_tx_mail("smtp-out", s->id, msgid, address, ok);
1831 }
1832
1833 static void
mta_report_tx_rcpt(struct mta_session * s,uint32_t msgid,const char * address,int ok)1834 mta_report_tx_rcpt(struct mta_session *s, uint32_t msgid, const char *address, int ok)
1835 {
1836 if (! SESSION_FILTERED(s))
1837 return;
1838
1839 report_smtp_tx_rcpt("smtp-out", s->id, msgid, address, ok);
1840 }
1841
1842 static void
mta_report_tx_envelope(struct mta_session * s,uint32_t msgid,uint64_t evpid)1843 mta_report_tx_envelope(struct mta_session *s, uint32_t msgid, uint64_t evpid)
1844 {
1845 if (! SESSION_FILTERED(s))
1846 return;
1847
1848 report_smtp_tx_envelope("smtp-out", s->id, msgid, evpid);
1849 }
1850
1851 static void
mta_report_tx_data(struct mta_session * s,uint32_t msgid,int ok)1852 mta_report_tx_data(struct mta_session *s, uint32_t msgid, int ok)
1853 {
1854 if (! SESSION_FILTERED(s))
1855 return;
1856
1857 report_smtp_tx_data("smtp-out", s->id, msgid, ok);
1858 }
1859
1860 static void
mta_report_tx_commit(struct mta_session * s,uint32_t msgid,size_t msgsz)1861 mta_report_tx_commit(struct mta_session *s, uint32_t msgid, size_t msgsz)
1862 {
1863 if (! SESSION_FILTERED(s))
1864 return;
1865
1866 report_smtp_tx_commit("smtp-out", s->id, msgid, msgsz);
1867 }
1868
1869 static void
mta_report_tx_rollback(struct mta_session * s,uint32_t msgid)1870 mta_report_tx_rollback(struct mta_session *s, uint32_t msgid)
1871 {
1872 if (! SESSION_FILTERED(s))
1873 return;
1874
1875 report_smtp_tx_rollback("smtp-out", s->id, msgid);
1876 }
1877
1878 static void
mta_report_protocol_client(struct mta_session * s,const char * command)1879 mta_report_protocol_client(struct mta_session *s, const char *command)
1880 {
1881 if (! SESSION_FILTERED(s))
1882 return;
1883
1884 report_smtp_protocol_client("smtp-out", s->id, command);
1885 }
1886
1887 static void
mta_report_protocol_server(struct mta_session * s,const char * response)1888 mta_report_protocol_server(struct mta_session *s, const char *response)
1889 {
1890 if (! SESSION_FILTERED(s))
1891 return;
1892
1893 report_smtp_protocol_server("smtp-out", s->id, response);
1894 }
1895
1896 #if 0
1897 static void
1898 mta_report_filter_response(struct mta_session *s, int phase, int response, const char *param)
1899 {
1900 if (! SESSION_FILTERED(s))
1901 return;
1902
1903 report_smtp_filter_response("smtp-out", s->id, phase, response, param);
1904 }
1905 #endif
1906
1907 static void
mta_report_timeout(struct mta_session * s)1908 mta_report_timeout(struct mta_session *s)
1909 {
1910 if (! SESSION_FILTERED(s))
1911 return;
1912
1913 report_smtp_timeout("smtp-out", s->id);
1914 }
1915