dispatcher.c revision 1.3
1/*	$OpenBSD: dispatcher.c,v 1.3 2021/04/21 07:54:10 eric Exp $	*/
2
3/*
4 * Copyright (c) 2014 Gilles Chehade <gilles@poolp.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/queue.h>
21#include <sys/tree.h>
22#include <sys/socket.h>
23
24#include <ctype.h>
25#include <err.h>
26#include <errno.h>
27#include <event.h>
28#include <imsg.h>
29#include <inttypes.h>
30#include <pwd.h>
31#include <signal.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <time.h>
36#include <unistd.h>
37#include <limits.h>
38#include <grp.h>
39
40#include "smtpd.h"
41#include "log.h"
42
43void mda_imsg(struct mproc *, struct imsg *);
44void mta_imsg(struct mproc *, struct imsg *);
45void smtp_imsg(struct mproc *, struct imsg *);
46
47static void dispatcher_shutdown(void);
48
49void
50dispatcher_imsg(struct mproc *p, struct imsg *imsg)
51{
52	struct msg	m;
53	int		v;
54
55	if (imsg == NULL)
56		dispatcher_shutdown();
57
58	switch (imsg->hdr.type) {
59
60	case IMSG_GETADDRINFO:
61	case IMSG_GETADDRINFO_END:
62	case IMSG_GETNAMEINFO:
63	case IMSG_RES_QUERY:
64		resolver_dispatch_result(p, imsg);
65		return;
66
67	case IMSG_CONF_START:
68		return;
69	case IMSG_CONF_END:
70		smtp_configure();
71		return;
72	case IMSG_CTL_VERBOSE:
73		m_msg(&m, imsg);
74		m_get_int(&m, &v);
75		m_end(&m);
76		log_trace_verbose(v);
77		return;
78	case IMSG_CTL_PROFILE:
79		m_msg(&m, imsg);
80		m_get_int(&m, &v);
81		m_end(&m);
82		profiling = v;
83		return;
84
85	/* smtp imsg */
86	case IMSG_SMTP_CHECK_SENDER:
87	case IMSG_SMTP_EXPAND_RCPT:
88	case IMSG_SMTP_LOOKUP_HELO:
89	case IMSG_SMTP_AUTHENTICATE:
90	case IMSG_SMTP_MESSAGE_COMMIT:
91	case IMSG_SMTP_MESSAGE_CREATE:
92	case IMSG_SMTP_MESSAGE_OPEN:
93	case IMSG_FILTER_SMTP_PROTOCOL:
94	case IMSG_FILTER_SMTP_DATA_BEGIN:
95	case IMSG_QUEUE_ENVELOPE_SUBMIT:
96	case IMSG_QUEUE_ENVELOPE_COMMIT:
97	case IMSG_QUEUE_SMTP_SESSION:
98	case IMSG_CTL_SMTP_SESSION:
99	case IMSG_CTL_PAUSE_SMTP:
100	case IMSG_CTL_RESUME_SMTP:
101		smtp_imsg(p, imsg);
102		return;
103
104        /* mta imsg */
105	case IMSG_QUEUE_TRANSFER:
106	case IMSG_MTA_OPEN_MESSAGE:
107	case IMSG_MTA_LOOKUP_CREDENTIALS:
108	case IMSG_MTA_LOOKUP_SMARTHOST:
109	case IMSG_MTA_LOOKUP_SOURCE:
110	case IMSG_MTA_LOOKUP_HELO:
111	case IMSG_MTA_DNS_HOST:
112	case IMSG_MTA_DNS_HOST_END:
113	case IMSG_MTA_DNS_MX_PREFERENCE:
114	case IMSG_CTL_RESUME_ROUTE:
115	case IMSG_CTL_MTA_SHOW_HOSTS:
116	case IMSG_CTL_MTA_SHOW_RELAYS:
117	case IMSG_CTL_MTA_SHOW_ROUTES:
118	case IMSG_CTL_MTA_SHOW_HOSTSTATS:
119	case IMSG_CTL_MTA_BLOCK:
120	case IMSG_CTL_MTA_UNBLOCK:
121	case IMSG_CTL_MTA_SHOW_BLOCK:
122		mta_imsg(p, imsg);
123		return;
124
125        /* mda imsg */
126	case IMSG_MDA_LOOKUP_USERINFO:
127	case IMSG_QUEUE_DELIVER:
128	case IMSG_MDA_OPEN_MESSAGE:
129	case IMSG_MDA_FORK:
130	case IMSG_MDA_DONE:
131		mda_imsg(p, imsg);
132		return;
133	default:
134		break;
135	}
136
137	errx(1, "session_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
138}
139
140static void
141dispatcher_shutdown(void)
142{
143	log_debug("debug: dispatcher agent exiting");
144	_exit(0);
145}
146
147int
148dispatcher(void)
149{
150	struct passwd	*pw;
151
152	ca_engine_init();
153
154	mda_postfork();
155	mta_postfork();
156	smtp_postfork();
157
158	/* do not purge listeners and pki, they are purged
159	 * in smtp_configure()
160	 */
161	purge_config(PURGE_TABLES|PURGE_RULES);
162
163	if ((pw = getpwnam(SMTPD_USER)) == NULL)
164		fatalx("unknown user " SMTPD_USER);
165
166	if (chroot(PATH_CHROOT) == -1)
167		fatal("dispatcher: chroot");
168	if (chdir("/") == -1)
169		fatal("dispatcher: chdir(\"/\")");
170
171	config_process(PROC_DISPATCHER);
172
173	if (setgroups(1, &pw->pw_gid) ||
174	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
175	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
176		fatal("dispatcher: cannot drop privileges");
177
178	imsg_callback = dispatcher_imsg;
179	event_init();
180
181	mda_postprivdrop();
182	mta_postprivdrop();
183	smtp_postprivdrop();
184
185	signal(SIGINT, SIG_IGN);
186	signal(SIGTERM, SIG_IGN);
187	signal(SIGPIPE, SIG_IGN);
188	signal(SIGHUP, SIG_IGN);
189
190	config_peer(PROC_PARENT);
191	config_peer(PROC_QUEUE);
192	config_peer(PROC_LKA);
193	config_peer(PROC_CONTROL);
194	config_peer(PROC_CA);
195
196	if (pledge("stdio inet unix recvfd sendfd", NULL) == -1)
197		err(1, "pledge");
198
199	event_dispatch();
200	fatalx("exited event loop");
201
202	return (0);
203}
204