2 * Copyright (c) 2006 Robert N. M. Watson
5 * This software was developed by Robert Watson for the TrustedBSD Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/auditfilterd.c#13 $
32 * Main file for the audit filter daemon, which presents audit records to a
33 * set of run-time registered loadable modules. This is the main event loop
34 * of the daemon, which handles starting up, waiting for records, and
35 * presenting records to configured modules. auditfilterd_conf.c handles the
36 * reading and management of the configuration, module list and module state,
40 #include <sys/types.h>
44 #include <config/config.h>
45 #ifdef HAVE_FULL_QUEUE_H
46 #include <sys/queue.h>
48 #include <compat/queue.h>
51 #ifndef HAVE_CLOCK_GETTIME
52 #include <compat/clock_gettime.h>
55 #include <bsm/libbsm.h>
56 #include <bsm/audit_filter.h>
57 #include <bsm/audit_internal.h>
66 #include "auditfilterd.h"
69 * Global list of registered filters.
71 struct auditfilter_module_list filter_list;
74 * Configuration and signal->main flags.
76 int debug; /* Debugging mode requested, don't detach. */
77 int reread_config; /* SIGHUP has been received. */
78 int quit; /* SIGQUIT/TERM/INT has been received. */
84 fprintf(stderr, "auditfilterd [-d] [-c conffile] [-p pipefile]"
86 fprintf(stderr, " -c Specify configuration file (default: %s)\n",
87 AUDITFILTERD_CONFFILE);
88 fprintf(stderr, " -d Debugging mode, don't daemonize\n");
89 fprintf(stderr, " -p Specify pipe file (default: %s)\n",
90 AUDITFILTERD_PIPEFILE);
91 fprintf(stderr, " -t Specify audit trail file (default: none)\n");
96 auditfilterd_init(void)
99 TAILQ_INIT(&filter_list);
103 signal_handler(int signum)
120 * Present raw BSM to a set of registered and interested filters.
123 present_rawrecord(struct timespec *ts, u_char *data, u_int len)
125 struct auditfilter_module *am;
127 TAILQ_FOREACH(am, &filter_list, am_list) {
128 if (am->am_rawrecord != NULL)
129 (am->am_rawrecord)(am, ts, data, len);
134 * Parse the BSM into a set of tokens, which will be pased to registered
135 * and interested filters.
137 #define MAX_TOKENS 128 /* Maximum tokens we handle per record. */
139 present_tokens(struct timespec *ts, u_char *data, u_int len)
141 struct auditfilter_module *am;
142 tokenstr_t tokens[MAX_TOKENS];
147 while (bytesread < len) {
148 if (au_fetch_tok(&tokens[tokencount], data + bytesread,
149 len - bytesread) == -1)
151 bytesread += tokens[tokencount].len;
155 TAILQ_FOREACH(am, &filter_list, am_list) {
156 if (am->am_record != NULL)
157 (am->am_record)(am, ts, tokencount, tokens);
162 * The main loop spins pulling records out of the record source and passing
163 * them to modules for processing.
166 mainloop_file(const char *conffile, const char *trailfile, FILE *trail_fp)
175 * On SIGHUP, we reread the configuration file and reopen
180 warnx("rereading configuration");
181 conf_fp = fopen(conffile, "r");
183 err(-1, "%s", conffile);
184 auditfilterd_conf(conffile, conf_fp);
188 trail_fp = fopen(trailfile, "r");
189 if (trail_fp == NULL)
190 err(-1, "%s", trailfile);
198 * For now, be relatively unrobust about incomplete records,
199 * but in the future will want to do better. Need to look
200 * more at the right blocking and signal behavior here.
202 reclen = au_read_rec(trail_fp, &buf);
205 if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
206 err(-1, "clock_gettime");
207 present_rawrecord(&ts, buf, reclen);
208 present_tokens(&ts, buf, reclen);
214 * The main loop spins pulling records out of the record source and passing
215 * them to modules for processing. This version of the function accepts
216 * discrete record input from a file descriptor, as opposed to buffered input
217 * from a file stream.
220 mainloop_pipe(const char *conffile, const char *pipefile __unused, int pipe_fd)
222 u_char record[MAX_AUDIT_RECORD_SIZE];
229 * On SIGHUP, we reread the configuration file. Unlike with
230 * a trail file, we don't reopen the pipe, as we don't want
231 * to miss records which will be flushed if we do.
235 warnx("rereading configuration");
236 conf_fp = fopen(conffile, "r");
238 err(-1, "%s", conffile);
239 auditfilterd_conf(conffile, conf_fp);
248 * For now, be relatively unrobust about incomplete records,
249 * but in the future will want to do better. Need to look
250 * more at the right blocking and signal behavior here.
252 reclen = read(pipe_fd, record, MAX_AUDIT_RECORD_SIZE);
255 if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
256 err(-1, "clock_gettime");
257 present_rawrecord(&ts, record, reclen);
258 present_tokens(&ts, record, reclen);
263 main(int argc, char *argv[])
265 const char *pipefile, *trailfile, *conffile;
266 FILE *trail_fp, *conf_fp;
271 conffile = AUDITFILTERD_CONFFILE;
274 while ((ch = getopt(argc, argv, "c:dp:t:")) != -1) {
285 if (trailfile != NULL || pipefile != NULL)
291 if (pipefile != NULL || trailfile != NULL)
308 * We allow only one of a pipe or a trail to be used. If none is
309 * specified, we provide a default pipe path.
311 if (pipefile == NULL && trailfile == NULL)
312 pipefile = AUDITFILTERD_PIPEFILE;
314 if (pipefile != NULL) {
315 pipe_fd = open(pipefile, O_RDONLY);
317 err(-1, "open:%s", pipefile);
318 if (fstat(pipe_fd, &sb) < 0)
319 err(-1, "stat: %s", pipefile);
320 if (!S_ISCHR(sb.st_mode))
321 errx(-1, "fstat: %s not device", pipefile);
323 trail_fp = fopen(trailfile, "r");
324 if (trail_fp == NULL)
325 err(-1, "%s", trailfile);
328 conf_fp = fopen(conffile, "r");
330 err(-1, "%s", conffile);
333 if (auditfilterd_conf(conffile, conf_fp) < 0)
338 if (daemon(0, 0) < 0)
342 signal(SIGHUP, signal_handler);
343 signal(SIGINT, signal_handler);
344 signal(SIGQUIT, signal_handler);
345 signal(SIGTERM, signal_handler);
347 if (pipefile != NULL)
348 mainloop_pipe(conffile, pipefile, pipe_fd);
350 mainloop_file(conffile, trailfile, trail_fp);
352 auditfilterd_conf_shutdown();