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