xref: /openbsd-src/usr.sbin/smtpd/smtpd.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: smtpd.c,v 1.52 2009/04/03 05:20:17 oga Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/tree.h>
23 #include <sys/param.h>
24 #include <sys/socket.h>
25 #include <sys/wait.h>
26 #include <sys/stat.h>
27 #include <sys/uio.h>
28 #include <sys/resource.h>
29 
30 #include <bsd_auth.h>
31 #include <err.h>
32 #include <errno.h>
33 #include <event.h>
34 #include <fcntl.h>
35 #include <login_cap.h>
36 #include <paths.h>
37 #include <paths.h>
38 #include <pwd.h>
39 #include <regex.h>
40 #include <signal.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sysexits.h>
45 #include <time.h>
46 #include <unistd.h>
47 
48 #include <keynote.h>
49 
50 #include "smtpd.h"
51 
52 __dead void	usage(void);
53 void		parent_shutdown(void);
54 void		parent_send_config(int, short, void *);
55 void		parent_dispatch_lka(int, short, void *);
56 void		parent_dispatch_mda(int, short, void *);
57 void		parent_dispatch_mfa(int, short, void *);
58 void		parent_dispatch_smtp(int, short, void *);
59 void		parent_dispatch_control(int, short, void *);
60 void		parent_sig_handler(int, short, void *);
61 int		parent_open_message_file(struct batch *);
62 int		parent_mailbox_init(struct passwd *, char *);
63 int		parent_mailbox_open(char *, struct passwd *, struct batch *);
64 int		parent_filename_open(char *, struct passwd *, struct batch *);
65 int		parent_mailfile_rename(struct batch *, struct path *);
66 int		parent_maildir_open(char *, struct passwd *, struct batch *);
67 int		parent_maildir_init(struct passwd *, char *);
68 int		parent_external_mda(char *, struct passwd *, struct batch *);
69 int		parent_forward_open(char *);
70 int		check_child(pid_t, const char *);
71 int		setup_spool(uid_t, gid_t);
72 
73 extern char	**environ;
74 
75 pid_t	lka_pid = 0;
76 pid_t	mfa_pid = 0;
77 pid_t	queue_pid = 0;
78 pid_t	mda_pid = 0;
79 pid_t	mta_pid = 0;
80 pid_t	control_pid = 0;
81 pid_t	smtp_pid = 0;
82 pid_t	runner_pid = 0;
83 
84 struct s_parent	s_parent;
85 
86 int __b64_pton(char const *, unsigned char *, size_t);
87 
88 __dead void
89 usage(void)
90 {
91 	extern char	*__progname;
92 
93 	fprintf(stderr, "usage: %s [-dnv] [-D macro=value] "
94 	    "[-f file]\n", __progname);
95 	exit(1);
96 }
97 
98 void
99 parent_shutdown(void)
100 {
101 	u_int		i;
102 	pid_t		pid;
103 	pid_t		pids[] = {
104 		lka_pid,
105 		mfa_pid,
106 		queue_pid,
107 		mda_pid,
108 		mta_pid,
109 		control_pid,
110 		smtp_pid,
111 		runner_pid
112 	};
113 
114 	for (i = 0; i < sizeof(pids) / sizeof(pid); i++)
115 		if (pids[i])
116 			kill(pids[i], SIGTERM);
117 
118 	do {
119 		if ((pid = wait(NULL)) == -1 &&
120 		    errno != EINTR && errno != ECHILD)
121 			fatal("wait");
122 	} while (pid != -1 || (pid == -1 && errno == EINTR));
123 
124 	log_info("terminating");
125 	exit(0);
126 }
127 
128 void
129 parent_send_config(int fd, short event, void *p)
130 {
131 	struct smtpd		*env = p;
132 	struct iovec		iov[3];
133 	struct listener		*l;
134 	struct ssl		*s;
135 
136 	log_debug("parent_send_config: configuring smtp");
137 	imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_START,
138 	    0, 0, -1, NULL, 0);
139 
140 	SPLAY_FOREACH(s, ssltree, &env->sc_ssl) {
141 		iov[0].iov_base = s;
142 		iov[0].iov_len = sizeof(*s);
143 		iov[1].iov_base = s->ssl_cert;
144 		iov[1].iov_len = s->ssl_cert_len;
145 		iov[2].iov_base = s->ssl_key;
146 		iov[2].iov_len = s->ssl_key_len;
147 
148 		imsg_composev(env->sc_ibufs[PROC_SMTP], IMSG_CONF_SSL, 0, 0, -1,
149 		    iov, sizeof(iov)/sizeof(iov[0]));
150 	}
151 
152 	TAILQ_FOREACH(l, &env->sc_listeners, entry) {
153 		smtp_listener_setup(env, l);
154 		imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_LISTENER,
155 		    0, 0, l->fd, l, sizeof(*l));
156 	}
157 	imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_CONF_END,
158 	    0, 0, -1, NULL, 0);
159 }
160 
161 void
162 parent_dispatch_lka(int fd, short event, void *p)
163 {
164 	struct smtpd		*env = p;
165 	struct imsgbuf		*ibuf;
166 	struct imsg		 imsg;
167 	ssize_t			 n;
168 
169 	ibuf = env->sc_ibufs[PROC_LKA];
170 	switch (event) {
171 	case EV_READ:
172 		if ((n = imsg_read(ibuf)) == -1)
173 			fatal("imsg_read_error");
174 		if (n == 0) {
175 			/* this pipe is dead, so remove the event handler */
176 			event_del(&ibuf->ev);
177 			event_loopexit(NULL);
178 			return;
179 		}
180 		break;
181 	case EV_WRITE:
182 		if (msgbuf_write(&ibuf->w) == -1)
183 			fatal("msgbuf_write");
184 		imsg_event_add(ibuf);
185 		return;
186 	default:
187 		fatalx("unknown event");
188 	}
189 
190 	for (;;) {
191 		if ((n = imsg_get(ibuf, &imsg)) == -1)
192 			fatal("parent_dispatch_lka: imsg_read error");
193 		if (n == 0)
194 			break;
195 
196 		switch (imsg.hdr.type) {
197 		case IMSG_PARENT_FORWARD_OPEN: {
198 			int ret;
199 			struct forward_req *fwreq;
200 
201 			fwreq = imsg.data;
202 			ret = parent_forward_open(fwreq->pw_name);
203 			fwreq->status = 0;
204 			if (ret == -1) {
205 				if (errno == ENOENT)
206 					fwreq->status = 1;
207 			}
208 			imsg_compose(ibuf, IMSG_PARENT_FORWARD_OPEN, 0, 0, ret, fwreq, sizeof(*fwreq));
209 			break;
210 		}
211 		default:
212 			log_warnx("parent_dispatch_lka: got imsg %d",
213 			    imsg.hdr.type);
214 			fatalx("parent_dispatch_lka: unexpected imsg");
215 		}
216 		imsg_free(&imsg);
217 	}
218 	imsg_event_add(ibuf);
219 }
220 
221 void
222 parent_dispatch_mfa(int fd, short event, void *p)
223 {
224 	struct smtpd		*env = p;
225 	struct imsgbuf		*ibuf;
226 	struct imsg		 imsg;
227 	ssize_t			 n;
228 
229 	ibuf = env->sc_ibufs[PROC_MFA];
230 	switch (event) {
231 	case EV_READ:
232 		if ((n = imsg_read(ibuf)) == -1)
233 			fatal("imsg_read_error");
234 		if (n == 0) {
235 			/* this pipe is dead, so remove the event handler */
236 			event_del(&ibuf->ev);
237 			event_loopexit(NULL);
238 			return;
239 		}
240 		break;
241 	case EV_WRITE:
242 		if (msgbuf_write(&ibuf->w) == -1)
243 			fatal("msgbuf_write");
244 		imsg_event_add(ibuf);
245 		return;
246 	default:
247 		fatalx("unknown event");
248 	}
249 
250 	for (;;) {
251 		if ((n = imsg_get(ibuf, &imsg)) == -1)
252 			fatal("parent_dispatch_lka: imsg_read error");
253 		if (n == 0)
254 			break;
255 
256 		switch (imsg.hdr.type) {
257 		default:
258 			log_warnx("parent_dispatch_mfa: got imsg %d",
259 			    imsg.hdr.type);
260 			fatalx("parent_dispatch_mfa: unexpected imsg");
261 		}
262 		imsg_free(&imsg);
263 	}
264 	imsg_event_add(ibuf);
265 }
266 
267 void
268 parent_dispatch_mda(int fd, short event, void *p)
269 {
270 	struct smtpd		*env = p;
271 	struct imsgbuf		*ibuf;
272 	struct imsg		 imsg;
273 	ssize_t			 n;
274 
275 	ibuf = env->sc_ibufs[PROC_MDA];
276 	switch (event) {
277 	case EV_READ:
278 		if ((n = imsg_read(ibuf)) == -1)
279 			fatal("imsg_read_error");
280 		if (n == 0) {
281 			/* this pipe is dead, so remove the event handler */
282 			event_del(&ibuf->ev);
283 			event_loopexit(NULL);
284 			return;
285 		}
286 		break;
287 	case EV_WRITE:
288 		if (msgbuf_write(&ibuf->w) == -1)
289 			fatal("msgbuf_write");
290 		imsg_event_add(ibuf);
291 		return;
292 	default:
293 		fatalx("unknown event");
294 	}
295 
296 	for (;;) {
297 		if ((n = imsg_get(ibuf, &imsg)) == -1)
298 			fatal("parent_dispatch_mda: imsg_read error");
299 		if (n == 0)
300 			break;
301 
302 		switch (imsg.hdr.type) {
303 		case IMSG_PARENT_MAILBOX_OPEN: {
304 			struct batch *batchp;
305 			struct path *path;
306 			struct passwd *pw;
307 			char *pw_name;
308 			char *file;
309 			u_int8_t i;
310 			int desc;
311 			struct action_handler {
312 				enum action_type action;
313 				int (*handler)(char *, struct passwd *, struct batch *);
314 			} action_hdl_table[] = {
315 				{ A_MBOX,	parent_mailbox_open },
316 				{ A_MAILDIR,	parent_maildir_open },
317 				{ A_EXT,	parent_external_mda },
318 				{ A_FILENAME,	parent_filename_open }
319 			};
320 
321 			batchp = imsg.data;
322 			path = &batchp->message.recipient;
323 			if (batchp->type & T_DAEMON_BATCH) {
324 				path = &batchp->message.sender;
325 			}
326 
327 			for (i = 0; i < sizeof(action_hdl_table) / sizeof(struct action_handler); ++i)
328 				if (action_hdl_table[i].action == path->rule.r_action)
329 					break;
330 			if (i == sizeof(action_hdl_table) / sizeof(struct action_handler))
331 				fatalx("parent_dispatch_mda: unknown action");
332 
333 			file = path->rule.r_value.path;
334 			pw_name = path->pw_name;
335 			if (path->rule.r_action == A_FILENAME) {
336 				file = path->u.filename;
337 				pw_name = SMTPD_USER;
338 			}
339 
340 			errno = 0;
341 			pw = safe_getpwnam(pw_name);
342 			if (pw == NULL) {
343 				if (errno)
344 					batchp->message.status |= S_MESSAGE_TEMPFAILURE;
345 				else
346 					batchp->message.status |= S_MESSAGE_PERMFAILURE;
347 				imsg_compose(ibuf, IMSG_MDA_MAILBOX_FILE, 0, 0,
348 				    -1, batchp, sizeof(struct batch));
349 				break;
350 			}
351 
352 			if (setegid(pw->pw_gid) || seteuid(pw->pw_uid))
353 				fatal("privdrop failed");
354 
355 			desc = action_hdl_table[i].handler(file, pw, batchp);
356 			imsg_compose(ibuf, IMSG_MDA_MAILBOX_FILE, 0, 0,
357 			    desc, batchp, sizeof(struct batch));
358 
359 			if (setegid(0) || seteuid(0))
360 				fatal("privdrop failed");
361 
362 			break;
363 		}
364 		case IMSG_PARENT_MESSAGE_OPEN: {
365 			struct batch *batchp;
366 			int desc;
367 
368 			batchp = imsg.data;
369 			desc = parent_open_message_file(batchp);
370 
371 			imsg_compose(ibuf, IMSG_MDA_MESSAGE_FILE, 0, 0,
372 			    desc, batchp, sizeof(struct batch));
373 
374 			break;
375 		}
376 		case IMSG_PARENT_MAILBOX_RENAME: {
377 			struct batch *batchp;
378 			struct path *path;
379 			struct passwd *pw;
380 
381 			batchp = imsg.data;
382 			path = &batchp->message.recipient;
383 			if (batchp->type & T_DAEMON_BATCH) {
384 				path = &batchp->message.sender;
385 			}
386 
387 			pw = safe_getpwnam(path->pw_name);
388 			if (pw == NULL)
389 				break;
390 
391 			if (seteuid(pw->pw_uid) == -1)
392 				fatal("privdrop failed");
393 
394 			parent_mailfile_rename(batchp, path);
395 
396 			if (seteuid(0) == -1)
397 				fatal("privraise failed");
398 
399 			break;
400 		}
401 		default:
402 			log_warnx("parent_dispatch_mfa: got imsg %d",
403 			    imsg.hdr.type);
404 			fatalx("parent_dispatch_mda: unexpected imsg");
405 		}
406 		imsg_free(&imsg);
407 	}
408 	imsg_event_add(ibuf);
409 }
410 
411 void
412 parent_dispatch_smtp(int fd, short event, void *p)
413 {
414 	struct smtpd		*env = p;
415 	struct imsgbuf		*ibuf;
416 	struct imsg		 imsg;
417 	ssize_t			 n;
418 
419 	ibuf = env->sc_ibufs[PROC_SMTP];
420 	switch (event) {
421 	case EV_READ:
422 		if ((n = imsg_read(ibuf)) == -1)
423 			fatal("imsg_read_error");
424 		if (n == 0) {
425 			/* this pipe is dead, so remove the event handler */
426 			event_del(&ibuf->ev);
427 			event_loopexit(NULL);
428 			return;
429 		}
430 		break;
431 	case EV_WRITE:
432 		if (msgbuf_write(&ibuf->w) == -1)
433 			fatal("msgbuf_write");
434 		imsg_event_add(ibuf);
435 		return;
436 	default:
437 		fatalx("unknown event");
438 	}
439 
440 	for (;;) {
441 		if ((n = imsg_get(ibuf, &imsg)) == -1)
442 			fatal("parent_dispatch_smtp: imsg_read error");
443 		if (n == 0)
444 			break;
445 
446 		switch (imsg.hdr.type) {
447 		case IMSG_PARENT_SEND_CONFIG: {
448 			parent_send_config(-1, -1, env);
449 			break;
450 		}
451 		case IMSG_PARENT_AUTHENTICATE: {
452 			struct session_auth_req *req;
453 			struct session_auth_reply reply;
454 			char buf[1024];
455 			char *user;
456 			char *pass;
457 			int len;
458 
459 			req = (struct session_auth_req *)imsg.data;
460 
461 			reply.session_id = req->session_id;
462 			reply.value = 0;
463 
464 			/* String is not NUL terminated, leave room. */
465 			if ((len = kn_decode_base64(req->buffer, buf,
466 			    sizeof(buf) - 1)) == -1)
467 				goto out;
468 			/* buf is a byte string, NUL terminate. */
469 			buf[len] = '\0';
470 
471 			/*
472 			 * Skip "foo" in "foo\0user\0pass", if present.
473 			 */
474 			user = memchr(buf, '\0', len);
475 			if (user == NULL || user >= buf + len - 2)
476 				goto out;
477 			user++; /* skip NUL */
478 
479 			pass = memchr(user, '\0', len - (user - buf));
480 			if (pass == NULL || pass >= buf + len - 2)
481 				goto out;
482 			pass++; /* skip NUL */
483 
484 			if (auth_userokay(user, NULL, "auth-smtp", pass))
485 				reply.value = 1;
486 
487 out:
488 			imsg_compose(ibuf, IMSG_PARENT_AUTHENTICATE, 0, 0,
489 			    -1, &reply, sizeof(reply));
490 
491 			break;
492 		}
493 		default:
494 			log_warnx("parent_dispatch_smtp: got imsg %d",
495 			    imsg.hdr.type);
496 			fatalx("parent_dispatch_smtp: unexpected imsg");
497 		}
498 		imsg_free(&imsg);
499 	}
500 	imsg_event_add(ibuf);
501 }
502 
503 void
504 parent_dispatch_control(int sig, short event, void *p)
505 {
506 	struct smtpd		*env = p;
507 	struct imsgbuf		*ibuf;
508 	struct imsg		 imsg;
509 	ssize_t			 n;
510 
511 	ibuf = env->sc_ibufs[PROC_CONTROL];
512 	switch (event) {
513 	case EV_READ:
514 		if ((n = imsg_read(ibuf)) == -1)
515 			fatal("imsg_read_error");
516 		if (n == 0) {
517 			/* this pipe is dead, so remove the event handler */
518 			event_del(&ibuf->ev);
519 			event_loopexit(NULL);
520 			return;
521 		}
522 		break;
523 	case EV_WRITE:
524 		if (msgbuf_write(&ibuf->w) == -1)
525 			fatal("msgbuf_write");
526 		imsg_event_add(ibuf);
527 		return;
528 	default:
529 		fatalx("unknown event");
530 	}
531 
532 	for (;;) {
533 		if ((n = imsg_get(ibuf, &imsg)) == -1)
534 			fatal("parent_dispatch_control: imsg_read error");
535 		if (n == 0)
536 			break;
537 
538 		switch (imsg.hdr.type) {
539 		case IMSG_STATS: {
540 			struct stats *s;
541 
542 			s = imsg.data;
543 			s->u.parent = s_parent;
544 			imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s));
545 			break;
546 		}
547 		default:
548 			log_warnx("parent_dispatch_control: got imsg %d",
549 			    imsg.hdr.type);
550 			fatalx("parent_dispatch_control: unexpected imsg");
551 		}
552 		imsg_free(&imsg);
553 	}
554 	imsg_event_add(ibuf);
555 }
556 
557 void
558 parent_sig_handler(int sig, short event, void *p)
559 {
560 	int					 i;
561 	int					 die = 0;
562 	pid_t					 pid;
563 	struct mdaproc				*mdaproc;
564 	struct mdaproc				 lookup;
565 	struct smtpd				*env = p;
566 	struct { pid_t p; const char *s; }	 procs[] = {
567 		{ lka_pid,	"lookup agent" },
568 		{ mfa_pid,	"mail filter agent" },
569 		{ queue_pid,	"mail queue" },
570 		{ mda_pid,	"mail delivery agent" },
571 		{ mta_pid,	"mail transfer agent" },
572 		{ control_pid,	"control process" },
573 		{ smtp_pid,	"smtp server" },
574 		{ runner_pid,	"runner" },
575 		{ 0,		NULL },
576 	};
577 
578 	switch (sig) {
579 	case SIGTERM:
580 	case SIGINT:
581 		die = 1;
582 		/* FALLTHROUGH */
583 	case SIGCHLD:
584 		for (i = 0; procs[i].s != NULL; i++)
585 			if (check_child(procs[i].p, procs[i].s)) {
586 				procs[i].p = 0;
587 				die = 1;
588 			}
589 		if (die)
590 			parent_shutdown();
591 
592 		do {
593 			int status;
594 
595 			pid = waitpid(-1, &status, WNOHANG);
596 			if (pid > 0) {
597 				lookup.pid = pid;
598 				mdaproc = SPLAY_FIND(mdaproctree, &env->mdaproc_queue, &lookup);
599 				if (mdaproc == NULL)
600 					fatalx("unexpected SIGCHLD");
601 
602 				if (WIFEXITED(status) && !WIFSIGNALED(status)) {
603 					switch (WEXITSTATUS(status)) {
604 					case EX_OK:
605 						log_debug("DEBUG: external mda reported success");
606 						break;
607 					case EX_TEMPFAIL:
608 						log_debug("DEBUG: external mda reported temporary failure");
609 						break;
610 					default:
611 						log_warnx("external mda returned %d", WEXITSTATUS(status));
612 					}
613 				}
614 				else {
615 					log_warnx("external mda terminated abnormally");
616 				}
617 
618 				SPLAY_REMOVE(mdaproctree, &env->mdaproc_queue,
619 				    mdaproc);
620 				free(mdaproc);
621 			}
622 		} while (pid > 0 || (pid == -1 && errno == EINTR));
623 
624 		break;
625 	default:
626 		fatalx("unexpected signal");
627 	}
628 }
629 
630 int
631 main(int argc, char *argv[])
632 {
633 	int		 c;
634 	int		 debug;
635 	int		 opts;
636 	const char	*conffile = CONF_FILE;
637 	struct smtpd	 env;
638 	struct event	 ev_sigint;
639 	struct event	 ev_sigterm;
640 	struct event	 ev_sigchld;
641 	struct event	 ev_sighup;
642 	struct timeval	 tv;
643 	struct rlimit	 rl;
644 	struct peer	 peers[] = {
645 		{ PROC_CONTROL,	parent_dispatch_control },
646 		{ PROC_LKA,	parent_dispatch_lka },
647 		{ PROC_MDA,	parent_dispatch_mda },
648 		{ PROC_MFA,	parent_dispatch_mfa },
649 		{ PROC_SMTP,	parent_dispatch_smtp },
650 	};
651 
652 	opts = 0;
653 	debug = 0;
654 
655 	log_init(1);
656 
657 	while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
658 		switch (c) {
659 		case 'd':
660 			debug = 2;
661 			break;
662 		case 'D':
663 			if (cmdline_symset(optarg) < 0)
664 				log_warnx("could not parse macro definition %s",
665 				    optarg);
666 			break;
667 		case 'n':
668 			debug = 2;
669 			opts |= SMTPD_OPT_NOACTION;
670 			break;
671 		case 'f':
672 			conffile = optarg;
673 			break;
674 		case 'v':
675 			opts |= SMTPD_OPT_VERBOSE;
676 			break;
677 		default:
678 			usage();
679 		}
680 	}
681 
682 	argv += optind;
683 	argc -= optind;
684 
685 	if (parse_config(&env, conffile, opts))
686 		exit(1);
687 
688 	if (env.sc_opts & SMTPD_OPT_NOACTION) {
689 		fprintf(stderr, "configuration OK\n");
690 		exit(0);
691 	}
692 
693 	/* check for root privileges */
694 	if (geteuid())
695 		errx(1, "need root privileges");
696 
697 	if ((env.sc_pw =  getpwnam(SMTPD_USER)) == NULL)
698 		errx(1, "unknown user %s", SMTPD_USER);
699 	endpwent();
700 
701 	if (!setup_spool(env.sc_pw->pw_uid, 0))
702 		errx(1, "invalid directory permissions");
703 
704 	log_init(debug);
705 
706 	if (!debug)
707 		if (daemon(0, 0) == -1)
708 			err(1, "failed to daemonize");
709 
710 	log_info("startup%s", (debug > 1)?" [debug mode]":"");
711 
712 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
713 		fatal("smtpd: failed to get resource limit");
714 
715 	log_debug("smtpd: max open files %lld", rl.rlim_max);
716 
717 	/*
718 	 * Allow the maximum number of open file descriptors for this
719 	 * login class (which should be the class "daemon" by default).
720 	 */
721 	rl.rlim_cur = rl.rlim_max;
722 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
723 		fatal("smtpd: failed to set resource limit");
724 
725 	env.sc_maxconn = (rl.rlim_cur / 4) * 3;
726 	log_debug("smtpd: will accept at most %d clients", env.sc_maxconn);
727 
728 	env.sc_instances[PROC_PARENT] = 1;
729 	env.sc_instances[PROC_LKA] = 1;
730 	env.sc_instances[PROC_MFA] = 1;
731 	env.sc_instances[PROC_QUEUE] = 1;
732 	env.sc_instances[PROC_MDA] = 1;
733 	env.sc_instances[PROC_MTA] = 1;
734 	env.sc_instances[PROC_SMTP] = 1;
735 	env.sc_instances[PROC_CONTROL] = 1;
736 	env.sc_instances[PROC_RUNNER] = 1;
737 
738 	init_peers(&env);
739 
740 	/* start subprocesses */
741 	lka_pid = lka(&env);
742 	mfa_pid = mfa(&env);
743 	queue_pid = queue(&env);
744 	mda_pid = mda(&env);
745 	mta_pid = mta(&env);
746 	smtp_pid = smtp(&env);
747 	control_pid = control(&env);
748 	runner_pid = runner(&env);
749 
750 	setproctitle("parent");
751 	SPLAY_INIT(&env.mdaproc_queue);
752 
753 	s_parent.start = time(NULL);
754 
755 	event_init();
756 
757 	signal_set(&ev_sigint, SIGINT, parent_sig_handler, &env);
758 	signal_set(&ev_sigterm, SIGTERM, parent_sig_handler, &env);
759 	signal_set(&ev_sigchld, SIGCHLD, parent_sig_handler, &env);
760 	signal_set(&ev_sighup, SIGHUP, parent_sig_handler, &env);
761 	signal_add(&ev_sigint, NULL);
762 	signal_add(&ev_sigterm, NULL);
763 	signal_add(&ev_sigchld, NULL);
764 	signal_add(&ev_sighup, NULL);
765 	signal(SIGPIPE, SIG_IGN);
766 
767 	config_pipes(&env, peers, 5);
768 	config_peers(&env, peers, 5);
769 
770 	evtimer_set(&env.sc_ev, parent_send_config, &env);
771 	bzero(&tv, sizeof(tv));
772 	evtimer_add(&env.sc_ev, &tv);
773 
774 	event_dispatch();
775 
776 	return (0);
777 }
778 
779 
780 int
781 check_child(pid_t pid, const char *pname)
782 {
783 	int	status;
784 
785 	if (waitpid(pid, &status, WNOHANG) > 0) {
786 		if (WIFEXITED(status)) {
787 			log_warnx("check_child: lost child: %s exited", pname);
788 			return (1);
789 		}
790 		if (WIFSIGNALED(status)) {
791 			log_warnx("check_child: lost child: %s terminated; "
792 			    "signal %d", pname, WTERMSIG(status));
793 			return (1);
794 		}
795 	}
796 
797 	return (0);
798 }
799 
800 int
801 setup_spool(uid_t uid, gid_t gid)
802 {
803 	unsigned int	 n;
804 	char		*paths[] = { PATH_INCOMING, PATH_ENQUEUE, PATH_QUEUE,
805 				     PATH_RUNQUEUE, PATH_RUNQUEUELOW,
806 				     PATH_RUNQUEUEHIGH, PATH_PURGE };
807 	char		 pathname[MAXPATHLEN];
808 	struct stat	 sb;
809 	int		 ret;
810 
811 	if (! bsnprintf(pathname, sizeof(pathname), "%s", PATH_SPOOL))
812 		fatal("snprintf");
813 
814 	if (stat(pathname, &sb) == -1) {
815 		if (errno != ENOENT) {
816 			warn("stat: %s", pathname);
817 			return 0;
818 		}
819 
820 		if (mkdir(pathname, 0711) == -1) {
821 			warn("mkdir: %s", pathname);
822 			return 0;
823 		}
824 
825 		if (chown(pathname, 0, 0) == -1) {
826 			warn("chown: %s", pathname);
827 			return 0;
828 		}
829 
830 		if (stat(pathname, &sb) == -1)
831 			err(1, "stat: %s", pathname);
832 	}
833 
834 	/* check if it's a directory */
835 	if (!S_ISDIR(sb.st_mode)) {
836 		warnx("%s is not a directory", pathname);
837 		return 0;
838 	}
839 
840 	/* check that it is owned by uid/gid */
841 	if (sb.st_uid != 0 || sb.st_gid != 0) {
842 		warnx("%s must be owned by root:wheel", pathname);
843 		return 0;
844 	}
845 
846 	/* check permission */
847 	if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) ||
848 	    (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) != S_IXGRP ||
849 	    (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH)) != S_IXOTH) {
850 		warnx("%s must be rwx--x--x (0711)", pathname);
851 		return 0;
852 	}
853 
854 	ret = 1;
855 	for (n = 0; n < sizeof(paths)/sizeof(paths[0]); n++) {
856 		if (! bsnprintf(pathname, sizeof(pathname), "%s%s", PATH_SPOOL,
857 			paths[n]))
858 			fatal("snprintf");
859 
860 		if (stat(pathname, &sb) == -1) {
861 			if (errno != ENOENT) {
862 				warn("stat: %s", pathname);
863 				ret = 0;
864 				continue;
865 			}
866 
867 			if (mkdir(pathname, 0700) == -1) {
868 				ret = 0;
869 				warn("mkdir: %s", pathname);
870 			}
871 
872 			if (chown(pathname, uid, gid) == -1) {
873 				ret = 0;
874 				warn("chown: %s", pathname);
875 			}
876 
877 			if (stat(pathname, &sb) == -1)
878 				err(1, "stat: %s", pathname);
879 		}
880 
881 		/* check if it's a directory */
882 		if (!S_ISDIR(sb.st_mode)) {
883 			ret = 0;
884 			warnx("%s is not a directory", pathname);
885 		}
886 
887 		/* check that it is owned by uid/gid */
888 		if (sb.st_uid != uid) {
889 			ret = 0;
890 			warnx("%s is not owned by uid %d", pathname, uid);
891 		}
892 		if (sb.st_gid != gid) {
893 			ret = 0;
894 			warnx("%s is not owned by gid %d", pathname, gid);
895 		}
896 
897 		/* check permission */
898 		if ((sb.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR)) != (S_IRUSR|S_IWUSR|S_IXUSR) ||
899 		    (sb.st_mode & (S_IRGRP|S_IWGRP|S_IXGRP)) ||
900 		    (sb.st_mode & (S_IROTH|S_IWOTH|S_IXOTH))) {
901 			ret = 0;
902 			warnx("%s must be rwx------ (0700)", pathname);
903 		}
904 	}
905 	return ret;
906 }
907 
908 void
909 imsg_event_add(struct imsgbuf *ibuf)
910 {
911 	if (ibuf->handler == NULL) {
912 		imsg_flush(ibuf);
913 		return;
914 	}
915 
916 	ibuf->events = EV_READ;
917 	if (ibuf->w.queued)
918 		ibuf->events |= EV_WRITE;
919 
920 	event_del(&ibuf->ev);
921 	event_set(&ibuf->ev, ibuf->fd, ibuf->events, ibuf->handler, ibuf->data);
922 	event_add(&ibuf->ev, NULL);
923 }
924 
925 int
926 parent_open_message_file(struct batch *batchp)
927 {
928 	int fd;
929 	char pathname[MAXPATHLEN];
930 	u_int16_t hval;
931 	struct message *messagep;
932 
933 	messagep = &batchp->message;
934 	hval = queue_hash(messagep->message_id);
935 
936 	if (! bsnprintf(pathname, sizeof(pathname), "%s%s/%d/%s/message",
937 		PATH_SPOOL, PATH_QUEUE, hval, batchp->message_id)) {
938 		batchp->message.status |= S_MESSAGE_PERMFAILURE;
939 		return -1;
940 	}
941 
942 	fd = open(pathname, O_RDONLY);
943 	return fd;
944 }
945 
946 int
947 parent_mailbox_init(struct passwd *pw, char *pathname)
948 {
949 	int fd;
950 	int ret = 1;
951 	int mode = O_CREAT|O_EXCL;
952 
953 	/* user cannot create mailbox */
954 	if (seteuid(0) == -1)
955 		fatal("privraise failed");
956 
957 	errno = 0;
958 	fd = open(pathname, mode, 0600);
959 
960 	if (fd == -1) {
961 		if (errno != EEXIST)
962 			ret = 0;
963 	}
964 
965 	if (fd != -1) {
966 		if (fchown(fd, pw->pw_uid, 0) == -1)
967 			fatal("fchown");
968 		close(fd);
969 	}
970 
971 	if (seteuid(pw->pw_uid) == -1)
972 		fatal("privdropfailed");
973 
974 	return ret;
975 }
976 
977 int
978 parent_mailbox_open(char *path, struct passwd *pw, struct batch *batchp)
979 {
980 	pid_t pid;
981 	int pipefd[2];
982 	struct mdaproc *mdaproc;
983 	char sender[MAX_PATH_SIZE];
984 
985 	/* This can never happen, but better safe than sorry. */
986 	if (! bsnprintf(sender, MAX_PATH_SIZE, "%s@%s",
987 		batchp->message.sender.user,
988 		batchp->message.sender.domain)) {
989 		batchp->message.status |= S_MESSAGE_PERMFAILURE;
990 		return -1;
991 	}
992 
993 	if (! parent_mailbox_init(pw, path)) {
994 		batchp->message.status |= S_MESSAGE_TEMPFAILURE;
995 		return -1;
996 	}
997 
998 	log_debug("executing mail.local");
999 
1000 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) == -1) {
1001 		batchp->message.status |= S_MESSAGE_PERMFAILURE;
1002 		return -1;
1003 	}
1004 
1005 	/* raise privileges because mail.local needs root to
1006 	 * deliver to user mailboxes.
1007 	 */
1008 	if (seteuid(0) == -1)
1009 		fatal("privraise failed");
1010 
1011 	pid = fork();
1012 	if (pid == -1) {
1013 		close(pipefd[0]);
1014 		close(pipefd[1]);
1015 		batchp->message.status |= S_MESSAGE_PERMFAILURE;
1016 		return -1;
1017 	}
1018 
1019 	if (pid == 0) {
1020 		setproctitle("mail.local");
1021 
1022 		close(pipefd[0]);
1023 		close(STDOUT_FILENO);
1024 		close(STDERR_FILENO);
1025 		dup2(pipefd[1], 0);
1026 
1027 		execlp(PATH_MAILLOCAL, "mail.local", "-f", sender, pw->pw_name, (void *)NULL);
1028 		_exit(1);
1029 	}
1030 
1031 	if (seteuid(pw->pw_uid) == -1)
1032 		fatal("privdrop failed");
1033 
1034 	mdaproc = calloc(1, sizeof (struct mdaproc));
1035 	if (mdaproc == NULL)
1036 		fatal("calloc");
1037 	mdaproc->pid = pid;
1038 
1039 	SPLAY_INSERT(mdaproctree, &batchp->env->mdaproc_queue, mdaproc);
1040 
1041 	close(pipefd[1]);
1042 	return pipefd[0];
1043 }
1044 
1045 int
1046 parent_maildir_init(struct passwd *pw, char *root)
1047 {
1048 	u_int8_t i;
1049 	char pathname[MAXPATHLEN];
1050 	char *subdir[] = { "/", "/tmp", "/cur", "/new" };
1051 
1052 	for (i = 0; i < sizeof (subdir) / sizeof (char *); ++i) {
1053 		if (! bsnprintf(pathname, sizeof(pathname), "%s%s", root,
1054 			subdir[i]))
1055 			return 0;
1056 		if (mkdir(pathname, 0700) == -1)
1057 			if (errno != EEXIST)
1058 				return 0;
1059 	}
1060 
1061 	return 1;
1062 }
1063 
1064 int
1065 parent_maildir_open(char *path, struct passwd *pw, struct batch *batchp)
1066 {
1067 	int fd;
1068 	char tmp[MAXPATHLEN];
1069 	int mode = O_CREAT|O_RDWR|O_TRUNC|O_SYNC;
1070 
1071 	if (! parent_maildir_init(pw, path)) {
1072 		batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1073 		return -1;
1074 	}
1075 
1076 	if (! bsnprintf(tmp, sizeof(tmp), "%s/tmp/%s", path,
1077 		batchp->message.message_uid)) {
1078 		batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1079 		return -1;
1080 	}
1081 
1082 	fd = open(tmp, mode, 0600);
1083 	if (fd == -1) {
1084 		batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1085 		return -1;
1086 	}
1087 
1088 	return fd;
1089 }
1090 
1091 int
1092 parent_mailfile_rename(struct batch *batchp, struct path *path)
1093 {
1094 	char srcpath[MAXPATHLEN];
1095 	char dstpath[MAXPATHLEN];
1096 
1097 	if (! bsnprintf(srcpath, sizeof(srcpath), "%s/tmp/%s",
1098 		path->rule.r_value.path, batchp->message.message_uid) ||
1099 	    ! bsnprintf(dstpath, sizeof(dstpath), "%s/new/%s",
1100 		path->rule.r_value.path, batchp->message.message_uid))
1101 		return 0;
1102 
1103 	if (rename(srcpath, dstpath) == -1) {
1104 		if (unlink(srcpath) == -1)
1105 			fatal("unlink");
1106 		batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1107 		return 0;
1108 	}
1109 
1110 	return 1;
1111 }
1112 
1113 int
1114 parent_external_mda(char *path, struct passwd *pw, struct batch *batchp)
1115 {
1116 	pid_t pid;
1117 	int pipefd[2];
1118 	arglist args;
1119 	char *word;
1120 	struct mdaproc *mdaproc;
1121 	char *envp[2];
1122 
1123 	log_debug("executing filter as user: %s", pw->pw_name);
1124 
1125 	if (pipe(pipefd) == -1) {
1126 		if (errno == ENFILE) {
1127 			log_warn("parent_external_mda: pipe");
1128 			batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1129 			return -1;
1130 		}
1131 		fatal("parent_external_mda: pipe");
1132 	}
1133 
1134 	pid = fork();
1135 	if (pid == -1) {
1136 		log_warn("parent_external_mda: fork");
1137 		close(pipefd[0]);
1138 		close(pipefd[1]);
1139 		batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1140 		return -1;
1141 	}
1142 
1143 	if (pid == 0) {
1144 		setproctitle("external MDA");
1145 
1146 		if (seteuid(0) == -1)
1147 			fatal("privraise failed");
1148 		if (setgroups(1, &pw->pw_gid) ||
1149 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
1150 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
1151 			fatal("cannot drop privileges");
1152 
1153 		bzero(&args, sizeof(args));
1154 		while ((word = strsep(&path, " \t")) != NULL)
1155 			if (*word != '\0')
1156 				addargs(&args, "%s", word);
1157 
1158 		if (setsid() == -1)
1159 			fatal("setsid");
1160 
1161 		if (signal(SIGPIPE, SIG_DFL) == SIG_ERR)
1162 			fatal("signal");
1163 
1164 		if (dup2(pipefd[0], STDIN_FILENO) == -1)
1165 			fatal("dup2");
1166 
1167 		if (chdir(pw->pw_dir) == -1 && chdir("/") == -1)
1168 			fatal("chdir");
1169 
1170 		if (closefrom(STDERR_FILENO + 1) == -1)
1171 			fatal("closefrom");
1172 
1173 		envp[0] = "PATH=" _PATH_DEFPATH;
1174 		envp[1] = (char *)NULL;
1175 		environ = envp;
1176 
1177 		execvp(args.list[0], args.list);
1178 		_exit(1);
1179 	}
1180 
1181 	mdaproc = calloc(1, sizeof (struct mdaproc));
1182 	if (mdaproc == NULL)
1183 		fatal("calloc");
1184 	mdaproc->pid = pid;
1185 
1186 	SPLAY_INSERT(mdaproctree, &batchp->env->mdaproc_queue, mdaproc);
1187 
1188 	close(pipefd[0]);
1189 	return pipefd[1];
1190 }
1191 
1192 int
1193 parent_filename_open(char *path, struct passwd *pw, struct batch *batchp)
1194 {
1195 	int fd;
1196 	int mode = O_CREAT|O_APPEND|O_RDWR|O_SYNC|O_NONBLOCK;
1197 
1198 	fd = open(path, mode, 0600);
1199 	if (fd == -1) {
1200 		/* XXX - this needs to be discussed ... */
1201 		switch (errno) {
1202 		case ENOTDIR:
1203 		case ENOENT:
1204 		case EACCES:
1205 		case ELOOP:
1206 		case EROFS:
1207 		case EDQUOT:
1208 		case EINTR:
1209 		case EIO:
1210 		case EMFILE:
1211 		case ENFILE:
1212 		case ENOSPC:
1213 			batchp->message.status |= S_MESSAGE_TEMPFAILURE;
1214 			break;
1215 		case EWOULDBLOCK:
1216 			goto lockfail;
1217 		default:
1218 			batchp->message.status |= S_MESSAGE_PERMFAILURE;
1219 		}
1220 		return -1;
1221 	}
1222 
1223 	if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
1224 		if (errno == EWOULDBLOCK)
1225 			goto lockfail;
1226 		fatal("flock");
1227 	}
1228 
1229 	return fd;
1230 
1231 lockfail:
1232 	if (fd != -1)
1233 		close(fd);
1234 
1235 	batchp->message.status |= S_MESSAGE_TEMPFAILURE|S_MESSAGE_LOCKFAILURE;
1236 	return -1;
1237 }
1238 
1239 int
1240 parent_forward_open(char *username)
1241 {
1242 	struct passwd *pw;
1243 	struct stat sb;
1244 	char pathname[MAXPATHLEN];
1245 	int fd;
1246 
1247 	pw = safe_getpwnam(username);
1248 	if (pw == NULL)
1249 		return -1;
1250 
1251 	if (! bsnprintf(pathname, sizeof (pathname), "%s/.forward", pw->pw_dir))
1252 		return -1;
1253 
1254 	fd = open(pathname, O_RDONLY);
1255 	if (fd == -1) {
1256 		if (errno == ENOENT)
1257 			goto err;
1258 		return -1;
1259 	}
1260 
1261 	/* make sure ~/ is not writable by anyone but owner */
1262 	if (stat(pw->pw_dir, &sb) == -1)
1263 		goto errlog;
1264 
1265 	if (sb.st_uid != pw->pw_uid || sb.st_mode & (S_IWGRP|S_IWOTH))
1266 		goto errlog;
1267 
1268 	/* make sure ~/.forward is not writable by anyone but owner */
1269 	if (fstat(fd, &sb) == -1)
1270 		goto errlog;
1271 
1272 	if (sb.st_uid != pw->pw_uid || sb.st_mode & (S_IWGRP|S_IWOTH))
1273 		goto errlog;
1274 
1275 	return fd;
1276 
1277 errlog:
1278 	log_info("cannot process forward file for user %s due to wrong permissions", username);
1279 
1280 err:
1281 	return -1;
1282 }
1283 
1284 int
1285 mdaproc_cmp(struct mdaproc *s1, struct mdaproc *s2)
1286 {
1287 	if (s1->pid < s2->pid)
1288 		return (-1);
1289 
1290 	if (s1->pid > s2->pid)
1291 		return (1);
1292 
1293 	return (0);
1294 }
1295 
1296 SPLAY_GENERATE(mdaproctree, mdaproc, mdaproc_nodes, mdaproc_cmp);
1297