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