1 /* $OpenBSD: config.c,v 1.57 2019/05/08 19:57:45 reyk 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/tree.h> 22 #include <sys/time.h> 23 #include <sys/uio.h> 24 25 #include <unistd.h> 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include <imsg.h> 30 31 #include "httpd.h" 32 33 int config_getserver_config(struct httpd *, struct server *, 34 struct imsg *); 35 int config_getserver_auth(struct httpd *, struct server_config *); 36 37 int 38 config_init(struct httpd *env) 39 { 40 struct privsep *ps = env->sc_ps; 41 unsigned int what; 42 43 /* Global configuration */ 44 if (privsep_process == PROC_PARENT) 45 env->sc_prefork_server = SERVER_NUMPROC; 46 47 ps->ps_what[PROC_PARENT] = CONFIG_ALL; 48 ps->ps_what[PROC_SERVER] = 49 CONFIG_SERVERS|CONFIG_MEDIA|CONFIG_AUTH; 50 ps->ps_what[PROC_LOGGER] = CONFIG_SERVERS; 51 52 /* Other configuration */ 53 what = ps->ps_what[privsep_process]; 54 55 if (what & CONFIG_SERVERS) { 56 if ((env->sc_servers = 57 calloc(1, sizeof(*env->sc_servers))) == NULL) 58 return (-1); 59 TAILQ_INIT(env->sc_servers); 60 } 61 62 if (what & CONFIG_MEDIA) { 63 if ((env->sc_mediatypes = 64 calloc(1, sizeof(*env->sc_mediatypes))) == NULL) 65 return (-1); 66 RB_INIT(env->sc_mediatypes); 67 } 68 69 if (what & CONFIG_AUTH) { 70 if ((env->sc_auth = 71 calloc(1, sizeof(*env->sc_auth))) == NULL) 72 return (-1); 73 TAILQ_INIT(env->sc_auth); 74 } 75 76 return (0); 77 } 78 79 void 80 config_purge(struct httpd *env, unsigned int reset) 81 { 82 struct privsep *ps = env->sc_ps; 83 struct server *srv; 84 struct auth *auth; 85 unsigned int what; 86 87 what = ps->ps_what[privsep_process] & reset; 88 89 if (what & CONFIG_SERVERS && env->sc_servers != NULL) { 90 while ((srv = TAILQ_FIRST(env->sc_servers)) != NULL) 91 server_purge(srv); 92 } 93 94 if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL) 95 media_purge(env->sc_mediatypes); 96 97 if (what & CONFIG_AUTH && env->sc_auth != NULL) { 98 while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) { 99 auth_free(env->sc_auth, auth); 100 free(auth); 101 } 102 } 103 } 104 105 int 106 config_setreset(struct httpd *env, unsigned int reset) 107 { 108 struct privsep *ps = env->sc_ps; 109 int id; 110 111 for (id = 0; id < PROC_MAX; id++) { 112 if ((reset & ps->ps_what[id]) == 0 || 113 id == privsep_process) 114 continue; 115 proc_compose(ps, id, IMSG_CTL_RESET, 116 &reset, sizeof(reset)); 117 } 118 119 return (0); 120 } 121 122 int 123 config_getreset(struct httpd *env, struct imsg *imsg) 124 { 125 unsigned int mode; 126 127 IMSG_SIZE_CHECK(imsg, &mode); 128 memcpy(&mode, imsg->data, sizeof(mode)); 129 130 config_purge(env, mode); 131 132 return (0); 133 } 134 135 int 136 config_getcfg(struct httpd *env, struct imsg *imsg) 137 { 138 struct privsep *ps = env->sc_ps; 139 struct ctl_flags cf; 140 unsigned int what; 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 what = ps->ps_what[privsep_process]; 152 153 if (privsep_process != PROC_PARENT) 154 proc_compose(env->sc_ps, PROC_PARENT, 155 IMSG_CFG_DONE, NULL, 0); 156 157 return (0); 158 } 159 160 int 161 config_setserver(struct httpd *env, struct server *srv) 162 { 163 struct privsep *ps = env->sc_ps; 164 struct server_config s; 165 int id; 166 int fd, n, m; 167 struct iovec iov[6]; 168 size_t c; 169 unsigned int what; 170 171 /* opens listening sockets etc. */ 172 if (server_privinit(srv) == -1) 173 return (-1); 174 175 for (id = 0; id < PROC_MAX; id++) { 176 what = ps->ps_what[id]; 177 178 if ((what & CONFIG_SERVERS) == 0 || id == privsep_process) 179 continue; 180 181 DPRINTF("%s: sending %s \"%s[%u]\" to %s fd %d", __func__, 182 (srv->srv_conf.flags & SRVFLAG_LOCATION) ? 183 "location" : "server", 184 srv->srv_conf.name, srv->srv_conf.id, 185 ps->ps_title[id], srv->srv_s); 186 187 memcpy(&s, &srv->srv_conf, sizeof(s)); 188 189 c = 0; 190 iov[c].iov_base = &s; 191 iov[c++].iov_len = sizeof(s); 192 if (srv->srv_conf.return_uri_len != 0) { 193 iov[c].iov_base = srv->srv_conf.return_uri; 194 iov[c++].iov_len = srv->srv_conf.return_uri_len; 195 } 196 197 if (id == PROC_SERVER && 198 (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) { 199 /* XXX imsg code will close the fd after 1st call */ 200 n = -1; 201 proc_range(ps, id, &n, &m); 202 for (n = 0; n < m; n++) { 203 if (srv->srv_s == -1) 204 fd = -1; 205 else if ((fd = dup(srv->srv_s)) == -1) 206 return (-1); 207 if (proc_composev_imsg(ps, id, n, 208 IMSG_CFG_SERVER, -1, fd, iov, c) != 0) { 209 log_warn("%s: failed to compose " 210 "IMSG_CFG_SERVER imsg for `%s'", 211 __func__, srv->srv_conf.name); 212 return (-1); 213 } 214 215 /* Prevent fd exhaustion in the parent. */ 216 if (proc_flush_imsg(ps, id, n) == -1) { 217 log_warn("%s: failed to flush " 218 "IMSG_CFG_SERVER imsg for `%s'", 219 __func__, srv->srv_conf.name); 220 return (-1); 221 } 222 } 223 224 /* Configure TLS if necessary. */ 225 config_setserver_tls(env, srv); 226 } else { 227 if (proc_composev(ps, id, IMSG_CFG_SERVER, 228 iov, c) != 0) { 229 log_warn("%s: failed to compose " 230 "IMSG_CFG_SERVER imsg for `%s'", 231 __func__, srv->srv_conf.name); 232 return (-1); 233 } 234 235 /* Configure FCGI parmeters if necessary. */ 236 config_setserver_fcgiparams(env, srv); 237 } 238 } 239 240 /* Close server socket early to prevent fd exhaustion in the parent. */ 241 if (srv->srv_s != -1) { 242 close(srv->srv_s); 243 srv->srv_s = -1; 244 } 245 246 explicit_bzero(&srv->srv_conf.tls_ticket_key, 247 sizeof(srv->srv_conf.tls_ticket_key)); 248 249 return (0); 250 } 251 252 static int 253 config_settls(struct httpd *env, struct server *srv, enum tls_config_type type, 254 const char *label, uint8_t *data, size_t len) 255 { 256 struct privsep *ps = env->sc_ps; 257 struct server_config *srv_conf = &srv->srv_conf; 258 struct tls_config tls; 259 struct iovec iov[2]; 260 size_t c; 261 262 if (data == NULL || len == 0) 263 return (0); 264 265 DPRINTF("%s: sending tls %s for \"%s[%u]\" to %s fd %d", __func__, 266 label, srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 267 srv->srv_s); 268 269 memset(&tls, 0, sizeof(tls)); 270 tls.id = srv_conf->id; 271 tls.tls_type = type; 272 tls.tls_len = len; 273 tls.tls_chunk_offset = 0; 274 275 while (len > 0) { 276 tls.tls_chunk_len = len; 277 if (tls.tls_chunk_len > (MAX_IMSG_DATA_SIZE - sizeof(tls))) 278 tls.tls_chunk_len = MAX_IMSG_DATA_SIZE - sizeof(tls); 279 280 c = 0; 281 iov[c].iov_base = &tls; 282 iov[c++].iov_len = sizeof(tls); 283 iov[c].iov_base = data; 284 iov[c++].iov_len = tls.tls_chunk_len; 285 286 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) { 287 log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " 288 "`%s'", __func__, srv_conf->name); 289 return (-1); 290 } 291 292 tls.tls_chunk_offset += tls.tls_chunk_len; 293 data += tls.tls_chunk_len; 294 len -= tls.tls_chunk_len; 295 } 296 297 return (0); 298 } 299 300 int 301 config_getserver_fcgiparams(struct httpd *env, struct imsg *imsg) 302 { 303 struct server *srv; 304 struct server_config *srv_conf, *iconf; 305 struct fastcgi_param *fp; 306 uint32_t id; 307 size_t c, nc, len; 308 uint8_t *p = imsg->data; 309 310 len = sizeof(nc) + sizeof(id); 311 if (IMSG_DATA_SIZE(imsg) < len) { 312 log_debug("%s: invalid message length", __func__); 313 return (-1); 314 } 315 316 memcpy(&nc, p, sizeof(nc)); /* number of params */ 317 p += sizeof(nc); 318 319 memcpy(&id, p, sizeof(id)); /* server conf id */ 320 srv_conf = serverconfig_byid(id); 321 p += sizeof(id); 322 323 len += nc*sizeof(*fp); 324 if (IMSG_DATA_SIZE(imsg) < len) { 325 log_debug("%s: invalid message length", __func__); 326 return (-1); 327 } 328 329 /* Find associated server config */ 330 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) { 331 if (srv->srv_conf.id == id) { 332 srv_conf = &srv->srv_conf; 333 break; 334 } 335 TAILQ_FOREACH(iconf, &srv->srv_hosts, entry) { 336 if (iconf->id == id) { 337 srv_conf = iconf; 338 break; 339 } 340 } 341 } 342 343 /* Fetch FCGI parameters */ 344 for (c = 0; c < nc; c++) { 345 if ((fp = calloc(1, sizeof(*fp))) == NULL) 346 fatalx("fcgiparams out of memory"); 347 memcpy(fp, p, sizeof(*fp)); 348 TAILQ_INSERT_HEAD(&srv_conf->fcgiparams, fp, entry); 349 350 p += sizeof(*fp); 351 } 352 353 return (0); 354 } 355 356 int 357 config_setserver_fcgiparams(struct httpd *env, struct server *srv) 358 { 359 struct privsep *ps = env->sc_ps; 360 struct server_config *srv_conf = &srv->srv_conf; 361 struct fastcgi_param *fp; 362 struct iovec *iov; 363 size_t c = 0, nc = 0; 364 365 DPRINTF("%s: sending fcgiparam for \"%s[%u]\" to %s fd %d", __func__, 366 srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 367 srv->srv_s); 368 369 if (TAILQ_EMPTY(&srv_conf->fcgiparams)) /* nothing to do */ 370 return (0); 371 372 TAILQ_FOREACH(fp, &srv_conf->fcgiparams, entry) { 373 nc++; 374 } 375 if ((iov = calloc(nc + 2, sizeof(*iov))) == NULL) 376 return (-1); 377 378 iov[c].iov_base = &nc; /* number of params */ 379 iov[c++].iov_len = sizeof(nc); 380 iov[c].iov_base = &srv_conf->id; /* server config id */ 381 iov[c++].iov_len = sizeof(srv_conf->id); 382 383 TAILQ_FOREACH(fp, &srv_conf->fcgiparams, entry) { /* push FCGI params */ 384 iov[c].iov_base = fp; 385 iov[c++].iov_len = sizeof(*fp); 386 } 387 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_FCGI, iov, c) != 0) { 388 log_warn("%s: failed to compose IMSG_CFG_FCGI imsg for " 389 "`%s'", __func__, srv_conf->name); 390 return (-1); 391 } 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_SOCKET|SRVFLAG_FCGI; 502 if ((srv_conf->flags & f) == SRVFLAG_FCGI) { 503 srv_conf->flags |= f; 504 (void)strlcpy(srv_conf->socket, HTTPD_FCGI_SOCKET, 505 sizeof(srv_conf->socket)); 506 } 507 508 f = SRVFLAG_ROOT; 509 if ((srv_conf->flags & f) == 0) { 510 srv_conf->flags |= parent->flags & f; 511 (void)strlcpy(srv_conf->root, parent->root, 512 sizeof(srv_conf->root)); 513 } 514 515 f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI; 516 if ((srv_conf->flags & f) == 0) 517 srv_conf->flags |= parent->flags & f; 518 519 f = SRVFLAG_LOG|SRVFLAG_NO_LOG; 520 if ((srv_conf->flags & f) == 0) { 521 srv_conf->flags |= parent->flags & f; 522 srv_conf->logformat = parent->logformat; 523 } 524 525 f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG; 526 if ((srv_conf->flags & f) == 0) 527 srv_conf->flags |= parent->flags & f; 528 529 f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH; 530 if ((srv_conf->flags & f) == 0) { 531 srv_conf->flags |= parent->flags & f; 532 srv_conf->auth = parent->auth; 533 srv_conf->auth_id = parent->auth_id; 534 (void)strlcpy(srv_conf->auth_realm, 535 parent->auth_realm, 536 sizeof(srv_conf->auth_realm)); 537 } 538 539 f = SRVFLAG_TLS; 540 srv_conf->flags |= parent->flags & f; 541 srv_conf->tls_flags = parent->tls_flags; 542 543 f = SRVFLAG_ACCESS_LOG; 544 if ((srv_conf->flags & f) == 0) { 545 srv_conf->flags |= parent->flags & f; 546 (void)strlcpy(srv_conf->accesslog, 547 parent->accesslog, 548 sizeof(srv_conf->accesslog)); 549 } 550 551 f = SRVFLAG_ERROR_LOG; 552 if ((srv_conf->flags & f) == 0) { 553 srv_conf->flags |= parent->flags & f; 554 (void)strlcpy(srv_conf->errorlog, 555 parent->errorlog, 556 sizeof(srv_conf->errorlog)); 557 } 558 559 f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK; 560 if ((srv_conf->flags & f) == 0) { 561 free(srv_conf->return_uri); 562 srv_conf->flags |= parent->flags & f; 563 srv_conf->return_code = parent->return_code; 564 srv_conf->return_uri_len = parent->return_uri_len; 565 if (srv_conf->return_uri_len && 566 (srv_conf->return_uri = 567 strdup(parent->return_uri)) == NULL) 568 goto fail; 569 } 570 571 f = SRVFLAG_DEFAULT_TYPE; 572 if ((srv_conf->flags & f) == 0) { 573 srv_conf->flags |= parent->flags & f; 574 memcpy(&srv_conf->default_type, 575 &parent->default_type, sizeof(struct media_type)); 576 } 577 578 f = SRVFLAG_PATH_REWRITE|SRVFLAG_NO_PATH_REWRITE; 579 if ((srv_conf->flags & f) == 0) { 580 srv_conf->flags |= parent->flags & f; 581 (void)strlcpy(srv_conf->path, parent->path, 582 sizeof(srv_conf->path)); 583 } 584 585 f = SRVFLAG_SERVER_HSTS; 586 srv_conf->flags |= parent->flags & f; 587 srv_conf->hsts_max_age = parent->hsts_max_age; 588 srv_conf->hsts_flags = parent->hsts_flags; 589 590 memcpy(&srv_conf->timeout, &parent->timeout, 591 sizeof(srv_conf->timeout)); 592 srv_conf->maxrequests = parent->maxrequests; 593 srv_conf->maxrequestbody = parent->maxrequestbody; 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 s += srv->srv_conf.return_uri_len; 687 } 688 689 return (0); 690 691 fail: 692 if (imsg->fd != -1) 693 close(imsg->fd); 694 if (srv != NULL) 695 serverconfig_free(&srv->srv_conf); 696 free(srv); 697 698 return (-1); 699 } 700 701 static int 702 config_gettls(struct httpd *env, struct server_config *srv_conf, 703 struct tls_config *tls_conf, const char *label, uint8_t *data, size_t len, 704 uint8_t **outdata, size_t *outlen) 705 { 706 #ifdef DEBUG 707 struct privsep *ps = env->sc_ps; 708 #endif 709 710 DPRINTF("%s: %s %d getting tls %s (%zu:%zu@%zu) for \"%s[%u]\"", 711 __func__, ps->ps_title[privsep_process], ps->ps_instance, label, 712 tls_conf->tls_len, len, tls_conf->tls_chunk_offset, srv_conf->name, 713 srv_conf->id); 714 715 if (tls_conf->tls_chunk_offset == 0) { 716 free(*outdata); 717 *outlen = 0; 718 if ((*outdata = calloc(1, tls_conf->tls_len)) == NULL) 719 goto fail; 720 *outlen = tls_conf->tls_len; 721 } 722 723 if (*outdata == NULL) { 724 log_debug("%s: tls config invalid chunk sequence", __func__); 725 goto fail; 726 } 727 728 if (*outlen != tls_conf->tls_len) { 729 log_debug("%s: tls config length mismatch (%zu != %zu)", 730 __func__, *outlen, tls_conf->tls_len); 731 goto fail; 732 } 733 734 if (len > (tls_conf->tls_len - tls_conf->tls_chunk_offset)) { 735 log_debug("%s: tls config invalid chunk length", __func__); 736 goto fail; 737 } 738 739 memcpy(*outdata + tls_conf->tls_chunk_offset, data, len); 740 741 return (0); 742 743 fail: 744 return (-1); 745 } 746 747 int 748 config_getserver_tls(struct httpd *env, struct imsg *imsg) 749 { 750 struct server_config *srv_conf = NULL; 751 struct tls_config tls_conf; 752 uint8_t *p = imsg->data; 753 size_t len; 754 755 IMSG_SIZE_CHECK(imsg, &tls_conf); 756 memcpy(&tls_conf, p, sizeof(tls_conf)); 757 758 len = tls_conf.tls_chunk_len; 759 760 if ((IMSG_DATA_SIZE(imsg) - sizeof(tls_conf)) < len) { 761 log_debug("%s: invalid message length", __func__); 762 goto fail; 763 } 764 765 p += sizeof(tls_conf); 766 767 if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) { 768 log_debug("%s: server not found", __func__); 769 goto fail; 770 } 771 772 switch (tls_conf.tls_type) { 773 case TLS_CFG_CA: 774 if (config_gettls(env, srv_conf, &tls_conf, "ca", p, len, 775 &srv_conf->tls_ca, &srv_conf->tls_ca_len) != 0) 776 goto fail; 777 break; 778 779 case TLS_CFG_CERT: 780 if (config_gettls(env, srv_conf, &tls_conf, "cert", p, len, 781 &srv_conf->tls_cert, &srv_conf->tls_cert_len) != 0) 782 goto fail; 783 break; 784 785 case TLS_CFG_CRL: 786 if (config_gettls(env, srv_conf, &tls_conf, "crl", p, len, 787 &srv_conf->tls_crl, &srv_conf->tls_crl_len) != 0) 788 goto fail; 789 break; 790 791 case TLS_CFG_KEY: 792 if (config_gettls(env, srv_conf, &tls_conf, "key", p, len, 793 &srv_conf->tls_key, &srv_conf->tls_key_len) != 0) 794 goto fail; 795 break; 796 797 case TLS_CFG_OCSP_STAPLE: 798 if (config_gettls(env, srv_conf, &tls_conf, "ocsp staple", 799 p, len, &srv_conf->tls_ocsp_staple, 800 &srv_conf->tls_ocsp_staple_len) != 0) 801 goto fail; 802 break; 803 804 default: 805 log_debug("%s: unknown tls config type %i\n", 806 __func__, tls_conf.tls_type); 807 goto fail; 808 } 809 810 return (0); 811 812 fail: 813 return (-1); 814 } 815 816 int 817 config_setmedia(struct httpd *env, struct media_type *media) 818 { 819 struct privsep *ps = env->sc_ps; 820 int id; 821 unsigned int what; 822 823 for (id = 0; id < PROC_MAX; id++) { 824 what = ps->ps_what[id]; 825 826 if ((what & CONFIG_MEDIA) == 0 || id == privsep_process) 827 continue; 828 829 DPRINTF("%s: sending media \"%s\" to %s", __func__, 830 media->media_name, ps->ps_title[id]); 831 832 proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media)); 833 } 834 835 return (0); 836 } 837 838 int 839 config_getmedia(struct httpd *env, struct imsg *imsg) 840 { 841 #ifdef DEBUG 842 struct privsep *ps = env->sc_ps; 843 #endif 844 struct media_type media; 845 uint8_t *p = imsg->data; 846 847 IMSG_SIZE_CHECK(imsg, &media); 848 memcpy(&media, p, sizeof(media)); 849 850 if (media_add(env->sc_mediatypes, &media) == NULL) { 851 log_debug("%s: failed to add media \"%s\"", 852 __func__, media.media_name); 853 return (-1); 854 } 855 856 DPRINTF("%s: %s %d received media \"%s\"", __func__, 857 ps->ps_title[privsep_process], ps->ps_instance, 858 media.media_name); 859 860 return (0); 861 } 862 863 int 864 config_setauth(struct httpd *env, struct auth *auth) 865 { 866 struct privsep *ps = env->sc_ps; 867 int id; 868 unsigned int what; 869 870 for (id = 0; id < PROC_MAX; id++) { 871 what = ps->ps_what[id]; 872 873 if ((what & CONFIG_AUTH) == 0 || id == privsep_process) 874 continue; 875 876 DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__, 877 auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]); 878 879 proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth)); 880 } 881 882 return (0); 883 } 884 885 int 886 config_getauth(struct httpd *env, struct imsg *imsg) 887 { 888 #ifdef DEBUG 889 struct privsep *ps = env->sc_ps; 890 #endif 891 struct auth auth; 892 uint8_t *p = imsg->data; 893 894 IMSG_SIZE_CHECK(imsg, &auth); 895 memcpy(&auth, p, sizeof(auth)); 896 897 if (auth_add(env->sc_auth, &auth) == NULL) { 898 log_debug("%s: failed to add auth \"%s[%u]\"", 899 __func__, auth.auth_htpasswd, auth.auth_id); 900 return (-1); 901 } 902 903 DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__, 904 ps->ps_title[privsep_process], ps->ps_instance, 905 auth.auth_htpasswd, auth.auth_id); 906 907 return (0); 908 } 909