xref: /openbsd-src/usr.sbin/smtpd/smtp_session.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: smtp_session.c,v 1.424 2020/02/03 15:53:52 gilles 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(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, NI_NAMEREQD,
641 		    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 		/* Message body */
1136 		eom = 0;
1137 		if (s->state == STATE_BODY) {
1138 			if (strcmp(line, ".")) {
1139 				s->tx->datain += strlen(line) + 1;
1140 				if (s->tx->datain > env->sc_maxsize)
1141 					s->tx->error = TX_ERROR_SIZE;
1142 			}
1143 			eom = (s->tx->filter == NULL) ?
1144 			    smtp_tx_dataline(s->tx, line) :
1145 			    smtp_tx_filtered_dataline(s->tx, line);
1146 			if (eom == 0)
1147 				goto nextline;
1148 		}
1149 
1150 		/* Pipelining not supported */
1151 		if (io_datalen(s->io)) {
1152 			s->flags |= SF_BADINPUT;
1153 			smtp_reply(s, "500 %s %s: Pipelining not supported",
1154 			    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1155 			    esc_description(ESC_INVALID_COMMAND));
1156 			smtp_enter_state(s, STATE_QUIT);
1157 			io_set_write(io);
1158 			return;
1159 		}
1160 
1161 		if (eom) {
1162 			io_set_write(io);
1163 			if (s->tx->filter == NULL)
1164 				smtp_tx_eom(s->tx);
1165 			return;
1166 		}
1167 
1168 		/* Must be a command */
1169 		if (strlcpy(s->cmd, line, sizeof(s->cmd)) >= sizeof(s->cmd)) {
1170 			s->flags |= SF_BADINPUT;
1171 			smtp_reply(s, "500 %s Command line too long",
1172 			    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_STATUS));
1173 			smtp_enter_state(s, STATE_QUIT);
1174 			io_set_write(io);
1175 			return;
1176 		}
1177 		io_set_write(io);
1178 		smtp_command(s, line);
1179 		break;
1180 
1181 	case IO_LOWAT:
1182 		if (s->state == STATE_QUIT) {
1183 			log_info("%016"PRIx64" smtp disconnected "
1184 			    "reason=quit",
1185 			    s->id);
1186 			smtp_free(s, "done");
1187 			break;
1188 		}
1189 
1190 		/* Wait for the client to start tls */
1191 		if (s->state == STATE_TLS) {
1192 			smtp_cert_init(s);
1193 			break;
1194 		}
1195 
1196 		io_set_read(io);
1197 		break;
1198 
1199 	case IO_TIMEOUT:
1200 		log_info("%016"PRIx64" smtp disconnected "
1201 		    "reason=timeout",
1202 		    s->id);
1203 		smtp_report_timeout(s);
1204 		smtp_free(s, "timeout");
1205 		break;
1206 
1207 	case IO_DISCONNECTED:
1208 		log_info("%016"PRIx64" smtp disconnected "
1209 		    "reason=disconnect",
1210 		    s->id);
1211 		smtp_free(s, "disconnected");
1212 		break;
1213 
1214 	case IO_ERROR:
1215 		log_info("%016"PRIx64" smtp disconnected "
1216 		    "reason=\"io-error: %s\"",
1217 		    s->id, io_error(io));
1218 		smtp_free(s, "IO error");
1219 		break;
1220 
1221 	default:
1222 		fatalx("smtp_io()");
1223 	}
1224 }
1225 
1226 static void
1227 smtp_command(struct smtp_session *s, char *line)
1228 {
1229 	char			       *args;
1230 	int				cmd, i;
1231 
1232 	log_trace(TRACE_SMTP, "smtp: %p: <<< %s", s, line);
1233 
1234 	/*
1235 	 * These states are special.
1236 	 */
1237 	if (s->state == STATE_AUTH_INIT) {
1238 		smtp_report_protocol_client(s, "********");
1239 		smtp_rfc4954_auth_plain(s, line);
1240 		return;
1241 	}
1242 	if (s->state == STATE_AUTH_USERNAME || s->state == STATE_AUTH_PASSWORD) {
1243 		smtp_report_protocol_client(s, "********");
1244 		smtp_rfc4954_auth_login(s, line);
1245 		return;
1246 	}
1247 
1248 	if (s->state == STATE_HELO && strncasecmp(line, "AUTH PLAIN ", 11) == 0)
1249 		smtp_report_protocol_client(s, "AUTH PLAIN ********");
1250 	else
1251 		smtp_report_protocol_client(s, line);
1252 
1253 
1254 	/*
1255 	 * Unlike other commands, "mail from" and "rcpt to" contain a
1256 	 * space in the command name.
1257 	 */
1258 	if (strncasecmp("mail from:", line, 10) == 0 ||
1259 	    strncasecmp("rcpt to:", line, 8) == 0)
1260 		args = strchr(line, ':');
1261 	else
1262 		args = strchr(line, ' ');
1263 
1264 	if (args) {
1265 		*args++ = '\0';
1266 		while (isspace((unsigned char)*args))
1267 			args++;
1268 	}
1269 
1270 	cmd = -1;
1271 	for (i = 0; commands[i].code != -1; i++)
1272 		if (!strcasecmp(line, commands[i].cmd)) {
1273 			cmd = commands[i].code;
1274 			break;
1275 		}
1276 
1277 	s->last_cmd = cmd;
1278 	switch (cmd) {
1279 	/*
1280 	 * INIT
1281 	 */
1282 	case CMD_HELO:
1283 		if (!smtp_check_helo(s, args))
1284 			break;
1285 		smtp_filter_phase(FILTER_HELO, s, args);
1286 		break;
1287 
1288 	case CMD_EHLO:
1289 		if (!smtp_check_ehlo(s, args))
1290 			break;
1291 		smtp_filter_phase(FILTER_EHLO, s, args);
1292 		break;
1293 
1294 	/*
1295 	 * SETUP
1296 	 */
1297 	case CMD_STARTTLS:
1298 		if (!smtp_check_starttls(s, args))
1299 			break;
1300 
1301 		smtp_filter_phase(FILTER_STARTTLS, s, NULL);
1302 		break;
1303 
1304 	case CMD_AUTH:
1305 		if (!smtp_check_auth(s, args))
1306 			break;
1307 		smtp_filter_phase(FILTER_AUTH, s, args);
1308 		break;
1309 
1310 	case CMD_MAIL_FROM:
1311 		if (!smtp_check_mail_from(s, args))
1312 			break;
1313 		smtp_filter_phase(FILTER_MAIL_FROM, s, args);
1314 		break;
1315 
1316 	/*
1317 	 * TRANSACTION
1318 	 */
1319 	case CMD_RCPT_TO:
1320 		if (!smtp_check_rcpt_to(s, args))
1321 			break;
1322 		smtp_filter_phase(FILTER_RCPT_TO, s, args);
1323 		break;
1324 
1325 	case CMD_RSET:
1326 		if (!smtp_check_rset(s, args))
1327 			break;
1328 		smtp_filter_phase(FILTER_RSET, s, NULL);
1329 		break;
1330 
1331 	case CMD_DATA:
1332 		if (!smtp_check_data(s, args))
1333 			break;
1334 		smtp_filter_phase(FILTER_DATA, s, NULL);
1335 		break;
1336 
1337 	/*
1338 	 * ANY
1339 	 */
1340 	case CMD_QUIT:
1341 		if (!smtp_check_noparam(s, args))
1342 			break;
1343 		smtp_filter_phase(FILTER_QUIT, s, NULL);
1344 		break;
1345 
1346 	case CMD_NOOP:
1347 		if (!smtp_check_noparam(s, args))
1348 			break;
1349 		smtp_filter_phase(FILTER_NOOP, s, NULL);
1350 		break;
1351 
1352 	case CMD_HELP:
1353 		if (!smtp_check_noparam(s, args))
1354 			break;
1355 		smtp_proceed_help(s, NULL);
1356 		break;
1357 
1358 	case CMD_WIZ:
1359 		if (!smtp_check_noparam(s, args))
1360 			break;
1361 		smtp_proceed_wiz(s, NULL);
1362 		break;
1363 
1364 	default:
1365 		smtp_reply(s, "500 %s %s: Command unrecognized",
1366 			    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1367 			    esc_description(ESC_INVALID_COMMAND));
1368 		break;
1369 	}
1370 }
1371 
1372 static int
1373 smtp_check_rset(struct smtp_session *s, const char *args)
1374 {
1375 	if (!smtp_check_noparam(s, args))
1376 		return 0;
1377 
1378 	if (s->helo[0] == '\0') {
1379 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1380 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1381 		    esc_description(ESC_INVALID_COMMAND));
1382 		return 0;
1383 	}
1384 	return 1;
1385 }
1386 
1387 static int
1388 smtp_check_helo(struct smtp_session *s, const char *args)
1389 {
1390 	if (!s->banner_sent) {
1391 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1392 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1393 		    esc_description(ESC_INVALID_COMMAND));
1394 		return 0;
1395 	}
1396 
1397 	if (s->helo[0]) {
1398 		smtp_reply(s, "503 %s %s: Already identified",
1399 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1400 		    esc_description(ESC_INVALID_COMMAND));
1401 		return 0;
1402 	}
1403 
1404 	if (args == NULL) {
1405 		smtp_reply(s, "501 %s %s: HELO requires domain name",
1406 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1407 		    esc_description(ESC_INVALID_COMMAND));
1408 		return 0;
1409 	}
1410 
1411 	if (!valid_domainpart(args)) {
1412 		smtp_reply(s, "501 %s %s: Invalid domain name",
1413 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1414 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1415 		return 0;
1416 	}
1417 
1418 	return 1;
1419 }
1420 
1421 static int
1422 smtp_check_ehlo(struct smtp_session *s, const char *args)
1423 {
1424 	if (!s->banner_sent) {
1425 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1426 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1427 		    esc_description(ESC_INVALID_COMMAND));
1428 		return 0;
1429 	}
1430 
1431 	if (s->helo[0]) {
1432 		smtp_reply(s, "503 %s %s: Already identified",
1433 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1434 		    esc_description(ESC_INVALID_COMMAND));
1435 		return 0;
1436 	}
1437 
1438 	if (args == NULL) {
1439 		smtp_reply(s, "501 %s %s: EHLO requires domain name",
1440 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1441 		    esc_description(ESC_INVALID_COMMAND));
1442 		return 0;
1443 	}
1444 
1445 	if (!valid_domainpart(args)) {
1446 		smtp_reply(s, "501 %s %s: Invalid domain name",
1447 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1448 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1449 		return 0;
1450 	}
1451 
1452 	return 1;
1453 }
1454 
1455 static int
1456 smtp_check_auth(struct smtp_session *s, const char *args)
1457 {
1458 	if (s->helo[0] == '\0' || s->tx) {
1459 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1460 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1461 		    esc_description(ESC_INVALID_COMMAND));
1462 		return 0;
1463 	}
1464 
1465 	if (s->flags & SF_AUTHENTICATED) {
1466 		smtp_reply(s, "503 %s %s: Already authenticated",
1467 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1468 		    esc_description(ESC_INVALID_COMMAND));
1469 		return 0;
1470 	}
1471 
1472 	if (!ADVERTISE_AUTH(s)) {
1473 		smtp_reply(s, "503 %s %s: Command not supported",
1474 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1475 		    esc_description(ESC_INVALID_COMMAND));
1476 		return 0;
1477 	}
1478 
1479 	if (args == NULL) {
1480 		smtp_reply(s, "501 %s %s: No parameters given",
1481 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1482 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1483 		return 0;
1484 	}
1485 
1486 	return 1;
1487 }
1488 
1489 static int
1490 smtp_check_starttls(struct smtp_session *s, const char *args)
1491 {
1492 	if (s->helo[0] == '\0' || s->tx) {
1493 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1494 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1495 		    esc_description(ESC_INVALID_COMMAND));
1496 		return 0;
1497 	}
1498 
1499 	if (!(s->listener->flags & F_STARTTLS)) {
1500 		smtp_reply(s, "503 %s %s: Command not supported",
1501 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1502 		    esc_description(ESC_INVALID_COMMAND));
1503 		return 0;
1504 	}
1505 
1506 	if (s->flags & SF_SECURE) {
1507 		smtp_reply(s, "503 %s %s: Channel already secured",
1508 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1509 		    esc_description(ESC_INVALID_COMMAND));
1510 		return 0;
1511 	}
1512 
1513 	if (args != NULL) {
1514 		smtp_reply(s, "501 %s %s: No parameters allowed",
1515 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1516 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1517 		return 0;
1518 	}
1519 
1520 	return 1;
1521 }
1522 
1523 static int
1524 smtp_check_mail_from(struct smtp_session *s, const char *args)
1525 {
1526 	char *copy;
1527 	char tmp[SMTP_LINE_MAX];
1528 	struct mailaddr	sender;
1529 
1530 	(void)strlcpy(tmp, args, sizeof tmp);
1531 	copy = tmp;
1532 
1533 	if (s->helo[0] == '\0' || s->tx) {
1534 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1535 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1536 		    esc_description(ESC_INVALID_COMMAND));
1537 		return 0;
1538 	}
1539 
1540 	if (s->listener->flags & F_STARTTLS_REQUIRE &&
1541 	    !(s->flags & SF_SECURE)) {
1542 		smtp_reply(s,
1543 		    "530 %s %s: Must issue a STARTTLS command first",
1544 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1545 		    esc_description(ESC_INVALID_COMMAND));
1546 		return 0;
1547 	}
1548 
1549 	if (s->listener->flags & F_AUTH_REQUIRE &&
1550 	    !(s->flags & SF_AUTHENTICATED)) {
1551 		smtp_reply(s,
1552 		    "530 %s %s: Must issue an AUTH command first",
1553 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1554 		    esc_description(ESC_INVALID_COMMAND));
1555 		return 0;
1556 	}
1557 
1558 	if (s->mailcount >= env->sc_session_max_mails) {
1559 		/* we can pretend we had too many recipients */
1560 		smtp_reply(s, "452 %s %s: Too many messages sent",
1561 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS),
1562 		    esc_description(ESC_TOO_MANY_RECIPIENTS));
1563 		return 0;
1564 	}
1565 
1566 	if (smtp_mailaddr(&sender, copy, 1, &copy,
1567 		s->smtpname) == 0) {
1568 		smtp_reply(s, "553 %s Sender address syntax error",
1569 		    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
1570 		return 0;
1571 	}
1572 
1573 	return 1;
1574 }
1575 
1576 static int
1577 smtp_check_rcpt_to(struct smtp_session *s, const char *args)
1578 {
1579 	char *copy;
1580 	char tmp[SMTP_LINE_MAX];
1581 
1582 	(void)strlcpy(tmp, args, sizeof tmp);
1583 	copy = tmp;
1584 
1585 	if (s->tx == NULL) {
1586 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1587 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1588 		    esc_description(ESC_INVALID_COMMAND));
1589 		return 0;
1590 	}
1591 
1592 	if (s->tx->rcptcount >= env->sc_session_max_rcpt) {
1593 		smtp_reply(s->tx->session, "451 %s %s: Too many recipients",
1594 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS),
1595 		    esc_description(ESC_TOO_MANY_RECIPIENTS));
1596 		return 0;
1597 	}
1598 
1599 	if (smtp_mailaddr(&s->tx->evp.rcpt, copy, 0, &copy,
1600 		s->tx->session->smtpname) == 0) {
1601 		smtp_reply(s->tx->session,
1602 		    "501 %s Recipient address syntax error",
1603 		    esc_code(ESC_STATUS_PERMFAIL,
1604 		        ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX));
1605 		return 0;
1606 	}
1607 
1608 	return 1;
1609 }
1610 
1611 static int
1612 smtp_check_data(struct smtp_session *s, const char *args)
1613 {
1614 	if (!smtp_check_noparam(s, args))
1615 		return 0;
1616 
1617 	if (s->tx == NULL) {
1618 		smtp_reply(s, "503 %s %s: Command not allowed at this point.",
1619 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1620 		    esc_description(ESC_INVALID_COMMAND));
1621 		return 0;
1622 	}
1623 
1624 	if (s->tx->rcptcount == 0) {
1625 		smtp_reply(s, "503 %s %s: No recipient specified",
1626 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1627 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1628 		return 0;
1629 	}
1630 
1631 	return 1;
1632 }
1633 
1634 static int
1635 smtp_check_noparam(struct smtp_session *s, const char *args)
1636 {
1637 	if (args != NULL) {
1638 		smtp_reply(s, "500 %s %s: command does not accept arguments.",
1639 		    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
1640 		    esc_description(ESC_INVALID_COMMAND_ARGUMENTS));
1641 		return 0;
1642 	}
1643 	return 1;
1644 }
1645 
1646 static void
1647 smtp_query_filters(enum filter_phase phase, struct smtp_session *s, const char *args)
1648 {
1649 	m_create(p_lka, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1);
1650 	m_add_id(p_lka, s->id);
1651 	m_add_int(p_lka, phase);
1652 	m_add_string(p_lka, args);
1653 	m_close(p_lka);
1654 	tree_xset(&wait_filters, s->id, s);
1655 }
1656 
1657 static void
1658 smtp_filter_begin(struct smtp_session *s)
1659 {
1660 	if (!SESSION_FILTERED(s))
1661 		return;
1662 
1663 	m_create(p_lka, IMSG_FILTER_SMTP_BEGIN, 0, 0, -1);
1664 	m_add_id(p_lka, s->id);
1665 	m_add_string(p_lka, s->listener->filter_name);
1666 	m_close(p_lka);
1667 }
1668 
1669 static void
1670 smtp_filter_end(struct smtp_session *s)
1671 {
1672 	if (!SESSION_FILTERED(s))
1673 		return;
1674 
1675 	m_create(p_lka, IMSG_FILTER_SMTP_END, 0, 0, -1);
1676 	m_add_id(p_lka, s->id);
1677 	m_close(p_lka);
1678 }
1679 
1680 static void
1681 smtp_filter_data_begin(struct smtp_session *s)
1682 {
1683 	if (!SESSION_FILTERED(s))
1684 		return;
1685 
1686 	m_create(p_lka, IMSG_FILTER_SMTP_DATA_BEGIN, 0, 0, -1);
1687 	m_add_id(p_lka, s->id);
1688 	m_close(p_lka);
1689 	tree_xset(&wait_filter_fd, s->id, s);
1690 }
1691 
1692 static void
1693 smtp_filter_data_end(struct smtp_session *s)
1694 {
1695 	if (!SESSION_FILTERED(s))
1696 		return;
1697 
1698 	if (s->tx->filter == NULL)
1699 		return;
1700 
1701 	io_free(s->tx->filter);
1702 	s->tx->filter = NULL;
1703 
1704 	m_create(p_lka, IMSG_FILTER_SMTP_DATA_END, 0, 0, -1);
1705 	m_add_id(p_lka, s->id);
1706 	m_close(p_lka);
1707 }
1708 
1709 static void
1710 smtp_filter_phase(enum filter_phase phase, struct smtp_session *s, const char *param)
1711 {
1712 	uint8_t i;
1713 
1714 	s->filter_phase = phase;
1715 	s->filter_param = param;
1716 
1717 	if (SESSION_FILTERED(s)) {
1718 		smtp_query_filters(phase, s, param ? param : "");
1719 		return;
1720 	}
1721 
1722 	if (s->filter_phase == FILTER_CONNECT) {
1723 		smtp_proceed_connected(s);
1724 		return;
1725 	}
1726 
1727 	for (i = 0; i < nitems(commands); ++i)
1728 		if (commands[i].filter_phase == s->filter_phase) {
1729 			commands[i].proceed(s, param);
1730 			break;
1731 		}
1732 }
1733 
1734 static void
1735 smtp_proceed_rset(struct smtp_session *s, const char *args)
1736 {
1737 	smtp_reply(s, "250 %s Reset state",
1738 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1739 
1740 	if (s->tx) {
1741 		if (s->tx->msgid)
1742 			smtp_tx_rollback(s->tx);
1743 		smtp_tx_free(s->tx);
1744 	}
1745 }
1746 
1747 static void
1748 smtp_proceed_helo(struct smtp_session *s, const char *args)
1749 {
1750 	(void)strlcpy(s->helo, args, sizeof(s->helo));
1751 	s->flags &= SF_SECURE | SF_AUTHENTICATED | SF_VERIFIED;
1752 
1753 	smtp_report_link_identify(s, "HELO", s->helo);
1754 
1755 	smtp_enter_state(s, STATE_HELO);
1756 
1757 	smtp_reply(s, "250 %s Hello %s %s%s%s, pleased to meet you",
1758 	    s->smtpname,
1759 	    s->helo,
1760 	    s->ss.ss_family == AF_INET6 ? "" : "[",
1761 	    ss_to_text(&s->ss),
1762 	    s->ss.ss_family == AF_INET6 ? "" : "]");
1763 }
1764 
1765 static void
1766 smtp_proceed_ehlo(struct smtp_session *s, const char *args)
1767 {
1768 	(void)strlcpy(s->helo, args, sizeof(s->helo));
1769 	s->flags &= SF_SECURE | SF_AUTHENTICATED | SF_VERIFIED;
1770 	s->flags |= SF_EHLO;
1771 	s->flags |= SF_8BITMIME;
1772 
1773 	smtp_report_link_identify(s, "EHLO", s->helo);
1774 
1775 	smtp_enter_state(s, STATE_HELO);
1776 	smtp_reply(s, "250-%s Hello %s %s%s%s, pleased to meet you",
1777 	    s->smtpname,
1778 	    s->helo,
1779 	    s->ss.ss_family == AF_INET6 ? "" : "[",
1780 	    ss_to_text(&s->ss),
1781 	    s->ss.ss_family == AF_INET6 ? "" : "]");
1782 
1783 	smtp_reply(s, "250-8BITMIME");
1784 	smtp_reply(s, "250-ENHANCEDSTATUSCODES");
1785 	smtp_reply(s, "250-SIZE %zu", env->sc_maxsize);
1786 	if (ADVERTISE_EXT_DSN(s))
1787 		smtp_reply(s, "250-DSN");
1788 	if (ADVERTISE_TLS(s))
1789 		smtp_reply(s, "250-STARTTLS");
1790 	if (ADVERTISE_AUTH(s))
1791 		smtp_reply(s, "250-AUTH PLAIN LOGIN");
1792 	smtp_reply(s, "250 HELP");
1793 }
1794 
1795 static void
1796 smtp_proceed_auth(struct smtp_session *s, const char *args)
1797 {
1798 	char tmp[SMTP_LINE_MAX];
1799 	char *eom, *method;
1800 
1801 	(void)strlcpy(tmp, args, sizeof tmp);
1802 
1803 	method = tmp;
1804 	eom = strchr(tmp, ' ');
1805 	if (eom == NULL)
1806 		eom = strchr(tmp, '\t');
1807 	if (eom != NULL)
1808 		*eom++ = '\0';
1809 	if (strcasecmp(method, "PLAIN") == 0)
1810 		smtp_rfc4954_auth_plain(s, eom);
1811 	else if (strcasecmp(method, "LOGIN") == 0)
1812 		smtp_rfc4954_auth_login(s, eom);
1813 	else
1814 		smtp_reply(s, "504 %s %s: AUTH method \"%s\" not supported",
1815 		    esc_code(ESC_STATUS_PERMFAIL, ESC_SECURITY_FEATURES_NOT_SUPPORTED),
1816 		    esc_description(ESC_SECURITY_FEATURES_NOT_SUPPORTED),
1817 		    method);
1818 }
1819 
1820 static void
1821 smtp_proceed_starttls(struct smtp_session *s, const char *args)
1822 {
1823 	smtp_reply(s, "220 %s Ready to start TLS",
1824 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1825 	smtp_enter_state(s, STATE_TLS);
1826 }
1827 
1828 static void
1829 smtp_proceed_mail_from(struct smtp_session *s, const char *args)
1830 {
1831 	char *copy;
1832 	char tmp[SMTP_LINE_MAX];
1833 
1834 	(void)strlcpy(tmp, args, sizeof tmp);
1835 	copy = tmp;
1836 
1837        	if (!smtp_tx(s)) {
1838 		smtp_reply(s, "421 %s Temporary Error",
1839 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
1840 		smtp_enter_state(s, STATE_QUIT);
1841 		return;
1842 	}
1843 
1844 	if (smtp_mailaddr(&s->tx->evp.sender, copy, 1, &copy,
1845 		s->smtpname) == 0) {
1846 		smtp_reply(s, "553 %s Sender address syntax error",
1847 		    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
1848 		smtp_tx_free(s->tx);
1849 		return;
1850 	}
1851 
1852 	smtp_tx_mail_from(s->tx, args);
1853 }
1854 
1855 static void
1856 smtp_proceed_rcpt_to(struct smtp_session *s, const char *args)
1857 {
1858 	smtp_tx_rcpt_to(s->tx, args);
1859 }
1860 
1861 static void
1862 smtp_proceed_data(struct smtp_session *s, const char *args)
1863 {
1864 	smtp_tx_open_message(s->tx);
1865 }
1866 
1867 static void
1868 smtp_proceed_quit(struct smtp_session *s, const char *args)
1869 {
1870 	smtp_reply(s, "221 %s Bye",
1871 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1872 	smtp_enter_state(s, STATE_QUIT);
1873 }
1874 
1875 static void
1876 smtp_proceed_noop(struct smtp_session *s, const char *args)
1877 {
1878 	smtp_reply(s, "250 %s Ok",
1879 	    esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS));
1880 }
1881 
1882 static void
1883 smtp_proceed_help(struct smtp_session *s, const char *args)
1884 {
1885 	const char *code = esc_code(ESC_STATUS_OK, ESC_OTHER_STATUS);
1886 
1887 	smtp_reply(s, "214-%s This is " SMTPD_NAME, code);
1888 	smtp_reply(s, "214-%s To report bugs in the implementation, "
1889 	    "please contact bugs@openbsd.org", code);
1890 	smtp_reply(s, "214-%s with full details", code);
1891 	smtp_reply(s, "214 %s End of HELP info", code);
1892 }
1893 
1894 static void
1895 smtp_proceed_wiz(struct smtp_session *s, const char *args)
1896 {
1897 	smtp_reply(s, "500 %s %s: this feature is not supported yet ;-)",
1898 	    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND),
1899 	    esc_description(ESC_INVALID_COMMAND));
1900 }
1901 
1902 static void
1903 smtp_proceed_commit(struct smtp_session *s, const char *args)
1904 {
1905 	smtp_message_end(s->tx);
1906 }
1907 
1908 static void
1909 smtp_proceed_rollback(struct smtp_session *s, const char *args)
1910 {
1911 	struct smtp_tx *tx;
1912 
1913 	tx = s->tx;
1914 
1915 	fclose(tx->ofile);
1916 	tx->ofile = NULL;
1917 
1918 	smtp_tx_rollback(tx);
1919 	smtp_tx_free(tx);
1920 	smtp_enter_state(s, STATE_HELO);
1921 }
1922 
1923 static void
1924 smtp_rfc4954_auth_plain(struct smtp_session *s, char *arg)
1925 {
1926 	char		 buf[1024], *user, *pass;
1927 	int		 len;
1928 
1929 	switch (s->state) {
1930 	case STATE_HELO:
1931 		if (arg == NULL) {
1932 			smtp_enter_state(s, STATE_AUTH_INIT);
1933 			smtp_reply(s, "334 ");
1934 			return;
1935 		}
1936 		smtp_enter_state(s, STATE_AUTH_INIT);
1937 		/* FALLTHROUGH */
1938 
1939 	case STATE_AUTH_INIT:
1940 		/* String is not NUL terminated, leave room. */
1941 		if ((len = base64_decode(arg, (unsigned char *)buf,
1942 			    sizeof(buf) - 1)) == -1)
1943 			goto abort;
1944 		/* buf is a byte string, NUL terminate. */
1945 		buf[len] = '\0';
1946 
1947 		/*
1948 		 * Skip "foo" in "foo\0user\0pass", if present.
1949 		 */
1950 		user = memchr(buf, '\0', len);
1951 		if (user == NULL || user >= buf + len - 2)
1952 			goto abort;
1953 		user++; /* skip NUL */
1954 		if (strlcpy(s->username, user, sizeof(s->username))
1955 		    >= sizeof(s->username))
1956 			goto abort;
1957 
1958 		pass = memchr(user, '\0', len - (user - buf));
1959 		if (pass == NULL || pass >= buf + len - 2)
1960 			goto abort;
1961 		pass++; /* skip NUL */
1962 
1963 		m_create(p_lka,  IMSG_SMTP_AUTHENTICATE, 0, 0, -1);
1964 		m_add_id(p_lka, s->id);
1965 		m_add_string(p_lka, s->listener->authtable);
1966 		m_add_string(p_lka, user);
1967 		m_add_string(p_lka, pass);
1968 		m_close(p_lka);
1969 		tree_xset(&wait_parent_auth, s->id, s);
1970 		return;
1971 
1972 	default:
1973 		fatal("smtp_rfc4954_auth_plain: unknown state");
1974 	}
1975 
1976 abort:
1977 	smtp_reply(s, "501 %s %s: Syntax error",
1978 	    esc_code(ESC_STATUS_PERMFAIL, ESC_SYNTAX_ERROR),
1979 	    esc_description(ESC_SYNTAX_ERROR));
1980 	smtp_enter_state(s, STATE_HELO);
1981 }
1982 
1983 static void
1984 smtp_rfc4954_auth_login(struct smtp_session *s, char *arg)
1985 {
1986 	char		buf[LINE_MAX];
1987 
1988 	switch (s->state) {
1989 	case STATE_HELO:
1990 		smtp_enter_state(s, STATE_AUTH_USERNAME);
1991 		if (arg != NULL && *arg != '\0') {
1992 			smtp_rfc4954_auth_login(s, arg);
1993 			return;
1994 		}
1995 		smtp_reply(s, "334 VXNlcm5hbWU6");
1996 		return;
1997 
1998 	case STATE_AUTH_USERNAME:
1999 		memset(s->username, 0, sizeof(s->username));
2000 		if (base64_decode(arg, (unsigned char *)s->username,
2001 				  sizeof(s->username) - 1) == -1)
2002 			goto abort;
2003 
2004 		smtp_enter_state(s, STATE_AUTH_PASSWORD);
2005 		smtp_reply(s, "334 UGFzc3dvcmQ6");
2006 		return;
2007 
2008 	case STATE_AUTH_PASSWORD:
2009 		memset(buf, 0, sizeof(buf));
2010 		if (base64_decode(arg, (unsigned char *)buf,
2011 				  sizeof(buf)-1) == -1)
2012 			goto abort;
2013 
2014 		m_create(p_lka,  IMSG_SMTP_AUTHENTICATE, 0, 0, -1);
2015 		m_add_id(p_lka, s->id);
2016 		m_add_string(p_lka, s->listener->authtable);
2017 		m_add_string(p_lka, s->username);
2018 		m_add_string(p_lka, buf);
2019 		m_close(p_lka);
2020 		tree_xset(&wait_parent_auth, s->id, s);
2021 		return;
2022 
2023 	default:
2024 		fatal("smtp_rfc4954_auth_login: unknown state");
2025 	}
2026 
2027 abort:
2028 	smtp_reply(s, "501 %s %s: Syntax error",
2029 	    esc_code(ESC_STATUS_PERMFAIL, ESC_SYNTAX_ERROR),
2030 	    esc_description(ESC_SYNTAX_ERROR));
2031 	smtp_enter_state(s, STATE_HELO);
2032 }
2033 
2034 static void
2035 smtp_lookup_servername(struct smtp_session *s)
2036 {
2037 	if (s->listener->hostnametable[0]) {
2038 		m_create(p_lka, IMSG_SMTP_LOOKUP_HELO, 0, 0, -1);
2039 		m_add_id(p_lka, s->id);
2040 		m_add_string(p_lka, s->listener->hostnametable);
2041 		m_add_sockaddr(p_lka, (struct sockaddr*)&s->listener->ss);
2042 		m_close(p_lka);
2043 		tree_xset(&wait_lka_helo, s->id, s);
2044 		return;
2045 	}
2046 
2047 	smtp_connected(s);
2048 }
2049 
2050 static void
2051 smtp_connected(struct smtp_session *s)
2052 {
2053 	smtp_enter_state(s, STATE_CONNECTED);
2054 
2055 	log_info("%016"PRIx64" smtp connected address=%s host=%s",
2056 	    s->id, ss_to_text(&s->ss), s->rdns);
2057 
2058 	smtp_filter_begin(s);
2059 
2060 	smtp_report_link_connect(s, s->rdns, s->fcrdns, &s->ss,
2061 	    &s->listener->ss);
2062 
2063 	smtp_filter_phase(FILTER_CONNECT, s, ss_to_text(&s->ss));
2064 }
2065 
2066 static void
2067 smtp_proceed_connected(struct smtp_session *s)
2068 {
2069 	if (s->listener->flags & F_SMTPS)
2070 		smtp_cert_init(s);
2071 	else
2072 		smtp_send_banner(s);
2073 }
2074 
2075 static void
2076 smtp_send_banner(struct smtp_session *s)
2077 {
2078 	smtp_reply(s, "220 %s ESMTP %s", s->smtpname, SMTPD_NAME);
2079 	s->banner_sent = 1;
2080 	smtp_report_link_greeting(s, s->smtpname);
2081 }
2082 
2083 void
2084 smtp_enter_state(struct smtp_session *s, int newstate)
2085 {
2086 	log_trace(TRACE_SMTP, "smtp: %p: %s -> %s", s,
2087 	    smtp_strstate(s->state),
2088 	    smtp_strstate(newstate));
2089 
2090 	s->state = newstate;
2091 }
2092 
2093 static void
2094 smtp_reply(struct smtp_session *s, char *fmt, ...)
2095 {
2096 	va_list	 ap;
2097 	int	 n;
2098 	char	 buf[LINE_MAX*2], tmp[LINE_MAX*2];
2099 
2100 	va_start(ap, fmt);
2101 	n = vsnprintf(buf, sizeof buf, fmt, ap);
2102 	va_end(ap);
2103 	if (n < 0)
2104 		fatalx("smtp_reply: response format error");
2105 	if (n < 4)
2106 		fatalx("smtp_reply: response too short");
2107 	if (n >= (int)sizeof buf) {
2108 		/* only first three bytes are used by SMTP logic,
2109 		 * so if _our_ reply does not fit entirely in the
2110 		 * buffer, it's ok to truncate.
2111 		 */
2112 	}
2113 
2114 	log_trace(TRACE_SMTP, "smtp: %p: >>> %s", s, buf);
2115 	smtp_report_protocol_server(s, buf);
2116 
2117 	switch (buf[0]) {
2118 	case '2':
2119 		if (s->tx) {
2120 			if (s->last_cmd == CMD_MAIL_FROM) {
2121 				smtp_report_tx_begin(s, s->tx->msgid);
2122 				smtp_report_tx_mail(s, s->tx->msgid, s->cmd + 10, 1);
2123 			}
2124 			else if (s->last_cmd == CMD_RCPT_TO)
2125 				smtp_report_tx_rcpt(s, s->tx->msgid, s->cmd + 8, 1);
2126 		}
2127 		break;
2128 	case '3':
2129 		if (s->tx) {
2130 			if (s->last_cmd == CMD_DATA)
2131 				smtp_report_tx_data(s, s->tx->msgid, 1);
2132 		}
2133 		break;
2134 	case '5':
2135 	case '4':
2136 		/* do not report smtp_tx_mail/smtp_tx_rcpt errors
2137 		 * if they happened outside of a transaction.
2138 		 */
2139 		if (s->tx) {
2140 			if (s->last_cmd == CMD_MAIL_FROM)
2141 				smtp_report_tx_mail(s, s->tx->msgid,
2142 				    s->cmd + 10, buf[0] == '4' ? -1 : 0);
2143 			else if (s->last_cmd == CMD_RCPT_TO)
2144 				smtp_report_tx_rcpt(s,
2145 				    s->tx->msgid, s->cmd + 8, buf[0] == '4' ? -1 : 0);
2146 			else if (s->last_cmd == CMD_DATA && s->tx->rcptcount)
2147 				smtp_report_tx_data(s, s->tx->msgid,
2148 				    buf[0] == '4' ? -1 : 0);
2149 		}
2150 
2151 		if (s->flags & SF_BADINPUT) {
2152 			log_info("%016"PRIx64" smtp "
2153 			    "bad-input result=\"%.*s\"",
2154 			    s->id, n, buf);
2155 		}
2156 		else if (s->state == STATE_AUTH_INIT) {
2157 			log_info("%016"PRIx64" smtp "
2158 			    "failed-command "
2159 			    "command=\"AUTH PLAIN (...)\" result=\"%.*s\"",
2160 			    s->id, n, buf);
2161 		}
2162 		else if (s->state == STATE_AUTH_USERNAME) {
2163 			log_info("%016"PRIx64" smtp "
2164 			    "failed-command "
2165 			    "command=\"AUTH LOGIN (username)\" result=\"%.*s\"",
2166 			    s->id, n, buf);
2167 		}
2168 		else if (s->state == STATE_AUTH_PASSWORD) {
2169 			log_info("%016"PRIx64" smtp "
2170 			    "failed-command "
2171 			    "command=\"AUTH LOGIN (password)\" result=\"%.*s\"",
2172 			    s->id, n, buf);
2173 		}
2174 		else {
2175 			strnvis(tmp, s->cmd, sizeof tmp, VIS_SAFE | VIS_CSTYLE);
2176 			log_info("%016"PRIx64" smtp "
2177 			    "failed-command command=\"%s\" "
2178 			    "result=\"%.*s\"",
2179 			    s->id, tmp, n, buf);
2180 		}
2181 		break;
2182 	}
2183 
2184 	io_xprintf(s->io, "%s\r\n", buf);
2185 }
2186 
2187 static void
2188 smtp_free(struct smtp_session *s, const char * reason)
2189 {
2190 	if (s->tx) {
2191 		if (s->tx->msgid)
2192 			smtp_tx_rollback(s->tx);
2193 		smtp_tx_free(s->tx);
2194 	}
2195 
2196 	smtp_report_link_disconnect(s);
2197 	smtp_filter_end(s);
2198 
2199 	if (s->flags & SF_SECURE && s->listener->flags & F_SMTPS)
2200 		stat_decrement("smtp.smtps", 1);
2201 	if (s->flags & SF_SECURE && s->listener->flags & F_STARTTLS)
2202 		stat_decrement("smtp.tls", 1);
2203 
2204 	io_free(s->io);
2205 	free(s);
2206 
2207 	smtp_collect();
2208 }
2209 
2210 static int
2211 smtp_mailaddr(struct mailaddr *maddr, char *line, int mailfrom, char **args,
2212     const char *domain)
2213 {
2214 	char   *p, *e;
2215 
2216 	if (line == NULL)
2217 		return (0);
2218 
2219 	if (*line != '<')
2220 		return (0);
2221 
2222 	e = strchr(line, '>');
2223 	if (e == NULL)
2224 		return (0);
2225 	*e++ = '\0';
2226 	while (*e == ' ')
2227 		e++;
2228 	*args = e;
2229 
2230 	if (!text_to_mailaddr(maddr, line + 1))
2231 		return (0);
2232 
2233 	p = strchr(maddr->user, ':');
2234 	if (p != NULL) {
2235 		p++;
2236 		memmove(maddr->user, p, strlen(p) + 1);
2237 	}
2238 
2239 	/* accept empty return-path in MAIL FROM, required for bounces */
2240 	if (mailfrom && maddr->user[0] == '\0' && maddr->domain[0] == '\0')
2241 		return (1);
2242 
2243 	/* no or invalid user-part, reject */
2244 	if (maddr->user[0] == '\0' || !valid_localpart(maddr->user))
2245 		return (0);
2246 
2247 	/* no domain part, local user */
2248 	if (maddr->domain[0] == '\0') {
2249 		(void)strlcpy(maddr->domain, domain,
2250 			sizeof(maddr->domain));
2251 	}
2252 
2253 	if (!valid_domainpart(maddr->domain))
2254 		return (0);
2255 
2256 	return (1);
2257 }
2258 
2259 static void
2260 smtp_cert_init(struct smtp_session *s)
2261 {
2262 	const char *name;
2263 	int fallback;
2264 
2265 	if (s->listener->pki_name[0]) {
2266 		name = s->listener->pki_name;
2267 		fallback = 0;
2268 	}
2269 	else {
2270 		name = s->smtpname;
2271 		fallback = 1;
2272 	}
2273 
2274 	if (cert_init(name, fallback, smtp_cert_init_cb, s))
2275 		tree_xset(&wait_ssl_init, s->id, s);
2276 }
2277 
2278 static void
2279 smtp_cert_init_cb(void *arg, int status, const char *name, const void *cert,
2280     size_t cert_len)
2281 {
2282 	struct smtp_session *s = arg;
2283 	void *ssl, *ssl_ctx;
2284 
2285 	tree_pop(&wait_ssl_init, s->id);
2286 
2287 	if (status == CA_FAIL) {
2288 		log_info("%016"PRIx64" smtp disconnected "
2289 		    "reason=ca-failure",
2290 		    s->id);
2291 		smtp_free(s, "CA failure");
2292 		return;
2293 	}
2294 
2295 	ssl_ctx = dict_get(env->sc_ssl_dict, name);
2296 	ssl = ssl_smtp_init(ssl_ctx, s->listener->flags & F_TLS_VERIFY);
2297 	io_set_read(s->io);
2298 	io_start_tls(s->io, ssl);
2299 }
2300 
2301 static void
2302 smtp_cert_verify(struct smtp_session *s)
2303 {
2304 	const char *name;
2305 	int fallback;
2306 
2307 	if (s->listener->ca_name[0]) {
2308 		name = s->listener->ca_name;
2309 		fallback = 0;
2310 	}
2311 	else {
2312 		name = s->smtpname;
2313 		fallback = 1;
2314 	}
2315 
2316 	if (cert_verify(io_tls(s->io), name, fallback, smtp_cert_verify_cb, s)) {
2317 		tree_xset(&wait_ssl_verify, s->id, s);
2318 		io_pause(s->io, IO_IN);
2319 	}
2320 }
2321 
2322 static void
2323 smtp_cert_verify_cb(void *arg, int status)
2324 {
2325 	struct smtp_session *s = arg;
2326 	const char *reason = NULL;
2327 	int resume;
2328 
2329 	resume = tree_pop(&wait_ssl_verify, s->id) != NULL;
2330 
2331 	switch (status) {
2332 	case CERT_OK:
2333 		reason = "cert-ok";
2334 		s->flags |= SF_VERIFIED;
2335 		break;
2336 	case CERT_NOCA:
2337 		reason = "no-ca";
2338 		break;
2339 	case CERT_NOCERT:
2340 		reason = "no-client-cert";
2341 		break;
2342 	case CERT_INVALID:
2343 		reason = "cert-invalid";
2344 		break;
2345 	default:
2346 		reason = "cert-check-failed";
2347 		break;
2348 	}
2349 
2350 	log_debug("smtp: %p: smtp_cert_verify_cb: %s", s, reason);
2351 
2352 	if (!(s->flags & SF_VERIFIED) && (s->listener->flags & F_TLS_VERIFY)) {
2353 		log_info("%016"PRIx64" smtp disconnected "
2354 		    " reason=%s", s->id,
2355 		    reason);
2356 		smtp_free(s, "SSL certificate check failed");
2357 		return;
2358 	}
2359 
2360 	smtp_tls_verified(s);
2361 	if (resume)
2362 		io_resume(s->io, IO_IN);
2363 }
2364 
2365 static void
2366 smtp_auth_failure_resume(int fd, short event, void *p)
2367 {
2368 	struct smtp_session *s = p;
2369 
2370 	smtp_reply(s, "535 Authentication failed");
2371 	smtp_enter_state(s, STATE_HELO);
2372 }
2373 
2374 static void
2375 smtp_auth_failure_pause(struct smtp_session *s)
2376 {
2377 	struct timeval	tv;
2378 
2379 	tv.tv_sec = 0;
2380 	tv.tv_usec = arc4random_uniform(1000000);
2381 	log_trace(TRACE_SMTP, "smtp: timing-attack protection triggered, "
2382 	    "will defer answer for %lu microseconds", tv.tv_usec);
2383 	evtimer_set(&s->pause, smtp_auth_failure_resume, s);
2384 	evtimer_add(&s->pause, &tv);
2385 }
2386 
2387 static int
2388 smtp_tx(struct smtp_session *s)
2389 {
2390 	struct smtp_tx *tx;
2391 
2392 	tx = calloc(1, sizeof(*tx));
2393 	if (tx == NULL)
2394 		return 0;
2395 
2396 	TAILQ_INIT(&tx->rcpts);
2397 
2398 	s->tx = tx;
2399 	tx->session = s;
2400 
2401 	/* setup the envelope */
2402 	tx->evp.ss = s->ss;
2403 	(void)strlcpy(tx->evp.tag, s->listener->tag, sizeof(tx->evp.tag));
2404 	(void)strlcpy(tx->evp.smtpname, s->smtpname, sizeof(tx->evp.smtpname));
2405 	(void)strlcpy(tx->evp.hostname, s->rdns, sizeof tx->evp.hostname);
2406 	(void)strlcpy(tx->evp.helo, s->helo, sizeof(tx->evp.helo));
2407 	(void)strlcpy(tx->evp.username, s->username, sizeof(tx->evp.username));
2408 
2409 	if (s->flags & SF_BOUNCE)
2410 		tx->evp.flags |= EF_BOUNCE;
2411 	if (s->flags & SF_AUTHENTICATED)
2412 		tx->evp.flags |= EF_AUTHENTICATED;
2413 
2414 	if ((tx->parser = rfc5322_parser_new()) == NULL) {
2415 		free(tx);
2416 		return 0;
2417 	}
2418 
2419 	return 1;
2420 }
2421 
2422 static void
2423 smtp_tx_free(struct smtp_tx *tx)
2424 {
2425 	struct smtp_rcpt *rcpt;
2426 
2427 	rfc5322_free(tx->parser);
2428 
2429 	while ((rcpt = TAILQ_FIRST(&tx->rcpts))) {
2430 		TAILQ_REMOVE(&tx->rcpts, rcpt, entry);
2431 		free(rcpt);
2432 	}
2433 
2434 	if (tx->ofile)
2435 		fclose(tx->ofile);
2436 
2437 	tx->session->tx = NULL;
2438 
2439 	free(tx);
2440 }
2441 
2442 static void
2443 smtp_tx_mail_from(struct smtp_tx *tx, const char *line)
2444 {
2445 	char *opt;
2446 	char *copy;
2447 	char tmp[SMTP_LINE_MAX];
2448 
2449 	(void)strlcpy(tmp, line, sizeof tmp);
2450 	copy = tmp;
2451 
2452 	if (smtp_mailaddr(&tx->evp.sender, copy, 1, &copy,
2453 		tx->session->smtpname) == 0) {
2454 		smtp_reply(tx->session, "553 %s Sender address syntax error",
2455 		    esc_code(ESC_STATUS_PERMFAIL, ESC_OTHER_ADDRESS_STATUS));
2456 		smtp_tx_free(tx);
2457 		return;
2458 	}
2459 
2460 	while ((opt = strsep(&copy, " "))) {
2461 		if (*opt == '\0')
2462 			continue;
2463 
2464 		if (strncasecmp(opt, "AUTH=", 5) == 0)
2465 			log_debug("debug: smtp: AUTH in MAIL FROM command");
2466 		else if (strncasecmp(opt, "SIZE=", 5) == 0)
2467 			log_debug("debug: smtp: SIZE in MAIL FROM command");
2468 		else if (strcasecmp(opt, "BODY=7BIT") == 0)
2469 			/* XXX only for this transaction */
2470 			tx->session->flags &= ~SF_8BITMIME;
2471 		else if (strcasecmp(opt, "BODY=8BITMIME") == 0)
2472 			;
2473 		else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "RET=", 4) == 0) {
2474 			opt += 4;
2475 			if (strcasecmp(opt, "HDRS") == 0)
2476 				tx->evp.dsn_ret = DSN_RETHDRS;
2477 			else if (strcasecmp(opt, "FULL") == 0)
2478 				tx->evp.dsn_ret = DSN_RETFULL;
2479 		} else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "ENVID=", 6) == 0) {
2480 			opt += 6;
2481 			if (strlcpy(tx->evp.dsn_envid, opt, sizeof(tx->evp.dsn_envid))
2482 			    >= sizeof(tx->evp.dsn_envid)) {
2483 				smtp_reply(tx->session,
2484 				    "503 %s %s: option too large, truncated: %s",
2485 				    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
2486 				    esc_description(ESC_INVALID_COMMAND_ARGUMENTS), opt);
2487 				smtp_tx_free(tx);
2488 				return;
2489 			}
2490 		} else {
2491 			smtp_reply(tx->session, "503 %s %s: Unsupported option %s",
2492 			    esc_code(ESC_STATUS_PERMFAIL, ESC_INVALID_COMMAND_ARGUMENTS),
2493 			    esc_description(ESC_INVALID_COMMAND_ARGUMENTS), opt);
2494 			smtp_tx_free(tx);
2495 			return;
2496 		}
2497 	}
2498 
2499 	/* only check sendertable if defined and user has authenticated */
2500 	if (tx->session->flags & SF_AUTHENTICATED &&
2501 	    tx->session->listener->sendertable[0]) {
2502 		m_create(p_lka, IMSG_SMTP_CHECK_SENDER, 0, 0, -1);
2503 		m_add_id(p_lka, tx->session->id);
2504 		m_add_string(p_lka, tx->session->listener->sendertable);
2505 		m_add_string(p_lka, tx->session->username);
2506 		m_add_mailaddr(p_lka, &tx->evp.sender);
2507 		m_close(p_lka);
2508 		tree_xset(&wait_lka_mail, tx->session->id, tx->session);
2509 	}
2510 	else
2511 		smtp_tx_create_message(tx);
2512 }
2513 
2514 static void
2515 smtp_tx_create_message(struct smtp_tx *tx)
2516 {
2517 	m_create(p_queue, IMSG_SMTP_MESSAGE_CREATE, 0, 0, -1);
2518 	m_add_id(p_queue, tx->session->id);
2519 	m_close(p_queue);
2520 	tree_xset(&wait_queue_msg, tx->session->id, tx->session);
2521 }
2522 
2523 static void
2524 smtp_tx_rcpt_to(struct smtp_tx *tx, const char *line)
2525 {
2526 	char *opt, *p;
2527 	char *copy;
2528 	char tmp[SMTP_LINE_MAX];
2529 
2530 	(void)strlcpy(tmp, line, sizeof tmp);
2531 	copy = tmp;
2532 
2533 	if (tx->rcptcount >= env->sc_session_max_rcpt) {
2534 		smtp_reply(tx->session, "451 %s %s: Too many recipients",
2535 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_TOO_MANY_RECIPIENTS),
2536 		    esc_description(ESC_TOO_MANY_RECIPIENTS));
2537 		return;
2538 	}
2539 
2540 	if (smtp_mailaddr(&tx->evp.rcpt, copy, 0, &copy,
2541 	    tx->session->smtpname) == 0) {
2542 		smtp_reply(tx->session,
2543 		    "501 %s Recipient address syntax error",
2544 		    esc_code(ESC_STATUS_PERMFAIL,
2545 		        ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX));
2546 		return;
2547 	}
2548 
2549 	while ((opt = strsep(&copy, " "))) {
2550 		if (*opt == '\0')
2551 			continue;
2552 
2553 		if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "NOTIFY=", 7) == 0) {
2554 			opt += 7;
2555 			while ((p = strsep(&opt, ","))) {
2556 				if (strcasecmp(p, "SUCCESS") == 0)
2557 					tx->evp.dsn_notify |= DSN_SUCCESS;
2558 				else if (strcasecmp(p, "FAILURE") == 0)
2559 					tx->evp.dsn_notify |= DSN_FAILURE;
2560 				else if (strcasecmp(p, "DELAY") == 0)
2561 					tx->evp.dsn_notify |= DSN_DELAY;
2562 				else if (strcasecmp(p, "NEVER") == 0)
2563 					tx->evp.dsn_notify |= DSN_NEVER;
2564 			}
2565 
2566 			if (tx->evp.dsn_notify & DSN_NEVER &&
2567 			    tx->evp.dsn_notify & (DSN_SUCCESS | DSN_FAILURE |
2568 			    DSN_DELAY)) {
2569 				smtp_reply(tx->session,
2570 				    "553 NOTIFY option NEVER cannot be"
2571 				    " combined with other options");
2572 				return;
2573 			}
2574 		} else if (ADVERTISE_EXT_DSN(tx->session) && strncasecmp(opt, "ORCPT=", 6) == 0) {
2575 			opt += 6;
2576 
2577 			if (strncasecmp(opt, "rfc822;", 7) == 0)
2578 				opt += 7;
2579 
2580 			if (!text_to_mailaddr(&tx->evp.dsn_orcpt, opt) ||
2581 			    !valid_localpart(tx->evp.dsn_orcpt.user) ||
2582 			    !valid_domainpart(tx->evp.dsn_orcpt.domain)) {
2583 				smtp_reply(tx->session,
2584 				    "553 ORCPT address syntax error");
2585 				return;
2586 			}
2587 		} else {
2588 			smtp_reply(tx->session, "503 Unsupported option %s", opt);
2589 			return;
2590 		}
2591 	}
2592 
2593 	m_create(p_lka, IMSG_SMTP_EXPAND_RCPT, 0, 0, -1);
2594 	m_add_id(p_lka, tx->session->id);
2595 	m_add_envelope(p_lka, &tx->evp);
2596 	m_close(p_lka);
2597 	tree_xset(&wait_lka_rcpt, tx->session->id, tx->session);
2598 }
2599 
2600 static void
2601 smtp_tx_open_message(struct smtp_tx *tx)
2602 {
2603 	m_create(p_queue, IMSG_SMTP_MESSAGE_OPEN, 0, 0, -1);
2604 	m_add_id(p_queue, tx->session->id);
2605 	m_add_msgid(p_queue, tx->msgid);
2606 	m_close(p_queue);
2607 	tree_xset(&wait_queue_fd, tx->session->id, tx->session);
2608 }
2609 
2610 static void
2611 smtp_tx_commit(struct smtp_tx *tx)
2612 {
2613 	m_create(p_queue, IMSG_SMTP_MESSAGE_COMMIT, 0, 0, -1);
2614 	m_add_id(p_queue, tx->session->id);
2615 	m_add_msgid(p_queue, tx->msgid);
2616 	m_close(p_queue);
2617 	tree_xset(&wait_queue_commit, tx->session->id, tx->session);
2618 	smtp_filter_data_end(tx->session);
2619 }
2620 
2621 static void
2622 smtp_tx_rollback(struct smtp_tx *tx)
2623 {
2624 	m_create(p_queue, IMSG_SMTP_MESSAGE_ROLLBACK, 0, 0, -1);
2625 	m_add_msgid(p_queue, tx->msgid);
2626 	m_close(p_queue);
2627 	smtp_report_tx_rollback(tx->session, tx->msgid);
2628 	smtp_report_tx_reset(tx->session, tx->msgid);
2629 	smtp_filter_data_end(tx->session);
2630 }
2631 
2632 static int
2633 smtp_tx_dataline(struct smtp_tx *tx, const char *line)
2634 {
2635 	struct rfc5322_result res;
2636 	int r;
2637 
2638 	log_trace(TRACE_SMTP, "<<< [MSG] %s", line);
2639 
2640 	if (!strcmp(line, ".")) {
2641 		smtp_report_protocol_client(tx->session, ".");
2642 		log_trace(TRACE_SMTP, "<<< [EOM]");
2643 		if (tx->error)
2644 			return 1;
2645 		line = NULL;
2646 	}
2647 	else {
2648 		/* ignore data line if an error is set */
2649 		if (tx->error)
2650 			return 0;
2651 
2652 		/* escape lines starting with a '.' */
2653 		if (line[0] == '.')
2654 			line += 1;
2655 	}
2656 
2657 	if (rfc5322_push(tx->parser, line) == -1) {
2658 		log_warnx("failed to push dataline");
2659 		tx->error = TX_ERROR_INTERNAL;
2660 		return 0;
2661 	}
2662 
2663 	for(;;) {
2664 		r = rfc5322_next(tx->parser, &res);
2665 		switch (r) {
2666 		case -1:
2667 			if (errno == ENOMEM)
2668 				tx->error = TX_ERROR_INTERNAL;
2669 			else
2670 				tx->error = TX_ERROR_MALFORMED;
2671 			return 0;
2672 
2673 		case RFC5322_NONE:
2674 			/* Need more data */
2675 			return 0;
2676 
2677 		case RFC5322_HEADER_START:
2678 			/* ignore bcc */
2679 			if (!strcasecmp("Bcc", res.hdr))
2680 				continue;
2681 
2682 			if (!strcasecmp("To", res.hdr) ||
2683 			    !strcasecmp("Cc", res.hdr) ||
2684 			    !strcasecmp("From", res.hdr)) {
2685 				rfc5322_unfold_header(tx->parser);
2686 				continue;
2687 			}
2688 
2689 			if (!strcasecmp("Received", res.hdr)) {
2690 				if (++tx->rcvcount >= MAX_HOPS_COUNT) {
2691 					log_warnx("warn: loop detected");
2692 					tx->error = TX_ERROR_LOOP;
2693 					return 0;
2694 				}
2695 			}
2696 			else if (!tx->has_date && !strcasecmp("Date", res.hdr))
2697 				tx->has_date = 1;
2698 			else if (!tx->has_message_id &&
2699 			    !strcasecmp("Message-Id", res.hdr))
2700 				tx->has_message_id = 1;
2701 
2702 			smtp_message_printf(tx, "%s:%s\n", res.hdr, res.value);
2703 			break;
2704 
2705 		case RFC5322_HEADER_CONT:
2706 
2707 			if (!strcasecmp("Bcc", res.hdr) ||
2708 			    !strcasecmp("To", res.hdr) ||
2709 			    !strcasecmp("Cc", res.hdr) ||
2710 			    !strcasecmp("From", res.hdr))
2711 				continue;
2712 
2713 			smtp_message_printf(tx, "%s\n", res.value);
2714 			break;
2715 
2716 		case RFC5322_HEADER_END:
2717 			if (!strcasecmp("To", res.hdr) ||
2718 			    !strcasecmp("Cc", res.hdr) ||
2719 			    !strcasecmp("From", res.hdr))
2720 				header_domain_append_callback(tx, res.hdr,
2721 				    res.value);
2722 			break;
2723 
2724 		case RFC5322_END_OF_HEADERS:
2725 			if (tx->session->listener->local ||
2726 			    tx->session->listener->port == 587) {
2727 
2728 				if (!tx->has_date) {
2729 					log_debug("debug: %p: adding Date", tx);
2730 					smtp_message_printf(tx, "Date: %s\n",
2731 					    time_to_text(tx->time));
2732 				}
2733 
2734 				if (!tx->has_message_id) {
2735 					log_debug("debug: %p: adding Message-ID", tx);
2736 					smtp_message_printf(tx,
2737 					    "Message-ID: <%016"PRIx64"@%s>\n",
2738 					    generate_uid(),
2739 					    tx->session->listener->hostname);
2740 				}
2741 			}
2742 			break;
2743 
2744 		case RFC5322_BODY_START:
2745 		case RFC5322_BODY:
2746 			smtp_message_printf(tx, "%s\n", res.value);
2747 			break;
2748 
2749 		case RFC5322_END_OF_MESSAGE:
2750 			return 1;
2751 
2752 		default:
2753 			fatalx("%s", __func__);
2754 		}
2755 	}
2756 }
2757 
2758 static int
2759 smtp_tx_filtered_dataline(struct smtp_tx *tx, const char *line)
2760 {
2761 	if (!strcmp(line, "."))
2762 		line = NULL;
2763 	else {
2764 		/* ignore data line if an error is set */
2765 		if (tx->error)
2766 			return 0;
2767 	}
2768 	io_printf(tx->filter, "%s\n", line ? line : ".");
2769 	return line ? 0 : 1;
2770 }
2771 
2772 static void
2773 smtp_tx_eom(struct smtp_tx *tx)
2774 {
2775 	smtp_filter_phase(FILTER_COMMIT, tx->session, NULL);
2776 }
2777 
2778 static int
2779 smtp_message_fd(struct smtp_tx *tx, int fd)
2780 {
2781 	struct smtp_session *s;
2782 
2783 	s = tx->session;
2784 
2785 	log_debug("smtp: %p: message fd %d", s, fd);
2786 
2787 	if ((tx->ofile = fdopen(fd, "w")) == NULL) {
2788 		close(fd);
2789 		smtp_reply(s, "421 %s Temporary Error",
2790 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
2791 		smtp_enter_state(s, STATE_QUIT);
2792 		return 0;
2793 	}
2794 	return 1;
2795 }
2796 
2797 static void
2798 filter_session_io(struct io *io, int evt, void *arg)
2799 {
2800 	struct smtp_tx*tx = arg;
2801 	char*line = NULL;
2802 	ssize_t len;
2803 
2804 	log_trace(TRACE_IO, "filter session io (smtp): %p: %s %s", tx, io_strevent(evt),
2805 	    io_strio(io));
2806 
2807 	switch (evt) {
2808 	case IO_DATAIN:
2809 	nextline:
2810 		line = io_getline(tx->filter, &len);
2811 		/* No complete line received */
2812 		if (line == NULL)
2813 			return;
2814 
2815 		if (smtp_tx_dataline(tx, line)) {
2816 			smtp_tx_eom(tx);
2817 			return;
2818 		}
2819 
2820 		goto nextline;
2821 	}
2822 }
2823 
2824 static void
2825 smtp_filter_fd(struct smtp_tx *tx, int fd)
2826 {
2827 	struct smtp_session *s;
2828 
2829 	s = tx->session;
2830 
2831 	log_debug("smtp: %p: filter fd %d", s, fd);
2832 
2833 	tx->filter = io_new();
2834 	io_set_fd(tx->filter, fd);
2835 	io_set_callback(tx->filter, filter_session_io, tx);
2836 }
2837 
2838 static void
2839 smtp_message_begin(struct smtp_tx *tx)
2840 {
2841 	struct smtp_session *s;
2842 	X509 *x;
2843 	int	(*m_printf)(struct smtp_tx *, const char *, ...);
2844 
2845 	m_printf = smtp_message_printf;
2846 	if (tx->filter)
2847 		m_printf = smtp_filter_printf;
2848 
2849 	s = tx->session;
2850 
2851 	log_debug("smtp: %p: message begin", s);
2852 
2853 	smtp_reply(s, "354 Enter mail, end with \".\""
2854 	    " on a line by itself");
2855 
2856 	if (s->junk || (s->tx && s->tx->junk))
2857 		m_printf(tx, "X-Spam: Yes\n");
2858 
2859 	m_printf(tx, "Received: ");
2860 	if (!(s->listener->flags & F_MASK_SOURCE)) {
2861 		m_printf(tx, "from %s (%s %s%s%s)",
2862 		    s->helo,
2863 		    s->rdns,
2864 		    s->ss.ss_family == AF_INET6 ? "" : "[",
2865 		    ss_to_text(&s->ss),
2866 		    s->ss.ss_family == AF_INET6 ? "" : "]");
2867 	}
2868 	m_printf(tx, "\n\tby %s (%s) with %sSMTP%s%s id %08x",
2869 	    s->smtpname,
2870 	    SMTPD_NAME,
2871 	    s->flags & SF_EHLO ? "E" : "",
2872 	    s->flags & SF_SECURE ? "S" : "",
2873 	    s->flags & SF_AUTHENTICATED ? "A" : "",
2874 	    tx->msgid);
2875 
2876 	if (s->flags & SF_SECURE) {
2877 		x = SSL_get_peer_certificate(io_tls(s->io));
2878 		m_printf(tx, " (%s:%s:%d:%s)",
2879 		    SSL_get_version(io_tls(s->io)),
2880 		    SSL_get_cipher_name(io_tls(s->io)),
2881 		    SSL_get_cipher_bits(io_tls(s->io), NULL),
2882 		    (s->flags & SF_VERIFIED) ? "YES" : (x ? "FAIL" : "NO"));
2883 		X509_free(x);
2884 
2885 		if (s->listener->flags & F_RECEIVEDAUTH) {
2886 			m_printf(tx, " auth=%s",
2887 			    s->username[0] ? "yes" : "no");
2888 			if (s->username[0])
2889 				m_printf(tx, " user=%s", s->username);
2890 		}
2891 	}
2892 
2893 	if (tx->rcptcount == 1) {
2894 		m_printf(tx, "\n\tfor <%s@%s>",
2895 		    tx->evp.rcpt.user,
2896 		    tx->evp.rcpt.domain);
2897 	}
2898 
2899 	m_printf(tx, ";\n\t%s\n", time_to_text(time(&tx->time)));
2900 
2901 	smtp_enter_state(s, STATE_BODY);
2902 }
2903 
2904 static void
2905 smtp_message_end(struct smtp_tx *tx)
2906 {
2907 	struct smtp_session *s;
2908 
2909 	s = tx->session;
2910 
2911 	log_debug("debug: %p: end of message, error=%d", s, tx->error);
2912 
2913 	fclose(tx->ofile);
2914 	tx->ofile = NULL;
2915 
2916 	switch(tx->error) {
2917 	case TX_OK:
2918 		smtp_tx_commit(tx);
2919 		return;
2920 
2921 	case TX_ERROR_SIZE:
2922 		smtp_reply(s, "554 %s %s: Transaction failed, message too big",
2923 		    esc_code(ESC_STATUS_PERMFAIL, ESC_MESSAGE_TOO_BIG_FOR_SYSTEM),
2924 		    esc_description(ESC_MESSAGE_TOO_BIG_FOR_SYSTEM));
2925 		break;
2926 
2927 	case TX_ERROR_LOOP:
2928 		smtp_reply(s, "500 %s %s: Loop detected",
2929 		   esc_code(ESC_STATUS_PERMFAIL, ESC_ROUTING_LOOP_DETECTED),
2930 		   esc_description(ESC_ROUTING_LOOP_DETECTED));
2931 		break;
2932 
2933 	case TX_ERROR_MALFORMED:
2934 		smtp_reply(s, "550 %s %s: Message is not RFC 2822 compliant",
2935 		    esc_code(ESC_STATUS_PERMFAIL, ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED),
2936 		    esc_description(ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED));
2937 		break;
2938 
2939 	case TX_ERROR_IO:
2940 	case TX_ERROR_RESOURCES:
2941 		smtp_reply(s, "421 %s Temporary Error",
2942 		    esc_code(ESC_STATUS_TEMPFAIL, ESC_OTHER_MAIL_SYSTEM_STATUS));
2943 		break;
2944 
2945 	default:
2946 		/* fatal? */
2947 		smtp_reply(s, "421 Internal server error");
2948 	}
2949 
2950 	smtp_tx_rollback(tx);
2951 	smtp_tx_free(tx);
2952 	smtp_enter_state(s, STATE_HELO);
2953 }
2954 
2955 static int
2956 smtp_filter_printf(struct smtp_tx *tx, const char *fmt, ...)
2957 {
2958 	va_list	ap;
2959 	int	len;
2960 
2961 	if (tx->error)
2962 		return -1;
2963 
2964 	va_start(ap, fmt);
2965 	len = io_vprintf(tx->filter, fmt, ap);
2966 	va_end(ap);
2967 
2968 	if (len < 0) {
2969 		log_warn("smtp-in: session %016"PRIx64": vfprintf", tx->session->id);
2970 		tx->error = TX_ERROR_IO;
2971 	}
2972 	else
2973 		tx->odatalen += len;
2974 
2975 	return len;
2976 }
2977 
2978 static int
2979 smtp_message_printf(struct smtp_tx *tx, const char *fmt, ...)
2980 {
2981 	va_list	ap;
2982 	int	len;
2983 
2984 	if (tx->error)
2985 		return -1;
2986 
2987 	va_start(ap, fmt);
2988 	len = vfprintf(tx->ofile, fmt, ap);
2989 	va_end(ap);
2990 
2991 	if (len == -1) {
2992 		log_warn("smtp-in: session %016"PRIx64": vfprintf", tx->session->id);
2993 		tx->error = TX_ERROR_IO;
2994 	}
2995 	else
2996 		tx->odatalen += len;
2997 
2998 	return len;
2999 }
3000 
3001 #define CASE(x) case x : return #x
3002 
3003 const char *
3004 smtp_strstate(int state)
3005 {
3006 	static char	buf[32];
3007 
3008 	switch (state) {
3009 	CASE(STATE_NEW);
3010 	CASE(STATE_CONNECTED);
3011 	CASE(STATE_TLS);
3012 	CASE(STATE_HELO);
3013 	CASE(STATE_AUTH_INIT);
3014 	CASE(STATE_AUTH_USERNAME);
3015 	CASE(STATE_AUTH_PASSWORD);
3016 	CASE(STATE_AUTH_FINALIZE);
3017 	CASE(STATE_BODY);
3018 	CASE(STATE_QUIT);
3019 	default:
3020 		(void)snprintf(buf, sizeof(buf), "STATE_??? (%d)", state);
3021 		return (buf);
3022 	}
3023 }
3024 
3025 
3026 static void
3027 smtp_report_link_connect(struct smtp_session *s, const char *rdns, int fcrdns,
3028     const struct sockaddr_storage *ss_src,
3029     const struct sockaddr_storage *ss_dest)
3030 {
3031 	if (! SESSION_FILTERED(s))
3032 		return;
3033 
3034 	report_smtp_link_connect("smtp-in", s->id, rdns, fcrdns, ss_src, ss_dest);
3035 }
3036 
3037 static void
3038 smtp_report_link_greeting(struct smtp_session *s,
3039     const char *domain)
3040 {
3041 	if (! SESSION_FILTERED(s))
3042 		return;
3043 
3044 	report_smtp_link_greeting("smtp-in", s->id, domain);
3045 }
3046 
3047 static void
3048 smtp_report_link_identify(struct smtp_session *s, const char *method, const char *identity)
3049 {
3050 	if (! SESSION_FILTERED(s))
3051 		return;
3052 
3053 	report_smtp_link_identify("smtp-in", s->id, method, identity);
3054 }
3055 
3056 static void
3057 smtp_report_link_tls(struct smtp_session *s, const char *ssl)
3058 {
3059 	if (! SESSION_FILTERED(s))
3060 		return;
3061 
3062 	report_smtp_link_tls("smtp-in", s->id, ssl);
3063 }
3064 
3065 static void
3066 smtp_report_link_disconnect(struct smtp_session *s)
3067 {
3068 	if (! SESSION_FILTERED(s))
3069 		return;
3070 
3071 	report_smtp_link_disconnect("smtp-in", s->id);
3072 }
3073 
3074 static void
3075 smtp_report_link_auth(struct smtp_session *s, const char *user, const char *result)
3076 {
3077 	if (! SESSION_FILTERED(s))
3078 		return;
3079 
3080 	report_smtp_link_auth("smtp-in", s->id, user, result);
3081 }
3082 
3083 static void
3084 smtp_report_tx_reset(struct smtp_session *s, uint32_t msgid)
3085 {
3086 	if (! SESSION_FILTERED(s))
3087 		return;
3088 
3089 	report_smtp_tx_reset("smtp-in", s->id, msgid);
3090 }
3091 
3092 static void
3093 smtp_report_tx_begin(struct smtp_session *s, uint32_t msgid)
3094 {
3095 	if (! SESSION_FILTERED(s))
3096 		return;
3097 
3098 	report_smtp_tx_begin("smtp-in", s->id, msgid);
3099 }
3100 
3101 static void
3102 smtp_report_tx_mail(struct smtp_session *s, uint32_t msgid, const char *address, int ok)
3103 {
3104 	char	mailaddr[SMTPD_MAXMAILADDRSIZE];
3105 	char    *p;
3106 
3107 	if (! SESSION_FILTERED(s))
3108 		return;
3109 
3110 	if ((p = strchr(address, '<')) == NULL)
3111 		return;
3112 	(void)strlcpy(mailaddr, p + 1, sizeof mailaddr);
3113 	if ((p = strchr(mailaddr, '>')) == NULL)
3114 		return;
3115 	*p = '\0';
3116 
3117 	report_smtp_tx_mail("smtp-in", s->id, msgid, mailaddr, ok);
3118 }
3119 
3120 static void
3121 smtp_report_tx_rcpt(struct smtp_session *s, uint32_t msgid, const char *address, int ok)
3122 {
3123 	char	mailaddr[SMTPD_MAXMAILADDRSIZE];
3124 	char    *p;
3125 
3126 	if (! SESSION_FILTERED(s))
3127 		return;
3128 
3129 	if ((p = strchr(address, '<')) == NULL)
3130 		return;
3131 	(void)strlcpy(mailaddr, p + 1, sizeof mailaddr);
3132 	if ((p = strchr(mailaddr, '>')) == NULL)
3133 		return;
3134 	*p = '\0';
3135 
3136 	report_smtp_tx_rcpt("smtp-in", s->id, msgid, mailaddr, ok);
3137 }
3138 
3139 static void
3140 smtp_report_tx_envelope(struct smtp_session *s, uint32_t msgid, uint64_t evpid)
3141 {
3142 	if (! SESSION_FILTERED(s))
3143 		return;
3144 
3145 	report_smtp_tx_envelope("smtp-in", s->id, msgid, evpid);
3146 }
3147 
3148 static void
3149 smtp_report_tx_data(struct smtp_session *s, uint32_t msgid, int ok)
3150 {
3151 	if (! SESSION_FILTERED(s))
3152 		return;
3153 
3154 	report_smtp_tx_data("smtp-in", s->id, msgid, ok);
3155 }
3156 
3157 static void
3158 smtp_report_tx_commit(struct smtp_session *s, uint32_t msgid, size_t msgsz)
3159 {
3160 	if (! SESSION_FILTERED(s))
3161 		return;
3162 
3163 	report_smtp_tx_commit("smtp-in", s->id, msgid, msgsz);
3164 }
3165 
3166 static void
3167 smtp_report_tx_rollback(struct smtp_session *s, uint32_t msgid)
3168 {
3169 	if (! SESSION_FILTERED(s))
3170 		return;
3171 
3172 	report_smtp_tx_rollback("smtp-in", s->id, msgid);
3173 }
3174 
3175 static void
3176 smtp_report_protocol_client(struct smtp_session *s, const char *command)
3177 {
3178 	if (! SESSION_FILTERED(s))
3179 		return;
3180 
3181 	report_smtp_protocol_client("smtp-in", s->id, command);
3182 }
3183 
3184 static void
3185 smtp_report_protocol_server(struct smtp_session *s, const char *response)
3186 {
3187 	if (! SESSION_FILTERED(s))
3188 		return;
3189 
3190 	report_smtp_protocol_server("smtp-in", s->id, response);
3191 }
3192 
3193 static void
3194 smtp_report_filter_response(struct smtp_session *s, int phase, int response, const char *param)
3195 {
3196 	if (! SESSION_FILTERED(s))
3197 		return;
3198 
3199 	report_smtp_filter_response("smtp-in", s->id, phase, response, param);
3200 }
3201 
3202 static void
3203 smtp_report_timeout(struct smtp_session *s)
3204 {
3205 	if (! SESSION_FILTERED(s))
3206 		return;
3207 
3208 	report_smtp_timeout("smtp-in", s->id);
3209 }
3210