2 * Copyright (c) 2012 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
30 #include <config/config.h>
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 */
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>
64 #include <openssl/hmac.h>
66 #ifndef HAVE_PIDFILE_OPEN
67 #include <compat/pidfile.h>
70 #include <compat/strlcpy.h>
72 #ifndef HAVE_SIGTIMEDWAIT
73 #include "sigtimedwait.h"
76 #include "auditdistd.h"
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. */
91 /* How often check for hooks running for too long. */
92 #define SIGNALS_CHECK_INTERVAL 5
98 errx(EX_USAGE, "[-dFhl] [-c config] [-P pidfile]");
102 descriptors_cleanup(struct adist_host *adhost)
104 struct adist_host *adh;
105 struct adist_listen *lst;
107 TAILQ_FOREACH(adh, &adcfg->adc_hosts, adh_next) {
110 if (adh->adh_remote != NULL) {
111 proto_close(adh->adh_remote);
112 adh->adh_remote = NULL;
115 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
116 if (lst->adl_conn != NULL)
117 proto_close(lst->adl_conn);
119 (void)pidfile_close(pfh);
124 child_cleanup(struct adist_host *adhost)
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;
132 adhost->adh_worker_pid = 0;
136 child_exit_log(const char *type, unsigned int pid, int status)
139 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
140 pjdlog_debug(1, "%s process exited gracefully (pid=%u).",
142 } else if (WIFSIGNALED(status)) {
143 pjdlog_error("%s process killed (pid=%u, signal=%d).",
144 type, pid, WTERMSIG(status));
146 pjdlog_error("%s process exited ungracefully (pid=%u, exitcode=%d).",
147 type, pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1);
154 struct adist_host *adhost;
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)
166 if (adhost == NULL) {
167 child_exit_log("Sandbox", pid, status);
169 if (adhost->adh_role == ADIST_ROLE_SENDER)
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", "");
180 /* We have some sender processes to restart. */
182 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
183 if (adhost->adh_role != ADIST_ROLE_SENDER)
185 if (adhost->adh_worker_pid != 0)
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", "");
200 pjdlog_info("Reloading configuration is not yet implemented.");
204 terminate_workers(void)
206 struct adist_host *adhost;
208 pjdlog_info("Termination signal received, exiting.");
209 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
210 if (adhost->adh_worker_pid == 0)
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)
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);
225 listen_accept(struct adist_listen *lst)
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];
236 proto_local_address(lst->adl_conn, laddr, sizeof(laddr));
237 pjdlog_debug(1, "Accepting connection to %s.", laddr);
239 if (proto_accept(lst->adl_conn, &conn) == -1) {
240 pjdlog_errno(LOG_ERR, "Unable to accept connection to %s",
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);
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");
254 * Before receiving any data see if remote host is known.
256 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
257 if (adhost->adh_role != ADIST_ROLE_RECEIVER)
259 if (!proto_address_match(conn, adhost->adh_remoteaddr))
263 if (adhost == NULL) {
264 pjdlog_error("Client %s is not known.", raddr);
267 /* Ok, remote host is known. */
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);
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);
284 version = MIN(ADIST_VERSION, atoi(welcome + 5));
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);
294 if (proto_recv(conn, adname, sizeof(adhost->adh_name)) < 0) {
295 pjdlog_errno(LOG_ERR, "Unable to receive hostname from %s",
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)
304 if (!proto_address_match(conn, adhost->adh_remoteaddr))
306 if (strcmp(adhost->adh_name, adname) != 0)
310 if (adhost == NULL) {
311 pjdlog_error("No configuration for host %s from address %s.",
316 adhost->adh_version = version;
317 pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version,
318 adhost->adh_remoteaddr);
320 /* Now that we know host name setup log prefix. */
321 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
322 role2str(adhost->adh_role));
324 if (adist_random(rnd, sizeof(rnd)) == -1) {
325 pjdlog_error("Unable to generate challenge.");
328 pjdlog_debug(1, "Challenge generated.");
330 if (proto_send(conn, rnd, sizeof(rnd)) == -1) {
331 pjdlog_errno(LOG_ERR, "Unable to send challenge to %s",
332 adhost->adh_remoteaddr);
335 pjdlog_debug(1, "Challenge sent.");
337 if (proto_recv(conn, resp, sizeof(resp)) == -1) {
338 pjdlog_errno(LOG_ERR, "Unable to receive response from %s",
339 adhost->adh_remoteaddr);
342 pjdlog_debug(1, "Response received.");
344 if (HMAC(EVP_sha256(), adhost->adh_password,
345 (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash,
347 pjdlog_error("Unable to generate hash.");
350 pjdlog_debug(1, "Hash generated.");
352 if (memcmp(resp, hash, sizeof(hash)) != 0) {
353 pjdlog_error("Invalid response from %s (wrong password?).",
354 adhost->adh_remoteaddr);
357 pjdlog_info("Sender authenticated.");
359 if (proto_recv(conn, rnd, sizeof(rnd)) == -1) {
360 pjdlog_errno(LOG_ERR, "Unable to receive challenge from %s",
361 adhost->adh_remoteaddr);
364 pjdlog_debug(1, "Challenge received.");
366 if (HMAC(EVP_sha256(), adhost->adh_password,
367 (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash,
369 pjdlog_error("Unable to generate response.");
372 pjdlog_debug(1, "Response generated.");
374 if (proto_send(conn, hash, sizeof(hash)) == -1) {
375 pjdlog_errno(LOG_ERR, "Unable to send response to %s",
376 adhost->adh_remoteaddr);
379 pjdlog_debug(1, "Response sent.");
381 if (adhost->adh_worker_pid != 0) {
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);
391 * Other than logging the problem we
392 * ignore it - nothing smart to do.
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);
403 child_exit_log("Worker", adhost->adh_worker_pid,
406 child_cleanup(adhost);
409 adhost->adh_remote = conn;
410 adist_receiver(adcfg, adhost);
412 pjdlog_prefix_set("%s", "");
416 pjdlog_prefix_set("%s", "");
420 connection_migrate(struct adist_host *adhost)
422 struct proto_conn *conn;
425 pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name,
426 role2str(adhost->adh_role));
428 PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER);
430 if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) {
431 pjdlog_errno(LOG_WARNING,
432 "Unable to receive connection command");
435 if (proto_set("tls:fingerprint", adhost->adh_fingerprint) == -1) {
437 pjdlog_errno(LOG_WARNING, "Unable to set fingerprint");
440 if (proto_connect(adhost->adh_localaddr[0] != '\0' ?
441 adhost->adh_localaddr : NULL,
442 adhost->adh_remoteaddr, -1, &conn) < 0) {
444 pjdlog_errno(LOG_WARNING, "Unable to connect to %s",
445 adhost->adh_remoteaddr);
450 if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) {
451 pjdlog_errno(LOG_WARNING,
452 "Unable to send reply to connection request");
454 if (val == 0 && proto_connection_send(adhost->adh_conn, conn) < 0)
455 pjdlog_errno(LOG_WARNING, "Unable to send connection");
457 pjdlog_prefix_set("%s", "");
463 struct timespec sigtimeout;
467 sigtimeout.tv_sec = 0;
468 sigtimeout.tv_nsec = 0;
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);
476 while ((signo = sigtimedwait(&mask, NULL, &sigtimeout)) != -1) {
480 sigexit_received = true;
491 PJDLOG_ABORT("Unexpected signal (%d).", signo);
499 struct adist_host *adhost;
500 struct adist_listen *lst;
501 struct timeval seltimeout;
505 seltimeout.tv_sec = SIGNALS_CHECK_INTERVAL;
506 seltimeout.tv_usec = 0;
508 pjdlog_info("Started successfully.");
513 /* Setup descriptors for select(2). */
516 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
517 if (lst->adl_conn == NULL)
519 fd = proto_descriptor(lst->adl_conn);
520 PJDLOG_ASSERT(fd >= 0);
522 maxfd = fd > maxfd ? fd : maxfd;
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);
531 maxfd = fd > maxfd ? fd : maxfd;
533 PJDLOG_ASSERT(adhost->adh_conn == NULL);
537 PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE);
538 ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout);
541 * select(2) timed out, so there should be no
542 * descriptors to check.
545 } else if (ret == -1) {
548 KEEP_ERRNO((void)pidfile_remove(pfh));
549 pjdlog_exit(EX_OSERR, "select() failed");
551 PJDLOG_ASSERT(ret > 0);
554 * Check for signals before we do anything to update our
555 * info about terminated workers in the meantime.
559 TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) {
560 if (lst->adl_conn == NULL)
562 if (FD_ISSET(proto_descriptor(lst->adl_conn), &rfds))
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),
570 connection_migrate(adhost);
573 PJDLOG_ASSERT(adhost->adh_conn == NULL);
580 adist_config_dump(struct adist_config *cfg)
582 struct adist_host *adhost;
583 struct adist_listen *lst;
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.");
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);
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);
615 dummy_sighandler(int sig __unused)
621 main(int argc, char *argv[])
623 struct adist_host *adhost;
624 struct adist_listen *lst;
625 const char *execpath, *pidfile;
626 bool foreground, launchd;
632 if (execpath[0] != '/') {
634 "auditdistd requires execution with an absolute path.");
638 * We are executed from proto to create sandbox.
640 if (argc > 1 && strcmp(argv[1], "proto") == 0) {
643 if (proto_exec(argc, argv) == -1)
644 err(EX_USAGE, "Unable to execute proto");
655 ch = getopt(argc, argv, "c:dFhlP:");
682 pjdlog_init(PJDLOG_MODE_STD);
683 pjdlog_debug_set(debuglevel);
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");
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 /.
697 if (cfgpath[0] != '/') {
698 const char *newcfgpath;
700 newcfgpath = realpath(cfgpath, NULL);
701 if (newcfgpath == NULL) {
702 pjdlog_exit(EX_CONFIG,
703 "Unable to obtain full path of %s", cfgpath);
705 cfgpath = newcfgpath;
708 adcfg = yy_config_parse(cfgpath, true);
709 PJDLOG_ASSERT(adcfg != NULL);
710 adist_config_dump(adcfg);
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");
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.");
724 if (foreground && pidfile == NULL) {
727 pfh = pidfile_open(adcfg->adc_pidfile, 0600, &otherpid);
729 if (errno == EEXIST) {
730 pjdlog_exitx(EX_TEMPFAIL,
731 "Another auditdistd is already running, pid: %jd.",
735 * If we cannot create pidfile from other reasons,
738 pjdlog_errno(LOG_WARNING,
739 "Unable to open or create pidfile %s",
745 * Restore default actions for interesting signals in case parent
746 * process (like init(8)) decided to ignore some of them (like SIGHUP).
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);
752 * Because SIGCHLD is ignored by default, setup dummy handler for it,
755 PJDLOG_VERIFY(signal(SIGCHLD, dummy_sighandler) != SIG_ERR);
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);
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",
774 if (!launchd && daemon(0, 0) == -1) {
775 KEEP_ERRNO((void)pidfile_remove(pfh));
776 pjdlog_exit(EX_OSERR, "Unable to daemonize");
779 /* Start logging to syslog. */
780 pjdlog_mode_set(PJDLOG_MODE_SYSLOG);
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");
790 TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) {
791 if (adhost->adh_role == ADIST_ROLE_SENDER)
792 adist_sender(adcfg, adhost);