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#11 $
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>
65 #include "auditfilterd.h"
68 * Global list of registered filters.
70 struct auditfilter_module_list filter_list;
73 * Configuration and signal->main flags.
75 int debug; /* Debugging mode requested, don't detach. */
76 int reread_config; /* SIGHUP has been received. */
77 int quit; /* SIGQUIT/TERM/INT has been received. */
83 fprintf(stderr, "auditfilterd [-d] [-c conffile] [-p pipefile]"
85 fprintf(stderr, " -c Specify configuration file (default: %s)\n",
86 AUDITFILTERD_CONFFILE);
87 fprintf(stderr, " -d Debugging mode, don't daemonize\n");
88 fprintf(stderr, " -p Specify pipe file (default: %s)\n",
89 AUDITFILTERD_PIPEFILE);
90 fprintf(stderr, " -t Specify audit trail file (default: none)\n");
95 auditfilterd_init(void)
98 TAILQ_INIT(&filter_list);
102 signal_handler(int signum)
119 * Present raw BSM to a set of registered and interested filters.
122 present_rawrecord(struct timespec *ts, u_char *data, u_int len)
124 struct auditfilter_module *am;
126 TAILQ_FOREACH(am, &filter_list, am_list) {
127 if (am->am_rawrecord != NULL)
128 (am->am_rawrecord)(am, ts, data, len);
133 * Parse the BSM into a set of tokens, which will be pased to registered
134 * and interested filters.
136 #define MAX_TOKENS 128 /* Maximum tokens we handle per record. */
138 present_tokens(struct timespec *ts, u_char *data, u_int len)
140 struct auditfilter_module *am;
141 tokenstr_t tokens[MAX_TOKENS];
146 while (bytesread < len) {
147 if (au_fetch_tok(&tokens[tokencount], data + bytesread,
148 len - bytesread) == -1)
150 bytesread += tokens[tokencount].len;
154 TAILQ_FOREACH(am, &filter_list, am_list) {
155 if (am->am_record != NULL)
156 (am->am_record)(am, ts, tokencount, tokens);
161 * The main loop spins pulling records out of the record source and passing
162 * them to modules for processing.
165 mainloop_file(const char *conffile, const char *trailfile, FILE *trail_fp)
174 * On SIGHUP, we reread the configuration file and reopen
179 warnx("rereading configuration");
180 conf_fp = fopen(conffile, "r");
182 err(-1, "%s", conffile);
183 auditfilterd_conf(conffile, conf_fp);
187 trail_fp = fopen(trailfile, "r");
188 if (trail_fp == NULL)
189 err(-1, "%s", trailfile);
197 * For now, be relatively unrobust about incomplete records,
198 * but in the future will want to do better. Need to look
199 * more at the right blocking and signal behavior here.
201 reclen = au_read_rec(trail_fp, &buf);
204 if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
205 err(-1, "clock_gettime");
206 present_rawrecord(&ts, buf, reclen);
207 present_tokens(&ts, buf, reclen);
213 * The main loop spins pulling records out of the record source and passing
214 * them to modules for processing. This version of the function accepts
215 * discrete record input from a file descriptor, as opposed to buffered input
216 * from a file stream.
219 mainloop_pipe(const char *conffile, const char *pipefile, int pipe_fd)
221 u_char record[MAX_AUDIT_RECORD_SIZE];
228 * On SIGHUP, we reread the configuration file. Unlike with
229 * a trail file, we don't reopen the pipe, as we don't want
230 * to miss records which will be flushed if we do.
234 warnx("rereading configuration");
235 conf_fp = fopen(conffile, "r");
237 err(-1, "%s", conffile);
238 auditfilterd_conf(conffile, conf_fp);
247 * For now, be relatively unrobust about incomplete records,
248 * but in the future will want to do better. Need to look
249 * more at the right blocking and signal behavior here.
251 reclen = read(pipe_fd, record, MAX_AUDIT_RECORD_SIZE);
254 if (clock_gettime(CLOCK_REALTIME, &ts) < 0)
255 err(-1, "clock_gettime");
256 present_rawrecord(&ts, record, reclen);
257 present_tokens(&ts, record, reclen);
262 main(int argc, char *argv[])
264 const char *pipefile, *trailfile, *conffile;
265 FILE *trail_fp, *conf_fp;
270 conffile = AUDITFILTERD_CONFFILE;
273 while ((ch = getopt(argc, argv, "c:dp:t:")) != -1) {
284 if (trailfile != NULL || pipefile != NULL)
290 if (pipefile != NULL || trailfile != NULL)
307 * We allow only one of a pipe or a trail to be used. If none is
308 * specified, we provide a default pipe path.
310 if (pipefile == NULL && trailfile == NULL)
311 pipefile = AUDITFILTERD_PIPEFILE;
313 if (pipefile != NULL) {
314 pipe_fd = open(pipefile, O_RDONLY);
316 err(-1, "open:%s", pipefile);
317 if (fstat(pipe_fd, &sb) < 0)
318 err(-1, "stat: %s", pipefile);
319 if (!S_ISCHR(sb.st_mode))
320 errx(-1, "fstat: %s not device", pipefile);
322 trail_fp = fopen(trailfile, "r");
323 if (trail_fp == NULL)
324 err(-1, "%s", trailfile);
327 conf_fp = fopen(conffile, "r");
329 err(-1, "%s", conffile);
332 if (auditfilterd_conf(conffile, conf_fp) < 0)
337 if (daemon(0, 0) < 0)
341 signal(SIGHUP, signal_handler);
342 signal(SIGINT, signal_handler);
343 signal(SIGQUIT, signal_handler);
344 signal(SIGTERM, signal_handler);
346 if (pipefile != NULL)
347 mainloop_pipe(conffile, pipefile, pipe_fd);
349 mainloop_file(conffile, trailfile, trail_fp);
351 auditfilterd_conf_shutdown();