xref: /openbsd/usr.sbin/relayd/config.c (revision 09467b48)
1 /*	$OpenBSD: config.c,v 1.41 2019/09/15 19:23:29 rob 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 			free(proto);
196 			while ((keyname =
197 			    TAILQ_FIRST(&proto->tlscerts)) != NULL) {
198 				TAILQ_REMOVE(&proto->tlscerts, keyname, entry);
199 				free(keyname->name);
200 				free(keyname);
201 			}
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 		if (tls_init() == -1)
300 			fatalx("unable to initialize TLS");
301 	}
302 
303 	if (privsep_process != PROC_PARENT)
304 		proc_compose(env->sc_ps, PROC_PARENT, IMSG_CFG_DONE, NULL, 0);
305 
306 	return (0);
307 }
308 
309 int
310 config_settable(struct relayd *env, struct table *tb)
311 {
312 	struct privsep	*ps = env->sc_ps;
313 	struct host	*host;
314 	int		 id, c;
315 	struct iovec	 iov[2];
316 
317 	for (id = 0; id < PROC_MAX; id++) {
318 		if ((ps->ps_what[id] & CONFIG_TABLES) == 0 ||
319 		    id == privsep_process)
320 			continue;
321 
322 		/* XXX need to send table to pfe for control socket */
323 		if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK)
324 			continue;
325 
326 		DPRINTF("%s: sending table %s %d to %s", __func__,
327 		    tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]);
328 
329 		c = 0;
330 		iov[c].iov_base = &tb->conf;
331 		iov[c++].iov_len = sizeof(tb->conf);
332 		if (tb->sendbuf != NULL) {
333 			iov[c].iov_base = tb->sendbuf;
334 			iov[c++].iov_len = strlen(tb->sendbuf);
335 		}
336 
337 		proc_composev(ps, id, IMSG_CFG_TABLE, iov, c);
338 
339 		TAILQ_FOREACH(host, &tb->hosts, entry) {
340 			proc_compose(ps, id, IMSG_CFG_HOST,
341 			    &host->conf, sizeof(host->conf));
342 		}
343 	}
344 
345 	return (0);
346 }
347 
348 int
349 config_gettable(struct relayd *env, struct imsg *imsg)
350 {
351 	struct table		*tb;
352 	size_t			 sb;
353 	u_int8_t		*p = imsg->data;
354 	size_t			 s;
355 
356 	if ((tb = calloc(1, sizeof(*tb))) == NULL)
357 		return (-1);
358 
359 	IMSG_SIZE_CHECK(imsg, &tb->conf);
360 	memcpy(&tb->conf, p, sizeof(tb->conf));
361 	s = sizeof(tb->conf);
362 
363 	sb = IMSG_DATA_SIZE(imsg) - s;
364 	if (sb > 0) {
365 		if ((tb->sendbuf = get_string(p + s, sb)) == NULL) {
366 			free(tb);
367 			return (-1);
368 		}
369 	}
370 	if (tb->conf.check == CHECK_BINSEND_EXPECT) {
371 		tb->sendbinbuf = string2binary(tb->sendbuf);
372 		if (tb->sendbinbuf == NULL) {
373 			free(tb);
374 			return (-1);
375 		}
376 	}
377 
378 	TAILQ_INIT(&tb->hosts);
379 	TAILQ_INSERT_TAIL(env->sc_tables, tb, entry);
380 
381 	env->sc_tablecount++;
382 
383 	DPRINTF("%s: %s %d received table %d (%s)", __func__,
384 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
385 	    tb->conf.id, tb->conf.name);
386 
387 	return (0);
388 }
389 
390 int
391 config_gethost(struct relayd *env, struct imsg *imsg)
392 {
393 	struct table		*tb;
394 	struct host		*host;
395 
396 	if ((host = calloc(1, sizeof(*host))) == NULL)
397 		return (-1);
398 
399 	IMSG_SIZE_CHECK(imsg, &host->conf);
400 	memcpy(&host->conf, imsg->data, sizeof(host->conf));
401 
402 	if (host_find(env, host->conf.id) != NULL) {
403 		log_debug("%s: host %d already exists",
404 		    __func__, host->conf.id);
405 		free(host);
406 		return (-1);
407 	}
408 
409 	if ((tb = table_find(env, host->conf.tableid)) == NULL) {
410 		log_debug("%s: "
411 		    "received host for unknown table %d", __func__,
412 		    host->conf.tableid);
413 		free(host);
414 		return (-1);
415 	}
416 
417 	host->tablename = tb->conf.name;
418 	host->cte.s = -1;
419 
420 	SLIST_INIT(&host->children);
421 	TAILQ_INSERT_TAIL(&tb->hosts, host, entry);
422 	TAILQ_INSERT_TAIL(&env->sc_hosts, host, globalentry);
423 
424 	DPRINTF("%s: %s %d received host %s for table %s", __func__,
425 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
426 	    host->conf.name, tb->conf.name);
427 
428 	return (0);
429 }
430 
431 int
432 config_setrdr(struct relayd *env, struct rdr *rdr)
433 {
434 	struct privsep	*ps = env->sc_ps;
435 	struct address	*virt;
436 	int		 id;
437 
438 	for (id = 0; id < PROC_MAX; id++) {
439 		if ((ps->ps_what[id] & CONFIG_RDRS) == 0 ||
440 		    id == privsep_process)
441 			continue;
442 
443 		DPRINTF("%s: sending rdr %s to %s", __func__,
444 		    rdr->conf.name, ps->ps_title[id]);
445 
446 		proc_compose(ps, id, IMSG_CFG_RDR,
447 		    &rdr->conf, sizeof(rdr->conf));
448 
449 		TAILQ_FOREACH(virt, &rdr->virts, entry) {
450 			virt->rdrid = rdr->conf.id;
451 			proc_compose(ps, id, IMSG_CFG_VIRT,
452 			    virt, sizeof(*virt));
453 		}
454 	}
455 
456 	return (0);
457 }
458 
459 int
460 config_getrdr(struct relayd *env, struct imsg *imsg)
461 {
462 	struct rdr		*rdr;
463 
464 	if ((rdr = calloc(1, sizeof(*rdr))) == NULL)
465 		return (-1);
466 
467 	IMSG_SIZE_CHECK(imsg, &rdr->conf);
468 	memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf));
469 
470 	if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) {
471 		log_debug("%s: table not found", __func__);
472 		free(rdr);
473 		return (-1);
474 	}
475 	if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) {
476 		rdr->conf.backup_id = EMPTY_TABLE;
477 		rdr->backup = &env->sc_empty_table;
478 	}
479 
480 	TAILQ_INIT(&rdr->virts);
481 	TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry);
482 
483 	env->sc_rdrcount++;
484 
485 	DPRINTF("%s: %s %d received rdr %s", __func__,
486 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
487 	    rdr->conf.name);
488 
489 	return (0);
490 }
491 
492 int
493 config_getvirt(struct relayd *env, struct imsg *imsg)
494 {
495 	struct rdr	*rdr;
496 	struct address	*virt;
497 
498 	IMSG_SIZE_CHECK(imsg, virt);
499 
500 	if ((virt = calloc(1, sizeof(*virt))) == NULL)
501 		return (-1);
502 	memcpy(virt, imsg->data, sizeof(*virt));
503 
504 	if ((rdr = rdr_find(env, virt->rdrid)) == NULL) {
505 		log_debug("%s: rdr not found", __func__);
506 		free(virt);
507 		return (-1);
508 	}
509 
510 	TAILQ_INSERT_TAIL(&rdr->virts, virt, entry);
511 
512 	DPRINTF("%s: %s %d received address for rdr %s", __func__,
513 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
514 	    rdr->conf.name);
515 
516 	return (0);
517 }
518 
519 int
520 config_setrt(struct relayd *env, struct router *rt)
521 {
522 	struct privsep	*ps = env->sc_ps;
523 	struct netroute	*nr;
524 	int		 id;
525 
526 	for (id = 0; id < PROC_MAX; id++) {
527 		if ((ps->ps_what[id] & CONFIG_RTS) == 0 ||
528 		    id == privsep_process)
529 			continue;
530 
531 		DPRINTF("%s: sending router %s to %s tbl %d", __func__,
532 		    rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable);
533 
534 		proc_compose(ps, id, IMSG_CFG_ROUTER,
535 		    &rt->rt_conf, sizeof(rt->rt_conf));
536 
537 		TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
538 			proc_compose(ps, id, IMSG_CFG_ROUTE,
539 			    &nr->nr_conf, sizeof(nr->nr_conf));
540 		}
541 	}
542 
543 	return (0);
544 }
545 
546 int
547 config_getrt(struct relayd *env, struct imsg *imsg)
548 {
549 	struct router		*rt;
550 
551 	if ((rt = calloc(1, sizeof(*rt))) == NULL)
552 		return (-1);
553 
554 	IMSG_SIZE_CHECK(imsg, &rt->rt_conf);
555 	memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf));
556 
557 	if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) {
558 		log_debug("%s: table not found", __func__);
559 		free(rt);
560 		return (-1);
561 	}
562 
563 	TAILQ_INIT(&rt->rt_netroutes);
564 	TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry);
565 
566 	env->sc_routercount++;
567 
568 	DPRINTF("%s: %s %d received router %s", __func__,
569 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
570 	    rt->rt_conf.name);
571 
572 	return (0);
573 }
574 
575 int
576 config_getroute(struct relayd *env, struct imsg *imsg)
577 {
578 	struct router		*rt;
579 	struct netroute		*nr;
580 
581 	if ((nr = calloc(1, sizeof(*nr))) == NULL)
582 		return (-1);
583 
584 	IMSG_SIZE_CHECK(imsg, &nr->nr_conf);
585 	memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf));
586 
587 	if (route_find(env, nr->nr_conf.id) != NULL) {
588 		log_debug("%s: route %d already exists",
589 		    __func__, nr->nr_conf.id);
590 		free(nr);
591 		return (-1);
592 	}
593 
594 	if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) {
595 		log_debug("%s: received route for unknown router", __func__);
596 		free(nr);
597 		return (-1);
598 	}
599 
600 	nr->nr_router = rt;
601 
602 	TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route);
603 	TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry);
604 
605 	env->sc_routecount++;
606 
607 	DPRINTF("%s: %s %d received route %d for router %s", __func__,
608 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
609 	    nr->nr_conf.id, rt->rt_conf.name);
610 
611 	return (0);
612 }
613 
614 int
615 config_setproto(struct relayd *env, struct protocol *proto)
616 {
617 	struct privsep		*ps = env->sc_ps;
618 	int			 id;
619 	struct iovec		 iov[IOV_MAX];
620 	size_t			 c;
621 
622 	for (id = 0; id < PROC_MAX; id++) {
623 		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
624 		    id == privsep_process)
625 			continue;
626 
627 		DPRINTF("%s: sending protocol %s to %s", __func__,
628 		    proto->name, ps->ps_title[id]);
629 
630 		c = 0;
631 		iov[c].iov_base = proto;
632 		iov[c++].iov_len = sizeof(*proto);
633 
634 		if (proto->style != NULL) {
635 			iov[c].iov_base = proto->style;
636 			iov[c++].iov_len = strlen(proto->style) + 1;
637 		}
638 
639 		proc_composev(ps, id, IMSG_CFG_PROTO, iov, c);
640 	}
641 
642 	return (0);
643 }
644 
645 int
646 config_setrule(struct relayd *env, struct protocol *proto)
647 {
648 	struct privsep		*ps = env->sc_ps;
649 	struct relay_rule	*rule;
650 	struct iovec		 iov[IOV_MAX];
651 	int			 id;
652 	size_t			 c, i;
653 
654 	for (id = 0; id < PROC_MAX; id++) {
655 		if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 ||
656 		    id == privsep_process)
657 			continue;
658 
659 		DPRINTF("%s: sending rules %s to %s", __func__,
660 		    proto->name, ps->ps_title[id]);
661 
662 		/* Now send all the rules */
663 		TAILQ_FOREACH(rule, &proto->rules, rule_entry) {
664 			rule->rule_protoid = proto->id;
665 			bzero(&rule->rule_ctl, sizeof(rule->rule_ctl));
666 			c = 0;
667 			iov[c].iov_base = rule;
668 			iov[c++].iov_len = sizeof(*rule);
669 			for (i = 1; i < KEY_TYPE_MAX; i++) {
670 				if (rule->rule_kv[i].kv_key != NULL) {
671 					rule->rule_ctl.kvlen[i].key =
672 					    strlen(rule->rule_kv[i].kv_key);
673 					iov[c].iov_base =
674 					    rule->rule_kv[i].kv_key;
675 					iov[c++].iov_len =
676 					    rule->rule_ctl.kvlen[i].key;
677 				} else
678 					rule->rule_ctl.kvlen[i].key = -1;
679 				if (rule->rule_kv[i].kv_value != NULL) {
680 					rule->rule_ctl.kvlen[i].value =
681 					    strlen(rule->rule_kv[i].kv_value);
682 					iov[c].iov_base =
683 					    rule->rule_kv[i].kv_value;
684 					iov[c++].iov_len =
685 					    rule->rule_ctl.kvlen[i].value;
686 				} else
687 					rule->rule_ctl.kvlen[i].value = -1;
688 			}
689 
690 			proc_composev(ps, id, IMSG_CFG_RULE, iov, c);
691 		}
692 	}
693 
694 	return (0);
695 }
696 
697 int
698 config_getproto(struct relayd *env, struct imsg *imsg)
699 {
700 	struct protocol		*proto;
701 	size_t			 styl;
702 	size_t			 s;
703 	u_int8_t		*p = imsg->data;
704 
705 	if ((proto = calloc(1, sizeof(*proto))) == NULL)
706 		return (-1);
707 
708 	IMSG_SIZE_CHECK(imsg, proto);
709 	memcpy(proto, p, sizeof(*proto));
710 	s = sizeof(*proto);
711 
712 	styl = IMSG_DATA_SIZE(imsg) - s;
713 	proto->style = NULL;
714 	if (styl > 0) {
715 		if ((proto->style = get_string(p + s, styl - 1)) == NULL) {
716 			free(proto);
717 			return (-1);
718 		}
719 	}
720 
721 	TAILQ_INIT(&proto->rules);
722 	TAILQ_INIT(&proto->tlscerts);
723 	proto->tlscapass = NULL;
724 
725 	TAILQ_INSERT_TAIL(env->sc_protos, proto, entry);
726 
727 	env->sc_protocount++;
728 
729 	DPRINTF("%s: %s %d received protocol %s", __func__,
730 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
731 	    proto->name);
732 
733 	return (0);
734 }
735 
736 int
737 config_getrule(struct relayd *env, struct imsg *imsg)
738 {
739 	struct protocol		*proto;
740 	struct relay_rule	*rule;
741 	size_t			 s, i;
742 	u_int8_t		*p = imsg->data;
743 	ssize_t			 len;
744 
745 	if ((rule = calloc(1, sizeof(*rule))) == NULL)
746 		return (-1);
747 
748 	IMSG_SIZE_CHECK(imsg, rule);
749 	memcpy(rule, p, sizeof(*rule));
750 	s = sizeof(*rule);
751 	len = IMSG_DATA_SIZE(imsg) - s;
752 
753 	if ((proto = proto_find(env, rule->rule_protoid)) == NULL) {
754 		free(rule);
755 		return (-1);
756 	}
757 
758 #define GETKV(_n, _f)	{						\
759 	if (rule->rule_ctl.kvlen[_n]._f >= 0) {				\
760 		/* Also accept "empty" 0-length strings */		\
761 		if ((len < rule->rule_ctl.kvlen[_n]._f) ||		\
762 		    (rule->rule_kv[_n].kv_##_f =			\
763 		    get_string(p + s,					\
764 		    rule->rule_ctl.kvlen[_n]._f)) == NULL) {		\
765 			free(rule);					\
766 			return (-1);					\
767 		}							\
768 		s += rule->rule_ctl.kvlen[_n]._f;			\
769 		len -= rule->rule_ctl.kvlen[_n]._f;			\
770 									\
771 		DPRINTF("%s: %s %s (len %ld, option %d): %s", __func__,	\
772 		    #_n, #_f, rule->rule_ctl.kvlen[_n]._f,		\
773 		    rule->rule_kv[_n].kv_option,			\
774 		    rule->rule_kv[_n].kv_##_f);				\
775 	}								\
776 }
777 
778 	memset(&rule->rule_kv[0], 0, sizeof(struct kv));
779 	for (i = 1; i < KEY_TYPE_MAX; i++) {
780 		TAILQ_INIT(&rule->rule_kv[i].kv_children);
781 		GETKV(i, key);
782 		GETKV(i, value);
783 	}
784 
785 	if (rule->rule_labelname[0])
786 		rule->rule_label = label_name2id(rule->rule_labelname);
787 
788 	if (rule->rule_tagname[0])
789 		rule->rule_tag = tag_name2id(rule->rule_tagname);
790 
791 	if (rule->rule_taggedname[0])
792 		rule->rule_tagged = tag_name2id(rule->rule_taggedname);
793 
794 	rule->rule_id = proto->rulecount++;
795 
796 	TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry);
797 
798 	DPRINTF("%s: %s %d received rule %u for protocol %s", __func__,
799 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
800 	    rule->rule_id, proto->name);
801 
802 	return (0);
803 }
804 
805 static int
806 config_setrelayfd(struct privsep *ps, int id, int n,
807     objid_t obj_id, objid_t rlay_id, enum fd_type type, int ofd)
808 {
809 	struct ctl_relayfd	rfd;
810 	int			fd;
811 
812 	rfd.id = obj_id;
813 	rfd.relayid = rlay_id;
814 	rfd.type = type;
815 
816 	if ((fd = dup(ofd)) == -1)
817 		return (-1);
818 	if (proc_compose_imsg(ps, id, n, IMSG_CFG_RELAY_FD, -1, fd,
819 	    &rfd, sizeof(rfd)) != 0)
820 		return (-1);
821 
822 	return (0);
823 }
824 
825 int
826 config_setrelay(struct relayd *env, struct relay *rlay)
827 {
828 	struct privsep		*ps = env->sc_ps;
829 	struct ctl_relaytable	 crt;
830 	struct relay_table	*rlt;
831 	struct relay_config	 rl;
832 	struct relay_cert	*cert;
833 	int			 id;
834 	int			 fd, n, m;
835 	struct iovec		 iov[6];
836 	size_t			 c;
837 	u_int			 what;
838 
839 	/* opens listening sockets etc. */
840 	if (relay_privinit(rlay) == -1)
841 		return (-1);
842 
843 	for (id = 0; id < PROC_MAX; id++) {
844 		what = ps->ps_what[id];
845 
846 		if ((what & CONFIG_RELAYS) == 0 || id == privsep_process)
847 			continue;
848 
849 		DPRINTF("%s: sending relay %s to %s fd %d", __func__,
850 		    rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s);
851 
852 		memcpy(&rl, &rlay->rl_conf, sizeof(rl));
853 
854 		c = 0;
855 		iov[c].iov_base = &rl;
856 		iov[c++].iov_len = sizeof(rl);
857 
858 		if ((what & CONFIG_CA_ENGINE) == 0 &&
859 		    rl.tls_cakey_len) {
860 			iov[c].iov_base = rlay->rl_tls_cakey;
861 			iov[c++].iov_len = rl.tls_cakey_len;
862 		} else
863 			rl.tls_cakey_len = 0;
864 
865 		if (id == PROC_RELAY) {
866 			/* XXX imsg code will close the fd after 1st call */
867 			n = -1;
868 			proc_range(ps, id, &n, &m);
869 			for (n = 0; n < m; n++) {
870 				if ((fd = dup(rlay->rl_s)) == -1)
871 					return (-1);
872 				if (proc_composev_imsg(ps, id, n,
873 				    IMSG_CFG_RELAY, -1, fd, iov, c) != 0) {
874 					log_warn("%s: failed to compose "
875 					    "IMSG_CFG_RELAY imsg for `%s'",
876 					    __func__, rlay->rl_conf.name);
877 					return (-1);
878 				}
879 				/* Prevent fd exhaustion in the parent. */
880 				if (proc_flush_imsg(ps, id, n) == -1) {
881 					log_warn("%s: failed to flush "
882 					    "IMSG_CFG_RELAY imsg for `%s'",
883 					    __func__, rlay->rl_conf.name);
884 					return (-1);
885 				}
886 			}
887 		} else {
888 			if (proc_composev(ps, id,
889 			    IMSG_CFG_RELAY, iov, c) != 0) {
890 				log_warn("%s: failed to compose "
891 				    "IMSG_CFG_RELAY imsg for `%s'",
892 				    __func__, rlay->rl_conf.name);
893 				return (-1);
894 			}
895 		}
896 
897 		/* cert keypairs */
898 		TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
899 			if (cert->cert_relayid != rlay->rl_conf.id)
900 				continue;
901 			n = -1;
902 			proc_range(ps, id, &n, &m);
903 			for (n = 0; (what & CONFIG_CERTS) && n < m; n++) {
904 				if (cert->cert_fd != -1 &&
905 				    config_setrelayfd(ps, id, n,
906 				    cert->cert_id, cert->cert_relayid,
907 				    RELAY_FD_CERT, cert->cert_fd) == -1) {
908 					log_warn("%s: fd passing failed for "
909 					    "`%s'", __func__,
910 					    rlay->rl_conf.name);
911 					return (-1);
912 				}
913 				if (id == PROC_RELAY &&
914 				    cert->cert_ocsp_fd != -1 &&
915 				    config_setrelayfd(ps, id, n,
916 				    cert->cert_id, cert->cert_relayid,
917 				    RELAY_FD_OCSP, cert->cert_ocsp_fd) == -1) {
918 					log_warn("%s: fd passing failed for "
919 					    "`%s'", __func__,
920 					    rlay->rl_conf.name);
921 					return (-1);
922 				}
923 				if (id == PROC_CA &&
924 				    cert->cert_key_fd != -1 &&
925 				    config_setrelayfd(ps, id, n,
926 				    cert->cert_id, cert->cert_relayid,
927 				    RELAY_FD_KEY, cert->cert_key_fd) == -1) {
928 					log_warn("%s: fd passing failed for "
929 					    "`%s'", __func__,
930 					    rlay->rl_conf.name);
931 					return (-1);
932 				}
933 			}
934 		}
935 
936 		/* CA certs */
937 		if (what & CONFIG_CERTS) {
938 			n = -1;
939 			proc_range(ps, id, &n, &m);
940 			for (n = 0; n < m; n++) {
941 				if (rlay->rl_tls_ca_fd != -1 &&
942 				    config_setrelayfd(ps, id, n, 0,
943 				    rlay->rl_conf.id, RELAY_FD_CACERT,
944 				    rlay->rl_tls_ca_fd) == -1) {
945 					log_warn("%s: fd passing failed for "
946 					    "`%s'", __func__,
947 					    rlay->rl_conf.name);
948 					return (-1);
949 				}
950 				if (rlay->rl_tls_cacert_fd != -1 &&
951 				    config_setrelayfd(ps, id, n, 0,
952 				    rlay->rl_conf.id, RELAY_FD_CAFILE,
953 				    rlay->rl_tls_cacert_fd) == -1) {
954 					log_warn("%s: fd passing failed for "
955 					    "`%s'", __func__,
956 					    rlay->rl_conf.name);
957 					return (-1);
958 				}
959 				/* Prevent fd exhaustion in the parent. */
960 				if (proc_flush_imsg(ps, id, n) == -1) {
961 					log_warn("%s: failed to flush "
962 					    "IMSG_CFG_RELAY imsg for `%s'",
963 					    __func__, rlay->rl_conf.name);
964 					return (-1);
965 				}
966 			}
967 		}
968 
969 		if ((what & CONFIG_TABLES) == 0)
970 			continue;
971 
972 		/* Now send the tables associated to this relay */
973 		TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
974 			crt.id = rlt->rlt_table->conf.id;
975 			crt.relayid = rlay->rl_conf.id;
976 			crt.mode = rlt->rlt_mode;
977 			crt.flags = rlt->rlt_flags;
978 
979 			c = 0;
980 			iov[c].iov_base = &crt;
981 			iov[c++].iov_len = sizeof(crt);
982 
983 			proc_composev(ps, id, IMSG_CFG_RELAY_TABLE, iov, c);
984 		}
985 	}
986 
987 	/* Close server socket early to prevent fd exhaustion in the parent. */
988 	if (rlay->rl_s != -1) {
989 		close(rlay->rl_s);
990 		rlay->rl_s = -1;
991 	}
992 	if (rlay->rl_tls_cacert_fd != -1) {
993 		close(rlay->rl_tls_cacert_fd);
994 		rlay->rl_tls_cacert_fd = -1;
995 	}
996 	if (rlay->rl_tls_ca_fd != -1) {
997 		close(rlay->rl_tls_ca_fd);
998 		rlay->rl_tls_ca_fd = -1;
999 	}
1000 	TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
1001 		if (cert->cert_relayid != rlay->rl_conf.id)
1002 			continue;
1003 
1004 		if (cert->cert_fd != -1) {
1005 			close(cert->cert_fd);
1006 			cert->cert_fd = -1;
1007 		}
1008 		if (cert->cert_key_fd != -1) {
1009 			close(cert->cert_key_fd);
1010 			cert->cert_key_fd = -1;
1011 		}
1012 		if (cert->cert_ocsp_fd != -1) {
1013 			close(cert->cert_ocsp_fd);
1014 			cert->cert_ocsp_fd = -1;
1015 		}
1016 	}
1017 
1018 	return (0);
1019 }
1020 
1021 int
1022 config_getrelay(struct relayd *env, struct imsg *imsg)
1023 {
1024 	struct privsep		*ps = env->sc_ps;
1025 	struct relay		*rlay;
1026 	u_int8_t		*p = imsg->data;
1027 	size_t			 s;
1028 
1029 	if ((rlay = calloc(1, sizeof(*rlay))) == NULL)
1030 		return (-1);
1031 
1032 	IMSG_SIZE_CHECK(imsg, &rlay->rl_conf);
1033 	memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf));
1034 	s = sizeof(rlay->rl_conf);
1035 
1036 	rlay->rl_s = imsg->fd;
1037 	rlay->rl_tls_ca_fd = -1;
1038 	rlay->rl_tls_cacert_fd = -1;
1039 
1040 	if (ps->ps_what[privsep_process] & CONFIG_PROTOS) {
1041 		if (rlay->rl_conf.proto == EMPTY_ID)
1042 			rlay->rl_proto = &env->sc_proto_default;
1043 		else if ((rlay->rl_proto =
1044 		    proto_find(env, rlay->rl_conf.proto)) == NULL) {
1045 			log_debug("%s: unknown protocol", __func__);
1046 			goto fail;
1047 		}
1048 	}
1049 
1050 	if ((off_t)(IMSG_DATA_SIZE(imsg) - s) <
1051 	    (rlay->rl_conf.tls_cakey_len)) {
1052 		log_debug("%s: invalid message length", __func__);
1053 		goto fail;
1054 	}
1055 
1056 	if (rlay->rl_conf.tls_cakey_len) {
1057 		if ((rlay->rl_tls_cakey = get_data(p + s,
1058 		    rlay->rl_conf.tls_cakey_len)) == NULL)
1059 			goto fail;
1060 		s += rlay->rl_conf.tls_cakey_len;
1061 	}
1062 
1063 	TAILQ_INIT(&rlay->rl_tables);
1064 	TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry);
1065 
1066 	env->sc_relaycount++;
1067 
1068 	DPRINTF("%s: %s %d received relay %s", __func__,
1069 	    ps->ps_title[privsep_process], ps->ps_instance,
1070 	    rlay->rl_conf.name);
1071 
1072 	return (0);
1073 
1074  fail:
1075 	free(rlay->rl_tls_cakey);
1076 	close(rlay->rl_s);
1077 	free(rlay);
1078 	return (-1);
1079 }
1080 
1081 int
1082 config_getrelaytable(struct relayd *env, struct imsg *imsg)
1083 {
1084 	struct relay_table	*rlt = NULL;
1085 	struct ctl_relaytable	 crt;
1086 	struct relay		*rlay;
1087 	struct table		*table;
1088 	u_int8_t		*p = imsg->data;
1089 
1090 	IMSG_SIZE_CHECK(imsg, &crt);
1091 	memcpy(&crt, p, sizeof(crt));
1092 
1093 	if ((rlay = relay_find(env, crt.relayid)) == NULL) {
1094 		log_debug("%s: unknown relay", __func__);
1095 		goto fail;
1096 	}
1097 
1098 	if ((table = table_find(env, crt.id)) == NULL) {
1099 		log_debug("%s: unknown table", __func__);
1100 		goto fail;
1101 	}
1102 
1103 	if ((rlt = calloc(1, sizeof(*rlt))) == NULL)
1104 		goto fail;
1105 
1106 	rlt->rlt_table = table;
1107 	rlt->rlt_mode = crt.mode;
1108 	rlt->rlt_flags = crt.flags;
1109 
1110 	TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
1111 
1112 	DPRINTF("%s: %s %d received relay table %s for relay %s", __func__,
1113 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1114 	    table->conf.name, rlay->rl_conf.name);
1115 
1116 	return (0);
1117 
1118  fail:
1119 	free(rlt);
1120 	return (-1);
1121 }
1122 
1123 int
1124 config_getrelayfd(struct relayd *env, struct imsg *imsg)
1125 {
1126 	struct ctl_relayfd	 crfd;
1127 	struct relay		*rlay = NULL;
1128 	struct relay_cert	*cert;
1129 	u_int8_t		*p = imsg->data;
1130 
1131 	IMSG_SIZE_CHECK(imsg, &crfd);
1132 	memcpy(&crfd, p, sizeof(crfd));
1133 
1134 	switch (crfd.type) {
1135 	case RELAY_FD_CERT:
1136 	case RELAY_FD_KEY:
1137 	case RELAY_FD_OCSP:
1138 		if ((cert = cert_find(env, crfd.id)) == NULL) {
1139 			if ((cert = cert_add(env, crfd.id)) == NULL)
1140 				return (-1);
1141 			cert->cert_relayid = crfd.relayid;
1142 		}
1143 		/* FALLTHROUGH */
1144 	default:
1145 		if ((rlay = relay_find(env, crfd.relayid)) == NULL) {
1146 			log_debug("%s: unknown relay", __func__);
1147 			return (-1);
1148 		}
1149 		break;
1150 	}
1151 
1152 	switch (crfd.type) {
1153 	case RELAY_FD_CERT:
1154 		cert->cert_fd = imsg->fd;
1155 		break;
1156 	case RELAY_FD_KEY:
1157 		cert->cert_key_fd = imsg->fd;
1158 		break;
1159 	case RELAY_FD_OCSP:
1160 		cert->cert_ocsp_fd = imsg->fd;
1161 		break;
1162 	case RELAY_FD_CACERT:
1163 		rlay->rl_tls_ca_fd = imsg->fd;
1164 		break;
1165 	case RELAY_FD_CAFILE:
1166 		rlay->rl_tls_cacert_fd = imsg->fd;
1167 		break;
1168 	}
1169 
1170 	DPRINTF("%s: %s %d received relay fd %d type %d for relay %s", __func__,
1171 	    env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance,
1172 	    imsg->fd, crfd.type, rlay->rl_conf.name);
1173 
1174 	return (0);
1175 }
1176