xref: /openbsd/usr.sbin/smtpd/dispatcher.c (revision 41b8cf0b)
1 /*	$OpenBSD: dispatcher.c,v 1.7 2022/02/18 16:57:36 millert 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 
26 void mda_imsg(struct mproc *, struct imsg *);
27 void mta_imsg(struct mproc *, struct imsg *);
28 void smtp_imsg(struct mproc *, struct imsg *);
29 
30 static void dispatcher_shutdown(void);
31 
32 void
dispatcher_imsg(struct mproc * p,struct imsg * imsg)33 dispatcher_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 
123 static void
dispatcher_shutdown(void)124 dispatcher_shutdown(void)
125 {
126 	log_debug("debug: dispatcher agent exiting");
127 	_exit(0);
128 }
129 
130 int
dispatcher(void)131 dispatcher(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