xref: /openbsd/usr.sbin/smtpd/mda.c (revision a6445c1d)
1 /*	$OpenBSD: mda.c,v 1.107 2014/07/08 07:59:31 sobrado Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
7  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/types.h>
23 #include <sys/queue.h>
24 #include <sys/tree.h>
25 #include <sys/socket.h>
26 
27 #include <ctype.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <event.h>
31 #include <imsg.h>
32 #include <inttypes.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <vis.h>
41 
42 #include "smtpd.h"
43 #include "log.h"
44 
45 #define MDA_HIWAT		65536
46 
47 struct mda_envelope {
48 	TAILQ_ENTRY(mda_envelope)	 entry;
49 	uint64_t			 id;
50 	time_t				 creation;
51 	char				*sender;
52 	char				*dest;
53 	char				*rcpt;
54 	enum action_type		 method;
55 	char				*user;
56 	char				*buffer;
57 };
58 
59 #define USER_WAITINFO	0x01
60 #define USER_RUNNABLE	0x02
61 #define USER_ONHOLD	0x04
62 #define USER_HOLDQ	0x08
63 
64 struct mda_user {
65 	uint64_t			id;
66 	TAILQ_ENTRY(mda_user)		entry;
67 	TAILQ_ENTRY(mda_user)		entry_runnable;
68 	char				name[SMTPD_MAXLOGNAME];
69 	char				usertable[SMTPD_MAXPATHLEN];
70 	size_t				evpcount;
71 	TAILQ_HEAD(, mda_envelope)	envelopes;
72 	int				flags;
73 	size_t				running;
74 	struct userinfo			userinfo;
75 };
76 
77 struct mda_session {
78 	uint64_t		 id;
79 	struct mda_user		*user;
80 	struct mda_envelope	*evp;
81 	struct io		 io;
82 	struct iobuf		 iobuf;
83 	FILE			*datafp;
84 };
85 
86 static void mda_io(struct io *, int);
87 static int mda_check_loop(FILE *, struct mda_envelope *);
88 static int mda_getlastline(int, char *, size_t);
89 static void mda_done(struct mda_session *);
90 static void mda_fail(struct mda_user *, int, const char *, enum enhanced_status_code);
91 static void mda_drain(void);
92 static void mda_log(const struct mda_envelope *, const char *, const char *);
93 static void mda_queue_ok(uint64_t);
94 static void mda_queue_tempfail(uint64_t, const char *, enum enhanced_status_code);
95 static void mda_queue_permfail(uint64_t, const char *, enum enhanced_status_code);
96 static void mda_queue_loop(uint64_t);
97 static struct mda_user *mda_user(const struct envelope *);
98 static void mda_user_free(struct mda_user *);
99 static const char *mda_user_to_text(const struct mda_user *);
100 static struct mda_envelope *mda_envelope(const struct envelope *);
101 static void mda_envelope_free(struct mda_envelope *);
102 static struct mda_session * mda_session(struct mda_user *);
103 
104 static struct tree	sessions;
105 static struct tree	users;
106 
107 static TAILQ_HEAD(, mda_user)	runnable;
108 
109 void
110 mda_imsg(struct mproc *p, struct imsg *imsg)
111 {
112 	struct mda_session	*s;
113 	struct mda_user		*u;
114 	struct mda_envelope	*e;
115 	struct envelope		 evp;
116 	struct userinfo		*userinfo;
117 	struct deliver		 deliver;
118 	struct msg		 m;
119 	const void		*data;
120 	const char		*error, *parent_error;
121 	uint64_t		 reqid;
122 	size_t			 sz;
123 	char			 out[256], buf[SMTPD_MAXLINESIZE];
124 	int			 n;
125 	enum lka_resp_status	status;
126 
127 	if (p->proc == PROC_LKA) {
128 		switch (imsg->hdr.type) {
129 		case IMSG_MDA_LOOKUP_USERINFO:
130 			m_msg(&m, imsg);
131 			m_get_id(&m, &reqid);
132 			m_get_int(&m, (int *)&status);
133 			if (status == LKA_OK)
134 				m_get_data(&m, &data, &sz);
135 			m_end(&m);
136 
137 			u = tree_xget(&users, reqid);
138 
139 			if (status == LKA_TEMPFAIL)
140 				mda_fail(u, 0,
141 				    "Temporary failure in user lookup",
142 				    ESC_OTHER_ADDRESS_STATUS);
143 			else if (status == LKA_PERMFAIL)
144 				mda_fail(u, 1,
145 				    "Permanent failure in user lookup",
146 				    ESC_DESTINATION_MAILBOX_HAS_MOVED);
147 			else {
148 				memmove(&u->userinfo, data, sz);
149 				u->flags &= ~USER_WAITINFO;
150 				u->flags |= USER_RUNNABLE;
151 				TAILQ_INSERT_TAIL(&runnable, u, entry_runnable);
152 				mda_drain();
153 			}
154 			return;
155 		}
156 	}
157 
158 	if (p->proc == PROC_QUEUE) {
159 		switch (imsg->hdr.type) {
160 
161 		case IMSG_QUEUE_DELIVER:
162 			m_msg(&m, imsg);
163 			m_get_envelope(&m, &evp);
164 			m_end(&m);
165 
166 			u = mda_user(&evp);
167 
168 			if (u->evpcount >= env->sc_mda_task_hiwat) {
169 				if (!(u->flags & USER_ONHOLD)) {
170 					log_debug("debug: mda: hiwat reached for "
171 					    "user \"%s\": holding envelopes",
172 					    mda_user_to_text(u));
173 					u->flags |= USER_ONHOLD;
174 				}
175 			}
176 
177 			if (u->flags & USER_ONHOLD) {
178 				u->flags |= USER_HOLDQ;
179 				m_create(p_queue, IMSG_MDA_DELIVERY_HOLD, 0, 0, -1);
180 				m_add_evpid(p_queue, evp.id);
181 				m_add_id(p_queue, u->id);
182 				m_close(p_queue);
183 				return;
184 			}
185 
186 			e = mda_envelope(&evp);
187 			TAILQ_INSERT_TAIL(&u->envelopes, e, entry);
188 			u->evpcount += 1;
189 			stat_increment("mda.pending", 1);
190 
191 			if (!(u->flags & USER_RUNNABLE) &&
192 			    !(u->flags & USER_WAITINFO)) {
193 				u->flags |= USER_RUNNABLE;
194 				TAILQ_INSERT_TAIL(&runnable, u, entry_runnable);
195 			}
196 
197 			mda_drain();
198 			return;
199 
200 		case IMSG_MDA_OPEN_MESSAGE:
201 			m_msg(&m, imsg);
202 			m_get_id(&m, &reqid);
203 			m_end(&m);
204 
205 			s = tree_xget(&sessions, reqid);
206 			e = s->evp;
207 
208 			if (imsg->fd == -1) {
209 				log_debug("debug: mda: cannot get message fd");
210 				mda_queue_tempfail(e->id, "Cannot get message fd",
211 				    ESC_OTHER_MAIL_SYSTEM_STATUS);
212 				mda_log(e, "TempFail", "Cannot get message fd");
213 				mda_done(s);
214 				return;
215 			}
216 
217 			log_debug("debug: mda: got message fd %d "
218 			    "for session %016"PRIx64 " evpid %016"PRIx64,
219 			    imsg->fd, s->id, e->id);
220 
221 			if ((s->datafp = fdopen(imsg->fd, "r")) == NULL) {
222 				log_warn("warn: mda: fdopen");
223 				close(imsg->fd);
224 				mda_queue_tempfail(e->id, "fdopen failed",
225 				    ESC_OTHER_MAIL_SYSTEM_STATUS);
226 				mda_log(e, "TempFail", "fdopen failed");
227 				mda_done(s);
228 				return;
229 			}
230 
231 			/* check delivery loop */
232 			if (mda_check_loop(s->datafp, e)) {
233 				log_debug("debug: mda: loop detected");
234 				mda_queue_loop(e->id);
235 				mda_log(e, "PermFail", "Loop detected");
236 				mda_done(s);
237 				return;
238 			}
239 
240 			/* start queueing delivery headers */
241 			if (e->sender[0])
242 				/* XXX: remove existing Return-Path, if any */
243 				n = iobuf_fqueue(&s->iobuf,
244 				    "Return-Path: %s\nDelivered-To: %s\n",
245 				    e->sender, e->rcpt ? e->rcpt : e->dest);
246 			else
247 				n = iobuf_fqueue(&s->iobuf,
248 				    "Delivered-To: %s\n",
249 				    e->rcpt ? e->rcpt : e->dest);
250 			if (n == -1) {
251 				log_warn("warn: mda: "
252 				    "fail to write delivery info");
253 				mda_queue_tempfail(e->id, "Out of memory",
254 				    ESC_OTHER_MAIL_SYSTEM_STATUS);
255 				mda_log(e, "TempFail", "Out of memory");
256 				mda_done(s);
257 				return;
258 			}
259 
260 			/* request parent to fork a helper process */
261 			userinfo = &s->user->userinfo;
262 			memset(&deliver, 0, sizeof deliver);
263 			switch (e->method) {
264 			case A_MDA:
265 				deliver.mode = A_MDA;
266 				deliver.userinfo = *userinfo;
267 				(void)strlcpy(deliver.user, userinfo->username,
268 				    sizeof(deliver.user));
269 				(void)strlcpy(deliver.to, e->buffer,
270 				    sizeof(deliver.to));
271 				break;
272 
273 			case A_MBOX:
274 				/* MBOX is a special case as we MUST deliver as root,
275 				 * just override the uid.
276 				 */
277 				deliver.mode = A_MBOX;
278 				deliver.userinfo = *userinfo;
279 				deliver.userinfo.uid = 0;
280 				(void)strlcpy(deliver.user, "root",
281 				    sizeof(deliver.user));
282 				(void)strlcpy(deliver.from, e->sender,
283 				    sizeof(deliver.from));
284 				(void)strlcpy(deliver.to, userinfo->username,
285 				    sizeof(deliver.to));
286 				break;
287 
288 			case A_MAILDIR:
289 				deliver.mode = A_MAILDIR;
290 				deliver.userinfo = *userinfo;
291 				(void)strlcpy(deliver.user, userinfo->username,
292 				    sizeof(deliver.user));
293 				(void)strlcpy(deliver.dest, e->dest,
294 				    sizeof(deliver.dest));
295 				if (strlcpy(deliver.to, e->buffer,
296 					sizeof(deliver.to))
297 				    >= sizeof(deliver.to)) {
298 					log_warn("warn: mda: "
299 					    "deliver buffer too large");
300 					mda_queue_tempfail(e->id,
301 					    "Maildir path too long",
302 					    ESC_OTHER_MAIL_SYSTEM_STATUS);
303 					mda_log(e, "TempFail",
304 					    "Maildir path too long");
305 					mda_done(s);
306 					return;
307 				}
308 				break;
309 
310 			case A_FILENAME:
311 				deliver.mode = A_FILENAME;
312 				deliver.userinfo = *userinfo;
313 				(void)strlcpy(deliver.user, userinfo->username,
314 				    sizeof deliver.user);
315 				if (strlcpy(deliver.to, e->buffer,
316 					sizeof(deliver.to))
317 				    >= sizeof(deliver.to)) {
318 					log_warn("warn: mda: "
319 					    "deliver buffer too large");
320 					mda_queue_tempfail(e->id,
321 					    "filename path too long",
322 					    ESC_OTHER_MAIL_SYSTEM_STATUS);
323 					mda_log(e, "TempFail",
324 					    "filename path too long");
325 					mda_done(s);
326 					return;
327 				}
328 				break;
329 
330 			case A_LMTP:
331 				deliver.mode = A_LMTP;
332 				deliver.userinfo = *userinfo;
333 				(void)strlcpy(deliver.user, userinfo->username,
334 				    sizeof(deliver.user));
335 				(void)strlcpy(deliver.from, e->sender,
336 				    sizeof(deliver.from));
337 				if (strlcpy(deliver.to, e->buffer,
338 					sizeof(deliver.to))
339 				    >= sizeof(deliver.to)) {
340 					log_warn("warn: mda: "
341 					    "deliver buffer too large");
342 					mda_queue_tempfail(e->id,
343 					    "socket path too long",
344 					    ESC_OTHER_MAIL_SYSTEM_STATUS);
345 					mda_log(e, "TempFail",
346 					    "socket path too long");
347 					mda_done(s);
348 					return;
349 				}
350 				break;
351 
352 			default:
353 				errx(1, "mda: unknown delivery method: %d",
354 				    e->method);
355 			}
356 
357 			log_debug("debug: mda: querying mda fd "
358 			    "for session %016"PRIx64 " evpid %016"PRIx64,
359 			    s->id, s->evp->id);
360 
361 			m_create(p_parent, IMSG_MDA_FORK, 0, 0, -1);
362 			m_add_id(p_parent, reqid);
363 			m_add_data(p_parent, &deliver, sizeof(deliver));
364 			m_close(p_parent);
365 			return;
366 		}
367 	}
368 
369 	if (p->proc == PROC_PARENT) {
370 		switch (imsg->hdr.type) {
371 		case IMSG_MDA_FORK:
372 			m_msg(&m, imsg);
373 			m_get_id(&m, &reqid);
374 			m_end(&m);
375 
376 			s = tree_xget(&sessions, reqid);
377 			e = s->evp;
378 			if (imsg->fd == -1) {
379 				log_warn("warn: mda: fail to retrieve mda fd");
380 				mda_queue_tempfail(e->id, "Cannot get mda fd",
381 				    ESC_OTHER_MAIL_SYSTEM_STATUS);
382 				mda_log(e, "TempFail", "Cannot get mda fd");
383 				mda_done(s);
384 				return;
385 			}
386 
387 			log_debug("debug: mda: got mda fd %d "
388 			    "for session %016"PRIx64 " evpid %016"PRIx64,
389 			    imsg->fd, s->id, s->evp->id);
390 
391 			io_set_blocking(imsg->fd, 0);
392 			io_init(&s->io, imsg->fd, s, mda_io, &s->iobuf);
393 			io_set_write(&s->io);
394 			return;
395 
396 		case IMSG_MDA_DONE:
397 			m_msg(&m, imsg);
398 			m_get_id(&m, &reqid);
399 			m_get_string(&m, &parent_error);
400 			m_end(&m);
401 
402 			s = tree_xget(&sessions, reqid);
403 			e = s->evp;
404 			/*
405 			 * Grab last line of mda stdout/stderr if available.
406 			 */
407 			out[0] = '\0';
408 			if (imsg->fd != -1)
409 				mda_getlastline(imsg->fd, out, sizeof(out));
410 			/*
411 			 * Choose between parent's description of error and
412 			 * child's output, the latter having preference over
413 			 * the former.
414 			 */
415 			error = NULL;
416 			if (strcmp(parent_error, "exited okay") == 0) {
417 				if (s->datafp || iobuf_queued(&s->iobuf))
418 					error = "mda exited prematurely";
419 			} else
420 				error = out[0] ? out : parent_error;
421 
422 			/* update queue entry */
423 			if (error) {
424 				mda_queue_tempfail(e->id, error,
425 				    ESC_OTHER_MAIL_SYSTEM_STATUS);
426 				(void)snprintf(buf, sizeof buf, "Error (%s)", error);
427 				mda_log(e, "TempFail", buf);
428 			}
429 			else {
430 				mda_queue_ok(e->id);
431 				mda_log(e, "Ok", "Delivered");
432 			}
433 			mda_done(s);
434 			return;
435 		}
436 	}
437 
438 	errx(1, "mda_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
439 }
440 
441 void
442 mda_postfork()
443 {
444 }
445 
446 void
447 mda_postprivdrop()
448 {
449 	tree_init(&sessions);
450 	tree_init(&users);
451 	TAILQ_INIT(&runnable);
452 }
453 
454 static void
455 mda_io(struct io *io, int evt)
456 {
457 	struct mda_session	*s = io->arg;
458 	char			*ln;
459 	size_t			 len;
460 
461 	log_trace(TRACE_IO, "mda: %p: %s %s", s, io_strevent(evt),
462 	    io_strio(io));
463 
464 	switch (evt) {
465 	case IO_LOWAT:
466 
467 		/* done */
468 	   done:
469 		if (s->datafp == NULL) {
470 			log_debug("debug: mda: all data sent for session"
471 			    " %016"PRIx64 " evpid %016"PRIx64,
472 			    s->id, s->evp->id);
473 			io_clear(io);
474 			return;
475 		}
476 
477 		while (iobuf_queued(&s->iobuf) < MDA_HIWAT) {
478 			if ((ln = fgetln(s->datafp, &len)) == NULL)
479 				break;
480 			if (iobuf_queue(&s->iobuf, ln, len) == -1) {
481 				m_create(p_parent, IMSG_MDA_KILL,
482 				    0, 0, -1);
483 				m_add_id(p_parent, s->id);
484 				m_add_string(p_parent, "Out of memory");
485 				m_close(p_parent);
486 				io_pause(io, IO_PAUSE_OUT);
487 				return;
488 			}
489 #if 0
490 			log_debug("debug: mda: %zu bytes queued "
491 			    "for session %016"PRIx64 " evpid %016"PRIx64,
492 			    iobuf_queued(&s->iobuf), s->id, s->evp->id);
493 #endif
494 		}
495 
496 		if (ferror(s->datafp)) {
497 			log_debug("debug: mda: ferror on session %016"PRIx64,
498 			    s->id);
499 			m_create(p_parent, IMSG_MDA_KILL, 0, 0, -1);
500 			m_add_id(p_parent, s->id);
501 			m_add_string(p_parent, "Error reading body");
502 			m_close(p_parent);
503 			io_pause(io, IO_PAUSE_OUT);
504 			return;
505 		}
506 
507 		if (feof(s->datafp)) {
508 			log_debug("debug: mda: end-of-file for session"
509 			    " %016"PRIx64 " evpid %016"PRIx64,
510 			    s->id, s->evp->id);
511 			fclose(s->datafp);
512 			s->datafp = NULL;
513  			if (iobuf_queued(&s->iobuf) == 0)
514 				goto done;
515 		}
516 		return;
517 
518 	case IO_TIMEOUT:
519 		log_debug("debug: mda: timeout on session %016"PRIx64, s->id);
520 		io_pause(io, IO_PAUSE_OUT);
521 		return;
522 
523 	case IO_ERROR:
524 		log_debug("debug: mda: io error on session %016"PRIx64": %s",
525 		    s->id, io->error);
526 		io_pause(io, IO_PAUSE_OUT);
527 		return;
528 
529 	case IO_DISCONNECTED:
530 		log_debug("debug: mda: io disconnected on session %016"PRIx64,
531 		    s->id);
532 		io_pause(io, IO_PAUSE_OUT);
533 		return;
534 
535 	default:
536 		log_debug("debug: mda: unexpected event on session %016"PRIx64,
537 		    s->id);
538 		io_pause(io, IO_PAUSE_OUT);
539 		return;
540 	}
541 }
542 
543 static int
544 mda_check_loop(FILE *fp, struct mda_envelope *e)
545 {
546 	char		*buf, *lbuf;
547 	size_t		 len;
548 	int		 ret = 0;
549 
550 	lbuf = NULL;
551 	while ((buf = fgetln(fp, &len))) {
552 		if (buf[len - 1] == '\n')
553 			buf[len - 1] = '\0';
554 		else {
555 			/* EOF without EOL, copy and add the NUL */
556 			lbuf = xmalloc(len + 1, "mda_check_loop");
557 			memcpy(lbuf, buf, len);
558 			lbuf[len] = '\0';
559 			buf = lbuf;
560 		}
561 
562 		if (strchr(buf, ':') == NULL && !isspace((unsigned char)*buf))
563 			break;
564 
565 		if (strncasecmp("Delivered-To: ", buf, 14) == 0) {
566 			if (strcasecmp(buf + 14, e->dest) == 0) {
567 				ret = 1;
568 				break;
569 			}
570 		}
571 		if (lbuf) {
572 			free(lbuf);
573 			lbuf = NULL;
574 		}
575 	}
576 	if (lbuf)
577 		free(lbuf);
578 
579 	fseek(fp, SEEK_SET, 0);
580 
581 	return (ret);
582 }
583 
584 static int
585 mda_getlastline(int fd, char *dst, size_t dstsz)
586 {
587 	FILE	*fp;
588 	char	*ln, buf[SMTPD_MAXLINESIZE];
589 	size_t	 len;
590 
591 	memset(buf, 0, sizeof buf);
592 	if (lseek(fd, 0, SEEK_SET) < 0) {
593 		log_warn("warn: mda: lseek");
594 		close(fd);
595 		return (-1);
596 	}
597 	fp = fdopen(fd, "r");
598 	if (fp == NULL) {
599 		log_warn("warn: mda: fdopen");
600 		close(fd);
601 		return (-1);
602 	}
603 	while ((ln = fgetln(fp, &len))) {
604 		if (ln[len - 1] == '\n')
605 			len--;
606 		if (len == 0)
607 			continue;
608 		if (len >= sizeof buf)
609 			len = (sizeof buf) - 1;
610 		memmove(buf, ln, len);
611 		buf[len] = '\0';
612 	}
613 	fclose(fp);
614 
615 	if (buf[0]) {
616 		(void)strlcpy(dst, "\"", dstsz);
617 		(void)strnvis(dst + 1, buf, dstsz - 2, VIS_SAFE | VIS_CSTYLE);
618 		(void)strlcat(dst, "\"", dstsz);
619 	}
620 
621 	return (0);
622 }
623 
624 static void
625 mda_fail(struct mda_user *user, int permfail, const char *error, enum enhanced_status_code code)
626 {
627 	struct mda_envelope	*e;
628 
629 	while ((e = TAILQ_FIRST(&user->envelopes))) {
630 		TAILQ_REMOVE(&user->envelopes, e, entry);
631 		if (permfail) {
632 			mda_log(e, "PermFail", error);
633 			mda_queue_permfail(e->id, error, code);
634 		}
635 		else {
636 			mda_log(e, "TempFail", error);
637 			mda_queue_tempfail(e->id, error, code);
638 		}
639 		mda_envelope_free(e);
640 	}
641 
642 	mda_user_free(user);
643 }
644 
645 static void
646 mda_drain(void)
647 {
648 	struct mda_user		*u;
649 
650 	while ((u = (TAILQ_FIRST(&runnable)))) {
651 
652 		TAILQ_REMOVE(&runnable, u, entry_runnable);
653 
654 		if (u->evpcount == 0 && u->running == 0) {
655 			log_debug("debug: mda: all done for user \"%s\"",
656 			    mda_user_to_text(u));
657 			mda_user_free(u);
658 			continue;
659 		}
660 
661 		if (u->evpcount == 0) {
662 			log_debug("debug: mda: no more envelope for \"%s\"",
663 			    mda_user_to_text(u));
664 			u->flags &= ~USER_RUNNABLE;
665 			continue;
666 		}
667 
668 		if (u->running >= env->sc_mda_max_user_session) {
669 			log_debug("debug: mda: "
670 			    "maximum number of session reached for user \"%s\"",
671 			    mda_user_to_text(u));
672 			u->flags &= ~USER_RUNNABLE;
673 			continue;
674 		}
675 
676 		if (tree_count(&sessions) >= env->sc_mda_max_session) {
677 			log_debug("debug: mda: "
678 			    "maximum number of session reached");
679 			TAILQ_INSERT_HEAD(&runnable, u, entry_runnable);
680 			return;
681 		}
682 
683 		mda_session(u);
684 
685 		if (u->evpcount == env->sc_mda_task_lowat) {
686 			if (u->flags & USER_ONHOLD) {
687 				log_debug("debug: mda: down to lowat for user \"%s\": releasing",
688 				    mda_user_to_text(u));
689 				u->flags &= ~USER_ONHOLD;
690 			}
691 			if (u->flags & USER_HOLDQ) {
692 				m_create(p_queue, IMSG_MDA_HOLDQ_RELEASE, 0, 0, -1);
693 				m_add_id(p_queue, u->id);
694 				m_add_int(p_queue, env->sc_mda_task_release);
695 				m_close(p_queue);
696 			}
697 		}
698 
699 		/* re-add the user at the tail of the queue */
700 		TAILQ_INSERT_TAIL(&runnable, u, entry_runnable);
701 	}
702 }
703 
704 static void
705 mda_done(struct mda_session *s)
706 {
707 	log_debug("debug: mda: session %016" PRIx64 " done", s->id);
708 
709 	tree_xpop(&sessions, s->id);
710 
711 	mda_envelope_free(s->evp);
712 
713 	s->user->running--;
714 	if (!(s->user->flags & USER_RUNNABLE)) {
715 		log_debug("debug: mda: user \"%s\" becomes runnable",
716 		    s->user->name);
717 		TAILQ_INSERT_TAIL(&runnable, s->user, entry_runnable);
718 		s->user->flags |= USER_RUNNABLE;
719 	}
720 
721 	if (s->datafp)
722 		fclose(s->datafp);
723 	io_clear(&s->io);
724 	iobuf_clear(&s->iobuf);
725 
726 	free(s);
727 
728 	stat_decrement("mda.running", 1);
729 
730 	mda_drain();
731 }
732 
733 static void
734 mda_log(const struct mda_envelope *evp, const char *prefix, const char *status)
735 {
736 	char rcpt[SMTPD_MAXLINESIZE];
737 	const char *method;
738 
739 	rcpt[0] = '\0';
740 	if (evp->rcpt)
741 		(void)snprintf(rcpt, sizeof rcpt, "rcpt=<%s>, ", evp->rcpt);
742 
743 	if (evp->method == A_MAILDIR)
744 		method = "maildir";
745 	else if (evp->method == A_MBOX)
746 		method = "mbox";
747 	else if (evp->method == A_FILENAME)
748 		method = "file";
749 	else if (evp->method == A_MDA)
750 		method = "mda";
751 	else if (evp->method == A_LMTP)
752 		method = "lmtp";
753 	else
754 		method = "???";
755 
756 	log_info("delivery: %s for %016" PRIx64 ": from=<%s>, to=<%s>, "
757 	    "%suser=%s, method=%s, delay=%s, stat=%s",
758 	    prefix,
759 	    evp->id,
760 	    evp->sender ? evp->sender : "",
761 	    evp->dest,
762 	    rcpt,
763 	    evp->user,
764 	    method,
765 	    duration_to_text(time(NULL) - evp->creation),
766 	    status);
767 }
768 
769 static void
770 mda_queue_ok(uint64_t evpid)
771 {
772 	m_create(p_queue, IMSG_MDA_DELIVERY_OK, 0, 0, -1);
773 	m_add_evpid(p_queue, evpid);
774 	m_close(p_queue);
775 }
776 
777 static void
778 mda_queue_tempfail(uint64_t evpid, const char *reason, enum enhanced_status_code code)
779 {
780 	m_create(p_queue, IMSG_MDA_DELIVERY_TEMPFAIL, 0, 0, -1);
781 	m_add_evpid(p_queue, evpid);
782 	m_add_string(p_queue, reason);
783 	m_add_int(p_queue, (int)code);
784 	m_close(p_queue);
785 }
786 
787 static void
788 mda_queue_permfail(uint64_t evpid, const char *reason, enum enhanced_status_code code)
789 {
790 	m_create(p_queue, IMSG_MDA_DELIVERY_PERMFAIL, 0, 0, -1);
791 	m_add_evpid(p_queue, evpid);
792 	m_add_string(p_queue, reason);
793 	m_add_int(p_queue, (int)code);
794 	m_close(p_queue);
795 }
796 
797 static void
798 mda_queue_loop(uint64_t evpid)
799 {
800 	m_create(p_queue, IMSG_MDA_DELIVERY_LOOP, 0, 0, -1);
801 	m_add_evpid(p_queue, evpid);
802 	m_close(p_queue);
803 }
804 
805 static struct mda_user *
806 mda_user(const struct envelope *evp)
807 {
808 	struct mda_user	*u;
809 	void		*i;
810 
811 	i = NULL;
812 	while (tree_iter(&users, &i, NULL, (void**)(&u))) {
813 		if (!strcmp(evp->agent.mda.username, u->name) &&
814 		    !strcmp(evp->agent.mda.usertable, u->usertable))
815 			return (u);
816 	}
817 
818 	u = xcalloc(1, sizeof *u, "mda_user");
819 	u->id = generate_uid();
820 	TAILQ_INIT(&u->envelopes);
821 	(void)strlcpy(u->name, evp->agent.mda.username, sizeof(u->name));
822 	(void)strlcpy(u->usertable, evp->agent.mda.usertable,
823 	    sizeof(u->usertable));
824 
825 	tree_xset(&users, u->id, u);
826 
827 	m_create(p_lka, IMSG_MDA_LOOKUP_USERINFO, 0, 0, -1);
828 	m_add_id(p_lka, u->id);
829 	m_add_string(p_lka, evp->agent.mda.usertable);
830 	m_add_string(p_lka, evp->agent.mda.username);
831 	m_close(p_lka);
832 	u->flags |= USER_WAITINFO;
833 
834 	stat_increment("mda.user", 1);
835 
836 	log_debug("mda: new user %llx for \"%s\"", u->id, mda_user_to_text(u));
837 
838 	return (u);
839 }
840 
841 static void
842 mda_user_free(struct mda_user *u)
843 {
844 	tree_xpop(&users, u->id);
845 
846 	if (u->flags & USER_HOLDQ) {
847 		m_create(p_queue, IMSG_MDA_HOLDQ_RELEASE, 0, 0, -1);
848 		m_add_id(p_queue, u->id);
849 		m_add_int(p_queue, 0);
850 		m_close(p_queue);
851 	}
852 
853 	free(u);
854 	stat_decrement("mda.user", 1);
855 }
856 
857 static const char *
858 mda_user_to_text(const struct mda_user *u)
859 {
860 	static char buf[1024];
861 
862 	(void)snprintf(buf, sizeof(buf), "%s:%s", u->usertable, u->name);
863 
864 	return (buf);
865 }
866 
867 static struct mda_envelope *
868 mda_envelope(const struct envelope *evp)
869 {
870 	struct mda_envelope	*e;
871 	char			 buf[SMTPD_MAXLINESIZE];
872 
873 	e = xcalloc(1, sizeof *e, "mda_envelope");
874 	e->id = evp->id;
875 	e->creation = evp->creation;
876 	buf[0] = '\0';
877 	if (evp->sender.user[0] && evp->sender.domain[0])
878 		(void)snprintf(buf, sizeof buf, "%s@%s",
879 		    evp->sender.user, evp->sender.domain);
880 	e->sender = xstrdup(buf, "mda_envelope:sender");
881 	(void)snprintf(buf, sizeof buf, "%s@%s", evp->dest.user, evp->dest.domain);
882 	e->dest = xstrdup(buf, "mda_envelope:dest");
883 	(void)snprintf(buf, sizeof buf, "%s@%s", evp->rcpt.user, evp->rcpt.domain);
884 	if (strcmp(buf, e->dest))
885 		e->rcpt = xstrdup(buf, "mda_envelope:rcpt");
886 	e->method = evp->agent.mda.method;
887 	e->buffer = xstrdup(evp->agent.mda.buffer, "mda_envelope:buffer");
888 	e->user = xstrdup(evp->agent.mda.username, "mda_envelope:user");
889 
890 	stat_increment("mda.envelope", 1);
891 
892 	return (e);
893 }
894 
895 static void
896 mda_envelope_free(struct mda_envelope *e)
897 {
898 	free(e->sender);
899 	free(e->dest);
900 	free(e->rcpt);
901 	free(e->user);
902 	free(e->buffer);
903 	free(e);
904 
905 	stat_decrement("mda.envelope", 1);
906 }
907 
908 static struct mda_session *
909 mda_session(struct mda_user * u)
910 {
911 	struct mda_session *s;
912 
913 	s = xcalloc(1, sizeof *s, "mda_session");
914 	s->id = generate_uid();
915 	s->user = u;
916 	s->io.sock = -1;
917 	if (iobuf_init(&s->iobuf, 0, 0) == -1)
918 		fatal("mda_session");
919 
920 	tree_xset(&sessions, s->id, s);
921 
922 	s->evp = TAILQ_FIRST(&u->envelopes);
923 	TAILQ_REMOVE(&u->envelopes, s->evp, entry);
924 	u->evpcount--;
925 	u->running++;
926 
927 	stat_decrement("mda.pending", 1);
928 	stat_increment("mda.running", 1);
929 
930 	log_debug("debug: mda: new session %016" PRIx64
931 	    " for user \"%s\" evpid %016" PRIx64, s->id,
932 	    mda_user_to_text(u), s->evp->id);
933 
934 	m_create(p_queue, IMSG_MDA_OPEN_MESSAGE, 0, 0, -1);
935 	m_add_id(p_queue, s->id);
936 	m_add_msgid(p_queue, evpid_to_msgid(s->evp->id));
937 	m_close(p_queue);
938 
939 	return (s);
940 }
941