1 /*- 2 * Copyright (c) 2012 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/auditdistd.c#3 $ 30 */ 31 32 #include <config/config.h> 33 34 #include <sys/param.h> 35 #if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) 36 #include <sys/endian.h> 37 #else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ 38 #ifdef HAVE_MACHINE_ENDIAN_H 39 #include <machine/endian.h> 40 #else /* !HAVE_MACHINE_ENDIAN_H */ 41 #ifdef HAVE_ENDIAN_H 42 #include <endian.h> 43 #else /* !HAVE_ENDIAN_H */ 44 #error "No supported endian.h" 45 #endif /* !HAVE_ENDIAN_H */ 46 #endif /* !HAVE_MACHINE_ENDIAN_H */ 47 #include <compat/endian.h> 48 #endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ 49 #include <sys/queue.h> 50 #include <sys/wait.h> 51 52 #include <ctype.h> 53 #include <err.h> 54 #include <errno.h> 55 #include <fcntl.h> 56 #ifdef HAVE_LIBUTIL_H 57 #include <libutil.h> 58 #endif 59 #include <signal.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #include <strings.h> 64 #include <unistd.h> 65 66 #include <openssl/hmac.h> 67 68 #ifndef HAVE_PIDFILE_OPEN 69 #include <compat/pidfile.h> 70 #endif 71 #ifndef HAVE_STRLCPY 72 #include <compat/strlcpy.h> 73 #endif 74 #ifndef HAVE_SIGTIMEDWAIT 75 #include "sigtimedwait.h" 76 #endif 77 78 #include "auditdistd.h" 79 #include "pjdlog.h" 80 #include "proto.h" 81 #include "subr.h" 82 #include "synch.h" 83 84 /* Path to configuration file. */ 85 const char *cfgpath = ADIST_CONFIG; 86 /* Auditdistd configuration. */ 87 static struct adist_config *adcfg; 88 /* Was SIGINT or SIGTERM signal received? */ 89 bool sigexit_received = false; 90 /* PID file handle. */ 91 struct pidfh *pfh; 92 93 /* How often check for hooks running for too long. */ 94 #define SIGNALS_CHECK_INTERVAL 5 95 96 static void 97 usage(void) 98 { 99 100 errx(EX_USAGE, "[-dFhl] [-c config] [-P pidfile]"); 101 } 102 103 void 104 descriptors_cleanup(struct adist_host *adhost) 105 { 106 struct adist_host *adh; 107 struct adist_listen *lst; 108 109 TAILQ_FOREACH(adh, &adcfg->adc_hosts, adh_next) { 110 if (adh == adhost) 111 continue; 112 if (adh->adh_remote != NULL) { 113 proto_close(adh->adh_remote); 114 adh->adh_remote = NULL; 115 } 116 } 117 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { 118 if (lst->adl_conn != NULL) 119 proto_close(lst->adl_conn); 120 } 121 (void)pidfile_close(pfh); 122 pjdlog_fini(); 123 } 124 125 static void 126 child_cleanup(struct adist_host *adhost) 127 { 128 129 if (adhost->adh_conn != NULL) { 130 PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); 131 proto_close(adhost->adh_conn); 132 adhost->adh_conn = NULL; 133 } 134 adhost->adh_worker_pid = 0; 135 } 136 137 static void 138 child_exit_log(const char *type, unsigned int pid, int status) 139 { 140 141 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 142 pjdlog_debug(1, "%s process exited gracefully (pid=%u).", 143 type, pid); 144 } else if (WIFSIGNALED(status)) { 145 pjdlog_error("%s process killed (pid=%u, signal=%d).", 146 type, pid, WTERMSIG(status)); 147 } else { 148 pjdlog_error("%s process exited ungracefully (pid=%u, exitcode=%d).", 149 type, pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1); 150 } 151 } 152 153 static void 154 child_exit(void) 155 { 156 struct adist_host *adhost; 157 bool restart; 158 int status; 159 pid_t pid; 160 161 restart = false; 162 while ((pid = wait3(&status, WNOHANG, NULL)) > 0) { 163 /* Find host related to the process that just exited. */ 164 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 165 if (pid == adhost->adh_worker_pid) 166 break; 167 } 168 if (adhost == NULL) { 169 child_exit_log("Sandbox", pid, status); 170 } else { 171 if (adhost->adh_role == ADIST_ROLE_SENDER) 172 restart = true; 173 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, 174 role2str(adhost->adh_role)); 175 child_exit_log("Worker", pid, status); 176 child_cleanup(adhost); 177 pjdlog_prefix_set("%s", ""); 178 } 179 } 180 if (!restart) 181 return; 182 /* We have some sender processes to restart. */ 183 sleep(1); 184 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 185 if (adhost->adh_role != ADIST_ROLE_SENDER) 186 continue; 187 if (adhost->adh_worker_pid != 0) 188 continue; 189 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, 190 role2str(adhost->adh_role)); 191 pjdlog_info("Restarting sender process."); 192 adist_sender(adcfg, adhost); 193 pjdlog_prefix_set("%s", ""); 194 } 195 } 196 197 /* TODO */ 198 static void 199 adist_reload(void) 200 { 201 202 pjdlog_info("Reloading configuration is not yet implemented."); 203 } 204 205 static void 206 terminate_workers(void) 207 { 208 struct adist_host *adhost; 209 210 pjdlog_info("Termination signal received, exiting."); 211 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 212 if (adhost->adh_worker_pid == 0) 213 continue; 214 pjdlog_info("Terminating worker process (adhost=%s, role=%s, pid=%u).", 215 adhost->adh_name, role2str(adhost->adh_role), 216 adhost->adh_worker_pid); 217 if (kill(adhost->adh_worker_pid, SIGTERM) == 0) 218 continue; 219 pjdlog_errno(LOG_WARNING, 220 "Unable to send signal to worker process (adhost=%s, role=%s, pid=%u).", 221 adhost->adh_name, role2str(adhost->adh_role), 222 adhost->adh_worker_pid); 223 } 224 } 225 226 static void 227 listen_accept(struct adist_listen *lst) 228 { 229 unsigned char rnd[32], hash[32], resp[32]; 230 struct adist_host *adhost; 231 struct proto_conn *conn; 232 char adname[ADIST_HOSTSIZE]; 233 char laddr[256], raddr[256]; 234 char welcome[8]; 235 int status, version; 236 pid_t pid; 237 238 proto_local_address(lst->adl_conn, laddr, sizeof(laddr)); 239 pjdlog_debug(1, "Accepting connection to %s.", laddr); 240 241 if (proto_accept(lst->adl_conn, &conn) == -1) { 242 pjdlog_errno(LOG_ERR, "Unable to accept connection to %s", 243 laddr); 244 return; 245 } 246 247 proto_local_address(conn, laddr, sizeof(laddr)); 248 proto_remote_address(conn, raddr, sizeof(raddr)); 249 pjdlog_info("Connection from %s to %s.", raddr, laddr); 250 251 /* Error in setting timeout is not critical, but why should it fail? */ 252 if (proto_timeout(conn, ADIST_TIMEOUT) < 0) 253 pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); 254 255 /* 256 * Before receiving any data see if remote host is known. 257 */ 258 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 259 if (adhost->adh_role != ADIST_ROLE_RECEIVER) 260 continue; 261 if (!proto_address_match(conn, adhost->adh_remoteaddr)) 262 continue; 263 break; 264 } 265 if (adhost == NULL) { 266 pjdlog_error("Client %s is not known.", raddr); 267 goto close; 268 } 269 /* Ok, remote host is known. */ 270 271 /* Exchange welcome message, which include version number. */ 272 bzero(welcome, sizeof(welcome)); 273 if (proto_recv(conn, welcome, sizeof(welcome)) == -1) { 274 pjdlog_errno(LOG_WARNING, 275 "Unable to receive welcome message from %s", 276 adhost->adh_remoteaddr); 277 goto close; 278 } 279 if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) || 280 !isdigit(welcome[6]) || welcome[7] != '\0') { 281 pjdlog_warning("Invalid welcome message from %s.", 282 adhost->adh_remoteaddr); 283 goto close; 284 } 285 286 version = MIN(ADIST_VERSION, atoi(welcome + 5)); 287 288 (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", version); 289 if (proto_send(conn, welcome, sizeof(welcome)) == -1) { 290 pjdlog_errno(LOG_WARNING, 291 "Unable to send welcome message to %s", 292 adhost->adh_remoteaddr); 293 goto close; 294 } 295 296 if (proto_recv(conn, adname, sizeof(adhost->adh_name)) < 0) { 297 pjdlog_errno(LOG_ERR, "Unable to receive hostname from %s", 298 raddr); 299 goto close; 300 } 301 302 /* Find host now that we have hostname. */ 303 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 304 if (adhost->adh_role != ADIST_ROLE_RECEIVER) 305 continue; 306 if (!proto_address_match(conn, adhost->adh_remoteaddr)) 307 continue; 308 if (strcmp(adhost->adh_name, adname) != 0) 309 continue; 310 break; 311 } 312 if (adhost == NULL) { 313 pjdlog_error("No configuration for host %s from address %s.", 314 adname, raddr); 315 goto close; 316 } 317 318 adhost->adh_version = version; 319 pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version, 320 adhost->adh_remoteaddr); 321 322 /* Now that we know host name setup log prefix. */ 323 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, 324 role2str(adhost->adh_role)); 325 326 if (adist_random(rnd, sizeof(rnd)) == -1) { 327 pjdlog_error("Unable to generate challenge."); 328 goto close; 329 } 330 pjdlog_debug(1, "Challenge generated."); 331 332 if (proto_send(conn, rnd, sizeof(rnd)) == -1) { 333 pjdlog_errno(LOG_ERR, "Unable to send challenge to %s", 334 adhost->adh_remoteaddr); 335 goto close; 336 } 337 pjdlog_debug(1, "Challenge sent."); 338 339 if (proto_recv(conn, resp, sizeof(resp)) == -1) { 340 pjdlog_errno(LOG_ERR, "Unable to receive response from %s", 341 adhost->adh_remoteaddr); 342 goto close; 343 } 344 pjdlog_debug(1, "Response received."); 345 346 if (HMAC(EVP_sha256(), adhost->adh_password, 347 (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, 348 NULL) == NULL) { 349 pjdlog_error("Unable to generate hash."); 350 goto close; 351 } 352 pjdlog_debug(1, "Hash generated."); 353 354 if (memcmp(resp, hash, sizeof(hash)) != 0) { 355 pjdlog_error("Invalid response from %s (wrong password?).", 356 adhost->adh_remoteaddr); 357 goto close; 358 } 359 pjdlog_info("Sender authenticated."); 360 361 if (proto_recv(conn, rnd, sizeof(rnd)) == -1) { 362 pjdlog_errno(LOG_ERR, "Unable to receive challenge from %s", 363 adhost->adh_remoteaddr); 364 goto close; 365 } 366 pjdlog_debug(1, "Challenge received."); 367 368 if (HMAC(EVP_sha256(), adhost->adh_password, 369 (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, 370 NULL) == NULL) { 371 pjdlog_error("Unable to generate response."); 372 goto close; 373 } 374 pjdlog_debug(1, "Response generated."); 375 376 if (proto_send(conn, hash, sizeof(hash)) == -1) { 377 pjdlog_errno(LOG_ERR, "Unable to send response to %s", 378 adhost->adh_remoteaddr); 379 goto close; 380 } 381 pjdlog_debug(1, "Response sent."); 382 383 if (adhost->adh_worker_pid != 0) { 384 pjdlog_debug(1, 385 "Receiver process exists (pid=%u), stopping it.", 386 (unsigned int)adhost->adh_worker_pid); 387 /* Stop child process. */ 388 if (kill(adhost->adh_worker_pid, SIGINT) == -1) { 389 pjdlog_errno(LOG_ERR, 390 "Unable to stop worker process (pid=%u)", 391 (unsigned int)adhost->adh_worker_pid); 392 /* 393 * Other than logging the problem we 394 * ignore it - nothing smart to do. 395 */ 396 } 397 /* Wait for it to exit. */ 398 else if ((pid = waitpid(adhost->adh_worker_pid, 399 &status, 0)) != adhost->adh_worker_pid) { 400 /* We can only log the problem. */ 401 pjdlog_errno(LOG_ERR, 402 "Waiting for worker process (pid=%u) failed", 403 (unsigned int)adhost->adh_worker_pid); 404 } else { 405 child_exit_log("Worker", adhost->adh_worker_pid, 406 status); 407 } 408 child_cleanup(adhost); 409 } 410 411 adhost->adh_remote = conn; 412 adist_receiver(adcfg, adhost); 413 414 pjdlog_prefix_set("%s", ""); 415 return; 416 close: 417 proto_close(conn); 418 pjdlog_prefix_set("%s", ""); 419 } 420 421 static void 422 connection_migrate(struct adist_host *adhost) 423 { 424 struct proto_conn *conn; 425 int16_t val = 0; 426 427 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, 428 role2str(adhost->adh_role)); 429 430 PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); 431 432 if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) { 433 pjdlog_errno(LOG_WARNING, 434 "Unable to receive connection command"); 435 return; 436 } 437 if (proto_set("tls:fingerprint", adhost->adh_fingerprint) == -1) { 438 val = errno; 439 pjdlog_errno(LOG_WARNING, "Unable to set fingerprint"); 440 goto out; 441 } 442 if (proto_connect(adhost->adh_localaddr[0] != '\0' ? 443 adhost->adh_localaddr : NULL, 444 adhost->adh_remoteaddr, -1, &conn) < 0) { 445 val = errno; 446 pjdlog_errno(LOG_WARNING, "Unable to connect to %s", 447 adhost->adh_remoteaddr); 448 goto out; 449 } 450 val = 0; 451 out: 452 if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) { 453 pjdlog_errno(LOG_WARNING, 454 "Unable to send reply to connection request"); 455 } 456 if (val == 0 && proto_connection_send(adhost->adh_conn, conn) < 0) 457 pjdlog_errno(LOG_WARNING, "Unable to send connection"); 458 459 pjdlog_prefix_set("%s", ""); 460 } 461 462 static void 463 check_signals(void) 464 { 465 struct timespec sigtimeout; 466 sigset_t mask; 467 int signo; 468 469 sigtimeout.tv_sec = 0; 470 sigtimeout.tv_nsec = 0; 471 472 PJDLOG_VERIFY(sigemptyset(&mask) == 0); 473 PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); 474 PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); 475 PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); 476 PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); 477 478 while ((signo = sigtimedwait(&mask, NULL, &sigtimeout)) != -1) { 479 switch (signo) { 480 case SIGINT: 481 case SIGTERM: 482 sigexit_received = true; 483 terminate_workers(); 484 exit(EX_OK); 485 break; 486 case SIGCHLD: 487 child_exit(); 488 break; 489 case SIGHUP: 490 adist_reload(); 491 break; 492 default: 493 PJDLOG_ABORT("Unexpected signal (%d).", signo); 494 } 495 } 496 } 497 498 static void 499 main_loop(void) 500 { 501 struct adist_host *adhost; 502 struct adist_listen *lst; 503 struct timeval seltimeout; 504 int fd, maxfd, ret; 505 fd_set rfds; 506 507 seltimeout.tv_sec = SIGNALS_CHECK_INTERVAL; 508 seltimeout.tv_usec = 0; 509 510 pjdlog_info("Started successfully."); 511 512 for (;;) { 513 check_signals(); 514 515 /* Setup descriptors for select(2). */ 516 FD_ZERO(&rfds); 517 maxfd = -1; 518 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { 519 if (lst->adl_conn == NULL) 520 continue; 521 fd = proto_descriptor(lst->adl_conn); 522 PJDLOG_ASSERT(fd >= 0); 523 FD_SET(fd, &rfds); 524 maxfd = fd > maxfd ? fd : maxfd; 525 } 526 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 527 if (adhost->adh_role == ADIST_ROLE_SENDER) { 528 /* Only sender workers asks for connections. */ 529 PJDLOG_ASSERT(adhost->adh_conn != NULL); 530 fd = proto_descriptor(adhost->adh_conn); 531 PJDLOG_ASSERT(fd >= 0); 532 FD_SET(fd, &rfds); 533 maxfd = fd > maxfd ? fd : maxfd; 534 } else { 535 PJDLOG_ASSERT(adhost->adh_conn == NULL); 536 } 537 } 538 539 PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); 540 ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout); 541 if (ret == 0) { 542 /* 543 * select(2) timed out, so there should be no 544 * descriptors to check. 545 */ 546 continue; 547 } else if (ret == -1) { 548 if (errno == EINTR) 549 continue; 550 KEEP_ERRNO((void)pidfile_remove(pfh)); 551 pjdlog_exit(EX_OSERR, "select() failed"); 552 } 553 PJDLOG_ASSERT(ret > 0); 554 555 /* 556 * Check for signals before we do anything to update our 557 * info about terminated workers in the meantime. 558 */ 559 check_signals(); 560 561 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { 562 if (lst->adl_conn == NULL) 563 continue; 564 if (FD_ISSET(proto_descriptor(lst->adl_conn), &rfds)) 565 listen_accept(lst); 566 } 567 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 568 if (adhost->adh_role == ADIST_ROLE_SENDER) { 569 PJDLOG_ASSERT(adhost->adh_conn != NULL); 570 if (FD_ISSET(proto_descriptor(adhost->adh_conn), 571 &rfds)) { 572 connection_migrate(adhost); 573 } 574 } else { 575 PJDLOG_ASSERT(adhost->adh_conn == NULL); 576 } 577 } 578 } 579 } 580 581 static void 582 adist_config_dump(struct adist_config *cfg) 583 { 584 struct adist_host *adhost; 585 struct adist_listen *lst; 586 587 pjdlog_debug(2, "Configuration:"); 588 pjdlog_debug(2, " Global:"); 589 pjdlog_debug(2, " pidfile: %s", cfg->adc_pidfile); 590 pjdlog_debug(2, " timeout: %d", cfg->adc_timeout); 591 if (TAILQ_EMPTY(&cfg->adc_listen)) { 592 pjdlog_debug(2, " Sender only, not listening."); 593 } else { 594 pjdlog_debug(2, " Listening on:"); 595 TAILQ_FOREACH(lst, &cfg->adc_listen, adl_next) { 596 pjdlog_debug(2, " listen: %s", lst->adl_addr); 597 pjdlog_debug(2, " conn: %p", lst->adl_conn); 598 } 599 } 600 pjdlog_debug(2, " Hosts:"); 601 TAILQ_FOREACH(adhost, &cfg->adc_hosts, adh_next) { 602 pjdlog_debug(2, " name: %s", adhost->adh_name); 603 pjdlog_debug(2, " role: %s", role2str(adhost->adh_role)); 604 pjdlog_debug(2, " version: %d", adhost->adh_version); 605 pjdlog_debug(2, " localaddr: %s", adhost->adh_localaddr); 606 pjdlog_debug(2, " remoteaddr: %s", adhost->adh_remoteaddr); 607 pjdlog_debug(2, " remote: %p", adhost->adh_remote); 608 pjdlog_debug(2, " directory: %s", adhost->adh_directory); 609 pjdlog_debug(2, " compression: %d", adhost->adh_compression); 610 pjdlog_debug(2, " checksum: %d", adhost->adh_checksum); 611 pjdlog_debug(2, " pid: %ld", (long)adhost->adh_worker_pid); 612 pjdlog_debug(2, " conn: %p", adhost->adh_conn); 613 } 614 } 615 616 static void 617 dummy_sighandler(int sig __unused) 618 { 619 /* Nothing to do. */ 620 } 621 622 int 623 main(int argc, char *argv[]) 624 { 625 struct adist_host *adhost; 626 struct adist_listen *lst; 627 const char *execpath, *pidfile; 628 bool foreground, launchd; 629 pid_t otherpid; 630 int debuglevel; 631 sigset_t mask; 632 633 execpath = argv[0]; 634 if (execpath[0] != '/') { 635 errx(EX_USAGE, 636 "auditdistd requires execution with an absolute path."); 637 } 638 639 /* 640 * We are executed from proto to create sandbox. 641 */ 642 if (argc > 1 && strcmp(argv[1], "proto") == 0) { 643 argc -= 2; 644 argv += 2; 645 if (proto_exec(argc, argv) == -1) 646 err(EX_USAGE, "Unable to execute proto"); 647 } 648 649 foreground = false; 650 debuglevel = 0; 651 launchd = false; 652 pidfile = NULL; 653 654 for (;;) { 655 int ch; 656 657 ch = getopt(argc, argv, "c:dFhlP:"); 658 if (ch == -1) 659 break; 660 switch (ch) { 661 case 'c': 662 cfgpath = optarg; 663 break; 664 case 'd': 665 debuglevel++; 666 break; 667 case 'F': 668 foreground = true; 669 break; 670 case 'l': 671 launchd = true; 672 break; 673 case 'P': 674 pidfile = optarg; 675 break; 676 case 'h': 677 default: 678 usage(); 679 } 680 } 681 argc -= optind; 682 argv += optind; 683 684 pjdlog_init(PJDLOG_MODE_STD); 685 pjdlog_debug_set(debuglevel); 686 687 if (proto_set("execpath", execpath) == -1) 688 pjdlog_exit(EX_TEMPFAIL, "Unable to set executable name"); 689 if (proto_set("user", ADIST_USER) == -1) 690 pjdlog_exit(EX_TEMPFAIL, "Unable to set proto user"); 691 if (proto_set("tcp:port", ADIST_TCP_PORT) == -1) 692 pjdlog_exit(EX_TEMPFAIL, "Unable to set default TCP port"); 693 694 /* 695 * When path to the configuration file is relative, obtain full path, 696 * so we can always find the file, even after daemonizing and changing 697 * working directory to /. 698 */ 699 if (cfgpath[0] != '/') { 700 const char *newcfgpath; 701 702 newcfgpath = realpath(cfgpath, NULL); 703 if (newcfgpath == NULL) { 704 pjdlog_exit(EX_CONFIG, 705 "Unable to obtain full path of %s", cfgpath); 706 } 707 cfgpath = newcfgpath; 708 } 709 710 adcfg = yy_config_parse(cfgpath, true); 711 PJDLOG_ASSERT(adcfg != NULL); 712 adist_config_dump(adcfg); 713 714 if (proto_set("tls:certfile", adcfg->adc_certfile) == -1) 715 pjdlog_exit(EX_TEMPFAIL, "Unable to set certfile path"); 716 if (proto_set("tls:keyfile", adcfg->adc_keyfile) == -1) 717 pjdlog_exit(EX_TEMPFAIL, "Unable to set keyfile path"); 718 719 if (pidfile != NULL) { 720 if (strlcpy(adcfg->adc_pidfile, pidfile, 721 sizeof(adcfg->adc_pidfile)) >= 722 sizeof(adcfg->adc_pidfile)) { 723 pjdlog_exitx(EX_CONFIG, "Pidfile path is too long."); 724 } 725 } 726 if (foreground && pidfile == NULL) { 727 pfh = NULL; 728 } else { 729 pfh = pidfile_open(adcfg->adc_pidfile, 0600, &otherpid); 730 if (pfh == NULL) { 731 if (errno == EEXIST) { 732 pjdlog_exitx(EX_TEMPFAIL, 733 "Another auditdistd is already running, pid: %jd.", 734 (intmax_t)otherpid); 735 } 736 /* 737 * If we cannot create pidfile from other reasons, 738 * only warn. 739 */ 740 pjdlog_errno(LOG_WARNING, 741 "Unable to open or create pidfile %s", 742 adcfg->adc_pidfile); 743 } 744 } 745 746 /* 747 * Restore default actions for interesting signals in case parent 748 * process (like init(8)) decided to ignore some of them (like SIGHUP). 749 */ 750 PJDLOG_VERIFY(signal(SIGHUP, SIG_DFL) != SIG_ERR); 751 PJDLOG_VERIFY(signal(SIGINT, SIG_DFL) != SIG_ERR); 752 PJDLOG_VERIFY(signal(SIGTERM, SIG_DFL) != SIG_ERR); 753 /* 754 * Because SIGCHLD is ignored by default, setup dummy handler for it, 755 * so we can mask it. 756 */ 757 PJDLOG_VERIFY(signal(SIGCHLD, dummy_sighandler) != SIG_ERR); 758 759 PJDLOG_VERIFY(sigemptyset(&mask) == 0); 760 PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); 761 PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); 762 PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); 763 PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); 764 PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); 765 766 /* Listen for remote connections. */ 767 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { 768 if (proto_server(lst->adl_addr, &lst->adl_conn) == -1) { 769 KEEP_ERRNO((void)pidfile_remove(pfh)); 770 pjdlog_exit(EX_OSERR, "Unable to listen on address %s", 771 lst->adl_addr); 772 } 773 } 774 775 if (!foreground) { 776 if (!launchd && daemon(0, 0) == -1) { 777 KEEP_ERRNO((void)pidfile_remove(pfh)); 778 pjdlog_exit(EX_OSERR, "Unable to daemonize"); 779 } 780 781 /* Start logging to syslog. */ 782 pjdlog_mode_set(PJDLOG_MODE_SYSLOG); 783 } 784 if (pfh != NULL) { 785 /* Write PID to a file. */ 786 if (pidfile_write(pfh) < 0) { 787 pjdlog_errno(LOG_WARNING, 788 "Unable to write PID to a file"); 789 } 790 } 791 792 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { 793 if (adhost->adh_role == ADIST_ROLE_SENDER) 794 adist_sender(adcfg, adhost); 795 } 796 797 main_loop(); 798 799 exit(0); 800 } 801