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