xref: /openbsd-src/usr.sbin/smtpd/smtp_session.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: smtp_session.c,v 1.63 2009/03/15 19:32:10 gilles Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/tree.h>
23 #include <sys/param.h>
24 #include <sys/socket.h>
25 
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 
29 #include <ctype.h>
30 #include <errno.h>
31 #include <event.h>
32 #include <pwd.h>
33 #include <regex.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include <keynote.h>
40 
41 #include "smtpd.h"
42 
43 int		session_rfc5321_helo_handler(struct session *, char *);
44 int		session_rfc5321_ehlo_handler(struct session *, char *);
45 int		session_rfc5321_rset_handler(struct session *, char *);
46 int		session_rfc5321_noop_handler(struct session *, char *);
47 int		session_rfc5321_data_handler(struct session *, char *);
48 int		session_rfc5321_mail_handler(struct session *, char *);
49 int		session_rfc5321_rcpt_handler(struct session *, char *);
50 int		session_rfc5321_vrfy_handler(struct session *, char *);
51 int		session_rfc5321_expn_handler(struct session *, char *);
52 int		session_rfc5321_turn_handler(struct session *, char *);
53 int		session_rfc5321_help_handler(struct session *, char *);
54 int		session_rfc5321_quit_handler(struct session *, char *);
55 int		session_rfc5321_none_handler(struct session *, char *);
56 
57 int		session_rfc1652_mail_handler(struct session *, char *);
58 
59 int		session_rfc3207_stls_handler(struct session *, char *);
60 
61 int		session_rfc4954_auth_handler(struct session *, char *);
62 int		session_rfc4954_auth_plain(struct session *, char *, size_t);
63 int		session_rfc4954_auth_login(struct session *, char *, size_t);
64 void		session_auth_pickup(struct session *, char *, size_t);
65 
66 void		session_read(struct bufferevent *, void *);
67 int		session_read_data(struct session *, char *, size_t);
68 void		session_write(struct bufferevent *, void *);
69 void		session_error(struct bufferevent *, short, void *);
70 void		session_msg_submit(struct session *);
71 void		session_command(struct session *, char *, char *);
72 int		session_set_path(struct path *, char *);
73 void		session_timeout(int, short, void *);
74 void		session_cleanup(struct session *);
75 
76 extern struct s_session	s_smtp;
77 
78 struct session_timeout {
79 	enum session_state	state;
80 	time_t			timeout;
81 };
82 
83 struct session_timeout rfc5321_timeouttab[] = {
84 	{ S_INIT,		300 },
85 	{ S_GREETED,		300 },
86 	{ S_HELO,		300 },
87 	{ S_MAIL,		300 },
88 	{ S_RCPT,		300 },
89 	{ S_DATA,		120 },
90 	{ S_DATACONTENT,	180 },
91 	{ S_DONE,		600 }
92 };
93 
94 struct session_cmd {
95 	char	 *name;
96 	int		(*func)(struct session *, char *);
97 };
98 
99 struct session_cmd rfc5321_cmdtab[] = {
100 	{ "helo",	session_rfc5321_helo_handler },
101 	{ "ehlo",	session_rfc5321_ehlo_handler },
102 	{ "rset",	session_rfc5321_rset_handler },
103 	{ "noop",	session_rfc5321_noop_handler },
104 	{ "data",	session_rfc5321_data_handler },
105 	{ "mail from",	session_rfc5321_mail_handler },
106 	{ "rcpt to",	session_rfc5321_rcpt_handler },
107 	{ "vrfy",	session_rfc5321_vrfy_handler },
108 	{ "expn",	session_rfc5321_expn_handler },
109 	{ "turn",	session_rfc5321_turn_handler },
110 	{ "help",	session_rfc5321_help_handler },
111 	{ "quit",	session_rfc5321_quit_handler }
112 };
113 
114 struct session_cmd rfc1652_cmdtab[] = {
115 	{ "mail from",	session_rfc1652_mail_handler },
116 };
117 
118 struct session_cmd rfc3207_cmdtab[] = {
119 	{ "starttls",	session_rfc3207_stls_handler }
120 };
121 
122 struct session_cmd rfc4954_cmdtab[] = {
123 	{ "auth",	session_rfc4954_auth_handler }
124 };
125 
126 int
127 session_rfc3207_stls_handler(struct session *s, char *args)
128 {
129 	if (s->s_state == S_GREETED) {
130 		session_respond(s, "503 Polite people say HELO first");
131 		return 1;
132 	}
133 
134 	if (args != NULL) {
135 		session_respond(s, "501 No parameters allowed");
136 		return 1;
137 	}
138 
139 	session_respond(s, "220 Ready to start TLS");
140 
141 	s->s_state = S_TLS;
142 
143 	return 1;
144 }
145 
146 int
147 session_rfc4954_auth_handler(struct session *s, char *args)
148 {
149 	char	*method;
150 	char	*eom;
151 
152 	if (s->s_state == S_GREETED) {
153 		session_respond(s, "503 Polite people say HELO first");
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 		return session_rfc4954_auth_plain(s, eom, eom ? strlen(eom) : 0);
171 	else if (strcasecmp(method, "LOGIN") == 0)
172 		return session_rfc4954_auth_login(s, eom, eom ? strlen(eom) : 0);
173 
174 	session_respond(s, "501 Syntax error");
175 	return 1;
176 
177 }
178 
179 int
180 session_rfc4954_auth_plain(struct session *s, char *arg, size_t nr)
181 {
182 	if (arg == NULL) {
183 		session_respond(s, "334");
184 		s->s_state = S_AUTH_INIT;
185 		return 1;
186 	}
187 
188 	s->s_auth.session_id = s->s_id;
189 	if (strlcpy(s->s_auth.buffer, arg, sizeof(s->s_auth.buffer)) >=
190 	    sizeof(s->s_auth.buffer)) {
191 		session_respond(s, "501 Syntax error");
192 		return 1;
193 	}
194 
195 	s->s_state = S_AUTH_FINALIZE;
196 
197 	imsg_compose(s->s_env->sc_ibufs[PROC_PARENT], IMSG_PARENT_AUTHENTICATE,
198 	    0, 0, -1, &s->s_auth, sizeof(s->s_auth));
199 	s->s_flags |= F_EVLOCKED;
200 	bufferevent_disable(s->s_bev, EV_READ);
201 
202 	return 1;
203 }
204 
205 int
206 session_rfc4954_auth_login(struct session *s, char *arg, size_t nr)
207 {
208 	struct session_auth_req req;
209 	size_t len = 0;
210 
211 	switch (s->s_state) {
212 	case S_HELO:
213 		session_respond(s, "334 VXNlcm5hbWU6");
214 		s->s_auth.session_id = s->s_id;
215 		s->s_state = S_AUTH_USERNAME;
216 		return 1;
217 
218 	case S_AUTH_USERNAME:
219 		bzero(s->s_auth.buffer, sizeof(s->s_auth.buffer));
220 		if (kn_decode_base64(arg, req.buffer, 1024) == -1 ||
221 		    ! bsnprintf(s->s_auth.buffer + 1, sizeof(s->s_auth.buffer) - 1, "%s", req.buffer))
222 			goto err;
223 
224 		session_respond(s, "334 UGFzc3dvcmQ6");
225 		s->s_state = S_AUTH_PASSWORD;
226 
227 		return 1;
228 
229 	case S_AUTH_PASSWORD: {
230 		len = strlen(s->s_auth.buffer + 1);
231 		if (kn_decode_base64(arg, req.buffer, 1024) == -1 ||
232 		    ! bsnprintf(s->s_auth.buffer + len + 2, sizeof(s->s_auth.buffer) - len - 2, "%s", req.buffer))
233 			goto err;
234 
235 		break;
236 	}
237 	default:
238 		fatal("session_rfc4954_auth_login: unknown state");
239 	}
240 
241 	s->s_state = S_AUTH_FINALIZE;
242 
243 	req = s->s_auth;
244 	len = strlen(s->s_auth.buffer + 1) + strlen(arg) + 2;
245 	if (kn_encode_base64(req.buffer, len, s->s_auth.buffer, sizeof(s->s_auth.buffer)) == -1)
246 		goto err;
247 
248 	imsg_compose(s->s_env->sc_ibufs[PROC_PARENT], IMSG_PARENT_AUTHENTICATE,
249 	    0, 0, -1, &s->s_auth, sizeof(s->s_auth));
250 	s->s_flags |= F_EVLOCKED;
251 	bufferevent_disable(s->s_bev, EV_READ);
252 
253 	return 1;
254 err:
255 	s->s_state = S_HELO;
256 	session_respond(s, "535 Authentication failed");
257 	return 1;
258 }
259 
260 int
261 session_rfc1652_mail_handler(struct session *s, char *args)
262 {
263 	char *body;
264 
265 	if (s->s_state == S_GREETED) {
266 		session_respond(s, "503 Polite people say HELO first");
267 		return 1;
268 	}
269 
270 	body = strrchr(args, ' ');
271 	if (body != NULL) {
272 		*body++ = '\0';
273 
274 		if (strcasecmp("body=7bit", body) == 0) {
275 			s->s_flags &= ~F_8BITMIME;
276 		}
277 
278 		else if (strcasecmp("body=8bitmime", body) != 0) {
279 			session_respond(s, "503 Invalid BODY");
280 			return 1;
281 		}
282 
283 		return session_rfc5321_mail_handler(s, args);
284 	}
285 
286 	return 0;
287 }
288 
289 int
290 session_rfc5321_helo_handler(struct session *s, char *args)
291 {
292 	if (args == NULL) {
293 		session_respond(s, "501 HELO requires domain address");
294 		return 1;
295 	}
296 
297 	if (strlcpy(s->s_msg.session_helo, args, sizeof(s->s_msg.session_helo))
298 	    >= sizeof(s->s_msg.session_helo)) {
299 		session_respond(s, "501 Invalid domain name");
300 		return 1;
301 	}
302 
303 	s->s_state = S_HELO;
304 	s->s_flags &= F_SECURE;
305 
306 	session_respond(s, "250 %s Hello %s [%s], pleased to meet you",
307 	    s->s_env->sc_hostname, args, ss_to_text(&s->s_ss));
308 
309 	return 1;
310 }
311 
312 int
313 session_rfc5321_ehlo_handler(struct session *s, char *args)
314 {
315 	if (args == NULL) {
316 		session_respond(s, "501 EHLO requires domain address");
317 		return 1;
318 	}
319 
320 	if (strlcpy(s->s_msg.session_helo, args, sizeof(s->s_msg.session_helo))
321 	    >= sizeof(s->s_msg.session_helo)) {
322 		session_respond(s, "501 Invalid domain name");
323 		return 1;
324 	}
325 
326 	s->s_state = S_HELO;
327 	s->s_flags &= F_SECURE;
328 	s->s_flags |= F_EHLO;
329 	s->s_flags |= F_8BITMIME;
330 
331 	session_respond(s, "250-%s Hello %s [%s], pleased to meet you",
332 	    s->s_env->sc_hostname, args, ss_to_text(&s->s_ss));
333 	session_respond(s, "250-8BITMIME");
334 
335 	/* only advertise starttls if listener can support it */
336 	if (s->s_l->flags & F_STARTTLS)
337 		session_respond(s, "250-STARTTLS");
338 
339 	/* only advertise auth if session is secure */
340 	if ((s->s_l->flags & F_AUTH) && (s->s_flags & F_SECURE))
341 		session_respond(s, "250-AUTH PLAIN LOGIN");
342 
343 	session_respond(s, "250 HELP");
344 
345 	return 1;
346 }
347 
348 int
349 session_rfc5321_rset_handler(struct session *s, char *args)
350 {
351 	s->s_state = S_HELO;
352 	session_respond(s, "250 Reset state");
353 
354 	return 1;
355 }
356 
357 int
358 session_rfc5321_noop_handler(struct session *s, char *args)
359 {
360 	session_respond(s, "250 OK");
361 
362 	return 1;
363 }
364 
365 int
366 session_rfc5321_mail_handler(struct session *s, char *args)
367 {
368 	char buffer[MAX_PATH_SIZE];
369 
370 	if (s->s_state == S_GREETED) {
371 		session_respond(s, "503 Polite people say HELO first");
372 		return 1;
373 	}
374 
375 	if (strlcpy(buffer, args, sizeof(buffer)) >= sizeof(buffer)) {
376 		session_respond(s, "553 Sender address syntax error");
377 		return 1;
378 	}
379 
380 	if (! session_set_path(&s->s_msg.sender, buffer)) {
381 		/* No need to even transmit to MFA, path is invalid */
382 		session_respond(s, "553 Sender address syntax error");
383 		return 1;
384 	}
385 
386 	session_cleanup(s);
387 	s->rcptcount = 0;
388 	s->s_state = S_MAILREQUEST;
389 	s->s_msg.id = s->s_id;
390 	s->s_msg.session_id = s->s_id;
391 	s->s_msg.session_ss = s->s_ss;
392 
393 	log_debug("session_mail_handler: sending notification to mfa");
394 
395 	imsg_compose(s->s_env->sc_ibufs[PROC_MFA], IMSG_MFA_MAIL,
396 	    0, 0, -1, &s->s_msg, sizeof(s->s_msg));
397 	s->s_flags |= F_EVLOCKED;
398 	bufferevent_disable(s->s_bev, EV_READ);
399 	return 1;
400 }
401 
402 int
403 session_rfc5321_rcpt_handler(struct session *s, char *args)
404 {
405 	char buffer[MAX_PATH_SIZE];
406 	struct message_recipient	mr;
407 
408 	if (s->s_state == S_GREETED) {
409 		session_respond(s, "503 Polite people say HELO first");
410 		return 1;
411 	}
412 
413 	if (s->s_state == S_HELO) {
414 		session_respond(s, "503 Need MAIL before RCPT");
415 		return 1;
416 	}
417 
418 	bzero(&mr, sizeof(mr));
419 
420 	if (strlcpy(buffer, args, sizeof(buffer)) >= sizeof(buffer)) {
421 		session_respond(s, "553 Recipient address syntax error");
422 		return 1;
423 	}
424 
425 	if (! session_set_path(&mr.path, buffer)) {
426 		/* No need to even transmit to MFA, path is invalid */
427 		session_respond(s, "553 Recipient address syntax error");
428 		return 1;
429 	}
430 
431 	s->s_msg.session_rcpt = mr.path;
432 
433 	mr.id = s->s_msg.id;
434 	s->s_state = S_RCPTREQUEST;
435 	mr.ss = s->s_ss;
436 	mr.msg = s->s_msg;
437 
438 
439 	if (s->s_flags & F_AUTHENTICATED) {
440 		s->s_msg.flags |= F_MESSAGE_AUTHENTICATED;
441 		mr.flags |= F_MESSAGE_AUTHENTICATED;
442 	}
443 
444 	imsg_compose(s->s_env->sc_ibufs[PROC_MFA], IMSG_MFA_RCPT,
445 	    0, 0, -1, &mr, sizeof(mr));
446 	s->s_flags |= F_EVLOCKED;
447 	bufferevent_disable(s->s_bev, EV_READ);
448 	return 1;
449 }
450 
451 int
452 session_rfc5321_quit_handler(struct session *s, char *args)
453 {
454 	session_respond(s, "221 %s Closing connection", s->s_env->sc_hostname);
455 
456 	s->s_flags |= F_QUIT;
457 
458 	return 1;
459 }
460 
461 int
462 session_rfc5321_data_handler(struct session *s, char *args)
463 {
464 	if (s->s_state == S_GREETED) {
465 		session_respond(s, "503 Polite people say HELO first");
466 		return 1;
467 	}
468 
469 	if (s->s_state == S_HELO) {
470 		session_respond(s, "503 Need MAIL before DATA");
471 		return 1;
472 	}
473 
474 	if (s->s_state == S_MAIL) {
475 		session_respond(s, "503 Need RCPT before DATA");
476 		return 1;
477 	}
478 
479 	s->s_state = S_DATAREQUEST;
480 	session_pickup(s, NULL);
481 	return 1;
482 }
483 
484 int
485 session_rfc5321_vrfy_handler(struct session *s, char *args)
486 {
487 	session_respond(s, "252 Cannot VRFY; try RCPT to attempt delivery");
488 
489 	return 1;
490 }
491 
492 int
493 session_rfc5321_expn_handler(struct session *s, char *args)
494 {
495 	session_respond(s, "502 Sorry, we do not allow this operation");
496 
497 	return 1;
498 }
499 
500 int
501 session_rfc5321_turn_handler(struct session *s, char *args)
502 {
503 	session_respond(s, "502 Sorry, we do not allow this operation");
504 
505 	return 1;
506 }
507 
508 int
509 session_rfc5321_help_handler(struct session *s, char *args)
510 {
511 	session_respond(s, "214- This is OpenSMTPD");
512 	session_respond(s, "214- To report bugs in the implementation, please "
513 	    "contact bugs@openbsd.org");
514 	session_respond(s, "214- with full details");
515 	session_respond(s, "214 End of HELP info");
516 
517 	return 1;
518 }
519 
520 void
521 session_command(struct session *s, char *cmd, char *args)
522 {
523 	int	i;
524 
525 	if (!(s->s_flags & F_EHLO))
526 		goto rfc5321;
527 
528 	/* RFC 1652 - 8BITMIME */
529 	for (i = 0; i < (int)(sizeof(rfc1652_cmdtab) / sizeof(struct session_cmd)); ++i)
530 		if (strcasecmp(rfc1652_cmdtab[i].name, cmd) == 0)
531 			break;
532 	if (i < (int)(sizeof(rfc1652_cmdtab) / sizeof(struct session_cmd))) {
533 		if (rfc1652_cmdtab[i].func(s, args))
534 			return;
535 	}
536 
537 	/* RFC 3207 - STARTTLS */
538 	for (i = 0; i < (int)(sizeof(rfc3207_cmdtab) / sizeof(struct session_cmd)); ++i)
539 		if (strcasecmp(rfc3207_cmdtab[i].name, cmd) == 0)
540 			break;
541 	if (i < (int)(sizeof(rfc3207_cmdtab) / sizeof(struct session_cmd))) {
542 		if (rfc3207_cmdtab[i].func(s, args))
543 			return;
544 	}
545 
546 	/* RFC 4954 - AUTH */
547 	if ((s->s_l->flags & F_AUTH) && (s->s_flags & F_SECURE)) {
548 		for (i = 0; i < (int)(sizeof(rfc4954_cmdtab) / sizeof(struct session_cmd)); ++i)
549 			if (strcasecmp(rfc4954_cmdtab[i].name, cmd) == 0)
550 				break;
551 		if (i < (int)(sizeof(rfc4954_cmdtab) / sizeof(struct session_cmd))) {
552 			if (rfc4954_cmdtab[i].func(s, args))
553 				return;
554 		}
555 	}
556 
557 rfc5321:
558 	/* RFC 5321 - SMTP */
559 	for (i = 0; i < (int)(sizeof(rfc5321_cmdtab) / sizeof(struct session_cmd)); ++i)
560 		if (strcasecmp(rfc5321_cmdtab[i].name, cmd) == 0)
561 			break;
562 	if (i < (int)(sizeof(rfc5321_cmdtab) / sizeof(struct session_cmd))) {
563 		if (rfc5321_cmdtab[i].func(s, args))
564 			return;
565 	}
566 
567 	session_respond(s, "500 Command unrecognized");
568 }
569 
570 void
571 session_auth_pickup(struct session *s, char *arg, size_t nr)
572 {
573 	if (s == NULL)
574 		fatal("session_pickup: desynchronized");
575 
576 	bufferevent_enable(s->s_bev, EV_READ);
577 
578 	switch (s->s_state) {
579 	case S_AUTH_INIT:
580 		session_rfc4954_auth_plain(s, arg, nr);
581 		break;
582 	case S_AUTH_USERNAME:
583 		session_rfc4954_auth_login(s, arg, nr);
584 		break;
585 	case S_AUTH_PASSWORD:
586 		session_rfc4954_auth_login(s, arg, nr);
587 		break;
588 	case S_AUTH_FINALIZE:
589 		if (s->s_flags & F_AUTHENTICATED)
590 			session_respond(s, "235 Authentication succeeded");
591 		else
592 			session_respond(s, "535 Authentication failed");
593 		s->s_state = S_HELO;
594 		break;
595 	default:
596 		fatal("session_auth_pickup: unknown state");
597 	}
598 	return;
599 }
600 
601 void
602 session_pickup(struct session *s, struct submit_status *ss)
603 {
604 	if (s == NULL)
605 		fatal("session_pickup: desynchronized");
606 
607 	bufferevent_enable(s->s_bev, EV_READ);
608 
609 	if ((ss != NULL && ss->code == 421) ||
610 	    (s->s_msg.status & S_MESSAGE_TEMPFAILURE))
611 		goto tempfail;
612 
613 	switch (s->s_state) {
614 	case S_INIT:
615 		s->s_state = S_GREETED;
616 		log_debug("session_pickup: greeting client");
617 		session_respond(s, SMTPD_BANNER, s->s_env->sc_hostname);
618 		break;
619 
620 	case S_GREETED:
621 	case S_HELO:
622 		break;
623 
624 	case S_TLS:
625 		s->s_flags |= F_EVLOCKED;
626 		bufferevent_disable(s->s_bev, EV_READ|EV_WRITE);
627 		s->s_state = S_GREETED;
628 		ssl_session_init(s);
629 		break;
630 
631 	case S_MAILREQUEST:
632 		if (ss == NULL)
633 			fatalx("bad ss at S_MAILREQUEST");
634 		/* sender was not accepted, downgrade state */
635 		if (ss->code != 250) {
636 			s->s_state = S_HELO;
637 			session_respond(s, "%d Sender rejected", ss->code);
638 			return;
639 		}
640 
641 		s->s_state = S_MAIL;
642 		s->s_msg.sender = ss->u.path;
643 
644 		imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE],
645 		    IMSG_QUEUE_CREATE_MESSAGE, 0, 0, -1, &s->s_msg,
646 		    sizeof(s->s_msg));
647 		s->s_flags |= F_EVLOCKED;
648 		bufferevent_disable(s->s_bev, EV_READ);
649 		break;
650 
651 	case S_MAIL:
652 		if (ss == NULL)
653 			fatalx("bad ss at S_MAIL");
654 		session_respond(s, "%d Sender ok", ss->code);
655 		break;
656 
657 	case S_RCPTREQUEST:
658 		if (ss == NULL)
659 			fatalx("bad ss at S_RCPTREQUEST");
660 		/* recipient was not accepted */
661 		if (ss->code != 250) {
662 			/* We do not have a valid recipient, downgrade state */
663 			if (s->rcptcount == 0)
664 				s->s_state = S_MAIL;
665 			else
666 				s->s_state = S_RCPT;
667 			session_respond(s, "%d Recipient rejected", ss->code);
668 			return;
669 		}
670 
671 		s->s_state = S_RCPT;
672 		s->rcptcount++;
673 		s->s_msg.recipient = ss->u.path;
674 
675 	case S_RCPT:
676 		if (ss == NULL)
677 			fatalx("bad ss at S_RCPT");
678 		session_respond(s, "%d Recipient ok", ss->code);
679 		break;
680 
681 	case S_DATAREQUEST:
682 		s->s_state = S_DATA;
683 		imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE],
684 		    IMSG_QUEUE_MESSAGE_FILE, 0, 0, -1, &s->s_msg,
685 		    sizeof(s->s_msg));
686 		s->s_flags |= F_EVLOCKED;
687 		bufferevent_disable(s->s_bev, EV_READ);
688 		break;
689 
690 	case S_DATA:
691 		if (ss == NULL)
692 			fatalx("bad ss at S_DATA");
693 		if (s->datafp == NULL)
694 			goto tempfail;
695 
696 		s->s_state = S_DATACONTENT;
697 		session_respond(s, "354 Enter mail, end with \".\" on a line by"
698 		    " itself");
699 		break;
700 
701 	case S_DONE:
702 		s->s_state = S_HELO;
703 		session_respond(s, "250 %s Message accepted for delivery",
704 		    s->s_msg.message_id);
705 		log_info("%s: from=<%s@%s>, nrcpts=%zd, proto=%s, relay=%s [%s]",
706 		    s->s_msg.message_id,
707 		    s->s_msg.sender.user,
708 		    s->s_msg.sender.domain,
709 		    s->rcptcount,
710 		    s->s_flags & F_EHLO ? "ESMTP" : "SMTP",
711 		    s->s_hostname,
712 		    ss_to_text(&s->s_ss));
713 
714 		s->s_msg.message_id[0] = '\0';
715 		s->s_msg.message_uid[0] = '\0';
716 		break;
717 
718 	default:
719 		fatal("session_pickup: unknown state");
720 		break;
721 	}
722 
723 	return;
724 
725 tempfail:
726 	s->s_flags |= F_QUIT;
727 	session_respond(s, "421 Service temporarily unavailable");
728 	return;
729 }
730 
731 void
732 session_init(struct listener *l, struct session *s)
733 {
734 	s->s_state = S_INIT;
735 
736 	if ((s->s_bev = bufferevent_new(s->s_fd, session_read, session_write,
737 	    session_error, s)) == NULL)
738 		fatalx("session_init: bufferevent_new failed");
739 
740 	if (l->flags & F_SSMTP) {
741 		log_debug("session_init: initializing ssl");
742 		s->s_flags |= F_EVLOCKED;
743 		bufferevent_disable(s->s_bev, EV_READ|EV_WRITE);
744 		ssl_session_init(s);
745 		return;
746 	}
747 
748 	session_pickup(s, NULL);
749 }
750 
751 void
752 session_read(struct bufferevent *bev, void *p)
753 {
754 	struct session	*s = p;
755 	char		*line;
756 	char		*ep;
757 	char		*args;
758 	size_t		 nr;
759 
760 read:
761 	s->s_tm = time(NULL);
762 	nr = EVBUFFER_LENGTH(bev->input);
763 	line = evbuffer_readline(bev->input);
764 	if (line == NULL) {
765 		if (EVBUFFER_LENGTH(bev->input) > SMTP_ANYLINE_MAX) {
766 			session_respond(s, "500 Line too long");
767 			s->s_flags |= F_QUIT;
768 		}
769 		return;
770 	}
771 	nr -= EVBUFFER_LENGTH(bev->input);
772 
773 	if (s->s_state == S_DATACONTENT) {
774 		if (session_read_data(s, line, nr)) {
775 			free(line);
776 			return;
777 		}
778 		free(line);
779 		goto read;
780 	}
781 
782 	if (IS_AUTH(s->s_state)) {
783 		session_auth_pickup(s, line, nr);
784 		free(line);
785 		return;
786 	}
787 
788 	if (nr > SMTP_CMDLINE_MAX) {
789 		session_respond(s, "500 Line too long");
790 		return;
791 	}
792 
793 	if ((ep = strchr(line, ':')) == NULL)
794 		ep = strchr(line, ' ');
795 	if (ep != NULL) {
796 		*ep = '\0';
797 		args = ++ep;
798 		while (isspace((int)*args))
799 			args++;
800 	} else
801 		args = NULL;
802 	log_debug("command: %s\targs: %s", line, args);
803 	session_command(s, line, args);
804 	free(line);
805 	return;
806 }
807 
808 int
809 session_read_data(struct session *s, char *line, size_t nread)
810 {
811 	size_t len;
812 	size_t i;
813 
814 	if (strcmp(line, ".") == 0) {
815 		if (! safe_fclose(s->datafp))
816 			s->s_msg.status |= S_MESSAGE_TEMPFAILURE;
817 		s->datafp = NULL;
818 
819 		if (s->s_msg.status & S_MESSAGE_PERMFAILURE) {
820 			session_respond(s, "554 Transaction failed");
821 			s->s_state = S_HELO;
822 		} else if (s->s_msg.status & S_MESSAGE_TEMPFAILURE) {
823 			session_respond(s, "421 Temporary failure");
824 			s->s_state = S_HELO;
825 		} else {
826 			session_msg_submit(s);
827 			s->s_state = S_DONE;
828 		}
829 
830 		return 1;
831 	}
832 
833 	/* Don't waste resources on message if it's going to bin anyway. */
834 	if (s->s_msg.status & (S_MESSAGE_PERMFAILURE|S_MESSAGE_TEMPFAILURE))
835 		return 0;
836 
837 	if (nread > SMTP_TEXTLINE_MAX) {
838 		s->s_msg.status |= S_MESSAGE_PERMFAILURE;
839 		return 0;
840 	}
841 
842 	/* "If the first character is a period and there are other characters
843 	 *  on the line, the first character is deleted." [4.5.2]
844 	 */
845 	if (*line == '.')
846 		line++;
847 
848 	len = strlen(line);
849 
850 	if (fwrite(line, len, 1, s->datafp) != 1 ||
851 	    fwrite("\n", 1, 1, s->datafp) != 1) {
852 		s->s_msg.status |= S_MESSAGE_TEMPFAILURE;
853 		return 0;
854 	}
855 
856 	if (! (s->s_flags & F_8BITMIME)) {
857 		for (i = 0; i < len; ++i)
858 			if (line[i] & 0x80)
859 				break;
860 		if (i != len) {
861 			s->s_msg.status |= S_MESSAGE_PERMFAILURE;
862 			return 0;
863 		}
864 	}
865 
866 	return 0;
867 }
868 
869 void
870 session_write(struct bufferevent *bev, void *p)
871 {
872 	struct session	*s = p;
873 
874 	if (!(s->s_flags & F_QUIT)) {
875 
876 		if (s->s_state == S_TLS)
877 			session_pickup(s, NULL);
878 
879 		return;
880 	}
881 
882 	session_destroy(s);
883 }
884 
885 void
886 session_destroy(struct session *s)
887 {
888 	session_cleanup(s);
889 
890 	log_debug("session_destroy: killing client: %p", s);
891 	close(s->s_fd);
892 
893 	s_smtp.sessions_active--;
894 	if (s_smtp.sessions_active < s->s_env->sc_maxconn)
895 		event_add(&s->s_l->ev, NULL);
896 
897 	if (s->s_bev != NULL) {
898 		bufferevent_free(s->s_bev);
899 	}
900 	ssl_session_destroy(s);
901 
902 	SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s);
903 	bzero(s, sizeof(*s));
904 	free(s);
905 }
906 
907 void
908 session_cleanup(struct session *s)
909 {
910 	if (s->datafp != NULL) {
911 		fclose(s->datafp);
912 		s->datafp = NULL;
913 	}
914 
915 	if (s->s_msg.message_id[0] != '\0') {
916 		imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE],
917 		    IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &s->s_msg,
918 		    sizeof(s->s_msg));
919 		s->s_msg.message_id[0] = '\0';
920 		s->s_msg.message_uid[0] = '\0';
921 		s->s_flags |= F_EVLOCKED;
922 		bufferevent_disable(s->s_bev, EV_READ);
923 	}
924 }
925 
926 void
927 session_error(struct bufferevent *bev, short event, void *p)
928 {
929 	struct session	*s = p;
930 
931 	/* If events are locked, do not destroy session
932 	 * but set F_QUIT flag so that we destroy it as
933 	 * soon as the event lock is removed.
934 	 */
935 	s_smtp.aborted++;
936 	if (s->s_flags & F_EVLOCKED)
937 		s->s_flags |= F_QUIT;
938 	else
939 		session_destroy(s);
940 }
941 
942 void
943 session_msg_submit(struct session *s)
944 {
945 	imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE],
946 	    IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, &s->s_msg,
947 	    sizeof(s->s_msg));
948 	s->s_flags |= F_EVLOCKED;
949 	bufferevent_disable(s->s_bev, EV_READ);
950 	s->s_state = S_DONE;
951 }
952 
953 int
954 session_cmp(struct session *s1, struct session *s2)
955 {
956 	/*
957 	 * do not return u_int64_t's
958 	 */
959 	if (s1->s_id < s2->s_id)
960 		return (-1);
961 
962 	if (s1->s_id > s2->s_id)
963 		return (1);
964 
965 	return (0);
966 }
967 
968 int
969 session_set_path(struct path *path, char *line)
970 {
971 	size_t len;
972 
973 	len = strlen(line);
974 	if (*line != '<' || line[len - 1] != '>')
975 		return 0;
976 	line[len - 1] = '\0';
977 
978 	return recipient_to_path(path, line + 1);
979 }
980 
981 void
982 session_timeout(int fd, short event, void *p)
983 {
984 	struct smtpd		*env = p;
985 	struct session		*sessionp;
986 	struct session		*rmsession;
987 	struct timeval		 tv;
988 	time_t			 tm;
989 	u_int8_t		 i;
990 
991 	tm = time(NULL);
992 	rmsession = NULL;
993 	SPLAY_FOREACH(sessionp, sessiontree, &env->sc_sessions) {
994 
995 		if (rmsession != NULL) {
996 			session_destroy(rmsession);
997 			rmsession = NULL;
998 		}
999 
1000 		for (i = 0; i < sizeof (rfc5321_timeouttab) /
1001 			 sizeof(struct session_timeout); ++i)
1002 			if (rfc5321_timeouttab[i].state == sessionp->s_state)
1003 				break;
1004 
1005 		if (i == sizeof (rfc5321_timeouttab) / sizeof (struct session_timeout)) {
1006 			if (tm - SMTPD_SESSION_TIMEOUT < sessionp->s_tm)
1007 				continue;
1008 		}
1009 		else if (tm - rfc5321_timeouttab[i].timeout < sessionp->s_tm) {
1010 				continue;
1011 		}
1012 
1013 		rmsession = sessionp;
1014 	}
1015 
1016 	if (rmsession != NULL)
1017 		session_destroy(rmsession);
1018 
1019 	tv.tv_sec = 1;
1020 	tv.tv_usec = 0;
1021 	evtimer_add(&env->sc_ev, &tv);
1022 }
1023 
1024 void
1025 session_respond(struct session *s, char *fmt, ...)
1026 {
1027 	va_list ap;
1028 
1029 	va_start(ap, fmt);
1030 	if (evbuffer_add_vprintf(EVBUFFER_OUTPUT(s->s_bev), fmt, ap) == -1 ||
1031 	    evbuffer_add_printf(EVBUFFER_OUTPUT(s->s_bev), "\r\n") == -1)
1032 		fatal("session_respond: evbuffer_add_vprintf failed");
1033 	va_end(ap);
1034 
1035 	bufferevent_enable(s->s_bev, EV_WRITE);
1036 }
1037 
1038 SPLAY_GENERATE(sessiontree, session, s_nodes, session_cmp);
1039