xref: /openbsd-src/usr.sbin/smtpd/mta.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: mta.c,v 1.44 2009/04/28 21:56:36 gilles Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2008 Gilles Chehade <gilles@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 <ssl/ssl.h>
30 
31 #include <errno.h>
32 #include <event.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 
40 #include "smtpd.h"
41 
42 __dead void	mta_shutdown(void);
43 void		mta_sig_handler(int, short, void *);
44 void		mta_dispatch_parent(int, short, void *);
45 void		mta_dispatch_queue(int, short, void *);
46 void		mta_dispatch_runner(int, short, void *);
47 void		mta_dispatch_lka(int, short, void *);
48 void		mta_setup_events(struct smtpd *);
49 void		mta_disable_events(struct smtpd *);
50 void		mta_write(int, short, void *);
51 int		mta_connect(struct session *);
52 void		mta_read_handler(struct bufferevent *, void *);
53 void		mta_write_handler(struct bufferevent *, void *);
54 void		mta_error_handler(struct bufferevent *, short, void *);
55 int		mta_reply_handler(struct bufferevent *, void *);
56 void		mta_batch_update_queue(struct batch *);
57 void		mta_mxlookup(struct smtpd *, struct session *, char *, struct rule *);
58 void		ssl_client_init(struct session *);
59 
60 void
61 mta_sig_handler(int sig, short event, void *p)
62 {
63 	switch (sig) {
64 	case SIGINT:
65 	case SIGTERM:
66 		mta_shutdown();
67 		break;
68 	default:
69 		fatalx("mta_sig_handler: unexpected signal");
70 	}
71 }
72 
73 void
74 mta_dispatch_parent(int sig, short event, void *p)
75 {
76 	struct smtpd		*env = p;
77 	struct imsgbuf		*ibuf;
78 	struct imsg		 imsg;
79 	ssize_t			 n;
80 
81 	ibuf = env->sc_ibufs[PROC_PARENT];
82 	switch (event) {
83 	case EV_READ:
84 		if ((n = imsg_read(ibuf)) == -1)
85 			fatal("imsg_read_error");
86 		if (n == 0) {
87 			/* this pipe is dead, so remove the event handler */
88 			event_del(&ibuf->ev);
89 			event_loopexit(NULL);
90 			return;
91 		}
92 		break;
93 	case EV_WRITE:
94 		if (msgbuf_write(&ibuf->w) == -1)
95 			fatal("msgbuf_write");
96 		imsg_event_add(ibuf);
97 		return;
98 	default:
99 		fatalx("unknown event");
100 	}
101 
102 	for (;;) {
103 		if ((n = imsg_get(ibuf, &imsg)) == -1)
104 			fatalx("mta_dispatch_parent: imsg_get error");
105 		if (n == 0)
106 			break;
107 
108 		switch (imsg.hdr.type) {
109 		default:
110 			log_warnx("mta_dispatch_parent: got imsg %d",
111 			    imsg.hdr.type);
112 			fatalx("mta_dispatch_parent: unexpected imsg");
113 		}
114 		imsg_free(&imsg);
115 	}
116 	imsg_event_add(ibuf);
117 }
118 
119 void
120 mta_dispatch_lka(int sig, short event, void *p)
121 {
122 	struct smtpd		*env = p;
123 	struct imsgbuf		*ibuf;
124 	struct imsg		 imsg;
125 	ssize_t			 n;
126 
127 	ibuf = env->sc_ibufs[PROC_LKA];
128 	switch (event) {
129 	case EV_READ:
130 		if ((n = imsg_read(ibuf)) == -1)
131 			fatal("imsg_read_error");
132 		if (n == 0) {
133 			/* this pipe is dead, so remove the event handler */
134 			event_del(&ibuf->ev);
135 			event_loopexit(NULL);
136 			return;
137 		}
138 		break;
139 	case EV_WRITE:
140 		if (msgbuf_write(&ibuf->w) == -1)
141 			fatal("msgbuf_write");
142 		imsg_event_add(ibuf);
143 		return;
144 	default:
145 		fatalx("unknown event");
146 	}
147 
148 	for (;;) {
149 		if ((n = imsg_get(ibuf, &imsg)) == -1)
150 			fatalx("mta_dispatch_lka: imsg_get error");
151 		if (n == 0)
152 			break;
153 
154 		switch (imsg.hdr.type) {
155 		case IMSG_LKA_MX: {
156 			struct session key;
157 			struct mxrep *mxrep;
158 			struct session *s;
159 			struct mxhost *mxhost;
160 
161 			mxrep = imsg.data;
162 			key.s_id = mxrep->id;
163 
164 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
165 			if (s == NULL)
166 				fatal("mta_dispatch_lka: session is gone");
167 
168 			mxhost = calloc(1, sizeof(struct mxhost));
169 			if (mxhost == NULL)
170 				fatal("mta_dispatch_lka: calloc");
171 
172 			*mxhost = mxrep->mxhost;
173  			TAILQ_INSERT_TAIL(&s->mxhosts, mxhost, entry);
174 
175 			break;
176 		}
177 		case IMSG_LKA_MX_END: {
178 			struct session key;
179 			struct mxrep *mxrep;
180 			struct session *s;
181 			int ret;
182 
183 			mxrep = imsg.data;
184 			key.s_id = mxrep->id;
185 
186 			s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
187 			if (s == NULL)
188 				fatal("smtp_dispatch_parent: session is gone");
189 
190 			s->batch->flags |= F_BATCH_RESOLVED;
191 
192 			do {
193 				ret = mta_connect(s);
194 			} while (ret == 0);
195 
196 			if (ret < 0) {
197 				mta_batch_update_queue(s->batch);
198 				session_destroy(s);
199 			}
200 
201 			break;
202 		}
203 		default:
204 			log_warnx("mta_dispatch_parent: got imsg %d",
205 			    imsg.hdr.type);
206 			fatalx("mta_dispatch_lka: unexpected imsg");
207 		}
208 		imsg_free(&imsg);
209 	}
210 	imsg_event_add(ibuf);
211 }
212 
213 void
214 mta_dispatch_queue(int sig, short event, void *p)
215 {
216 	struct smtpd		*env = p;
217 	struct imsgbuf		*ibuf;
218 	struct imsg		 imsg;
219 	ssize_t			 n;
220 
221 	ibuf = env->sc_ibufs[PROC_QUEUE];
222 	switch (event) {
223 	case EV_READ:
224 		if ((n = imsg_read(ibuf)) == -1)
225 			fatal("imsg_read_error");
226 		if (n == 0) {
227 			/* this pipe is dead, so remove the event handler */
228 			event_del(&ibuf->ev);
229 			event_loopexit(NULL);
230 			return;
231 		}
232 		break;
233 	case EV_WRITE:
234 		if (msgbuf_write(&ibuf->w) == -1)
235 			fatal("msgbuf_write");
236 		imsg_event_add(ibuf);
237 		return;
238 	default:
239 		fatalx("unknown event");
240 	}
241 
242 	for (;;) {
243 		if ((n = imsg_get(ibuf, &imsg)) == -1)
244 			fatalx("mta_dispatch_queue: imsg_get error");
245 		if (n == 0)
246 			break;
247 
248 		switch (imsg.hdr.type) {
249 		case IMSG_QUEUE_MESSAGE_FD: {
250 			struct batch	*batchp;
251 			struct session	*sessionp;
252 			int fd;
253 
254 			if ((fd = imsg_get_fd(ibuf, &imsg)) == -1) {
255 				/* NEEDS_FIX - unsure yet how it must be handled */
256 				fatalx("mta_dispatch_queue: imsg_get_fd");
257 			}
258 
259 			batchp = (struct batch *)imsg.data;
260 			batchp = batch_by_id(env, batchp->id);
261 			sessionp = batchp->sessionp;
262 
263 			if ((batchp->messagefp = fdopen(fd, "r")) == NULL)
264 				fatal("mta_dispatch_queue: fdopen");
265 
266 			session_respond(sessionp, "DATA");
267 			bufferevent_enable(sessionp->s_bev, EV_READ);
268 			break;
269 		}
270 		default:
271 			log_warnx("mta_dispatch_queue: got imsg %d",
272 			    imsg.hdr.type);
273 			fatalx("mta_dispatch_queue: unexpected imsg");
274 		}
275 		imsg_free(&imsg);
276 	}
277 	imsg_event_add(ibuf);
278 }
279 
280 void
281 mta_dispatch_runner(int sig, short event, void *p)
282 {
283 	struct smtpd		*env = p;
284 	struct imsgbuf		*ibuf;
285 	struct imsg		 imsg;
286 	ssize_t			 n;
287 
288 	ibuf = env->sc_ibufs[PROC_RUNNER];
289 	switch (event) {
290 	case EV_READ:
291 		if ((n = imsg_read(ibuf)) == -1)
292 			fatal("imsg_read_error");
293 		if (n == 0) {
294 			/* this pipe is dead, so remove the event handler */
295 			event_del(&ibuf->ev);
296 			event_loopexit(NULL);
297 			return;
298 		}
299 		break;
300 	case EV_WRITE:
301 		if (msgbuf_write(&ibuf->w) == -1)
302 			fatal("msgbuf_write");
303 		imsg_event_add(ibuf);
304 		return;
305 	default:
306 		fatalx("unknown event");
307 	}
308 
309 	for (;;) {
310 		if ((n = imsg_get(ibuf, &imsg)) == -1)
311 			fatalx("mta_dispatch_runner: imsg_get error");
312 		if (n == 0)
313 			break;
314 
315 		switch (imsg.hdr.type) {
316 		case IMSG_BATCH_CREATE: {
317 			struct session *s;
318 			struct batch *batchp;
319 
320 			/* create a client session */
321 			if ((s = calloc(1, sizeof(*s))) == NULL)
322 				fatal(NULL);
323 			s->s_state = S_INIT;
324 			s->s_env = env;
325 			s->s_id = queue_generate_id();
326 			TAILQ_INIT(&s->mxhosts);
327 			SPLAY_INSERT(sessiontree, &s->s_env->sc_sessions, s);
328 
329 			/* create the batch for this session */
330 			batchp = calloc(1, sizeof (struct batch));
331 			if (batchp == NULL)
332 				fatal("mta_dispatch_runner: calloc");
333 
334 			*batchp = *(struct batch *)imsg.data;
335 			batchp->session_id = s->s_id;
336 			batchp->env = env;
337 			batchp->flags = 0;
338 			batchp->sessionp = s;
339 
340 			s->batch = batchp;
341 
342 			TAILQ_INIT(&batchp->messages);
343 			SPLAY_INSERT(batchtree, &env->batch_queue, batchp);
344 
345 			break;
346 		}
347 		case IMSG_BATCH_APPEND: {
348 			struct batch	*batchp;
349 			struct message	*messagep;
350 
351 			messagep = calloc(1, sizeof (struct message));
352 			if (messagep == NULL)
353 				fatal("mta_dispatch_runner: calloc");
354 
355 			*messagep = *(struct message *)imsg.data;
356 
357 			batchp = batch_by_id(env, messagep->batch_id);
358 			if (batchp == NULL)
359 				fatalx("mta_dispatch_runner: internal inconsistency.");
360 
361 			batchp->session_ss = messagep->session_ss;
362 			strlcpy(batchp->session_hostname,
363 			    messagep->session_hostname,
364 			    sizeof(batchp->session_hostname));
365 			strlcpy(batchp->session_helo, messagep->session_helo,
366 			    sizeof(batchp->session_helo));
367 
368  			TAILQ_INSERT_TAIL(&batchp->messages, messagep, entry);
369 			break;
370 		}
371 		case IMSG_BATCH_CLOSE: {
372 			struct batch		*batchp;
373 			struct session		*s;
374 
375 			batchp = (struct batch *)imsg.data;
376 			batchp = batch_by_id(env, batchp->id);
377 			if (batchp == NULL)
378 				fatalx("mta_dispatch_runner: internal inconsistency.");
379 
380 			batchp->flags |= F_BATCH_COMPLETE;
381 
382 			/* assume temporary failure by default, safest choice */
383 			batchp->status = S_BATCH_TEMPFAILURE;
384 
385 			log_debug("batch ready, we can initiate a session");
386 
387 			s = batchp->sessionp;
388 
389 			mta_mxlookup(env, s, batchp->hostname, &batchp->rule);
390 
391 			break;
392 		}
393 		default:
394 			log_warnx("mta_dispatch_runner: got imsg %d",
395 			    imsg.hdr.type);
396 			fatalx("mta_dispatch_runner: unexpected imsg");
397 		}
398 		imsg_free(&imsg);
399 	}
400 	imsg_event_add(ibuf);
401 }
402 
403 void
404 mta_shutdown(void)
405 {
406 	log_info("mail transfer agent exiting");
407 	_exit(0);
408 }
409 
410 void
411 mta_setup_events(struct smtpd *env)
412 {
413 }
414 
415 void
416 mta_disable_events(struct smtpd *env)
417 {
418 }
419 
420 pid_t
421 mta(struct smtpd *env)
422 {
423 	pid_t		 pid;
424 
425 	struct passwd	*pw;
426 	struct event	 ev_sigint;
427 	struct event	 ev_sigterm;
428 
429 	struct peer peers[] = {
430 		{ PROC_QUEUE,	mta_dispatch_queue },
431 		{ PROC_RUNNER,	mta_dispatch_runner },
432 		{ PROC_LKA,	mta_dispatch_lka }
433 	};
434 
435 	switch (pid = fork()) {
436 	case -1:
437 		fatal("mta: cannot fork");
438 	case 0:
439 		break;
440 	default:
441 		return (pid);
442 	}
443 
444 	ssl_init();
445 	purge_config(env, PURGE_EVERYTHING);
446 
447 	pw = env->sc_pw;
448 #ifndef DEBUG
449 	if (chroot(pw->pw_dir) == -1)
450 		fatal("mta: chroot");
451 	if (chdir("/") == -1)
452 		fatal("mta: chdir(\"/\")");
453 #else
454 #warning disabling privilege revocation and chroot in DEBUG MODE
455 #endif
456 
457 	setproctitle("mail transfer agent");
458 	smtpd_process = PROC_MTA;
459 
460 #ifndef DEBUG
461 	if (setgroups(1, &pw->pw_gid) ||
462 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
463 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
464 		fatal("mta: cannot drop privileges");
465 #endif
466 
467 	event_init();
468 
469 	signal_set(&ev_sigint, SIGINT, mta_sig_handler, env);
470 	signal_set(&ev_sigterm, SIGTERM, mta_sig_handler, env);
471 	signal_add(&ev_sigint, NULL);
472 	signal_add(&ev_sigterm, NULL);
473 	signal(SIGPIPE, SIG_IGN);
474 	signal(SIGHUP, SIG_IGN);
475 
476 	config_pipes(env, peers, 3);
477 	config_peers(env, peers, 3);
478 
479 	SPLAY_INIT(&env->batch_queue);
480 
481 	mta_setup_events(env);
482 	event_dispatch();
483 	mta_shutdown();
484 
485 	return (0);
486 }
487 
488 void
489 mta_mxlookup(struct smtpd *env, struct session *sessionp, char *hostname, struct rule *rule)
490 {
491 	struct mxreq mxreq;
492 
493 	mxreq.id = sessionp->s_id;
494 	mxreq.rule = *rule;
495 	(void)strlcpy(mxreq.hostname, hostname, MAXHOSTNAMELEN);
496 	imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_MX, 0, 0, -1,
497 	    &mxreq, sizeof(struct mxreq));
498 }
499 
500 /* shamelessly ripped usr.sbin/relayd/check_tcp.c ;) */
501 int
502 mta_connect(struct session *sessionp)
503 {
504 	int s;
505 	int type;
506 	struct linger lng;
507 	struct sockaddr_in ssin;
508 	struct sockaddr_in6 ssin6;
509 	struct mxhost *mxhost;
510 
511 	mxhost = TAILQ_FIRST(&sessionp->mxhosts);
512 	if (mxhost == NULL)
513 		return -1;
514 
515 	if ((s = socket(mxhost->ss.ss_family, SOCK_STREAM, 0)) == -1)
516 		goto bad;
517 
518 	bzero(&lng, sizeof(lng));
519 	if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof (lng)) == -1)
520 		goto bad;
521 
522 	type = 1;
523 	if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &type, sizeof (type)) == -1)
524 		goto bad;
525 
526 	session_socket_blockmode(s, BM_NONBLOCK);
527 
528 	if (mxhost->ss.ss_family == PF_INET) {
529 		ssin = *(struct sockaddr_in *)&mxhost->ss;
530 		if (connect(s, (struct sockaddr *)&ssin, sizeof(struct sockaddr_in)) == -1)
531 			if (errno != EINPROGRESS)
532 				goto bad;
533 	}
534 
535 	if (mxhost->ss.ss_family == PF_INET6) {
536 		ssin6 = *(struct sockaddr_in6 *)&mxhost->ss;
537 		if (connect(s, (struct sockaddr *)&ssin6, sizeof(struct sockaddr_in6)) == -1)
538 			if (errno != EINPROGRESS)
539 				goto bad;
540 	}
541 
542 	sessionp->s_tv.tv_sec = SMTPD_CONNECT_TIMEOUT;
543 	sessionp->s_tv.tv_usec = 0;
544 	sessionp->s_fd = s;
545 	event_set(&sessionp->s_ev, s, EV_TIMEOUT|EV_WRITE, mta_write, sessionp);
546 	event_add(&sessionp->s_ev, &sessionp->s_tv);
547 
548 	return 1;
549 
550 bad:
551 	if (mxhost) {
552 		TAILQ_REMOVE(&sessionp->mxhosts, mxhost, entry);
553 		free(mxhost);
554 	}
555 	close(s);
556 	return 0;
557 }
558 
559 void
560 mta_write(int s, short event, void *arg)
561 {
562 	struct session *sessionp = arg;
563 	struct batch *batchp = sessionp->batch;
564 	struct mxhost *mxhost;
565 	int ret;
566 
567 	mxhost = TAILQ_FIRST(&sessionp->mxhosts);
568 
569 	if (event == EV_TIMEOUT) {
570 
571 		if (mxhost) {
572 			TAILQ_REMOVE(&sessionp->mxhosts, mxhost, entry);
573 			free(mxhost);
574 		}
575 		close(s);
576 
577 		if (sessionp->s_bev) {
578 			bufferevent_free(sessionp->s_bev);
579 			sessionp->s_bev = NULL;
580 		}
581 		strlcpy(batchp->errorline, "connection timed-out.",
582 		    sizeof(batchp->errorline));
583 
584 		do {
585 			ret = mta_connect(sessionp);
586 		} while (ret == 0);
587 
588 		if (ret < 0) {
589 			mta_batch_update_queue(batchp);
590 			session_destroy(sessionp);
591 		}
592 
593 		return;
594 	}
595 
596 	sessionp->s_bev = bufferevent_new(s, mta_read_handler, mta_write_handler,
597 	    mta_error_handler, sessionp);
598 
599 	if (sessionp->s_bev == NULL) {
600 		mta_batch_update_queue(batchp);
601 		session_destroy(sessionp);
602 		return;
603 	}
604 
605 	if (mxhost && mxhost->flags & F_SMTPS) {
606 		ssl_client_init(sessionp);
607 		return;
608 	}
609 	bufferevent_enable(sessionp->s_bev, EV_READ);
610 }
611 
612 void
613 mta_read_handler(struct bufferevent *bev, void *arg)
614 {
615 	while (mta_reply_handler(bev, arg))
616 		;
617 }
618 
619 int
620 mta_reply_handler(struct bufferevent *bev, void *arg)
621 {
622 	struct session *sessionp = arg;
623 	struct batch *batchp = sessionp->batch;
624 	struct smtpd *env = batchp->env;
625 	struct message *messagep = NULL;
626 	char *line;
627 	int i;
628 	int code;
629 #define F_ISINFO	0x1
630 #define F_ISPROTOERROR	0x2
631 	char codebuf[4];
632 	const char *errstr;
633 	int flags = 0;
634 	struct mxhost *mxhost = TAILQ_FIRST(&sessionp->mxhosts);
635 
636 	line = evbuffer_readline(bev->input);
637 	if (line == NULL)
638 		return 0;
639 
640 	log_debug("remote server sent: [%s]", line);
641 
642 	strlcpy(codebuf, line, sizeof(codebuf));
643 	code = strtonum(codebuf, 0, UINT16_MAX, &errstr);
644 	if (errstr || code < 100) {
645 		/* Server sent invalid line, protocol error */
646 		batchp->status = S_BATCH_PERMFAILURE;
647 		strlcpy(batchp->errorline, line, sizeof(batchp->errorline));
648 		mta_batch_update_queue(batchp);
649 		session_destroy(sessionp);
650 		return 0;
651 	}
652 
653 	if (line[3] == '-') {
654 		if (strcasecmp(&line[4], "STARTTLS") == 0)
655 			sessionp->s_flags |= F_PEERHASTLS;
656 		else if (strncasecmp(&line[4], "AUTH ", 5) == 0 ||
657 		    strncasecmp(&line[4], "AUTH-", 5) == 0)
658 			sessionp->s_flags |= F_PEERHASAUTH;
659 		return 1;
660 	}
661 
662 	switch (code) {
663 	case 250:
664 		if (sessionp->s_state == S_DONE) {
665 			batchp->status = S_BATCH_ACCEPTED;
666 			mta_batch_update_queue(batchp);
667 			session_destroy(sessionp);
668 			return 0;
669 		}
670 
671 		if (sessionp->s_state == S_GREETED &&
672 		    (sessionp->s_flags & F_PEERHASTLS) &&
673 		    !(sessionp->s_flags & F_SECURE)) {
674 			session_respond(sessionp, "STARTTLS");
675 			sessionp->s_state = S_TLS;
676 			return 0;
677 		}
678 
679 		if (sessionp->s_state == S_GREETED &&
680 		    (sessionp->s_flags & F_PEERHASAUTH) &&
681 		    (sessionp->s_flags & F_SECURE) &&
682 		    (mxhost->flags & F_AUTH) &&
683 		    (mxhost->credentials[0] != '\0')) {
684 			log_debug("AUTH PLAIN %s", mxhost->credentials);
685 			session_respond(sessionp, "AUTH PLAIN %s",
686 			    mxhost->credentials);
687 			sessionp->s_state = S_AUTH_INIT;
688 			return 0;
689 		}
690 
691 		if (sessionp->s_state == S_GREETED &&
692 		    !(sessionp->s_flags & F_PEERHASTLS) &&
693 		    mxhost->flags & F_STARTTLS) {
694 			/* PERM - we want TLS but it is not advertised */
695 			batchp->status = S_BATCH_PERMFAILURE;
696 			mta_batch_update_queue(batchp);
697 			session_destroy(sessionp);
698 			return 0;
699 		}
700 
701 		if (sessionp->s_state == S_GREETED &&
702 		    !(sessionp->s_flags & F_PEERHASAUTH) &&
703 		    mxhost->flags & F_AUTH) {
704 			/* PERM - we want AUTH but it is not advertised */
705 			batchp->status = S_BATCH_PERMFAILURE;
706 			mta_batch_update_queue(batchp);
707 			session_destroy(sessionp);
708 			return 0;
709 		}
710 
711 		break;
712 
713 	case 220:
714 		if (sessionp->s_state == S_TLS) {
715 			ssl_client_init(sessionp);
716 			bufferevent_disable(bev, EV_READ|EV_WRITE);
717 			sessionp->s_state = S_GREETED;
718 			return 0;
719 		}
720 
721 		session_respond(sessionp, "EHLO %s", env->sc_hostname);
722 		sessionp->s_state = S_GREETED;
723 		return 1;
724 
725 	case 235:
726 		if (sessionp->s_state == S_AUTH_INIT) {
727 			sessionp->s_flags |= F_AUTHENTICATED;
728 			sessionp->s_state = S_GREETED;
729 			break;
730 		}
731 		return 0;
732 	case 421:
733 	case 450:
734 	case 451:
735 		strlcpy(batchp->errorline, line, sizeof(batchp->errorline));
736 		mta_batch_update_queue(batchp);
737 		session_destroy(sessionp);
738 		return 0;
739 
740 		/* The following codes are state dependant and will cause
741 		 * a batch rejection if returned at the wrong state.
742 		 */
743 	case 530:
744 	case 550:
745 		if (sessionp->s_state == S_RCPT) {
746 			batchp->messagep->status = (S_MESSAGE_REJECTED|S_MESSAGE_PERMFAILURE);
747 			strlcpy(batchp->messagep->session_errorline, line,
748 			    sizeof(batchp->messagep->session_errorline));
749 			break;
750 		}
751 	case 354:
752 		if (sessionp->s_state == S_RCPT && batchp->messagep == NULL) {
753 			sessionp->s_state = S_DATA;
754 			break;
755 		}
756 
757 	case 221:
758 		if (sessionp->s_state == S_DONE) {
759 			batchp->status = S_BATCH_ACCEPTED;
760 			mta_batch_update_queue(batchp);
761 			session_destroy(sessionp);
762 			return 0;
763 		}
764 
765 	case 535:
766 		/* Authentication failed*/
767 	case 552:
768 	case 553:
769 		flags |= F_ISPROTOERROR;
770 	default:
771 		/* Server sent code we know nothing about, error */
772 		if (!(flags & F_ISPROTOERROR))
773 			log_warn("SMTP session returned unknown status %d.", code);
774 
775 		strlcpy(batchp->errorline, line, sizeof(batchp->errorline));
776 		mta_batch_update_queue(batchp);
777 		session_destroy(sessionp);
778 		return 0;
779 	}
780 
781 
782 	switch (sessionp->s_state) {
783 	case S_GREETED: {
784 		char *user;
785 		char *domain;
786 
787 		if (batchp->type & T_DAEMON_BATCH) {
788 			user = "MAILER-DAEMON";
789 			domain = env->sc_hostname;
790 		}
791 		else {
792 			messagep = TAILQ_FIRST(&batchp->messages);
793 			user = messagep->sender.user;
794 			domain = messagep->sender.domain;
795 		}
796 
797 		if (user[0] == '\0' && domain[0] == '\0')
798 			session_respond(sessionp, "MAIL FROM:<>");
799 		else
800 			session_respond(sessionp,  "MAIL FROM:<%s@%s>", user, domain);
801 
802 		sessionp->s_state = S_MAIL;
803 
804 		break;
805 	}
806 
807 	case S_MAIL:
808 		sessionp->s_state = S_RCPT;
809 
810 	case S_RCPT: {
811 		char *user;
812 		char *domain;
813 
814 		/* Is this the first RCPT ? */
815 		if (batchp->messagep == NULL)
816 			messagep = TAILQ_FIRST(&batchp->messages);
817 		else {
818 			/* We already had a RCPT, mark is as accepted and
819 			 * fetch next one from queue if we aren't dealing
820 			 * with a daemon batch.
821 			 */
822 			if (batchp->type & T_DAEMON_BATCH)
823 				messagep = NULL;
824 			else {
825 				messagep = batchp->messagep;
826 				if ((messagep->status & S_MESSAGE_REJECTED) == 0)
827 					messagep->status = S_MESSAGE_ACCEPTED;
828 				messagep = TAILQ_NEXT(batchp->messagep, entry);
829 			}
830 		}
831 		batchp->messagep = messagep;
832 
833 		if (messagep) {
834 			if (batchp->type & T_DAEMON_BATCH) {
835 				user = messagep->sender.user;
836 				domain = messagep->sender.domain;
837 			}
838 			else {
839 				user = messagep->recipient.user;
840 				domain = messagep->recipient.domain;
841 			}
842 			session_respond(sessionp, "RCPT TO:<%s@%s>", user, domain);
843 		}
844 		else {
845 			/* Do we have at least one accepted recipient ? */
846 			if ((batchp->type & T_DAEMON_BATCH) == 0) {
847 				TAILQ_FOREACH(messagep, &batchp->messages, entry) {
848 					if (messagep->status & S_MESSAGE_ACCEPTED)
849 						break;
850 				}
851 				if (messagep == NULL) {
852 					batchp->status = S_BATCH_PERMFAILURE;
853 					mta_batch_update_queue(batchp);
854 					session_destroy(sessionp);
855 					return 0;
856 				}
857 			}
858 
859 			imsg_compose(env->sc_ibufs[PROC_QUEUE], IMSG_QUEUE_MESSAGE_FD,
860 			    0, 0, -1, batchp, sizeof(*batchp));
861 			bufferevent_disable(sessionp->s_bev, EV_READ);
862 		}
863 		break;
864 	}
865 
866 	case S_DATA: {
867 		session_respond(sessionp, "Received: from %s (%s [%s])",
868 		    batchp->session_helo, batchp->session_hostname,
869 		    ss_to_text(&batchp->session_ss));
870 
871 		session_respond(sessionp, "\tby %s with ESMTP id %s;",
872 		    batchp->env->sc_hostname, batchp->message_id);
873 
874 		session_respond(sessionp, "\t%s", time_to_text(batchp->creation));
875 
876 		if (sessionp->s_flags & F_SECURE) {
877 			log_info("%s: version=%s cipher=%s bits=%d",
878 			batchp->message_id,
879 			SSL_get_cipher_version(sessionp->s_ssl),
880 			SSL_get_cipher_name(sessionp->s_ssl),
881 			SSL_get_cipher_bits(sessionp->s_ssl, NULL));
882 		}
883 
884 		TAILQ_FOREACH(messagep, &batchp->messages, entry) {
885 			session_respond(sessionp, "X-OpenSMTPD-Loop: %s@%s",
886 			    messagep->session_rcpt.user,
887 			    messagep->session_rcpt.domain);
888 		}
889 
890 		if (batchp->type & T_DAEMON_BATCH) {
891 			session_respond(sessionp, "Hi !");
892 			session_respond(sessionp, "%s", "");
893 			session_respond(sessionp, "This is the MAILER-DAEMON, please DO NOT REPLY to this e-mail it is");
894 			session_respond(sessionp, "just a notification to let you know that an error has occured.");
895 			session_respond(sessionp, "%s", "");
896 
897 			if (batchp->status == S_BATCH_PERMFAILURE) {
898 				session_respond(sessionp, "You ran into a PERMANENT FAILURE, which means that the e-mail can't");
899 				session_respond(sessionp, "be delivered to the remote host no matter how much I'll try.");
900 				session_respond(sessionp, "%s", "");
901 				session_respond(sessionp, "Diagnostic:");
902 				session_respond(sessionp, "%s", batchp->errorline);
903 				session_respond(sessionp, "%s", "");
904 			}
905 
906 			if (batchp->status == S_BATCH_TEMPFAILURE) {
907 				session_respond(sessionp, "You ran into a TEMPORARY FAILURE, which means that the e-mail can't");
908 				session_respond(sessionp, "be delivered right now, but could be deliberable at a later time. I");
909 				session_respond(sessionp, "will attempt until it succeeds for the next four days, then let you");
910 				session_respond(sessionp, "know if it didn't work out.");
911 				session_respond(sessionp, "%s", "");
912 				session_respond(sessionp, "Diagnostic:");
913 				session_respond(sessionp, "%s", batchp->errorline);
914 				session_respond(sessionp, "%s", "");
915 			}
916 
917 			i = 0;
918 			TAILQ_FOREACH(messagep, &batchp->messages, entry) {
919 				if (messagep->status & S_MESSAGE_TEMPFAILURE) {
920 					if (i == 0) {
921 						session_respond(sessionp, "The following recipients caused a temporary failure:");
922 						++i;
923 					}
924 
925 					session_respond(sessionp,
926 					    "\t<%s@%s>:", messagep->recipient.user, messagep->recipient.domain);
927 					session_respond(sessionp,
928 					    "%s", messagep->session_errorline);
929 					session_respond(sessionp, "%s", "");
930 				}
931 			}
932 
933 			i = 0;
934 			TAILQ_FOREACH(messagep, &batchp->messages, entry) {
935 				if (messagep->status & S_MESSAGE_PERMFAILURE) {
936 					if (i == 0) {
937 						session_respond(sessionp,
938 						    "The following recipients caused a permanent failure:");
939 						++i;
940 					}
941 
942 					session_respond(sessionp,
943 					    "\t<%s@%s>:", messagep->recipient.user, messagep->recipient.domain);
944 					session_respond(sessionp,
945 					    "%s", messagep->session_errorline);
946 					session_respond(sessionp, "%s", "");
947 				}
948 			}
949 
950 			session_respond(sessionp, "Below is a copy of the original message:");
951 			session_respond(sessionp, "%s", "");
952 		}
953 
954 		break;
955 	}
956 	case S_DONE:
957 		session_respond(sessionp, "QUIT");
958 		sessionp->s_state = S_QUIT;
959 		break;
960 
961 	default:
962 		log_info("unknown command: %d", sessionp->s_state);
963 	}
964 
965 	return 1;
966 }
967 
968 void
969 mta_write_handler(struct bufferevent *bev, void *arg)
970 {
971 	struct session *sessionp = arg;
972 	struct batch *batchp = sessionp->batch;
973 	char *buf, *lbuf;
974 	size_t len;
975 
976 	if (sessionp->s_state == S_QUIT) {
977 		bufferevent_disable(bev, EV_READ|EV_WRITE);
978 		log_debug("closing connection because of QUIT");
979 		close(sessionp->s_fd);
980 		return;
981 	}
982 
983 	/* Progressively fill the output buffer with data */
984 	if (sessionp->s_state == S_DATA) {
985 
986 		lbuf = NULL;
987 		if ((buf = fgetln(batchp->messagefp, &len))) {
988 			if (buf[len - 1] == '\n')
989 				buf[len - 1] = '\0';
990 			else {
991 				if ((lbuf = malloc(len + 1)) == NULL)
992 					fatal("mta_write_handler: malloc");
993 				memcpy(lbuf, buf, len);
994 				lbuf[len] = '\0';
995 				buf = lbuf;
996 			}
997 
998 			/* "If first character of the line is a period, one
999 			 *  additional period is inserted at the beginning."
1000 			 * [4.5.2]
1001 			 */
1002 			if (*buf == '.')
1003 				evbuffer_add_printf(sessionp->s_bev->output, ".");
1004 
1005 			session_respond(sessionp, "%s", buf);
1006 			free(lbuf);
1007 			lbuf = NULL;
1008 		}
1009 		else {
1010 			session_respond(sessionp, ".");
1011 			sessionp->s_state = S_DONE;
1012 			fclose(batchp->messagefp);
1013 			batchp->messagefp = NULL;
1014 		}
1015 	}
1016 }
1017 
1018 void
1019 mta_error_handler(struct bufferevent *bev, short error, void *arg)
1020 {
1021 	struct session *sessionp = arg;
1022 
1023 	if (error & (EVBUFFER_TIMEOUT|EVBUFFER_EOF)) {
1024 		bufferevent_disable(bev, EV_READ|EV_WRITE);
1025 		log_debug("closing connection because of an error");
1026 		close(sessionp->s_fd);
1027 		return;
1028 	}
1029 }
1030 
1031 void
1032 mta_batch_update_queue(struct batch *batchp)
1033 {
1034 	struct smtpd *env = batchp->env;
1035 	struct message *messagep;
1036 
1037 	while ((messagep = TAILQ_FIRST(&batchp->messages)) != NULL) {
1038 
1039 		if (batchp->status == S_BATCH_PERMFAILURE) {
1040 			messagep->status |= S_MESSAGE_PERMFAILURE;
1041 		}
1042 
1043 		if (batchp->status == S_BATCH_TEMPFAILURE) {
1044 			if (messagep->status != S_MESSAGE_PERMFAILURE)
1045 				messagep->status |= S_MESSAGE_TEMPFAILURE;
1046 		}
1047 
1048 		if ((messagep->status & S_MESSAGE_TEMPFAILURE) == 0 &&
1049 		    (messagep->status & S_MESSAGE_PERMFAILURE) == 0) {
1050 			log_info("%s: to=<%s@%s>, delay=%d, stat=Sent",
1051 			    messagep->message_uid,
1052 			    messagep->recipient.user,
1053 			    messagep->recipient.domain,
1054 			    time(NULL) - messagep->creation);
1055 		}
1056 
1057 		imsg_compose(env->sc_ibufs[PROC_QUEUE],
1058 		    IMSG_QUEUE_MESSAGE_UPDATE, 0, 0, -1, messagep,
1059 		    sizeof(struct message));
1060 		TAILQ_REMOVE(&batchp->messages, messagep, entry);
1061 		free(messagep);
1062 	}
1063 
1064 	SPLAY_REMOVE(batchtree, &env->batch_queue, batchp);
1065 
1066 	if (batchp->messagefp)
1067 		fclose(batchp->messagefp);
1068 
1069 	free(batchp);
1070 
1071 }
1072