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