Bug Summary

File:src/usr.sbin/smtpd/smtpd/../mta_session.c
Warning:line 1535, column 7
Although the value stored to 'len' is used in the enclosing expression, the value is never actually read from 'len'

Annotated Source Code

Press '?' to see keyboard shortcuts

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