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