xref: /openbsd-src/usr.sbin/smtpd/dispatcher.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
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 
43 void mda_imsg(struct mproc *, struct imsg *);
44 void mta_imsg(struct mproc *, struct imsg *);
45 void smtp_imsg(struct mproc *, struct imsg *);
46 
47 static void dispatcher_shutdown(void);
48 
49 void
50 dispatcher_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 
140 static void
141 dispatcher_shutdown(void)
142 {
143 	log_debug("debug: dispatcher agent exiting");
144 	_exit(0);
145 }
146 
147 int
148 dispatcher(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