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