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