xref: /openbsd-src/usr.sbin/smtpd/smtp_session.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: smtp_session.c,v 1.147 2011/09/12 20:47:15 gilles Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  * Copyright (c) 2008-2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 #include <sys/tree.h>
24 #include <sys/param.h>
25 #include <sys/socket.h>
26 
27 #include <netinet/in.h>
28 
29 #include <ctype.h>
30 #include <event.h>
31 #include <imsg.h>
32 #include <resolv.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 
37 #include <openssl/ssl.h>
38 
39 #include "smtpd.h"
40 #include "log.h"
41 
42 static int session_rfc5321_helo_handler(struct session *, char *);
43 static int session_rfc5321_ehlo_handler(struct session *, char *);
44 static int session_rfc5321_rset_handler(struct session *, char *);
45 static int session_rfc5321_noop_handler(struct session *, char *);
46 static int session_rfc5321_data_handler(struct session *, char *);
47 static int session_rfc5321_mail_handler(struct session *, char *);
48 static int session_rfc5321_rcpt_handler(struct session *, char *);
49 static int session_rfc5321_vrfy_handler(struct session *, char *);
50 static int session_rfc5321_expn_handler(struct session *, char *);
51 static int session_rfc5321_turn_handler(struct session *, char *);
52 static int session_rfc5321_help_handler(struct session *, char *);
53 static int session_rfc5321_quit_handler(struct session *, char *);
54 
55 static int session_rfc1652_mail_handler(struct session *, char *);
56 
57 static int session_rfc3207_stls_handler(struct session *, char *);
58 
59 static int session_rfc4954_auth_handler(struct session *, char *);
60 static void session_rfc4954_auth_plain(struct session *, char *);
61 static void session_rfc4954_auth_login(struct session *, char *);
62 
63 static void session_read(struct bufferevent *, void *);
64 static void session_read_data(struct session *, char *);
65 static void session_write(struct bufferevent *, void *);
66 static void session_error(struct bufferevent *, short event, void *);
67 static void session_command(struct session *, char *);
68 static char *session_readline(struct session *);
69 static void session_respond_delayed(int, short, void *);
70 static int session_set_mailaddr(struct mailaddr *, char *);
71 static void session_imsg(struct session *, enum smtp_proc_type,
72     enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t);
73 
74 struct session_cmd {
75 	char	 *name;
76 	int		(*func)(struct session *, char *);
77 };
78 
79 struct session_cmd rfc5321_cmdtab[] = {
80 	{ "helo",	session_rfc5321_helo_handler },
81 	{ "ehlo",	session_rfc5321_ehlo_handler },
82 	{ "rset",	session_rfc5321_rset_handler },
83 	{ "noop",	session_rfc5321_noop_handler },
84 	{ "data",	session_rfc5321_data_handler },
85 	{ "mail from",	session_rfc5321_mail_handler },
86 	{ "rcpt to",	session_rfc5321_rcpt_handler },
87 	{ "vrfy",	session_rfc5321_vrfy_handler },
88 	{ "expn",	session_rfc5321_expn_handler },
89 	{ "turn",	session_rfc5321_turn_handler },
90 	{ "help",	session_rfc5321_help_handler },
91 	{ "quit",	session_rfc5321_quit_handler }
92 };
93 
94 struct session_cmd rfc1652_cmdtab[] = {
95 	{ "mail from",	session_rfc1652_mail_handler },
96 };
97 
98 struct session_cmd rfc3207_cmdtab[] = {
99 	{ "starttls",	session_rfc3207_stls_handler }
100 };
101 
102 struct session_cmd rfc4954_cmdtab[] = {
103 	{ "auth",	session_rfc4954_auth_handler }
104 };
105 
106 static int
107 session_rfc3207_stls_handler(struct session *s, char *args)
108 {
109 	if (! ADVERTISE_TLS(s))
110 		return 0;
111 
112 	if (s->s_state == S_GREETED) {
113 		session_respond(s, "503 Polite people say HELO first");
114 		return 1;
115 	}
116 
117 	if (s->s_state != S_HELO) {
118 		session_respond(s, "503 TLS not allowed at this stage");
119 		return 1;
120 	}
121 
122 	if (args != NULL) {
123 		session_respond(s, "501 No parameters allowed");
124 		return 1;
125 	}
126 
127 	s->s_state = S_TLS;
128 	session_respond(s, "220 Ready to start TLS");
129 
130 	return 1;
131 }
132 
133 static int
134 session_rfc4954_auth_handler(struct session *s, char *args)
135 {
136 	char	*method;
137 	char	*eom;
138 
139 	if (! ADVERTISE_AUTH(s)) {
140 		if (s->s_flags & F_AUTHENTICATED) {
141 			session_respond(s, "503 Already authenticated");
142 			return 1;
143 		} else
144 			return 0;
145 	}
146 
147 	if (s->s_state == S_GREETED) {
148 		session_respond(s, "503 Polite people say HELO first");
149 		return 1;
150 	}
151 
152 	if (s->s_state != S_HELO) {
153 		session_respond(s, "503 Session already in progress");
154 		return 1;
155 	}
156 
157 	if (args == NULL) {
158 		session_respond(s, "501 No parameters given");
159 		return 1;
160 	}
161 
162 	method = args;
163 	eom = strchr(args, ' ');
164 	if (eom == NULL)
165 		eom = strchr(args, '\t');
166 	if (eom != NULL)
167 		*eom++ = '\0';
168 
169 	if (strcasecmp(method, "PLAIN") == 0)
170 		session_rfc4954_auth_plain(s, eom);
171 	else if (strcasecmp(method, "LOGIN") == 0)
172 		session_rfc4954_auth_login(s, eom);
173 	else
174 		session_respond(s, "504 AUTH method '%s' unsupported", method);
175 
176 	return 1;
177 }
178 
179 static void
180 session_rfc4954_auth_plain(struct session *s, char *arg)
181 {
182 	struct auth	*a = &s->s_auth;
183 	char		 buf[1024], *user, *pass;
184 	int		 len;
185 
186 	switch (s->s_state) {
187 	case S_HELO:
188 		if (arg == NULL) {
189 			s->s_state = S_AUTH_INIT;
190 			session_respond(s, "334 ");
191 			return;
192 		}
193 		s->s_state = S_AUTH_INIT;
194 		/* FALLTHROUGH */
195 
196 	case S_AUTH_INIT:
197 		/* String is not NUL terminated, leave room. */
198 		if ((len = __b64_pton(arg, (unsigned char *)buf, sizeof(buf) - 1)) == -1)
199 			goto abort;
200 		/* buf is a byte string, NUL terminate. */
201 		buf[len] = '\0';
202 
203 		/*
204 		 * Skip "foo" in "foo\0user\0pass", if present.
205 		 */
206 		user = memchr(buf, '\0', len);
207 		if (user == NULL || user >= buf + len - 2)
208 			goto abort;
209 		user++; /* skip NUL */
210 		if (strlcpy(a->user, user, sizeof(a->user)) >= sizeof(a->user))
211 			goto abort;
212 
213 		pass = memchr(user, '\0', len - (user - buf));
214 		if (pass == NULL || pass >= buf + len - 2)
215 			goto abort;
216 		pass++; /* skip NUL */
217 		if (strlcpy(a->pass, pass, sizeof(a->pass)) >= sizeof(a->pass))
218 			goto abort;
219 
220 		s->s_state = S_AUTH_FINALIZE;
221 
222 		a->id = s->s_id;
223 		session_imsg(s, PROC_PARENT, IMSG_PARENT_AUTHENTICATE, 0, 0, -1,
224 		    a, sizeof(*a));
225 
226 		bzero(a->pass, sizeof(a->pass));
227 		return;
228 
229 	default:
230 		fatal("session_rfc4954_auth_plain: unknown state");
231 	}
232 
233 abort:
234 	session_respond(s, "501 Syntax error");
235 	s->s_state = S_HELO;
236 }
237 
238 static void
239 session_rfc4954_auth_login(struct session *s, char *arg)
240 {
241 	struct auth	*a = &s->s_auth;
242 
243 	switch (s->s_state) {
244 	case S_HELO:
245 		s->s_state = S_AUTH_USERNAME;
246 		session_respond(s, "334 VXNlcm5hbWU6");
247 		return;
248 
249 	case S_AUTH_USERNAME:
250 		bzero(a->user, sizeof(a->user));
251 		if (__b64_pton(arg, (unsigned char *)a->user, sizeof(a->user) - 1) == -1)
252 			goto abort;
253 
254 		s->s_state = S_AUTH_PASSWORD;
255 		session_respond(s, "334 UGFzc3dvcmQ6");
256 		return;
257 
258 	case S_AUTH_PASSWORD:
259 		bzero(a->pass, sizeof(a->pass));
260 		if (__b64_pton(arg, (unsigned char *)a->pass, sizeof(a->pass) - 1) == -1)
261 			goto abort;
262 
263 		s->s_state = S_AUTH_FINALIZE;
264 
265 		a->id = s->s_id;
266 		session_imsg(s, PROC_PARENT, IMSG_PARENT_AUTHENTICATE, 0, 0, -1,
267 		    a, sizeof(*a));
268 
269 		bzero(a->pass, sizeof(a->pass));
270 		return;
271 
272 	default:
273 		fatal("session_rfc4954_auth_login: unknown state");
274 	}
275 
276 abort:
277 	session_respond(s, "501 Syntax error");
278 	s->s_state = S_HELO;
279 }
280 
281 static int
282 session_rfc1652_mail_handler(struct session *s, char *args)
283 {
284 	char *body;
285 
286 	if (s->s_state == S_GREETED) {
287 		session_respond(s, "503 5.5.1 Polite people say HELO first");
288 		return 1;
289 	}
290 
291 	for (body = strrchr(args, ' '); body != NULL;
292 		body = strrchr(args, ' ')) {
293 		*body++ = '\0';
294 
295 		if (strncasecmp(body, "AUTH=", 5) == 0) {
296 			log_debug("AUTH in MAIL FROM command, skipping");
297 			continue;
298 		}
299 
300 		if (strncasecmp(body, "BODY=", 5) == 0) {
301 			log_debug("BODY in MAIL FROM command");
302 
303 			if (strncasecmp("body=7bit", body, 9) == 0) {
304 				s->s_flags &= ~F_8BITMIME;
305 				continue;
306 			}
307 
308 			else if (strncasecmp("body=8bitmime", body, 13) != 0) {
309 				session_respond(s, "503 5.5.4 Unsupported option %s", body);
310 				return 1;
311 			}
312 		}
313 	}
314 
315 	return session_rfc5321_mail_handler(s, args);
316 }
317 
318 static int
319 session_rfc5321_helo_handler(struct session *s, char *args)
320 {
321 	if (args == NULL) {
322 		session_respond(s, "501 HELO requires domain address");
323 		return 1;
324 	}
325 
326 	if (strlcpy(s->s_msg.delivery.helo, args, sizeof(s->s_msg.delivery.helo))
327 	    >= sizeof(s->s_msg.delivery.helo)) {
328 		session_respond(s, "501 Invalid domain name");
329 		return 1;
330 	}
331 
332 	s->s_msg.session_id = s->s_id;
333 	s->s_state = S_HELO;
334 	s->s_flags &= F_SECURE|F_AUTHENTICATED;
335 
336 	session_imsg(s, PROC_MFA, IMSG_MFA_HELO, 0, 0, -1, &s->s_msg,
337 	    sizeof(s->s_msg));
338 	return 1;
339 }
340 
341 static int
342 session_rfc5321_ehlo_handler(struct session *s, char *args)
343 {
344 	if (args == NULL) {
345 		session_respond(s, "501 EHLO requires domain address");
346 		return 1;
347 	}
348 
349 	if (strlcpy(s->s_msg.delivery.helo, args, sizeof(s->s_msg.delivery.helo))
350 	    >= sizeof(s->s_msg.delivery.helo)) {
351 		session_respond(s, "501 Invalid domain name");
352 		return 1;
353 	}
354 
355 	s->s_msg.session_id = s->s_id;
356 	s->s_state = S_HELO;
357 	s->s_flags &= F_SECURE|F_AUTHENTICATED;
358 	s->s_flags |= F_EHLO;
359 	s->s_flags |= F_8BITMIME;
360 
361 	session_imsg(s, PROC_MFA, IMSG_MFA_HELO, 0, 0, -1, &s->s_msg,
362 	    sizeof(s->s_msg));
363 	return 1;
364 }
365 
366 static int
367 session_rfc5321_rset_handler(struct session *s, char *args)
368 {
369 	s->s_state = S_HELO;
370 	session_respond(s, "250 2.0.0 Reset state");
371 
372 	return 1;
373 }
374 
375 static int
376 session_rfc5321_noop_handler(struct session *s, char *args)
377 {
378 	session_respond(s, "250 2.0.0 OK");
379 
380 	return 1;
381 }
382 
383 static int
384 session_rfc5321_mail_handler(struct session *s, char *args)
385 {
386 	if (s->s_state == S_GREETED) {
387 		session_respond(s, "503 5.5.1 Polite people say HELO first");
388 		return 1;
389 	}
390 
391 	if (s->s_state != S_HELO) {
392 		session_respond(s, "503 5.5.1 Sender already specified");
393 		return 1;
394 	}
395 
396 	if (! session_set_mailaddr(&s->s_msg.delivery.from, args)) {
397 		/* No need to even transmit to MFA, path is invalid */
398 		session_respond(s, "553 5.1.7 Sender address syntax error");
399 		return 1;
400 	}
401 
402 	s->rcptcount = 0;
403 	s->s_state = S_MAIL_MFA;
404 	s->s_msg.delivery.id = 0;
405 	s->s_msg.delivery.ss = s->s_ss;
406 
407 	log_debug("session_rfc5321_mail_handler: sending notification to mfa");
408 
409 	session_imsg(s, PROC_MFA, IMSG_MFA_MAIL, 0, 0, -1, &s->s_msg,
410 	    sizeof(s->s_msg));
411 	return 1;
412 }
413 
414 static int
415 session_rfc5321_rcpt_handler(struct session *s, char *args)
416 {
417 	if (s->s_state == S_GREETED) {
418 		session_respond(s, "503 5.5.1 Polite people say HELO first");
419 		return 1;
420 	}
421 
422 	if (s->s_state == S_HELO) {
423 		session_respond(s, "503 5.5.1 Need MAIL before RCPT");
424 		return 1;
425 	}
426 
427 	if (! session_set_mailaddr(&s->s_msg.delivery.rcpt_orig, args)) {
428 		/* No need to even transmit to MFA, path is invalid */
429 		session_respond(s, "553 5.1.3 Recipient address syntax error");
430 		return 1;
431 	}
432 
433 	s->s_state = S_RCPT_MFA;
434 	session_imsg(s, PROC_MFA, IMSG_MFA_RCPT, 0, 0, -1, &s->s_msg,
435 	    sizeof(s->s_msg));
436 	return 1;
437 }
438 
439 static int
440 session_rfc5321_quit_handler(struct session *s, char *args)
441 {
442 	s->s_flags |= F_QUIT;
443 	session_respond(s, "221 2.0.0 %s Closing connection", env->sc_hostname);
444 	return 1;
445 }
446 
447 static int
448 session_rfc5321_data_handler(struct session *s, char *args)
449 {
450 	if (s->s_state == S_GREETED) {
451 		session_respond(s, "503 5.5.1 Polite people say HELO first");
452 		return 1;
453 	}
454 
455 	if (s->s_state == S_HELO) {
456 		session_respond(s, "503 5.5.1 Need MAIL before DATA");
457 		return 1;
458 	}
459 
460 	if (s->s_state == S_MAIL) {
461 		session_respond(s, "503 5.5.1 Need RCPT before DATA");
462 		return 1;
463 	}
464 
465 	s->s_state = S_DATA_QUEUE;
466 
467 	session_imsg(s, PROC_QUEUE, IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1,
468 	    &s->s_msg, sizeof(s->s_msg));
469 
470 	return 1;
471 }
472 
473 static int
474 session_rfc5321_vrfy_handler(struct session *s, char *args)
475 {
476 	session_respond(s, "252 5.5.1 Cannot VRFY; try RCPT to attempt delivery");
477 
478 	return 1;
479 }
480 
481 static int
482 session_rfc5321_expn_handler(struct session *s, char *args)
483 {
484 	session_respond(s, "502 5.5.2 Sorry, we do not allow this operation");
485 
486 	return 1;
487 }
488 
489 static int
490 session_rfc5321_turn_handler(struct session *s, char *args)
491 {
492 	session_respond(s, "502 5.5.2 Sorry, we do not allow this operation");
493 
494 	return 1;
495 }
496 
497 static int
498 session_rfc5321_help_handler(struct session *s, char *args)
499 {
500 	session_respond(s, "214- This is OpenSMTPD");
501 	session_respond(s, "214- To report bugs in the implementation, please "
502 	    "contact bugs@openbsd.org");
503 	session_respond(s, "214- with full details");
504 	session_respond(s, "214 End of HELP info");
505 
506 	return 1;
507 }
508 
509 static void
510 session_command(struct session *s, char *cmd)
511 {
512 	char		*ep, *args;
513 	unsigned int	 i;
514 
515 	/*
516 	 * unlike other commands, "mail from" and "rcpt to" contain a
517 	 * space in the command name.
518 	 */
519 	if (strncasecmp("mail from:", cmd, 10) == 0 ||
520 	    strncasecmp("rcpt to:", cmd, 8) == 0)
521 		ep = strchr(cmd, ':');
522 	else
523 		ep = strchr(cmd, ' ');
524 
525 	if (ep != NULL) {
526 		*ep = '\0';
527 		args = ++ep;
528 		while (isspace((int)*args))
529 			args++;
530 	} else
531 		args = NULL;
532 
533 	log_debug("command: %s\targs: %s", cmd, args);
534 
535 	if (!(s->s_flags & F_EHLO))
536 		goto rfc5321;
537 
538 	/* RFC 1652 - 8BITMIME */
539 	for (i = 0; i < nitems(rfc1652_cmdtab); ++i)
540 		if (strcasecmp(rfc1652_cmdtab[i].name, cmd) == 0)
541 			break;
542 	if (i < nitems(rfc1652_cmdtab)) {
543 		if (rfc1652_cmdtab[i].func(s, args))
544 			return;
545 	}
546 
547 	/* RFC 3207 - STARTTLS */
548 	for (i = 0; i < nitems(rfc3207_cmdtab); ++i)
549 		if (strcasecmp(rfc3207_cmdtab[i].name, cmd) == 0)
550 			break;
551 	if (i < nitems(rfc3207_cmdtab)) {
552 		if (rfc3207_cmdtab[i].func(s, args))
553 			return;
554 	}
555 
556 	/* RFC 4954 - AUTH */
557 	for (i = 0; i < nitems(rfc4954_cmdtab); ++i)
558 		if (strcasecmp(rfc4954_cmdtab[i].name, cmd) == 0)
559 			break;
560 	if (i < nitems(rfc4954_cmdtab)) {
561 		if (rfc4954_cmdtab[i].func(s, args))
562 			return;
563 	}
564 
565 rfc5321:
566 	/* RFC 5321 - SMTP */
567 	for (i = 0; i < nitems(rfc5321_cmdtab); ++i)
568 		if (strcasecmp(rfc5321_cmdtab[i].name, cmd) == 0)
569 			break;
570 	if (i < nitems(rfc5321_cmdtab)) {
571 		if (rfc5321_cmdtab[i].func(s, args))
572 			return;
573 	}
574 
575 	session_respond(s, "500 Command unrecognized");
576 }
577 
578 void
579 session_pickup(struct session *s, struct submit_status *ss)
580 {
581 	if (s == NULL)
582 		fatal("session_pickup: desynchronized");
583 
584 	if ((ss != NULL && ss->code == 421) ||
585 	    (s->s_msg.delivery.status & DS_TEMPFAILURE)) {
586 		session_respond(s, "421 Service temporarily unavailable");
587 		env->stats->smtp.tempfail++;
588 		s->s_flags |= F_QUIT;
589 		return;
590 	}
591 
592 	switch (s->s_state) {
593 	case S_INIT:
594 		s->s_state = S_GREETED;
595 		log_debug("session_pickup: greeting client");
596 		session_respond(s, SMTPD_BANNER, env->sc_hostname);
597 		break;
598 
599 	case S_TLS:
600 		if (s->s_flags & F_WRITEONLY)
601 			fatalx("session_pickup: corrupt session");
602 		bufferevent_enable(s->s_bev, EV_READ);
603 		s->s_state = S_GREETED;
604 		break;
605 
606 	case S_AUTH_FINALIZE:
607 		if (s->s_flags & F_AUTHENTICATED)
608 			session_respond(s, "235 Authentication succeeded");
609 		else
610 			session_respond(s, "535 Authentication failed");
611 		s->s_state = S_HELO;
612 		break;
613 
614 	case S_HELO:
615 		if (ss == NULL)
616 			fatalx("bad ss at S_HELO");
617 		if (ss->code != 250) {
618 			s->s_state = S_GREETED;
619 			session_respond(s, "%d Helo rejected", ss->code);
620 			return;
621 		}
622 
623 		session_respond(s, "250%c%s Hello %s [%s], pleased to meet you",
624 		    (s->s_flags & F_EHLO) ? '-' : ' ',
625 		    env->sc_hostname, s->s_msg.delivery.helo, ss_to_text(&s->s_ss));
626 
627 		if (s->s_flags & F_EHLO) {
628 			/* unconditionnal extensions go first */
629 			session_respond(s, "250-8BITMIME");
630 			session_respond(s, "250-ENHANCEDSTATUSCODES");
631 
632 			/* XXX - we also want to support reading SIZE from MAIL parameters */
633 			session_respond(s, "250-SIZE %zu", env->sc_maxsize);
634 
635 			if (ADVERTISE_TLS(s))
636 				session_respond(s, "250-STARTTLS");
637 
638 			if (ADVERTISE_AUTH(s))
639 				session_respond(s, "250-AUTH PLAIN LOGIN");
640 			session_respond(s, "250 HELP");
641 		}
642 		break;
643 
644 	case S_MAIL_MFA:
645 		if (ss == NULL)
646 			fatalx("bad ss at S_MAIL_MFA");
647 		if (ss->code != 250) {
648 			s->s_state = S_HELO;
649 			session_respond(s, "%d Sender rejected", ss->code);
650 			return;
651 		}
652 
653 		s->s_state = S_MAIL_QUEUE;
654 		s->s_msg.delivery.from = ss->u.maddr;
655 
656 		session_imsg(s, PROC_QUEUE, IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1,
657 		    &s->s_msg, sizeof(s->s_msg));
658 		break;
659 
660 	case S_MAIL_QUEUE:
661 		if (ss == NULL)
662 			fatalx("bad ss at S_MAIL_QUEUE");
663 		s->s_state = S_MAIL;
664 		session_respond(s, "%d 2.1.0 Sender ok", ss->code);
665 		break;
666 
667 	case S_RCPT_MFA:
668 		if (ss == NULL)
669 			fatalx("bad ss at S_RCPT_MFA");
670 		/* recipient was not accepted */
671 		if (ss->code != 250) {
672 			/* We do not have a valid recipient, downgrade state */
673 			if (s->rcptcount == 0)
674 				s->s_state = S_MAIL;
675 			else
676 				s->s_state = S_RCPT;
677 			session_respond(s, "%d 5.0.0 Recipient rejected: %s@%s", ss->code,
678 			    s->s_msg.delivery.rcpt_orig.user,
679 			    s->s_msg.delivery.rcpt_orig.domain);
680 			return;
681 		}
682 
683 		s->s_state = S_RCPT;
684 		s->rcptcount++;
685 		s->s_msg.delivery.rcpt = ss->u.maddr;
686 
687 		session_respond(s, "%d 2.0.0 Recipient ok", ss->code);
688 		break;
689 
690 	case S_DATA_QUEUE:
691 		s->s_state = S_DATACONTENT;
692 		session_respond(s, "354 Enter mail, end with \".\" on a line by"
693 		    " itself");
694 
695 		fprintf(s->datafp, "Received: from %s (%s [%s])\n",
696 		    s->s_msg.delivery.helo, s->s_hostname, ss_to_text(&s->s_ss));
697 		fprintf(s->datafp, "\tby %s (OpenSMTPD) with %sSMTP id %08x",
698 		    env->sc_hostname, s->s_flags & F_EHLO ? "E" : "",
699 		    (u_int32_t)(s->s_msg.delivery.id >> 32));
700 
701 		if (s->s_flags & F_SECURE) {
702 			fprintf(s->datafp, "\n\t(version=%s cipher=%s bits=%d)",
703 			    SSL_get_cipher_version(s->s_ssl),
704 			    SSL_get_cipher_name(s->s_ssl),
705 			    SSL_get_cipher_bits(s->s_ssl, NULL));
706 		}
707 		if (s->rcptcount == 1)
708 			fprintf(s->datafp, "\n\tfor <%s@%s>; ",
709 			    s->s_msg.delivery.rcpt_orig.user,
710 			    s->s_msg.delivery.rcpt_orig.domain);
711 		else
712 			fprintf(s->datafp, ";\n\t");
713 
714 		fprintf(s->datafp, "%s\n", time_to_text(time(NULL)));
715 		break;
716 
717 	case S_DATACONTENT:
718 		if (ss->code != 250)
719 			s->s_msg.delivery.status |= DS_PERMFAILURE;
720 		session_read_data(s, ss->u.dataline);
721 		break;
722 
723 	case S_DONE:
724 		session_respond(s, "250 2.0.0 %08x Message accepted for delivery",
725 		    (u_int32_t)(s->s_msg.delivery.id >> 32));
726 		log_info("%08x: from=<%s%s%s>, size=%ld, nrcpts=%zd, proto=%s, "
727 		    "relay=%s [%s]",
728 		    (u_int32_t)(s->s_msg.delivery.id >> 32),
729 		    s->s_msg.delivery.from.user,
730 		    s->s_msg.delivery.from.user[0] == '\0' ? "" : "@",
731 		    s->s_msg.delivery.from.domain,
732 		    s->s_datalen,
733 		    s->rcptcount,
734 		    s->s_flags & F_EHLO ? "ESMTP" : "SMTP",
735 		    s->s_hostname,
736 		    ss_to_text(&s->s_ss));
737 
738 		s->s_state = S_HELO;
739 		s->s_msg.delivery.id = 0;
740 		bzero(&s->s_nresp, sizeof(s->s_nresp));
741 		break;
742 
743 	default:
744 		fatal("session_pickup: unknown state");
745 	}
746 }
747 
748 void
749 session_init(struct listener *l, struct session *s)
750 {
751 	s->s_state = S_INIT;
752 
753 	if (l->flags & F_SMTPS) {
754 		ssl_session_init(s);
755 		return;
756 	}
757 
758 	session_bufferevent_new(s);
759 	session_pickup(s, NULL);
760 }
761 
762 void
763 session_bufferevent_new(struct session *s)
764 {
765 	if (s->s_bev != NULL)
766 		fatalx("session_bufferevent_new: attempt to override existing "
767 		    "bufferevent");
768 
769 	if (s->s_flags & F_WRITEONLY)
770 		fatalx("session_bufferevent_new: corrupt session");
771 
772 	s->s_bev = bufferevent_new(s->s_fd, session_read, session_write,
773 	    session_error, s);
774 	if (s->s_bev == NULL)
775 		fatal("session_bufferevent_new");
776 
777 	bufferevent_settimeout(s->s_bev, SMTPD_SESSION_TIMEOUT,
778 	    SMTPD_SESSION_TIMEOUT);
779 }
780 
781 static void
782 session_read(struct bufferevent *bev, void *p)
783 {
784 	struct session	*s = p;
785 	char		*line;
786 
787 	for (;;) {
788 		line = session_readline(s);
789 		if (line == NULL)
790 			return;
791 
792 		switch (s->s_state) {
793 		case S_AUTH_INIT:
794 			if (s->s_msg.delivery.status & DS_TEMPFAILURE)
795 				goto tempfail;
796 			session_rfc4954_auth_plain(s, line);
797 			break;
798 
799 		case S_AUTH_USERNAME:
800 		case S_AUTH_PASSWORD:
801 			if (s->s_msg.delivery.status & DS_TEMPFAILURE)
802 				goto tempfail;
803 			session_rfc4954_auth_login(s, line);
804 			break;
805 
806 		case S_GREETED:
807 		case S_HELO:
808 		case S_MAIL:
809 		case S_RCPT:
810 			if (s->s_msg.delivery.status & DS_TEMPFAILURE)
811 				goto tempfail;
812 			session_command(s, line);
813 			break;
814 
815 		case S_DATACONTENT: {
816 			struct submit_status ss;
817 
818 			bzero(&ss, sizeof(ss));
819 			ss.id = s->s_id;
820 			if (strlcpy(ss.u.dataline, line,
821 				sizeof(ss.u.dataline)) >= sizeof(ss.u.dataline))
822 				fatal("session_read: data truncation");
823 			free(line);
824 
825 			if (env->filtermask & FILTER_DATALINE)
826 				session_imsg(s, PROC_MFA, IMSG_MFA_DATALINE,
827 				    0, 0, -1, &ss, sizeof(ss));
828 			else {
829 				log_debug("no filter");
830 				ss.code = 250;
831 				session_pickup(s, &ss);
832 			}
833 			return;
834 		}
835 
836 		default:
837 			fatalx("session_read: unexpected state");
838 		}
839 
840 		free(line);
841 	}
842 	return;
843 
844 tempfail:
845 	session_respond(s, "421 4.0.0 Service temporarily unavailable");
846 	env->stats->smtp.tempfail++;
847 	s->s_flags |= F_QUIT;
848 	free(line);
849 }
850 
851 static void
852 session_read_data(struct session *s, char *line)
853 {
854 	size_t datalen;
855 	size_t len;
856 	size_t i;
857 
858 	if (strcmp(line, ".") == 0) {
859 		s->s_datalen = ftell(s->datafp);
860 		if (! safe_fclose(s->datafp))
861 			s->s_msg.delivery.status |= DS_TEMPFAILURE;
862 		s->datafp = NULL;
863 
864 		if (s->s_msg.delivery.status & DS_PERMFAILURE) {
865 			session_respond(s, "554 5.0.0 Transaction failed");
866 			s->s_state = S_HELO;
867 		} else if (s->s_msg.delivery.status & DS_TEMPFAILURE) {
868 			session_respond(s, "421 4.0.0 Temporary failure");
869 			s->s_flags |= F_QUIT;
870 			env->stats->smtp.tempfail++;
871 		} else {
872 			session_imsg(s, PROC_QUEUE, IMSG_QUEUE_COMMIT_MESSAGE,
873 			    0, 0, -1, &s->s_msg, sizeof(s->s_msg));
874 			s->s_state = S_DONE;
875 		}
876 		goto end;
877 	}
878 
879 	/* Don't waste resources on message if it's going to bin anyway. */
880 	if (s->s_msg.delivery.status & (DS_PERMFAILURE|DS_TEMPFAILURE))
881 		goto end;
882 
883 	/* "If the first character is a period and there are other characters
884 	 *  on the line, the first character is deleted." [4.5.2]
885 	 */
886 	if (*line == '.')
887 		line++;
888 
889 	len = strlen(line);
890 
891 	/* If size of data overflows a size_t or exceeds max size allowed
892 	 * for a message, set permanent failure.
893 	 */
894 	datalen = ftell(s->datafp);
895 	if (SIZE_MAX - datalen < len + 1 ||
896 	    datalen + len + 1 > env->sc_maxsize) {
897 		s->s_msg.delivery.status |= DS_PERMFAILURE;
898 		goto end;
899 	}
900 
901 	if (fprintf(s->datafp, "%s\n", line) != (int)len + 1) {
902 		s->s_msg.delivery.status |= DS_TEMPFAILURE;
903 		goto end;
904 	}
905 
906 	if (! (s->s_flags & F_8BITMIME)) {
907 		for (i = 0; i < len; ++i)
908 			if (line[i] & 0x80)
909 				line[i] = line[i] & 0x7f;
910 	}
911 
912 end:
913 	bufferevent_enable(s->s_bev, EV_READ);
914 	session_read(s->s_bev, s);
915 }
916 
917 static void
918 session_write(struct bufferevent *bev, void *p)
919 {
920 	struct session	*s = p;
921 
922 	if (s->s_flags & F_WRITEONLY) {
923 		/*
924 		 * Finished writing to a session that is waiting for an IMSG
925 		 * response, therefore can't destroy session nor re-enable
926 		 * reading from it.
927 		 *
928 		 * If session_respond caller used F_QUIT to request session
929 		 * destroy after final write, then session will be destroyed
930 		 * in session_lookup.
931 		 *
932 		 * Reading from session will be re-enabled in session_pickup
933 		 * using another call to session_respond.
934 		 */
935 		return;
936 	} else if (s->s_flags & F_QUIT) {
937 		/*
938 		 * session_respond caller requested the session to be dropped.
939 		 */
940 		session_destroy(s);
941 	} else if (s->s_state == S_TLS) {
942 		/*
943 		 * Start the TLS conversation.
944 		 * Destroy the bufferevent as the SSL module re-creates it.
945 		 */
946 		bufferevent_free(s->s_bev);
947 		s->s_bev = NULL;
948 		ssl_session_init(s);
949 	} else {
950 		/*
951 		 * Common case of responding to client's request.
952 		 * Re-enable reading from session so that more commands can
953 		 * be processed.
954 		 */
955 		bufferevent_enable(s->s_bev, EV_READ);
956 	}
957 }
958 
959 static void
960 session_error(struct bufferevent *bev, short event, void *p)
961 {
962 	struct session	*s = p;
963 	char		*ip = ss_to_text(&s->s_ss);
964 
965 	if (event & EVBUFFER_READ) {
966 		if (event & EVBUFFER_TIMEOUT) {
967 			log_warnx("client %s read timeout", ip);
968 			env->stats->smtp.read_timeout++;
969 		} else if (event & EVBUFFER_EOF)
970 			env->stats->smtp.read_eof++;
971 		else if (event & EVBUFFER_ERROR) {
972 			log_warn("client %s read error", ip);
973 			env->stats->smtp.read_error++;
974 		}
975 
976 		session_destroy(s);
977 		return;
978 	}
979 
980 	if (event & EVBUFFER_WRITE) {
981 		if (event & EVBUFFER_TIMEOUT) {
982 			log_warnx("client %s write timeout", ip);
983 			env->stats->smtp.write_timeout++;
984 		} else if (event & EVBUFFER_EOF)
985 			env->stats->smtp.write_eof++;
986 		else if (event & EVBUFFER_ERROR) {
987 			log_warn("client %s write error", ip);
988 			env->stats->smtp.write_error++;
989 		}
990 
991 		if (s->s_flags & F_WRITEONLY)
992 			s->s_flags |= F_QUIT;
993 		else
994 			session_destroy(s);
995 		return;
996 	}
997 
998 	fatalx("session_error: unexpected error");
999 }
1000 
1001 void
1002 session_destroy(struct session *s)
1003 {
1004 	size_t resume;
1005 
1006 	log_debug("session_destroy: killing client: %p", s);
1007 
1008 	if (s->s_flags & F_WRITEONLY)
1009 		fatalx("session_destroy: corrupt session");
1010 
1011 	if (s->datafp != NULL)
1012 		fclose(s->datafp);
1013 
1014 	if (s->s_msg.delivery.id != 0 && s->s_state != S_DONE)
1015 		imsg_compose_event(env->sc_ievs[PROC_QUEUE],
1016 		    IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &s->s_msg,
1017 		    sizeof(s->s_msg));
1018 
1019 	ssl_session_destroy(s);
1020 
1021 	if (s->s_bev != NULL)
1022 		bufferevent_free(s->s_bev);
1023 
1024 	if (s->s_fd != -1 && close(s->s_fd) == -1)
1025 		fatal("session_destroy: close");
1026 
1027 	/* resume when session count decreases to 95% */
1028 	resume = env->sc_maxconn * 95 / 100;
1029 	if (stat_decrement(STATS_SMTP_SESSION) == resume) {
1030 		log_warnx("re-enabling incoming connections");
1031 		smtp_resume();
1032 	}
1033 
1034 	SPLAY_REMOVE(sessiontree, &env->sc_sessions, s);
1035 	bzero(s, sizeof(*s));
1036 	free(s);
1037 }
1038 
1039 static char *
1040 session_readline(struct session *s)
1041 {
1042 	char	*line, *line2;
1043 	size_t	 nr;
1044 
1045 	nr = EVBUFFER_LENGTH(s->s_bev->input);
1046 	line = evbuffer_readln(s->s_bev->input, NULL, EVBUFFER_EOL_CRLF);
1047 	if (line == NULL) {
1048 		if (EVBUFFER_LENGTH(s->s_bev->input) > SMTP_LINE_MAX) {
1049 			session_respond(s, "500 5.0.0 Line too long");
1050 			env->stats->smtp.linetoolong++;
1051 			s->s_flags |= F_QUIT;
1052 		}
1053 		return NULL;
1054 	}
1055 	nr -= EVBUFFER_LENGTH(s->s_bev->input);
1056 
1057 	if (s->s_flags & F_WRITEONLY)
1058 		fatalx("session_readline: corrupt session");
1059 
1060 	if (nr > SMTP_LINE_MAX) {
1061 		session_respond(s, "500 5.0.0 Line too long");
1062 		env->stats->smtp.linetoolong++;
1063 		s->s_flags |= F_QUIT;
1064 		return NULL;
1065 	}
1066 
1067 	if ((s->s_state != S_DATACONTENT || strcmp(line, ".") == 0) &&
1068 	    (line2 = evbuffer_readln(s->s_bev->input, NULL,
1069 		EVBUFFER_EOL_CRLF)) != NULL) {
1070 		session_respond(s, "500 5.0.0 Pipelining unsupported");
1071 		env->stats->smtp.toofast++;
1072 		s->s_flags |= F_QUIT;
1073 		free(line);
1074 		free(line2);
1075 		return NULL;
1076 	}
1077 
1078 	return line;
1079 }
1080 
1081 int
1082 session_cmp(struct session *s1, struct session *s2)
1083 {
1084 	/*
1085 	 * do not return u_int64_t's
1086 	 */
1087 	if (s1->s_id < s2->s_id)
1088 		return (-1);
1089 
1090 	if (s1->s_id > s2->s_id)
1091 		return (1);
1092 
1093 	return (0);
1094 }
1095 
1096 static int
1097 session_set_mailaddr(struct mailaddr *maddr, char *line)
1098 {
1099 	size_t len;
1100 
1101 	len = strlen(line);
1102 	if (*line != '<' || line[len - 1] != '>')
1103 		return 0;
1104 	line[len - 1] = '\0';
1105 
1106 	return email_to_mailaddr(maddr, line + 1);
1107 }
1108 
1109 void
1110 session_respond(struct session *s, char *fmt, ...)
1111 {
1112 	va_list	 ap;
1113 	int	 n, delay;
1114 
1115 	n = EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev));
1116 
1117 	va_start(ap, fmt);
1118 	if (evbuffer_add_vprintf(EVBUFFER_OUTPUT(s->s_bev), fmt, ap) == -1 ||
1119 	    evbuffer_add_printf(EVBUFFER_OUTPUT(s->s_bev), "\r\n") == -1)
1120 		fatal("session_respond: evbuffer_add_vprintf failed");
1121 	va_end(ap);
1122 
1123 	bufferevent_disable(s->s_bev, EV_READ);
1124 
1125 	/*
1126 	 * Log failures.  Might be annoying in the long term, but it is a good
1127 	 * development aid for now.
1128 	 */
1129 	switch (EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev))[n]) {
1130 	case '5':
1131 	case '4':
1132 		log_info("%08x: from=<%s@%s>, relay=%s [%s], stat=LocalError (%.*s)",
1133 		    (u_int32_t)(s->s_msg.delivery.id >> 32),
1134 		    s->s_msg.delivery.from.user, s->s_msg.delivery.from.domain,
1135 		    s->s_hostname, ss_to_text(&s->s_ss),
1136 		    (int)EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev)) - n - 2,
1137 		    EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev)));
1138 		break;
1139 	}
1140 
1141 	/* Detect multi-line response. */
1142 	if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(s->s_bev)) - n < 4)
1143 		fatalx("session_respond: invalid response length");
1144 	switch (EVBUFFER_DATA(EVBUFFER_OUTPUT(s->s_bev))[n + 3]) {
1145 	case '-':
1146 		return;
1147 	case ' ':
1148 		break;
1149 	default:
1150 		fatalx("session_respond: invalid response");
1151 	}
1152 
1153 	/*
1154 	 * Deal with request flooding; avoid letting response rate keep up
1155 	 * with incoming request rate.
1156 	 */
1157 	s->s_nresp[s->s_state]++;
1158 
1159 	if (s->s_state == S_RCPT)
1160 		delay = 0;
1161 	else if ((n = s->s_nresp[s->s_state] - FAST_RESPONSES) > 0)
1162 		delay = MIN(1 << (n - 1), MAX_RESPONSE_DELAY);
1163 	else
1164 		delay = 0;
1165 
1166 	if (delay > 0) {
1167 		struct timeval tv = { delay, 0 };
1168 
1169 		env->stats->smtp.delays++;
1170 		evtimer_set(&s->s_ev, session_respond_delayed, s);
1171 		evtimer_add(&s->s_ev, &tv);
1172 	} else
1173 		bufferevent_enable(s->s_bev, EV_WRITE);
1174 }
1175 
1176 static void
1177 session_respond_delayed(int fd, short event, void *p)
1178 {
1179 	struct session	*s = p;
1180 
1181 	bufferevent_enable(s->s_bev, EV_WRITE);
1182 }
1183 
1184 /*
1185  * Send IMSG, waiting for reply safely.
1186  */
1187 static void
1188 session_imsg(struct session *s, enum smtp_proc_type proc, enum imsg_type type,
1189     u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen)
1190 {
1191 	if (s->s_flags & F_WRITEONLY)
1192 		fatalx("session_imsg: corrupt session");
1193 
1194 	/*
1195 	 * Each outgoing IMSG has a response IMSG associated that must be
1196 	 * waited for before the session can be progressed further.
1197 	 * During the wait period:
1198 	 * 1) session must not be destroyed,
1199 	 * 2) session must not be read from,
1200 	 * 3) session may be written to.
1201 	 * Session flag F_WRITEONLY is needed to enforce this policy.
1202 	 *
1203 	 * F_WRITEONLY is cleared in session_lookup.
1204 	 * Reading is re-enabled in session_pickup.
1205 	 */
1206 	s->s_flags |= F_WRITEONLY;
1207 	bufferevent_disable(s->s_bev, EV_READ);
1208 	imsg_compose_event(env->sc_ievs[proc], type, peerid, pid, fd, data,
1209 	    datalen);
1210 }
1211 
1212 SPLAY_GENERATE(sessiontree, session, s_nodes, session_cmp);
1213