1 /* $OpenBSD: config.c,v 1.45 2016/04/28 14:20:11 jsing 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 53 /* Other configuration */ 54 what = ps->ps_what[privsep_process]; 55 56 if (what & CONFIG_SERVERS) { 57 if ((env->sc_servers = 58 calloc(1, sizeof(*env->sc_servers))) == NULL) 59 return (-1); 60 TAILQ_INIT(env->sc_servers); 61 } 62 63 if (what & CONFIG_MEDIA) { 64 if ((env->sc_mediatypes = 65 calloc(1, sizeof(*env->sc_mediatypes))) == NULL) 66 return (-1); 67 RB_INIT(env->sc_mediatypes); 68 } 69 70 if (what & CONFIG_AUTH) { 71 if ((env->sc_auth = 72 calloc(1, sizeof(*env->sc_auth))) == NULL) 73 return (-1); 74 TAILQ_INIT(env->sc_auth); 75 } 76 77 return (0); 78 } 79 80 void 81 config_purge(struct httpd *env, unsigned int reset) 82 { 83 struct privsep *ps = env->sc_ps; 84 struct server *srv; 85 struct auth *auth; 86 unsigned int what; 87 88 what = ps->ps_what[privsep_process] & reset; 89 90 if (what & CONFIG_SERVERS && env->sc_servers != NULL) { 91 while ((srv = TAILQ_FIRST(env->sc_servers)) != NULL) 92 server_purge(srv); 93 } 94 95 if (what & CONFIG_MEDIA && env->sc_mediatypes != NULL) 96 media_purge(env->sc_mediatypes); 97 98 if (what & CONFIG_AUTH && env->sc_auth != NULL) { 99 while ((auth = TAILQ_FIRST(env->sc_auth)) != NULL) { 100 auth_free(env->sc_auth, auth); 101 free(auth); 102 } 103 } 104 } 105 106 int 107 config_setreset(struct httpd *env, unsigned int reset) 108 { 109 struct privsep *ps = env->sc_ps; 110 int id; 111 112 for (id = 0; id < PROC_MAX; id++) { 113 if ((reset & ps->ps_what[id]) == 0 || 114 id == privsep_process) 115 continue; 116 proc_compose(ps, id, IMSG_CTL_RESET, 117 &reset, sizeof(reset)); 118 } 119 120 return (0); 121 } 122 123 int 124 config_getreset(struct httpd *env, struct imsg *imsg) 125 { 126 unsigned int mode; 127 128 IMSG_SIZE_CHECK(imsg, &mode); 129 memcpy(&mode, imsg->data, sizeof(mode)); 130 131 config_purge(env, mode); 132 133 return (0); 134 } 135 136 int 137 config_getcfg(struct httpd *env, struct imsg *imsg) 138 { 139 struct privsep *ps = env->sc_ps; 140 struct ctl_flags cf; 141 unsigned int what; 142 143 if (IMSG_DATA_SIZE(imsg) != sizeof(cf)) 144 return (0); /* ignore */ 145 146 /* Update runtime flags */ 147 memcpy(&cf, imsg->data, sizeof(cf)); 148 env->sc_opts = cf.cf_opts; 149 env->sc_flags = cf.cf_flags; 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 216 /* Configure TLS if necessary. */ 217 config_settls(env, srv); 218 } else { 219 if (proc_composev(ps, id, IMSG_CFG_SERVER, 220 iov, c) != 0) { 221 log_warn("%s: failed to compose " 222 "IMSG_CFG_SERVER imsg for `%s'", 223 __func__, srv->srv_conf.name); 224 return (-1); 225 } 226 } 227 } 228 229 return (0); 230 } 231 232 int 233 config_settls(struct httpd *env, struct server *srv) 234 { 235 struct privsep *ps = env->sc_ps; 236 struct server_config *srv_conf = &srv->srv_conf; 237 struct tls_config tls; 238 struct iovec iov[2]; 239 size_t c; 240 241 if ((srv_conf->flags & SRVFLAG_TLS) == 0) 242 return (0); 243 244 log_debug("%s: configuring TLS for %s", __func__, srv_conf->name); 245 246 if (srv_conf->tls_cert_len != 0) { 247 DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__, 248 srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 249 srv->srv_s); 250 251 memset(&tls, 0, sizeof(tls)); 252 tls.id = srv_conf->id; 253 tls.tls_cert_len = srv_conf->tls_cert_len; 254 255 c = 0; 256 iov[c].iov_base = &tls; 257 iov[c++].iov_len = sizeof(tls); 258 iov[c].iov_base = srv_conf->tls_cert; 259 iov[c++].iov_len = srv_conf->tls_cert_len; 260 261 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) { 262 log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " 263 "`%s'", __func__, srv_conf->name); 264 return (-1); 265 } 266 } 267 268 if (srv_conf->tls_key_len != 0) { 269 DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__, 270 srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 271 srv->srv_s); 272 273 memset(&tls, 0, sizeof(tls)); 274 tls.id = srv_conf->id; 275 tls.tls_key_len = srv_conf->tls_key_len; 276 277 c = 0; 278 iov[c].iov_base = &tls; 279 iov[c++].iov_len = sizeof(tls); 280 iov[c].iov_base = srv_conf->tls_key; 281 iov[c++].iov_len = srv_conf->tls_key_len; 282 283 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) { 284 log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " 285 "`%s'", __func__, srv_conf->name); 286 return (-1); 287 } 288 } 289 290 return (0); 291 } 292 293 int 294 config_getserver_auth(struct httpd *env, struct server_config *srv_conf) 295 { 296 struct privsep *ps = env->sc_ps; 297 298 if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 || 299 (srv_conf->flags & SRVFLAG_AUTH) == 0) 300 return (0); 301 302 if ((srv_conf->auth = auth_byid(env->sc_auth, 303 srv_conf->auth_id)) == NULL) 304 return (-1); 305 306 return (0); 307 } 308 309 int 310 config_getserver_config(struct httpd *env, struct server *srv, 311 struct imsg *imsg) 312 { 313 #ifdef DEBUG 314 struct privsep *ps = env->sc_ps; 315 #endif 316 struct server_config *srv_conf, *parent; 317 uint8_t *p = imsg->data; 318 unsigned int f; 319 size_t s; 320 321 if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL) 322 return (-1); 323 324 IMSG_SIZE_CHECK(imsg, srv_conf); 325 memcpy(srv_conf, p, sizeof(*srv_conf)); 326 s = sizeof(*srv_conf); 327 328 /* Reset these variables to avoid free'ing invalid pointers */ 329 serverconfig_reset(srv_conf); 330 331 TAILQ_FOREACH(parent, &srv->srv_hosts, entry) { 332 if (strcmp(parent->name, srv_conf->name) == 0) 333 break; 334 } 335 if (parent == NULL) 336 parent = &srv->srv_conf; 337 338 if (config_getserver_auth(env, srv_conf) != 0) 339 goto fail; 340 341 /* 342 * Get variable-length values for the virtual host. The tls_* ones 343 * aren't needed in the virtual hosts unless we implement SNI. 344 */ 345 if (srv_conf->return_uri_len != 0) { 346 if ((srv_conf->return_uri = get_data(p + s, 347 srv_conf->return_uri_len)) == NULL) 348 goto fail; 349 s += srv_conf->return_uri_len; 350 } 351 352 if (srv_conf->flags & SRVFLAG_LOCATION) { 353 /* Inherit configuration from the parent */ 354 f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX; 355 if ((srv_conf->flags & f) == 0) { 356 srv_conf->flags |= parent->flags & f; 357 (void)strlcpy(srv_conf->index, parent->index, 358 sizeof(srv_conf->index)); 359 } 360 361 f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX; 362 if ((srv_conf->flags & f) == 0) 363 srv_conf->flags |= parent->flags & f; 364 365 f = SRVFLAG_SOCKET|SRVFLAG_FCGI; 366 if ((srv_conf->flags & f) == SRVFLAG_FCGI) { 367 srv_conf->flags |= f; 368 (void)strlcpy(srv_conf->socket, HTTPD_FCGI_SOCKET, 369 sizeof(srv_conf->socket)); 370 } 371 372 f = SRVFLAG_ROOT; 373 if ((srv_conf->flags & f) == 0) { 374 srv_conf->flags |= parent->flags & f; 375 (void)strlcpy(srv_conf->root, parent->root, 376 sizeof(srv_conf->root)); 377 } 378 379 f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI; 380 if ((srv_conf->flags & f) == 0) 381 srv_conf->flags |= parent->flags & f; 382 383 f = SRVFLAG_LOG|SRVFLAG_NO_LOG; 384 if ((srv_conf->flags & f) == 0) { 385 srv_conf->flags |= parent->flags & f; 386 srv_conf->logformat = parent->logformat; 387 } 388 389 f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG; 390 if ((srv_conf->flags & f) == 0) 391 srv_conf->flags |= parent->flags & f; 392 393 f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH; 394 if ((srv_conf->flags & f) == 0) { 395 srv_conf->flags |= parent->flags & f; 396 srv_conf->auth = parent->auth; 397 srv_conf->auth_id = parent->auth_id; 398 (void)strlcpy(srv_conf->auth_realm, 399 parent->auth_realm, 400 sizeof(srv_conf->auth_realm)); 401 } 402 403 f = SRVFLAG_TLS; 404 srv_conf->flags |= parent->flags & f; 405 406 f = SRVFLAG_ACCESS_LOG; 407 if ((srv_conf->flags & f) == 0) { 408 srv_conf->flags |= parent->flags & f; 409 (void)strlcpy(srv_conf->accesslog, 410 parent->accesslog, 411 sizeof(srv_conf->accesslog)); 412 } 413 414 f = SRVFLAG_ERROR_LOG; 415 if ((srv_conf->flags & f) == 0) { 416 srv_conf->flags |= parent->flags & f; 417 (void)strlcpy(srv_conf->errorlog, 418 parent->errorlog, 419 sizeof(srv_conf->errorlog)); 420 } 421 422 f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK; 423 if ((srv_conf->flags & f) == 0) { 424 free(srv_conf->return_uri); 425 srv_conf->flags |= parent->flags & f; 426 srv_conf->return_code = parent->return_code; 427 srv_conf->return_uri_len = parent->return_uri_len; 428 if (srv_conf->return_uri_len && 429 (srv_conf->return_uri = 430 strdup(parent->return_uri)) == NULL) 431 goto fail; 432 } 433 434 f = SRVFLAG_DEFAULT_TYPE; 435 if ((srv_conf->flags & f) == 0) { 436 srv_conf->flags |= parent->flags & f; 437 memcpy(&srv_conf->default_type, 438 &parent->default_type, sizeof(struct media_type)); 439 } 440 441 f = SRVFLAG_SERVER_HSTS; 442 srv_conf->flags |= parent->flags & f; 443 srv_conf->hsts_max_age = parent->hsts_max_age; 444 srv_conf->hsts_flags = parent->hsts_flags; 445 446 memcpy(&srv_conf->timeout, &parent->timeout, 447 sizeof(srv_conf->timeout)); 448 srv_conf->maxrequests = parent->maxrequests; 449 srv_conf->maxrequestbody = parent->maxrequestbody; 450 451 DPRINTF("%s: %s %d location \"%s\", " 452 "parent \"%s[%u]\", flags: %s", 453 __func__, ps->ps_title[privsep_process], ps->ps_instance, 454 srv_conf->location, parent->name, parent->id, 455 printb_flags(srv_conf->flags, SRVFLAG_BITS)); 456 } else { 457 /* Add a new "virtual" server */ 458 DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", " 459 "flags: %s", __func__, 460 ps->ps_title[privsep_process], ps->ps_instance, 461 srv_conf->name, srv_conf->id, parent->name, parent->id, 462 printb_flags(srv_conf->flags, SRVFLAG_BITS)); 463 } 464 465 TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry); 466 467 return (0); 468 469 fail: 470 serverconfig_free(srv_conf); 471 free(srv_conf); 472 return (-1); 473 } 474 475 int 476 config_getserver(struct httpd *env, struct imsg *imsg) 477 { 478 #ifdef DEBUG 479 struct privsep *ps = env->sc_ps; 480 #endif 481 struct server *srv = NULL; 482 struct server_config srv_conf; 483 uint8_t *p = imsg->data; 484 size_t s; 485 486 IMSG_SIZE_CHECK(imsg, &srv_conf); 487 memcpy(&srv_conf, p, sizeof(srv_conf)); 488 s = sizeof(srv_conf); 489 490 /* Reset these variables to avoid free'ing invalid pointers */ 491 serverconfig_reset(&srv_conf); 492 493 if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) { 494 log_debug("%s: invalid message length", __func__); 495 goto fail; 496 } 497 498 /* Check if server with matching listening socket already exists */ 499 if ((srv = server_byaddr((struct sockaddr *) 500 &srv_conf.ss, srv_conf.port)) != NULL) { 501 /* Add "host" to existing listening server */ 502 if (imsg->fd != -1) { 503 if (srv->srv_s == -1) 504 srv->srv_s = imsg->fd; 505 else 506 close(imsg->fd); 507 } 508 return (config_getserver_config(env, srv, imsg)); 509 } 510 511 if (srv_conf.flags & SRVFLAG_LOCATION) 512 fatalx("invalid location"); 513 514 /* Otherwise create a new server */ 515 if ((srv = calloc(1, sizeof(*srv))) == NULL) 516 goto fail; 517 518 memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf)); 519 srv->srv_s = imsg->fd; 520 521 if (config_getserver_auth(env, &srv->srv_conf) != 0) 522 goto fail; 523 524 SPLAY_INIT(&srv->srv_clients); 525 TAILQ_INIT(&srv->srv_hosts); 526 527 TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry); 528 TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry); 529 530 DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__, 531 ps->ps_title[privsep_process], ps->ps_instance, 532 srv->srv_conf.name, srv->srv_conf.id, 533 printb_flags(srv->srv_conf.flags, SRVFLAG_BITS)); 534 535 /* 536 * Get all variable-length values for the parent server. 537 */ 538 if (srv->srv_conf.return_uri_len != 0) { 539 if ((srv->srv_conf.return_uri = get_data(p + s, 540 srv->srv_conf.return_uri_len)) == NULL) 541 goto fail; 542 s += srv->srv_conf.return_uri_len; 543 } 544 545 return (0); 546 547 fail: 548 if (imsg->fd != -1) 549 close(imsg->fd); 550 if (srv != NULL) 551 serverconfig_free(&srv->srv_conf); 552 free(srv); 553 554 return (-1); 555 } 556 557 int 558 config_gettls(struct httpd *env, struct imsg *imsg) 559 { 560 #ifdef DEBUG 561 struct privsep *ps = env->sc_ps; 562 #endif 563 struct server_config *srv_conf = NULL; 564 struct tls_config tls_conf; 565 uint8_t *p = imsg->data; 566 size_t s; 567 568 IMSG_SIZE_CHECK(imsg, &tls_conf); 569 memcpy(&tls_conf, p, sizeof(tls_conf)); 570 s = sizeof(tls_conf); 571 572 if ((IMSG_DATA_SIZE(imsg) - s) < 573 (tls_conf.tls_cert_len + tls_conf.tls_key_len)) { 574 log_debug("%s: invalid message length", __func__); 575 goto fail; 576 } 577 578 if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) { 579 log_debug("%s: server not found", __func__); 580 goto fail; 581 } 582 583 DPRINTF("%s: %s %d TLS configuration \"%s[%u]\"", __func__, 584 ps->ps_title[privsep_process], ps->ps_instance, 585 srv_conf->name, srv->srv_conf.id); 586 587 if (tls_conf.tls_cert_len != 0) { 588 srv_conf->tls_cert_len = tls_conf.tls_cert_len; 589 if ((srv_conf->tls_cert = get_data(p + s, 590 tls_conf.tls_cert_len)) == NULL) 591 goto fail; 592 s += tls_conf.tls_cert_len; 593 } 594 if (tls_conf.tls_key_len != 0) { 595 srv_conf->tls_key_len = tls_conf.tls_key_len; 596 if ((srv_conf->tls_key = get_data(p + s, 597 tls_conf.tls_key_len)) == NULL) 598 goto fail; 599 s += tls_conf.tls_key_len; 600 } 601 602 return (0); 603 604 fail: 605 return (-1); 606 } 607 608 int 609 config_setmedia(struct httpd *env, struct media_type *media) 610 { 611 struct privsep *ps = env->sc_ps; 612 int id; 613 unsigned int what; 614 615 for (id = 0; id < PROC_MAX; id++) { 616 what = ps->ps_what[id]; 617 618 if ((what & CONFIG_MEDIA) == 0 || id == privsep_process) 619 continue; 620 621 DPRINTF("%s: sending media \"%s\" to %s", __func__, 622 media->media_name, ps->ps_title[id]); 623 624 proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media)); 625 } 626 627 return (0); 628 } 629 630 int 631 config_getmedia(struct httpd *env, struct imsg *imsg) 632 { 633 #ifdef DEBUG 634 struct privsep *ps = env->sc_ps; 635 #endif 636 struct media_type media; 637 uint8_t *p = imsg->data; 638 639 IMSG_SIZE_CHECK(imsg, &media); 640 memcpy(&media, p, sizeof(media)); 641 642 if (media_add(env->sc_mediatypes, &media) == NULL) { 643 log_debug("%s: failed to add media \"%s\"", 644 __func__, media.media_name); 645 return (-1); 646 } 647 648 DPRINTF("%s: %s %d received media \"%s\"", __func__, 649 ps->ps_title[privsep_process], ps->ps_instance, 650 media.media_name); 651 652 return (0); 653 } 654 655 int 656 config_setauth(struct httpd *env, struct auth *auth) 657 { 658 struct privsep *ps = env->sc_ps; 659 int id; 660 unsigned int what; 661 662 for (id = 0; id < PROC_MAX; id++) { 663 what = ps->ps_what[id]; 664 665 if ((what & CONFIG_AUTH) == 0 || id == privsep_process) 666 continue; 667 668 DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__, 669 auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]); 670 671 proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth)); 672 } 673 674 return (0); 675 } 676 677 int 678 config_getauth(struct httpd *env, struct imsg *imsg) 679 { 680 #ifdef DEBUG 681 struct privsep *ps = env->sc_ps; 682 #endif 683 struct auth auth; 684 uint8_t *p = imsg->data; 685 686 IMSG_SIZE_CHECK(imsg, &auth); 687 memcpy(&auth, p, sizeof(auth)); 688 689 if (auth_add(env->sc_auth, &auth) == NULL) { 690 log_debug("%s: failed to add auth \"%s[%u]\"", 691 __func__, auth.auth_htpasswd, auth.auth_id); 692 return (-1); 693 } 694 695 DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__, 696 ps->ps_title[privsep_process], ps->ps_instance, 697 auth.auth_htpasswd, auth.auth_id); 698 699 return (0); 700 } 701