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