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