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