xref: /openbsd-src/usr.sbin/smtpd/dispatcher.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: dispatcher.c,v 1.1 2020/12/31 08:27:15 martijn 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_CERT_INIT:
68 	case IMSG_CERT_VERIFY:
69 		cert_dispatch_result(p, imsg);
70 		return;
71 
72 	case IMSG_CONF_START:
73 		return;
74 	case IMSG_CONF_END:
75 		smtp_configure();
76 		return;
77 	case IMSG_CTL_VERBOSE:
78 		m_msg(&m, imsg);
79 		m_get_int(&m, &v);
80 		m_end(&m);
81 		log_trace_verbose(v);
82 		return;
83 	case IMSG_CTL_PROFILE:
84 		m_msg(&m, imsg);
85 		m_get_int(&m, &v);
86 		m_end(&m);
87 		profiling = v;
88 		return;
89 
90 	/* smtp imsg */
91 	case IMSG_SMTP_CHECK_SENDER:
92 	case IMSG_SMTP_EXPAND_RCPT:
93 	case IMSG_SMTP_LOOKUP_HELO:
94 	case IMSG_SMTP_AUTHENTICATE:
95 	case IMSG_SMTP_MESSAGE_COMMIT:
96 	case IMSG_SMTP_MESSAGE_CREATE:
97 	case IMSG_SMTP_MESSAGE_OPEN:
98 	case IMSG_FILTER_SMTP_PROTOCOL:
99 	case IMSG_FILTER_SMTP_DATA_BEGIN:
100 	case IMSG_QUEUE_ENVELOPE_SUBMIT:
101 	case IMSG_QUEUE_ENVELOPE_COMMIT:
102 	case IMSG_QUEUE_SMTP_SESSION:
103 	case IMSG_CTL_SMTP_SESSION:
104 	case IMSG_CTL_PAUSE_SMTP:
105 	case IMSG_CTL_RESUME_SMTP:
106 		smtp_imsg(p, imsg);
107 		return;
108 
109         /* mta imsg */
110 	case IMSG_QUEUE_TRANSFER:
111 	case IMSG_MTA_OPEN_MESSAGE:
112 	case IMSG_MTA_LOOKUP_CREDENTIALS:
113 	case IMSG_MTA_LOOKUP_SMARTHOST:
114 	case IMSG_MTA_LOOKUP_SOURCE:
115 	case IMSG_MTA_LOOKUP_HELO:
116 	case IMSG_MTA_DNS_HOST:
117 	case IMSG_MTA_DNS_HOST_END:
118 	case IMSG_MTA_DNS_MX_PREFERENCE:
119 	case IMSG_CTL_RESUME_ROUTE:
120 	case IMSG_CTL_MTA_SHOW_HOSTS:
121 	case IMSG_CTL_MTA_SHOW_RELAYS:
122 	case IMSG_CTL_MTA_SHOW_ROUTES:
123 	case IMSG_CTL_MTA_SHOW_HOSTSTATS:
124 	case IMSG_CTL_MTA_BLOCK:
125 	case IMSG_CTL_MTA_UNBLOCK:
126 	case IMSG_CTL_MTA_SHOW_BLOCK:
127 		mta_imsg(p, imsg);
128 		return;
129 
130         /* mda imsg */
131 	case IMSG_MDA_LOOKUP_USERINFO:
132 	case IMSG_QUEUE_DELIVER:
133 	case IMSG_MDA_OPEN_MESSAGE:
134 	case IMSG_MDA_FORK:
135 	case IMSG_MDA_DONE:
136 		mda_imsg(p, imsg);
137 		return;
138 	default:
139 		break;
140 	}
141 
142 	errx(1, "session_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
143 }
144 
145 static void
146 dispatcher_shutdown(void)
147 {
148 	log_debug("debug: dispatcher agent exiting");
149 	_exit(0);
150 }
151 
152 int
153 dispatcher(void)
154 {
155 	struct passwd	*pw;
156 
157 	mda_postfork();
158 	mta_postfork();
159 	smtp_postfork();
160 
161 	/* do not purge listeners and pki, they are purged
162 	 * in smtp_configure()
163 	 */
164 	purge_config(PURGE_TABLES|PURGE_RULES);
165 
166 	if ((pw = getpwnam(SMTPD_USER)) == NULL)
167 		fatalx("unknown user " SMTPD_USER);
168 
169 	if (chroot(PATH_CHROOT) == -1)
170 		fatal("dispatcher: chroot");
171 	if (chdir("/") == -1)
172 		fatal("dispatcher: chdir(\"/\")");
173 
174 	config_process(PROC_DISPATCHER);
175 
176 	if (setgroups(1, &pw->pw_gid) ||
177 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
178 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
179 		fatal("dispatcher: cannot drop privileges");
180 
181 	imsg_callback = dispatcher_imsg;
182 	event_init();
183 
184 	mda_postprivdrop();
185 	mta_postprivdrop();
186 	smtp_postprivdrop();
187 
188 	signal(SIGINT, SIG_IGN);
189 	signal(SIGTERM, SIG_IGN);
190 	signal(SIGPIPE, SIG_IGN);
191 	signal(SIGHUP, SIG_IGN);
192 
193 	config_peer(PROC_PARENT);
194 	config_peer(PROC_QUEUE);
195 	config_peer(PROC_LKA);
196 	config_peer(PROC_CONTROL);
197 	config_peer(PROC_CA);
198 
199 	ca_engine_init();
200 
201 	if (pledge("stdio inet unix recvfd sendfd", NULL) == -1)
202 		err(1, "pledge");
203 
204 	event_dispatch();
205 	fatalx("exited event loop");
206 
207 	return (0);
208 }
209