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