xref: /openbsd-src/usr.sbin/smtpd/smtp_session.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /*	$OpenBSD: smtp_session.c,v 1.432 2021/07/01 07:42:16 eric Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  * Copyright (c) 2008-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 <ctype.h>
23 #include <errno.h>
24 #include <inttypes.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <tls.h>
28 #include <unistd.h>
29 #include <vis.h>
30 
31 #include "smtpd.h"
32 #include "log.h"
33 #include "rfc5322.h"
34 
35 #define	SMTP_LINE_MAX			65535
36 #define	DATA_HIWAT			65535
37 #define	APPEND_DOMAIN_BUFFER_SIZE	SMTP_LINE_MAX
38 
39 enum smtp_state {
40 	STATE_NEW = 0,
41 	STATE_CONNECTED,
42 	STATE_TLS,
43 	STATE_HELO,
44 	STATE_AUTH_INIT,
45 	STATE_AUTH_USERNAME,
46 	STATE_AUTH_PASSWORD,
47 	STATE_AUTH_FINALIZE,
48 	STATE_BODY,
49 	STATE_QUIT,
50 };
51 
52 enum session_flags {
53 	SF_EHLO			= 0x0001,
54 	SF_8BITMIME		= 0x0002,
55 	SF_SECURE		= 0x0004,
56 	SF_AUTHENTICATED	= 0x0008,
57 	SF_BOUNCE		= 0x0010,
58 	SF_VERIFIED		= 0x0020,
59 	SF_BADINPUT		= 0x0080,
60 };
61 
62 enum {
63 	TX_OK = 0,
64 	TX_ERROR_ENVELOPE,
65 	TX_ERROR_SIZE,
66 	TX_ERROR_IO,
67 	TX_ERROR_LOOP,
68 	TX_ERROR_MALFORMED,
69 	TX_ERROR_RESOURCES,
70 	TX_ERROR_INTERNAL,
71 };
72 
73 enum smtp_command {
74 	CMD_HELO = 0,
75 	CMD_EHLO,
76 	CMD_STARTTLS,
77 	CMD_AUTH,
78 	CMD_MAIL_FROM,
79 	CMD_RCPT_TO,
80 	CMD_DATA,
81 	CMD_RSET,
82 	CMD_QUIT,
83 	CMD_HELP,
84 	CMD_WIZ,
85 	CMD_NOOP,
86 	CMD_COMMIT,
87 };
88 
89 struct smtp_rcpt {
90 	TAILQ_ENTRY(smtp_rcpt)	 entry;
91 	uint64_t		 evpid;
92  	struct mailaddr		 maddr;
93 	size_t			 destcount;
94 };
95 
96 struct smtp_tx {
97 	struct smtp_session	*session;
98 	uint32_t		 msgid;
99 
100 	struct envelope		 evp;
101 	size_t			 rcptcount;
102 	size_t			 destcount;
103 	TAILQ_HEAD(, smtp_rcpt)	 rcpts;
104 
105 	time_t			 time;
106 	int			 error;
107 	size_t			 datain;
108 	size_t			 odatalen;
109 	FILE			*ofile;
110 	struct io		*filter;
111 	struct rfc5322_parser	*parser;
112 	int			 rcvcount;
113 	int			 has_date;
114 	int			 has_message_id;
115 
116 	uint8_t			 junk;
117 };
118 
119 struct smtp_session {
120 	uint64_t		 id;
121 	struct io		*io;
122 	struct listener		*listener;
123 	void			*ssl_ctx;
124 	struct sockaddr_storage	 ss;
125 	char			 rdns[HOST_NAME_MAX+1];
126 	char			 smtpname[HOST_NAME_MAX+1];
127 	int			 fcrdns;
128 
129 	int			 flags;
130 	enum smtp_state		 state;
131 
132 	uint8_t			 banner_sent;
133 	char			 helo[LINE_MAX];
134 	char			 cmd[LINE_MAX];
135 	char			 username[SMTPD_MAXMAILADDRSIZE];
136 
137 	size_t			 mailcount;
138 	struct event		 pause;
139 
140 	struct smtp_tx		*tx;
141 
142 	enum smtp_command	 last_cmd;
143 	enum filter_phase	 filter_phase;
144 	const char		*filter_param;
145 
146 	uint8_t			 junk;
147 };
148 
149 #define ADVERTISE_TLS(s) \
150 	((s)->listener->flags & F_STARTTLS && !((s)->flags & SF_SECURE))
151 
152 #define ADVERTISE_AUTH(s) \
153 	((s)->listener->flags & F_AUTH && (s)->flags & SF_SECURE && \
154 	 !((s)->flags & SF_AUTHENTICATED))
155 
156 #define ADVERTISE_EXT_DSN(s) \
157 	((s)->listener->flags & F_EXT_DSN)
158 
159 #define	SESSION_FILTERED(s) \
160 	((s)->listener->flags & F_FILTERED)
161 
162 #define	SESSION_DATA_FILTERED(s) \
163 	((s)->listener->flags & F_FILTERED)
164 
165 
166 static int smtp_mailaddr(struct mailaddr *, char *, int, char **, const char *);
167 static void smtp_session_init(void);
168 static void smtp_lookup_servername(struct smtp_session *);
169 static void smtp_getnameinfo_cb(void *, int, const char *, const char *);
170 static void smtp_getaddrinfo_cb(void *, int, struct addrinfo *);
171 static void smtp_connected(struct smtp_session *);
172 static void smtp_send_banner(struct smtp_session *);
173 static void smtp_tls_init(struct smtp_session *);
174 static void smtp_tls_started(struct smtp_session *);
175 static void smtp_io(struct io *, int, void *);
176 static void smtp_enter_state(struct smtp_session *, int);
177 static void smtp_reply(struct smtp_session *, char *, ...);
178 static void smtp_command(struct smtp_session *, char *);
179 static void smtp_rfc4954_auth_plain(struct smtp_session *, char *);
180 static void smtp_rfc4954_auth_login(struct smtp_session *, char *);
181 static void smtp_free(struct smtp_session *, const char *);
182 static const char *smtp_strstate(int);
183 static void smtp_auth_failure_pause(struct smtp_session *);
184 static void smtp_auth_failure_resume(int, short, void *);
185 
186 static int  smtp_tx(struct smtp_session *);
187 static void smtp_tx_free(struct smtp_tx *);
188 static void smtp_tx_create_message(struct smtp_tx *);
189 static void smtp_tx_mail_from(struct smtp_tx *, const char *);
190 static void smtp_tx_rcpt_to(struct smtp_tx *, const char *);
191 static void smtp_tx_open_message(struct smtp_tx *);
192 static void smtp_tx_commit(struct smtp_tx *);
193 static void smtp_tx_rollback(struct smtp_tx *);
194 static int  smtp_tx_dataline(struct smtp_tx *, const char *);
195 static int  smtp_tx_filtered_dataline(struct smtp_tx *, const char *);
196 static void smtp_tx_eom(struct smtp_tx *);
197 static void smtp_filter_fd(struct smtp_tx *, int);
198 static int  smtp_message_fd(struct smtp_tx *, int);
199 static void smtp_message_begin(struct smtp_tx *);
200 static void smtp_message_end(struct smtp_tx *);
201 static int  smtp_filter_printf(struct smtp_tx *, const char *, ...)
202     __attribute__((__format__ (printf, 2, 3)));
203 static int  smtp_message_printf(struct smtp_tx *, const char *, ...)
204     __attribute__((__format__ (printf, 2, 3)));
205 
206 static int  smtp_check_rset(struct smtp_session *, const char *);
207 static int  smtp_check_helo(struct smtp_session *, const char *);
208 static int  smtp_check_ehlo(struct smtp_session *, const char *);
209 static int  smtp_check_auth(struct smtp_session *s, const char *);
210 static int  smtp_check_starttls(struct smtp_session *, const char *);
211 static int  smtp_check_mail_from(struct smtp_session *, const char *);
212 static int  smtp_check_rcpt_to(struct smtp_session *, const char *);
213 static int  smtp_check_data(struct smtp_session *, const char *);
214 static int  smtp_check_noparam(struct smtp_session *, const char *);
215 
216 static void smtp_filter_phase(enum filter_phase, struct smtp_session *, const char *);
217 
218 static void smtp_proceed_connected(struct smtp_session *);
219 static void smtp_proceed_rset(struct smtp_session *, const char *);
220 static void smtp_proceed_helo(struct smtp_session *, const char *);
221 static void smtp_proceed_ehlo(struct smtp_session *, const char *);
222 static void smtp_proceed_auth(struct smtp_session *, const char *);
223 static void smtp_proceed_starttls(struct smtp_session *, const char *);
224 static void smtp_proceed_mail_from(struct smtp_session *, const char *);
225 static void smtp_proceed_rcpt_to(struct smtp_session *, const char *);
226 static void smtp_proceed_data(struct smtp_session *, const char *);
227 static void smtp_proceed_noop(struct smtp_session *, const char *);
228 static void smtp_proceed_help(struct smtp_session *, const char *);
229 static void smtp_proceed_wiz(struct smtp_session *, const char *);
230 static void smtp_proceed_quit(struct smtp_session *, const char *);
231 static void smtp_proceed_commit(struct smtp_session *, const char *);
232 static void smtp_proceed_rollback(struct smtp_session *, const char *);
233 
234 static void smtp_filter_begin(struct smtp_session *);
235 static void smtp_filter_end(struct smtp_session *);
236 static void smtp_filter_data_begin(struct smtp_session *);
237 static void smtp_filter_data_end(struct smtp_session *);
238 
239 static void smtp_report_link_connect(struct smtp_session *, const char *, int,
240     const struct sockaddr_storage *,
241     const struct sockaddr_storage *);
242 static void smtp_report_link_greeting(struct smtp_session *, const char *);
243 static void smtp_report_link_identify(struct smtp_session *, const char *, const char *);
244 static void smtp_report_link_tls(struct smtp_session *, const char *);
245 static void smtp_report_link_disconnect(struct smtp_session *);
246 static void smtp_report_link_auth(struct smtp_session *, const char *, const char *);
247 static void smtp_report_tx_reset(struct smtp_session *, uint32_t);
248 static void smtp_report_tx_begin(struct smtp_session *, uint32_t);
249 static void smtp_report_tx_mail(struct smtp_session *, uint32_t, const char *, int);
250 static void smtp_report_tx_rcpt(struct smtp_session *, uint32_t, const char *, int);
251 static void smtp_report_tx_envelope(struct smtp_session *, uint32_t, uint64_t);
252 static void smtp_report_tx_data(struct smtp_session *, uint32_t, int);
253 static void smtp_report_tx_commit(struct smtp_session *, uint32_t, size_t);
254 static void smtp_report_tx_rollback(struct smtp_session *, uint32_t);
255 static void smtp_report_protocol_client(struct smtp_session *, const char *);
256 static void smtp_report_protocol_server(struct smtp_session *, const char *);
257 static void smtp_report_filter_response(struct smtp_session *, int, int, const char *);
258 static void smtp_report_timeout(struct smtp_session *);
259 
260 
261 static struct {
262 	int code;
263 	enum filter_phase filter_phase;
264 	const char *cmd;
265 
266 	int (*check)(struct smtp_session *, const char *);
267 	void (*proceed)(struct smtp_session *, const char *);
268 } commands[] = {
269 	{ CMD_HELO,             FILTER_HELO,            "HELO",         smtp_check_helo,        smtp_proceed_helo },
270 	{ CMD_EHLO,             FILTER_EHLO,            "EHLO",         smtp_check_ehlo,        smtp_proceed_ehlo },
271 	{ CMD_STARTTLS,         FILTER_STARTTLS,        "STARTTLS",     smtp_check_starttls,    smtp_proceed_starttls },
272 	{ CMD_AUTH,             FILTER_AUTH,            "AUTH",         smtp_check_auth,        smtp_proceed_auth },
273 	{ CMD_MAIL_FROM,        FILTER_MAIL_FROM,       "MAIL FROM",    smtp_check_mail_from,   smtp_proceed_mail_from },
274 	{ CMD_RCPT_TO,          FILTER_RCPT_TO,         "RCPT TO",      smtp_check_rcpt_to,     smtp_proceed_rcpt_to },
275 	{ CMD_DATA,             FILTER_DATA,            "DATA",         smtp_check_data,        smtp_proceed_data },
276 	{ CMD_RSET,             FILTER_RSET,            "RSET",         smtp_check_rset,        smtp_proceed_rset },
277 	{ CMD_QUIT,             FILTER_QUIT,            "QUIT",         smtp_check_noparam,     smtp_proceed_quit },
278 	{ CMD_NOOP,             FILTER_NOOP,            "NOOP",         smtp_check_noparam,     smtp_proceed_noop },
279 	{ CMD_HELP,             FILTER_HELP,            "HELP",         smtp_check_noparam,     smtp_proceed_help },
280 	{ CMD_WIZ,              FILTER_WIZ,             "WIZ",          smtp_check_noparam,     smtp_proceed_wiz },
281 	{ CMD_COMMIT,  		FILTER_COMMIT,		".",		smtp_check_noparam,	smtp_proceed_commit },
282 	{ -1,                   0,                      NULL,           NULL },
283 };
284 
285 static struct tree wait_lka_helo;
286 static struct tree wait_lka_mail;
287 static struct tree wait_lka_rcpt;
288 static struct tree wait_parent_auth;
289 static struct tree wait_queue_msg;
290 static struct tree wait_queue_fd;
291 static struct tree wait_queue_commit;
292 static struct tree wait_ssl_init;
293 static struct tree wait_ssl_verify;
294 static struct tree wait_filters;
295 static struct tree wait_filter_fd;
296 
297 static void
298 header_append_domain_buffer(char *buffer, char *domain, size_t len)
299 {
300 	size_t	i;
301 	int	escape, quote, comment, bracket;
302 	int	has_domain, has_bracket, has_group;
303 	int	pos_bracket, pos_component, pos_insert;
304 	char	copy[APPEND_DOMAIN_BUFFER_SIZE];
305 
306 	escape = quote = comment = bracket = 0;
307 	has_domain = has_bracket = has_group = 0;
308 	pos_bracket = pos_insert = pos_component = 0;
309 	for (i = 0; buffer[i]; ++i) {
310 		if (buffer[i] == '(' && !escape && !quote)
311 			comment++;
312 		if (buffer[i] == '"' && !escape && !comment)
313 			quote = !quote;
314 		if (buffer[i] == ')' && !escape && !quote && comment)
315 			comment--;
316 		if (buffer[i] == '\\' && !escape && !comment && !quote)
317 			escape = 1;
318 		else
319 			escape = 0;
320 		if (buffer[i] == '<' && !escape && !comment && !quote && !bracket) {
321 			bracket++;
322 			has_bracket = 1;
323 		}
324 		if (buffer[i] == '>' && !escape && !comment && !quote && bracket) {
325 			bracket--;
326 			pos_bracket = i;
327 		}
328 		if (buffer[i] == '@' && !escape && !comment && !quote)
329 			has_domain = 1;
330 		if (buffer[i] == ':' && !escape && !comment && !quote)
331 			has_group = 1;
332 
333 		/* update insert point if not in comment and not on a whitespace */
334 		if (!comment && buffer[i] != ')' && !isspace((unsigned char)buffer[i]))
335 			pos_component = i;
336 	}
337 
338 	/* parse error, do not attempt to modify */
339 	if (escape || quote || comment || bracket)
340 		return;
341 
342 	/* domain already present, no need to modify */
343 	if (has_domain)
344 		return;
345 
346 	/* address is group, skip */
347 	if (has_group)
348 		return;
349 
350 	/* there's an address between brackets, just append domain */
351 	if (has_bracket) {
352 		pos_bracket--;
353 		while (isspace((unsigned char)buffer[pos_bracket]))
354 			pos_bracket--;
355 		if (buffer[pos_bracket] == '<')
356 			return;
357 		pos_insert = pos_bracket + 1;
358 	}
359 	else {
360 		/* otherwise append address to last component */
361 		pos_insert = pos_component + 1;
362 
363 		/* empty address */
364                 if (buffer[pos_component] == '\0' ||
365 		    isspace((unsigned char)buffer[pos_component]))
366                         return;
367 	}
368 
369 	if (snprintf(copy, sizeof copy, "%.*s@%s%s",
370 		(int)pos_insert, buffer,
371 		domain,
372 		buffer+pos_insert) >= (int)sizeof copy)
373 		return;
374 
375 	memcpy(buffer, copy, len);
376 }
377 
378 static void
379 header_address_rewrite_buffer(char *buffer, const char *address, size_t len)
380 {
381 	size_t	i;
382 	int	address_len;
383 	int	escape, quote, comment, bracket;
384 	int	has_bracket, has_group;
385 	int	pos_bracket_beg, pos_bracket_end, pos_component_beg, pos_component_end;
386 	int	insert_beg, insert_end;
387 	char	copy[APPEND_DOMAIN_BUFFER_SIZE];
388 
389 	escape = quote = comment = bracket = 0;
390 	has_bracket = has_group = 0;
391 	pos_bracket_beg = pos_bracket_end = pos_component_beg = pos_component_end = 0;
392 	for (i = 0; buffer[i]; ++i) {
393 		if (buffer[i] == '(' && !escape && !quote)
394 			comment++;
395 		if (buffer[i] == '"' && !escape && !comment)
396 			quote = !quote;
397 		if (buffer[i] == ')' && !escape && !quote && comment)
398 			comment--;
399 		if (buffer[i] == '\\' && !escape && !comment && !quote)
400 			escape = 1;
401 		else
402 			escape = 0;
403 		if (buffer[i] == '<' && !escape && !comment && !quote && !bracket) {
404 			bracket++;
405 			has_bracket = 1;
406 			pos_bracket_beg = i+1;
407 		}
408 		if (buffer[i] == '>' && !escape && !comment && !quote && bracket) {
409 			bracket--;
410 			pos_bracket_end = i;
411 		}
412 		if (buffer[i] == ':' && !escape && !comment && !quote)
413 			has_group = 1;
414 
415 		/* update insert point if not in comment and not on a whitespace */
416 		if (!comment && buffer[i] != ')' && !isspace((unsigned char)buffer[i]))
417 			pos_component_end = i;
418 	}
419 
420 	/* parse error, do not attempt to modify */
421 	if (escape || quote || comment || bracket)
422 		return;
423 
424 	/* address is group, skip */
425 	if (has_group)
426 		return;
427 
428 	/* there's an address between brackets, just replace everything brackets */
429 	if (has_bracket) {
430 		insert_beg = pos_bracket_beg;
431 		insert_end = pos_bracket_end;
432 	}
433 	else {
434 		if (pos_component_end == 0)
435 			pos_component_beg = 0;
436 		else {
437 			for (pos_component_beg = pos_component_end; pos_component_beg >= 0; --pos_component_beg)
438 				if (buffer[pos_component_beg] == ')' || isspace((unsigned char)buffer[pos_component_beg]))
439 					break;
440 			pos_component_beg += 1;
441 			pos_component_end += 1;
442 		}
443 		insert_beg = pos_component_beg;
444 		insert_end = pos_component_end;
445 	}
446 
447 	/* check that masquerade won' t overflow */
448 	address_len = strlen(address);
449 	if (strlen(buffer) - (insert_end - insert_beg) + address_len >= len)
450 		return;
451 
452 	(void)strlcpy(copy, buffer, sizeof copy);
453 	(void)strlcpy(copy+insert_beg, address, sizeof (copy) - insert_beg);
454 	(void)strlcat(copy, buffer+insert_end, sizeof (copy));
455 	memcpy(buffer, copy, len);
456 }
457 
458 static void
459 header_domain_append_callback(struct smtp_tx *tx, const char *hdr,
460     const char *val)
461 {
462 	size_t			i, j, linelen;
463 	int			escape, quote, comment, skip;
464 	char			buffer[APPEND_DOMAIN_BUFFER_SIZE];
465 	const char *line, *end;
466 
467 	if (smtp_message_printf(tx, "%s:", hdr) == -1)
468 		return;
469 
470 	j = 0;
471 	escape = quote = comment = skip = 0;
472 	memset(buffer, 0, sizeof buffer);
473 
474 	for (line = val; line; line = end) {
475 		end = strchr(line, '\n');
476 		if (end) {
477 			linelen = end - line;
478 			end++;
479 		}
480 		else
481 			linelen = strlen(line);
482 
483 		for (i = 0; i < linelen; ++i) {
484 			if (line[i] == '(' && !escape && !quote)
485 				comment++;
486 			if (line[i] == '"' && !escape && !comment)
487 				quote = !quote;
488 			if (line[i] == ')' && !escape && !quote && comment)
489 				comment--;
490 			if (line[i] == '\\' && !escape && !comment && !quote)
491 				escape = 1;
492 			else
493 				escape = 0;
494 
495 			/* found a separator, buffer contains a full address */
496 			if (line[i] == ',' && !escape && !quote && !comment) {
497 				if (!skip && j + strlen(tx->session->listener->hostname) + 1 < sizeof buffer) {
498 					header_append_domain_buffer(buffer, tx->session->listener->hostname, sizeof buffer);
499 					if (tx->session->flags & SF_AUTHENTICATED &&
500 					    tx->session->listener->sendertable[0] &&
501 					    tx->session->listener->flags & F_MASQUERADE &&
502 					    !(strcasecmp(hdr, "From")))
503 						header_address_rewrite_buffer(buffer, mailaddr_to_text(&tx->evp.sender),
504 						    sizeof buffer);
505 				}
506 				if (smtp_message_printf(tx, "%s,", buffer) == -1)
507 					return;
508 				j = 0;
509 				skip = 0;
510 				memset(buffer, 0, sizeof buffer);
511 			}
512 			else {
513 				if (skip) {
514 					if (smtp_message_printf(tx, "%c", line[i]) == -1)
515 						return;
516 				}
517 				else {
518 					buffer[j++] = line[i];
519 					if (j == sizeof (buffer) - 1) {
520 						if (smtp_message_printf(tx, "%s", buffer) == -1)
521 							return;
522 						skip = 1;
523 						j = 0;
524 						memset(buffer, 0, sizeof buffer);
525 					}
526 				}
527 			}
528 		}
529 		if (skip) {
530 			if (smtp_message_printf(tx, "\n") == -1)
531 				return;
532 		}
533 		else {
534 			buffer[j++] = '\n';
535 			if (j == sizeof (buffer) - 1) {
536 				if (smtp_message_printf(tx, "%s", buffer) == -1)
537 					return;
538 				skip = 1;
539 				j = 0;
540 				memset(buffer, 0, sizeof buffer);
541 			}
542 		}
543 	}
544 
545 	/* end of header, if buffer is not empty we'll process it */
546 	if (buffer[0]) {
547 		if (j + strlen(tx->session->listener->hostname) + 1 < sizeof buffer) {
548 			header_append_domain_buffer(buffer, tx->session->listener->hostname, sizeof buffer);
549 			if (tx->session->flags & SF_AUTHENTICATED &&
550 			    tx->session->listener->sendertable[0] &&
551 			    tx->session->listener->flags & F_MASQUERADE &&
552 			    !(strcasecmp(hdr, "From")))
553 				header_address_rewrite_buffer(buffer, mailaddr_to_text(&tx->evp.sender),
554 				    sizeof buffer);
555 		}
556 		smtp_message_printf(tx, "%s", buffer);
557 	}
558 }
559 
560 static void
561 smtp_session_init(void)
562 {
563 	static int	init = 0;
564 
565 	if (!init) {
566 		tree_init(&wait_lka_helo);
567 		tree_init(&wait_lka_mail);
568 		tree_init(&wait_lka_rcpt);
569 		tree_init(&wait_parent_auth);
570 		tree_init(&wait_queue_msg);
571 		tree_init(&wait_queue_fd);
572 		tree_init(&wait_queue_commit);
573 		tree_init(&wait_ssl_init);
574 		tree_init(&wait_ssl_verify);
575 		tree_init(&wait_filters);
576 		tree_init(&wait_filter_fd);
577 		init = 1;
578 	}
579 }
580 
581 int
582 smtp_session(struct listener *listener, int sock,
583     const struct sockaddr_storage *ss, const char *hostname, struct io *io)
584 {
585 	struct smtp_session	*s;
586 
587 	smtp_session_init();
588 
589 	if ((s = calloc(1, sizeof(*s))) == NULL)
590 		return (-1);
591 
592 	s->id = generate_uid();
593 	s->listener = listener;
594 	memmove(&s->ss, ss, sizeof(*ss));
595 
596 	if (io != NULL)
597 		s->io = io;
598 	else
599 		s->io = io_new();
600 
601 	io_set_callback(s->io, smtp_io, s);
602 	io_set_fd(s->io, sock);
603 	io_set_timeout(s->io, SMTPD_SESSION_TIMEOUT * 1000);
604 	io_set_write(s->io);
605 	s->state = STATE_NEW;
606 
607 	(void)strlcpy(s->smtpname, listener->hostname, sizeof(s->smtpname));
608 
609 	log_trace(TRACE_SMTP, "smtp: %p: connected to listener %p "
610 	    "[hostname=%s, port=%d, tag=%s]", s, listener,
611 	    listener->hostname, ntohs(listener->port), listener->tag);
612 
613 	/* For local enqueueing, the hostname is already set */
614 	if (hostname) {
615 		s->flags |= SF_AUTHENTICATED;
616 		/* A bit of a hack */
617 		if (!strcmp(hostname, "localhost"))
618 			s->flags |= SF_BOUNCE;
619 		(void)strlcpy(s->rdns, hostname, sizeof(s->rdns));
620 		s->fcrdns = 1;
621 		smtp_lookup_servername(s);
622 	} else {
623 		resolver_getnameinfo((struct sockaddr *)&s->ss,
624 		    NI_NAMEREQD | NI_NUMERICSERV, smtp_getnameinfo_cb, s);
625 	}
626 
627 	/* session may have been freed by now */
628 
629 	return (0);
630 }
631 
632 static void
633 smtp_getnameinfo_cb(void *arg, int gaierrno, const char *host, const char *serv)
634 {
635 	struct smtp_session *s = arg;
636 	struct addrinfo hints;
637 
638 	if (gaierrno) {
639 		(void)strlcpy(s->rdns, "<unknown>", sizeof(s->rdns));
640 
641 		if (gaierrno == EAI_NODATA || gaierrno == EAI_NONAME)
642 			s->fcrdns = 0;
643 		else {
644 			log_warnx("getnameinfo: %s: %s", ss_to_text(&s->ss),
645 			    gai_strerror(gaierrno));
646 			s->fcrdns = -1;
647 		}
648 
649 		smtp_lookup_servername(s);
650 		return;
651 	}
652 
653 	(void)strlcpy(s->rdns, host, sizeof(s->rdns));
654 
655 	memset(&hints, 0, sizeof(hints));
656 	hints.ai_family = s->ss.ss_family;
657 	hints.ai_socktype = SOCK_STREAM;
658 	resolver_getaddrinfo(s->rdns, NULL, &hints, smtp_getaddrinfo_cb, s);
659 }
660 
661 static void
662 smtp_getaddrinfo_cb(void *arg, int gaierrno, struct addrinfo *ai0)
663 {
664 	struct smtp_session *s = arg;
665 	struct addrinfo *ai;
666 	char fwd[64], rev[64];
667 
668 	if (gaierrno) {
669 		if (gaierrno == EAI_NODATA || gaierrno == EAI_NONAME)
670 			s->fcrdns = 0;
671 		else {
672 			log_warnx("getaddrinfo: %s: %s", s->rdns,
673 			    gai_strerror(gaierrno));
674 			s->fcrdns = -1;
675 		}
676 	}
677 	else {
678 		strlcpy(rev, ss_to_text(&s->ss), sizeof(rev));
679 		for (ai = ai0; ai; ai = ai->ai_next) {
680 			strlcpy(fwd, sa_to_text(ai->ai_addr), sizeof(fwd));
681 			if (!strcmp(fwd, rev)) {
682 				s->fcrdns = 1;
683 				break;
684 			}
685 		}
686 		freeaddrinfo(ai0);
687 	}
688 
689 	smtp_lookup_servername(s);
690 }
691 
692 void
693 smtp_session_imsg(struct mproc *p, struct imsg *imsg)
694 {
695 	struct smtp_session		*s;
696 	struct smtp_rcpt		*rcpt;
697 	char				 user[SMTPD_MAXMAILADDRSIZE];
698 	char				 tmp[SMTP_LINE_MAX];
699 	struct msg			 m;
700 	const char			*line, *helo;
701 	uint64_t			 reqid, evpid;
702 	uint32_t			 msgid;
703 	int				 status, success;
704 	int                              filter_response;
705 	const char                      *filter_param;
706 	uint8_t                          i;
707 
708 	switch (imsg->hdr.type) {
709 
710 	case IMSG_SMTP_CHECK_SENDER:
711 		m_msg(&m, imsg);
712 		m_get_id(&m, &reqid);
713 		m_get_int(&m, &status);
714 		m_end(&m);
715 		s = tree_xpop(&wait_lka_mail, reqid);
716 		switch (status) {
717 		case LKA_OK:
718 			smtp_tx_create_message(s->tx);
719 			break;
720 
721 		case LKA_PERMFAIL:
722 			smtp_tx_free(s->tx);
723 			smtp_reply(s, "%d %s", 530, "Sender rejected");
724 			break;
725 		case LKA_TEMPFAIL:
726 			smtp_tx_free(s->tx);
727 			smtp_reply(s, "421 %s Temporary Error",
728 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
729 			break;
730 		}
731 		return;
732 
733 	case IMSG_SMTP_EXPAND_RCPT:
734 		m_msg(&m, imsg);
735 		m_get_id(&m, &reqid);
736 		m_get_int(&m, &status);
737 		m_get_string(&m, &line);
738 		m_end(&m);
739 		s = tree_xpop(&wait_lka_rcpt, reqid);
740 
741 		tmp[0] = '\0';
742 		if (s->tx->evp.rcpt.user[0]) {
743 			(void)strlcpy(tmp, s->tx->evp.rcpt.user, sizeof tmp);
744 			if (s->tx->evp.rcpt.domain[0]) {
745 				(void)strlcat(tmp, "@", sizeof tmp);
746 				(void)strlcat(tmp, s->tx->evp.rcpt.domain,
747 				    sizeof tmp);
748 			}
749 		}
750 
751 		switch (status) {
752 		case LKA_OK:
753 			fatalx("unexpected ok");
754 		case LKA_PERMFAIL:
755 			smtp_reply(s, "%s: <%s>", line, tmp);
756 			break;
757 		case LKA_TEMPFAIL:
758 			smtp_reply(s, "%s: <%s>", line, tmp);
759 			break;
760 		}
761 		return;
762 
763 	case IMSG_SMTP_LOOKUP_HELO:
764 		m_msg(&m, imsg);
765 		m_get_id(&m, &reqid);
766 		s = tree_xpop(&wait_lka_helo, reqid);
767 		m_get_int(&m, &status);
768 		if (status == LKA_OK) {
769 			m_get_string(&m, &helo);
770 			(void)strlcpy(s->smtpname, helo, sizeof(s->smtpname));
771 		}
772 		m_end(&m);
773 		smtp_connected(s);
774 		return;
775 
776 	case IMSG_SMTP_MESSAGE_CREATE:
777 		m_msg(&m, imsg);
778 		m_get_id(&m, &reqid);
779 		m_get_int(&m, &success);
780 		s = tree_xpop(&wait_queue_msg, reqid);
781 		if (success) {
782 			m_get_msgid(&m, &msgid);
783 			s->tx->msgid = msgid;
784 			s->tx->evp.id = msgid_to_evpid(msgid);
785 			s->tx->rcptcount = 0;
786 			smtp_reply(s, "250 %s Ok",
787 			    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
788 		} else {
789 			smtp_reply(s, "421 %s Temporary Error",
790 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
791 			smtp_tx_free(s->tx);
792 			smtp_enter_state(s, STATE_QUIT);
793 		}
794 		m_end(&m);
795 		return;
796 
797 	case IMSG_SMTP_MESSAGE_OPEN:
798 		m_msg(&m, imsg);
799 		m_get_id(&m, &reqid);
800 		m_get_int(&m, &success);
801 		m_end(&m);
802 
803 		s = tree_xpop(&wait_queue_fd, reqid);
804 		if (!success || imsg->fd == -1) {
805 			if (imsg->fd != -1)
806 				close(imsg->fd);
807 			smtp_reply(s, "421 %s Temporary Error",
808 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
809 			smtp_enter_state(s, STATE_QUIT);
810 			return;
811 		}
812 
813 		log_debug("smtp: %p: fd %d from queue", s, imsg->fd);
814 
815 		if (smtp_message_fd(s->tx, imsg->fd)) {
816 			if (!SESSION_DATA_FILTERED(s))
817 				smtp_message_begin(s->tx);
818 			else
819 				smtp_filter_data_begin(s);
820 		}
821 		return;
822 
823 	case IMSG_FILTER_SMTP_DATA_BEGIN:
824 		m_msg(&m, imsg);
825 		m_get_id(&m, &reqid);
826 		m_get_int(&m, &success);
827 		m_end(&m);
828 
829 		s = tree_xpop(&wait_filter_fd, reqid);
830 		if (!success || imsg->fd == -1) {
831 			if (imsg->fd != -1)
832 				close(imsg->fd);
833 			smtp_reply(s, "421 %s Temporary Error",
834 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
835 			smtp_enter_state(s, STATE_QUIT);
836 			return;
837 		}
838 
839 		log_debug("smtp: %p: fd %d from lka", s, imsg->fd);
840 
841 		smtp_filter_fd(s->tx, imsg->fd);
842 		smtp_message_begin(s->tx);
843 		return;
844 
845 	case IMSG_QUEUE_ENVELOPE_SUBMIT:
846 		m_msg(&m, imsg);
847 		m_get_id(&m, &reqid);
848 		m_get_int(&m, &success);
849 		s = tree_xget(&wait_lka_rcpt, reqid);
850 		if (success) {
851 			m_get_evpid(&m, &evpid);
852 			s->tx->evp.id = evpid;
853 			s->tx->destcount++;
854 			smtp_report_tx_envelope(s, s->tx->msgid, evpid);
855 		}
856 		else
857 			s->tx->error = TX_ERROR_ENVELOPE;
858 		m_end(&m);
859 		return;
860 
861 	case IMSG_QUEUE_ENVELOPE_COMMIT:
862 		m_msg(&m, imsg);
863 		m_get_id(&m, &reqid);
864 		m_get_int(&m, &success);
865 		m_end(&m);
866 		if (!success)
867 			fatalx("commit evp failed: not supposed to happen");
868 		s = tree_xpop(&wait_lka_rcpt, reqid);
869 		if (s->tx->error) {
870 			/*
871 			 * If an envelope failed, we can't cancel the last
872 			 * RCPT only so we must cancel the whole transaction
873 			 * and close the connection.
874 			 */
875 			smtp_reply(s, "421 %s Temporary failure",
876 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
877 			smtp_enter_state(s, STATE_QUIT);
878 		}
879 		else {
880 			rcpt = xcalloc(1, sizeof(*rcpt));
881 			rcpt->evpid = s->tx->evp.id;
882 			rcpt->destcount = s->tx->destcount;
883 			rcpt->maddr = s->tx->evp.rcpt;
884 			TAILQ_INSERT_TAIL(&s->tx->rcpts, rcpt, entry);
885 
886 			s->tx->destcount = 0;
887 			s->tx->rcptcount++;
888 			smtp_reply(s, "250 %s %s: Recipient ok",
889 			    esc_code(ESC_STATUS_OK, ESC_DESTINATION_ADDRESS_VALID),
890 			    esc_description(ESC_DESTINATION_ADDRESS_VALID));
891 		}
892 		return;
893 
894 	case IMSG_SMTP_MESSAGE_COMMIT:
895 		m_msg(&m, imsg);
896 		m_get_id(&m, &reqid);
897 		m_get_int(&m, &success);
898 		m_end(&m);
899 		s = tree_xpop(&wait_queue_commit, reqid);
900 		if (!success) {
901 			smtp_reply(s, "421 %s Temporary failure",
902 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
903 			smtp_tx_free(s->tx);
904 			smtp_enter_state(s, STATE_QUIT);
905 			return;
906 		}
907 
908 		smtp_reply(s, "250 %s %08x Message accepted for delivery",
909 		    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS),
910 		    s->tx->msgid);
911 		smtp_report_tx_commit(s, s->tx->msgid, s->tx->odatalen);
912 		smtp_report_tx_reset(s, s->tx->msgid);
913 
914 		log_info("%016"PRIx64" smtp message "
915 		    "msgid=%08x size=%zu nrcpt=%zu proto=%s",
916 		    s->id,
917 		    s->tx->msgid,
918 		    s->tx->odatalen,
919 		    s->tx->rcptcount,
920 		    s->flags & SF_EHLO ? "ESMTP" : "SMTP");
921 		TAILQ_FOREACH(rcpt, &s->tx->rcpts, entry) {
922 			log_info("%016"PRIx64" smtp envelope "
923 			    "evpid=%016"PRIx64" from=<%s%s%s> to=<%s%s%s>",
924 			    s->id,
925 			    rcpt->evpid,
926 			    s->tx->evp.sender.user,
927 			    s->tx->evp.sender.user[0] == '\0' ? "" : "@",
928 			    s->tx->evp.sender.domain,
929 			    rcpt->maddr.user,
930 			    rcpt->maddr.user[0] == '\0' ? "" : "@",
931 			    rcpt->maddr.domain);
932 		}
933 		smtp_tx_free(s->tx);
934 		s->mailcount++;
935 		smtp_enter_state(s, STATE_HELO);
936 		return;
937 
938 	case IMSG_SMTP_AUTHENTICATE:
939 		m_msg(&m, imsg);
940 		m_get_id(&m, &reqid);
941 		m_get_int(&m, &success);
942 		m_end(&m);
943 
944 		s = tree_xpop(&wait_parent_auth, reqid);
945 		strnvis(user, s->username, sizeof user, VIS_WHITE | VIS_SAFE);
946 		if (success == LKA_OK) {
947 			log_info("%016"PRIx64" smtp "
948 			    "authentication user=%s "
949 			    "result=ok",
950 			    s->id, user);
951 			s->flags |= SF_AUTHENTICATED;
952 			smtp_report_link_auth(s, user, "pass");
953 			smtp_reply(s, "235 %s Authentication succeeded",
954 			    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
955 		}
956 		else if (success == LKA_PERMFAIL) {
957 			log_info("%016"PRIx64" smtp "
958 			    "authentication user=%s "
959 			    "result=permfail",
960 			    s->id, user);
961 			smtp_report_link_auth(s, user, "fail");
962 			smtp_auth_failure_pause(s);
963 			return;
964 		}
965 		else if (success == LKA_TEMPFAIL) {
966 			log_info("%016"PRIx64" smtp "
967 			    "authentication user=%s "
968 			    "result=tempfail",
969 			    s->id, user);
970 			smtp_report_link_auth(s, user, "error");
971 			smtp_reply(s, "421 %s Temporary failure",
972 			    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
973 		}
974 		else
975 			fatalx("bad lka response");
976 
977 		smtp_enter_state(s, STATE_HELO);
978 		return;
979 
980 	case IMSG_FILTER_SMTP_PROTOCOL:
981 		m_msg(&m, imsg);
982 		m_get_id(&m, &reqid);
983 		m_get_int(&m, &filter_response);
984 		if (filter_response != FILTER_PROCEED &&
985 		    filter_response != FILTER_JUNK)
986 			m_get_string(&m, &filter_param);
987 		else
988 			filter_param = NULL;
989 		m_end(&m);
990 
991 		s = tree_xpop(&wait_filters, reqid);
992 
993 		switch (filter_response) {
994 		case FILTER_REJECT:
995 		case FILTER_DISCONNECT:
996 			if (!valid_smtp_response(filter_param) ||
997 			    (filter_param[0] != '4' && filter_param[0] != '5'))
998 				filter_param = "421 Internal server error";
999 			if (!strncmp(filter_param, "421", 3))
1000 				filter_response = FILTER_DISCONNECT;
1001 
1002 			smtp_report_filter_response(s, s->filter_phase,
1003 			    filter_response, filter_param);
1004 
1005 			smtp_reply(s, "%s", filter_param);
1006 
1007 			if (filter_response == FILTER_DISCONNECT)
1008 				smtp_enter_state(s, STATE_QUIT);
1009 			else if (s->filter_phase == FILTER_COMMIT)
1010 				smtp_proceed_rollback(s, NULL);
1011 			break;
1012 
1013 
1014 		case FILTER_JUNK:
1015 			if (s->tx)
1016 				s->tx->junk = 1;
1017 			else
1018 				s->junk = 1;
1019 			/* fallthrough */
1020 
1021 		case FILTER_PROCEED:
1022 			filter_param = s->filter_param;
1023 			/* fallthrough */
1024 
1025 		case FILTER_REWRITE:
1026 			smtp_report_filter_response(s, s->filter_phase,
1027 			    filter_response,
1028 			    filter_param == s->filter_param ? NULL : filter_param);
1029 			if (s->filter_phase == FILTER_CONNECT) {
1030 				smtp_proceed_connected(s);
1031 				return;
1032 			}
1033 			for (i = 0; i < nitems(commands); ++i)
1034 				if (commands[i].filter_phase == s->filter_phase) {
1035 					if (filter_response == FILTER_REWRITE)
1036 						if (!commands[i].check(s, filter_param))
1037 							break;
1038 					commands[i].proceed(s, filter_param);
1039 					break;
1040 				}
1041 			break;
1042 		}
1043 		return;
1044 	}
1045 
1046 	log_warnx("smtp_session_imsg: unexpected %s imsg",
1047 	    imsg_to_str(imsg->hdr.type));
1048 	fatalx(NULL);
1049 }
1050 
1051 static void
1052 smtp_tls_init(struct smtp_session *s)
1053 {
1054 	io_set_read(s->io);
1055 	if (io_accept_tls(s->io, s->listener->tls) == -1) {
1056 		log_info("%016"PRIx64" smtp disconnected "
1057 		    "reason=tls-accept-failed",
1058 		    s->id);
1059 		smtp_free(s, "accept failed");
1060 	}
1061 }
1062 
1063 static void
1064 smtp_tls_started(struct smtp_session *s)
1065 {
1066 	if (tls_peer_cert_provided(io_tls(s->io))) {
1067 		log_info("%016"PRIx64" smtp "
1068 		    "cert-check result=\"%s\" fingerprint=\"%s\"",
1069 		    s->id,
1070 		    (s->flags & SF_VERIFIED) ? "verified" : "unchecked",
1071 		    tls_peer_cert_hash(io_tls(s->io)));
1072 	}
1073 
1074 	if (s->listener->flags & F_SMTPS) {
1075 		stat_increment("smtp.smtps", 1);
1076 		io_set_write(s->io);
1077 		smtp_send_banner(s);
1078 	}
1079 	else {
1080 		stat_increment("smtp.tls", 1);
1081 		smtp_enter_state(s, STATE_HELO);
1082 	}
1083 }
1084 
1085 static void
1086 smtp_io(struct io *io, int evt, void *arg)
1087 {
1088 	struct smtp_session    *s = arg;
1089 	char		       *line;
1090 	size_t			len;
1091 	int			eom;
1092 
1093 	log_trace(TRACE_IO, "smtp: %p: %s %s", s, io_strevent(evt),
1094 	    io_strio(io));
1095 
1096 	switch (evt) {
1097 
1098 	case IO_TLSREADY:
1099 		log_info("%016"PRIx64" smtp tls ciphers=%s",
1100 		    s->id, tls_to_text(io_tls(s->io)));
1101 
1102 		smtp_report_link_tls(s, tls_to_text(io_tls(s->io)));
1103 
1104 		s->flags |= SF_SECURE;
1105 		if (s->listener->flags & F_TLS_VERIFY)
1106 			s->flags |= SF_VERIFIED;
1107 		s->helo[0] = '\0';
1108 
1109 		smtp_tls_started(s);
1110 		break;
1111 
1112 	case IO_DATAIN:
1113 	    nextline:
1114 		line = io_getline(s->io, &len);
1115 		if ((line == NULL && io_datalen(s->io) >= SMTP_LINE_MAX) ||
1116 		    (line && len >= SMTP_LINE_MAX)) {
1117 			s->flags |= SF_BADINPUT;
1118 			smtp_reply(s, "500 %s Line too long",
1119 			    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_STATUS));
1120 			smtp_enter_state(s, STATE_QUIT);
1121 			io_set_write(io);
1122 			return;
1123 		}
1124 
1125 		/* No complete line received */
1126 		if (line == NULL)
1127 			return;
1128 
1129 		/* Strip trailing '\r' */
1130 		if (len && line[len - 1] == '\r')
1131 			line[--len] = '\0';
1132 
1133 		/* Message body */
1134 		eom = 0;
1135 		if (s->state == STATE_BODY) {
1136 			if (strcmp(line, ".")) {
1137 				s->tx->datain += strlen(line) + 1;
1138 				if (s->tx->datain > env->sc_maxsize)
1139 					s->tx->error = TX_ERROR_SIZE;
1140 			}
1141 			eom = (s->tx->filter == NULL) ?
1142 			    smtp_tx_dataline(s->tx, line) :
1143 			    smtp_tx_filtered_dataline(s->tx, line);
1144 			if (eom == 0)
1145 				goto nextline;
1146 		}
1147 
1148 		/* Pipelining not supported */
1149 		if (io_datalen(s->io)) {
1150 			s->flags |= SF_BADINPUT;
1151 			smtp_reply(s, "500 %s %s: Pipelining not supported",
1152 			    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1153 			    esc_description(ESC_INVALID_COMMAND));
1154 			smtp_enter_state(s, STATE_QUIT);
1155 			io_set_write(io);
1156 			return;
1157 		}
1158 
1159 		if (eom) {
1160 			io_set_write(io);
1161 			if (s->tx->filter == NULL)
1162 				smtp_tx_eom(s->tx);
1163 			return;
1164 		}
1165 
1166 		/* Must be a command */
1167 		if (strlcpy(s->cmd, line, sizeof(s->cmd)) >= sizeof(s->cmd)) {
1168 			s->flags |= SF_BADINPUT;
1169 			smtp_reply(s, "500 %s Command line too long",
1170 			    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_STATUS));
1171 			smtp_enter_state(s, STATE_QUIT);
1172 			io_set_write(io);
1173 			return;
1174 		}
1175 		io_set_write(io);
1176 		smtp_command(s, line);
1177 		break;
1178 
1179 	case IO_LOWAT:
1180 		if (s->state == STATE_QUIT) {
1181 			log_info("%016"PRIx64" smtp disconnected "
1182 			    "reason=quit",
1183 			    s->id);
1184 			smtp_free(s, "done");
1185 			break;
1186 		}
1187 
1188 		/* Wait for the client to start tls */
1189 		if (s->state == STATE_TLS) {
1190 			smtp_tls_init(s);
1191 			break;
1192 		}
1193 
1194 		io_set_read(io);
1195 		break;
1196 
1197 	case IO_TIMEOUT:
1198 		log_info("%016"PRIx64" smtp disconnected "
1199 		    "reason=timeout",
1200 		    s->id);
1201 		smtp_report_timeout(s);
1202 		smtp_free(s, "timeout");
1203 		break;
1204 
1205 	case IO_DISCONNECTED:
1206 		log_info("%016"PRIx64" smtp disconnected "
1207 		    "reason=disconnect",
1208 		    s->id);
1209 		smtp_free(s, "disconnected");
1210 		break;
1211 
1212 	case IO_ERROR:
1213 		log_info("%016"PRIx64" smtp disconnected "
1214 		    "reason=\"io-error: %s\"",
1215 		    s->id, io_error(io));
1216 		smtp_free(s, "IO error");
1217 		break;
1218 
1219 	default:
1220 		fatalx("smtp_io()");
1221 	}
1222 }
1223 
1224 static void
1225 smtp_command(struct smtp_session *s, char *line)
1226 {
1227 	char			       *args;
1228 	int				cmd, i;
1229 
1230 	log_trace(TRACE_SMTP, "smtp: %p: <<< %s", s, line);
1231 
1232 	/*
1233 	 * These states are special.
1234 	 */
1235 	if (s->state == STATE_AUTH_INIT) {
1236 		smtp_report_protocol_client(s, "********");
1237 		smtp_rfc4954_auth_plain(s, line);
1238 		return;
1239 	}
1240 	if (s->state == STATE_AUTH_USERNAME || s->state == STATE_AUTH_PASSWORD) {
1241 		smtp_report_protocol_client(s, "********");
1242 		smtp_rfc4954_auth_login(s, line);
1243 		return;
1244 	}
1245 
1246 	if (s->state == STATE_HELO && strncasecmp(line, "AUTH PLAIN ", 11) == 0)
1247 		smtp_report_protocol_client(s, "AUTH PLAIN ********");
1248 	else
1249 		smtp_report_protocol_client(s, line);
1250 
1251 
1252 	/*
1253 	 * Unlike other commands, "mail from" and "rcpt to" contain a
1254 	 * space in the command name.
1255 	 */
1256 	if (strncasecmp("mail from:", line, 10) == 0 ||
1257 	    strncasecmp("rcpt to:", line, 8) == 0)
1258 		args = strchr(line, ':');
1259 	else
1260 		args = strchr(line, ' ');
1261 
1262 	if (args) {
1263 		*args++ = '\0';
1264 		while (isspace((unsigned char)*args))
1265 			args++;
1266 	}
1267 
1268 	cmd = -1;
1269 	for (i = 0; commands[i].code != -1; i++)
1270 		if (!strcasecmp(line, commands[i].cmd)) {
1271 			cmd = commands[i].code;
1272 			break;
1273 		}
1274 
1275 	s->last_cmd = cmd;
1276 	switch (cmd) {
1277 	/*
1278 	 * INIT
1279 	 */
1280 	case CMD_HELO:
1281 		if (!smtp_check_helo(s, args))
1282 			break;
1283 		smtp_filter_phase(FILTER_HELO, s, args);
1284 		break;
1285 
1286 	case CMD_EHLO:
1287 		if (!smtp_check_ehlo(s, args))
1288 			break;
1289 		smtp_filter_phase(FILTER_EHLO, s, args);
1290 		break;
1291 
1292 	/*
1293 	 * SETUP
1294 	 */
1295 	case CMD_STARTTLS:
1296 		if (!smtp_check_starttls(s, args))
1297 			break;
1298 
1299 		smtp_filter_phase(FILTER_STARTTLS, s, NULL);
1300 		break;
1301 
1302 	case CMD_AUTH:
1303 		if (!smtp_check_auth(s, args))
1304 			break;
1305 		smtp_filter_phase(FILTER_AUTH, s, args);
1306 		break;
1307 
1308 	case CMD_MAIL_FROM:
1309 		if (!smtp_check_mail_from(s, args))
1310 			break;
1311 		smtp_filter_phase(FILTER_MAIL_FROM, s, args);
1312 		break;
1313 
1314 	/*
1315 	 * TRANSACTION
1316 	 */
1317 	case CMD_RCPT_TO:
1318 		if (!smtp_check_rcpt_to(s, args))
1319 			break;
1320 		smtp_filter_phase(FILTER_RCPT_TO, s, args);
1321 		break;
1322 
1323 	case CMD_RSET:
1324 		if (!smtp_check_rset(s, args))
1325 			break;
1326 		smtp_filter_phase(FILTER_RSET, s, NULL);
1327 		break;
1328 
1329 	case CMD_DATA:
1330 		if (!smtp_check_data(s, args))
1331 			break;
1332 		smtp_filter_phase(FILTER_DATA, s, NULL);
1333 		break;
1334 
1335 	/*
1336 	 * ANY
1337 	 */
1338 	case CMD_QUIT:
1339 		if (!smtp_check_noparam(s, args))
1340 			break;
1341 		smtp_filter_phase(FILTER_QUIT, s, NULL);
1342 		break;
1343 
1344 	case CMD_NOOP:
1345 		if (!smtp_check_noparam(s, args))
1346 			break;
1347 		smtp_filter_phase(FILTER_NOOP, s, NULL);
1348 		break;
1349 
1350 	case CMD_HELP:
1351 		if (!smtp_check_noparam(s, args))
1352 			break;
1353 		smtp_proceed_help(s, NULL);
1354 		break;
1355 
1356 	case CMD_WIZ:
1357 		if (!smtp_check_noparam(s, args))
1358 			break;
1359 		smtp_proceed_wiz(s, NULL);
1360 		break;
1361 
1362 	default:
1363 		smtp_reply(s, "500 %s %s: Command unrecognized",
1364 			    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1365 			    esc_description(ESC_INVALID_COMMAND));
1366 		break;
1367 	}
1368 }
1369 
1370 static int
1371 smtp_check_rset(struct smtp_session *s, const char *args)
1372 {
1373 	if (!smtp_check_noparam(s, args))
1374 		return 0;
1375 
1376 	if (s->helo[0] == '\0') {
1377 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1378 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1379 		    esc_description(ESC_INVALID_COMMAND));
1380 		return 0;
1381 	}
1382 	return 1;
1383 }
1384 
1385 static int
1386 smtp_check_helo(struct smtp_session *s, const char *args)
1387 {
1388 	if (!s->banner_sent) {
1389 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1390 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1391 		    esc_description(ESC_INVALID_COMMAND));
1392 		return 0;
1393 	}
1394 
1395 	if (s->helo[0]) {
1396 		smtp_reply(s, "503 %s %s: Already identified",
1397 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1398 		    esc_description(ESC_INVALID_COMMAND));
1399 		return 0;
1400 	}
1401 
1402 	if (args == NULL) {
1403 		smtp_reply(s, "501 %s %s: HELO requires domain name",
1404 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1405 		    esc_description(ESC_INVALID_COMMAND));
1406 		return 0;
1407 	}
1408 
1409 	if (!valid_domainpart(args)) {
1410 		smtp_reply(s, "501 %s %s: Invalid domain name",
1411 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1412 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1413 		return 0;
1414 	}
1415 
1416 	return 1;
1417 }
1418 
1419 static int
1420 smtp_check_ehlo(struct smtp_session *s, const char *args)
1421 {
1422 	if (!s->banner_sent) {
1423 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1424 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1425 		    esc_description(ESC_INVALID_COMMAND));
1426 		return 0;
1427 	}
1428 
1429 	if (s->helo[0]) {
1430 		smtp_reply(s, "503 %s %s: Already identified",
1431 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1432 		    esc_description(ESC_INVALID_COMMAND));
1433 		return 0;
1434 	}
1435 
1436 	if (args == NULL) {
1437 		smtp_reply(s, "501 %s %s: EHLO requires domain name",
1438 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1439 		    esc_description(ESC_INVALID_COMMAND));
1440 		return 0;
1441 	}
1442 
1443 	if (!valid_domainpart(args)) {
1444 		smtp_reply(s, "501 %s %s: Invalid domain name",
1445 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1446 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1447 		return 0;
1448 	}
1449 
1450 	return 1;
1451 }
1452 
1453 static int
1454 smtp_check_auth(struct smtp_session *s, const char *args)
1455 {
1456 	if (s->helo[0] == '\0' || s->tx) {
1457 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1458 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1459 		    esc_description(ESC_INVALID_COMMAND));
1460 		return 0;
1461 	}
1462 
1463 	if (s->flags & SF_AUTHENTICATED) {
1464 		smtp_reply(s, "503 %s %s: Already authenticated",
1465 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1466 		    esc_description(ESC_INVALID_COMMAND));
1467 		return 0;
1468 	}
1469 
1470 	if (!ADVERTISE_AUTH(s)) {
1471 		smtp_reply(s, "503 %s %s: Command not supported",
1472 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1473 		    esc_description(ESC_INVALID_COMMAND));
1474 		return 0;
1475 	}
1476 
1477 	if (args == NULL) {
1478 		smtp_reply(s, "501 %s %s: No parameters given",
1479 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1480 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1481 		return 0;
1482 	}
1483 
1484 	return 1;
1485 }
1486 
1487 static int
1488 smtp_check_starttls(struct smtp_session *s, const char *args)
1489 {
1490 	if (s->helo[0] == '\0' || s->tx) {
1491 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1492 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1493 		    esc_description(ESC_INVALID_COMMAND));
1494 		return 0;
1495 	}
1496 
1497 	if (!(s->listener->flags & F_STARTTLS)) {
1498 		smtp_reply(s, "503 %s %s: Command not supported",
1499 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1500 		    esc_description(ESC_INVALID_COMMAND));
1501 		return 0;
1502 	}
1503 
1504 	if (s->flags & SF_SECURE) {
1505 		smtp_reply(s, "503 %s %s: Channel already secured",
1506 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1507 		    esc_description(ESC_INVALID_COMMAND));
1508 		return 0;
1509 	}
1510 
1511 	if (args != NULL) {
1512 		smtp_reply(s, "501 %s %s: No parameters allowed",
1513 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1514 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1515 		return 0;
1516 	}
1517 
1518 	return 1;
1519 }
1520 
1521 static int
1522 smtp_check_mail_from(struct smtp_session *s, const char *args)
1523 {
1524 	char *copy;
1525 	char tmp[SMTP_LINE_MAX];
1526 	struct mailaddr	sender;
1527 
1528 	(void)strlcpy(tmp, args, sizeof tmp);
1529 	copy = tmp;
1530 
1531 	if (s->helo[0] == '\0' || s->tx) {
1532 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1533 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1534 		    esc_description(ESC_INVALID_COMMAND));
1535 		return 0;
1536 	}
1537 
1538 	if (s->listener->flags & F_STARTTLS_REQUIRE &&
1539 	    !(s->flags & SF_SECURE)) {
1540 		smtp_reply(s,
1541 		    "530 %s %s: Must issue a STARTTLS command first",
1542 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1543 		    esc_description(ESC_INVALID_COMMAND));
1544 		return 0;
1545 	}
1546 
1547 	if (s->listener->flags & F_AUTH_REQUIRE &&
1548 	    !(s->flags & SF_AUTHENTICATED)) {
1549 		smtp_reply(s,
1550 		    "530 %s %s: Must issue an AUTH command first",
1551 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1552 		    esc_description(ESC_INVALID_COMMAND));
1553 		return 0;
1554 	}
1555 
1556 	if (s->mailcount >= env->sc_session_max_mails) {
1557 		/* we can pretend we had too many recipients */
1558 		smtp_reply(s, "452 %s %s: Too many messages sent",
1559 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS),
1560 		    esc_description(ESC_TOO_MANY_RECIPIENTS));
1561 		return 0;
1562 	}
1563 
1564 	if (smtp_mailaddr(&sender, copy, 1, &copy,
1565 		s->smtpname) == 0) {
1566 		smtp_reply(s, "553 %s Sender address syntax error",
1567 		    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
1568 		return 0;
1569 	}
1570 
1571 	return 1;
1572 }
1573 
1574 static int
1575 smtp_check_rcpt_to(struct smtp_session *s, const char *args)
1576 {
1577 	char *copy;
1578 	char tmp[SMTP_LINE_MAX];
1579 
1580 	(void)strlcpy(tmp, args, sizeof tmp);
1581 	copy = tmp;
1582 
1583 	if (s->tx == NULL) {
1584 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1585 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1586 		    esc_description(ESC_INVALID_COMMAND));
1587 		return 0;
1588 	}
1589 
1590 	if (s->tx->rcptcount >= env->sc_session_max_rcpt) {
1591 		smtp_reply(s->tx->session, "451 %s %s: Too many recipients",
1592 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS),
1593 		    esc_description(ESC_TOO_MANY_RECIPIENTS));
1594 		return 0;
1595 	}
1596 
1597 	if (smtp_mailaddr(&s->tx->evp.rcpt, copy, 0, &copy,
1598 		s->tx->session->smtpname) == 0) {
1599 		smtp_reply(s->tx->session,
1600 		    "501 %s Recipient address syntax error",
1601 		    esc_code(ESC_STATUS_PERMFAIL,
1602 		        ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX));
1603 		return 0;
1604 	}
1605 
1606 	return 1;
1607 }
1608 
1609 static int
1610 smtp_check_data(struct smtp_session *s, const char *args)
1611 {
1612 	if (!smtp_check_noparam(s, args))
1613 		return 0;
1614 
1615 	if (s->tx == NULL) {
1616 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1617 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1618 		    esc_description(ESC_INVALID_COMMAND));
1619 		return 0;
1620 	}
1621 
1622 	if (s->tx->rcptcount == 0) {
1623 		smtp_reply(s, "503 %s %s: No recipient specified",
1624 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1625 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1626 		return 0;
1627 	}
1628 
1629 	return 1;
1630 }
1631 
1632 static int
1633 smtp_check_noparam(struct smtp_session *s, const char *args)
1634 {
1635 	if (args != NULL) {
1636 		smtp_reply(s, "500 %s %s: command does not accept arguments.",
1637 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1638 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1639 		return 0;
1640 	}
1641 	return 1;
1642 }
1643 
1644 static void
1645 smtp_query_filters(enum filter_phase phase, struct smtp_session *s, const char *args)
1646 {
1647 	m_create(p_lka, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1);
1648 	m_add_id(p_lka, s->id);
1649 	m_add_int(p_lka, phase);
1650 	m_add_string(p_lka, args);
1651 	m_close(p_lka);
1652 	tree_xset(&wait_filters, s->id, s);
1653 }
1654 
1655 static void
1656 smtp_filter_begin(struct smtp_session *s)
1657 {
1658 	if (!SESSION_FILTERED(s))
1659 		return;
1660 
1661 	m_create(p_lka, IMSG_FILTER_SMTP_BEGIN, 0, 0, -1);
1662 	m_add_id(p_lka, s->id);
1663 	m_add_string(p_lka, s->listener->filter_name);
1664 	m_close(p_lka);
1665 }
1666 
1667 static void
1668 smtp_filter_end(struct smtp_session *s)
1669 {
1670 	if (!SESSION_FILTERED(s))
1671 		return;
1672 
1673 	m_create(p_lka, IMSG_FILTER_SMTP_END, 0, 0, -1);
1674 	m_add_id(p_lka, s->id);
1675 	m_close(p_lka);
1676 }
1677 
1678 static void
1679 smtp_filter_data_begin(struct smtp_session *s)
1680 {
1681 	if (!SESSION_FILTERED(s))
1682 		return;
1683 
1684 	m_create(p_lka, IMSG_FILTER_SMTP_DATA_BEGIN, 0, 0, -1);
1685 	m_add_id(p_lka, s->id);
1686 	m_close(p_lka);
1687 	tree_xset(&wait_filter_fd, s->id, s);
1688 }
1689 
1690 static void
1691 smtp_filter_data_end(struct smtp_session *s)
1692 {
1693 	if (!SESSION_FILTERED(s))
1694 		return;
1695 
1696 	if (s->tx->filter == NULL)
1697 		return;
1698 
1699 	io_free(s->tx->filter);
1700 	s->tx->filter = NULL;
1701 
1702 	m_create(p_lka, IMSG_FILTER_SMTP_DATA_END, 0, 0, -1);
1703 	m_add_id(p_lka, s->id);
1704 	m_close(p_lka);
1705 }
1706 
1707 static void
1708 smtp_filter_phase(enum filter_phase phase, struct smtp_session *s, const char *param)
1709 {
1710 	uint8_t i;
1711 
1712 	s->filter_phase = phase;
1713 	s->filter_param = param;
1714 
1715 	if (SESSION_FILTERED(s)) {
1716 		smtp_query_filters(phase, s, param ? param : "");
1717 		return;
1718 	}
1719 
1720 	if (s->filter_phase == FILTER_CONNECT) {
1721 		smtp_proceed_connected(s);
1722 		return;
1723 	}
1724 
1725 	for (i = 0; i < nitems(commands); ++i)
1726 		if (commands[i].filter_phase == s->filter_phase) {
1727 			commands[i].proceed(s, param);
1728 			break;
1729 		}
1730 }
1731 
1732 static void
1733 smtp_proceed_rset(struct smtp_session *s, const char *args)
1734 {
1735 	smtp_reply(s, "250 %s Reset state",
1736 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1737 
1738 	if (s->tx) {
1739 		if (s->tx->msgid)
1740 			smtp_tx_rollback(s->tx);
1741 		smtp_tx_free(s->tx);
1742 	}
1743 }
1744 
1745 static void
1746 smtp_proceed_helo(struct smtp_session *s, const char *args)
1747 {
1748 	(void)strlcpy(s->helo, args, sizeof(s->helo));
1749 	s->flags &= SF_SECURE | SF_AUTHENTICATED | SF_VERIFIED;
1750 
1751 	smtp_report_link_identify(s, "HELO", s->helo);
1752 
1753 	smtp_enter_state(s, STATE_HELO);
1754 
1755 	smtp_reply(s, "250 %s Hello %s %s%s%s, pleased to meet you",
1756 	    s->smtpname,
1757 	    s->helo,
1758 	    s->ss.ss_family == AF_INET6 ? "" : "[",
1759 	    ss_to_text(&s->ss),
1760 	    s->ss.ss_family == AF_INET6 ? "" : "]");
1761 }
1762 
1763 static void
1764 smtp_proceed_ehlo(struct smtp_session *s, const char *args)
1765 {
1766 	(void)strlcpy(s->helo, args, sizeof(s->helo));
1767 	s->flags &= SF_SECURE | SF_AUTHENTICATED | SF_VERIFIED;
1768 	s->flags |= SF_EHLO;
1769 	s->flags |= SF_8BITMIME;
1770 
1771 	smtp_report_link_identify(s, "EHLO", s->helo);
1772 
1773 	smtp_enter_state(s, STATE_HELO);
1774 	smtp_reply(s, "250-%s Hello %s %s%s%s, pleased to meet you",
1775 	    s->smtpname,
1776 	    s->helo,
1777 	    s->ss.ss_family == AF_INET6 ? "" : "[",
1778 	    ss_to_text(&s->ss),
1779 	    s->ss.ss_family == AF_INET6 ? "" : "]");
1780 
1781 	smtp_reply(s, "250-8BITMIME");
1782 	smtp_reply(s, "250-ENHANCEDSTATUSCODES");
1783 	smtp_reply(s, "250-SIZE %zu", env->sc_maxsize);
1784 	if (ADVERTISE_EXT_DSN(s))
1785 		smtp_reply(s, "250-DSN");
1786 	if (ADVERTISE_TLS(s))
1787 		smtp_reply(s, "250-STARTTLS");
1788 	if (ADVERTISE_AUTH(s))
1789 		smtp_reply(s, "250-AUTH PLAIN LOGIN");
1790 	smtp_reply(s, "250 HELP");
1791 }
1792 
1793 static void
1794 smtp_proceed_auth(struct smtp_session *s, const char *args)
1795 {
1796 	char tmp[SMTP_LINE_MAX];
1797 	char *eom, *method;
1798 
1799 	(void)strlcpy(tmp, args, sizeof tmp);
1800 
1801 	method = tmp;
1802 	eom = strchr(tmp, ' ');
1803 	if (eom == NULL)
1804 		eom = strchr(tmp, '\t');
1805 	if (eom != NULL)
1806 		*eom++ = '\0';
1807 	if (strcasecmp(method, "PLAIN") == 0)
1808 		smtp_rfc4954_auth_plain(s, eom);
1809 	else if (strcasecmp(method, "LOGIN") == 0)
1810 		smtp_rfc4954_auth_login(s, eom);
1811 	else
1812 		smtp_reply(s, "504 %s %s: AUTH method \"%s\" not supported",
1813 		    esc_code(ESC_STATUS_PERMFAIL, ESC_SECURITY_FEATURES_NOT_SUPPORTED),
1814 		    esc_description(ESC_SECURITY_FEATURES_NOT_SUPPORTED),
1815 		    method);
1816 }
1817 
1818 static void
1819 smtp_proceed_starttls(struct smtp_session *s, const char *args)
1820 {
1821 	smtp_reply(s, "220 %s Ready to start TLS",
1822 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1823 	smtp_enter_state(s, STATE_TLS);
1824 }
1825 
1826 static void
1827 smtp_proceed_mail_from(struct smtp_session *s, const char *args)
1828 {
1829 	char *copy;
1830 	char tmp[SMTP_LINE_MAX];
1831 
1832 	(void)strlcpy(tmp, args, sizeof tmp);
1833 	copy = tmp;
1834 
1835        	if (!smtp_tx(s)) {
1836 		smtp_reply(s, "421 %s Temporary Error",
1837 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
1838 		smtp_enter_state(s, STATE_QUIT);
1839 		return;
1840 	}
1841 
1842 	if (smtp_mailaddr(&s->tx->evp.sender, copy, 1, &copy,
1843 		s->smtpname) == 0) {
1844 		smtp_reply(s, "553 %s Sender address syntax error",
1845 		    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
1846 		smtp_tx_free(s->tx);
1847 		return;
1848 	}
1849 
1850 	smtp_tx_mail_from(s->tx, args);
1851 }
1852 
1853 static void
1854 smtp_proceed_rcpt_to(struct smtp_session *s, const char *args)
1855 {
1856 	smtp_tx_rcpt_to(s->tx, args);
1857 }
1858 
1859 static void
1860 smtp_proceed_data(struct smtp_session *s, const char *args)
1861 {
1862 	smtp_tx_open_message(s->tx);
1863 }
1864 
1865 static void
1866 smtp_proceed_quit(struct smtp_session *s, const char *args)
1867 {
1868 	smtp_reply(s, "221 %s Bye",
1869 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1870 	smtp_enter_state(s, STATE_QUIT);
1871 }
1872 
1873 static void
1874 smtp_proceed_noop(struct smtp_session *s, const char *args)
1875 {
1876 	smtp_reply(s, "250 %s Ok",
1877 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1878 }
1879 
1880 static void
1881 smtp_proceed_help(struct smtp_session *s, const char *args)
1882 {
1883 	const char *code = esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS);
1884 
1885 	smtp_reply(s, "214-%s This is " SMTPD_NAME, code);
1886 	smtp_reply(s, "214-%s To report bugs in the implementation, "
1887 	    "please contact bugs@openbsd.org", code);
1888 	smtp_reply(s, "214-%s with full details", code);
1889 	smtp_reply(s, "214 %s End of HELP info", code);
1890 }
1891 
1892 static void
1893 smtp_proceed_wiz(struct smtp_session *s, const char *args)
1894 {
1895 	smtp_reply(s, "500 %s %s: this feature is not supported yet ;-)",
1896 	    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1897 	    esc_description(ESC_INVALID_COMMAND));
1898 }
1899 
1900 static void
1901 smtp_proceed_commit(struct smtp_session *s, const char *args)
1902 {
1903 	smtp_message_end(s->tx);
1904 }
1905 
1906 static void
1907 smtp_proceed_rollback(struct smtp_session *s, const char *args)
1908 {
1909 	struct smtp_tx *tx;
1910 
1911 	tx = s->tx;
1912 
1913 	fclose(tx->ofile);
1914 	tx->ofile = NULL;
1915 
1916 	smtp_tx_rollback(tx);
1917 	smtp_tx_free(tx);
1918 	smtp_enter_state(s, STATE_HELO);
1919 }
1920 
1921 static void
1922 smtp_rfc4954_auth_plain(struct smtp_session *s, char *arg)
1923 {
1924 	char		 buf[1024], *user, *pass;
1925 	int		 len;
1926 
1927 	switch (s->state) {
1928 	case STATE_HELO:
1929 		if (arg == NULL) {
1930 			smtp_enter_state(s, STATE_AUTH_INIT);
1931 			smtp_reply(s, "334 ");
1932 			return;
1933 		}
1934 		smtp_enter_state(s, STATE_AUTH_INIT);
1935 		/* FALLTHROUGH */
1936 
1937 	case STATE_AUTH_INIT:
1938 		/* String is not NUL terminated, leave room. */
1939 		if ((len = base64_decode(arg, (unsigned char *)buf,
1940 			    sizeof(buf) - 1)) == -1)
1941 			goto abort;
1942 		/* buf is a byte string, NUL terminate. */
1943 		buf[len] = '\0';
1944 
1945 		/*
1946 		 * Skip "foo" in "foo\0user\0pass", if present.
1947 		 */
1948 		user = memchr(buf, '\0', len);
1949 		if (user == NULL || user >= buf + len - 2)
1950 			goto abort;
1951 		user++; /* skip NUL */
1952 		if (strlcpy(s->username, user, sizeof(s->username))
1953 		    >= sizeof(s->username))
1954 			goto abort;
1955 
1956 		pass = memchr(user, '\0', len - (user - buf));
1957 		if (pass == NULL || pass >= buf + len - 2)
1958 			goto abort;
1959 		pass++; /* skip NUL */
1960 
1961 		m_create(p_lka,  IMSG_SMTP_AUTHENTICATE, 0, 0, -1);
1962 		m_add_id(p_lka, s->id);
1963 		m_add_string(p_lka, s->listener->authtable);
1964 		m_add_string(p_lka, user);
1965 		m_add_string(p_lka, pass);
1966 		m_close(p_lka);
1967 		tree_xset(&wait_parent_auth, s->id, s);
1968 		return;
1969 
1970 	default:
1971 		fatal("smtp_rfc4954_auth_plain: unknown state");
1972 	}
1973 
1974 abort:
1975 	smtp_reply(s, "501 %s %s: Syntax error",
1976 	    esc_code(ESC_STATUS_PERMFAIL, ESC_SYNTAX_ERROR),
1977 	    esc_description(ESC_SYNTAX_ERROR));
1978 	smtp_enter_state(s, STATE_HELO);
1979 }
1980 
1981 static void
1982 smtp_rfc4954_auth_login(struct smtp_session *s, char *arg)
1983 {
1984 	char		buf[LINE_MAX];
1985 
1986 	switch (s->state) {
1987 	case STATE_HELO:
1988 		smtp_enter_state(s, STATE_AUTH_USERNAME);
1989 		if (arg != NULL && *arg != '\0') {
1990 			smtp_rfc4954_auth_login(s, arg);
1991 			return;
1992 		}
1993 		smtp_reply(s, "334 VXNlcm5hbWU6");
1994 		return;
1995 
1996 	case STATE_AUTH_USERNAME:
1997 		memset(s->username, 0, sizeof(s->username));
1998 		if (base64_decode(arg, (unsigned char *)s->username,
1999 				  sizeof(s->username) - 1) == -1)
2000 			goto abort;
2001 
2002 		smtp_enter_state(s, STATE_AUTH_PASSWORD);
2003 		smtp_reply(s, "334 UGFzc3dvcmQ6");
2004 		return;
2005 
2006 	case STATE_AUTH_PASSWORD:
2007 		memset(buf, 0, sizeof(buf));
2008 		if (base64_decode(arg, (unsigned char *)buf,
2009 				  sizeof(buf)-1) == -1)
2010 			goto abort;
2011 
2012 		m_create(p_lka,  IMSG_SMTP_AUTHENTICATE, 0, 0, -1);
2013 		m_add_id(p_lka, s->id);
2014 		m_add_string(p_lka, s->listener->authtable);
2015 		m_add_string(p_lka, s->username);
2016 		m_add_string(p_lka, buf);
2017 		m_close(p_lka);
2018 		tree_xset(&wait_parent_auth, s->id, s);
2019 		return;
2020 
2021 	default:
2022 		fatal("smtp_rfc4954_auth_login: unknown state");
2023 	}
2024 
2025 abort:
2026 	smtp_reply(s, "501 %s %s: Syntax error",
2027 	    esc_code(ESC_STATUS_PERMFAIL, ESC_SYNTAX_ERROR),
2028 	    esc_description(ESC_SYNTAX_ERROR));
2029 	smtp_enter_state(s, STATE_HELO);
2030 }
2031 
2032 static void
2033 smtp_lookup_servername(struct smtp_session *s)
2034 {
2035 	if (s->listener->hostnametable[0]) {
2036 		m_create(p_lka, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1);
2037 		m_add_id(p_lka, s->id);
2038 		m_add_string(p_lka, s->listener->hostnametable);
2039 		m_add_sockaddr(p_lka, (struct sockaddr*)&s->listener->ss);
2040 		m_close(p_lka);
2041 		tree_xset(&wait_lka_helo, s->id, s);
2042 		return;
2043 	}
2044 
2045 	smtp_connected(s);
2046 }
2047 
2048 static void
2049 smtp_connected(struct smtp_session *s)
2050 {
2051 	smtp_enter_state(s, STATE_CONNECTED);
2052 
2053 	log_info("%016"PRIx64" smtp connected address=%s host=%s",
2054 	    s->id, ss_to_text(&s->ss), s->rdns);
2055 
2056 	smtp_filter_begin(s);
2057 
2058 	smtp_report_link_connect(s, s->rdns, s->fcrdns, &s->ss,
2059 	    &s->listener->ss);
2060 
2061 	smtp_filter_phase(FILTER_CONNECT, s, ss_to_text(&s->ss));
2062 }
2063 
2064 static void
2065 smtp_proceed_connected(struct smtp_session *s)
2066 {
2067 	if (s->listener->flags & F_SMTPS)
2068 		smtp_tls_init(s);
2069 	else
2070 		smtp_send_banner(s);
2071 }
2072 
2073 static void
2074 smtp_send_banner(struct smtp_session *s)
2075 {
2076 	smtp_reply(s, "220 %s ESMTP %s", s->smtpname, SMTPD_NAME);
2077 	s->banner_sent = 1;
2078 	smtp_report_link_greeting(s, s->smtpname);
2079 }
2080 
2081 void
2082 smtp_enter_state(struct smtp_session *s, int newstate)
2083 {
2084 	log_trace(TRACE_SMTP, "smtp: %p: %s -> %s", s,
2085 	    smtp_strstate(s->state),
2086 	    smtp_strstate(newstate));
2087 
2088 	s->state = newstate;
2089 }
2090 
2091 static void
2092 smtp_reply(struct smtp_session *s, char *fmt, ...)
2093 {
2094 	va_list	 ap;
2095 	int	 n;
2096 	char	 buf[LINE_MAX*2], tmp[LINE_MAX*2];
2097 
2098 	va_start(ap, fmt);
2099 	n = vsnprintf(buf, sizeof buf, fmt, ap);
2100 	va_end(ap);
2101 	if (n < 0)
2102 		fatalx("smtp_reply: response format error");
2103 	if (n < 4)
2104 		fatalx("smtp_reply: response too short");
2105 	if (n >= (int)sizeof buf) {
2106 		/* only first three bytes are used by SMTP logic,
2107 		 * so if _our_ reply does not fit entirely in the
2108 		 * buffer, it's ok to truncate.
2109 		 */
2110 	}
2111 
2112 	log_trace(TRACE_SMTP, "smtp: %p: >>> %s", s, buf);
2113 	smtp_report_protocol_server(s, buf);
2114 
2115 	switch (buf[0]) {
2116 	case '2':
2117 		if (s->tx) {
2118 			if (s->last_cmd == CMD_MAIL_FROM) {
2119 				smtp_report_tx_begin(s, s->tx->msgid);
2120 				smtp_report_tx_mail(s, s->tx->msgid, s->cmd + 10, 1);
2121 			}
2122 			else if (s->last_cmd == CMD_RCPT_TO)
2123 				smtp_report_tx_rcpt(s, s->tx->msgid, s->cmd + 8, 1);
2124 		}
2125 		break;
2126 	case '3':
2127 		if (s->tx) {
2128 			if (s->last_cmd == CMD_DATA)
2129 				smtp_report_tx_data(s, s->tx->msgid, 1);
2130 		}
2131 		break;
2132 	case '5':
2133 	case '4':
2134 		/* do not report smtp_tx_mail/smtp_tx_rcpt errors
2135 		 * if they happened outside of a transaction.
2136 		 */
2137 		if (s->tx) {
2138 			if (s->last_cmd == CMD_MAIL_FROM)
2139 				smtp_report_tx_mail(s, s->tx->msgid,
2140 				    s->cmd + 10, buf[0] == '4' ? -1 : 0);
2141 			else if (s->last_cmd == CMD_RCPT_TO)
2142 				smtp_report_tx_rcpt(s,
2143 				    s->tx->msgid, s->cmd + 8, buf[0] == '4' ? -1 : 0);
2144 			else if (s->last_cmd == CMD_DATA && s->tx->rcptcount)
2145 				smtp_report_tx_data(s, s->tx->msgid,
2146 				    buf[0] == '4' ? -1 : 0);
2147 		}
2148 
2149 		if (s->flags & SF_BADINPUT) {
2150 			log_info("%016"PRIx64" smtp "
2151 			    "bad-input result=\"%.*s\"",
2152 			    s->id, n, buf);
2153 		}
2154 		else if (s->state == STATE_AUTH_INIT) {
2155 			log_info("%016"PRIx64" smtp "
2156 			    "failed-command "
2157 			    "command=\"AUTH PLAIN (...)\" result=\"%.*s\"",
2158 			    s->id, n, buf);
2159 		}
2160 		else if (s->state == STATE_AUTH_USERNAME) {
2161 			log_info("%016"PRIx64" smtp "
2162 			    "failed-command "
2163 			    "command=\"AUTH LOGIN (username)\" result=\"%.*s\"",
2164 			    s->id, n, buf);
2165 		}
2166 		else if (s->state == STATE_AUTH_PASSWORD) {
2167 			log_info("%016"PRIx64" smtp "
2168 			    "failed-command "
2169 			    "command=\"AUTH LOGIN (password)\" result=\"%.*s\"",
2170 			    s->id, n, buf);
2171 		}
2172 		else {
2173 			strnvis(tmp, s->cmd, sizeof tmp, VIS_SAFE | VIS_CSTYLE);
2174 			log_info("%016"PRIx64" smtp "
2175 			    "failed-command command=\"%s\" "
2176 			    "result=\"%.*s\"",
2177 			    s->id, tmp, n, buf);
2178 		}
2179 		break;
2180 	}
2181 
2182 	io_xprintf(s->io, "%s\r\n", buf);
2183 }
2184 
2185 static void
2186 smtp_free(struct smtp_session *s, const char * reason)
2187 {
2188 	if (s->tx) {
2189 		if (s->tx->msgid)
2190 			smtp_tx_rollback(s->tx);
2191 		smtp_tx_free(s->tx);
2192 	}
2193 
2194 	smtp_report_link_disconnect(s);
2195 	smtp_filter_end(s);
2196 
2197 	if (s->flags & SF_SECURE && s->listener->flags & F_SMTPS)
2198 		stat_decrement("smtp.smtps", 1);
2199 	if (s->flags & SF_SECURE && s->listener->flags & F_STARTTLS)
2200 		stat_decrement("smtp.tls", 1);
2201 
2202 	io_free(s->io);
2203 	free(s);
2204 
2205 	smtp_collect();
2206 }
2207 
2208 static int
2209 smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args,
2210     const char *domain)
2211 {
2212 	char   *p, *e;
2213 
2214 	if (line == NULL)
2215 		return (0);
2216 
2217 	if (*line != '<')
2218 		return (0);
2219 
2220 	e = strchr(line, '>');
2221 	if (e == NULL)
2222 		return (0);
2223 	*e++ = '\0';
2224 	while (*e == ' ')
2225 		e++;
2226 	*args = e;
2227 
2228 	if (!text_to_mailaddr(maddr, line + 1))
2229 		return (0);
2230 
2231 	p = strchr(maddr->user, ':');
2232 	if (p != NULL) {
2233 		p++;
2234 		memmove(maddr->user, p, strlen(p) + 1);
2235 	}
2236 
2237 	/* accept empty return-path in MAIL FROM, required for bounces */
2238 	if (mailfrom && maddr->user[0] == '\0' && maddr->domain[0] == '\0')
2239 		return (1);
2240 
2241 	/* no or invalid user-part, reject */
2242 	if (maddr->user[0] == '\0' || !valid_localpart(maddr->user))
2243 		return (0);
2244 
2245 	/* no domain part, local user */
2246 	if (maddr->domain[0] == '\0') {
2247 		(void)strlcpy(maddr->domain, domain,
2248 			sizeof(maddr->domain));
2249 	}
2250 
2251 	if (!valid_domainpart(maddr->domain))
2252 		return (0);
2253 
2254 	return (1);
2255 }
2256 
2257 static void
2258 smtp_auth_failure_resume(int fd, short event, void *p)
2259 {
2260 	struct smtp_session *s = p;
2261 
2262 	smtp_reply(s, "535 Authentication failed");
2263 	smtp_enter_state(s, STATE_HELO);
2264 }
2265 
2266 static void
2267 smtp_auth_failure_pause(struct smtp_session *s)
2268 {
2269 	struct timeval	tv;
2270 
2271 	tv.tv_sec = 0;
2272 	tv.tv_usec = arc4random_uniform(1000000);
2273 	log_trace(TRACE_SMTP, "smtp: timing-attack protection triggered, "
2274 	    "will defer answer for %lu microseconds", tv.tv_usec);
2275 	evtimer_set(&s->pause, smtp_auth_failure_resume, s);
2276 	evtimer_add(&s->pause, &tv);
2277 }
2278 
2279 static int
2280 smtp_tx(struct smtp_session *s)
2281 {
2282 	struct smtp_tx *tx;
2283 
2284 	tx = calloc(1, sizeof(*tx));
2285 	if (tx == NULL)
2286 		return 0;
2287 
2288 	TAILQ_INIT(&tx->rcpts);
2289 
2290 	s->tx = tx;
2291 	tx->session = s;
2292 
2293 	/* setup the envelope */
2294 	tx->evp.ss = s->ss;
2295 	(void)strlcpy(tx->evp.tag, s->listener->tag, sizeof(tx->evp.tag));
2296 	(void)strlcpy(tx->evp.smtpname, s->smtpname, sizeof(tx->evp.smtpname));
2297 	(void)strlcpy(tx->evp.hostname, s->rdns, sizeof tx->evp.hostname);
2298 	(void)strlcpy(tx->evp.helo, s->helo, sizeof(tx->evp.helo));
2299 	(void)strlcpy(tx->evp.username, s->username, sizeof(tx->evp.username));
2300 
2301 	if (s->flags & SF_BOUNCE)
2302 		tx->evp.flags |= EF_BOUNCE;
2303 	if (s->flags & SF_AUTHENTICATED)
2304 		tx->evp.flags |= EF_AUTHENTICATED;
2305 
2306 	if ((tx->parser = rfc5322_parser_new()) == NULL) {
2307 		free(tx);
2308 		return 0;
2309 	}
2310 
2311 	return 1;
2312 }
2313 
2314 static void
2315 smtp_tx_free(struct smtp_tx *tx)
2316 {
2317 	struct smtp_rcpt *rcpt;
2318 
2319 	rfc5322_free(tx->parser);
2320 
2321 	while ((rcpt = TAILQ_FIRST(&tx->rcpts))) {
2322 		TAILQ_REMOVE(&tx->rcpts, rcpt, entry);
2323 		free(rcpt);
2324 	}
2325 
2326 	if (tx->ofile)
2327 		fclose(tx->ofile);
2328 
2329 	tx->session->tx = NULL;
2330 
2331 	free(tx);
2332 }
2333 
2334 static void
2335 smtp_tx_mail_from(struct smtp_tx *tx, const char *line)
2336 {
2337 	char *opt;
2338 	char *copy;
2339 	char tmp[SMTP_LINE_MAX];
2340 
2341 	(void)strlcpy(tmp, line, sizeof tmp);
2342 	copy = tmp;
2343 
2344 	if (smtp_mailaddr(&tx->evp.sender, copy, 1, &copy,
2345 		tx->session->smtpname) == 0) {
2346 		smtp_reply(tx->session, "553 %s Sender address syntax error",
2347 		    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
2348 		smtp_tx_free(tx);
2349 		return;
2350 	}
2351 
2352 	while ((opt = strsep(&copy, " "))) {
2353 		if (*opt == '\0')
2354 			continue;
2355 
2356 		if (strncasecmp(opt, "AUTH=", 5) == 0)
2357 			log_debug("debug: smtp: AUTH in MAIL FROM command");
2358 		else if (strncasecmp(opt, "SIZE=", 5) == 0)
2359 			log_debug("debug: smtp: SIZE in MAIL FROM command");
2360 		else if (strcasecmp(opt, "BODY=7BIT") == 0)
2361 			/* XXX only for this transaction */
2362 			tx->session->flags &= ~SF_8BITMIME;
2363 		else if (strcasecmp(opt, "BODY=8BITMIME") == 0)
2364 			;
2365 		else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "RET=", 4) == 0) {
2366 			opt += 4;
2367 			if (strcasecmp(opt, "HDRS") == 0)
2368 				tx->evp.dsn_ret = DSN_RETHDRS;
2369 			else if (strcasecmp(opt, "FULL") == 0)
2370 				tx->evp.dsn_ret = DSN_RETFULL;
2371 		} else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "ENVID=", 6) == 0) {
2372 			opt += 6;
2373 			if (strlcpy(tx->evp.dsn_envid, opt, sizeof(tx->evp.dsn_envid))
2374 			    >= sizeof(tx->evp.dsn_envid)) {
2375 				smtp_reply(tx->session,
2376 				    "503 %s %s: option too large, truncated: %s",
2377 				    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
2378 				    esc_description(ESC_INVALID_COMMAND_ARGUMENTS), opt);
2379 				smtp_tx_free(tx);
2380 				return;
2381 			}
2382 		} else {
2383 			smtp_reply(tx->session, "503 %s %s: Unsupported option %s",
2384 			    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
2385 			    esc_description(ESC_INVALID_COMMAND_ARGUMENTS), opt);
2386 			smtp_tx_free(tx);
2387 			return;
2388 		}
2389 	}
2390 
2391 	/* only check sendertable if defined and user has authenticated */
2392 	if (tx->session->flags & SF_AUTHENTICATED &&
2393 	    tx->session->listener->sendertable[0]) {
2394 		m_create(p_lka, IMSG_SMTP_CHECK_SENDER, 0, 0, -1);
2395 		m_add_id(p_lka, tx->session->id);
2396 		m_add_string(p_lka, tx->session->listener->sendertable);
2397 		m_add_string(p_lka, tx->session->username);
2398 		m_add_mailaddr(p_lka, &tx->evp.sender);
2399 		m_close(p_lka);
2400 		tree_xset(&wait_lka_mail, tx->session->id, tx->session);
2401 	}
2402 	else
2403 		smtp_tx_create_message(tx);
2404 }
2405 
2406 static void
2407 smtp_tx_create_message(struct smtp_tx *tx)
2408 {
2409 	m_create(p_queue, IMSG_SMTP_MESSAGE_CREATE, 0, 0, -1);
2410 	m_add_id(p_queue, tx->session->id);
2411 	m_close(p_queue);
2412 	tree_xset(&wait_queue_msg, tx->session->id, tx->session);
2413 }
2414 
2415 static void
2416 smtp_tx_rcpt_to(struct smtp_tx *tx, const char *line)
2417 {
2418 	char *opt, *p;
2419 	char *copy;
2420 	char tmp[SMTP_LINE_MAX];
2421 
2422 	(void)strlcpy(tmp, line, sizeof tmp);
2423 	copy = tmp;
2424 
2425 	if (tx->rcptcount >= env->sc_session_max_rcpt) {
2426 		smtp_reply(tx->session, "451 %s %s: Too many recipients",
2427 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS),
2428 		    esc_description(ESC_TOO_MANY_RECIPIENTS));
2429 		return;
2430 	}
2431 
2432 	if (smtp_mailaddr(&tx->evp.rcpt, copy, 0, &copy,
2433 	    tx->session->smtpname) == 0) {
2434 		smtp_reply(tx->session,
2435 		    "501 %s Recipient address syntax error",
2436 		    esc_code(ESC_STATUS_PERMFAIL,
2437 		        ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX));
2438 		return;
2439 	}
2440 
2441 	while ((opt = strsep(&copy, " "))) {
2442 		if (*opt == '\0')
2443 			continue;
2444 
2445 		if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "NOTIFY=", 7) == 0) {
2446 			opt += 7;
2447 			while ((p = strsep(&opt, ","))) {
2448 				if (strcasecmp(p, "SUCCESS") == 0)
2449 					tx->evp.dsn_notify |= DSN_SUCCESS;
2450 				else if (strcasecmp(p, "FAILURE") == 0)
2451 					tx->evp.dsn_notify |= DSN_FAILURE;
2452 				else if (strcasecmp(p, "DELAY") == 0)
2453 					tx->evp.dsn_notify |= DSN_DELAY;
2454 				else if (strcasecmp(p, "NEVER") == 0)
2455 					tx->evp.dsn_notify |= DSN_NEVER;
2456 			}
2457 
2458 			if (tx->evp.dsn_notify & DSN_NEVER &&
2459 			    tx->evp.dsn_notify & (DSN_SUCCESS | DSN_FAILURE |
2460 			    DSN_DELAY)) {
2461 				smtp_reply(tx->session,
2462 				    "553 NOTIFY option NEVER cannot be"
2463 				    " combined with other options");
2464 				return;
2465 			}
2466 		} else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "ORCPT=", 6) == 0) {
2467 			opt += 6;
2468 
2469 			if (strncasecmp(opt, "rfc822;", 7) == 0)
2470 				opt += 7;
2471 
2472 			if (!text_to_mailaddr(&tx->evp.dsn_orcpt, opt) ||
2473 			    !valid_localpart(tx->evp.dsn_orcpt.user) ||
2474 			    (strlen(tx->evp.dsn_orcpt.domain) != 0 &&
2475 			     !valid_domainpart(tx->evp.dsn_orcpt.domain))) {
2476 				smtp_reply(tx->session,
2477 				    "553 ORCPT address syntax error");
2478 				return;
2479 			}
2480 		} else {
2481 			smtp_reply(tx->session, "503 Unsupported option %s", opt);
2482 			return;
2483 		}
2484 	}
2485 
2486 	m_create(p_lka, IMSG_SMTP_EXPAND_RCPT, 0, 0, -1);
2487 	m_add_id(p_lka, tx->session->id);
2488 	m_add_envelope(p_lka, &tx->evp);
2489 	m_close(p_lka);
2490 	tree_xset(&wait_lka_rcpt, tx->session->id, tx->session);
2491 }
2492 
2493 static void
2494 smtp_tx_open_message(struct smtp_tx *tx)
2495 {
2496 	m_create(p_queue, IMSG_SMTP_MESSAGE_OPEN, 0, 0, -1);
2497 	m_add_id(p_queue, tx->session->id);
2498 	m_add_msgid(p_queue, tx->msgid);
2499 	m_close(p_queue);
2500 	tree_xset(&wait_queue_fd, tx->session->id, tx->session);
2501 }
2502 
2503 static void
2504 smtp_tx_commit(struct smtp_tx *tx)
2505 {
2506 	m_create(p_queue, IMSG_SMTP_MESSAGE_COMMIT, 0, 0, -1);
2507 	m_add_id(p_queue, tx->session->id);
2508 	m_add_msgid(p_queue, tx->msgid);
2509 	m_close(p_queue);
2510 	tree_xset(&wait_queue_commit, tx->session->id, tx->session);
2511 	smtp_filter_data_end(tx->session);
2512 }
2513 
2514 static void
2515 smtp_tx_rollback(struct smtp_tx *tx)
2516 {
2517 	m_create(p_queue, IMSG_SMTP_MESSAGE_ROLLBACK, 0, 0, -1);
2518 	m_add_msgid(p_queue, tx->msgid);
2519 	m_close(p_queue);
2520 	smtp_report_tx_rollback(tx->session, tx->msgid);
2521 	smtp_report_tx_reset(tx->session, tx->msgid);
2522 	smtp_filter_data_end(tx->session);
2523 }
2524 
2525 static int
2526 smtp_tx_dataline(struct smtp_tx *tx, const char *line)
2527 {
2528 	struct rfc5322_result res;
2529 	int r;
2530 
2531 	log_trace(TRACE_SMTP, "<<< [MSG] %s", line);
2532 
2533 	if (!strcmp(line, ".")) {
2534 		smtp_report_protocol_client(tx->session, ".");
2535 		log_trace(TRACE_SMTP, "<<< [EOM]");
2536 		if (tx->error)
2537 			return 1;
2538 		line = NULL;
2539 	}
2540 	else {
2541 		/* ignore data line if an error is set */
2542 		if (tx->error)
2543 			return 0;
2544 
2545 		/* escape lines starting with a '.' */
2546 		if (line[0] == '.')
2547 			line += 1;
2548 	}
2549 
2550 	if (rfc5322_push(tx->parser, line) == -1) {
2551 		log_warnx("failed to push dataline");
2552 		tx->error = TX_ERROR_INTERNAL;
2553 		return 0;
2554 	}
2555 
2556 	for(;;) {
2557 		r = rfc5322_next(tx->parser, &res);
2558 		switch (r) {
2559 		case -1:
2560 			if (errno == ENOMEM)
2561 				tx->error = TX_ERROR_INTERNAL;
2562 			else
2563 				tx->error = TX_ERROR_MALFORMED;
2564 			return 0;
2565 
2566 		case RFC5322_NONE:
2567 			/* Need more data */
2568 			return 0;
2569 
2570 		case RFC5322_HEADER_START:
2571 			/* ignore bcc */
2572 			if (!strcasecmp("Bcc", res.hdr))
2573 				continue;
2574 
2575 			if (!strcasecmp("To", res.hdr) ||
2576 			    !strcasecmp("Cc", res.hdr) ||
2577 			    !strcasecmp("From", res.hdr)) {
2578 				rfc5322_unfold_header(tx->parser);
2579 				continue;
2580 			}
2581 
2582 			if (!strcasecmp("Received", res.hdr)) {
2583 				if (++tx->rcvcount >= MAX_HOPS_COUNT) {
2584 					log_warnx("warn: loop detected");
2585 					tx->error = TX_ERROR_LOOP;
2586 					return 0;
2587 				}
2588 			}
2589 			else if (!tx->has_date && !strcasecmp("Date", res.hdr))
2590 				tx->has_date = 1;
2591 			else if (!tx->has_message_id &&
2592 			    !strcasecmp("Message-Id", res.hdr))
2593 				tx->has_message_id = 1;
2594 
2595 			smtp_message_printf(tx, "%s:%s\n", res.hdr, res.value);
2596 			break;
2597 
2598 		case RFC5322_HEADER_CONT:
2599 
2600 			if (!strcasecmp("Bcc", res.hdr) ||
2601 			    !strcasecmp("To", res.hdr) ||
2602 			    !strcasecmp("Cc", res.hdr) ||
2603 			    !strcasecmp("From", res.hdr))
2604 				continue;
2605 
2606 			smtp_message_printf(tx, "%s\n", res.value);
2607 			break;
2608 
2609 		case RFC5322_HEADER_END:
2610 			if (!strcasecmp("To", res.hdr) ||
2611 			    !strcasecmp("Cc", res.hdr) ||
2612 			    !strcasecmp("From", res.hdr))
2613 				header_domain_append_callback(tx, res.hdr,
2614 				    res.value);
2615 			break;
2616 
2617 		case RFC5322_END_OF_HEADERS:
2618 			if (tx->session->listener->local ||
2619 			    tx->session->listener->port == 587) {
2620 
2621 				if (!tx->has_date) {
2622 					log_debug("debug: %p: adding Date", tx);
2623 					smtp_message_printf(tx, "Date: %s\n",
2624 					    time_to_text(tx->time));
2625 				}
2626 
2627 				if (!tx->has_message_id) {
2628 					log_debug("debug: %p: adding Message-ID", tx);
2629 					smtp_message_printf(tx,
2630 					    "Message-ID: <%016"PRIx64"@%s>\n",
2631 					    generate_uid(),
2632 					    tx->session->listener->hostname);
2633 				}
2634 			}
2635 			break;
2636 
2637 		case RFC5322_BODY_START:
2638 		case RFC5322_BODY:
2639 			smtp_message_printf(tx, "%s\n", res.value);
2640 			break;
2641 
2642 		case RFC5322_END_OF_MESSAGE:
2643 			return 1;
2644 
2645 		default:
2646 			fatalx("%s", __func__);
2647 		}
2648 	}
2649 }
2650 
2651 static int
2652 smtp_tx_filtered_dataline(struct smtp_tx *tx, const char *line)
2653 {
2654 	if (!strcmp(line, "."))
2655 		line = NULL;
2656 	else {
2657 		/* ignore data line if an error is set */
2658 		if (tx->error)
2659 			return 0;
2660 	}
2661 	io_printf(tx->filter, "%s\n", line ? line : ".");
2662 	return line ? 0 : 1;
2663 }
2664 
2665 static void
2666 smtp_tx_eom(struct smtp_tx *tx)
2667 {
2668 	smtp_filter_phase(FILTER_COMMIT, tx->session, NULL);
2669 }
2670 
2671 static int
2672 smtp_message_fd(struct smtp_tx *tx, int fd)
2673 {
2674 	struct smtp_session *s;
2675 
2676 	s = tx->session;
2677 
2678 	log_debug("smtp: %p: message fd %d", s, fd);
2679 
2680 	if ((tx->ofile = fdopen(fd, "w")) == NULL) {
2681 		close(fd);
2682 		smtp_reply(s, "421 %s Temporary Error",
2683 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
2684 		smtp_enter_state(s, STATE_QUIT);
2685 		return 0;
2686 	}
2687 	return 1;
2688 }
2689 
2690 static void
2691 filter_session_io(struct io *io, int evt, void *arg)
2692 {
2693 	struct smtp_tx*tx = arg;
2694 	char*line = NULL;
2695 	ssize_t len;
2696 
2697 	log_trace(TRACE_IO, "filter session io (smtp): %p: %s %s", tx, io_strevent(evt),
2698 	    io_strio(io));
2699 
2700 	switch (evt) {
2701 	case IO_DATAIN:
2702 	nextline:
2703 		line = io_getline(tx->filter, &len);
2704 		/* No complete line received */
2705 		if (line == NULL)
2706 			return;
2707 
2708 		if (smtp_tx_dataline(tx, line)) {
2709 			smtp_tx_eom(tx);
2710 			return;
2711 		}
2712 
2713 		goto nextline;
2714 	}
2715 }
2716 
2717 static void
2718 smtp_filter_fd(struct smtp_tx *tx, int fd)
2719 {
2720 	struct smtp_session *s;
2721 
2722 	s = tx->session;
2723 
2724 	log_debug("smtp: %p: filter fd %d", s, fd);
2725 
2726 	tx->filter = io_new();
2727 	io_set_fd(tx->filter, fd);
2728 	io_set_callback(tx->filter, filter_session_io, tx);
2729 }
2730 
2731 static void
2732 smtp_message_begin(struct smtp_tx *tx)
2733 {
2734 	struct smtp_session *s;
2735 	int	(*m_printf)(struct smtp_tx *, const char *, ...);
2736 
2737 	m_printf = smtp_message_printf;
2738 	if (tx->filter)
2739 		m_printf = smtp_filter_printf;
2740 
2741 	s = tx->session;
2742 
2743 	log_debug("smtp: %p: message begin", s);
2744 
2745 	smtp_reply(s, "354 Enter mail, end with \".\""
2746 	    " on a line by itself");
2747 
2748 	if (s->junk || (s->tx && s->tx->junk))
2749 		m_printf(tx, "X-Spam: Yes\n");
2750 
2751 	m_printf(tx, "Received: ");
2752 	if (!(s->listener->flags & F_MASK_SOURCE)) {
2753 		m_printf(tx, "from %s (%s %s%s%s)",
2754 		    s->helo,
2755 		    s->rdns,
2756 		    s->ss.ss_family == AF_INET6 ? "" : "[",
2757 		    ss_to_text(&s->ss),
2758 		    s->ss.ss_family == AF_INET6 ? "" : "]");
2759 	}
2760 	m_printf(tx, "\n\tby %s (%s) with %sSMTP%s%s id %08x",
2761 	    s->smtpname,
2762 	    SMTPD_NAME,
2763 	    s->flags & SF_EHLO ? "E" : "",
2764 	    s->flags & SF_SECURE ? "S" : "",
2765 	    s->flags & SF_AUTHENTICATED ? "A" : "",
2766 	    tx->msgid);
2767 
2768 	if (s->flags & SF_SECURE) {
2769 		m_printf(tx, " (%s:%s:%d:%s)",
2770 		    tls_conn_version(io_tls(s->io)),
2771 		    tls_conn_cipher(io_tls(s->io)),
2772 		    tls_conn_cipher_strength(io_tls(s->io)),
2773 		    (s->flags & SF_VERIFIED) ? "YES" : "NO");
2774 
2775 		if (s->listener->flags & F_RECEIVEDAUTH) {
2776 			m_printf(tx, " auth=%s",
2777 			    s->username[0] ? "yes" : "no");
2778 			if (s->username[0])
2779 				m_printf(tx, " user=%s", s->username);
2780 		}
2781 	}
2782 
2783 	if (tx->rcptcount == 1) {
2784 		m_printf(tx, "\n\tfor <%s@%s>",
2785 		    tx->evp.rcpt.user,
2786 		    tx->evp.rcpt.domain);
2787 	}
2788 
2789 	m_printf(tx, ";\n\t%s\n", time_to_text(time(&tx->time)));
2790 
2791 	smtp_enter_state(s, STATE_BODY);
2792 }
2793 
2794 static void
2795 smtp_message_end(struct smtp_tx *tx)
2796 {
2797 	struct smtp_session *s;
2798 
2799 	s = tx->session;
2800 
2801 	log_debug("debug: %p: end of message, error=%d", s, tx->error);
2802 
2803 	fclose(tx->ofile);
2804 	tx->ofile = NULL;
2805 
2806 	switch(tx->error) {
2807 	case TX_OK:
2808 		smtp_tx_commit(tx);
2809 		return;
2810 
2811 	case TX_ERROR_SIZE:
2812 		smtp_reply(s, "554 %s %s: Transaction failed, message too big",
2813 		    esc_code(ESC_STATUS_PERMFAIL, ESC_MESSAGE_TOO_BIG_FOR_SYSTEM),
2814 		    esc_description(ESC_MESSAGE_TOO_BIG_FOR_SYSTEM));
2815 		break;
2816 
2817 	case TX_ERROR_LOOP:
2818 		smtp_reply(s, "500 %s %s: Loop detected",
2819 		   esc_code(ESC_STATUS_PERMFAIL, ESC_ROUTING_LOOP_DETECTED),
2820 		   esc_description(ESC_ROUTING_LOOP_DETECTED));
2821 		break;
2822 
2823 	case TX_ERROR_MALFORMED:
2824 		smtp_reply(s, "550 %s %s: Message is not RFC 2822 compliant",
2825 		    esc_code(ESC_STATUS_PERMFAIL, ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED),
2826 		    esc_description(ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED));
2827 		break;
2828 
2829 	case TX_ERROR_IO:
2830 	case TX_ERROR_RESOURCES:
2831 		smtp_reply(s, "421 %s Temporary Error",
2832 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
2833 		break;
2834 
2835 	default:
2836 		/* fatal? */
2837 		smtp_reply(s, "421 Internal server error");
2838 	}
2839 
2840 	smtp_tx_rollback(tx);
2841 	smtp_tx_free(tx);
2842 	smtp_enter_state(s, STATE_HELO);
2843 }
2844 
2845 static int
2846 smtp_filter_printf(struct smtp_tx *tx, const char *fmt, ...)
2847 {
2848 	va_list	ap;
2849 	int	len;
2850 
2851 	if (tx->error)
2852 		return -1;
2853 
2854 	va_start(ap, fmt);
2855 	len = io_vprintf(tx->filter, fmt, ap);
2856 	va_end(ap);
2857 
2858 	if (len < 0) {
2859 		log_warn("smtp-in: session %016"PRIx64": vfprintf", tx->session->id);
2860 		tx->error = TX_ERROR_IO;
2861 	}
2862 	else
2863 		tx->odatalen += len;
2864 
2865 	return len;
2866 }
2867 
2868 static int
2869 smtp_message_printf(struct smtp_tx *tx, const char *fmt, ...)
2870 {
2871 	va_list	ap;
2872 	int	len;
2873 
2874 	if (tx->error)
2875 		return -1;
2876 
2877 	va_start(ap, fmt);
2878 	len = vfprintf(tx->ofile, fmt, ap);
2879 	va_end(ap);
2880 
2881 	if (len == -1) {
2882 		log_warn("smtp-in: session %016"PRIx64": vfprintf", tx->session->id);
2883 		tx->error = TX_ERROR_IO;
2884 	}
2885 	else
2886 		tx->odatalen += len;
2887 
2888 	return len;
2889 }
2890 
2891 #define CASE(x) case x : return #x
2892 
2893 const char *
2894 smtp_strstate(int state)
2895 {
2896 	static char	buf[32];
2897 
2898 	switch (state) {
2899 	CASE(STATE_NEW);
2900 	CASE(STATE_CONNECTED);
2901 	CASE(STATE_TLS);
2902 	CASE(STATE_HELO);
2903 	CASE(STATE_AUTH_INIT);
2904 	CASE(STATE_AUTH_USERNAME);
2905 	CASE(STATE_AUTH_PASSWORD);
2906 	CASE(STATE_AUTH_FINALIZE);
2907 	CASE(STATE_BODY);
2908 	CASE(STATE_QUIT);
2909 	default:
2910 		(void)snprintf(buf, sizeof(buf), "STATE_??? (%d)", state);
2911 		return (buf);
2912 	}
2913 }
2914 
2915 
2916 static void
2917 smtp_report_link_connect(struct smtp_session *s, const char *rdns, int fcrdns,
2918     const struct sockaddr_storage *ss_src,
2919     const struct sockaddr_storage *ss_dest)
2920 {
2921 	if (! SESSION_FILTERED(s))
2922 		return;
2923 
2924 	report_smtp_link_connect("smtp-in", s->id, rdns, fcrdns, ss_src, ss_dest);
2925 }
2926 
2927 static void
2928 smtp_report_link_greeting(struct smtp_session *s,
2929     const char *domain)
2930 {
2931 	if (! SESSION_FILTERED(s))
2932 		return;
2933 
2934 	report_smtp_link_greeting("smtp-in", s->id, domain);
2935 }
2936 
2937 static void
2938 smtp_report_link_identify(struct smtp_session *s, const char *method, const char *identity)
2939 {
2940 	if (! SESSION_FILTERED(s))
2941 		return;
2942 
2943 	report_smtp_link_identify("smtp-in", s->id, method, identity);
2944 }
2945 
2946 static void
2947 smtp_report_link_tls(struct smtp_session *s, const char *ssl)
2948 {
2949 	if (! SESSION_FILTERED(s))
2950 		return;
2951 
2952 	report_smtp_link_tls("smtp-in", s->id, ssl);
2953 }
2954 
2955 static void
2956 smtp_report_link_disconnect(struct smtp_session *s)
2957 {
2958 	if (! SESSION_FILTERED(s))
2959 		return;
2960 
2961 	report_smtp_link_disconnect("smtp-in", s->id);
2962 }
2963 
2964 static void
2965 smtp_report_link_auth(struct smtp_session *s, const char *user, const char *result)
2966 {
2967 	if (! SESSION_FILTERED(s))
2968 		return;
2969 
2970 	report_smtp_link_auth("smtp-in", s->id, user, result);
2971 }
2972 
2973 static void
2974 smtp_report_tx_reset(struct smtp_session *s, uint32_t msgid)
2975 {
2976 	if (! SESSION_FILTERED(s))
2977 		return;
2978 
2979 	report_smtp_tx_reset("smtp-in", s->id, msgid);
2980 }
2981 
2982 static void
2983 smtp_report_tx_begin(struct smtp_session *s, uint32_t msgid)
2984 {
2985 	if (! SESSION_FILTERED(s))
2986 		return;
2987 
2988 	report_smtp_tx_begin("smtp-in", s->id, msgid);
2989 }
2990 
2991 static void
2992 smtp_report_tx_mail(struct smtp_session *s, uint32_t msgid, const char *address, int ok)
2993 {
2994 	char	mailaddr[SMTPD_MAXMAILADDRSIZE];
2995 	char    *p;
2996 
2997 	if (! SESSION_FILTERED(s))
2998 		return;
2999 
3000 	if ((p = strchr(address, '<')) == NULL)
3001 		return;
3002 	(void)strlcpy(mailaddr, p + 1, sizeof mailaddr);
3003 	if ((p = strchr(mailaddr, '>')) == NULL)
3004 		return;
3005 	*p = '\0';
3006 
3007 	report_smtp_tx_mail("smtp-in", s->id, msgid, mailaddr, ok);
3008 }
3009 
3010 static void
3011 smtp_report_tx_rcpt(struct smtp_session *s, uint32_t msgid, const char *address, int ok)
3012 {
3013 	char	mailaddr[SMTPD_MAXMAILADDRSIZE];
3014 	char    *p;
3015 
3016 	if (! SESSION_FILTERED(s))
3017 		return;
3018 
3019 	if ((p = strchr(address, '<')) == NULL)
3020 		return;
3021 	(void)strlcpy(mailaddr, p + 1, sizeof mailaddr);
3022 	if ((p = strchr(mailaddr, '>')) == NULL)
3023 		return;
3024 	*p = '\0';
3025 
3026 	report_smtp_tx_rcpt("smtp-in", s->id, msgid, mailaddr, ok);
3027 }
3028 
3029 static void
3030 smtp_report_tx_envelope(struct smtp_session *s, uint32_t msgid, uint64_t evpid)
3031 {
3032 	if (! SESSION_FILTERED(s))
3033 		return;
3034 
3035 	report_smtp_tx_envelope("smtp-in", s->id, msgid, evpid);
3036 }
3037 
3038 static void
3039 smtp_report_tx_data(struct smtp_session *s, uint32_t msgid, int ok)
3040 {
3041 	if (! SESSION_FILTERED(s))
3042 		return;
3043 
3044 	report_smtp_tx_data("smtp-in", s->id, msgid, ok);
3045 }
3046 
3047 static void
3048 smtp_report_tx_commit(struct smtp_session *s, uint32_t msgid, size_t msgsz)
3049 {
3050 	if (! SESSION_FILTERED(s))
3051 		return;
3052 
3053 	report_smtp_tx_commit("smtp-in", s->id, msgid, msgsz);
3054 }
3055 
3056 static void
3057 smtp_report_tx_rollback(struct smtp_session *s, uint32_t msgid)
3058 {
3059 	if (! SESSION_FILTERED(s))
3060 		return;
3061 
3062 	report_smtp_tx_rollback("smtp-in", s->id, msgid);
3063 }
3064 
3065 static void
3066 smtp_report_protocol_client(struct smtp_session *s, const char *command)
3067 {
3068 	if (! SESSION_FILTERED(s))
3069 		return;
3070 
3071 	report_smtp_protocol_client("smtp-in", s->id, command);
3072 }
3073 
3074 static void
3075 smtp_report_protocol_server(struct smtp_session *s, const char *response)
3076 {
3077 	if (! SESSION_FILTERED(s))
3078 		return;
3079 
3080 	report_smtp_protocol_server("smtp-in", s->id, response);
3081 }
3082 
3083 static void
3084 smtp_report_filter_response(struct smtp_session *s, int phase, int response, const char *param)
3085 {
3086 	if (! SESSION_FILTERED(s))
3087 		return;
3088 
3089 	report_smtp_filter_response("smtp-in", s->id, phase, response, param);
3090 }
3091 
3092 static void
3093 smtp_report_timeout(struct smtp_session *s)
3094 {
3095 	if (! SESSION_FILTERED(s))
3096 		return;
3097 
3098 	report_smtp_timeout("smtp-in", s->id);
3099 }
3100