1 /* $OpenBSD: config.c,v 1.63 2022/12/28 21:30:16 jmc Exp $ */ 2 3 /* 4 * Copyright (c) 2011 - 2015 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/socket.h> 22 #include <sys/un.h> 23 #include <sys/tree.h> 24 #include <sys/time.h> 25 #include <sys/uio.h> 26 27 #include <unistd.h> 28 #include <stdlib.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <imsg.h> 32 33 #include "httpd.h" 34 35 int config_getserver_config(struct httpd *, struct server *, 36 struct imsg *); 37 int config_getserver_auth(struct httpd *, struct server_config *); 38 39 int 40 config_init(struct httpd *env) 41 { 42 struct privsep *ps = env->sc_ps; 43 unsigned int what; 44 45 /* Global configuration */ 46 if (privsep_process == PROC_PARENT) 47 env->sc_prefork_server = SERVER_NUMPROC; 48 49 ps->ps_what[PROC_PARENT] = CONFIG_ALL; 50 ps->ps_what[PROC_SERVER] = 51 CONFIG_SERVERS|CONFIG_MEDIA|CONFIG_AUTH; 52 ps->ps_what[PROC_LOGGER] = CONFIG_SERVERS; 53 54 (void)strlcpy(env->sc_errdocroot, "", 55 sizeof(env->sc_errdocroot)); 56 57 /* Other configuration */ 58 what = ps->ps_what[privsep_process]; 59 60 if (what & CONFIG_SERVERS) { 61 if ((env->sc_servers = 62 calloc(1, sizeof(*env->sc_servers))) == NULL) 63 return (-1); 64 TAILQ_INIT(env->sc_servers); 65 } 66 67 if (what & CONFIG_MEDIA) { 68 if ((env->sc_mediatypes = 69 calloc(1, sizeof(*env->sc_mediatypes))) == NULL) 70 return (-1); 71 RB_INIT(env->sc_mediatypes); 72 } 73 74 if (what & CONFIG_AUTH) { 75 if ((env->sc_auth = 76 calloc(1, sizeof(*env->sc_auth))) == NULL) 77 return (-1); 78 TAILQ_INIT(env->sc_auth); 79 } 80 81 return (0); 82 } 83 84 void 85 config_purge(struct httpd *env, unsigned int reset) 86 { 87 struct privsep *ps = env->sc_ps; 88 struct server *srv; 89 struct auth *auth; 90 unsigned int what; 91 92 what = ps->ps_what[privsep_process] & reset; 93 94 if (what & CONFIG_SERVERS && env->sc_servers != NULL) { 95 while ((srv = TAILQ_FIRST(env->sc_servers)) != NULL) 96 server_purge(srv); 97 } 98 99 if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL) 100 media_purge(env->sc_mediatypes); 101 102 if (what & CONFIG_AUTH && env->sc_auth != NULL) { 103 while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) { 104 auth_free(env->sc_auth, auth); 105 free(auth); 106 } 107 } 108 } 109 110 int 111 config_setreset(struct httpd *env, unsigned int reset) 112 { 113 struct privsep *ps = env->sc_ps; 114 int id; 115 116 for (id = 0; id < PROC_MAX; id++) { 117 if ((reset & ps->ps_what[id]) == 0 || 118 id == privsep_process) 119 continue; 120 proc_compose(ps, id, IMSG_CTL_RESET, 121 &reset, sizeof(reset)); 122 } 123 124 return (0); 125 } 126 127 int 128 config_getreset(struct httpd *env, struct imsg *imsg) 129 { 130 unsigned int mode; 131 132 IMSG_SIZE_CHECK(imsg, &mode); 133 memcpy(&mode, imsg->data, sizeof(mode)); 134 135 config_purge(env, mode); 136 137 return (0); 138 } 139 140 int 141 config_getcfg(struct httpd *env, struct imsg *imsg) 142 { 143 struct ctl_flags cf; 144 145 if (IMSG_DATA_SIZE(imsg) != sizeof(cf)) 146 return (0); /* ignore */ 147 148 /* Update runtime flags */ 149 memcpy(&cf, imsg->data, sizeof(cf)); 150 env->sc_opts = cf.cf_opts; 151 env->sc_flags = cf.cf_flags; 152 memcpy(env->sc_tls_sid, cf.cf_tls_sid, sizeof(env->sc_tls_sid)); 153 154 if (privsep_process != PROC_PARENT) 155 proc_compose(env->sc_ps, PROC_PARENT, 156 IMSG_CFG_DONE, NULL, 0); 157 158 return (0); 159 } 160 161 int 162 config_setserver(struct httpd *env, struct server *srv) 163 { 164 struct privsep *ps = env->sc_ps; 165 struct server_config s; 166 int id; 167 int fd, n, m; 168 struct iovec iov[6]; 169 size_t c; 170 unsigned int what; 171 172 /* opens listening sockets etc. */ 173 if (server_privinit(srv) == -1) 174 return (-1); 175 176 for (id = 0; id < PROC_MAX; id++) { 177 what = ps->ps_what[id]; 178 179 if ((what & CONFIG_SERVERS) == 0 || id == privsep_process) 180 continue; 181 182 DPRINTF("%s: sending %s \"%s[%u]\" to %s fd %d", __func__, 183 (srv->srv_conf.flags & SRVFLAG_LOCATION) ? 184 "location" : "server", 185 srv->srv_conf.name, srv->srv_conf.id, 186 ps->ps_title[id], srv->srv_s); 187 188 memcpy(&s, &srv->srv_conf, sizeof(s)); 189 190 c = 0; 191 iov[c].iov_base = &s; 192 iov[c++].iov_len = sizeof(s); 193 if (srv->srv_conf.return_uri_len != 0) { 194 iov[c].iov_base = srv->srv_conf.return_uri; 195 iov[c++].iov_len = srv->srv_conf.return_uri_len; 196 } 197 198 if (id == PROC_SERVER && 199 (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) { 200 /* XXX imsg code will close the fd after 1st call */ 201 n = -1; 202 proc_range(ps, id, &n, &m); 203 for (n = 0; n < m; n++) { 204 if (srv->srv_s == -1) 205 fd = -1; 206 else if ((fd = dup(srv->srv_s)) == -1) 207 return (-1); 208 if (proc_composev_imsg(ps, id, n, 209 IMSG_CFG_SERVER, -1, fd, iov, c) != 0) { 210 log_warn("%s: failed to compose " 211 "IMSG_CFG_SERVER imsg for `%s'", 212 __func__, srv->srv_conf.name); 213 return (-1); 214 } 215 216 /* Prevent fd exhaustion in the parent. */ 217 if (proc_flush_imsg(ps, id, n) == -1) { 218 log_warn("%s: failed to flush " 219 "IMSG_CFG_SERVER imsg for `%s'", 220 __func__, srv->srv_conf.name); 221 return (-1); 222 } 223 } 224 225 /* Configure TLS if necessary. */ 226 config_setserver_tls(env, srv); 227 } else { 228 if (proc_composev(ps, id, IMSG_CFG_SERVER, 229 iov, c) != 0) { 230 log_warn("%s: failed to compose " 231 "IMSG_CFG_SERVER imsg for `%s'", 232 __func__, srv->srv_conf.name); 233 return (-1); 234 } 235 236 /* Configure FCGI parameters if necessary. */ 237 config_setserver_fcgiparams(env, srv); 238 } 239 } 240 241 /* Close server socket early to prevent fd exhaustion in the parent. */ 242 if (srv->srv_s != -1) { 243 close(srv->srv_s); 244 srv->srv_s = -1; 245 } 246 247 explicit_bzero(&srv->srv_conf.tls_ticket_key, 248 sizeof(srv->srv_conf.tls_ticket_key)); 249 250 return (0); 251 } 252 253 static int 254 config_settls(struct httpd *env, struct server *srv, enum tls_config_type type, 255 const char *label, uint8_t *data, size_t len) 256 { 257 struct privsep *ps = env->sc_ps; 258 struct server_config *srv_conf = &srv->srv_conf; 259 struct tls_config tls; 260 struct iovec iov[2]; 261 size_t c; 262 263 if (data == NULL || len == 0) 264 return (0); 265 266 DPRINTF("%s: sending tls %s for \"%s[%u]\" to %s fd %d", __func__, 267 label, srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 268 srv->srv_s); 269 270 memset(&tls, 0, sizeof(tls)); 271 tls.id = srv_conf->id; 272 tls.tls_type = type; 273 tls.tls_len = len; 274 tls.tls_chunk_offset = 0; 275 276 while (len > 0) { 277 tls.tls_chunk_len = len; 278 if (tls.tls_chunk_len > (MAX_IMSG_DATA_SIZE - sizeof(tls))) 279 tls.tls_chunk_len = MAX_IMSG_DATA_SIZE - sizeof(tls); 280 281 c = 0; 282 iov[c].iov_base = &tls; 283 iov[c++].iov_len = sizeof(tls); 284 iov[c].iov_base = data; 285 iov[c++].iov_len = tls.tls_chunk_len; 286 287 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) { 288 log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " 289 "`%s'", __func__, srv_conf->name); 290 return (-1); 291 } 292 293 tls.tls_chunk_offset += tls.tls_chunk_len; 294 data += tls.tls_chunk_len; 295 len -= tls.tls_chunk_len; 296 } 297 298 return (0); 299 } 300 301 int 302 config_getserver_fcgiparams(struct httpd *env, struct imsg *imsg) 303 { 304 struct server *srv; 305 struct server_config *srv_conf, *iconf; 306 struct fastcgi_param *fp; 307 uint32_t id; 308 size_t c, nc, len; 309 uint8_t *p = imsg->data; 310 311 len = sizeof(nc) + sizeof(id); 312 if (IMSG_DATA_SIZE(imsg) < len) { 313 log_debug("%s: invalid message length", __func__); 314 return (-1); 315 } 316 317 memcpy(&nc, p, sizeof(nc)); /* number of params */ 318 p += sizeof(nc); 319 320 memcpy(&id, p, sizeof(id)); /* server conf id */ 321 srv_conf = serverconfig_byid(id); 322 p += sizeof(id); 323 324 len += nc*sizeof(*fp); 325 if (IMSG_DATA_SIZE(imsg) < len) { 326 log_debug("%s: invalid message length", __func__); 327 return (-1); 328 } 329 330 /* Find associated server config */ 331 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { 332 if (srv->srv_conf.id == id) { 333 srv_conf = &srv->srv_conf; 334 break; 335 } 336 TAILQ_FOREACH(iconf, &srv->srv_hosts, entry) { 337 if (iconf->id == id) { 338 srv_conf = iconf; 339 break; 340 } 341 } 342 } 343 344 /* Fetch FCGI parameters */ 345 for (c = 0; c < nc; c++) { 346 if ((fp = calloc(1, sizeof(*fp))) == NULL) 347 fatalx("fcgiparams out of memory"); 348 memcpy(fp, p, sizeof(*fp)); 349 TAILQ_INSERT_HEAD(&srv_conf->fcgiparams, fp, entry); 350 351 p += sizeof(*fp); 352 } 353 354 return (0); 355 } 356 357 int 358 config_setserver_fcgiparams(struct httpd *env, struct server *srv) 359 { 360 struct privsep *ps = env->sc_ps; 361 struct server_config *srv_conf = &srv->srv_conf; 362 struct fastcgi_param *fp; 363 struct iovec *iov; 364 size_t c = 0, nc = 0; 365 366 DPRINTF("%s: sending fcgiparam for \"%s[%u]\" to %s fd %d", __func__, 367 srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 368 srv->srv_s); 369 370 if (TAILQ_EMPTY(&srv_conf->fcgiparams)) /* nothing to do */ 371 return (0); 372 373 TAILQ_FOREACH(fp, &srv_conf->fcgiparams, entry) { 374 nc++; 375 } 376 if ((iov = calloc(nc + 2, sizeof(*iov))) == NULL) 377 return (-1); 378 379 iov[c].iov_base = &nc; /* number of params */ 380 iov[c++].iov_len = sizeof(nc); 381 iov[c].iov_base = &srv_conf->id; /* server config id */ 382 iov[c++].iov_len = sizeof(srv_conf->id); 383 384 TAILQ_FOREACH(fp, &srv_conf->fcgiparams, entry) { /* push FCGI params */ 385 iov[c].iov_base = fp; 386 iov[c++].iov_len = sizeof(*fp); 387 } 388 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_FCGI, iov, c) != 0) { 389 log_warn("%s: failed to compose IMSG_CFG_FCGI imsg for " 390 "`%s'", __func__, srv_conf->name); 391 free(iov); 392 return (-1); 393 } 394 free(iov); 395 396 return (0); 397 } 398 399 int 400 config_setserver_tls(struct httpd *env, struct server *srv) 401 { 402 struct server_config *srv_conf = &srv->srv_conf; 403 404 if ((srv_conf->flags & SRVFLAG_TLS) == 0) 405 return (0); 406 407 log_debug("%s: configuring tls for %s", __func__, srv_conf->name); 408 409 if (config_settls(env, srv, TLS_CFG_CA, "ca", srv_conf->tls_ca, 410 srv_conf->tls_ca_len) != 0) 411 return (-1); 412 413 if (config_settls(env, srv, TLS_CFG_CERT, "cert", srv_conf->tls_cert, 414 srv_conf->tls_cert_len) != 0) 415 return (-1); 416 417 if (config_settls(env, srv, TLS_CFG_CRL, "crl", srv_conf->tls_crl, 418 srv_conf->tls_crl_len) != 0) 419 return (-1); 420 421 if (config_settls(env, srv, TLS_CFG_KEY, "key", srv_conf->tls_key, 422 srv_conf->tls_key_len) != 0) 423 return (-1); 424 425 if (config_settls(env, srv, TLS_CFG_OCSP_STAPLE, "ocsp staple", 426 srv_conf->tls_ocsp_staple, srv_conf->tls_ocsp_staple_len) != 0) 427 return (-1); 428 429 return (0); 430 } 431 432 int 433 config_getserver_auth(struct httpd *env, struct server_config *srv_conf) 434 { 435 struct privsep *ps = env->sc_ps; 436 437 if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 || 438 (srv_conf->flags & SRVFLAG_AUTH) == 0) 439 return (0); 440 441 if ((srv_conf->auth = auth_byid(env->sc_auth, 442 srv_conf->auth_id)) == NULL) 443 return (-1); 444 445 return (0); 446 } 447 448 int 449 config_getserver_config(struct httpd *env, struct server *srv, 450 struct imsg *imsg) 451 { 452 #ifdef DEBUG 453 struct privsep *ps = env->sc_ps; 454 #endif 455 struct server_config *srv_conf, *parent; 456 uint8_t *p = imsg->data; 457 unsigned int f; 458 size_t s; 459 460 if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL) 461 return (-1); 462 463 IMSG_SIZE_CHECK(imsg, srv_conf); 464 memcpy(srv_conf, p, sizeof(*srv_conf)); 465 s = sizeof(*srv_conf); 466 467 /* Reset these variables to avoid free'ing invalid pointers */ 468 serverconfig_reset(srv_conf); 469 470 TAILQ_FOREACH(parent, &srv->srv_hosts, entry) { 471 if (strcmp(parent->name, srv_conf->name) == 0) 472 break; 473 } 474 if (parent == NULL) 475 parent = &srv->srv_conf; 476 477 if (config_getserver_auth(env, srv_conf) != 0) 478 goto fail; 479 480 /* 481 * Get variable-length values for the virtual host. The tls_* ones 482 * aren't needed in the virtual hosts unless we implement SNI. 483 */ 484 if (srv_conf->return_uri_len != 0) { 485 if ((srv_conf->return_uri = get_data(p + s, 486 srv_conf->return_uri_len)) == NULL) 487 goto fail; 488 s += srv_conf->return_uri_len; 489 } 490 491 if (srv_conf->flags & SRVFLAG_LOCATION) { 492 /* Inherit configuration from the parent */ 493 f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX; 494 if ((srv_conf->flags & f) == 0) { 495 srv_conf->flags |= parent->flags & f; 496 (void)strlcpy(srv_conf->index, parent->index, 497 sizeof(srv_conf->index)); 498 } 499 500 f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX; 501 if ((srv_conf->flags & f) == 0) 502 srv_conf->flags |= parent->flags & f; 503 504 f = SRVFLAG_ROOT; 505 if ((srv_conf->flags & f) == 0) { 506 srv_conf->flags |= parent->flags & f; 507 (void)strlcpy(srv_conf->root, parent->root, 508 sizeof(srv_conf->root)); 509 } 510 511 f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI; 512 if ((srv_conf->flags & f) == 0) 513 srv_conf->flags |= parent->flags & f; 514 515 f = SRVFLAG_LOG|SRVFLAG_NO_LOG; 516 if ((srv_conf->flags & f) == 0) { 517 srv_conf->flags |= parent->flags & f; 518 srv_conf->logformat = parent->logformat; 519 } 520 521 f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG; 522 if ((srv_conf->flags & f) == 0) 523 srv_conf->flags |= parent->flags & f; 524 525 f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH; 526 if ((srv_conf->flags & f) == 0) { 527 srv_conf->flags |= parent->flags & f; 528 srv_conf->auth = parent->auth; 529 srv_conf->auth_id = parent->auth_id; 530 (void)strlcpy(srv_conf->auth_realm, 531 parent->auth_realm, 532 sizeof(srv_conf->auth_realm)); 533 } 534 535 f = SRVFLAG_TLS; 536 srv_conf->flags |= parent->flags & f; 537 srv_conf->tls_flags = parent->tls_flags; 538 539 f = SRVFLAG_ACCESS_LOG; 540 if ((srv_conf->flags & f) == 0) { 541 srv_conf->flags |= parent->flags & f; 542 (void)strlcpy(srv_conf->accesslog, 543 parent->accesslog, 544 sizeof(srv_conf->accesslog)); 545 } 546 547 f = SRVFLAG_ERROR_LOG; 548 if ((srv_conf->flags & f) == 0) { 549 srv_conf->flags |= parent->flags & f; 550 (void)strlcpy(srv_conf->errorlog, 551 parent->errorlog, 552 sizeof(srv_conf->errorlog)); 553 } 554 555 f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK; 556 if ((srv_conf->flags & f) == 0) { 557 free(srv_conf->return_uri); 558 srv_conf->flags |= parent->flags & f; 559 srv_conf->return_code = parent->return_code; 560 srv_conf->return_uri_len = parent->return_uri_len; 561 if (srv_conf->return_uri_len && 562 (srv_conf->return_uri = 563 strdup(parent->return_uri)) == NULL) 564 goto fail; 565 } 566 567 f = SRVFLAG_DEFAULT_TYPE; 568 if ((srv_conf->flags & f) == 0) { 569 srv_conf->flags |= parent->flags & f; 570 memcpy(&srv_conf->default_type, 571 &parent->default_type, sizeof(struct media_type)); 572 } 573 574 f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE; 575 if ((srv_conf->flags & f) == 0) { 576 srv_conf->flags |= parent->flags & f; 577 (void)strlcpy(srv_conf->path, parent->path, 578 sizeof(srv_conf->path)); 579 } 580 581 f = SRVFLAG_SERVER_HSTS; 582 srv_conf->flags |= parent->flags & f; 583 srv_conf->hsts_max_age = parent->hsts_max_age; 584 srv_conf->hsts_flags = parent->hsts_flags; 585 586 memcpy(&srv_conf->timeout, &parent->timeout, 587 sizeof(srv_conf->timeout)); 588 srv_conf->maxrequests = parent->maxrequests; 589 srv_conf->maxrequestbody = parent->maxrequestbody; 590 591 srv_conf->flags |= parent->flags & SRVFLAG_ERRDOCS; 592 (void)strlcpy(srv_conf->errdocroot, parent->errdocroot, 593 sizeof(srv_conf->errdocroot)); 594 595 DPRINTF("%s: %s %d location \"%s\", " 596 "parent \"%s[%u]\", flags: %s", 597 __func__, ps->ps_title[privsep_process], ps->ps_instance, 598 srv_conf->location, parent->name, parent->id, 599 printb_flags(srv_conf->flags, SRVFLAG_BITS)); 600 } else { 601 /* Add a new "virtual" server */ 602 DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", " 603 "flags: %s", __func__, 604 ps->ps_title[privsep_process], ps->ps_instance, 605 srv_conf->name, srv_conf->id, parent->name, parent->id, 606 printb_flags(srv_conf->flags, SRVFLAG_BITS)); 607 } 608 609 TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry); 610 611 return (0); 612 613 fail: 614 serverconfig_free(srv_conf); 615 free(srv_conf); 616 return (-1); 617 } 618 619 int 620 config_getserver(struct httpd *env, struct imsg *imsg) 621 { 622 #ifdef DEBUG 623 struct privsep *ps = env->sc_ps; 624 #endif 625 struct server *srv = NULL; 626 struct server_config srv_conf; 627 uint8_t *p = imsg->data; 628 size_t s; 629 630 IMSG_SIZE_CHECK(imsg, &srv_conf); 631 memcpy(&srv_conf, p, sizeof(srv_conf)); 632 s = sizeof(srv_conf); 633 634 /* Reset these variables to avoid free'ing invalid pointers */ 635 serverconfig_reset(&srv_conf); 636 637 if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) { 638 log_debug("%s: invalid message length", __func__); 639 goto fail; 640 } 641 642 /* Check if server with matching listening socket already exists */ 643 if ((srv = server_byaddr((struct sockaddr *) 644 &srv_conf.ss, srv_conf.port)) != NULL) { 645 /* Add "host" to existing listening server */ 646 if (imsg->fd != -1) { 647 if (srv->srv_s == -1) 648 srv->srv_s = imsg->fd; 649 else 650 close(imsg->fd); 651 } 652 return (config_getserver_config(env, srv, imsg)); 653 } 654 655 if (srv_conf.flags & SRVFLAG_LOCATION) 656 fatalx("invalid location"); 657 658 /* Otherwise create a new server */ 659 if ((srv = calloc(1, sizeof(*srv))) == NULL) 660 goto fail; 661 662 memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf)); 663 srv->srv_s = imsg->fd; 664 665 if (config_getserver_auth(env, &srv->srv_conf) != 0) 666 goto fail; 667 668 SPLAY_INIT(&srv->srv_clients); 669 TAILQ_INIT(&srv->srv_hosts); 670 671 TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry); 672 TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry); 673 674 DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__, 675 ps->ps_title[privsep_process], ps->ps_instance, 676 srv->srv_conf.name, srv->srv_conf.id, 677 printb_flags(srv->srv_conf.flags, SRVFLAG_BITS)); 678 679 /* 680 * Get all variable-length values for the parent server. 681 */ 682 if (srv->srv_conf.return_uri_len != 0) { 683 if ((srv->srv_conf.return_uri = get_data(p + s, 684 srv->srv_conf.return_uri_len)) == NULL) 685 goto fail; 686 } 687 688 return (0); 689 690 fail: 691 if (imsg->fd != -1) 692 close(imsg->fd); 693 if (srv != NULL) 694 serverconfig_free(&srv->srv_conf); 695 free(srv); 696 697 return (-1); 698 } 699 700 static int 701 config_gettls(struct httpd *env, struct server_config *srv_conf, 702 struct tls_config *tls_conf, const char *label, uint8_t *data, size_t len, 703 uint8_t **outdata, size_t *outlen) 704 { 705 #ifdef DEBUG 706 struct privsep *ps = env->sc_ps; 707 #endif 708 709 DPRINTF("%s: %s %d getting tls %s (%zu:%zu@%zu) for \"%s[%u]\"", 710 __func__, ps->ps_title[privsep_process], ps->ps_instance, label, 711 tls_conf->tls_len, len, tls_conf->tls_chunk_offset, srv_conf->name, 712 srv_conf->id); 713 714 if (tls_conf->tls_chunk_offset == 0) { 715 free(*outdata); 716 *outlen = 0; 717 if ((*outdata = calloc(1, tls_conf->tls_len)) == NULL) 718 goto fail; 719 *outlen = tls_conf->tls_len; 720 } 721 722 if (*outdata == NULL) { 723 log_debug("%s: tls config invalid chunk sequence", __func__); 724 goto fail; 725 } 726 727 if (*outlen != tls_conf->tls_len) { 728 log_debug("%s: tls config length mismatch (%zu != %zu)", 729 __func__, *outlen, tls_conf->tls_len); 730 goto fail; 731 } 732 733 if (len > (tls_conf->tls_len - tls_conf->tls_chunk_offset)) { 734 log_debug("%s: tls config invalid chunk length", __func__); 735 goto fail; 736 } 737 738 memcpy(*outdata + tls_conf->tls_chunk_offset, data, len); 739 740 return (0); 741 742 fail: 743 return (-1); 744 } 745 746 int 747 config_getserver_tls(struct httpd *env, struct imsg *imsg) 748 { 749 struct server_config *srv_conf = NULL; 750 struct tls_config tls_conf; 751 uint8_t *p = imsg->data; 752 size_t len; 753 754 IMSG_SIZE_CHECK(imsg, &tls_conf); 755 memcpy(&tls_conf, p, sizeof(tls_conf)); 756 757 len = tls_conf.tls_chunk_len; 758 759 if ((IMSG_DATA_SIZE(imsg) - sizeof(tls_conf)) < len) { 760 log_debug("%s: invalid message length", __func__); 761 goto fail; 762 } 763 764 p += sizeof(tls_conf); 765 766 if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) { 767 log_debug("%s: server not found", __func__); 768 goto fail; 769 } 770 771 switch (tls_conf.tls_type) { 772 case TLS_CFG_CA: 773 if (config_gettls(env, srv_conf, &tls_conf, "ca", p, len, 774 &srv_conf->tls_ca, &srv_conf->tls_ca_len) != 0) 775 goto fail; 776 break; 777 778 case TLS_CFG_CERT: 779 if (config_gettls(env, srv_conf, &tls_conf, "cert", p, len, 780 &srv_conf->tls_cert, &srv_conf->tls_cert_len) != 0) 781 goto fail; 782 break; 783 784 case TLS_CFG_CRL: 785 if (config_gettls(env, srv_conf, &tls_conf, "crl", p, len, 786 &srv_conf->tls_crl, &srv_conf->tls_crl_len) != 0) 787 goto fail; 788 break; 789 790 case TLS_CFG_KEY: 791 if (config_gettls(env, srv_conf, &tls_conf, "key", p, len, 792 &srv_conf->tls_key, &srv_conf->tls_key_len) != 0) 793 goto fail; 794 break; 795 796 case TLS_CFG_OCSP_STAPLE: 797 if (config_gettls(env, srv_conf, &tls_conf, "ocsp staple", 798 p, len, &srv_conf->tls_ocsp_staple, 799 &srv_conf->tls_ocsp_staple_len) != 0) 800 goto fail; 801 break; 802 803 default: 804 log_debug("%s: unknown tls config type %i\n", 805 __func__, tls_conf.tls_type); 806 goto fail; 807 } 808 809 return (0); 810 811 fail: 812 return (-1); 813 } 814 815 int 816 config_setmedia(struct httpd *env, struct media_type *media) 817 { 818 struct privsep *ps = env->sc_ps; 819 int id; 820 unsigned int what; 821 822 for (id = 0; id < PROC_MAX; id++) { 823 what = ps->ps_what[id]; 824 825 if ((what & CONFIG_MEDIA) == 0 || id == privsep_process) 826 continue; 827 828 DPRINTF("%s: sending media \"%s\" to %s", __func__, 829 media->media_name, ps->ps_title[id]); 830 831 proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media)); 832 } 833 834 return (0); 835 } 836 837 int 838 config_getmedia(struct httpd *env, struct imsg *imsg) 839 { 840 #ifdef DEBUG 841 struct privsep *ps = env->sc_ps; 842 #endif 843 struct media_type media; 844 uint8_t *p = imsg->data; 845 846 IMSG_SIZE_CHECK(imsg, &media); 847 memcpy(&media, p, sizeof(media)); 848 849 if (media_add(env->sc_mediatypes, &media) == NULL) { 850 log_debug("%s: failed to add media \"%s\"", 851 __func__, media.media_name); 852 return (-1); 853 } 854 855 DPRINTF("%s: %s %d received media \"%s\"", __func__, 856 ps->ps_title[privsep_process], ps->ps_instance, 857 media.media_name); 858 859 return (0); 860 } 861 862 int 863 config_setauth(struct httpd *env, struct auth *auth) 864 { 865 struct privsep *ps = env->sc_ps; 866 int id; 867 unsigned int what; 868 869 for (id = 0; id < PROC_MAX; id++) { 870 what = ps->ps_what[id]; 871 872 if ((what & CONFIG_AUTH) == 0 || id == privsep_process) 873 continue; 874 875 DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__, 876 auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]); 877 878 proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth)); 879 } 880 881 return (0); 882 } 883 884 int 885 config_getauth(struct httpd *env, struct imsg *imsg) 886 { 887 #ifdef DEBUG 888 struct privsep *ps = env->sc_ps; 889 #endif 890 struct auth auth; 891 uint8_t *p = imsg->data; 892 893 IMSG_SIZE_CHECK(imsg, &auth); 894 memcpy(&auth, p, sizeof(auth)); 895 896 if (auth_add(env->sc_auth, &auth) == NULL) { 897 log_debug("%s: failed to add auth \"%s[%u]\"", 898 __func__, auth.auth_htpasswd, auth.auth_id); 899 return (-1); 900 } 901 902 DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__, 903 ps->ps_title[privsep_process], ps->ps_instance, 904 auth.auth_htpasswd, auth.auth_id); 905 906 return (0); 907 } 908