xref: /openbsd/usr.sbin/smtpd/smtpd.c (revision 8529ddd3)
1 /*	$OpenBSD: smtpd.c,v 1.238 2015/01/20 17:37:54 deraadt 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  *
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/socket.h>
25 #include <sys/wait.h>
26 #include <sys/stat.h>
27 #include <sys/uio.h>
28 #include <sys/mman.h>
29 
30 #include <bsd_auth.h>
31 #include <dirent.h>
32 #include <err.h>
33 #include <errno.h>
34 #include <event.h>
35 #include <fcntl.h>
36 #include <imsg.h>
37 #include <inttypes.h>
38 #include <login_cap.h>
39 #include <paths.h>
40 #include <pwd.h>
41 #include <signal.h>
42 #include <stdio.h>
43 #include <limits.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48 #include <util.h>
49 
50 #include <openssl/ssl.h>
51 #include <openssl/evp.h>
52 
53 #include "smtpd.h"
54 #include "log.h"
55 #include "ssl.h"
56 
57 static void parent_imsg(struct mproc *, struct imsg *);
58 static void usage(void);
59 static void parent_shutdown(int);
60 static void parent_send_config(int, short, void *);
61 static void parent_send_config_lka(void);
62 static void parent_send_config_pony(void);
63 static void parent_send_config_ca(void);
64 static void parent_sig_handler(int, short, void *);
65 static void forkmda(struct mproc *, uint64_t, struct deliver *);
66 static int parent_forward_open(char *, char *, uid_t, gid_t);
67 static void fork_peers(void);
68 static struct child *child_add(pid_t, int, const char *);
69 
70 static void	offline_scan(int, short, void *);
71 static int	offline_add(char *);
72 static void	offline_done(void);
73 static int	offline_enqueue(char *);
74 
75 static void	purge_task(void);
76 static int	parent_auth_user(const char *, const char *);
77 static void	load_pki_tree(void);
78 static void	load_pki_keys(void);
79 
80 enum child_type {
81 	CHILD_DAEMON,
82 	CHILD_MDA,
83 	CHILD_ENQUEUE_OFFLINE,
84 };
85 
86 struct child {
87 	pid_t			 pid;
88 	enum child_type		 type;
89 	const char		*title;
90 	int			 mda_out;
91 	uint64_t		 mda_id;
92 	char			*path;
93 	char			*cause;
94 };
95 
96 struct offline {
97 	TAILQ_ENTRY(offline)	 entry;
98 	char			*path;
99 };
100 
101 #define OFFLINE_READMAX		20
102 #define OFFLINE_QUEUEMAX	5
103 static size_t			offline_running = 0;
104 TAILQ_HEAD(, offline)		offline_q;
105 
106 static struct event		config_ev;
107 static struct event		offline_ev;
108 static struct timeval		offline_timeout;
109 
110 static pid_t			purge_pid = -1;
111 
112 extern char	**environ;
113 void		(*imsg_callback)(struct mproc *, struct imsg *);
114 
115 enum smtp_proc_type	smtpd_process;
116 
117 struct smtpd	*env = NULL;
118 
119 struct mproc	*p_control = NULL;
120 struct mproc	*p_lka = NULL;
121 struct mproc	*p_parent = NULL;
122 struct mproc	*p_queue = NULL;
123 struct mproc	*p_scheduler = NULL;
124 struct mproc	*p_pony = NULL;
125 struct mproc	*p_ca = NULL;
126 
127 const char	*backend_queue = "fs";
128 const char	*backend_scheduler = "ramqueue";
129 const char	*backend_stat = "ram";
130 
131 int	profiling = 0;
132 int	verbose = 0;
133 int	debug = 0;
134 int	foreground = 0;
135 int	control_socket = -1;
136 
137 struct tree	 children;
138 
139 static void
140 parent_imsg(struct mproc *p, struct imsg *imsg)
141 {
142 	struct forward_req	*fwreq;
143 	struct deliver		 deliver;
144 	struct child		*c;
145 	struct msg		 m;
146 	const void		*data;
147 	const char		*username, *password, *cause;
148 	uint64_t		 reqid;
149 	size_t			 sz;
150 	void			*i;
151 	int			 fd, n, v, ret;
152 
153 	if (p->proc == PROC_LKA) {
154 		switch (imsg->hdr.type) {
155 		case IMSG_LKA_OPEN_FORWARD:
156 			fwreq = imsg->data;
157 			fd = parent_forward_open(fwreq->user, fwreq->directory,
158 			    fwreq->uid, fwreq->gid);
159 			fwreq->status = 0;
160 			if (fd == -1 && errno != ENOENT) {
161 				if (errno == EAGAIN)
162 					fwreq->status = -1;
163 			}
164 			else
165 				fwreq->status = 1;
166 			m_compose(p, IMSG_LKA_OPEN_FORWARD, 0, 0, fd,
167 			    fwreq, sizeof *fwreq);
168 			return;
169 
170 		case IMSG_LKA_AUTHENTICATE:
171 			/*
172 			 * If we reached here, it means we want root to lookup
173 			 * system user.
174 			 */
175 			m_msg(&m, imsg);
176 			m_get_id(&m, &reqid);
177 			m_get_string(&m, &username);
178 			m_get_string(&m, &password);
179 			m_end(&m);
180 
181 			ret = parent_auth_user(username, password);
182 
183 			m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
184 			m_add_id(p, reqid);
185 			m_add_int(p, ret);
186 			m_close(p);
187 			return;
188 		}
189 	}
190 
191 	if (p->proc == PROC_PONY) {
192 		switch (imsg->hdr.type) {
193 		case IMSG_MDA_FORK:
194 			m_msg(&m, imsg);
195 			m_get_id(&m, &reqid);
196 			m_get_data(&m, &data, &sz);
197 			m_end(&m);
198 			if (sz != sizeof(deliver))
199 				fatalx("expected deliver");
200 			memmove(&deliver, data, sz);
201 			forkmda(p, reqid, &deliver);
202 			return;
203 
204 		case IMSG_MDA_KILL:
205 			m_msg(&m, imsg);
206 			m_get_id(&m, &reqid);
207 			m_get_string(&m, &cause);
208 			m_end(&m);
209 
210 			i = NULL;
211 			while ((n = tree_iter(&children, &i, NULL, (void**)&c)))
212 				if (c->type == CHILD_MDA &&
213 				    c->mda_id == reqid &&
214 				    c->cause == NULL)
215 					break;
216 			if (!n) {
217 				log_debug("debug: smtpd: "
218 				    "kill request: proc not found");
219 				return;
220 			}
221 
222 			c->cause = xstrdup(cause, "parent_imsg");
223 			log_debug("debug: smtpd: kill requested for %u: %s",
224 			    c->pid, c->cause);
225 			kill(c->pid, SIGTERM);
226 			return;
227 		}
228 	}
229 
230 	if (p->proc == PROC_CONTROL) {
231 		switch (imsg->hdr.type) {
232 		case IMSG_CTL_VERBOSE:
233 			m_msg(&m, imsg);
234 			m_get_int(&m, &v);
235 			m_end(&m);
236 			log_verbose(v);
237 			return;
238 
239 		case IMSG_CTL_PROFILE:
240 			m_msg(&m, imsg);
241 			m_get_int(&m, &v);
242 			m_end(&m);
243 			profiling = v;
244 			return;
245 
246 		case IMSG_CTL_SHUTDOWN:
247 			parent_shutdown(0);
248 			return;
249 		}
250 	}
251 
252 	errx(1, "parent_imsg: unexpected %s imsg from %s",
253 	    imsg_to_str(imsg->hdr.type), proc_title(p->proc));
254 }
255 
256 static void
257 usage(void)
258 {
259 	extern char	*__progname;
260 
261 	fprintf(stderr, "usage: %s [-dhnv] [-D macro=value] "
262 	    "[-f file] [-P system] [-T trace]\n", __progname);
263 	exit(1);
264 }
265 
266 static void
267 parent_shutdown(int ret)
268 {
269 	void		*iter;
270 	struct child	*child;
271 	pid_t		 pid;
272 
273 	iter = NULL;
274 	while (tree_iter(&children, &iter, NULL, (void**)&child))
275 		if (child->type == CHILD_DAEMON)
276 			kill(child->pid, SIGTERM);
277 
278 	do {
279 		pid = waitpid(WAIT_MYPGRP, NULL, 0);
280 	} while (pid != -1 || (pid == -1 && errno == EINTR));
281 
282 	unlink(SMTPD_SOCKET);
283 
284 	log_warnx("warn: parent terminating");
285 	exit(ret);
286 }
287 
288 static void
289 parent_send_config(int fd, short event, void *p)
290 {
291 	parent_send_config_lka();
292 	parent_send_config_pony();
293 	parent_send_config_ca();
294 	purge_config(PURGE_PKI);
295 }
296 
297 static void
298 parent_send_config_pony(void)
299 {
300 	log_debug("debug: parent_send_config: configuring pony process");
301 	m_compose(p_pony, IMSG_CONF_START, 0, 0, -1, NULL, 0);
302 	m_compose(p_pony, IMSG_CONF_END, 0, 0, -1, NULL, 0);
303 }
304 
305 void
306 parent_send_config_lka()
307 {
308 	log_debug("debug: parent_send_config_ruleset: reloading");
309 	m_compose(p_lka, IMSG_CONF_START, 0, 0, -1, NULL, 0);
310 	m_compose(p_lka, IMSG_CONF_END, 0, 0, -1, NULL, 0);
311 }
312 
313 static void
314 parent_send_config_ca(void)
315 {
316 	log_debug("debug: parent_send_config: configuring ca process");
317 	m_compose(p_ca, IMSG_CONF_START, 0, 0, -1, NULL, 0);
318 	m_compose(p_ca, IMSG_CONF_END, 0, 0, -1, NULL, 0);
319 }
320 
321 static void
322 parent_sig_handler(int sig, short event, void *p)
323 {
324 	struct child	*child;
325 	int		 die = 0, status, fail;
326 	pid_t		 pid;
327 	char		*cause;
328 
329 	switch (sig) {
330 	case SIGTERM:
331 	case SIGINT:
332 		die = 1;
333 		/* FALLTHROUGH */
334 	case SIGCHLD:
335 		do {
336 			pid = waitpid(-1, &status, WNOHANG);
337 			if (pid <= 0)
338 				continue;
339 
340 			fail = 0;
341 			if (WIFSIGNALED(status)) {
342 				fail = 1;
343 				asprintf(&cause, "terminated; signal %d",
344 				    WTERMSIG(status));
345 			} else if (WIFEXITED(status)) {
346 				if (WEXITSTATUS(status) != 0) {
347 					fail = 1;
348 					asprintf(&cause, "exited abnormally");
349 				} else
350 					asprintf(&cause, "exited okay");
351 			} else
352 				fatalx("smtpd: unexpected cause of SIGCHLD");
353 
354 			if (pid == purge_pid)
355 				purge_pid = -1;
356 
357 			child = tree_pop(&children, pid);
358 			if (child == NULL)
359 				goto skip;
360 
361 			switch (child->type) {
362 			case CHILD_DAEMON:
363 				die = 1;
364 				if (fail)
365 					log_warnx("warn: lost child: %s %s",
366 					    child->title, cause);
367 				break;
368 
369 			case CHILD_MDA:
370 				if (WIFSIGNALED(status) &&
371 				    WTERMSIG(status) == SIGALRM) {
372 					free(cause);
373 					asprintf(&cause, "terminated; timeout");
374 				}
375 				else if (child->cause &&
376 				    WIFSIGNALED(status) &&
377 				    WTERMSIG(status) == SIGTERM) {
378 					free(cause);
379 					cause = child->cause;
380 					child->cause = NULL;
381 				}
382 				if (child->cause)
383 					free(child->cause);
384 				log_debug("debug: smtpd: mda process done "
385 				    "for session %016"PRIx64 ": %s",
386 				    child->mda_id, cause);
387 				m_create(p_pony, IMSG_MDA_DONE, 0, 0,
388 				    child->mda_out);
389 				m_add_id(p_pony, child->mda_id);
390 				m_add_string(p_pony, cause);
391 				m_close(p_pony);
392 				/* free(cause); */
393 				break;
394 
395 			case CHILD_ENQUEUE_OFFLINE:
396 				if (fail)
397 					log_warnx("warn: smtpd: "
398 					    "couldn't enqueue offline "
399 					    "message %s; smtpctl %s",
400 					    child->path, cause);
401 				else
402 					unlink(child->path);
403 				free(child->path);
404 				offline_done();
405 				break;
406 
407 			default:
408 				fatalx("smtpd: unexpected child type");
409 			}
410 			free(child);
411     skip:
412 			free(cause);
413 		} while (pid > 0 || (pid == -1 && errno == EINTR));
414 
415 		if (die)
416 			parent_shutdown(1);
417 		break;
418 	default:
419 		fatalx("smtpd: unexpected signal");
420 	}
421 }
422 
423 int
424 main(int argc, char *argv[])
425 {
426 	int		 c, i;
427 	int		 opts, flags;
428 	const char	*conffile = CONF_FILE;
429 	struct smtpd	 smtpd;
430 	struct event	 ev_sigint;
431 	struct event	 ev_sigterm;
432 	struct event	 ev_sigchld;
433 	struct event	 ev_sighup;
434 	struct timeval	 tv;
435 
436 	env = &smtpd;
437 
438 	flags = 0;
439 	opts = 0;
440 	debug = 0;
441 	verbose = 0;
442 
443 	log_init(1);
444 
445 	TAILQ_INIT(&offline_q);
446 
447 	while ((c = getopt(argc, argv, "B:dD:hnP:f:T:v")) != -1) {
448 		switch (c) {
449 		case 'B':
450 			if (strstr(optarg, "queue=") == optarg)
451 				backend_queue = strchr(optarg, '=') + 1;
452 			else if (strstr(optarg, "scheduler=") == optarg)
453 				backend_scheduler = strchr(optarg, '=') + 1;
454 			else if (strstr(optarg, "stat=") == optarg)
455 				backend_stat = strchr(optarg, '=') + 1;
456 			else
457 				log_warnx("warn: "
458 				    "invalid backend specifier %s",
459 				    optarg);
460 			break;
461 		case 'd':
462 			foreground = 1;
463 			break;
464 		case 'D':
465 			if (cmdline_symset(optarg) < 0)
466 				log_warnx("warn: "
467 				    "could not parse macro definition %s",
468 				    optarg);
469 			break;
470 		case 'h':
471 			log_info("version: OpenSMTPD " SMTPD_VERSION);
472 			usage();
473 			break;
474 		case 'n':
475 			debug = 2;
476 			opts |= SMTPD_OPT_NOACTION;
477 			break;
478 		case 'f':
479 			conffile = optarg;
480 			break;
481 		case 'T':
482 			if (!strcmp(optarg, "imsg"))
483 				verbose |= TRACE_IMSG;
484 			else if (!strcmp(optarg, "io"))
485 				verbose |= TRACE_IO;
486 			else if (!strcmp(optarg, "smtp"))
487 				verbose |= TRACE_SMTP;
488 			else if (!strcmp(optarg, "mfa") ||
489 			    !strcmp(optarg, "filter") ||
490 			    !strcmp(optarg, "filters"))
491 				verbose |= TRACE_FILTERS;
492 			else if (!strcmp(optarg, "mta") ||
493 			    !strcmp(optarg, "transfer"))
494 				verbose |= TRACE_MTA;
495 			else if (!strcmp(optarg, "bounce") ||
496 			    !strcmp(optarg, "bounces"))
497 				verbose |= TRACE_BOUNCE;
498 			else if (!strcmp(optarg, "scheduler"))
499 				verbose |= TRACE_SCHEDULER;
500 			else if (!strcmp(optarg, "lookup"))
501 				verbose |= TRACE_LOOKUP;
502 			else if (!strcmp(optarg, "stat") ||
503 			    !strcmp(optarg, "stats"))
504 				verbose |= TRACE_STAT;
505 			else if (!strcmp(optarg, "rules"))
506 				verbose |= TRACE_RULES;
507 			else if (!strcmp(optarg, "mproc"))
508 				verbose |= TRACE_MPROC;
509 			else if (!strcmp(optarg, "expand"))
510 				verbose |= TRACE_EXPAND;
511 			else if (!strcmp(optarg, "table") ||
512 			    !strcmp(optarg, "tables"))
513 				verbose |= TRACE_TABLES;
514 			else if (!strcmp(optarg, "queue"))
515 				verbose |= TRACE_QUEUE;
516 			else if (!strcmp(optarg, "all"))
517 				verbose |= ~TRACE_DEBUG;
518 			else if (!strcmp(optarg, "profstat"))
519 				profiling |= PROFILE_TOSTAT;
520 			else if (!strcmp(optarg, "profile-imsg"))
521 				profiling |= PROFILE_IMSG;
522 			else if (!strcmp(optarg, "profile-queue"))
523 				profiling |= PROFILE_QUEUE;
524 			else if (!strcmp(optarg, "profile-buffers"))
525 				profiling |= PROFILE_BUFFERS;
526 			else
527 				log_warnx("warn: unknown trace flag \"%s\"",
528 				    optarg);
529 			break;
530 		case 'P':
531 			if (!strcmp(optarg, "smtp"))
532 				flags |= SMTPD_SMTP_PAUSED;
533 			else if (!strcmp(optarg, "mta"))
534 				flags |= SMTPD_MTA_PAUSED;
535 			else if (!strcmp(optarg, "mda"))
536 				flags |= SMTPD_MDA_PAUSED;
537 			break;
538 		case 'v':
539 			verbose |=  TRACE_DEBUG;
540 			break;
541 		default:
542 			usage();
543 		}
544 	}
545 
546 	argv += optind;
547 	argc -= optind;
548 
549 	if (argc || *argv)
550 		usage();
551 
552 	ssl_init();
553 
554 	if (parse_config(&smtpd, conffile, opts))
555 		exit(1);
556 
557 	if (strlcpy(env->sc_conffile, conffile, PATH_MAX)
558 	    >= PATH_MAX)
559 		errx(1, "config file exceeds PATH_MAX");
560 
561 	if (env->sc_opts & SMTPD_OPT_NOACTION) {
562 		load_pki_tree();
563 		load_pki_keys();
564 		fprintf(stderr, "configuration OK\n");
565 		exit(0);
566 	}
567 
568 	env->sc_flags |= flags;
569 
570 	/* check for root privileges */
571 	if (geteuid())
572 		errx(1, "need root privileges");
573 
574 	/* the control socket ensures that only one smtpd instance is running */
575 	control_socket = control_create_socket();
576 
577 	if (!queue_init(backend_queue, 1))
578 		errx(1, "could not initialize queue backend");
579 
580 	env->sc_stat = stat_backend_lookup(backend_stat);
581 	if (env->sc_stat == NULL)
582 		errx(1, "could not find stat backend \"%s\"", backend_stat);
583 
584 	if (env->sc_queue_flags & QUEUE_ENCRYPTION) {
585 		if (env->sc_queue_key == NULL) {
586 			char	*password;
587 
588 			password = getpass("queue key: ");
589 			if (password == NULL)
590 				err(1, "getpass");
591 
592 			env->sc_queue_key = strdup(password);
593 			explicit_bzero(password, strlen(password));
594 			if (env->sc_queue_key == NULL)
595 				err(1, "strdup");
596 		}
597 		else {
598 			char   *buf;
599 			char   *lbuf;
600 			size_t	len;
601 
602 			if (strcasecmp(env->sc_queue_key, "stdin") == 0) {
603 				lbuf = NULL;
604 				buf = fgetln(stdin, &len);
605 				if (buf[len - 1] == '\n') {
606 					lbuf = calloc(len, 1);
607 					if (lbuf == NULL)
608 						err(1, "calloc");
609 					memcpy(lbuf, buf, len-1);
610 				}
611 				else {
612 					lbuf = calloc(len+1, 1);
613 					if (lbuf == NULL)
614 						err(1, "calloc");
615 					memcpy(lbuf, buf, len);
616 				}
617 				env->sc_queue_key = lbuf;
618 			}
619 		}
620 	}
621 
622 	if (env->sc_queue_flags & QUEUE_COMPRESSION)
623 		env->sc_comp = compress_backend_lookup("gzip");
624 
625 	log_init(foreground);
626 	log_verbose(verbose);
627 
628 	load_pki_tree();
629 
630 	log_info("info: %s %s starting", SMTPD_NAME, SMTPD_VERSION);
631 
632 	if (! foreground)
633 		if (daemon(0, 0) == -1)
634 			err(1, "failed to daemonize");
635 
636 	for (i = 0; i < MAX_BOUNCE_WARN; i++) {
637 		if (env->sc_bounce_warn[i] == 0)
638 			break;
639 		log_debug("debug: bounce warning after %s",
640 		    duration_to_text(env->sc_bounce_warn[i]));
641 	}
642 
643 	log_debug("debug: using \"%s\" queue backend", backend_queue);
644 	log_debug("debug: using \"%s\" scheduler backend", backend_scheduler);
645 	log_debug("debug: using \"%s\" stat backend", backend_stat);
646 	log_info("info: startup%s", (verbose & TRACE_DEBUG)?" [debug mode]":"");
647 
648 	if (env->sc_hostname[0] == '\0')
649 		errx(1, "machine does not have a hostname set");
650 	env->sc_uptime = time(NULL);
651 
652 	fork_peers();
653 
654 	config_process(PROC_PARENT);
655 
656 	imsg_callback = parent_imsg;
657 	event_init();
658 
659 	signal_set(&ev_sigint, SIGINT, parent_sig_handler, NULL);
660 	signal_set(&ev_sigterm, SIGTERM, parent_sig_handler, NULL);
661 	signal_set(&ev_sigchld, SIGCHLD, parent_sig_handler, NULL);
662 	signal_set(&ev_sighup, SIGHUP, parent_sig_handler, NULL);
663 	signal_add(&ev_sigint, NULL);
664 	signal_add(&ev_sigterm, NULL);
665 	signal_add(&ev_sigchld, NULL);
666 	signal_add(&ev_sighup, NULL);
667 	signal(SIGPIPE, SIG_IGN);
668 
669 	config_peer(PROC_CONTROL);
670 	config_peer(PROC_LKA);
671 	config_peer(PROC_QUEUE);
672 	config_peer(PROC_CA);
673 	config_peer(PROC_PONY);
674 	config_done();
675 
676 	evtimer_set(&config_ev, parent_send_config, NULL);
677 	memset(&tv, 0, sizeof(tv));
678 	evtimer_add(&config_ev, &tv);
679 
680 	/* defer offline scanning for a second */
681 	evtimer_set(&offline_ev, offline_scan, NULL);
682 	offline_timeout.tv_sec = 1;
683 	offline_timeout.tv_usec = 0;
684 	evtimer_add(&offline_ev, &offline_timeout);
685 
686 	if (pidfile(NULL) < 0)
687 		err(1, "pidfile");
688 
689 	purge_task();
690 
691 	if (event_dispatch() < 0)
692 		fatal("smtpd: event_dispatch");
693 
694 	return (0);
695 }
696 
697 static void
698 load_pki_tree(void)
699 {
700 	struct pki	*pki;
701 	const char	*k;
702 	void		*iter_dict;
703 
704 	log_debug("debug: init ssl-tree");
705 	iter_dict = NULL;
706 	while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
707 		log_debug("info: loading pki information for %s", k);
708 		if (pki->pki_cert_file == NULL)
709 			fatalx("load_pki_tree: missing certificate file");
710 		if (pki->pki_key_file == NULL)
711 			fatalx("load_pki_tree: missing key file");
712 
713 		if (! ssl_load_certificate(pki, pki->pki_cert_file))
714 			fatalx("load_pki_tree: failed to load certificate file");
715 
716 		if (pki->pki_ca_file)
717 			if (! ssl_load_cafile(pki, pki->pki_ca_file))
718 				fatalx("load_pki_tree: failed to load CA file");
719 		if (pki->pki_dhparams_file)
720 			if (! ssl_load_dhparams(pki, pki->pki_dhparams_file))
721 				fatalx("load_pki_tree: failed to load dhparams file");
722 	}
723 }
724 
725 void
726 load_pki_keys(void)
727 {
728 	struct pki	*pki;
729 	const char	*k;
730 	void		*iter_dict;
731 
732 	log_debug("debug: init ssl-tree");
733 	iter_dict = NULL;
734 	while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
735 		log_debug("info: loading pki keys for %s", k);
736 
737 		if (! ssl_load_keyfile(pki, pki->pki_key_file, k))
738 			fatalx("load_pki_keys: failed to load key file");
739 	}
740 }
741 
742 static void
743 fork_peers(void)
744 {
745 	tree_init(&children);
746 
747 	init_pipes();
748 
749 	child_add(queue(), CHILD_DAEMON, proc_title(PROC_QUEUE));
750 	child_add(control(), CHILD_DAEMON, proc_title(PROC_CONTROL));
751 	child_add(lka(), CHILD_DAEMON, proc_title(PROC_LKA));
752 	child_add(scheduler(), CHILD_DAEMON, proc_title(PROC_SCHEDULER));
753 	child_add(pony(), CHILD_DAEMON, proc_title(PROC_PONY));
754 	child_add(ca(), CHILD_DAEMON, proc_title(PROC_CA));
755 	post_fork(PROC_PARENT);
756 }
757 
758 void
759 post_fork(int proc)
760 {
761 	if (proc != PROC_QUEUE && env->sc_queue_key)
762 		explicit_bzero(env->sc_queue_key, strlen(env->sc_queue_key));
763 
764 	if (proc != PROC_CONTROL) {
765 		close(control_socket);
766 		control_socket = -1;
767 	}
768 
769 	if (proc == PROC_CA) {
770 		load_pki_keys();
771 	}
772 }
773 
774 int
775 fork_proc_backend(const char *key, const char *conf, const char *procname)
776 {
777 	pid_t		pid;
778 	int		sp[2];
779 	char		path[PATH_MAX];
780 	char		name[PATH_MAX];
781 	char		*arg;
782 
783 	if (strlcpy(name, conf, sizeof(name)) >= sizeof(name)) {
784 		log_warnx("warn: %s-proc: conf too long", key);
785 		return (0);
786 	}
787 
788 	arg = strchr(name, ':');
789 	if (arg)
790 		*arg++ = '\0';
791 
792 	if (snprintf(path, sizeof(path), PATH_LIBEXEC "/%s-%s", key, name) >=
793 	    (ssize_t)sizeof(path)) {
794 		log_warn("warn: %s-proc: exec path too long", key);
795 		return (-1);
796 	}
797 
798 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) {
799 		log_warn("warn: %s-proc: socketpair", key);
800 		return (-1);
801 	}
802 
803 	if ((pid = fork()) == -1) {
804 		log_warn("warn: %s-proc: fork", key);
805 		close(sp[0]);
806 		close(sp[1]);
807 		return (-1);
808 	}
809 
810 	if (pid == 0) {
811 		/* child process */
812 		dup2(sp[0], STDIN_FILENO);
813 		if (closefrom(STDERR_FILENO + 1) < 0)
814 			exit(1);
815 
816 		if (procname == NULL)
817 			procname = name;
818 
819 		execl(path, procname, arg, NULL);
820 		err(1, "execl: %s", path);
821 	}
822 
823 	/* parent process */
824 	close(sp[0]);
825 
826 	return (sp[1]);
827 }
828 
829 struct child *
830 child_add(pid_t pid, int type, const char *title)
831 {
832 	struct child	*child;
833 
834 	if ((child = calloc(1, sizeof(*child))) == NULL)
835 		fatal("smtpd: child_add: calloc");
836 
837 	child->pid = pid;
838 	child->type = type;
839 	child->title = title;
840 
841 	tree_xset(&children, pid, child);
842 
843 	return (child);
844 }
845 
846 static void
847 purge_task(void)
848 {
849 	struct passwd	*pw;
850 	DIR		*d;
851 	int		 n;
852 	uid_t		 uid;
853 	gid_t		 gid;
854 
855 	n = 0;
856 	if ((d = opendir(PATH_SPOOL PATH_PURGE))) {
857 		while (readdir(d) != NULL)
858 			n++;
859 		closedir(d);
860 	} else
861 		log_warn("warn: purge_task: opendir");
862 
863 	if (n > 2) {
864 		switch (purge_pid = fork()) {
865 		case -1:
866 			log_warn("warn: purge_task: fork");
867 			break;
868 		case 0:
869 			if ((pw = getpwnam(SMTPD_USER)) == NULL)
870 				fatalx("unknown user " SMTPD_USER);
871 			if (chroot(PATH_SPOOL PATH_PURGE) == -1)
872 				fatal("smtpd: chroot");
873 			if (chdir("/") == -1)
874 				fatal("smtpd: chdir");
875 			uid = pw->pw_uid;
876 			gid = pw->pw_gid;
877 			if (setgroups(1, &gid) ||
878 			    setresgid(gid, gid, gid) ||
879 			    setresuid(uid, uid, uid))
880 				fatal("smtpd: cannot drop privileges");
881 			rmtree("/", 1);
882 			_exit(0);
883 			break;
884 		default:
885 			break;
886 		}
887 	}
888 }
889 
890 static void
891 forkmda(struct mproc *p, uint64_t id, struct deliver *deliver)
892 {
893 	char		 ebuf[128], sfn[32];
894 	struct delivery_backend	*db;
895 	struct child	*child;
896 	pid_t		 pid;
897 	int		 allout, pipefd[2];
898 	mode_t		 omode;
899 
900 	log_debug("debug: smtpd: forking mda for session %016"PRIx64
901 	    ": \"%s\" as %s", id, deliver->to, deliver->user);
902 
903 	db = delivery_backend_lookup(deliver->mode);
904 	if (db == NULL) {
905 		(void)snprintf(ebuf, sizeof ebuf, "could not find delivery backend");
906 		m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1);
907 		m_add_id(p_pony, id);
908 		m_add_string(p_pony, ebuf);
909 		m_close(p_pony);
910 		return;
911 	}
912 
913 	if (deliver->userinfo.uid == 0 && ! db->allow_root) {
914 		(void)snprintf(ebuf, sizeof ebuf, "not allowed to deliver to: %s",
915 		    deliver->user);
916 		m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1);
917 		m_add_id(p_pony, id);
918 		m_add_string(p_pony, ebuf);
919 		m_close(p_pony);
920 		return;
921 	}
922 
923 	if (pipe(pipefd) < 0) {
924 		(void)snprintf(ebuf, sizeof ebuf, "pipe: %s", strerror(errno));
925 		m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1);
926 		m_add_id(p_pony, id);
927 		m_add_string(p_pony, ebuf);
928 		m_close(p_pony);
929 		return;
930 	}
931 
932 	/* prepare file which captures stdout and stderr */
933 	(void)strlcpy(sfn, "/tmp/smtpd.out.XXXXXXXXXXX", sizeof(sfn));
934 	omode = umask(7077);
935 	allout = mkstemp(sfn);
936 	umask(omode);
937 	if (allout < 0) {
938 		(void)snprintf(ebuf, sizeof ebuf, "mkstemp: %s", strerror(errno));
939 		m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1);
940 		m_add_id(p_pony, id);
941 		m_add_string(p_pony, ebuf);
942 		m_close(p_pony);
943 		close(pipefd[0]);
944 		close(pipefd[1]);
945 		return;
946 	}
947 	unlink(sfn);
948 
949 	pid = fork();
950 	if (pid < 0) {
951 		(void)snprintf(ebuf, sizeof ebuf, "fork: %s", strerror(errno));
952 		m_create(p_pony, IMSG_MDA_DONE, 0, 0, -1);
953 		m_add_id(p_pony, id);
954 		m_add_string(p_pony, ebuf);
955 		m_close(p_pony);
956 		close(pipefd[0]);
957 		close(pipefd[1]);
958 		close(allout);
959 		return;
960 	}
961 
962 	/* parent passes the child fd over to mda */
963 	if (pid > 0) {
964 		child = child_add(pid, CHILD_MDA, NULL);
965 		child->mda_out = allout;
966 		child->mda_id = id;
967 		close(pipefd[0]);
968 		m_create(p, IMSG_MDA_FORK, 0, 0, pipefd[1]);
969 		m_add_id(p, id);
970 		m_close(p);
971 		return;
972 	}
973 
974 	if (chdir(deliver->userinfo.directory) < 0 && chdir("/") < 0)
975 		err(1, "chdir");
976 	if (setgroups(1, &deliver->userinfo.gid) ||
977 	    setresgid(deliver->userinfo.gid, deliver->userinfo.gid, deliver->userinfo.gid) ||
978 	    setresuid(deliver->userinfo.uid, deliver->userinfo.uid, deliver->userinfo.uid))
979 		err(1, "forkmda: cannot drop privileges");
980 	if (dup2(pipefd[0], STDIN_FILENO) < 0 ||
981 	    dup2(allout, STDOUT_FILENO) < 0 ||
982 	    dup2(allout, STDERR_FILENO) < 0)
983 		err(1, "forkmda: dup2");
984 	if (closefrom(STDERR_FILENO + 1) < 0)
985 		err(1, "closefrom");
986 	if (setsid() < 0)
987 		err(1, "setsid");
988 	if (signal(SIGPIPE, SIG_DFL) == SIG_ERR ||
989 	    signal(SIGINT, SIG_DFL) == SIG_ERR ||
990 	    signal(SIGTERM, SIG_DFL) == SIG_ERR ||
991 	    signal(SIGCHLD, SIG_DFL) == SIG_ERR ||
992 	    signal(SIGHUP, SIG_DFL) == SIG_ERR)
993 		err(1, "signal");
994 
995 	/* avoid hangs by setting 5m timeout */
996 	alarm(300);
997 
998 	db->open(deliver);
999 }
1000 
1001 static void
1002 offline_scan(int fd, short ev, void *arg)
1003 {
1004 	DIR		*dir = arg;
1005 	struct dirent	*d;
1006 	int		 n = 0;
1007 
1008 	if (dir == NULL) {
1009 		log_debug("debug: smtpd: scanning offline queue...");
1010 		if ((dir = opendir(PATH_SPOOL PATH_OFFLINE)) == NULL)
1011 			errx(1, "smtpd: opendir");
1012 	}
1013 
1014 	while ((d = readdir(dir)) != NULL) {
1015 		if (d->d_type != DT_REG)
1016 			continue;
1017 
1018 		if (offline_add(d->d_name)) {
1019 			log_warnx("warn: smtpd: "
1020 			    "could not add offline message %s", d->d_name);
1021 			continue;
1022 		}
1023 
1024 		if ((n++) == OFFLINE_READMAX) {
1025 			evtimer_set(&offline_ev, offline_scan, dir);
1026 			offline_timeout.tv_sec = 0;
1027 			offline_timeout.tv_usec = 100000;
1028 			evtimer_add(&offline_ev, &offline_timeout);
1029 			return;
1030 		}
1031 	}
1032 
1033 	log_debug("debug: smtpd: offline scanning done");
1034 	closedir(dir);
1035 }
1036 
1037 static int
1038 offline_enqueue(char *name)
1039 {
1040 	char		 t[PATH_MAX], *path;
1041 	struct stat	 sb;
1042 	pid_t		 pid;
1043 	struct child	*child;
1044 	struct passwd	*pw;
1045 
1046 	if (!bsnprintf(t, sizeof t, "%s/%s", PATH_SPOOL PATH_OFFLINE, name)) {
1047 		log_warnx("warn: smtpd: path name too long");
1048 		return (-1);
1049 	}
1050 
1051 	if ((path = strdup(t)) == NULL) {
1052 		log_warn("warn: smtpd: strdup");
1053 		return (-1);
1054 	}
1055 
1056 	log_debug("debug: smtpd: enqueueing offline message %s", path);
1057 
1058 	if ((pid = fork()) == -1) {
1059 		log_warn("warn: smtpd: fork");
1060 		free(path);
1061 		return (-1);
1062 	}
1063 
1064 	if (pid == 0) {
1065 		char	*envp[2], *p, *tmp;
1066 		FILE	*fp;
1067 		size_t	 len;
1068 		arglist	 args;
1069 
1070 		memset(&args, 0, sizeof(args));
1071 
1072 		if (lstat(path, &sb) == -1) {
1073 			log_warn("warn: smtpd: lstat: %s", path);
1074 			_exit(1);
1075 		}
1076 
1077 		if (chflags(path, 0) == -1) {
1078 			log_warn("warn: smtpd: chflags: %s", path);
1079 			_exit(1);
1080 		}
1081 
1082 		pw = getpwuid(sb.st_uid);
1083 		if (pw == NULL) {
1084 			log_warnx("warn: smtpd: getpwuid for uid %d failed",
1085 			    sb.st_uid);
1086 			_exit(1);
1087 		}
1088 
1089 		if (! S_ISREG(sb.st_mode)) {
1090 			log_warnx("warn: smtpd: file %s (uid %d) not regular",
1091 			    path, sb.st_uid);
1092 			_exit(1);
1093 		}
1094 
1095 		if (setgroups(1, &pw->pw_gid) ||
1096 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
1097 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) ||
1098 		    closefrom(STDERR_FILENO + 1) == -1)
1099 			_exit(1);
1100 
1101 		if ((fp = fopen(path, "r")) == NULL)
1102 			_exit(1);
1103 
1104 		if (chdir(pw->pw_dir) == -1 && chdir("/") == -1)
1105 			_exit(1);
1106 
1107 		if (setsid() == -1 ||
1108 		    signal(SIGPIPE, SIG_DFL) == SIG_ERR ||
1109 		    dup2(fileno(fp), STDIN_FILENO) == -1)
1110 			_exit(1);
1111 
1112 		if ((p = fgetln(fp, &len)) == NULL)
1113 			_exit(1);
1114 
1115 		if (p[len - 1] != '\n')
1116 			_exit(1);
1117 		p[len - 1] = '\0';
1118 
1119 		addargs(&args, "%s", "sendmail");
1120 		addargs(&args, "%s", "-S");
1121 
1122 		while ((tmp = strsep(&p, "|")) != NULL)
1123 			addargs(&args, "%s", tmp);
1124 
1125 		if (lseek(fileno(fp), len, SEEK_SET) == -1)
1126 			_exit(1);
1127 
1128 		envp[0] = "PATH=" _PATH_DEFPATH;
1129 		envp[1] = (char *)NULL;
1130 		environ = envp;
1131 
1132 		execvp(PATH_SMTPCTL, args.list);
1133 		_exit(1);
1134 	}
1135 
1136 	offline_running++;
1137 	child = child_add(pid, CHILD_ENQUEUE_OFFLINE, NULL);
1138 	child->path = path;
1139 
1140 	return (0);
1141 }
1142 
1143 static int
1144 offline_add(char *path)
1145 {
1146 	struct offline	*q;
1147 
1148 	if (offline_running < OFFLINE_QUEUEMAX)
1149 		/* skip queue */
1150 		return offline_enqueue(path);
1151 
1152 	q = malloc(sizeof(*q) + strlen(path) + 1);
1153 	if (q == NULL)
1154 		return (-1);
1155 	q->path = (char *)q + sizeof(*q);
1156 	memmove(q->path, path, strlen(path) + 1);
1157 	TAILQ_INSERT_TAIL(&offline_q, q, entry);
1158 
1159 	return (0);
1160 }
1161 
1162 static void
1163 offline_done(void)
1164 {
1165 	struct offline	*q;
1166 
1167 	offline_running--;
1168 
1169 	while (offline_running < OFFLINE_QUEUEMAX) {
1170 		if ((q = TAILQ_FIRST(&offline_q)) == NULL)
1171 			break; /* all done */
1172 		TAILQ_REMOVE(&offline_q, q, entry);
1173 		offline_enqueue(q->path);
1174 		free(q);
1175 	}
1176 }
1177 
1178 static int
1179 parent_forward_open(char *username, char *directory, uid_t uid, gid_t gid)
1180 {
1181 	char		pathname[PATH_MAX];
1182 	int		fd;
1183 	struct stat	sb;
1184 
1185 	if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward",
1186 		directory))
1187 		fatal("smtpd: parent_forward_open: snprintf");
1188 
1189 	if (stat(directory, &sb) < 0) {
1190 		log_warn("warn: smtpd: parent_forward_open: %s", directory);
1191 		return -1;
1192 	}
1193 	if (sb.st_mode & S_ISVTX) {
1194 		log_warnx("warn: smtpd: parent_forward_open: %s is sticky",
1195 		    directory);
1196 		errno = EAGAIN;
1197 		return -1;
1198 	}
1199 
1200 	do {
1201 		fd = open(pathname, O_RDONLY);
1202 	} while (fd == -1 && errno == EINTR);
1203 	if (fd == -1) {
1204 		if (errno == ENOENT)
1205 			return -1;
1206 		if (errno == EMFILE || errno == ENFILE || errno == EIO) {
1207 			errno = EAGAIN;
1208 			return -1;
1209 		}
1210 		log_warn("warn: smtpd: parent_forward_open: %s", pathname);
1211 		return -1;
1212 	}
1213 
1214 	if (! secure_file(fd, pathname, directory, uid, 1)) {
1215 		log_warnx("warn: smtpd: %s: unsecure file", pathname);
1216 		close(fd);
1217 		return -1;
1218 	}
1219 
1220 	return fd;
1221 }
1222 
1223 void
1224 imsg_dispatch(struct mproc *p, struct imsg *imsg)
1225 {
1226 	struct timespec	t0, t1, dt;
1227 	int		msg;
1228 
1229 	if (imsg == NULL) {
1230 		exit(1);
1231 		return;
1232 	}
1233 
1234 	log_imsg(smtpd_process, p->proc, imsg);
1235 
1236 	if (profiling & PROFILE_IMSG)
1237 		clock_gettime(CLOCK_MONOTONIC, &t0);
1238 
1239 	msg = imsg->hdr.type;
1240 	imsg_callback(p, imsg);
1241 
1242 	if (profiling & PROFILE_IMSG) {
1243 		clock_gettime(CLOCK_MONOTONIC, &t1);
1244 		timespecsub(&t1, &t0, &dt);
1245 
1246 		log_debug("profile-imsg: %s %s %s %d %lld.%09ld",
1247 		    proc_name(smtpd_process),
1248 		    proc_name(p->proc),
1249 		    imsg_to_str(msg),
1250 		    (int)imsg->hdr.len,
1251 		    (long long)dt.tv_sec,
1252 		    dt.tv_nsec);
1253 
1254 		if (profiling & PROFILE_TOSTAT) {
1255 			char	key[STAT_KEY_SIZE];
1256 			/* can't profstat control process yet */
1257 			if (smtpd_process == PROC_CONTROL)
1258 				return;
1259 
1260 			if (! bsnprintf(key, sizeof key,
1261 				"profiling.imsg.%s.%s.%s",
1262 				proc_name(smtpd_process),
1263 				proc_name(p->proc),
1264 				imsg_to_str(msg)))
1265 				return;
1266 			stat_set(key, stat_timespec(&dt));
1267 		}
1268 	}
1269 }
1270 
1271 void
1272 log_imsg(int to, int from, struct imsg *imsg)
1273 {
1274 
1275 	if (to == PROC_CONTROL && imsg->hdr.type == IMSG_STAT_SET)
1276 		return;
1277 
1278 	if (imsg->fd != -1)
1279 		log_trace(TRACE_IMSG, "imsg: %s <- %s: %s (len=%zu, fd=%d)",
1280 		    proc_name(to),
1281 		    proc_name(from),
1282 		    imsg_to_str(imsg->hdr.type),
1283 		    imsg->hdr.len - IMSG_HEADER_SIZE,
1284 		    imsg->fd);
1285 	else
1286 		log_trace(TRACE_IMSG, "imsg: %s <- %s: %s (len=%zu)",
1287 		    proc_name(to),
1288 		    proc_name(from),
1289 		    imsg_to_str(imsg->hdr.type),
1290 		    imsg->hdr.len - IMSG_HEADER_SIZE);
1291 }
1292 
1293 const char *
1294 proc_title(enum smtp_proc_type proc)
1295 {
1296 	switch (proc) {
1297 	case PROC_PARENT:
1298 		return "[priv]";
1299 	case PROC_LKA:
1300 		return "lookup";
1301 	case PROC_QUEUE:
1302 		return "queue";
1303 	case PROC_CONTROL:
1304 		return "control";
1305 	case PROC_SCHEDULER:
1306 		return "scheduler";
1307 	case PROC_PONY:
1308 		return "pony express";
1309 	case PROC_CA:
1310 		return "klondike";
1311 	default:
1312 		return "unknown";
1313 	}
1314 }
1315 
1316 const char *
1317 proc_name(enum smtp_proc_type proc)
1318 {
1319 	switch (proc) {
1320 	case PROC_PARENT:
1321 		return "parent";
1322 	case PROC_LKA:
1323 		return "lka";
1324 	case PROC_QUEUE:
1325 		return "queue";
1326 	case PROC_CONTROL:
1327 		return "control";
1328 	case PROC_SCHEDULER:
1329 		return "scheduler";
1330 	case PROC_PONY:
1331 		return "pony";
1332 	case PROC_CA:
1333 		return "ca";
1334 	case PROC_FILTER:
1335 		return "filter-proc";
1336 	case PROC_CLIENT:
1337 		return "client-proc";
1338 	default:
1339 		return "unknown";
1340 	}
1341 }
1342 
1343 #define CASE(x) case x : return #x
1344 
1345 const char *
1346 imsg_to_str(int type)
1347 {
1348 	static char	 buf[32];
1349 
1350 	switch (type) {
1351 	CASE(IMSG_NONE);
1352 
1353 	CASE(IMSG_CTL_OK);
1354 	CASE(IMSG_CTL_FAIL);
1355 
1356 	CASE(IMSG_CTL_GET_DIGEST);
1357 	CASE(IMSG_CTL_GET_STATS);
1358 	CASE(IMSG_CTL_LIST_MESSAGES);
1359 	CASE(IMSG_CTL_LIST_ENVELOPES);
1360 	CASE(IMSG_CTL_MTA_SHOW_HOSTS);
1361 	CASE(IMSG_CTL_MTA_SHOW_RELAYS);
1362 	CASE(IMSG_CTL_MTA_SHOW_ROUTES);
1363 	CASE(IMSG_CTL_MTA_SHOW_HOSTSTATS);
1364 	CASE(IMSG_CTL_MTA_BLOCK);
1365 	CASE(IMSG_CTL_MTA_UNBLOCK);
1366 	CASE(IMSG_CTL_MTA_SHOW_BLOCK);
1367 	CASE(IMSG_CTL_PAUSE_EVP);
1368 	CASE(IMSG_CTL_PAUSE_MDA);
1369 	CASE(IMSG_CTL_PAUSE_MTA);
1370 	CASE(IMSG_CTL_PAUSE_SMTP);
1371 	CASE(IMSG_CTL_PROFILE);
1372 	CASE(IMSG_CTL_PROFILE_DISABLE);
1373 	CASE(IMSG_CTL_PROFILE_ENABLE);
1374 	CASE(IMSG_CTL_RESUME_EVP);
1375 	CASE(IMSG_CTL_RESUME_MDA);
1376 	CASE(IMSG_CTL_RESUME_MTA);
1377 	CASE(IMSG_CTL_RESUME_SMTP);
1378 	CASE(IMSG_CTL_RESUME_ROUTE);
1379 	CASE(IMSG_CTL_REMOVE);
1380 	CASE(IMSG_CTL_SCHEDULE);
1381 	CASE(IMSG_CTL_SHOW_STATUS);
1382 	CASE(IMSG_CTL_SHUTDOWN);
1383 	CASE(IMSG_CTL_TRACE_DISABLE);
1384 	CASE(IMSG_CTL_TRACE_ENABLE);
1385 	CASE(IMSG_CTL_UPDATE_TABLE);
1386 	CASE(IMSG_CTL_VERBOSE);
1387 
1388 	CASE(IMSG_CTL_SMTP_SESSION);
1389 
1390 	CASE(IMSG_CONF_START);
1391 	CASE(IMSG_CONF_END);
1392 
1393 	CASE(IMSG_STAT_INCREMENT);
1394 	CASE(IMSG_STAT_DECREMENT);
1395 	CASE(IMSG_STAT_SET);
1396 
1397 	CASE(IMSG_LKA_AUTHENTICATE);
1398 	CASE(IMSG_LKA_OPEN_FORWARD);
1399 	CASE(IMSG_LKA_ENVELOPE_SUBMIT);
1400 	CASE(IMSG_LKA_ENVELOPE_COMMIT);
1401 
1402 	CASE(IMSG_QUEUE_DELIVER);
1403 	CASE(IMSG_QUEUE_DELIVERY_OK);
1404 	CASE(IMSG_QUEUE_DELIVERY_TEMPFAIL);
1405 	CASE(IMSG_QUEUE_DELIVERY_PERMFAIL);
1406 	CASE(IMSG_QUEUE_DELIVERY_LOOP);
1407 	CASE(IMSG_QUEUE_ENVELOPE_ACK);
1408 	CASE(IMSG_QUEUE_ENVELOPE_COMMIT);
1409 	CASE(IMSG_QUEUE_ENVELOPE_REMOVE);
1410 	CASE(IMSG_QUEUE_ENVELOPE_SCHEDULE);
1411 	CASE(IMSG_QUEUE_ENVELOPE_SUBMIT);
1412 	CASE(IMSG_QUEUE_HOLDQ_HOLD);
1413 	CASE(IMSG_QUEUE_HOLDQ_RELEASE);
1414 	CASE(IMSG_QUEUE_MESSAGE_COMMIT);
1415 	CASE(IMSG_QUEUE_MESSAGE_ROLLBACK);
1416 	CASE(IMSG_QUEUE_SMTP_SESSION);
1417 	CASE(IMSG_QUEUE_TRANSFER);
1418 
1419 	CASE(IMSG_MDA_DELIVERY_OK);
1420 	CASE(IMSG_MDA_DELIVERY_TEMPFAIL);
1421 	CASE(IMSG_MDA_DELIVERY_PERMFAIL);
1422 	CASE(IMSG_MDA_DELIVERY_LOOP);
1423 	CASE(IMSG_MDA_DELIVERY_HOLD);
1424 	CASE(IMSG_MDA_DONE);
1425 	CASE(IMSG_MDA_FORK);
1426 	CASE(IMSG_MDA_HOLDQ_RELEASE);
1427 	CASE(IMSG_MDA_LOOKUP_USERINFO);
1428 	CASE(IMSG_MDA_KILL);
1429 	CASE(IMSG_MDA_OPEN_MESSAGE);
1430 
1431 	CASE(IMSG_MTA_DELIVERY_OK);
1432 	CASE(IMSG_MTA_DELIVERY_TEMPFAIL);
1433 	CASE(IMSG_MTA_DELIVERY_PERMFAIL);
1434 	CASE(IMSG_MTA_DELIVERY_LOOP);
1435 	CASE(IMSG_MTA_DELIVERY_HOLD);
1436 	CASE(IMSG_MTA_DNS_HOST);
1437 	CASE(IMSG_MTA_DNS_HOST_END);
1438 	CASE(IMSG_MTA_DNS_PTR);
1439 	CASE(IMSG_MTA_DNS_MX);
1440 	CASE(IMSG_MTA_DNS_MX_PREFERENCE);
1441 	CASE(IMSG_MTA_HOLDQ_RELEASE);
1442 	CASE(IMSG_MTA_LOOKUP_CREDENTIALS);
1443 	CASE(IMSG_MTA_LOOKUP_SOURCE);
1444 	CASE(IMSG_MTA_LOOKUP_HELO);
1445 	CASE(IMSG_MTA_OPEN_MESSAGE);
1446 	CASE(IMSG_MTA_SCHEDULE);
1447 	CASE(IMSG_MTA_SSL_INIT);
1448 	CASE(IMSG_MTA_SSL_VERIFY_CERT);
1449 	CASE(IMSG_MTA_SSL_VERIFY_CHAIN);
1450 	CASE(IMSG_MTA_SSL_VERIFY);
1451 
1452 	CASE(IMSG_SCHED_ENVELOPE_BOUNCE);
1453 	CASE(IMSG_SCHED_ENVELOPE_DELIVER);
1454 	CASE(IMSG_SCHED_ENVELOPE_EXPIRE);
1455 	CASE(IMSG_SCHED_ENVELOPE_INJECT);
1456 	CASE(IMSG_SCHED_ENVELOPE_REMOVE);
1457 	CASE(IMSG_SCHED_ENVELOPE_TRANSFER);
1458 
1459 	CASE(IMSG_SMTP_AUTHENTICATE);
1460 	CASE(IMSG_SMTP_DNS_PTR);
1461 	CASE(IMSG_SMTP_MESSAGE_COMMIT);
1462 	CASE(IMSG_SMTP_MESSAGE_CREATE);
1463 	CASE(IMSG_SMTP_MESSAGE_ROLLBACK);
1464 	CASE(IMSG_SMTP_MESSAGE_OPEN);
1465 	CASE(IMSG_SMTP_EXPAND_RCPT);
1466 	CASE(IMSG_SMTP_LOOKUP_HELO);
1467 	CASE(IMSG_SMTP_SSL_INIT);
1468 	CASE(IMSG_SMTP_SSL_VERIFY_CERT);
1469 	CASE(IMSG_SMTP_SSL_VERIFY_CHAIN);
1470 	CASE(IMSG_SMTP_SSL_VERIFY);
1471 
1472 	CASE(IMSG_SMTP_REQ_CONNECT);
1473 	CASE(IMSG_SMTP_REQ_HELO);
1474 	CASE(IMSG_SMTP_REQ_MAIL);
1475 	CASE(IMSG_SMTP_REQ_RCPT);
1476 	CASE(IMSG_SMTP_REQ_DATA);
1477 	CASE(IMSG_SMTP_REQ_EOM);
1478 	CASE(IMSG_SMTP_EVENT_RSET);
1479 	CASE(IMSG_SMTP_EVENT_COMMIT);
1480 	CASE(IMSG_SMTP_EVENT_ROLLBACK);
1481 	CASE(IMSG_SMTP_EVENT_DISCONNECT);
1482 
1483 	CASE(IMSG_CA_PRIVENC);
1484 	CASE(IMSG_CA_PRIVDEC);
1485 	default:
1486 		(void)snprintf(buf, sizeof(buf), "IMSG_??? (%d)", type);
1487 
1488 		return buf;
1489 	}
1490 }
1491 
1492 int
1493 parent_auth_user(const char *username, const char *password)
1494 {
1495 	char	user[LOGIN_NAME_MAX];
1496 	char	pass[LINE_MAX];
1497 	int	ret;
1498 
1499 	(void)strlcpy(user, username, sizeof(user));
1500 	(void)strlcpy(pass, password, sizeof(pass));
1501 
1502 	ret = auth_userokay(user, NULL, "auth-smtp", pass);
1503 	if (ret)
1504 		return LKA_OK;
1505 	return LKA_PERMFAIL;
1506 }
1507