xref: /openbsd-src/usr.sbin/relayd/config.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /*	$OpenBSD: config.c,v 1.43 2021/12/05 13:48:14 jsg Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 - 2014 Reyk Floeter <reyk@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/types.h>
20 #include <sys/queue.h>
21 #include <sys/time.h>
22 #include <sys/uio.h>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <string.h>
29 #include <imsg.h>
30 
31 #include "relayd.h"
32 
33 int
34 config_init(struct relayd *env)
35 {
36 	struct privsep	*ps = env->sc_ps;
37 	u_int		 what;
38 
39 	/* Global configuration */
40 	if (privsep_process == PROC_PARENT) {
41 		env->sc_conf.timeout.tv_sec = CHECK_TIMEOUT / 1000;
42 		env->sc_conf.timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
43 		env->sc_conf.interval.tv_sec = CHECK_INTERVAL;
44 		env->sc_conf.interval.tv_usec = 0;
45 		env->sc_conf.prefork_relay = RELAY_NUMPROC;
46 		env->sc_conf.statinterval.tv_sec = RELAY_STATINTERVAL;
47 		env->sc_ps->ps_csock.cs_name = RELAYD_SOCKET;
48 	}
49 
50 	ps->ps_what[PROC_PARENT] = CONFIG_ALL;
51 	ps->ps_what[PROC_PFE] = CONFIG_ALL & ~(CONFIG_PROTOS|CONFIG_CERTS);
52 	ps->ps_what[PROC_HCE] = CONFIG_TABLES;
53 	ps->ps_what[PROC_CA] = CONFIG_RELAYS|CONFIG_CERTS;
54 	ps->ps_what[PROC_RELAY] = CONFIG_RELAYS|CONFIG_CERTS|
55 	    CONFIG_TABLES|CONFIG_PROTOS|CONFIG_CA_ENGINE;
56 
57 	/* Other configuration */
58 	what = ps->ps_what[privsep_process];
59 	if (what & CONFIG_TABLES) {
60 		if ((env->sc_tables =
61 		    calloc(1, sizeof(*env->sc_tables))) == NULL)
62 			return (-1);
63 		TAILQ_INIT(env->sc_tables);
64 
65 		memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table));
66 		env->sc_empty_table.conf.id = EMPTY_TABLE;
67 		env->sc_empty_table.conf.flags |= F_DISABLE;
68 		(void)strlcpy(env->sc_empty_table.conf.name, "empty",
69 		    sizeof(env->sc_empty_table.conf.name));
70 
71 	}
72 	if (what & CONFIG_RDRS) {
73 		if ((env->sc_rdrs =
74 		    calloc(1, sizeof(*env->sc_rdrs))) == NULL)
75 			return (-1);
76 		TAILQ_INIT(env->sc_rdrs);
77 
78 	}
79 	if (what & CONFIG_RELAYS) {
80 		if ((env->sc_relays =
81 		    calloc(1, sizeof(*env->sc_relays))) == NULL)
82 			return (-1);
83 		TAILQ_INIT(env->sc_relays);
84 
85 		if ((env->sc_certs =
86 		    calloc(1, sizeof(*env->sc_certs))) == NULL)
87 			return (-1);
88 		TAILQ_INIT(env->sc_certs);
89 
90 		if ((env->sc_pkeys =
91 		    calloc(1, sizeof(*env->sc_pkeys))) == NULL)
92 			return (-1);
93 		TAILQ_INIT(env->sc_pkeys);
94 	}
95 	if (what & CONFIG_PROTOS) {
96 		if ((env->sc_protos =
97 		    calloc(1, sizeof(*env->sc_protos))) == NULL)
98 			return (-1);
99 		TAILQ_INIT(env->sc_protos);
100 
101 		bzero(&env->sc_proto_default, sizeof(env->sc_proto_default));
102 		env->sc_proto_default.id = EMPTY_ID;
103 		env->sc_proto_default.flags = F_USED;
104 		env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
105 		env->sc_proto_default.tcpbacklog = RELAY_BACKLOG;
106 		env->sc_proto_default.tlsflags = TLSFLAG_DEFAULT;
107 		TAILQ_INIT(&env->sc_proto_default.tlscerts);
108 		(void)strlcpy(env->sc_proto_default.tlsciphers,
109 		    TLSCIPHERS_DEFAULT,
110 		    sizeof(env->sc_proto_default.tlsciphers));
111 		(void)strlcpy(env->sc_proto_default.tlsecdhecurves,
112 		    TLSECDHECURVES_DEFAULT,
113 		    sizeof(env->sc_proto_default.tlsecdhecurves));
114 		(void)strlcpy(env->sc_proto_default.tlsdhparams,
115 		    TLSDHPARAM_DEFAULT,
116 		    sizeof(env->sc_proto_default.tlsdhparams));
117 		env->sc_proto_default.type = RELAY_PROTO_TCP;
118 		(void)strlcpy(env->sc_proto_default.name, "default",
119 		    sizeof(env->sc_proto_default.name));
120 	}
121 	if (what & CONFIG_RTS) {
122 		if ((env->sc_rts =
123 		    calloc(1, sizeof(*env->sc_rts))) == NULL)
124 			return (-1);
125 		TAILQ_INIT(env->sc_rts);
126 	}
127 	if (what & CONFIG_ROUTES) {
128 		if ((env->sc_routes =
129 		    calloc(1, sizeof(*env->sc_routes))) == NULL)
130 			return (-1);
131 		TAILQ_INIT(env->sc_routes);
132 	}
133 
134 	return (0);
135 }
136 
137 void
138 config_purge(struct relayd *env, u_int reset)
139 {
140 	struct privsep		*ps = env->sc_ps;
141 	struct table		*table;
142 	struct rdr		*rdr;
143 	struct address		*virt;
144 	struct protocol		*proto;
145 	struct relay_rule	*rule;
146 	struct relay		*rlay;
147 	struct netroute		*nr;
148 	struct router		*rt;
149 	struct ca_pkey		*pkey;
150 	struct keyname		*keyname;
151 	u_int			 what;
152 
153 	what = ps->ps_what[privsep_process] & reset;
154 
155 	if (what & CONFIG_TABLES && env->sc_tables != NULL) {
156 		while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
157 			purge_table(env, env->sc_tables, table);
158 		env->sc_tablecount = 0;
159 	}
160 	if (what & CONFIG_RDRS && env->sc_rdrs != NULL) {
161 		while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
162 			TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
163 			while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
164 				TAILQ_REMOVE(&rdr->virts, virt, entry);
165 				free(virt);
166 			}
167 			free(rdr);
168 		}
169 		env->sc_rdrcount = 0;
170 	}
171 	if (what & CONFIG_RELAYS && env->sc_pkeys != NULL) {
172 		while ((pkey = TAILQ_FIRST(env->sc_pkeys)) != NULL) {
173 			TAILQ_REMOVE(env->sc_pkeys, pkey, pkey_entry);
174 			free(pkey);
175 		}
176 	}
177 	if (what & CONFIG_RELAYS && env->sc_relays != NULL) {
178 		while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL)
179 			purge_relay(env, rlay);
180 		env->sc_relaycount = 0;
181 	}
182 	if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
183 		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
184 			TAILQ_REMOVE(env->sc_protos, proto, entry);
185 			while ((rule = TAILQ_FIRST(&proto->rules)) != NULL)
186 				rule_delete(&proto->rules, rule);
187 			proto->rulecount = 0;
188 		}
189 	}
190 	if (what & CONFIG_PROTOS && env->sc_protos != NULL) {
191 		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
192 			TAILQ_REMOVE(env->sc_protos, proto, entry);
193 			free(proto->style);
194 			free(proto->tlscapass);
195 			while ((keyname =
196 			    TAILQ_FIRST(&proto->tlscerts)) != NULL) {
197 				TAILQ_REMOVE(&proto->tlscerts, keyname, entry);
198 				free(keyname->name);
199 				free(keyname);
200 			}
201 			free(proto);
202 		}
203 		env->sc_protocount = 0;
204 	}
205 	if (what & CONFIG_RTS && env->sc_rts != NULL) {
206 		while ((rt = TAILQ_FIRST(env->sc_rts)) != NULL) {
207 			TAILQ_REMOVE(env->sc_rts, rt, rt_entry);
208 			while ((nr = TAILQ_FIRST(&rt->rt_netroutes)) != NULL) {
209 				TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
210 				TAILQ_REMOVE(env->sc_routes, nr, nr_route);
211 				free(nr);
212 				env->sc_routecount--;
213 			}
214 			free(rt);
215 		}
216 		env->sc_routercount = 0;
217 	}
218 	if (what & CONFIG_ROUTES && env->sc_routes != NULL) {
219 		while ((nr = TAILQ_FIRST(env->sc_routes)) != NULL) {
220 			if ((rt = nr->nr_router) != NULL)
221 				TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry);
222 			TAILQ_REMOVE(env->sc_routes, nr, nr_route);
223 			free(nr);
224 		}
225 		env->sc_routecount = 0;
226 	}
227 }
228 
229 int
230 config_setreset(struct relayd *env, u_int reset)
231 {
232 	struct privsep	*ps = env->sc_ps;
233 	int		 id;
234 
235 	for (id = 0; id < PROC_MAX; id++) {
236 		if ((reset & ps->ps_what[id]) == 0 ||
237 		    id == privsep_process)
238 			continue;
239 		proc_compose(ps, id, IMSG_CTL_RESET, &reset, sizeof(reset));
240 
241 		/*
242 		 * XXX Make sure that the reset message is sent
243 		 * immediately by flushing the imsg output buffer, before
244 		 * sending any other imsg that potentially include an fd.
245 		 * This should better be fixed in the imsg API itself.
246 		 */
247 		proc_flush_imsg(ps, id, -1);
248 	}
249 
250 	return (0);
251 }
252 
253 int
254 config_getreset(struct relayd *env, struct imsg *imsg)
255 {
256 	u_int		 mode;
257 
258 	IMSG_SIZE_CHECK(imsg, &mode);
259 	memcpy(&mode, imsg->data, sizeof(mode));
260 
261 	config_purge(env, mode);
262 
263 	return (0);
264 }
265 
266 int
267 config_getcfg(struct relayd *env, struct imsg *imsg)
268 {
269 	struct privsep		*ps = env->sc_ps;
270 	struct table		*tb;
271 	struct host		*h, *ph;
272 	u_int			 what;
273 
274 	if (IMSG_DATA_SIZE(imsg) != sizeof(struct relayd_config))
275 		return (0); /* ignore */
276 
277 	/* Update runtime flags */
278 	memcpy(&env->sc_conf, imsg->data, sizeof(env->sc_conf));
279 
280 	what = ps->ps_what[privsep_process];
281 
282 	if (what & CONFIG_TABLES) {
283 		/* Update the tables */
284 		TAILQ_FOREACH(tb, env->sc_tables, entry) {
285 			TAILQ_FOREACH(h, &tb->hosts, entry) {
286 				if (h->conf.parentid && (ph = host_find(env,
287 				    h->conf.parentid)) != NULL) {
288 					SLIST_INSERT_HEAD(&ph->children,
289 					    h, child);
290 				}
291 			}
292 		}
293 	}
294 
295 	if (env->sc_conf.flags & (F_TLS|F_TLSCLIENT)) {
296 		ssl_init(env);
297 		if (what & CONFIG_CA_ENGINE)
298 			ca_engine_init(env);
299 	}
300 
301 	if (privsep_process != PROC_PARENT)
302 		proc_compose(env->sc_ps, PROC_PARENT, IMSG_CFG_DONE, NULL, 0);
303 
304 	return (0);
305 }
306 
307 int
308 config_settable(struct relayd *env, struct table *tb)
309 {
310 	struct privsep	*ps = env->sc_ps;
311 	struct host	*host;
312 	int		 id, c;
313 	struct iovec	 iov[2];
314 
315 	for (id = 0; id < PROC_MAX; id++) {
316 		if ((ps->ps_what[id] & CONFIG_TABLES) == 0 ||
317 		    id == privsep_process)
318 			continue;
319 
320 		/* XXX need to send table to pfe for control socket */
321 		if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
322 			continue;
323 
324 		DPRINTF("%s: sending table %s %d to %s", __func__,
325 		    tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]);
326 
327 		c = 0;
328 		iov[c].iov_base = &tb->conf;
329 		iov[c++].iov_len = sizeof(tb->conf);
330 		if (tb->sendbuf != NULL) {
331 			iov[c].iov_base = tb->sendbuf;
332 			iov[c++].iov_len = strlen(tb->sendbuf);
333 		}
334 
335 		proc_composev(ps, id, IMSG_CFG_TABLE, iov, c);
336 
337 		TAILQ_FOREACH(host, &tb->hosts, entry) {
338 			proc_compose(ps, id, IMSG_CFG_HOST,
339 			    &host->conf, sizeof(host->conf));
340 		}
341 	}
342 
343 	return (0);
344 }
345 
346 int
347 config_gettable(struct relayd *env, struct imsg *imsg)
348 {
349 	struct table		*tb;
350 	size_t			 sb;
351 	u_int8_t		*p = imsg->data;
352 	size_t			 s;
353 
354 	if ((tb = calloc(1, sizeof(*tb))) == NULL)
355 		return (-1);
356 
357 	IMSG_SIZE_CHECK(imsg, &tb->conf);
358 	memcpy(&tb->conf, p, sizeof(tb->conf));
359 	s = sizeof(tb->conf);
360 
361 	sb = IMSG_DATA_SIZE(imsg) - s;
362 	if (sb > 0) {
363 		if ((tb->sendbuf = get_string(p + s, sb)) == NULL) {
364 			free(tb);
365 			return (-1);
366 		}
367 	}
368 	if (tb->conf.check == CHECK_BINSEND_EXPECT) {
369 		tb->sendbinbuf = string2binary(tb->sendbuf);
370 		if (tb->sendbinbuf == NULL) {
371 			free(tb);
372 			return (-1);
373 		}
374 	}
375 
376 	TAILQ_INIT(&tb->hosts);
377 	TAILQ_INSERT_TAIL(env->sc_tables, tb, entry);
378 
379 	env->sc_tablecount++;
380 
381 	DPRINTF("%s: %s %d received table %d (%s)", __func__,
382 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
383 	    tb->conf.id, tb->conf.name);
384 
385 	return (0);
386 }
387 
388 int
389 config_gethost(struct relayd *env, struct imsg *imsg)
390 {
391 	struct table		*tb;
392 	struct host		*host;
393 
394 	if ((host = calloc(1, sizeof(*host))) == NULL)
395 		return (-1);
396 
397 	IMSG_SIZE_CHECK(imsg, &host->conf);
398 	memcpy(&host->conf, imsg->data, sizeof(host->conf));
399 
400 	if (host_find(env, host->conf.id) != NULL) {
401 		log_debug("%s: host %d already exists",
402 		    __func__, host->conf.id);
403 		free(host);
404 		return (-1);
405 	}
406 
407 	if ((tb = table_find(env, host->conf.tableid)) == NULL) {
408 		log_debug("%s: "
409 		    "received host for unknown table %d", __func__,
410 		    host->conf.tableid);
411 		free(host);
412 		return (-1);
413 	}
414 
415 	host->tablename = tb->conf.name;
416 	host->cte.s = -1;
417 
418 	SLIST_INIT(&host->children);
419 	TAILQ_INSERT_TAIL(&tb->hosts, host, entry);
420 	TAILQ_INSERT_TAIL(&env->sc_hosts, host, globalentry);
421 
422 	DPRINTF("%s: %s %d received host %s for table %s", __func__,
423 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
424 	    host->conf.name, tb->conf.name);
425 
426 	return (0);
427 }
428 
429 int
430 config_setrdr(struct relayd *env, struct rdr *rdr)
431 {
432 	struct privsep	*ps = env->sc_ps;
433 	struct address	*virt;
434 	int		 id;
435 
436 	for (id = 0; id < PROC_MAX; id++) {
437 		if ((ps->ps_what[id] & CONFIG_RDRS) == 0 ||
438 		    id == privsep_process)
439 			continue;
440 
441 		DPRINTF("%s: sending rdr %s to %s", __func__,
442 		    rdr->conf.name, ps->ps_title[id]);
443 
444 		proc_compose(ps, id, IMSG_CFG_RDR,
445 		    &rdr->conf, sizeof(rdr->conf));
446 
447 		TAILQ_FOREACH(virt, &rdr->virts, entry) {
448 			virt->rdrid = rdr->conf.id;
449 			proc_compose(ps, id, IMSG_CFG_VIRT,
450 			    virt, sizeof(*virt));
451 		}
452 	}
453 
454 	return (0);
455 }
456 
457 int
458 config_getrdr(struct relayd *env, struct imsg *imsg)
459 {
460 	struct rdr		*rdr;
461 
462 	if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
463 		return (-1);
464 
465 	IMSG_SIZE_CHECK(imsg, &rdr->conf);
466 	memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
467 
468 	if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) {
469 		log_debug("%s: table not found", __func__);
470 		free(rdr);
471 		return (-1);
472 	}
473 	if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) {
474 		rdr->conf.backup_id = EMPTY_TABLE;
475 		rdr->backup = &env->sc_empty_table;
476 	}
477 
478 	TAILQ_INIT(&rdr->virts);
479 	TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
480 
481 	env->sc_rdrcount++;
482 
483 	DPRINTF("%s: %s %d received rdr %s", __func__,
484 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
485 	    rdr->conf.name);
486 
487 	return (0);
488 }
489 
490 int
491 config_getvirt(struct relayd *env, struct imsg *imsg)
492 {
493 	struct rdr	*rdr;
494 	struct address	*virt;
495 
496 	IMSG_SIZE_CHECK(imsg, virt);
497 
498 	if ((virt = calloc(1, sizeof(*virt))) == NULL)
499 		return (-1);
500 	memcpy(virt, imsg->data, sizeof(*virt));
501 
502 	if ((rdr = rdr_find(env, virt->rdrid)) == NULL) {
503 		log_debug("%s: rdr not found", __func__);
504 		free(virt);
505 		return (-1);
506 	}
507 
508 	TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
509 
510 	DPRINTF("%s: %s %d received address for rdr %s", __func__,
511 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
512 	    rdr->conf.name);
513 
514 	return (0);
515 }
516 
517 int
518 config_setrt(struct relayd *env, struct router *rt)
519 {
520 	struct privsep	*ps = env->sc_ps;
521 	struct netroute	*nr;
522 	int		 id;
523 
524 	for (id = 0; id < PROC_MAX; id++) {
525 		if ((ps->ps_what[id] & CONFIG_RTS) == 0 ||
526 		    id == privsep_process)
527 			continue;
528 
529 		DPRINTF("%s: sending router %s to %s tbl %d", __func__,
530 		    rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable);
531 
532 		proc_compose(ps, id, IMSG_CFG_ROUTER,
533 		    &rt->rt_conf, sizeof(rt->rt_conf));
534 
535 		TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
536 			proc_compose(ps, id, IMSG_CFG_ROUTE,
537 			    &nr->nr_conf, sizeof(nr->nr_conf));
538 		}
539 	}
540 
541 	return (0);
542 }
543 
544 int
545 config_getrt(struct relayd *env, struct imsg *imsg)
546 {
547 	struct router		*rt;
548 
549 	if ((rt = calloc(1, sizeof(*rt))) == NULL)
550 		return (-1);
551 
552 	IMSG_SIZE_CHECK(imsg, &rt->rt_conf);
553 	memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
554 
555 	if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) {
556 		log_debug("%s: table not found", __func__);
557 		free(rt);
558 		return (-1);
559 	}
560 
561 	TAILQ_INIT(&rt->rt_netroutes);
562 	TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry);
563 
564 	env->sc_routercount++;
565 
566 	DPRINTF("%s: %s %d received router %s", __func__,
567 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
568 	    rt->rt_conf.name);
569 
570 	return (0);
571 }
572 
573 int
574 config_getroute(struct relayd *env, struct imsg *imsg)
575 {
576 	struct router		*rt;
577 	struct netroute		*nr;
578 
579 	if ((nr = calloc(1, sizeof(*nr))) == NULL)
580 		return (-1);
581 
582 	IMSG_SIZE_CHECK(imsg, &nr->nr_conf);
583 	memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
584 
585 	if (route_find(env, nr->nr_conf.id) != NULL) {
586 		log_debug("%s: route %d already exists",
587 		    __func__, nr->nr_conf.id);
588 		free(nr);
589 		return (-1);
590 	}
591 
592 	if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) {
593 		log_debug("%s: received route for unknown router", __func__);
594 		free(nr);
595 		return (-1);
596 	}
597 
598 	nr->nr_router = rt;
599 
600 	TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route);
601 	TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry);
602 
603 	env->sc_routecount++;
604 
605 	DPRINTF("%s: %s %d received route %d for router %s", __func__,
606 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
607 	    nr->nr_conf.id, rt->rt_conf.name);
608 
609 	return (0);
610 }
611 
612 int
613 config_setproto(struct relayd *env, struct protocol *proto)
614 {
615 	struct privsep		*ps = env->sc_ps;
616 	int			 id;
617 	struct iovec		 iov[IOV_MAX];
618 	size_t			 c;
619 
620 	for (id = 0; id < PROC_MAX; id++) {
621 		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
622 		    id == privsep_process)
623 			continue;
624 
625 		DPRINTF("%s: sending protocol %s to %s", __func__,
626 		    proto->name, ps->ps_title[id]);
627 
628 		c = 0;
629 		iov[c].iov_base = proto;
630 		iov[c++].iov_len = sizeof(*proto);
631 
632 		if (proto->style != NULL) {
633 			iov[c].iov_base = proto->style;
634 			iov[c++].iov_len = strlen(proto->style) + 1;
635 		}
636 
637 		proc_composev(ps, id, IMSG_CFG_PROTO, iov, c);
638 	}
639 
640 	return (0);
641 }
642 
643 int
644 config_setrule(struct relayd *env, struct protocol *proto)
645 {
646 	struct privsep		*ps = env->sc_ps;
647 	struct relay_rule	*rule;
648 	struct iovec		 iov[IOV_MAX];
649 	int			 id;
650 	size_t			 c, i;
651 
652 	for (id = 0; id < PROC_MAX; id++) {
653 		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
654 		    id == privsep_process)
655 			continue;
656 
657 		DPRINTF("%s: sending rules %s to %s", __func__,
658 		    proto->name, ps->ps_title[id]);
659 
660 		/* Now send all the rules */
661 		TAILQ_FOREACH(rule, &proto->rules, rule_entry) {
662 			rule->rule_protoid = proto->id;
663 			bzero(&rule->rule_ctl, sizeof(rule->rule_ctl));
664 			c = 0;
665 			iov[c].iov_base = rule;
666 			iov[c++].iov_len = sizeof(*rule);
667 			for (i = 1; i < KEY_TYPE_MAX; i++) {
668 				if (rule->rule_kv[i].kv_key != NULL) {
669 					rule->rule_ctl.kvlen[i].key =
670 					    strlen(rule->rule_kv[i].kv_key);
671 					iov[c].iov_base =
672 					    rule->rule_kv[i].kv_key;
673 					iov[c++].iov_len =
674 					    rule->rule_ctl.kvlen[i].key;
675 				} else
676 					rule->rule_ctl.kvlen[i].key = -1;
677 				if (rule->rule_kv[i].kv_value != NULL) {
678 					rule->rule_ctl.kvlen[i].value =
679 					    strlen(rule->rule_kv[i].kv_value);
680 					iov[c].iov_base =
681 					    rule->rule_kv[i].kv_value;
682 					iov[c++].iov_len =
683 					    rule->rule_ctl.kvlen[i].value;
684 				} else
685 					rule->rule_ctl.kvlen[i].value = -1;
686 			}
687 
688 			proc_composev(ps, id, IMSG_CFG_RULE, iov, c);
689 		}
690 	}
691 
692 	return (0);
693 }
694 
695 int
696 config_getproto(struct relayd *env, struct imsg *imsg)
697 {
698 	struct protocol		*proto;
699 	size_t			 styl;
700 	size_t			 s;
701 	u_int8_t		*p = imsg->data;
702 
703 	if ((proto = calloc(1, sizeof(*proto))) == NULL)
704 		return (-1);
705 
706 	IMSG_SIZE_CHECK(imsg, proto);
707 	memcpy(proto, p, sizeof(*proto));
708 	s = sizeof(*proto);
709 
710 	styl = IMSG_DATA_SIZE(imsg) - s;
711 	proto->style = NULL;
712 	if (styl > 0) {
713 		if ((proto->style = get_string(p + s, styl - 1)) == NULL) {
714 			free(proto);
715 			return (-1);
716 		}
717 	}
718 
719 	TAILQ_INIT(&proto->rules);
720 	TAILQ_INIT(&proto->tlscerts);
721 	proto->tlscapass = NULL;
722 
723 	TAILQ_INSERT_TAIL(env->sc_protos, proto, entry);
724 
725 	env->sc_protocount++;
726 
727 	DPRINTF("%s: %s %d received protocol %s", __func__,
728 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
729 	    proto->name);
730 
731 	return (0);
732 }
733 
734 int
735 config_getrule(struct relayd *env, struct imsg *imsg)
736 {
737 	struct protocol		*proto;
738 	struct relay_rule	*rule;
739 	size_t			 s, i;
740 	u_int8_t		*p = imsg->data;
741 	ssize_t			 len;
742 
743 	if ((rule = calloc(1, sizeof(*rule))) == NULL)
744 		return (-1);
745 
746 	IMSG_SIZE_CHECK(imsg, rule);
747 	memcpy(rule, p, sizeof(*rule));
748 	s = sizeof(*rule);
749 	len = IMSG_DATA_SIZE(imsg) - s;
750 
751 	if ((proto = proto_find(env, rule->rule_protoid)) == NULL) {
752 		free(rule);
753 		return (-1);
754 	}
755 
756 #define GETKV(_n, _f)	{						\
757 	if (rule->rule_ctl.kvlen[_n]._f >= 0) {				\
758 		/* Also accept "empty" 0-length strings */		\
759 		if ((len < rule->rule_ctl.kvlen[_n]._f) ||		\
760 		    (rule->rule_kv[_n].kv_##_f =			\
761 		    get_string(p + s,					\
762 		    rule->rule_ctl.kvlen[_n]._f)) == NULL) {		\
763 			free(rule);					\
764 			return (-1);					\
765 		}							\
766 		s += rule->rule_ctl.kvlen[_n]._f;			\
767 		len -= rule->rule_ctl.kvlen[_n]._f;			\
768 									\
769 		DPRINTF("%s: %s %s (len %ld, option %d): %s", __func__,	\
770 		    #_n, #_f, rule->rule_ctl.kvlen[_n]._f,		\
771 		    rule->rule_kv[_n].kv_option,			\
772 		    rule->rule_kv[_n].kv_##_f);				\
773 	}								\
774 }
775 
776 	memset(&rule->rule_kv[0], 0, sizeof(struct kv));
777 	for (i = 1; i < KEY_TYPE_MAX; i++) {
778 		TAILQ_INIT(&rule->rule_kv[i].kv_children);
779 		GETKV(i, key);
780 		GETKV(i, value);
781 	}
782 
783 	if (rule->rule_labelname[0])
784 		rule->rule_label = label_name2id(rule->rule_labelname);
785 
786 	if (rule->rule_tagname[0])
787 		rule->rule_tag = tag_name2id(rule->rule_tagname);
788 
789 	if (rule->rule_taggedname[0])
790 		rule->rule_tagged = tag_name2id(rule->rule_taggedname);
791 
792 	rule->rule_id = proto->rulecount++;
793 
794 	TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry);
795 
796 	DPRINTF("%s: %s %d received rule %u for protocol %s", __func__,
797 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
798 	    rule->rule_id, proto->name);
799 
800 	return (0);
801 }
802 
803 static int
804 config_setrelayfd(struct privsep *ps, int id, int n,
805     objid_t obj_id, objid_t rlay_id, enum fd_type type, int ofd)
806 {
807 	struct ctl_relayfd	rfd;
808 	int			fd;
809 
810 	rfd.id = obj_id;
811 	rfd.relayid = rlay_id;
812 	rfd.type = type;
813 
814 	if ((fd = dup(ofd)) == -1)
815 		return (-1);
816 	if (proc_compose_imsg(ps, id, n, IMSG_CFG_RELAY_FD, -1, fd,
817 	    &rfd, sizeof(rfd)) != 0)
818 		return (-1);
819 
820 	return (0);
821 }
822 
823 int
824 config_setrelay(struct relayd *env, struct relay *rlay)
825 {
826 	struct privsep		*ps = env->sc_ps;
827 	struct ctl_relaytable	 crt;
828 	struct relay_table	*rlt;
829 	struct relay_config	 rl;
830 	struct relay_cert	*cert;
831 	int			 id;
832 	int			 fd, n, m;
833 	struct iovec		 iov[6];
834 	size_t			 c;
835 	u_int			 what;
836 
837 	/* opens listening sockets etc. */
838 	if (relay_privinit(rlay) == -1)
839 		return (-1);
840 
841 	for (id = 0; id < PROC_MAX; id++) {
842 		what = ps->ps_what[id];
843 
844 		if ((what & CONFIG_RELAYS) == 0 || id == privsep_process)
845 			continue;
846 
847 		DPRINTF("%s: sending relay %s to %s fd %d", __func__,
848 		    rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s);
849 
850 		memcpy(&rl, &rlay->rl_conf, sizeof(rl));
851 
852 		c = 0;
853 		iov[c].iov_base = &rl;
854 		iov[c++].iov_len = sizeof(rl);
855 
856 		if ((what & CONFIG_CA_ENGINE) == 0 &&
857 		    rl.tls_cakey_len) {
858 			iov[c].iov_base = rlay->rl_tls_cakey;
859 			iov[c++].iov_len = rl.tls_cakey_len;
860 		} else
861 			rl.tls_cakey_len = 0;
862 
863 		if (id == PROC_RELAY) {
864 			/* XXX imsg code will close the fd after 1st call */
865 			n = -1;
866 			proc_range(ps, id, &n, &m);
867 			for (n = 0; n < m; n++) {
868 				if ((fd = dup(rlay->rl_s)) == -1)
869 					return (-1);
870 				if (proc_composev_imsg(ps, id, n,
871 				    IMSG_CFG_RELAY, -1, fd, iov, c) != 0) {
872 					log_warn("%s: failed to compose "
873 					    "IMSG_CFG_RELAY imsg for `%s'",
874 					    __func__, rlay->rl_conf.name);
875 					return (-1);
876 				}
877 				/* Prevent fd exhaustion in the parent. */
878 				if (proc_flush_imsg(ps, id, n) == -1) {
879 					log_warn("%s: failed to flush "
880 					    "IMSG_CFG_RELAY imsg for `%s'",
881 					    __func__, rlay->rl_conf.name);
882 					return (-1);
883 				}
884 			}
885 		} else {
886 			if (proc_composev(ps, id,
887 			    IMSG_CFG_RELAY, iov, c) != 0) {
888 				log_warn("%s: failed to compose "
889 				    "IMSG_CFG_RELAY imsg for `%s'",
890 				    __func__, rlay->rl_conf.name);
891 				return (-1);
892 			}
893 		}
894 
895 		/* cert keypairs */
896 		TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
897 			if (cert->cert_relayid != rlay->rl_conf.id)
898 				continue;
899 			n = -1;
900 			proc_range(ps, id, &n, &m);
901 			for (n = 0; (what & CONFIG_CERTS) && n < m; n++) {
902 				if (cert->cert_fd != -1 &&
903 				    config_setrelayfd(ps, id, n,
904 				    cert->cert_id, cert->cert_relayid,
905 				    RELAY_FD_CERT, cert->cert_fd) == -1) {
906 					log_warn("%s: fd passing failed for "
907 					    "`%s'", __func__,
908 					    rlay->rl_conf.name);
909 					return (-1);
910 				}
911 				if (id == PROC_RELAY &&
912 				    cert->cert_ocsp_fd != -1 &&
913 				    config_setrelayfd(ps, id, n,
914 				    cert->cert_id, cert->cert_relayid,
915 				    RELAY_FD_OCSP, cert->cert_ocsp_fd) == -1) {
916 					log_warn("%s: fd passing failed for "
917 					    "`%s'", __func__,
918 					    rlay->rl_conf.name);
919 					return (-1);
920 				}
921 				if (id == PROC_CA &&
922 				    cert->cert_key_fd != -1 &&
923 				    config_setrelayfd(ps, id, n,
924 				    cert->cert_id, cert->cert_relayid,
925 				    RELAY_FD_KEY, cert->cert_key_fd) == -1) {
926 					log_warn("%s: fd passing failed for "
927 					    "`%s'", __func__,
928 					    rlay->rl_conf.name);
929 					return (-1);
930 				}
931 			}
932 		}
933 
934 		/* CA certs */
935 		if (what & CONFIG_CERTS) {
936 			n = -1;
937 			proc_range(ps, id, &n, &m);
938 			for (n = 0; n < m; n++) {
939 				if (rlay->rl_tls_ca_fd != -1 &&
940 				    config_setrelayfd(ps, id, n, 0,
941 				    rlay->rl_conf.id, RELAY_FD_CACERT,
942 				    rlay->rl_tls_ca_fd) == -1) {
943 					log_warn("%s: fd passing failed for "
944 					    "`%s'", __func__,
945 					    rlay->rl_conf.name);
946 					return (-1);
947 				}
948 				if (rlay->rl_tls_cacert_fd != -1 &&
949 				    config_setrelayfd(ps, id, n, 0,
950 				    rlay->rl_conf.id, RELAY_FD_CAFILE,
951 				    rlay->rl_tls_cacert_fd) == -1) {
952 					log_warn("%s: fd passing failed for "
953 					    "`%s'", __func__,
954 					    rlay->rl_conf.name);
955 					return (-1);
956 				}
957 				/* Prevent fd exhaustion in the parent. */
958 				if (proc_flush_imsg(ps, id, n) == -1) {
959 					log_warn("%s: failed to flush "
960 					    "IMSG_CFG_RELAY imsg for `%s'",
961 					    __func__, rlay->rl_conf.name);
962 					return (-1);
963 				}
964 			}
965 		}
966 
967 		if ((what & CONFIG_TABLES) == 0)
968 			continue;
969 
970 		/* Now send the tables associated to this relay */
971 		TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
972 			crt.id = rlt->rlt_table->conf.id;
973 			crt.relayid = rlay->rl_conf.id;
974 			crt.mode = rlt->rlt_mode;
975 			crt.flags = rlt->rlt_flags;
976 
977 			c = 0;
978 			iov[c].iov_base = &crt;
979 			iov[c++].iov_len = sizeof(crt);
980 
981 			proc_composev(ps, id, IMSG_CFG_RELAY_TABLE, iov, c);
982 		}
983 	}
984 
985 	/* Close server socket early to prevent fd exhaustion in the parent. */
986 	if (rlay->rl_s != -1) {
987 		close(rlay->rl_s);
988 		rlay->rl_s = -1;
989 	}
990 	if (rlay->rl_tls_cacert_fd != -1) {
991 		close(rlay->rl_tls_cacert_fd);
992 		rlay->rl_tls_cacert_fd = -1;
993 	}
994 	if (rlay->rl_tls_ca_fd != -1) {
995 		close(rlay->rl_tls_ca_fd);
996 		rlay->rl_tls_ca_fd = -1;
997 	}
998 	TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
999 		if (cert->cert_relayid != rlay->rl_conf.id)
1000 			continue;
1001 
1002 		if (cert->cert_fd != -1) {
1003 			close(cert->cert_fd);
1004 			cert->cert_fd = -1;
1005 		}
1006 		if (cert->cert_key_fd != -1) {
1007 			close(cert->cert_key_fd);
1008 			cert->cert_key_fd = -1;
1009 		}
1010 		if (cert->cert_ocsp_fd != -1) {
1011 			close(cert->cert_ocsp_fd);
1012 			cert->cert_ocsp_fd = -1;
1013 		}
1014 	}
1015 
1016 	return (0);
1017 }
1018 
1019 int
1020 config_getrelay(struct relayd *env, struct imsg *imsg)
1021 {
1022 	struct privsep		*ps = env->sc_ps;
1023 	struct relay		*rlay;
1024 	u_int8_t		*p = imsg->data;
1025 	size_t			 s;
1026 
1027 	if ((rlay = calloc(1, sizeof(*rlay))) == NULL)
1028 		return (-1);
1029 
1030 	IMSG_SIZE_CHECK(imsg, &rlay->rl_conf);
1031 	memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
1032 	s = sizeof(rlay->rl_conf);
1033 
1034 	rlay->rl_s = imsg->fd;
1035 	rlay->rl_tls_ca_fd = -1;
1036 	rlay->rl_tls_cacert_fd = -1;
1037 
1038 	if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
1039 		if (rlay->rl_conf.proto == EMPTY_ID)
1040 			rlay->rl_proto = &env->sc_proto_default;
1041 		else if ((rlay->rl_proto =
1042 		    proto_find(env, rlay->rl_conf.proto)) == NULL) {
1043 			log_debug("%s: unknown protocol", __func__);
1044 			goto fail;
1045 		}
1046 	}
1047 
1048 	if ((off_t)(IMSG_DATA_SIZE(imsg) - s) <
1049 	    (rlay->rl_conf.tls_cakey_len)) {
1050 		log_debug("%s: invalid message length", __func__);
1051 		goto fail;
1052 	}
1053 
1054 	if (rlay->rl_conf.tls_cakey_len) {
1055 		if ((rlay->rl_tls_cakey = get_data(p + s,
1056 		    rlay->rl_conf.tls_cakey_len)) == NULL)
1057 			goto fail;
1058 		s += rlay->rl_conf.tls_cakey_len;
1059 	}
1060 
1061 	TAILQ_INIT(&rlay->rl_tables);
1062 	TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
1063 
1064 	env->sc_relaycount++;
1065 
1066 	DPRINTF("%s: %s %d received relay %s", __func__,
1067 	    ps->ps_title[privsep_process], ps->ps_instance,
1068 	    rlay->rl_conf.name);
1069 
1070 	return (0);
1071 
1072  fail:
1073 	free(rlay->rl_tls_cakey);
1074 	close(rlay->rl_s);
1075 	free(rlay);
1076 	return (-1);
1077 }
1078 
1079 int
1080 config_getrelaytable(struct relayd *env, struct imsg *imsg)
1081 {
1082 	struct relay_table	*rlt = NULL;
1083 	struct ctl_relaytable	 crt;
1084 	struct relay		*rlay;
1085 	struct table		*table;
1086 	u_int8_t		*p = imsg->data;
1087 
1088 	IMSG_SIZE_CHECK(imsg, &crt);
1089 	memcpy(&crt, p, sizeof(crt));
1090 
1091 	if ((rlay = relay_find(env, crt.relayid)) == NULL) {
1092 		log_debug("%s: unknown relay", __func__);
1093 		goto fail;
1094 	}
1095 
1096 	if ((table = table_find(env, crt.id)) == NULL) {
1097 		log_debug("%s: unknown table", __func__);
1098 		goto fail;
1099 	}
1100 
1101 	if ((rlt = calloc(1, sizeof(*rlt))) == NULL)
1102 		goto fail;
1103 
1104 	rlt->rlt_table = table;
1105 	rlt->rlt_mode = crt.mode;
1106 	rlt->rlt_flags = crt.flags;
1107 
1108 	TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
1109 
1110 	DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,
1111 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1112 	    table->conf.name, rlay->rl_conf.name);
1113 
1114 	return (0);
1115 
1116  fail:
1117 	free(rlt);
1118 	return (-1);
1119 }
1120 
1121 int
1122 config_getrelayfd(struct relayd *env, struct imsg *imsg)
1123 {
1124 	struct ctl_relayfd	 crfd;
1125 	struct relay		*rlay = NULL;
1126 	struct relay_cert	*cert;
1127 	u_int8_t		*p = imsg->data;
1128 
1129 	IMSG_SIZE_CHECK(imsg, &crfd);
1130 	memcpy(&crfd, p, sizeof(crfd));
1131 
1132 	switch (crfd.type) {
1133 	case RELAY_FD_CERT:
1134 	case RELAY_FD_KEY:
1135 	case RELAY_FD_OCSP:
1136 		if ((cert = cert_find(env, crfd.id)) == NULL) {
1137 			if ((cert = cert_add(env, crfd.id)) == NULL)
1138 				return (-1);
1139 			cert->cert_relayid = crfd.relayid;
1140 		}
1141 		/* FALLTHROUGH */
1142 	default:
1143 		if ((rlay = relay_find(env, crfd.relayid)) == NULL) {
1144 			log_debug("%s: unknown relay", __func__);
1145 			return (-1);
1146 		}
1147 		break;
1148 	}
1149 
1150 	switch (crfd.type) {
1151 	case RELAY_FD_CERT:
1152 		cert->cert_fd = imsg->fd;
1153 		break;
1154 	case RELAY_FD_KEY:
1155 		cert->cert_key_fd = imsg->fd;
1156 		break;
1157 	case RELAY_FD_OCSP:
1158 		cert->cert_ocsp_fd = imsg->fd;
1159 		break;
1160 	case RELAY_FD_CACERT:
1161 		rlay->rl_tls_ca_fd = imsg->fd;
1162 		break;
1163 	case RELAY_FD_CAFILE:
1164 		rlay->rl_tls_cacert_fd = imsg->fd;
1165 		break;
1166 	}
1167 
1168 	DPRINTF("%s: %s %d received relay fd %d type %d for relay %s", __func__,
1169 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1170 	    imsg->fd, crfd.type, rlay->rl_conf.name);
1171 
1172 	return (0);
1173 }
1174