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