dispatcher.c revision 1.5
1/*	$OpenBSD: dispatcher.c,v 1.5 2021/06/14 17:58:15 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 <pwd.h>
20#include <signal.h>
21#include <unistd.h>
22
23#include "smtpd.h"
24#include "log.h"
25
26void mda_imsg(struct mproc *, struct imsg *);
27void mta_imsg(struct mproc *, struct imsg *);
28void smtp_imsg(struct mproc *, struct imsg *);
29
30static void dispatcher_shutdown(void);
31
32void
33dispatcher_imsg(struct mproc *p, struct imsg *imsg)
34{
35	struct msg	m;
36	int		v;
37
38	if (imsg == NULL)
39		dispatcher_shutdown();
40
41	switch (imsg->hdr.type) {
42
43	case IMSG_GETADDRINFO:
44	case IMSG_GETADDRINFO_END:
45	case IMSG_GETNAMEINFO:
46	case IMSG_RES_QUERY:
47		resolver_dispatch_result(p, imsg);
48		return;
49
50	case IMSG_CONF_START:
51		return;
52	case IMSG_CONF_END:
53		smtp_configure();
54		return;
55	case IMSG_CTL_VERBOSE:
56		m_msg(&m, imsg);
57		m_get_int(&m, &v);
58		m_end(&m);
59		log_trace_verbose(v);
60		return;
61	case IMSG_CTL_PROFILE:
62		m_msg(&m, imsg);
63		m_get_int(&m, &v);
64		m_end(&m);
65		profiling = v;
66		return;
67
68	/* smtp imsg */
69	case IMSG_SMTP_CHECK_SENDER:
70	case IMSG_SMTP_EXPAND_RCPT:
71	case IMSG_SMTP_LOOKUP_HELO:
72	case IMSG_SMTP_AUTHENTICATE:
73	case IMSG_SMTP_MESSAGE_COMMIT:
74	case IMSG_SMTP_MESSAGE_CREATE:
75	case IMSG_SMTP_MESSAGE_OPEN:
76	case IMSG_FILTER_SMTP_PROTOCOL:
77	case IMSG_FILTER_SMTP_DATA_BEGIN:
78	case IMSG_QUEUE_ENVELOPE_SUBMIT:
79	case IMSG_QUEUE_ENVELOPE_COMMIT:
80	case IMSG_QUEUE_SMTP_SESSION:
81	case IMSG_CTL_SMTP_SESSION:
82	case IMSG_CTL_PAUSE_SMTP:
83	case IMSG_CTL_RESUME_SMTP:
84		smtp_imsg(p, imsg);
85		return;
86
87        /* mta imsg */
88	case IMSG_QUEUE_TRANSFER:
89	case IMSG_MTA_OPEN_MESSAGE:
90	case IMSG_MTA_LOOKUP_CREDENTIALS:
91	case IMSG_MTA_LOOKUP_SMARTHOST:
92	case IMSG_MTA_LOOKUP_SOURCE:
93	case IMSG_MTA_LOOKUP_HELO:
94	case IMSG_MTA_DNS_HOST:
95	case IMSG_MTA_DNS_HOST_END:
96	case IMSG_MTA_DNS_MX_PREFERENCE:
97	case IMSG_CTL_RESUME_ROUTE:
98	case IMSG_CTL_MTA_SHOW_HOSTS:
99	case IMSG_CTL_MTA_SHOW_RELAYS:
100	case IMSG_CTL_MTA_SHOW_ROUTES:
101	case IMSG_CTL_MTA_SHOW_HOSTSTATS:
102	case IMSG_CTL_MTA_BLOCK:
103	case IMSG_CTL_MTA_UNBLOCK:
104	case IMSG_CTL_MTA_SHOW_BLOCK:
105		mta_imsg(p, imsg);
106		return;
107
108        /* mda imsg */
109	case IMSG_MDA_LOOKUP_USERINFO:
110	case IMSG_QUEUE_DELIVER:
111	case IMSG_MDA_OPEN_MESSAGE:
112	case IMSG_MDA_FORK:
113	case IMSG_MDA_DONE:
114		mda_imsg(p, imsg);
115		return;
116	default:
117		break;
118	}
119
120	fatalx("session_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
121}
122
123static void
124dispatcher_shutdown(void)
125{
126	log_debug("debug: dispatcher agent exiting");
127	_exit(0);
128}
129
130int
131dispatcher(void)
132{
133	struct passwd	*pw;
134
135	ca_engine_init();
136
137	mda_postfork();
138	mta_postfork();
139	smtp_postfork();
140
141	/* do not purge listeners and pki, they are purged
142	 * in smtp_configure()
143	 */
144	purge_config(PURGE_TABLES|PURGE_RULES);
145
146	if ((pw = getpwnam(SMTPD_USER)) == NULL)
147		fatalx("unknown user " SMTPD_USER);
148
149	if (chroot(PATH_CHROOT) == -1)
150		fatal("dispatcher: chroot");
151	if (chdir("/") == -1)
152		fatal("dispatcher: chdir(\"/\")");
153
154	config_process(PROC_DISPATCHER);
155
156	if (setgroups(1, &pw->pw_gid) ||
157	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
158	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
159		fatal("dispatcher: cannot drop privileges");
160
161	imsg_callback = dispatcher_imsg;
162	event_init();
163
164	mda_postprivdrop();
165	mta_postprivdrop();
166	smtp_postprivdrop();
167
168	signal(SIGINT, SIG_IGN);
169	signal(SIGTERM, SIG_IGN);
170	signal(SIGPIPE, SIG_IGN);
171	signal(SIGHUP, SIG_IGN);
172
173	config_peer(PROC_PARENT);
174	config_peer(PROC_QUEUE);
175	config_peer(PROC_LKA);
176	config_peer(PROC_CONTROL);
177	config_peer(PROC_CA);
178
179	if (pledge("stdio inet unix recvfd sendfd", NULL) == -1)
180		fatal("pledge");
181
182	event_dispatch();
183	fatalx("exited event loop");
184
185	return (0);
186}
187