aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/src/auditd.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/src/auditd.c')
-rw-r--r--framework/src/audit/src/auditd.c917
1 files changed, 0 insertions, 917 deletions
diff --git a/framework/src/audit/src/auditd.c b/framework/src/audit/src/auditd.c
deleted file mode 100644
index 5afebac2..00000000
--- a/framework/src/audit/src/auditd.c
+++ /dev/null
@@ -1,917 +0,0 @@
-/* auditd.c --
- * Copyright 2004-09,2011,2013 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- * Rickard E. (Rik) Faith <faith@redhat.com>
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <sys/utsname.h>
-#include <getopt.h>
-
-#include "libaudit.h"
-#include "auditd-event.h"
-#include "auditd-config.h"
-#include "auditd-dispatch.h"
-#include "auditd-listen.h"
-#include "private.h"
-
-#include "ev.h"
-
-#define EV_STOP() ev_unloop (ev_default_loop (EVFLAG_AUTO), EVUNLOOP_ALL), stop = 1;
-
-#define DEFAULT_BUF_SZ 448
-#define DMSG_SIZE (DEFAULT_BUF_SZ + 48)
-#define SUCCESS 0
-#define FAILURE 1
-#define SUBJ_LEN 4097
-
-/* Global Data */
-volatile int stop = 0;
-
-/* Local data */
-static int fd = -1;
-static struct daemon_conf config;
-static const char *pidfile = "/var/run/auditd.pid";
-static int init_pipe[2];
-static int do_fork = 1;
-static struct auditd_reply_list *rep = NULL;
-static int hup_info_requested = 0;
-static int usr1_info_requested = 0, usr2_info_requested = 0;
-static char subj[SUBJ_LEN];
-
-/* Local function prototypes */
-int send_audit_event(int type, const char *str);
-static void close_down(void);
-static void clean_exit(void);
-static int get_reply(int fd, struct audit_reply *rep, int seq);
-static char *getsubj(char *subj);
-
-enum startup_state {startup_disable=0, startup_enable, startup_nochange,
- startup_INVALID};
-static const char *startup_states[] = {"disable", "enable", "nochange"};
-
-/*
- * Output a usage message
- */
-static void usage(void)
-{
- fprintf(stderr, "Usage: auditd [-f] [-l] [-n] [-s %s|%s|%s]\n",
- startup_states[startup_disable],
- startup_states[startup_enable],
- startup_states[startup_nochange]);
-
- exit(2);
-}
-
-
-/*
- * SIGTERM handler
- */
-static void term_handler(struct ev_loop *loop, struct ev_signal *sig,
- int revents)
-{
- EV_STOP ();
-}
-
-/*
- * Used with sigalrm to force exit
- */
-static void thread_killer( int sig )
-{
- exit(0);
-}
-
-/*
- * Used with sigalrm to force exit
- */
-static void hup_handler( struct ev_loop *loop, struct ev_signal *sig, int revents )
-{
- int rc;
-
- rc = audit_request_signal_info(fd);
- if (rc < 0)
- send_audit_event(AUDIT_DAEMON_CONFIG,
- "auditd error getting hup info - no change, sending auid=? pid=? subj=? res=failed");
- else
- hup_info_requested = 1;
-}
-
-/*
- * Used to force log rotation
- */
-static void user1_handler(struct ev_loop *loop, struct ev_signal *sig,
- int revents)
-{
- int rc;
-
- rc = audit_request_signal_info(fd);
- if (rc < 0)
- send_audit_event(AUDIT_DAEMON_ROTATE,
- "auditd error getting usr1 info - no change, sending auid=? pid=? subj=? res=failed");
- else
- usr1_info_requested = 1;
-}
-
-/*
- * Used to resume logging
- */
-static void user2_handler( struct ev_loop *loop, struct ev_signal *sig, int revents )
-{
- int rc;
-
- rc = audit_request_signal_info(fd);
- if (rc < 0) {
- resume_logging();
- send_audit_event(AUDIT_DAEMON_RESUME,
- "auditd resuming logging, sending auid=? pid=? subj=? res=success");
- } else
- usr2_info_requested = 1;
-}
-
-/*
- * Used with email alerts to cleanup
- */
-static void child_handler(struct ev_loop *loop, struct ev_signal *sig,
- int revents)
-{
- int pid;
-
- while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
- if (pid == dispatcher_pid())
- dispatcher_reaped();
- }
-}
-
-static void distribute_event(struct auditd_reply_list *rep)
-{
- int attempt = 0;
-
- /* Make first attempt to send to plugins */
- if (dispatch_event(&rep->reply, attempt) == 1)
- attempt++; /* Failed sending, retry after writing to disk */
-
- /* End of Event is for realtime interface - skip local logging of it */
- if (rep->reply.type != AUDIT_EOE) {
- int yield = rep->reply.type <= AUDIT_LAST_DAEMON &&
- rep->reply.type >= AUDIT_FIRST_DAEMON ? 1 : 0;
- /* Write to local disk */
- enqueue_event(rep);
- if (yield) {
- struct timespec ts;
- ts.tv_sec = 0;
- ts.tv_nsec = 2 * 1000 * 1000; // 2 milliseconds
- nanosleep(&ts, NULL); // Let other thread try to log it
- }
- } else
- free(rep); // This function takes custody of the memory
-
- // FIXME: This is commented out since it fails to work. The
- // problem is that the logger thread free's the buffer. Probably
- // need a way to flag in the buffer if logger thread should free or
- // move the free to this function.
-
- /* Last chance to send...maybe the pipe is empty now. */
-// if (attempt)
-// dispatch_event(&rep->reply, attempt);
-}
-
-/*
- * This function is used to send start, stop, and abort messages
- * to the audit log.
- */
-static unsigned seq_num = 0;
-int send_audit_event(int type, const char *str)
-{
- struct auditd_reply_list *rep;
- struct timeval tv;
-
- if ((rep = malloc(sizeof(*rep))) == NULL) {
- audit_msg(LOG_ERR, "Cannot allocate audit reply");
- return 1;
- }
-
- rep->reply.type = type;
- rep->reply.message = (char *)malloc(DMSG_SIZE);
- if (rep->reply.message == NULL) {
- free(rep);
- audit_msg(LOG_ERR, "Cannot allocate local event message");
- return 1;
- }
- if (seq_num == 0) {
- srand(time(NULL));
- seq_num = rand()%10000;
- } else
- seq_num++;
- if (gettimeofday(&tv, NULL) == 0) {
- rep->reply.len = snprintf((char *)rep->reply.message,
- DMSG_SIZE, "audit(%lu.%03u:%u): %s",
- tv.tv_sec, (unsigned)(tv.tv_usec/1000), seq_num, str);
- } else {
- rep->reply.len = snprintf((char *)rep->reply.message,
- DMSG_SIZE, "audit(%lu.%03u:%u): %s",
- (unsigned long)time(NULL), 0, seq_num, str);
- }
- if (rep->reply.len > DMSG_SIZE)
- rep->reply.len = DMSG_SIZE;
-
- distribute_event(rep);
- return 0;
-}
-
-static int write_pid_file(void)
-{
- int pidfd, len;
- char val[16];
-
- len = snprintf(val, sizeof(val), "%u\n", getpid());
- if (len <= 0) {
- audit_msg(LOG_ERR, "Pid error (%s)", strerror(errno));
- pidfile = 0;
- return 1;
- }
- pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
- if (pidfd < 0) {
- audit_msg(LOG_ERR, "Unable to set pidfile (%s)",
- strerror(errno));
- pidfile = 0;
- return 1;
- }
- if (write(pidfd, val, (unsigned int)len) != len) {
- audit_msg(LOG_ERR, "Unable to write pidfile (%s)",
- strerror(errno));
- close(pidfd);
- pidfile = 0;
- return 1;
- }
- close(pidfd);
- return 0;
-}
-
-static void avoid_oom_killer(void)
-{
- int oomfd, len, rc;
- char *score = NULL;
-
- /* New kernels use different technique */
- if ((oomfd = open("/proc/self/oom_score_adj",
- O_NOFOLLOW | O_WRONLY)) >= 0) {
- score = "-1000";
- } else if ((oomfd = open("/proc/self/oom_adj",
- O_NOFOLLOW | O_WRONLY)) >= 0) {
- score = "-17";
- } else {
- audit_msg(LOG_NOTICE, "Cannot open out of memory adjuster");
- return;
- }
-
- len = strlen(score);
- rc = write(oomfd, score, len);
- if (rc != len)
- audit_msg(LOG_NOTICE, "Unable to adjust out of memory score");
-
- close(oomfd);
-}
-
-/*
- * This function will take care of becoming a daemon. The parent
- * will wait until the child notifies it by writing into a special
- * pipe to signify that it successfully initialized. This prevents
- * a race in the init script where rules get loaded before the daemon
- * is ready and they wind up in syslog. The child returns 0 on success
- * and nonzero on failure. The parent returns nonzero on failure. On
- * success, the parent calls _exit with 0.
- */
-static int become_daemon(void)
-{
- int fd, rc;
- pid_t pid;
- int status;
-
- if (do_fork) {
- if (pipe(init_pipe) ||
- fcntl(init_pipe[0], F_SETFD, FD_CLOEXEC) ||
- fcntl(init_pipe[0], F_SETFD, FD_CLOEXEC))
- return -1;
- pid = fork();
- } else
- pid = 0;
-
- switch (pid)
- {
- case 0:
- /* No longer need this... */
- if (do_fork)
- close(init_pipe[0]);
-
- /* Open stdin,out,err to /dev/null */
- fd = open("/dev/null", O_RDWR);
- if (fd < 0) {
- audit_msg(LOG_ERR, "Cannot open /dev/null");
- return -1;
- }
- if ((dup2(fd, 0) < 0) || (dup2(fd, 1) < 0) ||
- (dup2(fd, 2) < 0)) {
- audit_msg(LOG_ERR,
- "Cannot reassign descriptors to /dev/null");
- close(fd);
- return -1;
- }
- close(fd);
-
- /* Change to '/' */
- rc = chdir("/");
- if (rc < 0) {
- audit_msg(LOG_ERR,
- "Cannot change working directory to /");
- return -1;
- }
-
- /* Become session/process group leader */
- setsid();
- break;
- case -1:
- return -1;
- break;
- default:
- /* Wait for the child to say its done */
- rc = read(init_pipe[0], &status, sizeof(status));
- if (rc < 0)
- return -1;
-
- /* Success - die a happy death */
- if (status == SUCCESS)
- _exit(0);
- else
- return -1;
- break;
- }
-
- return 0;
-}
-
-static void tell_parent(int status)
-{
- int rc;
-
- if (config.daemonize != D_BACKGROUND || do_fork == 0)
- return;
- do {
- rc = write(init_pipe[1], &status, sizeof(status));
- } while (rc < 0 && errno == EINTR);
-}
-
-static void netlink_handler(struct ev_loop *loop, struct ev_io *io,
- int revents)
-{
- if (rep == NULL) {
- if ((rep = malloc(sizeof(*rep))) == NULL) {
- char emsg[DEFAULT_BUF_SZ];
- if (*subj)
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d subj=%s res=failed",
- audit_getloginuid(), getpid(), subj);
- else
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d res=failed",
- audit_getloginuid(), getpid());
- EV_STOP ();
- send_audit_event(AUDIT_DAEMON_ABORT, emsg);
- audit_msg(LOG_ERR,
- "Cannot allocate audit reply, exiting");
- close_down();
- if (pidfile)
- unlink(pidfile);
- shutdown_dispatcher();
- return;
- }
- }
- if (audit_get_reply(fd, &rep->reply,
- GET_REPLY_NONBLOCKING, 0) > 0) {
- switch (rep->reply.type)
- { /* For now dont process these */
- case NLMSG_NOOP:
- case NLMSG_DONE:
- case NLMSG_ERROR:
- case AUDIT_GET: /* Or these */
- case AUDIT_LIST_RULES:
- case AUDIT_FIRST_DAEMON...AUDIT_LAST_DAEMON:
- break;
- case AUDIT_SIGNAL_INFO:
- if (hup_info_requested) {
- audit_msg(LOG_DEBUG,
- "HUP detected, starting config manager");
- if (start_config_manager(rep)) {
- send_audit_event(
- AUDIT_DAEMON_CONFIG,
- "auditd error getting hup info - no change,"
- " sending auid=? pid=? subj=? res=failed");
- }
- rep = NULL;
- hup_info_requested = 0;
- } else if (usr1_info_requested) {
- char usr1[MAX_AUDIT_MESSAGE_LENGTH];
- if (rep->reply.len == 24) {
- snprintf(usr1, sizeof(usr1),
- "auditd sending auid=? pid=? subj=?");
- } else {
- snprintf(usr1, sizeof(usr1),
- "auditd sending auid=%u pid=%d subj=%s",
- rep->reply.signal_info->uid,
- rep->reply.signal_info->pid,
- rep->reply.signal_info->ctx);
- }
- send_audit_event(AUDIT_DAEMON_ROTATE, usr1);
- usr1_info_requested = 0;
- } else if (usr2_info_requested) {
- char usr2[MAX_AUDIT_MESSAGE_LENGTH];
- if (rep->reply.len == 24) {
- snprintf(usr2, sizeof(usr2),
- "auditd resuming logging, "
- "sending auid=? pid=? subj=? "
- "res=success");
- } else {
- snprintf(usr2, sizeof(usr2),
- "auditd resuming logging, "
- "sending auid=%u pid=%d subj=%s res=success",
- rep->reply.signal_info->uid,
- rep->reply.signal_info->pid,
- rep->reply.signal_info->ctx);
- }
- resume_logging();
- send_audit_event(AUDIT_DAEMON_RESUME, usr2);
- usr2_info_requested = 0;
- }
- break;
- default:
- distribute_event(rep);
- rep = NULL;
- break;
- }
- } else {
- if (errno == EFBIG) {
- // FIXME do err action
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- struct sigaction sa;
- struct rlimit limit;
- int i, c, rc;
- int opt_foreground = 0, opt_allow_links = 0;
- enum startup_state opt_startup = startup_enable;
- extern char *optarg;
- extern int optind;
- struct ev_loop *loop;
- struct ev_io netlink_watcher;
- struct ev_signal sigterm_watcher;
- struct ev_signal sighup_watcher;
- struct ev_signal sigusr1_watcher;
- struct ev_signal sigusr2_watcher;
- struct ev_signal sigchld_watcher;
-
- /* Get params && set mode */
- while ((c = getopt(argc, argv, "flns:")) != -1) {
- switch (c) {
- case 'f':
- opt_foreground = 1;
- break;
- case 'l':
- opt_allow_links=1;
- break;
- case 'n':
- do_fork = 0;
- break;
- case 's':
- for (i=0; i<startup_INVALID; i++) {
- if (strncmp(optarg, startup_states[i],
- strlen(optarg)) == 0) {
- opt_startup = i;
- break;
- }
- }
- if (i == startup_INVALID) {
- fprintf(stderr, "unknown startup mode '%s'\n",
- optarg);
- usage();
- }
- break;
- default:
- usage();
- }
- }
-
- /* check for trailing command line following options */
- if (optind < argc) {
- usage();
- }
-
- if (opt_allow_links)
- set_allow_links(1);
-
- if (opt_foreground) {
- config.daemonize = D_FOREGROUND;
- set_aumessage_mode(MSG_STDERR, DBG_YES);
- } else {
- config.daemonize = D_BACKGROUND;
- set_aumessage_mode(MSG_SYSLOG, DBG_NO);
- (void) umask( umask( 077 ) | 022 );
- }
-
-#ifndef DEBUG
- /* Make sure we are root */
- if (getuid() != 0) {
- fprintf(stderr, "You must be root to run this program.\n");
- return 4;
- }
-#endif
-
- /* Register sighandlers */
- sa.sa_flags = 0 ;
- sigemptyset( &sa.sa_mask ) ;
- /* Ignore all signals by default */
- sa.sa_handler = SIG_IGN;
- for (i=1; i<NSIG; i++)
- sigaction( i, &sa, NULL );
-
- atexit(clean_exit);
-
- /* Raise the rlimits in case we're being started from a shell
- * with restrictions. Not a fatal error. */
- limit.rlim_cur = RLIM_INFINITY;
- limit.rlim_max = RLIM_INFINITY;
- setrlimit(RLIMIT_FSIZE, &limit);
- setrlimit(RLIMIT_CPU, &limit);
-
- /* Load the Configuration File */
- if (load_config(&config, TEST_AUDITD))
- return 6;
-
- if (config.priority_boost != 0) {
- errno = 0;
- rc = nice((int)-config.priority_boost);
- if (rc == -1 && errno) {
- audit_msg(LOG_ERR, "Cannot change priority (%s)",
- strerror(errno));
- return 1;
- }
- }
-
- /* Daemonize or stay in foreground for debugging */
- if (config.daemonize == D_BACKGROUND) {
- if (become_daemon() != 0) {
- audit_msg(LOG_ERR, "Cannot daemonize (%s)",
- strerror(errno));
- tell_parent(FAILURE);
- return 1;
- }
- openlog("auditd", LOG_PID, LOG_DAEMON);
- }
-
- /* Init netlink */
- if ((fd = audit_open()) < 0) {
- audit_msg(LOG_ERR, "Cannot open netlink audit socket");
- tell_parent(FAILURE);
- return 1;
- }
-
- /* Init the event handler thread */
- write_pid_file();
- if (init_event(&config)) {
- if (pidfile)
- unlink(pidfile);
- tell_parent(FAILURE);
- return 1;
- }
-
- if (init_dispatcher(&config)) {
- if (pidfile)
- unlink(pidfile);
- tell_parent(FAILURE);
- return 1;
- }
-
- /* Get machine name ready for use */
- if (resolve_node(&config)) {
- if (pidfile)
- unlink(pidfile);
- tell_parent(FAILURE);
- return 1;
- }
-
- /* Write message to log that we are alive */
- {
- struct utsname ubuf;
- char start[DEFAULT_BUF_SZ];
- const char *fmt = audit_lookup_format((int)config.log_format);
- if (fmt == NULL)
- fmt = "UNKNOWN";
- if (uname(&ubuf) != 0) {
- if (pidfile)
- unlink(pidfile);
- tell_parent(FAILURE);
- return 1;
- }
- if (getsubj(subj))
- snprintf(start, sizeof(start),
- "auditd start, ver=%s format=%s "
- "kernel=%.56s auid=%u pid=%d subj=%s res=success",
- VERSION, fmt, ubuf.release,
- audit_getloginuid(), getpid(), subj);
- else
- snprintf(start, sizeof(start),
- "auditd start, ver=%s format=%s "
- "kernel=%.56s auid=%u pid=%d res=success",
- VERSION, fmt, ubuf.release,
- audit_getloginuid(), getpid());
- if (send_audit_event(AUDIT_DAEMON_START, start)) {
- audit_msg(LOG_ERR, "Cannot send start message");
- if (pidfile)
- unlink(pidfile);
- shutdown_dispatcher();
- tell_parent(FAILURE);
- return 1;
- }
- }
-
- /* Tell kernel not to kill us */
- avoid_oom_killer();
-
- /* let config manager init */
- init_config_manager();
-
- if (opt_startup != startup_nochange && (audit_is_enabled(fd) < 2) &&
- audit_set_enabled(fd, (int)opt_startup) < 0) {
- char emsg[DEFAULT_BUF_SZ];
- if (*subj)
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d subj=%s res=failed",
- audit_getloginuid(), getpid(), subj);
- else
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d res=failed",
- audit_getloginuid(), getpid());
- stop = 1;
- send_audit_event(AUDIT_DAEMON_ABORT, emsg);
- audit_msg(LOG_ERR,
- "Unable to set initial audit startup state to '%s', exiting",
- startup_states[opt_startup]);
- close_down();
- if (pidfile)
- unlink(pidfile);
- shutdown_dispatcher();
- tell_parent(FAILURE);
- return 1;
- }
-
- /* Tell the kernel we are alive */
- if (audit_set_pid(fd, getpid(), WAIT_YES) < 0) {
- char emsg[DEFAULT_BUF_SZ];
- if (*subj)
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d subj=%s res=failed",
- audit_getloginuid(), getpid(), subj);
- else
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d res=failed",
- audit_getloginuid(), getpid());
- stop = 1;
- send_audit_event(AUDIT_DAEMON_ABORT, emsg);
- audit_msg(LOG_ERR, "Unable to set audit pid, exiting");
- close_down();
- if (pidfile)
- unlink(pidfile);
- shutdown_dispatcher();
- tell_parent(FAILURE);
- return 1;
- }
-
- /* Depending on value of opt_startup (-s) set initial audit state */
- loop = ev_default_loop (EVFLAG_NOENV);
-
- ev_io_init (&netlink_watcher, netlink_handler, fd, EV_READ);
- ev_io_start (loop, &netlink_watcher);
-
- ev_signal_init (&sigterm_watcher, term_handler, SIGTERM);
- ev_signal_start (loop, &sigterm_watcher);
-
- ev_signal_init (&sighup_watcher, hup_handler, SIGHUP);
- ev_signal_start (loop, &sighup_watcher);
-
- ev_signal_init (&sigusr1_watcher, user1_handler, SIGUSR1);
- ev_signal_start (loop, &sigusr1_watcher);
-
- ev_signal_init (&sigusr2_watcher, user2_handler, SIGUSR2);
- ev_signal_start (loop, &sigusr2_watcher);
-
- ev_signal_init (&sigchld_watcher, child_handler, SIGCHLD);
- ev_signal_start (loop, &sigchld_watcher);
-
- if (auditd_tcp_listen_init (loop, &config)) {
- char emsg[DEFAULT_BUF_SZ];
- if (*subj)
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d subj=%s res=failed",
- audit_getloginuid(), getpid(), subj);
- else
- snprintf(emsg, sizeof(emsg),
- "auditd error halt, auid=%u pid=%d res=failed",
- audit_getloginuid(), getpid());
- stop = 1;
- send_audit_event(AUDIT_DAEMON_ABORT, emsg);
- tell_parent(FAILURE);
- } else {
- /* Now tell parent that everything went OK */
- tell_parent(SUCCESS);
- audit_msg(LOG_NOTICE,
- "Init complete, auditd %s listening for events (startup state %s)",
- VERSION,
- startup_states[opt_startup]);
- }
-
- /* Parent should be gone by now... */
- if (do_fork)
- close(init_pipe[1]);
-
- // Init complete, start event loop
- if (!stop)
- ev_loop (loop, 0);
-
- auditd_tcp_listen_uninit (loop, &config);
-
- // Tear down IO watchers Part 1
- ev_signal_stop (loop, &sighup_watcher);
- ev_signal_stop (loop, &sigusr1_watcher);
- ev_signal_stop (loop, &sigusr2_watcher);
- ev_signal_stop (loop, &sigterm_watcher);
-
- /* Write message to log that we are going down */
- rc = audit_request_signal_info(fd);
- if (rc > 0) {
- struct audit_reply trep;
-
- rc = get_reply(fd, &trep, rc);
- if (rc > 0) {
- char txt[MAX_AUDIT_MESSAGE_LENGTH];
- snprintf(txt, sizeof(txt),
- "auditd normal halt, sending auid=%u "
- "pid=%d subj=%s res=success",
- trep.signal_info->uid,
- trep.signal_info->pid,
- trep.signal_info->ctx);
- send_audit_event(AUDIT_DAEMON_END, txt);
- }
- }
- if (rc <= 0)
- send_audit_event(AUDIT_DAEMON_END,
- "auditd normal halt, sending auid=? "
- "pid=? subj=? res=success");
- free(rep);
-
- // Tear down IO watchers Part 2
- ev_io_stop (loop, &netlink_watcher);
-
- // Give DAEMON_END event a little time to be sent in case
- // of remote logging
- usleep(10000); // 10 milliseconds
- shutdown_dispatcher();
-
- // Tear down IO watchers Part 3
- ev_signal_stop (loop, &sigchld_watcher);
-
- close_down();
- free_config(&config);
- ev_default_destroy();
-
- return 0;
-}
-
-static void close_down(void)
-{
- struct sigaction sa;
-
- /* We are going down. Give the event thread a chance to shutdown.
- Just in case it hangs, set a timer to get us out of trouble. */
- sa.sa_flags = 0 ;
- sigemptyset( &sa.sa_mask ) ;
- sa.sa_handler = thread_killer;
- sigaction( SIGALRM, &sa, NULL );
- shutdown_events();
-}
-
-
-/*
- * A clean exit means :
- * 1) we log that we are going down
- * 2) deregister with kernel
- * 3) close the netlink socket
- */
-static void clean_exit(void)
-{
- audit_msg(LOG_INFO, "The audit daemon is exiting.");
- if (fd >= 0) {
- audit_set_pid(fd, 0, WAIT_NO);
- audit_close(fd);
- }
- if (pidfile)
- unlink(pidfile);
- closelog();
-}
-
-/*
- * This function is used to get the reply for term info.
- * Returns 1 on success & -1 on failure.
- */
-static int get_reply(int fd, struct audit_reply *rep, int seq)
-{
- int rc, i;
- int timeout = 30; /* tenths of seconds */
-
- for (i = 0; i < timeout; i++) {
- struct timeval t;
- fd_set read_mask;
-
- t.tv_sec = 0;
- t.tv_usec = 100000; /* .1 second */
- FD_ZERO(&read_mask);
- FD_SET(fd, &read_mask);
- do {
- rc = select(fd+1, &read_mask, NULL, NULL, &t);
- } while (rc < 0 && errno == EINTR);
- rc = audit_get_reply(fd, rep,
- GET_REPLY_NONBLOCKING, 0);
- if (rc > 0) {
- /* Don't make decisions based on wrong packet */
- if (rep->nlh->nlmsg_seq != seq)
- continue;
-
- /* If its not what we are expecting, keep looping */
- if (rep->type == AUDIT_SIGNAL_INFO)
- return 1;
-
- /* If we get done or error, break out */
- if (rep->type == NLMSG_DONE || rep->type == NLMSG_ERROR)
- break;
- }
- }
- return -1;
-}
-
-//get the subj of the daemon
-static char *getsubj(char *subj)
-{
- pid_t pid = getpid();
- char filename[48];
- ssize_t num_read;
- int fd;
-
- snprintf(filename, sizeof(filename), "/proc/%u/attr/current", pid);
- fd = open(filename, O_RDONLY);
- if(fd == -1) {
- subj[0] = 0;
- return NULL;
- }
- do {
- num_read = read(fd, subj, SUBJ_LEN-1);
- } while (num_read < 0 && errno == EINTR);
- close(fd);
- if(num_read <= 0) {
- subj[0] = 0;
- return NULL;
- }
- subj[num_read] = '\0';
- return subj;
-}
-