xref: /openbsd-src/usr.sbin/smtpd/config.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /*	$OpenBSD: config.c,v 1.57 2021/06/14 17:58:15 eric Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.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/resource.h>
20 
21 #include <ifaddrs.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "smtpd.h"
26 #include "log.h"
27 #include "ssl.h"
28 
29 void		 set_local(struct smtpd *, const char *);
30 void		 set_localaddrs(struct smtpd *, struct table *);
31 
32 struct smtpd *
33 config_default(void)
34 {
35 	struct smtpd	       *conf = NULL;
36 	struct mta_limits      *limits = NULL;
37 	struct table	       *t = NULL;
38 	char			hostname[HOST_NAME_MAX+1];
39 
40 	if (getmailname(hostname, sizeof hostname) == -1)
41 		return NULL;
42 
43 	if ((conf = calloc(1, sizeof(*conf))) == NULL)
44 		return conf;
45 
46 	(void)strlcpy(conf->sc_hostname, hostname, sizeof(conf->sc_hostname));
47 
48 	conf->sc_maxsize = DEFAULT_MAX_BODY_SIZE;
49 	conf->sc_subaddressing_delim = SUBADDRESSING_DELIMITER;
50 	conf->sc_ttl = SMTPD_QUEUE_EXPIRY;
51 	conf->sc_srs_ttl = SMTPD_QUEUE_EXPIRY / 86400;
52 
53 	conf->sc_mta_max_deferred = 100;
54 	conf->sc_scheduler_max_inflight = 5000;
55 	conf->sc_scheduler_max_schedule = 10;
56 	conf->sc_scheduler_max_evp_batch_size = 256;
57 	conf->sc_scheduler_max_msg_batch_size = 1024;
58 
59 	conf->sc_session_max_rcpt = 1000;
60 	conf->sc_session_max_mails = 100;
61 
62 	conf->sc_mda_max_session = 50;
63 	conf->sc_mda_max_user_session = 7;
64 	conf->sc_mda_task_hiwat = 50;
65 	conf->sc_mda_task_lowat = 30;
66 	conf->sc_mda_task_release = 10;
67 
68 	/* Report mails delayed for more than 4 hours */
69 	conf->sc_bounce_warn[0] = 3600 * 4;
70 
71 	conf->sc_tables_dict = calloc(1, sizeof(*conf->sc_tables_dict));
72 	conf->sc_rules = calloc(1, sizeof(*conf->sc_rules));
73 	conf->sc_dispatchers = calloc(1, sizeof(*conf->sc_dispatchers));
74 	conf->sc_listeners = calloc(1, sizeof(*conf->sc_listeners));
75 	conf->sc_ca_dict = calloc(1, sizeof(*conf->sc_ca_dict));
76 	conf->sc_pki_dict = calloc(1, sizeof(*conf->sc_pki_dict));
77 	conf->sc_ssl_dict = calloc(1, sizeof(*conf->sc_ssl_dict));
78 	conf->sc_limits_dict = calloc(1, sizeof(*conf->sc_limits_dict));
79 	conf->sc_mda_wrappers = calloc(1, sizeof(*conf->sc_mda_wrappers));
80 	conf->sc_filter_processes_dict = calloc(1, sizeof(*conf->sc_filter_processes_dict));
81 	conf->sc_dispatcher_bounce = calloc(1, sizeof(*conf->sc_dispatcher_bounce));
82 	conf->sc_filters_dict = calloc(1, sizeof(*conf->sc_filters_dict));
83 	limits = calloc(1, sizeof(*limits));
84 
85 	if (conf->sc_tables_dict == NULL	||
86 	    conf->sc_rules == NULL		||
87 	    conf->sc_dispatchers == NULL	||
88 	    conf->sc_listeners == NULL		||
89 	    conf->sc_ca_dict == NULL		||
90 	    conf->sc_pki_dict == NULL		||
91 	    conf->sc_ssl_dict == NULL		||
92 	    conf->sc_limits_dict == NULL        ||
93 	    conf->sc_mda_wrappers == NULL	||
94 	    conf->sc_filter_processes_dict == NULL	||
95 	    conf->sc_dispatcher_bounce == NULL	||
96 	    conf->sc_filters_dict == NULL	||
97 	    limits == NULL)
98 		goto error;
99 
100 	dict_init(conf->sc_dispatchers);
101 	dict_init(conf->sc_mda_wrappers);
102 	dict_init(conf->sc_ca_dict);
103 	dict_init(conf->sc_pki_dict);
104 	dict_init(conf->sc_ssl_dict);
105 	dict_init(conf->sc_tables_dict);
106 	dict_init(conf->sc_limits_dict);
107 	dict_init(conf->sc_filter_processes_dict);
108 
109 	limit_mta_set_defaults(limits);
110 
111 	dict_xset(conf->sc_limits_dict, "default", limits);
112 
113 	TAILQ_INIT(conf->sc_listeners);
114 	TAILQ_INIT(conf->sc_rules);
115 
116 
117 	/* bounce dispatcher */
118 	conf->sc_dispatcher_bounce->type = DISPATCHER_BOUNCE;
119 
120 	/*
121 	 * declare special "localhost", "anyhost" and "localnames" tables
122 	 */
123 	set_local(conf, conf->sc_hostname);
124 
125 	t = table_create(conf, "static", "<anydestination>", NULL);
126 	table_add(t, "*", NULL);
127 
128 	hostname[strcspn(hostname, ".")] = '\0';
129 	if (strcmp(conf->sc_hostname, hostname) != 0)
130 		table_add(t, hostname, NULL);
131 
132 	table_create(conf, "getpwnam", "<getpwnam>", NULL);
133 
134 	return conf;
135 
136 error:
137 	free(conf->sc_tables_dict);
138 	free(conf->sc_rules);
139 	free(conf->sc_dispatchers);
140 	free(conf->sc_listeners);
141 	free(conf->sc_ca_dict);
142 	free(conf->sc_pki_dict);
143 	free(conf->sc_ssl_dict);
144 	free(conf->sc_limits_dict);
145 	free(conf->sc_mda_wrappers);
146 	free(conf->sc_filter_processes_dict);
147 	free(conf->sc_dispatcher_bounce);
148 	free(conf->sc_filters_dict);
149 	free(limits);
150 	free(conf);
151 	return NULL;
152 }
153 
154 void
155 set_local(struct smtpd *conf, const char *hostname)
156 {
157 	struct table	*t;
158 
159 	t = table_create(conf, "static", "<localnames>", NULL);
160 	table_add(t, "localhost", NULL);
161 	table_add(t, hostname, NULL);
162 
163 	set_localaddrs(conf, t);
164 }
165 
166 void
167 set_localaddrs(struct smtpd *conf, struct table *localnames)
168 {
169 	struct ifaddrs *ifap, *p;
170 	struct sockaddr_storage ss;
171 	struct sockaddr_in	*sain;
172 	struct sockaddr_in6	*sin6;
173 	struct table		*t;
174 	char buf[NI_MAXHOST + 5];
175 
176 	t = table_create(conf, "static", "<anyhost>", NULL);
177 	table_add(t, "local", NULL);
178 	table_add(t, "0.0.0.0/0", NULL);
179 	table_add(t, "::/0", NULL);
180 
181 	if (getifaddrs(&ifap) == -1)
182 		fatal("getifaddrs");
183 
184 	t = table_create(conf, "static", "<localhost>", NULL);
185 	table_add(t, "local", NULL);
186 
187 	for (p = ifap; p != NULL; p = p->ifa_next) {
188 		if (p->ifa_addr == NULL)
189 			continue;
190 		switch (p->ifa_addr->sa_family) {
191 		case AF_INET:
192 			sain = (struct sockaddr_in *)&ss;
193 			*sain = *(struct sockaddr_in *)p->ifa_addr;
194 			sain->sin_len = sizeof(struct sockaddr_in);
195 			table_add(t, ss_to_text(&ss), NULL);
196 			table_add(localnames, ss_to_text(&ss), NULL);
197 			(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
198 			table_add(localnames, buf, NULL);
199 			break;
200 
201 		case AF_INET6:
202 			sin6 = (struct sockaddr_in6 *)&ss;
203 			*sin6 = *(struct sockaddr_in6 *)p->ifa_addr;
204 			sin6->sin6_len = sizeof(struct sockaddr_in6);
205 #ifdef __KAME__
206 			if ((IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
207 			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr) ||
208 			    IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) &&
209 			    sin6->sin6_scope_id == 0) {
210 				sin6->sin6_scope_id = ntohs(
211 				    *(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
212 				sin6->sin6_addr.s6_addr[2] = 0;
213 				sin6->sin6_addr.s6_addr[3] = 0;
214 			}
215 #endif
216 			table_add(t, ss_to_text(&ss), NULL);
217 			table_add(localnames, ss_to_text(&ss), NULL);
218 			(void)snprintf(buf, sizeof buf, "[%s]", ss_to_text(&ss));
219 			table_add(localnames, buf, NULL);
220 			(void)snprintf(buf, sizeof buf, "[ipv6:%s]", ss_to_text(&ss));
221 			table_add(localnames, buf, NULL);
222 			break;
223 		}
224 	}
225 
226 	freeifaddrs(ifap);
227 }
228 
229 void
230 purge_config(uint8_t what)
231 {
232 	struct dispatcher	*d;
233 	struct listener	*l;
234 	struct table	*t;
235 	struct rule	*r;
236 	struct pki	*p;
237 	const char	*k;
238 	void		*iter_dict;
239 
240 	if (what & PURGE_LISTENERS) {
241 		while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) {
242 			TAILQ_REMOVE(env->sc_listeners, l, entry);
243 			free(l->tls_ciphers);
244 			free(l->tls_protocols);
245 			free(l->pki);
246 			free(l);
247 		}
248 		free(env->sc_listeners);
249 		env->sc_listeners = NULL;
250 	}
251 	if (what & PURGE_TABLES) {
252 		while (dict_root(env->sc_tables_dict, NULL, (void **)&t))
253 			table_destroy(env, t);
254 		free(env->sc_tables_dict);
255 		env->sc_tables_dict = NULL;
256 	}
257 	if (what & PURGE_RULES) {
258 		while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) {
259 			TAILQ_REMOVE(env->sc_rules, r, r_entry);
260 			free(r);
261 		}
262 		free(env->sc_rules);
263 		env->sc_rules = NULL;
264 	}
265 	if (what & PURGE_DISPATCHERS) {
266 		while (dict_poproot(env->sc_dispatchers, (void **)&d)) {
267 			free(d);
268 		}
269 		free(env->sc_dispatchers);
270 		env->sc_dispatchers = NULL;
271 	}
272 	if (what & PURGE_PKI) {
273 		while (dict_poproot(env->sc_pki_dict, (void **)&p)) {
274 			freezero(p->pki_cert, p->pki_cert_len);
275 			freezero(p->pki_key, p->pki_key_len);
276 			free(p);
277 		}
278 		free(env->sc_pki_dict);
279 		env->sc_pki_dict = NULL;
280 	} else if (what & PURGE_PKI_KEYS) {
281 		iter_dict = NULL;
282 		while (dict_iter(env->sc_pki_dict, &iter_dict, &k,
283 		    (void **)&p)) {
284 			freezero(p->pki_cert, p->pki_cert_len);
285 			p->pki_cert = NULL;
286 			freezero(p->pki_key, p->pki_key_len);
287 			p->pki_key = NULL;
288 		}
289 	}
290 }
291 
292 #ifndef CONFIG_MINIMUM
293 
294 void
295 config_process(enum smtp_proc_type proc)
296 {
297 	struct rlimit rl;
298 
299 	smtpd_process = proc;
300 	setproctitle("%s", proc_title(proc));
301 
302 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
303 		fatal("fdlimit: getrlimit");
304 	rl.rlim_cur = rl.rlim_max;
305 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
306 		fatal("fdlimit: setrlimit");
307 }
308 
309 void
310 config_peer(enum smtp_proc_type proc)
311 {
312 	struct mproc	*p;
313 
314 	if (proc == smtpd_process)
315 		fatal("config_peers: cannot peer with oneself");
316 
317 	if (proc == PROC_CONTROL)
318 		p = p_control;
319 	else if (proc == PROC_LKA)
320 		p = p_lka;
321 	else if (proc == PROC_PARENT)
322 		p = p_parent;
323 	else if (proc == PROC_QUEUE)
324 		p = p_queue;
325 	else if (proc == PROC_SCHEDULER)
326 		p = p_scheduler;
327 	else if (proc == PROC_DISPATCHER)
328 		p = p_dispatcher;
329 	else if (proc == PROC_CA)
330 		p = p_ca;
331 	else
332 		fatalx("bad peer");
333 
334 	mproc_enable(p);
335 }
336 
337 #else
338 
339 void config_process(enum smtp_proc_type proc) {}
340 void config_peer(enum smtp_proc_type proc) {}
341 
342 #endif
343