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