1 /* $OpenBSD: config.c,v 1.48 2016/09/01 16:07:55 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 150 what = ps->ps_what[privsep_process]; 151 152 if (privsep_process != PROC_PARENT) 153 proc_compose(env->sc_ps, PROC_PARENT, 154 IMSG_CFG_DONE, NULL, 0); 155 156 return (0); 157 } 158 159 int 160 config_setserver(struct httpd *env, struct server *srv) 161 { 162 struct privsep *ps = env->sc_ps; 163 struct server_config s; 164 int id; 165 int fd, n, m; 166 struct iovec iov[6]; 167 size_t c; 168 unsigned int what; 169 170 /* opens listening sockets etc. */ 171 if (server_privinit(srv) == -1) 172 return (-1); 173 174 for (id = 0; id < PROC_MAX; id++) { 175 what = ps->ps_what[id]; 176 177 if ((what & CONFIG_SERVERS) == 0 || id == privsep_process) 178 continue; 179 180 DPRINTF("%s: sending %s \"%s[%u]\" to %s fd %d", __func__, 181 (srv->srv_conf.flags & SRVFLAG_LOCATION) ? 182 "location" : "server", 183 srv->srv_conf.name, srv->srv_conf.id, 184 ps->ps_title[id], srv->srv_s); 185 186 memcpy(&s, &srv->srv_conf, sizeof(s)); 187 188 c = 0; 189 iov[c].iov_base = &s; 190 iov[c++].iov_len = sizeof(s); 191 if (srv->srv_conf.return_uri_len != 0) { 192 iov[c].iov_base = srv->srv_conf.return_uri; 193 iov[c++].iov_len = srv->srv_conf.return_uri_len; 194 } 195 196 if (id == PROC_SERVER && 197 (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) { 198 /* XXX imsg code will close the fd after 1st call */ 199 n = -1; 200 proc_range(ps, id, &n, &m); 201 for (n = 0; n < m; n++) { 202 if (srv->srv_s == -1) 203 fd = -1; 204 else if ((fd = dup(srv->srv_s)) == -1) 205 return (-1); 206 if (proc_composev_imsg(ps, id, n, 207 IMSG_CFG_SERVER, -1, fd, iov, c) != 0) { 208 log_warn("%s: failed to compose " 209 "IMSG_CFG_SERVER imsg for `%s'", 210 __func__, srv->srv_conf.name); 211 return (-1); 212 } 213 } 214 215 /* Configure TLS if necessary. */ 216 config_settls(env, srv); 217 } else { 218 if (proc_composev(ps, id, IMSG_CFG_SERVER, 219 iov, c) != 0) { 220 log_warn("%s: failed to compose " 221 "IMSG_CFG_SERVER imsg for `%s'", 222 __func__, srv->srv_conf.name); 223 return (-1); 224 } 225 } 226 } 227 228 return (0); 229 } 230 231 int 232 config_settls(struct httpd *env, struct server *srv) 233 { 234 struct privsep *ps = env->sc_ps; 235 struct server_config *srv_conf = &srv->srv_conf; 236 struct tls_config tls; 237 struct iovec iov[2]; 238 size_t c; 239 240 if ((srv_conf->flags & SRVFLAG_TLS) == 0) 241 return (0); 242 243 log_debug("%s: configuring tls for %s", __func__, srv_conf->name); 244 245 if (srv_conf->tls_cert_len != 0) { 246 DPRINTF("%s: sending tls cert \"%s[%u]\" to %s fd %d", __func__, 247 srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 248 srv->srv_s); 249 250 memset(&tls, 0, sizeof(tls)); 251 tls.id = srv_conf->id; 252 tls.tls_cert_len = srv_conf->tls_cert_len; 253 254 c = 0; 255 iov[c].iov_base = &tls; 256 iov[c++].iov_len = sizeof(tls); 257 iov[c].iov_base = srv_conf->tls_cert; 258 iov[c++].iov_len = srv_conf->tls_cert_len; 259 260 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) { 261 log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " 262 "`%s'", __func__, srv_conf->name); 263 return (-1); 264 } 265 } 266 267 if (srv_conf->tls_key_len != 0) { 268 DPRINTF("%s: sending tls key \"%s[%u]\" to %s fd %d", __func__, 269 srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER], 270 srv->srv_s); 271 272 memset(&tls, 0, sizeof(tls)); 273 tls.id = srv_conf->id; 274 tls.tls_key_len = srv_conf->tls_key_len; 275 276 c = 0; 277 iov[c].iov_base = &tls; 278 iov[c++].iov_len = sizeof(tls); 279 iov[c].iov_base = srv_conf->tls_key; 280 iov[c++].iov_len = srv_conf->tls_key_len; 281 282 if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) { 283 log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " 284 "`%s'", __func__, srv_conf->name); 285 return (-1); 286 } 287 } 288 289 return (0); 290 } 291 292 int 293 config_getserver_auth(struct httpd *env, struct server_config *srv_conf) 294 { 295 struct privsep *ps = env->sc_ps; 296 297 if ((ps->ps_what[privsep_process] & CONFIG_AUTH) == 0 || 298 (srv_conf->flags & SRVFLAG_AUTH) == 0) 299 return (0); 300 301 if ((srv_conf->auth = auth_byid(env->sc_auth, 302 srv_conf->auth_id)) == NULL) 303 return (-1); 304 305 return (0); 306 } 307 308 int 309 config_getserver_config(struct httpd *env, struct server *srv, 310 struct imsg *imsg) 311 { 312 #ifdef DEBUG 313 struct privsep *ps = env->sc_ps; 314 #endif 315 struct server_config *srv_conf, *parent; 316 uint8_t *p = imsg->data; 317 unsigned int f; 318 size_t s; 319 320 if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL) 321 return (-1); 322 323 IMSG_SIZE_CHECK(imsg, srv_conf); 324 memcpy(srv_conf, p, sizeof(*srv_conf)); 325 s = sizeof(*srv_conf); 326 327 /* Reset these variables to avoid free'ing invalid pointers */ 328 serverconfig_reset(srv_conf); 329 330 TAILQ_FOREACH(parent, &srv->srv_hosts, entry) { 331 if (strcmp(parent->name, srv_conf->name) == 0) 332 break; 333 } 334 if (parent == NULL) 335 parent = &srv->srv_conf; 336 337 if (config_getserver_auth(env, srv_conf) != 0) 338 goto fail; 339 340 /* 341 * Get variable-length values for the virtual host. The tls_* ones 342 * aren't needed in the virtual hosts unless we implement SNI. 343 */ 344 if (srv_conf->return_uri_len != 0) { 345 if ((srv_conf->return_uri = get_data(p + s, 346 srv_conf->return_uri_len)) == NULL) 347 goto fail; 348 s += srv_conf->return_uri_len; 349 } 350 351 if (srv_conf->flags & SRVFLAG_LOCATION) { 352 /* Inherit configuration from the parent */ 353 f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX; 354 if ((srv_conf->flags & f) == 0) { 355 srv_conf->flags |= parent->flags & f; 356 (void)strlcpy(srv_conf->index, parent->index, 357 sizeof(srv_conf->index)); 358 } 359 360 f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX; 361 if ((srv_conf->flags & f) == 0) 362 srv_conf->flags |= parent->flags & f; 363 364 f = SRVFLAG_SOCKET|SRVFLAG_FCGI; 365 if ((srv_conf->flags & f) == SRVFLAG_FCGI) { 366 srv_conf->flags |= f; 367 (void)strlcpy(srv_conf->socket, HTTPD_FCGI_SOCKET, 368 sizeof(srv_conf->socket)); 369 } 370 371 f = SRVFLAG_ROOT; 372 if ((srv_conf->flags & f) == 0) { 373 srv_conf->flags |= parent->flags & f; 374 (void)strlcpy(srv_conf->root, parent->root, 375 sizeof(srv_conf->root)); 376 } 377 378 f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI; 379 if ((srv_conf->flags & f) == 0) 380 srv_conf->flags |= parent->flags & f; 381 382 f = SRVFLAG_LOG|SRVFLAG_NO_LOG; 383 if ((srv_conf->flags & f) == 0) { 384 srv_conf->flags |= parent->flags & f; 385 srv_conf->logformat = parent->logformat; 386 } 387 388 f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG; 389 if ((srv_conf->flags & f) == 0) 390 srv_conf->flags |= parent->flags & f; 391 392 f = SRVFLAG_AUTH|SRVFLAG_NO_AUTH; 393 if ((srv_conf->flags & f) == 0) { 394 srv_conf->flags |= parent->flags & f; 395 srv_conf->auth = parent->auth; 396 srv_conf->auth_id = parent->auth_id; 397 (void)strlcpy(srv_conf->auth_realm, 398 parent->auth_realm, 399 sizeof(srv_conf->auth_realm)); 400 } 401 402 f = SRVFLAG_TLS; 403 srv_conf->flags |= parent->flags & f; 404 405 f = SRVFLAG_ACCESS_LOG; 406 if ((srv_conf->flags & f) == 0) { 407 srv_conf->flags |= parent->flags & f; 408 (void)strlcpy(srv_conf->accesslog, 409 parent->accesslog, 410 sizeof(srv_conf->accesslog)); 411 } 412 413 f = SRVFLAG_ERROR_LOG; 414 if ((srv_conf->flags & f) == 0) { 415 srv_conf->flags |= parent->flags & f; 416 (void)strlcpy(srv_conf->errorlog, 417 parent->errorlog, 418 sizeof(srv_conf->errorlog)); 419 } 420 421 f = SRVFLAG_BLOCK|SRVFLAG_NO_BLOCK; 422 if ((srv_conf->flags & f) == 0) { 423 free(srv_conf->return_uri); 424 srv_conf->flags |= parent->flags & f; 425 srv_conf->return_code = parent->return_code; 426 srv_conf->return_uri_len = parent->return_uri_len; 427 if (srv_conf->return_uri_len && 428 (srv_conf->return_uri = 429 strdup(parent->return_uri)) == NULL) 430 goto fail; 431 } 432 433 f = SRVFLAG_DEFAULT_TYPE; 434 if ((srv_conf->flags & f) == 0) { 435 srv_conf->flags |= parent->flags & f; 436 memcpy(&srv_conf->default_type, 437 &parent->default_type, sizeof(struct media_type)); 438 } 439 440 f = SRVFLAG_SERVER_HSTS; 441 srv_conf->flags |= parent->flags & f; 442 srv_conf->hsts_max_age = parent->hsts_max_age; 443 srv_conf->hsts_flags = parent->hsts_flags; 444 445 memcpy(&srv_conf->timeout, &parent->timeout, 446 sizeof(srv_conf->timeout)); 447 srv_conf->maxrequests = parent->maxrequests; 448 srv_conf->maxrequestbody = parent->maxrequestbody; 449 450 DPRINTF("%s: %s %d location \"%s\", " 451 "parent \"%s[%u]\", flags: %s", 452 __func__, ps->ps_title[privsep_process], ps->ps_instance, 453 srv_conf->location, parent->name, parent->id, 454 printb_flags(srv_conf->flags, SRVFLAG_BITS)); 455 } else { 456 /* Add a new "virtual" server */ 457 DPRINTF("%s: %s %d server \"%s[%u]\", parent \"%s[%u]\", " 458 "flags: %s", __func__, 459 ps->ps_title[privsep_process], ps->ps_instance, 460 srv_conf->name, srv_conf->id, parent->name, parent->id, 461 printb_flags(srv_conf->flags, SRVFLAG_BITS)); 462 } 463 464 TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry); 465 466 return (0); 467 468 fail: 469 serverconfig_free(srv_conf); 470 free(srv_conf); 471 return (-1); 472 } 473 474 int 475 config_getserver(struct httpd *env, struct imsg *imsg) 476 { 477 #ifdef DEBUG 478 struct privsep *ps = env->sc_ps; 479 #endif 480 struct server *srv = NULL; 481 struct server_config srv_conf; 482 uint8_t *p = imsg->data; 483 size_t s; 484 485 IMSG_SIZE_CHECK(imsg, &srv_conf); 486 memcpy(&srv_conf, p, sizeof(srv_conf)); 487 s = sizeof(srv_conf); 488 489 /* Reset these variables to avoid free'ing invalid pointers */ 490 serverconfig_reset(&srv_conf); 491 492 if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) { 493 log_debug("%s: invalid message length", __func__); 494 goto fail; 495 } 496 497 /* Check if server with matching listening socket already exists */ 498 if ((srv = server_byaddr((struct sockaddr *) 499 &srv_conf.ss, srv_conf.port)) != NULL) { 500 /* Add "host" to existing listening server */ 501 if (imsg->fd != -1) { 502 if (srv->srv_s == -1) 503 srv->srv_s = imsg->fd; 504 else 505 close(imsg->fd); 506 } 507 return (config_getserver_config(env, srv, imsg)); 508 } 509 510 if (srv_conf.flags & SRVFLAG_LOCATION) 511 fatalx("invalid location"); 512 513 /* Otherwise create a new server */ 514 if ((srv = calloc(1, sizeof(*srv))) == NULL) 515 goto fail; 516 517 memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf)); 518 srv->srv_s = imsg->fd; 519 520 if (config_getserver_auth(env, &srv->srv_conf) != 0) 521 goto fail; 522 523 SPLAY_INIT(&srv->srv_clients); 524 TAILQ_INIT(&srv->srv_hosts); 525 526 TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry); 527 TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry); 528 529 DPRINTF("%s: %s %d configuration \"%s[%u]\", flags: %s", __func__, 530 ps->ps_title[privsep_process], ps->ps_instance, 531 srv->srv_conf.name, srv->srv_conf.id, 532 printb_flags(srv->srv_conf.flags, SRVFLAG_BITS)); 533 534 /* 535 * Get all variable-length values for the parent server. 536 */ 537 if (srv->srv_conf.return_uri_len != 0) { 538 if ((srv->srv_conf.return_uri = get_data(p + s, 539 srv->srv_conf.return_uri_len)) == NULL) 540 goto fail; 541 s += srv->srv_conf.return_uri_len; 542 } 543 544 return (0); 545 546 fail: 547 if (imsg->fd != -1) 548 close(imsg->fd); 549 if (srv != NULL) 550 serverconfig_free(&srv->srv_conf); 551 free(srv); 552 553 return (-1); 554 } 555 556 int 557 config_gettls(struct httpd *env, struct imsg *imsg) 558 { 559 #ifdef DEBUG 560 struct privsep *ps = env->sc_ps; 561 #endif 562 struct server_config *srv_conf = NULL; 563 struct tls_config tls_conf; 564 uint8_t *p = imsg->data; 565 size_t s; 566 567 IMSG_SIZE_CHECK(imsg, &tls_conf); 568 memcpy(&tls_conf, p, sizeof(tls_conf)); 569 s = sizeof(tls_conf); 570 571 if ((IMSG_DATA_SIZE(imsg) - s) < 572 (tls_conf.tls_cert_len + tls_conf.tls_key_len)) { 573 log_debug("%s: invalid message length", __func__); 574 goto fail; 575 } 576 577 if ((srv_conf = serverconfig_byid(tls_conf.id)) == NULL) { 578 log_debug("%s: server not found", __func__); 579 goto fail; 580 } 581 582 DPRINTF("%s: %s %d tls configuration \"%s[%u]\"", __func__, 583 ps->ps_title[privsep_process], ps->ps_instance, 584 srv_conf->name, srv_conf->id); 585 586 if (tls_conf.tls_cert_len != 0) { 587 srv_conf->tls_cert_len = tls_conf.tls_cert_len; 588 if ((srv_conf->tls_cert = get_data(p + s, 589 tls_conf.tls_cert_len)) == NULL) 590 goto fail; 591 s += tls_conf.tls_cert_len; 592 } 593 if (tls_conf.tls_key_len != 0) { 594 srv_conf->tls_key_len = tls_conf.tls_key_len; 595 if ((srv_conf->tls_key = get_data(p + s, 596 tls_conf.tls_key_len)) == NULL) 597 goto fail; 598 s += tls_conf.tls_key_len; 599 } 600 601 return (0); 602 603 fail: 604 return (-1); 605 } 606 607 int 608 config_setmedia(struct httpd *env, struct media_type *media) 609 { 610 struct privsep *ps = env->sc_ps; 611 int id; 612 unsigned int what; 613 614 for (id = 0; id < PROC_MAX; id++) { 615 what = ps->ps_what[id]; 616 617 if ((what & CONFIG_MEDIA) == 0 || id == privsep_process) 618 continue; 619 620 DPRINTF("%s: sending media \"%s\" to %s", __func__, 621 media->media_name, ps->ps_title[id]); 622 623 proc_compose(ps, id, IMSG_CFG_MEDIA, media, sizeof(*media)); 624 } 625 626 return (0); 627 } 628 629 int 630 config_getmedia(struct httpd *env, struct imsg *imsg) 631 { 632 #ifdef DEBUG 633 struct privsep *ps = env->sc_ps; 634 #endif 635 struct media_type media; 636 uint8_t *p = imsg->data; 637 638 IMSG_SIZE_CHECK(imsg, &media); 639 memcpy(&media, p, sizeof(media)); 640 641 if (media_add(env->sc_mediatypes, &media) == NULL) { 642 log_debug("%s: failed to add media \"%s\"", 643 __func__, media.media_name); 644 return (-1); 645 } 646 647 DPRINTF("%s: %s %d received media \"%s\"", __func__, 648 ps->ps_title[privsep_process], ps->ps_instance, 649 media.media_name); 650 651 return (0); 652 } 653 654 int 655 config_setauth(struct httpd *env, struct auth *auth) 656 { 657 struct privsep *ps = env->sc_ps; 658 int id; 659 unsigned int what; 660 661 for (id = 0; id < PROC_MAX; id++) { 662 what = ps->ps_what[id]; 663 664 if ((what & CONFIG_AUTH) == 0 || id == privsep_process) 665 continue; 666 667 DPRINTF("%s: sending auth \"%s[%u]\" to %s", __func__, 668 auth->auth_htpasswd, auth->auth_id, ps->ps_title[id]); 669 670 proc_compose(ps, id, IMSG_CFG_AUTH, auth, sizeof(*auth)); 671 } 672 673 return (0); 674 } 675 676 int 677 config_getauth(struct httpd *env, struct imsg *imsg) 678 { 679 #ifdef DEBUG 680 struct privsep *ps = env->sc_ps; 681 #endif 682 struct auth auth; 683 uint8_t *p = imsg->data; 684 685 IMSG_SIZE_CHECK(imsg, &auth); 686 memcpy(&auth, p, sizeof(auth)); 687 688 if (auth_add(env->sc_auth, &auth) == NULL) { 689 log_debug("%s: failed to add auth \"%s[%u]\"", 690 __func__, auth.auth_htpasswd, auth.auth_id); 691 return (-1); 692 } 693 694 DPRINTF("%s: %s %d received auth \"%s[%u]\"", __func__, 695 ps->ps_title[privsep_process], ps->ps_instance, 696 auth.auth_htpasswd, auth.auth_id); 697 698 return (0); 699 } 700