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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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