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